📄 cpqphp_core.c
字号:
PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table(); if (!PCIIRQRoutingInfoLength) return -1; len = (PCIIRQRoutingInfoLength->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); // Make sure I got at least one entry if (len == 0) { kfree(PCIIRQRoutingInfoLength); return -1; } for (loop = 0; loop < len; ++loop) { tbus = PCIIRQRoutingInfoLength->slots[loop].bus; tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3; tslot = PCIIRQRoutingInfoLength->slots[loop].slot; if ((tbus == bus_num) && (tdevice == dev_num)) { *slot = tslot; kfree(PCIIRQRoutingInfoLength); return 0; } else { /* Did not get a match on the target PCI device. Check * if the current IRQ table entry is a PCI-to-PCI bridge * device. If so, and it's secondary bus matches the * bus number for the target device, I need to save the * bridge's slot number. If I can not find an entry for * the target device, I will have to assume it's on the * other side of the bridge, and assign it the bridge's * slot. */ bus->number = tbus; pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), PCI_REVISION_ID, &work); if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), PCI_PRIMARY_BUS, &work); // See if bridge's secondary bus matches target bus. if (((work >> 8) & 0x000000FF) == (long) bus_num) { bridgeSlot = tslot; } } } } // If we got here, we didn't find an entry in the IRQ mapping table // for the target PCI device. If we did determine that the target // device is on the other side of a PCI-to-PCI bridge, return the // slot number for the bridge. if (bridgeSlot != 0xFF) { *slot = bridgeSlot; kfree(PCIIRQRoutingInfoLength); return 0; } kfree(PCIIRQRoutingInfoLength); // Couldn't find an entry in the routing table for this PCI device return -1;}/** * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off * */static intcpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, u32 status){ u8 hp_slot; hp_slot = func->device - ctrl->slot_device_offset; if (func == NULL) return(1); // Wait for exclusive access to hardware down(&ctrl->crit_sect); if (status == 1) { amber_LED_on (ctrl, hp_slot); } else if (status == 0) { amber_LED_off (ctrl, hp_slot); } else { // Done with exclusive hardware access up(&ctrl->crit_sect); return(1); } set_SOGO(ctrl); // Wait for SOBS to be unset wait_for_ctrl_irq (ctrl); // Done with exclusive hardware access up(&ctrl->crit_sect); return(0);}/** * set_attention_status - Turns the Amber LED for a slot on or off * */static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status){ struct pci_func *slot_func; struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; u8 bus; u8 devfn; u8 device; u8 function; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; device = devfn >> 3; function = devfn & 0x7; dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); slot_func = cpqhp_slot_find(bus, device, function); if (!slot_func) return -ENODEV; return cpqhp_set_attention_status(ctrl, slot_func, status);}static int process_SI(struct hotplug_slot *hotplug_slot){ struct pci_func *slot_func; struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; u8 bus; u8 devfn; u8 device; u8 function; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; device = devfn >> 3; function = devfn & 0x7; dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); slot_func = cpqhp_slot_find(bus, device, function); if (!slot_func) return -ENODEV; slot_func->bus = bus; slot_func->device = device; slot_func->function = function; slot_func->configured = 0; dbg("board_added(%p, %p)\n", slot_func, ctrl); return cpqhp_process_SI(ctrl, slot_func);}static int process_SS(struct hotplug_slot *hotplug_slot){ struct pci_func *slot_func; struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; u8 bus; u8 devfn; u8 device; u8 function; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; device = devfn >> 3; function = devfn & 0x7; dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); slot_func = cpqhp_slot_find(bus, device, function); if (!slot_func) return -ENODEV; dbg("In %s, slot_func = %p, ctrl = %p\n", __FUNCTION__, slot_func, ctrl); return cpqhp_process_SS(ctrl, slot_func);}static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value){ struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); return cpqhp_hardware_test(ctrl, value); }static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = get_slot_enabled(ctrl, slot); return 0;}static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = cpq_get_attention_status(ctrl, slot); return 0;}static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = cpq_get_latch_status(ctrl, slot); return 0;}static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = get_presence_status(ctrl, slot); return 0;}static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value){ struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = ctrl->speed_capability; return 0;}static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value){ struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = ctrl->speed; return 0;}static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ u8 num_of_slots = 0; u8 hp_slot = 0; u8 device; u8 rev; u8 bus_cap; u16 temp_word; u16 vendor_id; u16 subsystem_vid; u16 subsystem_deviceid; u32 rc; struct controller *ctrl; struct pci_func *func; // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) { err(msg_HPC_non_compaq_or_intel); return -ENODEV; } dbg("Vendor ID: %x\n", vendor_id); rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); dbg("revision: %d\n", rev); if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) { err(msg_HPC_rev_error); return -ENODEV; } /* Check for the proper subsytem ID's * Intel uses a different SSID programming model than Compaq. * For Intel, each SSID bit identifies a PHP capability. * Also Intel HPC's may have RID=0. */ if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) { // TODO: This code can be made to support non-Compaq or Intel subsystem IDs rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); if (rc) { err("%s : pci_read_config_word failed\n", __FUNCTION__); return rc; } dbg("Subsystem Vendor ID: %x\n", subsystem_vid); if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { err(msg_HPC_non_compaq_or_intel); return -ENODEV; } ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); return -ENOMEM; } memset(ctrl, 0, sizeof(struct controller)); rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); if (rc) { err("%s : pci_read_config_word failed\n", __FUNCTION__); goto err_free_ctrl; } info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid); /* Set Vendor ID, so it can be accessed later from other functions */ ctrl->vendor_id = vendor_id; switch (subsystem_vid) { case PCI_VENDOR_ID_COMPAQ: if (rev >= 0x13) { /* CIOBX */ ctrl->push_flag = 1; ctrl->slot_switch_type = 1; ctrl->push_button = 1; ctrl->pci_config_space = 1; ctrl->defeature_PHP = 1; ctrl->pcix_support = 1; ctrl->pcix_speed_capability = 1; pci_read_config_byte(pdev, 0x41, &bus_cap); if (bus_cap & 0x80) { dbg("bus max supports 133MHz PCI-X\n"); ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; break; } if (bus_cap & 0x40) { dbg("bus max supports 100MHz PCI-X\n"); ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; break; } if (bus_cap & 20) { dbg("bus max supports 66MHz PCI-X\n"); ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; break; } if (bus_cap & 10) { dbg("bus max supports 66MHz PCI\n"); ctrl->speed_capability = PCI_SPEED_66MHz; break; } break; } switch (subsystem_deviceid) { case PCI_SUB_HPC_ID: /* Original 6500/7000 implementation */ ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_33MHz; ctrl->push_button = 0; ctrl->pci_config_space = 1; ctrl->defeature_PHP = 1; ctrl->pcix_support = 0; ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID2: /* First Pushbutton implementation */ ctrl->push_flag = 1; ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_33MHz; ctrl->push_button = 1; ctrl->pci_config_space = 1; ctrl->defeature_PHP = 1; ctrl->pcix_support = 0; ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID_INTC: /* Third party (6500/7000) */ ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_33MHz; ctrl->push_button = 0; ctrl->pci_config_space = 1; ctrl->defeature_PHP = 1; ctrl->pcix_support = 0; ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID3: /* First 66 Mhz implementation */ ctrl->push_flag = 1; ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_66MHz; ctrl->push_button = 1; ctrl->pci_config_space = 1; ctrl->defeature_PHP = 1; ctrl->pcix_support = 0; ctrl->pcix_speed_capability = 0; break; case PCI_SUB_HPC_ID4: /* First PCI-X implementation, 100MHz */ ctrl->push_flag = 1; ctrl->slot_switch_type = 1; ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; ctrl->push_button = 1; ctrl->pci_config_space = 1; ctrl->defeature_PHP = 1; ctrl->pcix_support = 1; ctrl->pcix_speed_capability = 0; break; default: err(msg_HPC_not_supported); rc = -ENODEV; goto err_free_ctrl; } break; case PCI_VENDOR_ID_INTEL: /* Check for speed capability (0=33, 1=66) */ if (subsystem_deviceid & 0x0001) { ctrl->speed_capability = PCI_SPEED_66MHz; } else { ctrl->speed_capability = PCI_SPEED_33MHz; } /* Check for push button */ if (subsystem_deviceid & 0x0002) { /* no push button */ ctrl->push_button = 0; } else { /* push button supported */ ctrl->push_button = 1; } /* Check for slot switch type (0=mechanical, 1=not mechanical) */ if (subsystem_deviceid & 0x0004) { /* no switch */ ctrl->slot_switch_type = 0; } else { /* switch */ ctrl->slot_switch_type = 1; } /* PHP Status (0=De-feature PHP, 1=Normal operation) */ if (subsystem_deviceid & 0x0008) { ctrl->defeature_PHP = 1; // PHP supported } else { ctrl->defeature_PHP = 0; // PHP not supported } /* Alternate Base Address Register Interface (0=not supported, 1=supported) */ if (subsystem_deviceid & 0x0010) { ctrl->alternate_base_address = 1; // supported } else { ctrl->alternate_base_address = 0; // not supported } /* PCI Config Space Index (0=not supported, 1=supported) */ if (subsystem_deviceid & 0x0020) { ctrl->pci_config_space = 1; // supported } else { ctrl->pci_config_space = 0; // not supported } /* PCI-X support */ if (subsystem_deviceid & 0x0080) { /* PCI-X capable */ ctrl->pcix_support = 1; /* Frequency of operation in PCI-X mode */ if (subsystem_deviceid & 0x0040) { /* 133MHz PCI-X if bit 7 is 1 */ ctrl->pcix_speed_capability = 1; } else { /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */ /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */ ctrl->pcix_speed_capability = 0; } } else { /* Conventional PCI */ ctrl->pcix_support = 0; ctrl->pcix_speed_capability = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -