summaryrefslogtreecommitdiffstats
path: root/board/MAI/bios_emulator/scitech/src/pm/common/pcilib.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/pm/common/pcilib.c')
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/common/pcilib.c747
1 files changed, 747 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/pm/common/pcilib.c b/board/MAI/bios_emulator/scitech/src/pm/common/pcilib.c
new file mode 100644
index 0000000000..8dd6dd13e3
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/common/pcilib.c
@@ -0,0 +1,747 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+*
+* Description: Module for interfacing to the PCI bus and configuration
+* space registers.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "pcilib.h"
+#if !defined(__WIN32_VXD__) && !defined(__NT_DRIVER__)
+#include <string.h>
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#pragma pack(1)
+
+/* Length of the memory mapping for the PCI BIOS */
+
+#define BIOS_LIMIT (128 * 1024L - 1)
+
+/* Macros for accessing the PCI BIOS functions from 32-bit protected mode */
+
+#define BIOS32_SIGNATURE (((ulong)'_' << 0) + ((ulong)'3' << 8) + ((ulong)'2' << 16) + ((ulong)'_' << 24))
+#define PCI_SIGNATURE (((ulong)'P' << 0) + ((ulong)'C' << 8) + ((ulong)'I' << 16) + ((ulong)' ' << 24))
+#define PCI_SERVICE (((ulong)'$' << 0) + ((ulong)'P' << 8) + ((ulong)'C' << 16) + ((ulong)'I' << 24))
+#define PCI_BIOS_PRESENT 0xB101
+#define FIND_PCI_DEVICE 0xB102
+#define FIND_PCI_CLASS 0xB103
+#define GENERATE_SPECIAL 0xB106
+#define READ_CONFIG_BYTE 0xB108
+#define READ_CONFIG_WORD 0xB109
+#define READ_CONFIG_DWORD 0xB10A
+#define WRITE_CONFIG_BYTE 0xB10B
+#define WRITE_CONFIG_WORD 0xB10C
+#define WRITE_CONFIG_DWORD 0xB10D
+#define GET_IRQ_ROUTING_OPT 0xB10E
+#define SET_PCI_IRQ 0xB10F
+
+/* This is the standard structure used to identify the entry point to the
+ * BIOS32 Service Directory, as documented in PCI 2.1 BIOS Specicition.
+ */
+
+typedef union {
+ struct {
+ ulong signature; /* _32_ */
+ ulong entry; /* 32 bit physical address */
+ uchar revision; /* Revision level, 0 */
+ uchar length; /* Length in paragraphs should be 01 */
+ uchar checksum; /* All bytes must add up to zero */
+ uchar reserved[5]; /* Must be zero */
+ } fields;
+ char chars[16];
+ } PCI_bios32;
+
+/* Structure for a far pointer to call the PCI BIOS services with */
+
+typedef struct {
+ ulong address;
+ ushort segment;
+ } PCIBIOS_entry;
+
+/* Macros to copy a structure that includes dwSize members */
+
+#define COPY_STRUCTURE(d,s) memcpy(d,s,MIN((s)->dwSize,(d)->dwSize))
+
+#pragma pack()
+
+/*--------------------------- Global variables ----------------------------*/
+
+static uchar *BIOSImage = NULL; /* BIOS image mapping */
+static int PCIBIOSVersion = -1;/* PCI BIOS version */
+static PCIBIOS_entry PCIEntry; /* PCI services entry point */
+static ulong PCIPhysEntry = 0; /* Physical address */
+
+/*----------------------------- Implementation ----------------------------*/
+
+/* External assembler helper functions */
+
+uchar _ASMAPI _BIOS32_service(ulong service,ulong function,ulong *physBase,ulong *length,ulong *serviceOffset,PCIBIOS_entry entry);
+ushort _ASMAPI _PCIBIOS_isPresent(ulong i_eax,ulong *o_edx,ushort *o_ax,uchar *o_cl,PCIBIOS_entry entry);
+ulong _ASMAPI _PCIBIOS_service(ulong r_eax,ulong r_ebx,ulong r_edi,ulong r_ecx,PCIBIOS_entry entry);
+int _ASMAPI _PCIBIOS_getRouting(PCIRoutingOptionsBuffer *buf,PCIBIOS_entry entry);
+ibool _ASMAPI _PCIBIOS_setIRQ(int busDev,int intPin,int IRQ,PCIBIOS_entry entry);
+ulong _ASMAPI _PCIBIOS_specialCycle(int bus,ulong data,PCIBIOS_entry entry);
+ushort _ASMAPI _PCI_getCS(void);
+
+/****************************************************************************
+REMARKS:
+This functions returns the physical address of the PCI BIOS entry point.
+****************************************************************************/
+ulong _ASMAPI PCIBIOS_getEntry(void)
+{ return PCIPhysEntry; }
+
+/****************************************************************************
+PARAMETERS:
+hwType - Place to store the PCI hardware access mechanism flags
+lastBus - Place to store the index of the last PCI bus in the system
+
+RETURNS:
+Version number of the PCI BIOS found.
+
+REMARKS:
+This function determines if the PCI BIOS is present in the system, and if
+so returns the information returned by the PCI BIOS detect function.
+****************************************************************************/
+static int PCIBIOS_detect(
+ uchar *hwType,
+ uchar *lastBus)
+{
+ ulong signature;
+ ushort stat,version;
+
+#ifndef __16BIT__
+ PCIBIOS_entry BIOSEntry = {0};
+ uchar *BIOSEnd;
+ PCI_bios32 *BIOSDir;
+ ulong physBase,length,offset;
+
+ /* Bail if we have already detected no BIOS is present */
+ if (PCIBIOSVersion == 0)
+ return 0;
+
+ /* First scan the memory from 0xE0000 to 0xFFFFF looking for the
+ * BIOS32 service directory, so we can determine if we can call it
+ * from 32-bit protected mode.
+ */
+ if (PCIBIOSVersion == -1) {
+ PCIBIOSVersion = 0;
+ BIOSImage = PM_mapPhysicalAddr(0xE0000,BIOS_LIMIT,false);
+ if (!BIOSImage)
+ return 0;
+ BIOSEnd = BIOSImage + 0x20000;
+ for (BIOSDir = (PCI_bios32*)BIOSImage; BIOSDir < (PCI_bios32*)BIOSEnd; BIOSDir++) {
+ uchar sum;
+ int i,length;
+
+ if (BIOSDir->fields.signature != BIOS32_SIGNATURE)
+ continue;
+ length = BIOSDir->fields.length * 16;
+ if (!length)
+ continue;
+ for (sum = i = 0; i < length ; i++)
+ sum += BIOSDir->chars[i];
+ if (sum != 0)
+ continue;
+ BIOSEntry.address = (ulong)BIOSImage + (BIOSDir->fields.entry - 0xE0000);
+ BIOSEntry.segment = _PCI_getCS();
+ break;
+ }
+
+ /* If we found the BIOS32 directory, call it to get the address of the
+ * PCI services.
+ */
+ if (BIOSEntry.address == 0)
+ return 0;
+ if (_BIOS32_service(PCI_SERVICE,0,&physBase,&length,&offset,BIOSEntry) != 0)
+ return 0;
+ PCIPhysEntry = physBase + offset;
+ PCIEntry.address = (ulong)BIOSImage + (PCIPhysEntry - 0xE0000);
+ PCIEntry.segment = _PCI_getCS();
+ }
+#endif
+ /* We found the BIOS entry, so now do the version check */
+ version = _PCIBIOS_isPresent(PCI_BIOS_PRESENT,&signature,&stat,lastBus,PCIEntry);
+ if (version > 0 && ((stat >> 8) == 0) && signature == PCI_SIGNATURE) {
+ *hwType = stat & 0xFF;
+ return PCIBIOSVersion = version;
+ }
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+info - Array of PCIDeviceInfo structures to check against
+index - Index of the current device to check
+
+RETURNS:
+True if the device is a duplicate, false if not.
+
+REMARKS:
+This function goes through the list of all devices preceeding the newly
+found device in the info structure, and checks that the device is not a
+duplicate of a previous device. Some devices incorrectly enumerate
+themselves at different function addresses so we check here to exclude
+those cases.
+****************************************************************************/
+static ibool CheckDuplicate(
+ PCIDeviceInfo *info,
+ PCIDeviceInfo *prev)
+{
+ /* Ignore devices with a vendor ID of 0 */
+ if (info->VendorID == 0)
+ return true;
+
+ /* NOTE: We only check against the current device on
+ * the bus to ensure that we do not exclude
+ * multiple controllers of the same device ID.
+ */
+ if (info->slot.p.Bus == prev->slot.p.Bus &&
+ info->slot.p.Device == prev->slot.p.Device &&
+ info->DeviceID == prev->DeviceID)
+ return true;
+ return false;
+}
+
+/****************************************************************************
+PARAMETERS:
+info - Array of PCIDeviceInfo structures to fill in
+maxDevices - Maximum number of of devices to enumerate into array
+
+RETURNS:
+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 array
+of configuration information blocks.
+****************************************************************************/
+static int PCI_enumerateMech1(
+ PCIDeviceInfo info[])
+{
+ int bus,device,function,i,numFound = 0;
+ ulong *lp,tmp;
+ PCIslot slot = {{0,0,0,0,0,0,1}};
+ PCIDeviceInfo pci,prev = {0};
+
+ /* Try PCI access mechanism 1 */
+ PM_outpb(0xCFB,0x01);
+ tmp = PM_inpd(0xCF8);
+ PM_outpd(0xCF8,slot.i);
+ if ((PM_inpd(0xCF8) == slot.i) && (PM_inpd(0xCFC) != 0xFFFFFFFFUL)) {
+ /* PCI access mechanism 1 - the preferred mechanism */
+ for (bus = 0; bus < 8; 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;
+ slot.p.Register = 0;
+ PM_outpd(0xCF8,slot.i);
+ if (PM_inpd(0xCFC) != 0xFFFFFFFFUL) {
+ memset(&pci,0,sizeof(pci));
+ pci.dwSize = sizeof(pci);
+ pci.mech1 = 1;
+ pci.slot = slot;
+ lp = (ulong*)&(pci.VendorID);
+ for (i = 0; i < NUM_PCI_REG; i++, lp++) {
+ slot.p.Register = i;
+ PM_outpd(0xCF8,slot.i);
+ *lp = PM_inpd(0xCFC);
+ }
+ if (!CheckDuplicate(&pci,&prev)) {
+ if (info)
+ COPY_STRUCTURE(&info[numFound],&pci);
+ ++numFound;
+ }
+ prev = pci;
+ }
+ }
+ }
+ }
+
+ /* Disable PCI config cycle on exit */
+ PM_outpd(0xCF8,0);
+ return numFound;
+ }
+ PM_outpd(0xCF8,tmp);
+
+ /* No hardware access mechanism 1 found */
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+info - Array of PCIDeviceInfo structures to fill in
+maxDevices - Maximum number of of devices to enumerate into array
+
+RETURNS:
+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 array
+of configuration information blocks.
+****************************************************************************/
+static int PCI_enumerateMech2(
+ PCIDeviceInfo info[])
+{
+ int bus,device,function,i,numFound = 0;
+ ushort deviceIO;
+ ulong *lp;
+ PCIslot slot = {{0,0,0,0,0,0,1}};
+ PCIDeviceInfo pci,prev = {0};
+
+ /* Try PCI access mechanism 2 */
+ PM_outpb(0xCFB,0x00);
+ PM_outpb(0xCF8,0x00);
+ PM_outpb(0xCFA,0x00);
+ if (PM_inpb(0xCF8) == 0x00 && PM_inpb(0xCFB) == 0x00) {
+ /* PCI access mechanism 2 - the older mechanism for legacy busses */
+ for (bus = 0; bus < 2; bus++) {
+ slot.p.Bus = bus;
+ PM_outpb(0xCFA,(uchar)bus);
+ for (device = 0; device < 16; device++) {
+ slot.p.Device = device;
+ 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));
+ }
+ if (!CheckDuplicate(&pci,&prev)) {
+ if (info)
+ COPY_STRUCTURE(&info[numFound],&pci);
+ ++numFound;
+ }
+ prev = pci;
+ }
+ }
+ }
+ }
+
+ /* 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 in
+maxDevices - Maximum number of of devices to enumerate into array
+
+RETURNS:
+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 array
+of configuration information blocks.
+****************************************************************************/
+static int PCI_enumerateBIOS(
+ PCIDeviceInfo info[])
+{
+ uchar hwType,lastBus;
+ int bus,device,function,i,numFound = 0;
+ ulong *lp;
+ PCIslot slot = {{0,0,0,0,0,0,1}};
+ PCIDeviceInfo pci,prev = {0};
+
+ 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);
+ if (!CheckDuplicate(&pci,&prev)) {
+ if (info)
+ COPY_STRUCTURE(&info[numFound],&pci);
+ ++numFound;
+ }
+ prev = pci;
+ }
+ }
+ }
+ }
+ }
+
+ /* Return number of devices found */
+ return numFound;
+}
+
+/****************************************************************************
+PARAMETERS:
+info - Array of PCIDeviceInfo structures to fill in
+maxDevices - Maximum number of of devices to enumerate into array
+
+RETURNS:
+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 array
+of configuration information blocks.
+****************************************************************************/
+int _ASMAPI PCI_enumerate(
+ PCIDeviceInfo info[])
+{
+ int numFound;
+
+ /* 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)) == 0) {
+ if ((numFound = PCI_enumerateMech2(info)) == 0) {
+ if ((numFound = PCI_enumerateBIOS(info)) == 0)
+ return 0;
+ }
+ }
+ return numFound;
+}
+
+/****************************************************************************
+PARAMETERS:
+info - Array of PCIDeviceInfo structures to fill in
+maxDevices - Maximum number of of devices to enumerate into array
+
+RETURNS:
+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 array
+of configuration information blocks.
+****************************************************************************/
+int _ASMAPI PCI_getNumDevices(void)
+{
+ return PCI_enumerate(NULL);
+}
+
+/****************************************************************************
+PARAMETERS:
+bar - Base address to measure
+pci - PCI device to access
+
+RETURNS:
+Size of the PCI base address in bytes
+
+REMARKS:
+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 size
+of the base address is determines by the bits that are hardwired to zero's.
+****************************************************************************/
+ulong _ASMAPI PCI_findBARSize(
+ int bar,
+ PCIDeviceInfo *pci)
+{
+ ulong base,size = 0;
+
+ base = PCI_accessReg(bar,0,PCI_READ_DWORD,pci);
+ if (base && !(base & 0x1)) {
+ /* For some strange reason some devices don't properly decode
+ * their base address registers (Intel PCI/PCI bridges!), and
+ * we read completely bogus values. We check for that here
+ * and clear out those BAR's.
+ *
+ * We check for that here because at least the low 12 bits
+ * of the address range must be zeros, since the page size
+ * on IA32 processors is always 4Kb.
+ */
+ if ((base & 0xFFF) == 0) {
+ 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);
+ }
+ }
+ pci->slot.p.Register = 0;
+ return size;
+}
+
+/****************************************************************************
+PARAMETERS:
+index - DWORD index of the register to access
+value - Value to write to the register for write access
+func - Function to implement
+
+RETURNS:
+The value read from the register for read operations
+
+REMARKS:
+The function code are defined as follows
+
+code - function
+0 - Read BYTE
+1 - Read WORD
+2 - Read DWORD
+3 - Write BYTE
+4 - Write WORD
+5 - 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 for
+
+RETURNS:
+0 on success, -1 on error, number of devices to enumerate if numDevices = 0
+
+REMARKS:
+This function reads the PCI routing information. If you pass a value of
+0 for numDevices, this function will return with the number of devices
+needed 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 device
+intPin - Value to store in the PCI InterruptPin register
+IRQ - 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 the
+desired PCI interrupt and the desired ISA bus compatible IRQ. This function
+may not be supported by the PCI BIOS, in which case this function will
+fail.
+****************************************************************************/
+ibool _ASMAPI PCI_setHardwareIRQ(
+ PCIDeviceInfo *info,
+ uint intPin,
+ uint IRQ)
+{
+ if (PCIPhysEntry) {
+ if (_PCIBIOS_setIRQ(info->slot.i >> 8,intPin,IRQ,PCIEntry)) {
+ info->u.type0.InterruptPin = intPin;
+ info->u.type0.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 for
+specialCycleData - Data to send for the special cyle
+
+REMARKS:
+This function generates a special cycle on the specified bus using with
+the 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 */
+}
+
+/****************************************************************************
+PARAMETERS:
+info - PCI device information block for device to access
+index - Index of register to start reading from
+dst - Place to store the values read from configuration space
+count - Count of bytes to read from configuration space
+
+REMARKS:
+This function is used to read a block of PCI configuration space registers
+from the configuration space into the passed in data block. This function
+will properly handle reading non-DWORD aligned data from the configuration
+space correctly.
+****************************************************************************/
+void _ASMAPI PCI_readRegBlock(
+ PCIDeviceInfo *info,
+ int index,
+ void *dst,
+ int count)
+{
+ uchar *pb;
+ ulong *pd;
+ int i;
+ int startCount = (index & 3);
+ int middleCount = (count - startCount) >> 2;
+ int endCount = count - middleCount * 4 - startCount;
+
+ for (i = 0,pb = dst; i < startCount; i++, index++) {
+ *pb++ = (uchar)PCI_accessReg(index,0,PCI_READ_BYTE,info);
+ }
+ for (i = 0,pd = (ulong*)pb; i < middleCount; i++, index += 4) {
+ *pd++ = (ulong)PCI_accessReg(index,0,PCI_READ_DWORD,info);
+ }
+ for (i = 0,pb = (uchar*)pd; i < endCount; i++, index++) {
+ *pb++ = (uchar)PCI_accessReg(index,0,PCI_READ_BYTE,info);
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+info - PCI device information block for device to access
+index - Index of register to start reading from
+dst - Place to store the values read from configuration space
+count - Count of bytes to read from configuration space
+
+REMARKS:
+This function is used to write a block of PCI configuration space registers
+to the configuration space from the passed in data block. This function
+will properly handle writing non-DWORD aligned data to the configuration
+space correctly.
+****************************************************************************/
+void _ASMAPI PCI_writeRegBlock(
+ PCIDeviceInfo *info,
+ int index,
+ void *src,
+ int count)
+{
+ uchar *pb;
+ ulong *pd;
+ int i;
+ int startCount = (index & 3);
+ int middleCount = (count - startCount) >> 2;
+ int endCount = count - middleCount * 4 - startCount;
+
+ for (i = 0,pb = src; i < startCount; i++, index++) {
+ PCI_accessReg(index,*pb++,PCI_WRITE_BYTE,info);
+ }
+ for (i = 0,pd = (ulong*)pb; i < middleCount; i++, index += 4) {
+ PCI_accessReg(index,*pd++,PCI_WRITE_DWORD,info);
+ }
+ for (i = 0,pb = (uchar*)pd; i < endCount; i++, index++) {
+ PCI_accessReg(index,*pb++,PCI_WRITE_BYTE,info);
+ }
+}
OpenPOWER on IntegriCloud