📄 pci_serv.c
字号:
if (pci_config_error) /* check to see if the NMI handler during the config cycle */
status = 1;
pci_config_cycle = 0; /* turn on exception handling after pci config cycle */
if (old_abort_vec)
{
((volatile unsigned *)0x20)[4] = old_abort_vec;
old_abort_vec = 0;
_flushICache();
}
if (status) return (ERROR);
else return (OK);
}
extern void __ignore_abort(void);
/**************************************************************************
* sys_config_setup - this function sets up a PCI configuration cycle
*
* This function sets up either the primary or secondary outbound configuration
* cycle address register. It is called by all the sys_*_config_* functions.
*
*/
static int sys_config_setup(ULONG busno, ULONG devno, ULONG funcno, ULONG regno, UINT32 **pci_occ_addr,
UINT32 **pci_occ_data)
{
/* First check the parameters for sanity */
if ((busno > 255) || (devno > 31) || (funcno> 7) || (regno > 63)) return (ERROR);
if (busno == primary_busno)
{
*pci_occ_addr = (UINT32 *) POCCAR_ADDR;
*pci_occ_data = (UINT32 *) POCCDR_ADDR;
}
else if (busno == secondary_busno)
{
*pci_occ_addr = (UINT32 *) SOCCAR_ADDR;
*pci_occ_data = (UINT32 *) SOCCDR_ADDR;
}
else if (busno <= bus0_lastbus)
{
*pci_occ_addr = (UINT32 *) POCCAR_ADDR;
*pci_occ_data = (UINT32 *) POCCDR_ADDR;
}
else if (busno <= bus1_lastbus)
{
*pci_occ_addr = (UINT32 *) SOCCAR_ADDR;
*pci_occ_data = (UINT32 *) SOCCDR_ADDR;
}
else return (ERROR);
(void)pci_cycle_cleanup(busno); /* start with clean slate */
pci_config_cycle = 1; /* turn off exception handling during pci config cycle */
if (old_abort_vec) {
printf("recursive config setup\n");
while (1);
}
old_abort_vec = ((volatile unsigned *)0x20)[4];
((volatile unsigned *)0x20)[4] = (unsigned)__ignore_abort;
_flushICache();
pci_config_error = FALSE;
/* turn off error messages which could be generated by non-existant devices */
PRINT_OFF();
if ((busno == PRIMARY_BUS_NUM) || (busno == SECONDARY_BUS_NUM))
{
/* set up the config access register for type 0 config cycles */
**pci_occ_addr =
(
(1 << ((devno & 0x1f) + 16)) |
((funcno & 0x07) << 8) |
((regno & 0x3f) << 2) |
(0) );
}
else
{
/* set up the config access register for type 1 config cycles */
**pci_occ_addr =
(
((busno & 0xff) << 16) |
((devno & 0x1f) << 11) |
((funcno& 0x07) << 8) |
((regno & 0x3f) << 2) |
(1) );
}
return (OK);
}
/**************************************************************************
* sys_read_config_byte - this function performs a PCI configuration cycle
* and returns a byte.
*
* This function will read a byte from config space on the PCI bus. It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_read_config_byte (UINT32 busno, UINT32 devno, UINT32 funcno, UINT32 offset, UINT8 *data)
{
UINT32 *pci_occ_data;
UINT32 regno;
UINT32 *pci_occ_addr;
/* initialize here to keep compiler happy */
pci_occ_addr = (UINT32 *) POCCAR_ADDR;
pci_occ_data = (UINT32 *) POCCDR_ADDR;
/* Register numbers are DWORD indexes */
regno = offset / 0x4;
/* Set up the cycle. */
if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
return (ERROR);
/* Now do the read */
*data = (UINT8)(((*pci_occ_data) >> ((offset % 0x4) * 8)) & 0xff);
if (pci_cycle_cleanup (busno) == OK)
{
PRINT_ON();
return (OK);
}
else
{
PRINT_ON();
return (ERROR);
}
}
/**************************************************************************
* sys_read_config_word - this function performs a PCI configuration cycle
* and returns a 16-bit word.
*
* This function will read a word from config space on the PCI bus. It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_read_config_word (UINT32 busno, UINT32 devno, UINT32 funcno, UINT32 offset, UINT16 *data)
{
UINT32 *pci_occ_data;
UINT32 regno;
UINT32 *pci_occ_addr;
/* initialize here to keep compiler happy */
pci_occ_addr = (UINT32 *) POCCAR_ADDR;
pci_occ_data = (UINT32 *) POCCDR_ADDR;
/* Offsets must be word-aligned */
if (offset % 0x2) return (ERROR);
/* Register numbers are DWORD indexes */
regno = offset / 0x4;
/* Set up the cycle. */
if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) return (ERROR);
/* Now do the read */
*data = (UINT16)(((*pci_occ_data) >> ((offset % 0x4) * 8)) & 0xffff);
if (pci_cycle_cleanup(busno) == OK)
{
PRINT_ON();
return (OK);
}
else
{
PRINT_ON();
return (ERROR);
}
}
/**************************************************************************
* sys_read_config_dword - this function performs a PCI configuration cycle
* and returns a 32-bit word.
*
* This function will read a dword from config space on the PCI bus. It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_read_config_dword (
UINT32 busno,
UINT32 devno,
UINT32 funcno,
UINT32 offset,
UINT32 *data
)
{
UINT32 *pci_occ_data;
UINT32 regno;
UINT32 *pci_occ_addr;
/* initialize here to keep compiler happy */
pci_occ_addr = (UINT32 *) POCCAR_ADDR;
pci_occ_data = (UINT32 *) POCCDR_ADDR;
/* Offsets must be dword-aligned */
if (offset % 0x4) return (ERROR);
/* Register numbers are DWORD indexes */
regno = offset / 0x4;
/* Set up the cycle. */
if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
return (ERROR);
/* Now do the read */
*data = *pci_occ_data;
if (pci_cycle_cleanup (busno) == OK)
{
PRINT_ON();
return (OK);
}
else
{
PRINT_ON();
return (ERROR);
}
}
/**************************************************************************
* sys_write_config_byte - this function performs a PCI configuration cycle
* and writes a byte.
*
* This function will write a byte to config space on the PCI bus. It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_write_config_byte (
UINT32 busno,
UINT32 devno,
UINT32 funcno,
UINT32 offset,
UINT8 *data
)
{
UINT32 *pci_occ_data;
UINT32 regno, temp;
UINT32 *pci_occ_addr;
UINT32 data_mask;
/* initialize here to keep compiler happy */
pci_occ_addr = (UINT32 *) POCCAR_ADDR;
pci_occ_data = (UINT32 *) POCCDR_ADDR;
/* Register numbers are DWORD indexes */
regno = offset / 0x4;
/* build mask for byte of interest */
data_mask = ~(0x000000ff << ((offset % 0x4) * 8));
/* Set up the cycle. */
if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
return (ERROR);
/* set up 32-bit word, clear old data, OR in new data */
temp = (UINT32)(((UINT32) *data) << ((offset % 0x4) * 8));
*pci_occ_data &= data_mask;
*pci_occ_data |= temp;
if (pci_cycle_cleanup (busno) == OK)
{
PRINT_ON();
return (OK);
}
else
{
PRINT_ON();
return (ERROR);
}
}
/**************************************************************************
* sys_write_config_word - this function performs a PCI configuration cycle
* and writes a 16-bit word.
*
* This function will write a word to config space on the PCI bus. It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_write_config_word (
UINT32 busno,
UINT32 devno,
UINT32 funcno,
UINT32 offset,
UINT16 *data
)
{
UINT32 *pci_occ_data;
UINT32 regno, temp;
UINT32 *pci_occ_addr;
UINT32 data_mask;
/* initialize here to keep compiler happy */
pci_occ_addr = (UINT32 *) POCCAR_ADDR;
pci_occ_data = (UINT32 *) POCCDR_ADDR;
/* Offsets must be word-aligned */
if (offset % 0x2) return (ERROR);
/* Register numbers are DWORD indexes */
regno = offset / 0x4;
/* build mask for word of interest */
data_mask= ~(0x0000ffff << ((offset % 0x4) * 8));
/* Set up the cycle. */
if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
return (ERROR);
/* set up 32-bit word */
temp = (UINT32)(((UINT32) *data) << ((offset % 0x4) * 8));
*pci_occ_data &= data_mask;
*pci_occ_data |= temp;
if (pci_cycle_cleanup (busno) == OK)
{
PRINT_ON();
return (OK);
}
else
{
PRINT_ON();
return (ERROR);
}
}
/**************************************************************************
* sys_write_config_dword - this function performs a PCI configuration cycle
* and writes a 32-bit word.
*
* This function will write a dword to config space on the PCI bus. It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_write_config_dword (
UINT32 busno,
UINT32 devno,
UINT32 funcno,
UINT32 offset,
UINT32 *data
)
{
UINT32 *pci_occ_data;
UINT32 regno;
UINT32 *pci_occ_addr;
/* initialize here to keep compiler happy */
pci_occ_addr = (UINT32 *) POCCAR_ADDR;
pci_occ_data = (UINT32 *) POCCDR_ADDR;
/* Offsets must be dword-aligned */
if (offset % 0x4) return (ERROR);
/* Register numbers are DWORD indexes */
regno = offset / 0x4;
/* Set up the cycle. */
if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
return (ERROR);
/* Now do the write */
*pci_occ_data = *data;
if (pci_cycle_cleanup (busno) == OK)
{
PRINT_ON();
return (OK);
}
else
{
PRINT_ON();
return (ERROR);
}
}
/******************************************************************************
* sys_find_pci_device - find a PCI device based on Vendor ID and Device ID
*
* This function returns the location of PCI devices that have a specific
* Device ID and Vendor ID. Given a Vendor ID, Device ID, and an Index, the
* function returns the Bus Number, Device Number, and Function Number of the
* Nth Device/Function whose Vendor ID and Device ID match the input parameters.
*
* Calling software can find all devices having the same Vendor ID and Device ID
* by making successive calls to this function starting with the index set to 0,
* and incrementing the index until the function returns DEVICE_NOT_FOUND. A
* return value of BAD_VENDOR_ID indicates that the Vendor ID value passed had
* a value of all 1's.
*
*/
STATUS sys_find_pci_device (int vendor_id, int device_id, int index, PCI_DEVICE_LOCATION *devloc)
{
int found;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -