📄 ixm1200pci.c
字号:
/* Assign Addresses */ for (i=0; i < nBars; i++) { /* Assign bar[i] */ if (Bars[i]->address != 0xFFFFFFFF) { /* Already Assigned */ continue; } /* Find first available addr */ addr = 0; /* check for conflicts */ for (j=0; j < nBars; j++) { if (Bars[j]->address == 0xFFFFFFFF) continue; /* Bars[j] has valid address */ if ((Bars[j]->address < addr + Bars[i]->size) && (addr < Bars[j]->address + Bars[j]->size)) { /* conflict */ addr = Bars[j]->address + Bars[j]->size; addr = (addr + Bars[i]->size - 1) & ~(Bars[i]->size - 1); j = -1; continue; } /* end if conflict */ } /* end for j */ /* no conflict */ Bars[i]->address = addr; } /* end for i */}/******************************************************************************** addPageEntries - Call sysMmuMapAdd to add page entries for specified range** This function takes a range of addresses containing a gap, and then calls* sysMmuMapAdd to add page table entries for the one or two memory ranges* specified.** RETURNS: N/A*/static voidaddPageEntries ( UINT32 start, /* Starting PCI address of range*/ UINT32 size, /* Size of range */ UINT32 offset /* Offset from PCI address to virtual address */ ){ UINT32 end = start + size; if (size != 0) { start = ROUND_DOWN(start, PAGE_SIZE); end = ROUND_UP(end, PAGE_SIZE); sysMmuMapAdd((void*)(offset + start), end-start, VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE, VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT); }}/******************************************************************************** sysPciAssignAddrs - Scan PCI bus and automatically assign PCI addresses** This function scans the PCI bus to see what other devices are there. It then* sorts the BARs that it finds and 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.** As a special case, it assigns its own SDRAM space to PCI address zero.** This funciton only has an effect if this processor is the PCI central function.** RETURNS: N/A*/voidsysPciAssignAddrs(void){ PciBar *memBars[MAX_BARS]; PciBar *ioBars[MAX_BARS]; int nMBars, nIOBars; int bus, dev, func, i, j; UINT16 data; INT32 data32, tmp, size;#if !(defined(IXM1200)) int central_func; central_func = IXP1200_SA_CONTROL_PCF & *(UINT32 *)IXP1200_SA_CONTROL; if (! central_func) return;#endif /* Assign first device to ourselves */ devices[0].bus = 0; devices[0].device = 0; devices[0].func = 0; devices[0].vendor_id = sysRead16((void*)IXM1200_PCI_VENDOR_ID); devices[0].device_id = sysRead16((void*)IXM1200_PCI_DEVICE_ID); devices[0].error = FALSE; devices[0].bar[CSR_BAR].size = IXM1200_PCI_MEM_BAR_SIZE; /* 1 Meg: CSR Mem Base */ devices[0].bar[CSR_BAR].address = *(UINT32 *)(IXM1200_PCI_MEM_BAR); /* Mem addr */ devices[0].bar[IO_BAR].size = IXM1200_PCI_IO_BAR_SIZE; /* 128: CSR I/O Base */ devices[0].bar[IO_BAR].address = *(UINT32 *)(IXM1200_PCI_IO_BAR); /* I/O addr */ devices[0].bar[SD_BAR].size = LOCAL_MEM_SIZE_ACTUAL; /* SDRAM Mem Base */ devices[0].bar[SD_BAR].address = *(UINT32 *)(IXM1200_PCI_DRAM_BAR); /* Mem addr */ devices[0].bar[NO_BAR].size = 0; nDevices = 1; nMBars = nIOBars = 0; /* But SDRAM base first */ memBars[nMBars++] = &devices[0].bar[SD_BAR]; memBars[nMBars++] = &devices[0].bar[CSR_BAR]; ioBars[nIOBars++] = &devices[0].bar[IO_BAR]; func = 0; for ( bus = 0; bus < PCI_MAX_BUS; bus++ ) { for (dev = 0; dev < PCI_MAX_DEV; dev++ ) { pciConfigInWord(bus, dev, func, 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 = func; devices[nDevices].vendor_id = data; pciConfigInWord(bus, dev, func, PCI_CFG_DEVICE_ID, &data); devices[nDevices].device_id = data; devices[nDevices].error = FALSE; for (i=0; i<6; i++) { pciConfigOutLong(bus, dev, func, PCI_CFG_BASE_ADDRESS_0 + (4*i), 0xFFFFFFFF); pciConfigInLong(bus, dev, func, PCI_CFG_BASE_ADDRESS_0 + (4*i), &data32); if (data32 == 0) break; devices[nDevices].bar[i].address = (data32 & 1); if (data32 & 1) { /* IO space */ tmp = data32 & ~0x00000003; size = ~(tmp-1); devices[nDevices].bar[i].size = size; devices[nDevices].bar[i].address = 0xFFFFFFFF; if (tmp != ~(size-1)) devices[nDevices].error = TRUE; else { if (nIOBars < MAX_BARS) ioBars[nIOBars++] = &devices[nDevices].bar[i]; } } else { /* Mem space */ tmp = data32 & ~0x0000000F; size = ~(tmp-1); devices[nDevices].bar[i].size = size; devices[nDevices].bar[i].address = 0xFFFFFFFF; if (tmp != ~(size-1)) devices[nDevices].error = TRUE; else { if (nMBars < MAX_BARS) memBars[nMBars++] = &devices[nDevices].bar[i]; } } } /* end for i */ devices[nDevices].bar[i].size = 0; devices[nDevices].irq = (int)INT_VEC_PIL; nDevices++; } /* end for dev */ } /* end for bus */ /* Sort bars, Leave our SDRAM at Mem zero */ sortBars(memBars, nMBars); sortBars(ioBars, nIOBars); for (i=0; i < nIOBars; i++) ioBars[i]->address |= 1; data = INITIAL_PCI_CMD; *(UINT32 *)(IXM1200_PCI_MEM_BAR) = devices[0].bar[CSR_BAR].address; *(UINT32 *)(IXM1200_PCI_IO_BAR) = devices[0].bar[IO_BAR].address; *(UINT32 *)(IXM1200_PCI_DRAM_BAR) = devices[0].bar[SD_BAR].address; /* Fix C0/Hyannis PCI CSR bug */ *(volatile int*)(IXM1200_PCI_MEM_BAR); for (i=1; i<nDevices; i++) { if (devices[i].error) continue; 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); addPageEntries(devices[i].bar[j].address, devices[i].bar[j].size, ((devices[i].bar[j].address & 1) ? PCI_IO_BASE : PCI_MEM_BASE)); } 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, data); } /* end for i */}/******************************************************************************** readBarsAddrs - Scan PCI bus and automatically reads the BARs addresses** This function scans the PCI bus and reads their addresses. It also adds* page entries to cover the range of PCI space used.** As a special case, it assigns its own SDRAM space to PCI address zero.** This funciton only has an effect if this processor is the PCI central function.** RETURNS: N/A*/voidreadBarsAddrs(void){ int bus, dev, func, i, j; UINT16 data; INT32 data32, tmp, size;#if !(defined(IXM1200)) int central_func; central_func = IXM1200_SA_CONTROL_PCF & *(UINT32 *)IXM1200_SA_CONTROL; if (! central_func) return;#endif /* Assign first device to ourselves */ devices[0].bus = 0; devices[0].device = 0; devices[0].func = 0; devices[0].vendor_id = sysRead16((void*)IXM1200_PCI_VENDOR_ID); devices[0].device_id = sysRead16((void*)IXM1200_PCI_DEVICE_ID); devices[0].error = FALSE; devices[0].bar[CSR_BAR].size = IXM1200_PCI_MEM_BAR_SIZE; /* 1 Meg: CSR Mem Base */ devices[0].bar[CSR_BAR].address = *(UINT32 *)(IXM1200_PCI_MEM_BAR); /* Mem addr */ devices[0].bar[IO_BAR].size = IXM1200_PCI_IO_BAR_SIZE; /* 128: CSR I/O Base */ devices[0].bar[IO_BAR].address = *(UINT32 *)(IXM1200_PCI_IO_BAR); /* I/O addr */ devices[0].bar[SD_BAR].size = LOCAL_MEM_SIZE_ACTUAL; /* SDRAM Mem Base */ devices[0].bar[SD_BAR].address = *(UINT32 *)(IXM1200_PCI_DRAM_BAR); /* Mem addr */ devices[0].bar[NO_BAR].size = 0; nDevices = 1; func = 0; for ( bus = 0; bus < PCI_MAX_BUS; bus++ ) { for (dev = 0; dev < PCI_MAX_DEV; dev++ ) { pciConfigInWord(bus, dev, func, 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 = func; devices[nDevices].vendor_id = data; pciConfigInWord(bus, dev, func, PCI_CFG_DEVICE_ID, &data); devices[nDevices].device_id = data; devices[nDevices].error = FALSE; for (i=0; i<6; i++) { pciConfigInLong(bus, dev, func, PCI_CFG_BASE_ADDRESS_0 + (4*i), &devices[nDevices].bar[i].address); pciConfigOutLong(bus, dev, func, PCI_CFG_BASE_ADDRESS_0 + (4*i), 0xFFFFFFFF); pciConfigInLong(bus, dev, func, PCI_CFG_BASE_ADDRESS_0 + (4*i), &data32); pciConfigOutLong(bus, dev, func, PCI_CFG_BASE_ADDRESS_0 + (4*i), devices[nDevices].bar[i].address); if (data32 == 0) break; devices[nDevices].bar[i].address = (data32 & 1); tmp = data32 & ~0x0000000F; size = ~(tmp-1); devices[nDevices].bar[i].size = size; if (tmp != ~(size-1)) devices[nDevices].error = TRUE; } /* end for i */ devices[nDevices].bar[i].size = 0; nDevices++; } /* end for dev */ } /* end for bus */ for (i=1; i<nDevices; i++) { if (devices[i].error) continue; for (j=0; devices[i].bar[j].size; j++) { addPageEntries(devices[i].bar[j].address, devices[i].bar[j].size, ((devices[i].bar[j].address & 1) ? PCI_IO_BASE : PCI_MEM_BASE)); } } /* 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, j; for (i=0; i<nDevices; i++) { printf("bus %d dev %d irq 0x%02X error %d id %04X %04X\n", devices[i].bus, devices[i].device, devices[i].irq, devices[i].error, 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]);}#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, 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 ); }#endif /* ifdef AUTO_PCI_CONFIG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -