summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMole Shang <[email protected]>2024-02-13 21:32:02 +0800
committerMole Shang <[email protected]>2024-02-13 21:50:47 +0800
commit904885a96efd1dd0221585f67477f5a39bcce7f7 (patch)
treeb635f479f94b5d970fb0b12e1718689710c7b9f6 /kernel
parent89ef6f717ed4b3e702e5f6f906f58fe1ea27d366 (diff)
downloadxv6-labs-904885a96efd1dd0221585f67477f5a39bcce7f7.tar.gz
xv6-labs-904885a96efd1dd0221585f67477f5a39bcce7f7.tar.bz2
xv6-labs-904885a96efd1dd0221585f67477f5a39bcce7f7.zip
lab net: finishnet
Diffstat (limited to 'kernel')
-rw-r--r--kernel/e1000.c65
-rw-r--r--kernel/pci.c2
2 files changed, 58 insertions, 9 deletions
diff --git a/kernel/e1000.c b/kernel/e1000.c
index 70a2adf..c9ba9e2 100644
--- a/kernel/e1000.c
+++ b/kernel/e1000.c
@@ -95,26 +95,75 @@ e1000_init(uint32 *xregs)
int
e1000_transmit(struct mbuf *m)
{
- //
- // Your code here.
- //
// the mbuf contains an ethernet frame; program it into
// the TX descriptor ring so that the e1000 sends it. Stash
// a pointer so that it can be freed after sending.
- //
+ acquire(&e1000_lock);
+
+ int cur_idx = regs[E1000_TDT];
+ // check if the STAT_DD bit is set in current descriptor
+ // if not set, means a previous tx in this descripter is still in flight, return an error.
+ if(!(tx_ring[cur_idx].status | E1000_TXD_STAT_DD)){
+ release(&e1000_lock);
+ return -1;
+ }
+
+ // free previous mbuf and update current descriptor
+ if(tx_mbufs[cur_idx])
+ mbuffree(tx_mbufs[cur_idx]);
+ tx_ring[cur_idx].addr = (uint64)m->head;
+ tx_ring[cur_idx].length = (uint64)m->len;
+ tx_ring[cur_idx].cmd = E1000_TXD_CMD_RS | E1000_TXD_CMD_EOP;
+ // also clear status bits
+ tx_ring[cur_idx].status = 0;
+
+ // stash current mbuf to tx_mbufs (would be freed later)
+ tx_mbufs[cur_idx] = m;
+
+ // update the ring position to point to the next descriptor;
+ regs[E1000_TDT] = (cur_idx + 1) % TX_RING_SIZE;
+
+ release(&e1000_lock);
return 0;
}
static void
e1000_recv(void)
{
- //
- // Your code here.
- //
// Check for packets that have arrived from the e1000
// Create and deliver an mbuf for each packet (using net_rx()).
- //
+ while(1){
+ acquire(&e1000_lock);
+ int cur_idx = (regs[E1000_RDT]+1) % RX_RING_SIZE;
+
+ // check if last rx is completed. If not, skip passing to net_rx()
+ if(!(rx_ring[cur_idx].status | E1000_RXD_STAT_DD))
+ break;
+
+ // update the mbuf's length to the len reported by rx_desc
+ // mbufput(rx_mbufs[cur_idx], rx_ring[cur_idx].length);
+ rx_mbufs[cur_idx]->len = rx_ring[cur_idx].length;
+
+ // stash mbuf, for later net_rx()
+ struct mbuf *rx_buf = rx_mbufs[cur_idx];
+
+ // net_rx() would free the passed mbuf invisibly, so we need to re-alloc it
+ rx_mbufs[cur_idx] = mbufalloc(0);
+ if(!rx_mbufs[cur_idx])
+ panic("e1000_recv: mbufalloc");
+
+ // update buffer addr and clear status bits
+ rx_ring[cur_idx].addr = (uint64)rx_mbufs[cur_idx]->head;
+ rx_ring[cur_idx].status = 0;
+
+ // update the E1000_RDT register to point to next position
+ regs[E1000_RDT] = cur_idx;
+ release(&e1000_lock);
+
+ // pass to the network stack, must not hold the lock coz it can lead to deadlocks under different cpus
+ net_rx(rx_buf);
+ }
}
void
diff --git a/kernel/pci.c b/kernel/pci.c
index 5cd2102..3e361c5 100644
--- a/kernel/pci.c
+++ b/kernel/pci.c
@@ -37,7 +37,7 @@ pci_init()
// bit 0 : I/O access enable
// bit 1 : memory access enable
// bit 2 : enable mastering
- base[1] = 7;
+ base[1] = 0b111;
__sync_synchronize();
for(int i = 0; i < 6; i++){