文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Linux协议栈IP层的路由处理

Linux协议栈IP层的路由处理

时间:2010-03-11  来源:cao5170


二:从网卡驱动说起。
         以intel 100M 网卡驱动为例简要概述数据包的接收与发送流程。代码见(drivers/net/e100.c) 网卡是属于PCI设备,它的注册跟一般的PCI设备注册没什么两样。 static int __init e100_init_module(void) {          if(((1 << debug) - 1) & NETIF_MSG_DRV) {                    printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);                    printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);          }            //注册PCI         return pci_module_init(&e100_driver); } 其中e100_driver对应为网卡的pci_driver. static struct pci_driver e100_driver = {          //驱动对应的名字          .name =         DRV_NAME,          //匹配类型          .id_table =     e100_id_table,          //侦测函数          .probe =        e100_probe,          //移除函数,设备移除时将调用此函数          .remove =       __devexit_p(e100_remove), #ifdef CONFIG_PM          .suspend =      e100_suspend,          .resume =       e100_resume, #endif } 当总数探测到PCI设备符合e100_id_table中的参数时,将会调用e100_probe,开始设备的初始化 在e100_probe中: static int __devinit e100_probe(struct pci_dev *pdev,          const struct pci_device_id *ent) {          struct net_device *netdev;          struct nic *nic;          int err;            //分配net_device并为其赋值          //alloc_etherdev为以太网接口的net_device分配函数。它是alloc_netdev的封装函数          if(!(netdev = alloc_etherdev(sizeof(struct nic)))) {                    if(((1 << debug) - 1) & NETIF_MSG_PROBE)                             printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n");                    return -ENOMEM;          }                   //对netdev中的函数指针赋初值          netdev->open = e100_open;          netdev->stop = e100_close;          netdev->hard_start_xmit = e100_xmit_frame;          netdev->get_stats = e100_get_stats;          netdev->set_multicast_list = e100_set_multicast_list;          netdev->set_mac_address = e100_set_mac_address;          netdev->change_mtu = e100_change_mtu;          netdev->do_ioctl = e100_do_ioctl;          //支持ethtool工具时有效          SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);          netdev->tx_timeout = e100_tx_timeout;          netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;          //轮询函数          netdev->poll = e100_poll;          netdev->weight = E100_NAPI_WEIGHT; #ifdef CONFIG_NET_POLL_CONTROLLER          netdev->poll_controller = e100_netpoll; #endif            //获得net_device私有数据区,并对其赋值          //私有数据大小是由alloc_etherdev()参数中指定的          nic = netdev_priv(netdev);          nic->netdev = netdev;          nic->pdev = pdev;          nic->msg_enable = (1 << debug) - 1;          pci_set_drvdata(pdev, netdev);            //启动网卡.为之后DMA,I/O内存映射做准备 //它实际上是对PCI的控制寄存器赋值来实现的          if((err = pci_enable_device(pdev))) {                    DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n");                    goto err_out_free_dev;          }            //获取该资源相关联的标志          //如果该设备存在I/O内存,则置IORESOURCE_MEM          if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {                    DPRINTK(PROBE, ERR, "Cannot find proper PCI device "                             "base address, aborting.\n");                    err = -ENODEV;                    goto err_out_disable_pdev;          }            //对PCI的6个寄存器都会调用资源分配函数进行申请          if((err = pci_request_regions(pdev, DRV_NAME))) {                    DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n");                    goto err_out_disable_pdev;          }            //探制设备的DMA能力。如果设备支持DMA。pci_set_dma_mask返回0          pci_set_master(pdev);          if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) {                    DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");                    goto err_out_free_res;          }            SET_MODULE_OWNER(netdev);          SET_NETDEV_DEV(netdev, &pdev->dev);            //映射设备对应的I/O。以后对设备寄存器的操作可以直接转换为对内存的操作          nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr));          if(!nic->csr) {                    DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");                    err = -ENOMEM;                    goto err_out_free_res;          }            if(ent->driver_data)                    nic->flags |= ich;          else                    nic->flags &= ~ich;            spin_lock_init(&nic->cb_lock);          spin_lock_init(&nic->cmd_lock);          //设置定时器。          init_timer(&nic->watchdog);          nic->watchdog.function = e100_watchdog;          nic->watchdog.data = (unsigned long)nic;          init_timer(&nic->blink_timer);          nic->blink_timer.function = e100_blink_led;          nic->blink_timer.data = (unsigned long)nic;            //为nic->mem建立线性DMA。只是在支持ethtool的时候才有用 if((err = e100_alloc(nic))) {                    DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");                    goto err_out_iounmap;          }          //对nic成员赋初值          e100_get_defaults(nic);          e100_hw_reset(nic);          e100_phy_init(nic);          //读取网卡的EEPROM。其中存放着网卡的MAC地址。          //对EEPROM是通过对I/O映射内存的操作实现的,即nic->csr          if((err = e100_eeprom_load(nic)))                    goto err_out_free;          //设置netdev->dev_addr          memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);          if(!is_valid_ether_addr(netdev->dev_addr)) {                    DPRINTK(PROBE, ERR, "Invalid MAC address from "                             "EEPROM, aborting.\n");                    err = -EAGAIN;                    goto err_out_free;          }            /* Wol magic packet can be enabled from eeprom */          if((nic->mac >= mac_82558_D101_A4) &&             (nic->eeprom[eeprom_id] & eeprom_id_wol))                    nic->flags |= wol_magic;            pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));          //注册网络设备          if((err = register_netdev(netdev))) {                    DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");                    goto err_out_free;          }            DPRINTK(PROBE, INFO, "addr 0x%lx, irq %d, "                    "MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n",                    pci_resource_start(pdev, 0), pdev->irq,                    netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],                    netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);            return 0;   err_out_free:          e100_free(nic); err_out_iounmap:          iounmap(nic->csr); err_out_free_res:          pci_release_regions(pdev); err_out_disable_pdev:          pci_disable_device(pdev); err_out_free_dev:          pci_set_drvdata(pdev, NULL);          free_netdev(netdev);          return err; }   本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/luoye144200720102030/archive/2009/06/04/4243344.aspx
相关阅读 更多 +
排行榜 更多 +
龙珠格斗火柴人

龙珠格斗火柴人

飞行射击 下载
荒野恐龙猎手安卓版

荒野恐龙猎手安卓版

飞行射击 下载
超凡坦克英雄

超凡坦克英雄

飞行射击 下载