From 904885a96efd1dd0221585f67477f5a39bcce7f7 Mon Sep 17 00:00:00 2001 From: Mole Shang <135e2@135e2.dev> Date: Tue, 13 Feb 2024 21:32:02 +0800 Subject: lab net: finish --- kernel/e1000.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- kernel/pci.c | 2 +- 2 files changed, 58 insertions(+), 9 deletions(-) (limited to 'kernel') 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++){ -- cgit v1.2.3