龙芯软件开发(26)-- PCI设备初始化4

继续来分析 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);
上面读取 PCI ID 标识。
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 选择,还有桥设备在上面的转换等等。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值