上面继续初始化南桥之后,再接着下来,就要初始化PCI总线上其它的设备了。看下面的代码:
CPU_ConfigCache();
上面重新配置龙芯2E的缓存。
_pci_businit(1); /* PCI bus initialization */
上面继续初始化PCI总线上的设备,这个函数里要初始化完成所有其它连接到PCI总线上的设备。接着看这个函数的代码如下:
void
_pci_businit (int init)
{
char *v;
tgt_putchar('P');
v = getenv("pciverbose");
if (v) {
_pciverbose = atol(v);
}
上面获取PCI显示值。
/* intialise the PCI bridge */
if (/*init*/ 1) {
SBD_DISPLAY ("PCIH", CHKPNT_PCIH);
init = _pci_hwinit (init, &def_bus_iot, &def_bus_memt);
pci_roots = init;
if (init < 1)
return;
}
上面实现PCI的分配空间,主要设置北桥。以便后面可以搜索到所有PCI的设备。
if(monarch_mode) {
int i;
struct pci_device *pb;
if (_pciverbose) {
printf("setting up %d bus\n", init);
}
for(i = 0, pb = _pci_head; i < pci_roots; i++, pb = pb->next) {
_pci_scan_dev(pb, i, 0, init);
}
上面实现所有PCI设备的枚举。由于PCI插槽上有很多设备,并且是即插即用,并不能确定那个设备一定存在,所以只能枚举所有设备。
_setup_pcibuses(init);
上面把发现的PCI设备全部初始化。
}
}
下面是PCI函数_pci_hwinit初始化实现:
int
_pci_hwinit(initialise, iot, memt)
int initialise;
bus_space_tag_t iot;
bus_space_tag_t memt;
{
/*pcireg_t stat;*/
struct pci_device *pd;
struct pci_bus *pb;
if (!initialise) {
return(0);
}
上面判断是否需要初始化,如果不需要分配PCI的链表,就返回去。
pci_local_mem_pci_base = PCI_LOCAL_MEM_PCI_BASE;
/*
* Allocate and initialize PCI bus heads.
*/
/*
* PCI Bus 0
*/
pd = pmalloc(sizeof(struct pci_device));
pb = pmalloc(sizeof(struct pci_bus));
if(pd == NULL || pb == NULL) {
printf("pci: can't alloc memory. pci not initialized\n");
return(-1);
}
上面分配一个PCI链表的节点,由于PCI总线上的设备是可变的,只能使用链表来保存设备信息。同时还判断内存是否分配成功。
pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
上面设置使用IO和内存空间。
pd->pa.pa_iot = pmalloc(sizeof(bus_space_tag_t));
pd->pa.pa_iot->bus_reverse = 1;
pd->pa.pa_iot->bus_base = BONITO_PCIIO_BASE_VA;
上面设置IO的TAG配置。
//printf("pd->pa.pa_iot=%p,bus_base=0x%x\n",pd->pa.pa_iot,pd->pa.pa_iot->bus_base);
pd->pa.pa_memt = pmalloc(sizeof(bus_space_tag_t));
pd->pa.pa_memt->bus_reverse = 1;
//pd->pa.pa_memt->bus_base = 0xa0000000; /* pci memory start from 0x10000000 */
pd->pa.pa_memt->bus_base = 0xb0000000; /* pci memory start from 0x00000000 */
上面设置内存空间。
pd->pa.pa_dmat = &bus_dmamap_tag;
上面设置DMA配置。
pd->bridge.secbus = pb;
_pci_head = pd;
上面保存PCI设备。
#ifndef NEW_PCI_WINDOW
/* reserve first window for vga mem */
pb->minpcimemaddr = PCI_MEM_SPACE_PCI_BASE+0x04000000;
pb->nextpcimemaddr = PCI_MEM_SPACE_PCI_BASE+BONITO_PCILO_SIZE;
#else
pb->minpcimemaddr = PCI_MEM_SPACE_PCI_BASE;
pb->nextpcimemaddr = PCI_MEM_SPACE_PCI_BASE+ 0x0a000000;
#endif
pb->minpciioaddr = PCI_IO_SPACE_BASE+0x000a000;
pb->nextpciioaddr = PCI_IO_SPACE_BASE+ BONITO_PCIIO_SIZE;
pb->pci_mem_base = BONITO_PCILO_BASE_VA;
pb->pci_io_base = BONITO_PCIIO_BASE_VA;
pb->max_lat = 255;
pb->fast_b2b = 1;
pb->prefetch = 1;
pb->bandwidth = 0x4000000;
pb->ndev = 1;
_pci_bushead = pb;
_pci_bus[_max_pci_bus++] = pd;
上面保存PCI总线配置。
bus_dmamap_tag._dmamap_offs = 0;
#ifndef NEW_PCI_WINDOW
/*set Bonito register; first windows for 0-0x4000000 pci mem */
BONITO_PCIMAP =
BONITO_PCIMAP_WIN(0, /*PCI_MEM_SPACE_PCI_BASE+*/0x00000000) |
BONITO_PCIMAP_WIN(1, PCI_MEM_SPACE_PCI_BASE+0x04000000) |
BONITO_PCIMAP_WIN(2, PCI_MEM_SPACE_PCI_BASE+0x08000000) |
BONITO_PCIMAP_PCIMAP_2;
#else
BONITO_PCIMAP = (PCI_MEM_SPACE_PCI_BASE >>27) | (((PCI_MEM_SPACE_PCI_BASE + 0x08000000) >>25)<<5);
#endif
BONITO_PCIBASE0 = PCI_LOCAL_MEM_PCI_BASE;
BONITO_PCIBASE1 = PCI_LOCAL_MEM_ISA_BASE;
BONITO_PCIBASE2 = PCI_LOCAL_REG_PCI_BASE;
/* pci base0/1 can access 256M sdram */
BONITO_PCIMEMBASECFG = 0;
上面设置了北桥里的PCI配置内存空间分配。
return(1);
}
这里的代码,先从北桥里分配PCI的IO空间和内存空间,然后通过枚举所有内存空间来发现PCI的设备,最后对于发现的设备进行配置,并启动相应的设备。
后面再仔细地查看怎么样实现查询PCI设备的发现和PCI设备配置。 查看本文来源