diff options
| author | Mole Shang <135e2@135e2.dev> | 2024-02-13 21:32:02 +0800 | 
|---|---|---|
| committer | Mole Shang <135e2@135e2.dev> | 2024-02-13 21:50:47 +0800 | 
| commit | 904885a96efd1dd0221585f67477f5a39bcce7f7 (patch) | |
| tree | b635f479f94b5d970fb0b12e1718689710c7b9f6 | |
| parent | 89ef6f717ed4b3e702e5f6f906f58fe1ea27d366 (diff) | |
| download | xv6-labs-904885a96efd1dd0221585f67477f5a39bcce7f7.tar.gz xv6-labs-904885a96efd1dd0221585f67477f5a39bcce7f7.tar.bz2 xv6-labs-904885a96efd1dd0221585f67477f5a39bcce7f7.zip | |
lab net: finishnet
| -rw-r--r-- | kernel/e1000.c | 65 | ||||
| -rw-r--r-- | kernel/pci.c | 2 | 
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++){ | 
