📄 pcilib.c
字号:
deviceIO = 0xC000 + (device << 8); for (function = 0; function < 8; function++) { slot.p.Function = function; slot.p.Register = 0; PM_outpb(0xCF8,(uchar)((function << 1) | 0x10)); if (PM_inpd(deviceIO) != 0xFFFFFFFFUL) { memset(&pci,0,sizeof(pci)); pci.dwSize = sizeof(pci); pci.mech1 = 0; pci.slot = slot; lp = (ulong*)&(pci.VendorID); for (i = 0; i < NUM_PCI_REG; i++, lp++) { slot.p.Register = i; *lp = PM_inpd(deviceIO + (i << 2)); } COPY_STRUCTURE(&info[numFound],&pci); if (!CheckDuplicate(info,numFound)) { if (++numFound >= maxDevices) break; } } if (numFound >= maxDevices) break; } if (numFound >= maxDevices) break; } if (numFound >= maxDevices) break; } /* Disable PCI config cycle on exit */ PM_outpb(0xCF8,0); return numFound; } /* No hardware access mechanism 2 found */ return 0;}/****************************************************************************REMARKS:This functions reads a configuration dword via the PCI BIOS.****************************************************************************/static ulong PCIBIOS_readDWORD( int index, ulong slot){ return (ulong)_PCIBIOS_service(READ_CONFIG_DWORD,slot >> 8,index,0,PCIEntry);}/****************************************************************************PARAMETERS:info - Array of PCIDeviceInfo structures to fill inmaxDevices - Maximum number of of devices to enumerate into arrayRETURNS:Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.REMARKS:Function to enumerate all available devices on the PCI bus into an arrayof configuration information blocks.****************************************************************************/static int PCI_enumerateBIOS( PCIDeviceInfo info[], int maxDevices){ uchar hwType,lastBus; int bus,device,function,i,numFound = 0; ulong *lp; PCIslot slot = {{0,0,0,0,0,0,1}}; PCIDeviceInfo pci; if (PCIBIOS_detect(&hwType,&lastBus)) { /* PCI BIOS access - the ultimate fallback */ for (bus = 0; bus <= lastBus; bus++) { slot.p.Bus = bus; for (device = 0; device < 32; device++) { slot.p.Device = device; for (function = 0; function < 8; function++) { slot.p.Function = function; if (PCIBIOS_readDWORD(0,slot.i) != 0xFFFFFFFFUL) { memset(&pci,0,sizeof(pci)); pci.dwSize = sizeof(pci); pci.mech1 = 2; pci.slot = slot; lp = (ulong*)&(pci.VendorID); for (i = 0; i < NUM_PCI_REG; i++, lp++) *lp = PCIBIOS_readDWORD(i << 2,slot.i); COPY_STRUCTURE(&info[numFound],&pci); if (!CheckDuplicate(info,numFound)) { if (++numFound >= maxDevices) break; } } if (numFound >= maxDevices) break; } if (numFound >= maxDevices) break; } if (numFound >= maxDevices) break; } } /* Return number of devices found */ return numFound;}/****************************************************************************PARAMETERS:bar - Base address to measurepci - PCI device to accessRETURNS:Size of the PCI base address in bytesREMARKS:This function measures the size of the PCI base address register in bytes,by writing all F's to the register, and reading the value back. The sizeof the base address is determines by the bits that are hardwired to zero's.****************************************************************************/static ulong PCI_findBARSize( int bar, PCIDeviceInfo *pci){ ulong base,size = 0; base = PCI_accessReg(bar,0,PCI_READ_DWORD,pci); if (base && !(base & 0x1)) { PCI_accessReg(bar,0xFFFFFFFF,PCI_WRITE_DWORD,pci); size = PCI_accessReg(bar,0,PCI_READ_DWORD,pci) & ~0xFF; size = ~size+1; PCI_accessReg(bar,base,PCI_WRITE_DWORD,pci); } return size;}/****************************************************************************PARAMETERS:info - Array of PCIDeviceInfo structures to fill inmaxDevices - Maximum number of of devices to enumerate into arrayRETURNS:Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.REMARKS:Function to enumerate all available devices on the PCI bus into an arrayof configuration information blocks.****************************************************************************/int _ASMAPI PCI_enumerate( PCIDeviceInfo info[], int maxDevices){ uchar hwType,lastBus; int numFound,i,j; ulong *size; /* Detect if we have the PCI BIOS services */ PCIBIOS_detect(&hwType,&lastBus); /* First try via the direct access mechanisms which are faster if we * have them (nearly always). The BIOS is used as a fallback, and for * stuff we can't do directly. */ if ((numFound = PCI_enumerateMech1(info,maxDevices)) == 0) { if ((numFound = PCI_enumerateMech2(info,maxDevices)) == 0) { if ((numFound = PCI_enumerateBIOS(info,maxDevices)) == 0) return 0; } } /* Now measure the size of all PCI base address registers */ for (i = 0; i < numFound; i++) { size = (ulong*)&(info[i].BaseAddress10Len); for (j = 0x10; j <= 0x24; j += 4, size++) { *size = PCI_findBARSize(j,&info[i]); } info[i].ROMBaseAddressLen = PCI_findBARSize(0x30,&info[i]); } return numFound;}/****************************************************************************PARAMETERS:index - DWORD index of the register to accessvalue - Value to write to the register for write accessfunc - Function to implementRETURNS:The value read from the register for read operationsREMARKS:The function code are defined as followscode - function0 - Read BYTE1 - Read WORD2 - Read DWORD3 - Write BYTE4 - Write WORD5 - Write DWORD****************************************************************************/ulong _ASMAPI PCI_accessReg( int index, ulong value, int func, PCIDeviceInfo *info){ int iobase; if (info->mech1 == 2) { /* Use PCI BIOS access since we dont have direct hardware access */ switch (func) { case PCI_READ_BYTE: return (uchar)_PCIBIOS_service(READ_CONFIG_BYTE,info->slot.i >> 8,index,0,PCIEntry); case PCI_READ_WORD: return (ushort)_PCIBIOS_service(READ_CONFIG_WORD,info->slot.i >> 8,index,0,PCIEntry); case PCI_READ_DWORD: return (ulong)_PCIBIOS_service(READ_CONFIG_DWORD,info->slot.i >> 8,index,0,PCIEntry); case PCI_WRITE_BYTE: _PCIBIOS_service(WRITE_CONFIG_BYTE,info->slot.i >> 8,index,value,PCIEntry); break; case PCI_WRITE_WORD: _PCIBIOS_service(WRITE_CONFIG_WORD,info->slot.i >> 8,index,value,PCIEntry); break; case PCI_WRITE_DWORD: _PCIBIOS_service(WRITE_CONFIG_DWORD,info->slot.i >> 8,index,value,PCIEntry); break; } } else { /* Use direct hardware access mechanisms */ if (info->mech1) { /* PCI access mechanism 1 */ iobase = 0xCFC + (index & 3); info->slot.p.Register = index >> 2; PM_outpd(0xCF8,info->slot.i); } else { /* PCI access mechanism 2 */ PM_outpb(0xCF8,(uchar)((info->slot.p.Function << 1) | 0x10)); PM_outpb(0xCFA,(uchar)info->slot.p.Bus); iobase = 0xC000 + (info->slot.p.Device << 8) + index; } switch (func) { case PCI_READ_BYTE: case PCI_READ_WORD: case PCI_READ_DWORD: value = PM_inpd(iobase); break; case PCI_WRITE_BYTE: PM_outpb(iobase,(uchar)value); break; case PCI_WRITE_WORD: PM_outpw(iobase,(ushort)value); break; case PCI_WRITE_DWORD: PM_outpd(iobase,(ulong)value); break; } PM_outpd(0xCF8,0); } return value;}/****************************************************************************PARAMETERS:numDevices - Number of devices to query info forRETURNS:0 on success, -1 on error, number of devices to enumerate if numDevices = 0REMARKS:This function reads the PCI routing information. If you pass a value of0 for numDevices, this function will return with the number of devicesneeded in the routing buffer that will be filled in by the BIOS.****************************************************************************/ibool _ASMAPI PCI_getIRQRoutingOptions( int numDevices, PCIRouteInfo *buffer){ PCIRoutingOptionsBuffer buf; int ret; if (PCIPhysEntry) { buf.BufferSize = numDevices * sizeof(PCIRouteInfo); buf.DataBuffer = buffer; if ((ret = _PCIBIOS_getRouting(&buf,PCIEntry)) == 0x89) return buf.BufferSize / sizeof(PCIRouteInfo); if (ret != 0) return -1; return 0; } /* We currently only support this via the PCI BIOS functions */ return -1;}/****************************************************************************PARAMETERS:info - PCI device information for the specified deviceintPin - Value to store in the PCI InterruptPin registerIRQ - New ISA IRQ to map the PCI interrupt to (0-15)RETURNS:True on success, or false if this function failed.REMARKS:This function changes the PCI IRQ routing for the specified device to thedesired PCI interrupt and the desired ISA bus compatible IRQ. This functionmay not be supported by the PCI BIOS, in which case this function willfail.****************************************************************************/ibool _ASMAPI PCI_setHardwareIRQ( PCIDeviceInfo *info, uint intPin, uint IRQ){ if (PCIPhysEntry) { if (_PCIBIOS_setIRQ(info->slot.i >> 8,intPin,IRQ,PCIEntry)) { info->InterruptPin = intPin; info->InterruptLine = IRQ; return true; } return false; } /* We currently only support this via the PCI BIOS functions */ return false;}/****************************************************************************PARAMETERS:bus - Bus number to generate the special cycle forspecialCycleData - Data to send for the special cyleREMARKS:This function generates a special cycle on the specified bus using withthe specified data.****************************************************************************/void _ASMAPI PCI_generateSpecialCyle( uint bus, ulong specialCycleData){ if (PCIPhysEntry) _PCIBIOS_specialCycle(bus,specialCycleData,PCIEntry); /* We currently only support this via the PCI BIOS functions */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -