📄 cpqphp_pci.c
字号:
unsigned int devfn; if (!func->is_a_board) return(ADD_NOT_SUPPORTED); func = cpqhp_slot_find(func->bus, func->device, index++); while (func != NULL) { pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register); // No adapter present if (temp_register == 0xFFFFFFFF) return(NO_ADAPTER_PRESENT); if (temp_register != func->config_space[0]) return(ADAPTER_NOT_SAME); // Check for same revision number and class code pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register); // Adapter not the same if (temp_register != func->config_space[0x08 >> 2]) return(ADAPTER_NOT_SAME); // Check for Bridge pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge // In order to continue checking, we must program the // bus registers in the bridge to respond to accesses // for it's subordinate bus(es) temp_register = func->config_space[0x18 >> 2]; pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register); secondary_bus = (temp_register >> 8) & 0xFF; next = cpqhp_slot_list[secondary_bus]; while (next != NULL) { rc = cpqhp_valid_replace(ctrl, next); if (rc) return rc; next = next->next; } } // Check to see if it is a standard config header else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { // Check subsystem vendor and ID pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register); if (temp_register != func->config_space[0x2C >> 2]) { // If it's a SMART-2 and the register isn't filled // in, ignore the difference because // they just have an old rev of the firmware if (!((func->config_space[0] == 0xAE100E11) && (temp_register == 0x00L))) return(ADAPTER_NOT_SAME); } // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x24; cloop += 4) { temp_register = 0xFFFFFFFF; pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); pci_bus_read_config_dword (pci_bus, devfn, 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; } // Check information in slot structure if (func->base_length[(cloop - 0x10) >> 2] != base) return(ADAPTER_NOT_SAME); if (func->base_type[(cloop - 0x10) >> 2] != type) return(ADAPTER_NOT_SAME); } // End of base register loop } // End of (type 0 config space) else else { // this is not a type 0 or 1 config space header so // we don't know how to do it return(DEVICE_TYPE_NOT_SUPPORTED); } // Get the next function func = cpqhp_slot_find(func->bus, func->device, index++); } return 0;}/* * cpqhp_find_available_resources * * Finds available memory, IO, and IRQ resources for programming * devices which may be added to the system * this function is for hot plug ADD! * * returns 0 if success */ int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start){ u8 temp; u8 populated_slot; u8 bridged_slot; void *one_slot; struct pci_func *func = NULL; int i = 10, index; u32 temp_dword, rc; struct pci_resource *mem_node; struct pci_resource *p_mem_node; struct pci_resource *io_node; struct pci_resource *bus_node; void *rom_resource_table; rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff); dbg("rom_resource_table = %p\n", rom_resource_table); if (rom_resource_table == NULL) { return -ENODEV; } // Sum all resources and setup resource maps unused_IRQ = readl(rom_resource_table + UNUSED_IRQ); dbg("unused_IRQ = %x\n", unused_IRQ); temp = 0; while (unused_IRQ) { if (unused_IRQ & 1) { cpqhp_disk_irq = temp; break; } unused_IRQ = unused_IRQ >> 1; temp++; } dbg("cpqhp_disk_irq= %d\n", cpqhp_disk_irq); unused_IRQ = unused_IRQ >> 1; temp++; while (unused_IRQ) { if (unused_IRQ & 1) { cpqhp_nic_irq = temp; break; } unused_IRQ = unused_IRQ >> 1; temp++; } dbg("cpqhp_nic_irq= %d\n", cpqhp_nic_irq); unused_IRQ = readl(rom_resource_table + PCIIRQ); temp = 0; if (!cpqhp_nic_irq) { cpqhp_nic_irq = ctrl->cfgspc_irq; } if (!cpqhp_disk_irq) { cpqhp_disk_irq = ctrl->cfgspc_irq; } dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq); rc = compaq_nvram_load(rom_start, ctrl); if (rc) return rc; one_slot = rom_resource_table + sizeof (struct hrt); i = readb(rom_resource_table + NUMBER_OF_ENTRIES); dbg("number_of_entries = %d\n", i); if (!readb(one_slot + SECONDARY_BUS)) return 1; dbg("dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n"); while (i && readb(one_slot + SECONDARY_BUS)) { u8 dev_func = readb(one_slot + DEV_FUNC); u8 primary_bus = readb(one_slot + PRIMARY_BUS); u8 secondary_bus = readb(one_slot + SECONDARY_BUS); u8 max_bus = readb(one_slot + MAX_BUS); u16 io_base = readw(one_slot + IO_BASE); u16 io_length = readw(one_slot + IO_LENGTH); u16 mem_base = readw(one_slot + MEM_BASE); u16 mem_length = readw(one_slot + MEM_LENGTH); u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE); u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH); dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n", dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length, primary_bus, secondary_bus, max_bus); // If this entry isn't for our controller's bus, ignore it if (primary_bus != ctrl->bus) { i--; one_slot += sizeof (struct slot_rt); continue; } // find out if this entry is for an occupied slot ctrl->pci_bus->number = primary_bus; pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword); dbg("temp_D_word = %x\n", temp_dword); if (temp_dword != 0xFFFFFFFF) { index = 0; func = cpqhp_slot_find(primary_bus, dev_func >> 3, 0); while (func && (func->function != (dev_func & 0x07))) { dbg("func = %p (bus, dev, fun) = (%d, %d, %d)\n", func, primary_bus, dev_func >> 3, index); func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++); } // If we can't find a match, skip this table entry if (!func) { i--; one_slot += sizeof (struct slot_rt); continue; } // this may not work and shouldn't be used if (secondary_bus != primary_bus) bridged_slot = 1; else bridged_slot = 0; populated_slot = 1; } else { populated_slot = 0; bridged_slot = 0; } // If we've got a valid IO base, use it temp_dword = io_base + io_length; if ((io_base) && (temp_dword < 0x10000)) { io_node = kmalloc(sizeof(*io_node), GFP_KERNEL); if (!io_node) return -ENOMEM; io_node->base = io_base; io_node->length = io_length; dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { io_node->next = ctrl->io_head; ctrl->io_head = io_node; } else { io_node->next = func->io_head; func->io_head = io_node; } } // If we've got a valid memory base, use it temp_dword = mem_base + mem_length; if ((mem_base) && (temp_dword < 0x10000)) { mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL); if (!mem_node) return -ENOMEM; mem_node->base = mem_base << 16; mem_node->length = mem_length << 16; dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { mem_node->next = ctrl->mem_head; ctrl->mem_head = mem_node; } else { mem_node->next = func->mem_head; func->mem_head = mem_node; } } // If we've got a valid prefetchable memory base, and // the base + length isn't greater than 0xFFFF temp_dword = pre_mem_base + pre_mem_length; if ((pre_mem_base) && (temp_dword < 0x10000)) { p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL); if (!p_mem_node) return -ENOMEM; p_mem_node->base = pre_mem_base << 16; p_mem_node->length = pre_mem_length << 16; dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { p_mem_node->next = ctrl->p_mem_head; ctrl->p_mem_head = p_mem_node; } else { p_mem_node->next = func->p_mem_head; func->p_mem_head = p_mem_node; } } // If we've got a valid bus number, use it // The second condition is to ignore bus numbers on // populated slots that don't have PCI-PCI bridges if (secondary_bus && (secondary_bus != primary_bus)) { bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL); if (!bus_node) return -ENOMEM; bus_node->base = secondary_bus; bus_node->length = max_bus - secondary_bus + 1; dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length); dbg("populated slot =%d \n", populated_slot); if (!populated_slot) { bus_node->next = ctrl->bus_head; ctrl->bus_head = bus_node; } else { bus_node->next = func->bus_head; func->bus_head = bus_node; } } i--; one_slot += sizeof (struct slot_rt); } // If all of the following fail, we don't have any resources for // hot plug add rc = 1; rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head)); rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head)); rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head)); rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); return rc;}/* * cpqhp_return_board_resources * * this routine returns all resources allocated to a board to * the available pool. * * returns 0 if success */int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists * resources){ int rc = 0; struct pci_resource *node; struct pci_resource *t_node; dbg("%s\n", __FUNCTION__); if (!func) return 1; node = func->io_head; func->io_head = NULL; while (node) { t_node = node->next; return_resource(&(resources->io_head), node); node = t_node; } node = func->mem_head; func->mem_head = NULL; while (node) { t_node = node->next; return_resource(&(resources->mem_head), node); node = t_node; } node = func->p_mem_head; func->p_mem_head = NULL; while (node) { t_node = node->next; return_resource(&(resources->p_mem_head), node); node = t_node; } node = func->bus_head; func->bus_head = NULL; while (node) { t_node = node->next; return_resource(&(resources->bus_head), node); node = t_node; } rc |= cpqhp_resource_sort_and_combine(&(resources->mem_head)); rc |= cpqhp_resource_sort_and_combine(&(resources->p_mem_head)); rc |= cpqhp_resource_sort_and_combine(&(resources->io_head)); rc |= cpqhp_resource_sort_and_combine(&(resources->bus_head)); return rc;}/* * cpqhp_destroy_resource_list * * Puts node back in the resource list pointed to by head */void cpqhp_destroy_resource_list (struct resource_lists * resources){ struct pci_resource *res, *tres; res = resources->io_head; resources->io_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); } res = resources->mem_head; resources->mem_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); } res = resources->p_mem_head; resources->p_mem_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); } res = resources->bus_head; resources->bus_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); }}/* * cpqhp_destroy_board_resources * * Puts node back in the resource list pointed to by head */void cpqhp_destroy_board_resources (struct pci_func * func){ struct pci_resource *res, *tres; res = func->io_head; func->io_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); } res = func->mem_head; func->mem_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); } res = func->p_mem_head; func->p_mem_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); } res = func->bus_head; func->bus_head = NULL; while (res) { tres = res; res = res->next; kfree(tres); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -