pci.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 612 行 · 第 1/2 页
C
612 行
* C D
* D A
*
* 6 A C
* B D
* C A
* D B
*
* 7 A D
* B A
* C B
* D C
*
* Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
* Thus, each swizzle is ((pin-1) + (device#-4)) % 4
*
*/
static unsigned char bridgeSwizzle(unsigned char pin, unsigned int slot)
{
return (((pin - 1) + slot) % 4) + 1;
}
#endif
#if 0
/*============================================================================
*
* routine: PCIir_AllocateInterrupt
*
* description: Allocate an interrupt #
*
* returns: void
*
*/
static void PCIir_AllocateInterrupt (PCIDevice_t * device)
{
PCIDevice_t *curr;
unsigned char pin;
unsigned char interrupt;
// read the interrupt pin from the device
pin = uHALr_PCICfgRead8(device->bus, device->slot, device->func,
PCI_INTERRUPT_PIN);
// figure out the interrupt number
if (device->bus == 0)
{
/*
* Primary bus
* pin is this device's pin
* curr is this device
*/
curr = device;
}
else
{
/* Secondary bus or beyond */
curr = device;
while (curr->bus != 0)
{
/* swizzle the interrupt pins through each PCI-PCI bridge */
pin = bridgeSwizzle(pin, curr->slot);
curr = curr->parent;
}
/*
* pin is now the pin of the last bridge
* curr is the last PCI-PCI bridge
*/
}
// 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)
uHALr_PCICfgWrite8 (device->bus, device->slot, device->func,
PCI_INTERRUPT_LINE, interrupt);
}
#endif
/**********************************************************************/
/*
* These functions are used to generate PCI configuration bus cycles. They
* all return 0 on success and non-zero on error. An error should be
* returned on a master abort for example, so that the presense/absense of
* a device can be established. Note that all configuration accesses are
* DWORD wide on the bus itself, so that the simulated BYTE and WORD
* accesses provided by these functions must be read/modify/writes of DWORDs.
*
*
* The parameters are:
*
* bBusNo - Target bus number for the configuration cycle. Type 0 or
* Type 1 bus cycles will be automatically based on the target
* specified. Since bus 0 is assumed to be directly connected to
* the host bridge, bus 0 references will generate Type 0 cycles
* and any other number will generate a Type 1 cycle.
*
* bDevNo - Device number on the target bus. The PCI specification allows
* device numbers from 0 through 20. Device 0 corresponds to
* setting bit 11 and clearing bits 12-31 in a Type 0 bus cycle.
* Device 19 corresponds to setting bit 30 and clearing bits
* 11-29 and 31,
*
* bFuncNo - The function being selected on the target device. This can
* be in the range of 0 to 7.
*
* bOffset - The offset into the specified configuration space. Note that
* the offset will only be aligned to the size of the data item
* being requested. For example, a byte read of bOffset = 7
* would return the high order byte of the second DWORD.
*
* xData - Pointer to the variable where the result should be stored.
*/
BYTE OEM_ReadConfigByte(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
DWORD dwOffset)
{
BYTE result;
volatile BYTE *pAddress;
/* open the (closed) configuration window from local bus memory */
_V3OpenConfigWindow();
/* generate the address of correct configuration space */
pAddress = (volatile BYTE *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
dwFuncNo, dwOffset));
/* now that we have valid params, go read the config space data */
result = *pAddress;
/* close the window */
_V3CloseConfigWindow();
return result;
}
void OEM_WriteConfigByte(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
DWORD dwOffset, BYTE bData)
{
volatile BYTE *pAddress;
/* open the (closed) configuration window from local bus memory */
_V3OpenConfigWindow();
/* generate the address of correct configuration space */
pAddress = (volatile BYTE *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
dwFuncNo, dwOffset));
/* now that we have valid params, go write the config space data */
*pAddress = bData;
/* close the window */
_V3CloseConfigWindow();
}
WORD OEM_ReadConfigWord(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
DWORD dwOffset)
{
WORD result;
volatile WORD *pAddress;
/* open the (closed) configuration window from local bus memory */
_V3OpenConfigWindow();
/* generate the address of correct configuration space */
pAddress = (volatile WORD *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
dwFuncNo, dwOffset));
/* now that we have valid params, go read the config space data */
result = *pAddress;
/* close the window */
_V3CloseConfigWindow();
return result;
}
void OEM_WriteConfigWord(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
DWORD dwOffset, WORD wData)
{
volatile WORD *pAddress;
/* open the (closed) configuration window from local bus memory */
_V3OpenConfigWindow();
/* generate the address of correct configuration space */
pAddress = (volatile WORD *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
dwFuncNo, dwOffset));
/* now that we have valid params, go write the config space data */
*pAddress = wData;
/* close the window */
_V3CloseConfigWindow();
}
DWORD OEM_ReadConfigDword(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
DWORD dwOffset)
{
DWORD result;
volatile DWORD *pAddress;
/* Open the (closed) configuration window from local bus memory */
_V3OpenConfigWindow();
/* generate the address of correct configuration space */
pAddress = (volatile DWORD *)PCIMakeConfigAddress(dwBusNo, dwDevNo,
dwFuncNo, dwOffset);
/* now that we have valid params, go read the config space data */
result = *pAddress;
/* close the window */
_V3CloseConfigWindow();
return result;
}
void OEM_WriteConfigDword(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
DWORD dwOffset, DWORD dwData)
{
volatile DWORD *pAddress;
/* open the (closed) configuration window from local bus memory */
_V3OpenConfigWindow();
/* generate the address of correct configuration space */
pAddress = (DWORD *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
dwFuncNo, dwOffset));
/* now that we have valid params, go write the config space data */
*pAddress = dwData;
if (*pAddress != dwData) { // V3 sync. bug, tmp Jes
*pAddress = dwData;
}
/* close the window */
_V3CloseConfigWindow();
}
/**********************************************************************/
/*
* This function will encode a Type 0 or Type 1 configuration address based on
* the parameters passed in.
*/
void OEM_EncodeConfigAddress(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
DWORD dwOffset, DWORD *pdwAddress )
{
*pdwAddress = (DWORD)PCIMakeConfigAddress(dwBusNo, dwDevNo,
dwFuncNo,dwOffset);
}
ULONG PCI_Type1_Configuration(ULONG BusNumber, ULONG SlotNumber, PVOID Buffer,\
ULONG Offset, ULONG Length, BOOL fSet)
{
PULONG pBuffer;
int registerOffset, endOffset;
ULONG DeviceNumber, FunctionNumber;
if (BusNumber >= PCI_MAX_BUS)
return (0);
DeviceNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.DeviceNumber;
FunctionNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.FunctionNumber;
if (DeviceNumber >= PCI_MAX_DEVICES)
return (0);
registerOffset = Offset / sizeof(ULONG);
endOffset = registerOffset + (Length + sizeof(ULONG) - 1) / sizeof(ULONG);
pBuffer = Buffer;
for ( ; registerOffset < endOffset; ++registerOffset)
{
if (fSet)
OEM_WriteConfigDword(BusNumber, DeviceNumber, FunctionNumber,
registerOffset * 4, *pBuffer++);
else
*(pBuffer++) = OEM_ReadConfigDword(BusNumber, DeviceNumber,
FunctionNumber,
registerOffset * 4);
}
return (Length);
}
ULONG PCIGetBusDataByOffset(IN ULONG BusNumber, IN ULONG SlotNumber,
IN PVOID Buffer, IN ULONG Offset,
IN ULONG Length)
{
return (PCI_Type1_Configuration(BusNumber, SlotNumber,
Buffer, Offset, Length, FALSE));
}
ULONG PCISetBusDataByOffset(IN ULONG BusNumber, IN ULONG SlotNumber,
IN PVOID Buffer, IN ULONG Offset,
IN ULONG Length)
{
return (PCI_Type1_Configuration(BusNumber, SlotNumber,
Buffer, Offset, Length, TRUE));
}
/* EOF pci.c */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?