📄 ixdp2400pci.c
字号:
{ return (void*)(~(*(UINT32 *)IXP2400_PCI_DRAM_BAR & ~0xF) & ((UINT32)PciAddr));}/******************************************************************************** sysPhysToPci - translate a physical address to a Pci address** This function converts a physical address to a Pci address. This only works* for PCI Memory space.** RETURNS: the Pci adddress*/void * sysPhysToPci(void *PhysAddr){ return (void*)((*(UINT32 *)IXP2400_PCI_DRAM_BAR & ~0xF) | ((UINT32)PhysAddr));}#ifdef AUTO_PCI_CONFIG/******************************************************************************** sysPciAssignAddrs - Scan PCI bus and automatically assign PCI addresses** This function scans the PCI bus to see what other devices are there. Then* it assigns them addresses. It also adds page entries to cover the range of* PCI space used. It enables PCI transactions as defined by INITIAL_PCI_CMD,* which defaults to enabling IO transactions.* It also does the transparent bridge init.** This funciton only has an effect if this processor is the PCI central function.** RETURNS: N/A*/voidsysPciAssignAddrs(void){ UINT32 ioStartAddr = 0; UINT32 memStartAddr = 0; int bus; int dev; int i; int j; UINT16 data; INT32 data32; INT32 size; UINT32 bridgeIoStart = 0; UINT32 bridgeIoLimit = 0; UINT32 bridgeMemStart = 0; UINT32 bridgeMemLimit = 0; int memAddrExt = 0; int ioAddrExt = 0; /* if this is slave npu then return */ if(!(strapOptionsVal & CFG_PCI_BOOT_HOST)) return; nDevices = 0; for(bus = 0; bus < PCI_MAX_BUS; bus++) { for(dev = 0; dev < PCI_MAX_DEV; dev++) { pciConfigInWord(bus, dev, 0, PCI_CFG_VENDOR_ID, &data); if (data == 0xFFFF) continue; if (nDevices == MAX_DEVICES) break; devices[nDevices].bus = bus; devices[nDevices].device = dev; devices[nDevices].func = 0; devices[nDevices].vendor_id = data; pciConfigInWord(bus, dev, 0, PCI_CFG_DEVICE_ID, &data); devices[nDevices].device_id = data; for (i = 0; i < 6; i++) { pciConfigOutLong(bus, dev, 0, PCI_CFG_BASE_ADDRESS_0 + (4*i), 0xFFFFFFFF); pciConfigInLong(bus, dev, 0, PCI_CFG_BASE_ADDRESS_0 + (4*i), &data32); if (data32 == 0) { devices[nDevices].bar[i].size = 0; break; } devices[nDevices].bar[i].address = (data32 & 1); if (data32 & 1) { /* IO space */ size = ~((data32 & ~0x3) - 1); devices[nDevices].bar[i].size = size; if((ioStartAddr + devices[nDevices].bar[i].size) < 0x2000000) { /* assign address */ ioStartAddr = ROUND_UP(ioStartAddr, devices[nDevices].bar[i].size); devices[nDevices].bar[i].address |= ioStartAddr; ioStartAddr += devices[nDevices].bar[i].size; } else { if(ioAddrExt < 0xFFFF) { ioAddrExt++; devices[nDevices].bar[i].address = ioAddrExt << 16; } } } else { /* Mem space */ size = ~((data32 & ~0xF) - 1); devices[nDevices].bar[i].size = size; if(((memStartAddr + devices[nDevices].bar[i].size) < 0x20000000) && (size < SZ_128M)) { /* assign address */ memStartAddr = ROUND_UP(memStartAddr, devices[nDevices].bar[i].size); devices[nDevices].bar[i].address |= memStartAddr; memStartAddr += devices[nDevices].bar[i].size; } else { if(memAddrExt < 7) { memAddrExt++; devices[nDevices].bar[i].address = memAddrExt << 29; } } } } /* end for i */ devices[nDevices].irq = (int)INT_VEC_PIL; nDevices++; } /* end for dev */ /* For bridges, the memory window must start and end on a 1M boundary and the I/O window must start and end on a 4K boundary. We round up the mem and I/O allocation bases to appropriate boundaries before configuring the devices on secondary bus */ if(bus == 0) { /* round up start of PCI memory space to a 1M boundary */ memStartAddr = ROUND_UP(memStartAddr, SZ_1M); /* round up start of PCI I/O space to a 4 Kbyte start address */ ioStartAddr = ROUND_UP(ioStartAddr, SZ_4K); /* save the starting offset for bus 1 */ bridgeIoStart = ioStartAddr; bridgeMemStart = memStartAddr; } } /* end for bus */ /* check if we used any IO space */ if(ioStartAddr > bridgeIoStart) { ioStartAddr = ROUND_UP(ioStartAddr, SZ_4K); bridgeIoLimit = ioStartAddr - 0x1000; /* configure bridge registers accordingly */ pciConfigOutWord(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_IO_BASE_U, (bridgeIoStart >> 16)); pciConfigOutWord(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_IO_LIMIT_U, (bridgeIoLimit >> 16)); pciConfigOutByte(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_IO_BASE, ((bridgeIoStart & 0xf000) >> 8)); pciConfigOutByte(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_IO_LIMIT, ((bridgeIoLimit & 0xf000) >> 8)); } /* check if we used any Mem space */ if(memStartAddr > bridgeMemStart) { memStartAddr = ROUND_UP(memStartAddr, SZ_1M); bridgeMemLimit = memStartAddr - 0x100000; /* configure bridge registers accordingly */ pciConfigOutWord(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_MEM_BASE, ((bridgeMemStart >> 16) & 0xfff0)); pciConfigOutWord(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_MEM_LIMIT, ((bridgeMemLimit >> 16) & 0xfff0)); pciConfigOutWord(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_PRE_MEM_LIMIT, 0); pciConfigOutWord(tbBusNo, tbDeviceNo, tbFuncNo, PCI_CFG_PRE_MEM_BASE, 0xfff0); } for(i = 0; i < nDevices; i++) { for (j = 0; devices[i].bar[j].size; j++) { pciConfigOutLong(devices[i].bus, devices[i].device, devices[i].func, PCI_CFG_BASE_ADDRESS_0 + (4*j), devices[i].bar[j].address); } pciConfigOutLong(devices[i].bus, devices[i].device, devices[i].func, PCI_CFG_DEV_INT_LINE, INT_VEC_PIL); pciConfigOutWord(devices[i].bus, devices[i].device, devices[i].func, PCI_CFG_COMMAND, PCI_CMD_STAT_VAL); } /* end for i */}#ifdef INCLUDE_AUTO_PCI_CONFIG_SHOW_ROUTINE/******************************************************************************** pciAddrShow - Shows PCI address assignments** This function prints the PCI address assignments automatically generated. * It prints a table giving for each device the bus number, device number,* a flag indicating whether there was an error for that device, and the* vendor/device ID. Then it lists the BARs for that device, giving the* size of the region and its address. If the low-order bit of the address* is "1", then the address corresponds to I/O space, otherwise it is in* memory space.** RETURNS: N/A*/void pciAddrShow(void){ int i; int j; for(i = 0; i < nDevices; i++) { printf("bus %d dev %d irq 0x%02X id %04X %04X\n", devices[i].bus, devices[i].device, devices[i].irq, devices[i].vendor_id, devices[i].device_id); for (j=0; devices[i].bar[j].size; j++) { printf(" size %08X addr %08X\n", devices[i].bar[j].size, devices[i].bar[j].address); } } /* end for i */}/******************************************************************************** pciInfoGet - Retrieves PCI device information** This function retrieves the PCI assignments of the specified device. * It returns a pointer to a PciDevice structure containing the bus number,* device number, a flag indicating whether there was an error for that* device, the vendor/device ID and a lists the BARs indicating the size of* the region and its address for that device. A NULL pointer will be* returned if the specified device is not within range of the configured* devices.** RETURNS: Pointer to PCI device information, or NULL*/PciDevice *pciInfoGet(UINT16 device){ if(device >= nDevices) return(NULL); return(&devices[device]);}/******************************************************************************** pciInfoSearch - Retrieves PCI device information** This function returns a pointer to the n'th instance of a specified device.* If the entry is not found, NULL is returned.** RETURNS: Pointer to PCI device information, or NULL*/PciDevice *pciInfoSearch(int bus, int device, int func, int count){ int ix; int cnt = 0; for ( ix = 0; ix < MAX_DEVICES; ix++) { if(devices[ix].bus == bus && devices[ix].device == device && devices[ix].func == func) { if(cnt == count) return (&devices[ix]); else cnt++; } } return((PciDevice *)NULL);}#endif /* ifdef #ifdef INCLUDE_AUTO_PCI_CONFIG_SHOW_ROUTINE *//******************************************************************************** pciDeviceGet - Retrieves PCI device information** This function returns a pointer to the n'th instance of a specified device.* If the entry is not found, NULL is returned.** RETURNS: Pointer to PCI device information, or NULL*/PciDevice *pciDeviceGet(int vendor_id, int device_id, int count){ int ix; int cnt = 0; for(ix = 0; ix < MAX_DEVICES; ix++) { if(devices[ix].vendor_id == vendor_id && devices[ix].device_id == device_id) { if(cnt == count) return (&devices[ix]); else cnt++; } } return( (PciDevice *)NULL );}/********************************************************************************* pciDeviceShow - print information about PCI devices** This routine prints information about PCI devices* There are two ways to find out an empty device.* - check Master Abort bit after the access.* - check whether the read value is 0xffff.* It uses the second method, since I didn't see the Master Abort bit of* the host/PCI bridge changing.** RETURNS:* OK, or ERROR if the library is not initialized.*/STATUS pciDeviceShow(void) { int deviceNo; if (pciLibInitStatus != OK) /* sanity check */ return (ERROR); printf ("bus device function vendorID deviceID\n"); for (deviceNo=0; deviceNo < nDevices; deviceNo++) { printf ("%.8x %.8x %.8x %.8x %.8x\n", devices[deviceNo].bus, devices[deviceNo].device, devices[deviceNo].func, devices[deviceNo].vendor_id, devices[deviceNo].device_id); } return (OK); }#endif /* ifdef AUTO_PCI_CONFIG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -