📄 pci_serv.c
字号:
} 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; int multifunction = FALSE; USHORT vendid, devid; ULONG bus, device, function; UCHAR header_type; if (vendor_id == 0xffff) return (BAD_VENDOR_ID); found = 0; for (bus = 0; bus <= lastbus; bus++) { for (device = 0; device < MAX_DEVICE_NUMBER; device++) { for (function = 0; function < MAX_FUNCTION_NUMBER; function++) { /* before we go beyond function 0, make sure that the device is truly a multi-function device, otherwise we may get aliasing */ if (function == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -