diff --git a/kernel/e1000.c b/kernel/e1000.c index 70a2adf..88e021d 100644 --- a/kernel/e1000.c +++ b/kernel/e1000.c @@ -103,6 +103,33 @@ e1000_transmit(struct mbuf *m) // a pointer so that it can be freed after sending. // + acquire(&e1000_lock); + + // First ask the E1000 for the TX ring index at which it's expecting the next packet + int tail = regs[E1000_TDT]; + + // Then whether the E1000 have finished the corresponding previous + // transmission request, if no, then return an error + if((tx_ring[tail].status & E1000_TXD_STAT_DD) == 0){ + release(&e1000_lock); + return -1; + } + + // Otherwish free the last mbuf if there was one + if(tx_mbufs[tail]){ + mbuffree(tx_mbufs[tail]); + } + + // Then fill in the descriptor + tx_ring[tail].addr = (uint64) m->head; + tx_ring[tail].length = m->len; + tx_ring[tail].cmd = E1000_TXD_CMD_RS | E1000_TXD_CMD_EOP; + + tx_mbufs[tail] = m; + + __sync_synchronize(); + + // Finally, update the ring position + regs[E1000_TDT] = (tail + 1) % TX_RING_SIZE; + release(&e1000_lock); return 0; } @@ -115,6 +142,30 @@ e1000_recv(void) // Check for packets that have arrived from the e1000 // Create and deliver an mbuf for each packet (using net_rx()). // + while(1){ + // First fetching the E1000_RDT control register + // and adding one modulo RX_RING_SIZE + int tail = (regs[E1000_RDT] + 1) % RX_RING_SIZE; + + // Then check if a new packet is available + if((rx_ring[tail].status & E1000_RXD_STAT_DD) == 0){ + return; + } + __sync_synchronize(); + // Otherwise, update the mbuf's m->len to the length reported in the descriptor + // Deliver the mbuf to the network stack using net_rx() + rx_mbufs[tail]->len = rx_ring[tail].length; + net_rx(rx_mbufs[tail]); + + // Then allocate a new mbuf using mbufalloc() to replace the one just given to net_rx() + // Program its data pointer (m->head) into the descriptor. Clear the descriptor's status bits to zero + rx_mbufs[tail] = mbufalloc(0); + if(!rx_mbufs[tail]) + panic("e1000_recv"); + rx_ring[tail].addr = (uint64) rx_mbufs[tail]->head; + rx_ring[tail].status = 0; + __sync_synchronize(); + + regs[E1000_RDT] = tail % RX_RING_SIZE; + } } void diff --git a/packets.pcap b/packets.pcap index 82d353e..58bcc0f 100644 Binary files a/packets.pcap and b/packets.pcap differ