MIT 6.s081 Lab11 networking


本实验是整个6.s081的最后一个实验,而且跟xv6的关系也不大,要求你阅读E1000的硬件开发手册然后完善一个网卡驱动,实现e1000_transmit()e1000_recv()这两个函数。

因为Hint给的非常详细,跟着Hint一步一步来就可以了。

直接放代码吧:

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);
  uint index = regs[E1000_TDT];
  if((tx_ring[index].status & E1000_TXD_STAT_DD) == 0){
    release(&e1000_lock);
    return -1;
  }
  if(tx_mbufs[index])
    mbuffree(tx_mbufs[index]);
  tx_mbufs[index] = m;
  tx_ring[index].length = m->len;
  tx_ring[index].addr = (uint64)m->head;
  tx_ring[index].cmd = E1000_TXD_CMD_RS | E1000_TXD_CMD_EOP;
  regs[E1000_TDT] = (index + 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()).
  //
  uint index = regs[E1000_RDT];
  index = (index + 1) % RX_RING_SIZE;
  while(rx_ring[index].status & E1000_RXD_STAT_DD) {
    rx_mbufs[index]->len = rx_ring[index].length;
    net_rx(rx_mbufs[index]);
    if((rx_mbufs[index] = mbufalloc(0)) == 0)
      panic("e1000");
    rx_ring[index].addr = (uint64)rx_mbufs[index]->head;
    rx_ring[index].status = 0;
    index = (index + 1) % RX_RING_SIZE;
  }
  if(index == 0)
    index = RX_RING_SIZE;
  regs[E1000_RDT] = (index - 1) % RX_RING_SIZE;
}

总结

6.s081总共11个实验,从各种角度由浅入深的了解xv6这个教学用操作系统的结构,一开始只是让你用已经写好的函数接口来实践多线程和系统调用,之后就需要你自己深入内核,自己添加系统调用,添加页表,修改文件系统等等。通过动手来亲自体验这些操作系统的共通性知识。尽管这些可能没有自己动手从零开始构建一个操作系统那么硬核,但是的确是一门操作系统入门的好课。之后还需要对操作系统进行更深入的学习。


文章作者: Watari
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Watari !
  目录