MIT 6.828 操作系统工程 Lab6: e1000 网络驱动程序

本文档记录了作者完成MIT 6.828操作系统工程Lab6的过程,涉及E1000网络驱动程序的实现,包括初始化、内存映射、数据包传输和接收等功能。通过一系列练习,详细阐述了如何与E1000网卡交互,以及如何处理传输和接收队列。
摘要由CSDN通过智能技术生成

MIT 6.828 操作系统工程 Lab6: 网络驱动程序

这篇是我自己探索实现 MIT 6.828 lab6 的笔记记录,会包含一部分代码注释和要求的翻译记录,以及踩过的坑/个人的解决方案

这里是我实现的完整代码仓库,也包含其他笔记等等:https://github.com/yunwei37/6.828-2018-labs

目录:

lab6 实际上并没有想象中那么难,代码量很少,主要是需要理解网卡外设的运作方式。

根据网页上的提示,在需要的时候去查找手册就好。

理解这张图的结构:请添加图片描述

练习 1.time_tick

一个简单的接口调用。

syscall.c

static int
sys_time_msec(void)
{
   
	// LAB 6: Your code here.
	return time_msec();
}

练习 2.浏览英特尔的E1000软件开发人员手册

现在不要担心细节;只需感受一下文档的结构,您就可以稍后查找内容。

练习 3. 实现一个附加函数来初始化 E1000

pci:

// pci_attach_vendor matches the vendor ID and device ID of a PCI device. key1
// and key2 should be the vendor ID and device ID respectively
struct pci_driver pci_attach_vendor[] = {
   
	{
    0x8086, 0x100e, pci_e1000_attach },
	{
    0, 0, 0 },
};

e1000


volatile void *e1000_base = 0;

inline static void 
write_reg(int reg, uint32_t value) {
   
    assert(e1000_base);
    *(uint32_t*)(e1000_base + reg) = value;
}

inline static uint32_t 
read_reg(int reg) {
   
    assert(e1000_base);
    return *(uint32_t*)(e1000_base + reg);
}

int 
pci_e1000_attach(struct pci_func *pcif) 
{
   
    pci_func_enable(pcif);
    cprintf("pci_e1000_attach reg_base[0] %x reg_size[0] %x\n", pcif->reg_base[0], pcif->reg_size[0]);

    return 1;
}

练习 4. mmio_map_regio

在您的附加函数中,通过调用mmio_map_region(您在实验 4 中编写以支持内存映射 LAPIC)为 E1000 的 BAR 0 创建虚拟内存映射 。

volatile void *e1000_base = 0;

inline static void 
write_reg(int reg, uint32_t value) {
   
    assert(e1000_base);
    *(uint32_t*)(e1000_base + reg) = value;
}

inline static uint32_t 
read_reg(int reg) {
   
    assert(e1000_base);
    return *(uint32_t*)(e1000_base + reg);
}

    ...
    e1000_base = mmio_map_region(pcif->reg_base[0], pcif->reg_size[0]);

    assert(read_reg(E1000_STATUS) == 0x80080783);
    ...

练习 5.执行第 14.5 节(但不是其小节)中描述的初始化步骤。

注意这里都需要使用物理地址。

struct tx_desc TXDarray[TDARRAY_SIZE] = {
   0};
char tx_buffer[TDARRAY_SIZE * 1518] = {
   0};

    for (int i = 0;i < TDARRAY_SIZE; ++i) {
   
        TXDarray[i].addr = PADDR((tx_buffer + i * 1518));
        TXDarray[i].status |= 1;
        //TXDarray[i].length = 1518;
    }

    write_reg(E1000_TDBAH, 0);
    write_reg(E1000_TDBAL, PADDR
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值