Chinaunix首页 | 论坛 | 博客
  • 博客访问: 155248
  • 博文数量: 72
  • 博客积分: 3680
  • 博客等级: 中校
  • 技术积分: 1051
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-22 13:51
文章分类
文章存档

2010年(72)

我的朋友

分类: LINUX

2010-09-24 08:44:55

PCI网卡驱动程序分析

 

1.  概述

该分析报告针对 GNIC-II的千兆以太网卡,源程序文件:drivers/net/hamachi.c,由于该分析报告旨在对介绍PCI驱动程序结构,所以程序中关于硬件操作的具体部分不作介绍。

 

2.  初始化

static int __init hamachi_init (void)

{

if (pci_register_driver(&hamachi_driver) > 0)

     return 0;

pci_unregister_driver(&hamachi_driver);

    return -ENODEV;

}

在模块初始化时采用pci_register_driver注册pci驱动程序。

 

static struct pci_driver hamachi_driver = {

name:      DRV_NAME,

id_table:  hamachi_pci_tbl,

probe:     hamachi_init_one,

remove:       __devexit_p(hamachi_remove_one),

};

 

static struct pci_device_id hamachi_pci_tbl[] __initdata = {

{ 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, },

}

该表记录的是该驱动能够支持的PCI设备,分别是厂商号,设备号,子厂商号,子设备号,其中子厂商号,子设备号为PCI_ANY_ID,表示支持各种子类型。 该表到底有什么实际用处?(通过分析函数pci_register_driver得出结论)

 

 

probe: hamachi_init_one (该函数的调用时机可通过分析pci_register_driver得出)

static int __init hamachi_init_one (struct pci_dev *pdev,

                          const struct pci_device_id *ent)

{

 

      /*  使能PCI设备 */

if (pci_enable_device(pdev)) {

           ret = -EIO;

           goto err_out;

      }

 

      /* 获取基地址 */

ioaddr = pci_resource_start(pdev, 0);

     

      /* 申请将要使用的地址空间 */

      i = pci_request_regions(pdev, DRV_NAME);

      if (i) return i;

 

      /* 获取中断号 */

      irq = pdev->irq;

     

/* 思考为什么这里要使用ioremap? */

ioaddr = (long) ioremap(ioaddr, 0x400);

     

if (!ioaddr)

           goto err_out_release;

 

      dev = alloc_etherdev(sizeof(struct hamachi_private));

      if (!dev)

           goto err_out_iounmap;

 

      SET_MODULE_OWNER(dev);

 

/* 硬件相关操作,省略 */

 

      /* The Hamachi-specific entries in the device structure. */

      dev->open = &hamachi_open;

      dev->hard_start_xmit = &hamachi_start_xmit;

      dev->stop = &hamachi_close;

      dev->get_stats = &hamachi_get_stats;

      dev->set_multicast_list = &set_rx_mode;

      dev->do_ioctl = &netdev_ioctl;

      dev->tx_timeout = &hamachi_tx_timeout;

      dev->watchdog_timeo = TX_TIMEOUT;

      if (mtu)

           dev->mtu = mtu;

 

      i = register_netdev(dev);

      if (i) {

           ret = i;

           goto err_out_unmap_rx;

      }

 

      /* Configure gigabit autonegotiation. */

      writew(0x0400, ioaddr + ANXchngCtrl);  /* Enable legacy links. */

      writew(0x08e0, ioaddr + ANAdvertise);   /* Set our advertise word. */

      writew(0x1000, ioaddr + ANCtrl);

 

      card_idx++;

      return 0;

}

阅读(772) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~