📄 cpqphp_pci.c
字号:
PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table(); len = (PCIIRQRoutingInfoLength->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); // Make sure I got at least one entry if (len == 0) { if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); return -1; } for (loop = 0; loop < len; ++loop) { tbus = PCIIRQRoutingInfoLength->slots[loop].bus; tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn; tslot = PCIIRQRoutingInfoLength->slots[loop].slot; if (tslot == slot) { *bus_num = tbus; *dev_num = tdevice; pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_VENDOR_ID, &work); if (!nobridge || (work == 0xffffffff)) { if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); return 0; } dbg("bus_num %d dev_num %d func_num %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7); pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_CLASS_REVISION, &work); dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS); if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { pci_read_config_byte_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_SECONDARY_BUS, &tbus); dbg("Scan bus for Non Bridge: bus %d\n", tbus); if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) { *bus_num = tbus; if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); return 0; } } else { if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); return 0; } } } if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); return -1;}int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot){ return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0); //plain (bridges allowed)}/* More PCI configuration routines; this time centered around hotplug controller *//* * cpqhp_save_config * * Reads configuration for all slots in a PCI bus and saves info. * * Note: For non-hot plug busses, the slot # saved is the device # * * returns 0 if success */int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug){ long rc; u8 class_code; u8 header_type; u32 ID; u8 secondary_bus; struct pci_func *new_slot; int sub_bus; int FirstSupported; int LastSupported; int max_functions; int function; u8 DevError; int device = 0; int cloop = 0; int stop_it; int index; // Decide which slots are supported if (is_hot_plug) { //********************************* // is_hot_plug is the slot mask //********************************* FirstSupported = is_hot_plug >> 4; LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1; } else { FirstSupported = 0; LastSupported = 0x1F; } // Save PCI configuration space for all devices in supported slots for (device = FirstSupported; device <= LastSupported; device++) { ID = 0xFFFFFFFF; rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { // device in slot rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, 0x0B, &class_code); if (rc) return rc; rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_HEADER_TYPE, &header_type); if (rc) return rc; // If multi-function device, set max_functions to 8 if (header_type & 0x80) max_functions = 8; else max_functions = 1; function = 0; do { DevError = 0; if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // P-P Bridge // Recurse the subordinate bus // get the subordinate bus number rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_SECONDARY_BUS, &secondary_bus); if (rc) { return rc; } else { sub_bus = (int) secondary_bus; // Save secondary bus cfg spc // with this recursive call. rc = cpqhp_save_config(ctrl, sub_bus, 0); if (rc) return rc; } } index = 0; new_slot = cpqhp_slot_find(busnumber, device, index++); while (new_slot && (new_slot->function != (u8) function)) new_slot = cpqhp_slot_find(busnumber, device, index++); if (!new_slot) { // Setup slot structure. new_slot = cpqhp_slot_create(busnumber); if (new_slot == NULL) return(1); } new_slot->bus = (u8) busnumber; new_slot->device = (u8) device; new_slot->function = (u8) function; new_slot->is_a_board = 1; new_slot->switch_save = 0x10; // In case of unsupported board new_slot->status = DevError; new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); for (cloop = 0; cloop < 0x20; cloop++) { rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); if (rc) return rc; } function++; stop_it = 0; // this loop skips to the next present function // reading in Class Code and Header type. while ((function < max_functions)&&(!stop_it)) { rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { // nothing there. function++; } else { // Something there rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, 0x0B, &class_code); if (rc) return rc; rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_HEADER_TYPE, &header_type); if (rc) return rc; stop_it++; } } } while (function < max_functions); } // End of IF (device in slot?) else if (is_hot_plug) { // Setup slot structure with entry for empty slot new_slot = cpqhp_slot_create(busnumber); if (new_slot == NULL) { return(1); } new_slot->bus = (u8) busnumber; new_slot->device = (u8) device; new_slot->function = 0; new_slot->is_a_board = 0; new_slot->presence_save = 0; new_slot->switch_save = 0; } } // End of FOR loop return(0);}/* * cpqhp_save_slot_config * * Saves configuration info for all PCI devices in a given slot * including subordinate busses. * * returns 0 if success */int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot){ long rc; u8 class_code; u8 header_type; u32 ID; u8 secondary_bus; int sub_bus; int max_functions; int function; int cloop = 0; int stop_it; ID = 0xFFFFFFFF; pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { // device in slot pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, 0x0B, &class_code); pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_HEADER_TYPE, &header_type); if (header_type & 0x80) // Multi-function device max_functions = 8; else max_functions = 1; function = 0; do { if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge // Recurse the subordinate bus pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_SECONDARY_BUS, &secondary_bus); sub_bus = (int) secondary_bus; // Save the config headers for the secondary bus. rc = cpqhp_save_config(ctrl, sub_bus, 0); if (rc) return(rc); } // End of IF new_slot->status = 0; for (cloop = 0; cloop < 0x20; cloop++) { pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); } function++; stop_it = 0; // this loop skips to the next present function // reading in the Class Code and the Header type. while ((function < max_functions) && (!stop_it)) { pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { // nothing there. function++; } else { // Something there pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, 0x0B, &class_code); pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_HEADER_TYPE, &header_type); stop_it++; } } } while (function < max_functions); } // End of IF (device in slot?) else { return(2); } return(0);}/* * cpqhp_save_base_addr_length * * Saves the length of all base address registers for the * specified slot. this is for hot plug REPLACE * * returns 0 if success */int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func){ u8 cloop; u8 header_type; u8 secondary_bus; u8 type; int sub_bus; u32 temp_register; u32 base; u32 rc; struct pci_func *next; int index = 0; func = cpqhp_slot_find(func->bus, func->device, index++); while (func != NULL) { // Check for Bridge pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus); sub_bus = (int) secondary_bus; next = cpqhp_slot_list[sub_bus]; while (next != NULL) { rc = cpqhp_save_base_addr_length(ctrl, next); if (rc) return(rc); next = next->next; } //FIXME: this loop is duplicated in the non-bridge case. The two could be rolled together // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x14; cloop += 4) { temp_register = 0xFFFFFFFF; pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); if (base) { // If this register is implemented if (base & 0x01L) { // IO base // set base = amount of IO space requested base = base & 0xFFFFFFFE; base = (~base) + 1; type = 1; } else { // memory base base = base & 0xFFFFFFF0; base = (~base) + 1; type = 0; } } else { base = 0x0L; type = 0; } // Save information in slot structure func->base_length[(cloop - 0x10) >> 2] = base; func->base_type[(cloop - 0x10) >> 2] = type; } // End of base register loop } else if ((header_type & 0x7F) == 0x00) { // PCI-PCI Bridge // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x24; cloop += 4) { temp_register = 0xFFFFFFFF; pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); if (base) { // If this register is implemented if (base & 0x01L) { // IO base // base = amount of IO space requested base = base & 0xFFFFFFFE; base = (~base) + 1; type = 1; } else { // memory base // base = amount of memory space requested base = base & 0xFFFFFFF0; base = (~base) + 1; type = 0; } } else { base = 0x0L; type = 0; } // Save information in slot structure func->base_length[(cloop - 0x10) >> 2] = base; func->base_type[(cloop - 0x10) >> 2] = type; } // End of base register loop } else { // Some other unknown header type } // find the next device in this slot func = cpqhp_slot_find(func->bus, func->device, index++); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -