本实验是整个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这个教学用操作系统的结构,一开始只是让你用已经写好的函数接口来实践多线程和系统调用,之后就需要你自己深入内核,自己添加系统调用,添加页表,修改文件系统等等。通过动手来亲自体验这些操作系统的共通性知识。尽管这些可能没有自己动手从零开始构建一个操作系统那么硬核,但是的确是一门操作系统入门的好课。之后还需要对操作系统进行更深入的学习。