pciconfig.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,063 行 · 第 1/3 页
C
1,063 行
}
/* work out the interrupt number from the slot/pin */
interrupt = uHALir_PCIMapInterrupt(pin, curr->slot);
/*
* write it to the device (this will be read later by a
* device driver
*/
OEM_WriteConfigByte(device->bus, device->slot, device->func,
PCI_INTERRUPT_LINE, interrupt);
#endif
}
/*
* Routine: PCI_AllocateIOSpace
*
* Description: Allocate space in PCI IO memory
*
* Returns: Base address of allocated PCI I/O space
*
* Note: Calling this code has a side effect of moving the global
* IO base on.
*/
static DWORD PCI_AllocateIOSpace(DWORD size)
{
DWORD base;
/*
* 20000329 KWelton
*
* I don't see why we need to align to DEFAULT_IO_ALIGNMENT at
* all - according to the spec we only need to align to the requested
* size
*/
#ifdef OldCode
DWORD alignto;
/* align in minimum sized chunks of DEFAULT_IO_ALIGNMENT */
alignto = MAX(size, DEFAULT_IO_ALIGNMENT);
base = ALIGN(PCI_IOBase, alignto);
#else /* OldCode */
base = ALIGN(PCI_IOBase, size);
#endif /* !def OldCode */
PCI_IOBase = base + size;
return base;
}
/*
* Routine: PCI_AllocatePCIDevice
*
* Description: Allocate new PCIDevice structure.
*
* Returns: Pointer to new structure, or NULL if it fails.
*/
static PCIDevice_t *PCI_AllocatePCIDevice(void)
{
PCIDevice_t *newDev;
newDev = freePCIDevices;
if (newDev != NULL)
{
freePCIDevices = newDev->next;
newDev->flags.bridge = 0;
newDev->next = NULL;
newDev->sibling = NULL;
newDev->parent = NULL;
newDev->bridge.children = NULL;
}
return newDev;
}
/*
* Routine: PCI_InitDevices
*
* Description: Initializes the devNode data structures.
*
* Returns: Nothing
*
*/
static void PCI_InitDevices(void)
{
int i;
PCIDevice_t *newDev;
for (i = 0; i < MAX_PCIDEVICES; i++)
{
newDev = &StaticPCIDevices[i];
newDev->next = freePCIDevices;
freePCIDevices = newDev;
}
PCIDevicesInitialised = TRUE;
}
/*
* Routine: PCI_AddPCIDevice
*
* Description: This routine will insert this device into the devNode tree.
* It will keep track of available devNodes.
*
* returns: Pointer to new device, NULL if it failed
*/
static PCIDevice_t *PCI_AddPCIDevice(PCIDevice_t *bridge, BYTE bus,
BYTE slot, BYTE func,
WORD vendor, WORD device)
{
PCIDevice_t *newDev;
/* first allocate a new one */
newDev = PCI_AllocatePCIDevice();
if (newDev != NULL)
{
newDev->bus = bus;
newDev->slot = slot;
newDev->func = func;
newDev->vendor = vendor;
newDev->device = device;
// enqueue it [1]
newDev->next = PCIDeviceList;
PCIDeviceList = newDev;
// enqueue it [2]
newDev->sibling = bridge->bridge.children;
bridge->bridge.children = newDev;
newDev->parent = bridge;
}
return newDev;
}
/*
* Routine: PCI_ScanPCI
*
* Description: This routine will insert all known fixed devices into the
* device node tree. It will then scan the PCI buses looking
* for valid devices.
*
* Returns: Number of maximum subordinate bus
*
*/
static unsigned char PCI_ScanPCI(PCIDevice_t *bus)
{
UCHAR slot, maxsub;
UCHAR thisbus = bus->bridge.secondary;
DWORD maxSlot;
/* maximum subordinate bus number (used in PCI bus numbering) */
maxsub = bus->bridge.secondary;
/*
* how many slots we scan depends on whether this is the primary
* PCI bus or we're going through one or more bridges
*/
maxSlot = (thisbus == 0) ? 20 : 31;
/* scan all possible buses and slots looking for devices */
for (slot = 0; slot <= maxSlot; slot++)
{
BOOL is_a_multi_function_device = FALSE;
UCHAR func;
/* now scan all functions */
for (func = 0; func < 8; func++)
{
WORD vendor, device;
DWORD devClass;
/*
* if it is not a multi-function device, do not
* treat it as one
*/
if ((func != 0) && !is_a_multi_function_device)
break;
/* read the device configuration space */
vendor = OEM_ReadConfigWord(thisbus, slot, func, PCI_VENDOR_ID);
/* check if it responds */
if (vendor != PCI_NOTFITTED)
{
UCHAR header_type;
PCIDevice_t *newDev;
/*
* read the header type (this may be a multi-function
* device)
*/
header_type = OEM_ReadConfigByte(thisbus, slot, func,
PCI_HEADER_TYPE);
if (func == 0)
is_a_multi_function_device = ((header_type & 0x80) != 0);
/*
* get the device and create PCI device data structure
*/
device = OEM_ReadConfigWord(thisbus, slot, func,
PCI_DEVICE_ID);
VDPF("PCI_ScanPCI: Device %x, Vendor %x on %d:%d:%d\n",
device, vendor, thisbus, slot, func);
newDev = PCI_AddPCIDevice(bus, thisbus, slot, func,
vendor, device);
/*
* is it a PCI-PCI bridge (make this a naturally aligned
* read)?
*/
devClass = (OEM_ReadConfigDword(thisbus, slot, func,
PCI_REV_ID) & 0xFFFFFF00) >> 8;
if ((devClass >> 16) == PCI_BRIDGE_CLASS)
{
if (((devClass & 0xFF00) >> 8) == 4)
{
unsigned int buses, command;
VDPF( "PCI_ScanPCI found a Bridge.\n" );
/* initialise it */
newDev->flags.bridge = TRUE;
newDev->bridge.secondary =
++maxsub;
newDev->bridge.primary = bus->bridge.secondary;
/*
* temporary subordinate bus number until we
* know better
*/
newDev->bridge.subordinate = 0xFF;
/*
* Clear all status bits, turn of memory, IO and
* master enables
*/
command = OEM_ReadConfigDword(thisbus, slot, func,
PCI_COMMAND);
OEM_WriteConfigWord(thisbus, slot, func,
PCI_COMMAND, 0x0000);
OEM_WriteConfigWord(thisbus, slot, func,
PCI_STATUS, 0xffff);
/* configure the bus numbers for this bridge */
/*
* 20000329 KWelton
*
* assign to buses, don't modify an unintialised
* variable
*/
#ifdef OldCode
buses &= 0xFF000000;
buses |= ((newDev->bridge.primary << 0) |
(newDev->bridge.secondary << 8) |
(newDev->bridge.subordinate << 16));
#else
/*
* TRACE
*
* should we set the secondary latency timer?
*/
buses = (newDev->bridge.primary << 0) |
(newDev->bridge.secondary << 8) |
(newDev->bridge.subordinate << 16);
#endif /* def OldCode */
OEM_WriteConfigDword(thisbus, slot, func,
PCI_BUSES_AND_LATENCY, buses);
/*
* scan all subordinate buses with a recursive
* call to this routine
*/
maxsub = PCI_ScanPCI(newDev);
/*
* set subordinate bus number to its (now
* known) value
*/
newDev->bridge.subordinate = maxsub;
buses = (buses & 0xff00ffff) | (maxsub << 16);
OEM_WriteConfigDword(thisbus, slot, func,
PCI_BUSES_AND_LATENCY, buses);
}
}
}
}
}
/* all done */
return maxsub;
}
/*
* Routine: PCI_AssignResources
*
* Description: This routine will attempt to glean resource requirements
* from the device pointed to by handle
*
* Returns: Nothing
*/
static void PCI_AssignResources(PCIDevice_t *device)
{
unsigned int offset = PCI_MEM_BAR;
DWORD base, mask, size;
WORD barFlag = 0;
int i;
unsigned int bus, slot, func;
/* set up the bus, slot and func */
bus = device->bus;
slot = device->slot;
func = device->func;
/* Disable PCI IO and memory accesses */
OEM_WriteConfigWord(bus, slot, func, PCI_COMMAND, 0);
/* allocate an irq number */
PCI_AllocateInterrupt (device);
/* Scan each of the BARS for this device */
for (i = 0; i < PCI_MAX_BAR; i++)
{
/*
* write PCI_INVALID to BAR to get size, then read it back
*/
OEM_WriteConfigDword(bus, slot, func, offset, PCI_INVALID);
base = OEM_ReadConfigDword(bus, slot, func, offset);
/* check if this is an implemented BAR (size != 0) */
if (base != 0)
{
VDPF(" [%d] base: %x\n", i, base);
/*
* Assign some PCI memory (IO or Memory) space to this BAR
*/
if (base & PCI_IO_ENABLE)
{
/*
* I/O Space BAR
*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?