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. //
// 1.acquire the lock acquire(&e1000_lock); // 2.reading the E1000_TDT control register => get the tail index of the tx ring uint32 tx_desc_tail_idx = regs[E1000_TDT]; // 3.check if the ring overflowing... if ((tx_ring[tx_desc_tail_idx].status & E1000_TXD_STAT_DD) == 0) { release(&e1000_lock); return-1; // hasn't finish last transmition } // 4. free the mbuf if needed if (tx_mbufs[tx_desc_tail_idx]) { mbuffree(tx_mbufs[tx_desc_tail_idx]); } // 5. fill the descriptor tx_mbufs[tx_desc_tail_idx] = m; tx_ring[tx_desc_tail_idx].length = m->len; tx_ring[tx_desc_tail_idx].addr = (uint64)m->head; tx_ring[tx_desc_tail_idx].cmd = (E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS); // set the cmd flags // 6. update the tail pointer regs[E1000_TDT] = (tx_desc_tail_idx + 1) % TX_RING_SIZE; // 7.release the lock release(&e1000_lock); return0; }
staticvoid 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) { // 1. acquire the lock // acquire(&e1000_lock); // 2. get the position of the next received packet uint32 next_packet_idx = (regs[E1000_RDT] + 1) % RX_RING_SIZE; // 3. check if new packet available if ((rx_ring[next_packet_idx].status & E1000_RXD_STAT_DD) == 0) { // release(&e1000_lock); return; // no available packet } // 4. set the length and deliver the packet to the networking stack rx_mbufs[next_packet_idx]->len = rx_ring[next_packet_idx].length; net_rx(rx_mbufs[next_packet_idx]); // 5. refresh the mbuf if ((rx_mbufs[next_packet_idx] = mbufalloc(0)) == 0) panic("e1000_recv"); // 6. refresh the metadata in rx_ring rx_ring[next_packet_idx].addr = (uint64) rx_mbufs[next_packet_idx]->head; rx_ring[next_packet_idx].status &= 0; // 7. update the E1000_RDT regs[E1000_RDT] = next_packet_idx; // 8. release the lock // release(&e1000_lock); } }