科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件PCI设备初始化4

PCI设备初始化4

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

继续来分析PCI设备的搜索过程,下面就是通过调用搜索程序来实现的

作者:caimouse 来源:CSDN 2008年1月22日

关键字: 初始化 设备 Linux

  • 评论
  • 分享微博
  • 分享邮件
继续来分析PCI设备的搜索过程,下面就是通过调用搜索程序来实现的。
for(i = 0, pb = _pci_head; i < pci_roots; i++, pb = pb->next) {
           _pci_scan_dev(pb, i, 0, init);
       }
 
接着去看看函数_pci_scan_dev的实现:
static void
_pci_scan_dev(struct pci_device *dev, int bus, int device, int initialise)
{
    for(; device < 32; device++) {
       _pci_query_dev (dev, bus, device, initialise);
    }
}
上面是根据PCI的总线定义,可以知道它最多有32个设备,因此就需要把这32个设备进行枚举。下面的搜索过程是通过PCI的标识来进行的,因为每个PCI插槽存在设备时,它的ID不为0xFFFF FFFF,根据这样的特征,就可以知道是否存在PCI设备了。
static void
_pci_query_dev (struct pci_device *dev, int bus, int device, int initialise)
{
    pcitag_t tag;
    pcireg_t id;
    pcireg_t misc;
 
    tag = _pci_make_tag(bus, device, 0);
    if (!_pci_canscan (tag))
       return;
上面组成PCI标识地址。
 
    if (_pciverbose >= 2)
       _pci_bdfprintf (bus, device, -1, "probe...");
 
    id = _pci_conf_read(tag, PCI_ID_REG);
上面读取PCIID标识。
 
    if (_pciverbose >= 2) {
       PRINTF ("completed\n");
    }
 
    if (id == 0 || id == 0xffffffff) {
       return;
    }
上面判断是否存在PCI设备,如果不存在就返回。
 
    misc = _pci_conf_read(tag, PCI_BHLC_REG);
 
    if (PCI_HDRTYPE_MULTIFN(misc)) {
       int function;
       for (function = 0; function < 8; function++) {
           tag = _pci_make_tag(bus, device, function);
           id = _pci_conf_read(tag, PCI_ID_REG);
           if (id == 0 || id == 0xffffffff) {
              return;
           }
           _pci_query_dev_func (dev, tag, initialise);
       }
    }
    else {
       _pci_query_dev_func (dev, tag, initialise);
    }
上面读取PCI信息,并分类PCI设备,然后保存到PCI设备列表里。
 
}
 
找到所有设备之后,就需要把PCI的总线带宽分配,并分别分配设备的内存映射空间。通过下面的程序实现的:
 
static void
_setup_pcibuses(int initialise)
{
    struct pci_bus *pb;
    struct pci_device *pd;
    unsigned int def_ltim, max_ltim;
    int i;
 
    SBD_DISPLAY ("PCIS", CHKPNT_PCIS);
 
    for(pb = _pci_bushead; pb != NULL; pb = pb->next) {
   
       if (pb->ndev == 0)
           return;
 
       if (initialise) {
           /* convert largest minimum grant time to cycle count */
/*XXX 66/33 Mhz */   max_ltim = pb->min_gnt * 33 / 4;
       
           /* now see how much bandwidth is left to distribute */
           if (pb->bandwidth <= 0) {
              if (_pciverbose) {
                  _pci_bdfprintf (pb->bus, -1, -1,
                      "WARN: total bandwidth exceeded\n");
              }
              def_ltim = 1;
           }
           else {
              /* calculate a fair share for each device */
              def_ltim = pb->bandwidth / pb->ndev;
              if (def_ltim > pb->max_lat) {
              /* would exceed critical time for some device */
                  def_ltim = pb->max_lat;
              }
              /* convert to cycle count */
              def_ltim = def_ltim * 33 / 4;
           }
           /* most devices don't implement bottom three bits */
           def_ltim = (def_ltim + 7) & ~7;
           max_ltim = (max_ltim + 7) & ~7;
       
           pb->def_ltim = MIN (def_ltim, 255);
           pb->max_ltim = MIN (MAX (max_ltim, def_ltim), 255);
       }
    }
 
    SBD_DISPLAY ("PCIR", CHKPNT_PCIR);
    _pci_hwreinit ();
 
    /* setup the individual device windows */
    SBD_DISPLAY ("PCIW", CHKPNT_PCIW);
    for(i = 0, pd = _pci_head; i < pci_roots; i++, pd = pd->next) {
       _pci_setup_windows (pd);
    }
 
}
 
到这里,就已经把PCI局部总线上的设备配置完成。PCI总线配置是非常复杂的,不但有众多的设备,还有内存空间的分配,还有设备的DMA选择,还有桥设备在上面的转换等等。 

查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章