31 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/types.h>
36 #include <linux/slab.h>
38 #include <linux/pci.h>
43 #include <asm/uaccess.h>
57 static void __iomem *smbios_table;
58 static void __iomem *smbios_start;
59 static void __iomem *cpqhp_rom_start;
60 static bool power_mode;
64 #define DRIVER_VERSION "0.9.8"
66 #define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver"
78 #define CPQHPC_MODULE_MINOR 208
80 static inline int is_slot64bit(
struct slot *
slot)
85 static inline int is_slot66mhz(
struct slot *
slot)
104 endp = (end -
sizeof(
u32) + 1);
106 for (fp = begin; fp <= endp; fp += 16) {
123 dbg(
"Discovered SMBIOS Entry point at %p\n", fp);
147 while (number_of_slots) {
148 physical_slot = tempdword;
157 static int init_cpqhp_routing_table(
void)
162 if (cpqhp_routing_table ==
NULL)
165 len = cpqhp_routing_table_length();
167 kfree(cpqhp_routing_table);
168 cpqhp_routing_table =
NULL;
176 static void pci_print_IRQ_route(
void)
180 u8 tbus, tdevice, tslot;
182 len = cpqhp_routing_table_length();
184 dbg(
"bus dev func slot\n");
185 for (loop = 0; loop < len; ++loop) {
186 tbus = cpqhp_routing_table->
slots[loop].bus;
187 tdevice = cpqhp_routing_table->
slots[loop].devfn;
188 tslot = cpqhp_routing_table->
slots[loop].slot;
189 dbg(
"%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);
208 static void __iomem *get_subsequent_smbios_entry(
void __iomem *smbios_start,
213 u8 previous_byte = 1;
217 if (!smbios_table || !curr)
226 while ((p_temp < p_max) && !bail) {
231 if (!previous_byte && !(
readb(p_temp)))
234 previous_byte =
readb(p_temp);
268 previous = smbios_start;
270 previous = get_subsequent_smbios_entry(smbios_start,
271 smbios_table, previous);
275 previous = get_subsequent_smbios_entry(smbios_start,
276 smbios_table, previous);
283 static void release_slot(
struct hotplug_slot *hotplug_slot)
285 struct slot *slot = hotplug_slot->private;
287 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
294 static int ctrl_slot_cleanup (
struct controller * ctrl)
296 struct slot *old_slot, *next_slot;
298 old_slot = ctrl->
slot;
303 next_slot = old_slot->
next;
305 old_slot = next_slot;
340 u8 tbus, tdevice, tslot, bridgeSlot;
342 dbg(
"%s: %p, %d, %d, %p\n", __func__, bus, bus_num, dev_num, slot);
346 len = cpqhp_routing_table_length();
347 for (loop = 0; loop < len; ++loop) {
348 tbus = cpqhp_routing_table->
slots[loop].bus;
349 tdevice = cpqhp_routing_table->
slots[loop].devfn >> 3;
350 tslot = cpqhp_routing_table->
slots[loop].slot;
352 if ((tbus == bus_num) && (tdevice == dev_num)) {
366 pci_bus_read_config_dword(bus,
PCI_DEVFN(tdevice, 0),
370 pci_bus_read_config_dword(bus,
374 if (((work >> 8) & 0x000000FF) == (
long) bus_num)
386 if (bridgeSlot != 0xFF) {
416 amber_LED_on (ctrl, hp_slot);
417 else if (status == 0)
418 amber_LED_off (ctrl, hp_slot);
428 wait_for_ctrl_irq (ctrl);
442 static int set_attention_status (
struct hotplug_slot *hotplug_slot,
u8 status)
445 struct slot *slot = hotplug_slot->private;
452 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
458 function = devfn & 0x7;
459 dbg(
"bus, dev, fn = %d, %d, %d\n", bus, device,
function);
465 return cpqhp_set_attention_status(ctrl, slot_func, status);
469 static int process_SI(
struct hotplug_slot *hotplug_slot)
472 struct slot *slot = hotplug_slot->private;
479 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
485 function = devfn & 0x7;
486 dbg(
"bus, dev, fn = %d, %d, %d\n", bus, device,
function);
493 slot_func->
device = device;
496 dbg(
"board_added(%p, %p)\n", slot_func, ctrl);
501 static int process_SS(
struct hotplug_slot *hotplug_slot)
504 struct slot *slot = hotplug_slot->private;
511 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
517 function = devfn & 0x7;
518 dbg(
"bus, dev, fn = %d, %d, %d\n", bus, device,
function);
524 dbg(
"In %s, slot_func = %p, ctrl = %p\n", __func__, slot_func, ctrl);
529 static int hardware_test(
struct hotplug_slot *hotplug_slot,
u32 value)
531 struct slot *slot = hotplug_slot->private;
534 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
540 static int get_power_status(
struct hotplug_slot *hotplug_slot,
u8 *value)
542 struct slot *slot = hotplug_slot->private;
545 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
547 *value = get_slot_enabled(ctrl, slot);
551 static int get_attention_status(
struct hotplug_slot *hotplug_slot,
u8 *value)
553 struct slot *slot = hotplug_slot->private;
556 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
558 *value = cpq_get_attention_status(ctrl, slot);
562 static int get_latch_status(
struct hotplug_slot *hotplug_slot,
u8 *value)
564 struct slot *slot = hotplug_slot->private;
567 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
569 *value = cpq_get_latch_status(ctrl, slot);
574 static int get_adapter_status(
struct hotplug_slot *hotplug_slot,
u8 *value)
576 struct slot *slot = hotplug_slot->private;
579 dbg(
"%s - physical_slot = %s\n", __func__, slot_name(slot));
581 *value = get_presence_status(ctrl, slot);
588 .enable_slot = process_SI,
589 .disable_slot = process_SS,
597 #define SLOT_NAME_SIZE 10
599 static int ctrl_slot_setup(
struct controller *ctrl,
604 struct hotplug_slot *hotplug_slot;
616 dbg(
"%s\n", __func__);
624 while (number_of_slots) {
639 hotplug_slot->info = kzalloc(
sizeof(*(hotplug_slot->info)),
641 if (!hotplug_slot->info) {
645 hotplug_slot_info = hotplug_slot->info;
649 slot->
device = slot_device;
651 dbg(
"slot->number = %u\n", slot->
number);
653 slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
658 slot_entry = get_SMBIOS_entry(smbios_start,
659 smbios_table, 9, slot_entry);
674 if (is_slot64bit(slot))
676 if (is_slot66mhz(slot))
686 ((((~tempdword) >> 23) |
687 ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
690 ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
693 ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
696 hotplug_slot->release = &release_slot;
697 hotplug_slot->private =
slot;
699 hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
701 hotplug_slot_info->
power_status = get_slot_enabled(ctrl, slot);
703 cpq_get_attention_status(ctrl, slot);
705 cpq_get_latch_status(ctrl, slot);
707 get_presence_status(ctrl, slot);
709 dbg(
"registering bus %d, dev %d, number %d, "
710 "ctrl->slot_device_offset %d, slot %d\n",
719 err(
"pci_hp_register failed with error %d\n", result);
733 kfree(hotplug_slot_info);
742 static int one_time_init(
void)
752 retval = init_cpqhp_routing_table();
757 pci_print_IRQ_route();
759 dbg(
"Initialize + Start the notification mechanism \n");
765 dbg(
"Initialize slot lists\n");
766 for (loop = 0; loop < 256; loop++)
767 cpqhp_slot_list[loop] =
NULL;
775 if (!cpqhp_rom_start) {
776 err (
"Could not ioremap memory region for ROM\n");
787 smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
790 err (
"Could not find the SMBIOS pointer in memory\n");
792 goto error_rom_start;
798 err (
"Could not ioremap memory region taken from SMBIOS values\n");
800 goto error_smbios_start;
824 u16 subsystem_deviceid;
834 pci_name(pdev), err);
840 dev_notice(&pdev->
dev,
"the device is not a bridge, "
843 goto err_disable_device;
854 goto err_disable_device;
856 dbg(
"Vendor ID: %x\n", vendor_id);
862 goto err_disable_device;
879 dbg(
"Subsystem Vendor ID: %x\n", subsystem_vid);
883 goto err_disable_device;
888 err(
"%s : out of memory\n", __func__);
890 goto err_disable_device;
895 info(
"Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid);
902 switch (subsystem_vid) {
912 pci_read_config_byte(pdev, 0x41, &bus_cap);
913 if (bus_cap & 0x80) {
914 dbg(
"bus max supports 133MHz PCI-X\n");
918 if (bus_cap & 0x40) {
919 dbg(
"bus max supports 100MHz PCI-X\n");
924 dbg(
"bus max supports 66MHz PCI-X\n");
929 dbg(
"bus max supports 66MHz PCI\n");
937 switch (subsystem_deviceid) {
1000 if (subsystem_deviceid & 0x0001)
1006 if (subsystem_deviceid & 0x0002)
1012 if (subsystem_deviceid & 0x0004)
1018 if (subsystem_deviceid & 0x0008)
1026 if (subsystem_deviceid & 0x0010)
1032 if (subsystem_deviceid & 0x0020)
1038 if (subsystem_deviceid & 0x0080) {
1040 if (subsystem_deviceid & 0x0040)
1061 info(
"Initializing the PCI hot plug controller residing on PCI bus %d\n",
1064 dbg(
"Hotplug controller capabilities:\n");
1067 "switch present" :
"no switch");
1069 "PHP supported" :
"PHP not supported");
1071 "supported" :
"not supported");
1073 "supported" :
"not supported");
1075 "supported" :
"not supported");
1077 "supported" :
"not supported");
1080 pci_set_drvdata(pdev, ctrl);
1086 err(
"out of memory\n");
1091 ctrl->
bus = pdev->
bus->number;
1093 dbg(
"bus device function rev: %d %d %d %d\n", ctrl->
bus,
1100 rc = one_time_init();
1105 dbg(
"pdev = %p\n", pdev);
1111 err(
"cannot reserve MMIO region\n");
1119 err(
"cannot remap MMIO region %llx @ %llx\n",
1123 goto err_free_mem_region;
1144 rc = get_slot_mapping(ctrl->
pci_bus, pdev->
bus->number,
1147 dbg(
"get_slot_mapping: first_slot = %d, returned = %d\n",
1157 err(
"%s: unable to save PCI configuration data, error %d\n",
1169 dbg(
"System seems to be configured for Full Table Mapped MPS mode\n");
1178 dbg(
"cpqhp_find_available_resources = 0x%x\n", rc);
1179 err(
"unable to locate PCI configuration resources for hot plug add.\n");
1192 rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table);
1195 err(
"%s: unable to save PCI configuration data, error %d\n",
1207 err(
"Can't get irq %d for the hotplug pci controller\n",
1217 temp_word |= 0x4006;
1227 if (!cpqhp_ctrl_list) {
1228 cpqhp_ctrl_list =
ctrl;
1232 cpqhp_ctrl_list =
ctrl;
1245 while (num_of_slots) {
1246 dbg(
"num_of_slots: %d\n", num_of_slots);
1252 dbg(
"hp_slot: %d\n", hp_slot);
1266 green_LED_off(ctrl, hp_slot);
1267 slot_disable(ctrl, hp_slot);
1277 wait_for_ctrl_irq(ctrl);
1280 rc = init_SERR(ctrl);
1282 err(
"init_SERR failed\n");
1298 err_free_mem_region:
1309 static void __exit unload_cpqphpd(
void)
1327 rc = read_slot_enable (ctrl);
1337 ctrl_slot_cleanup(ctrl);
1374 for (loop = 0; loop < 256; loop++) {
1375 next = cpqhp_slot_list[loop];
1376 while (next !=
NULL) {
1416 if (cpqhp_rom_start)
1440 .name =
"compaq_pci_hotplug",
1441 .id_table = hpcd_pci_tbl,
1442 .probe = cpqhpc_probe,
1446 static int __init cpqhpc_init(
void)
1454 result = pci_register_driver(&cpqhpc_driver);
1455 dbg(
"pci_register_driver = %d\n", result);
1459 static void __exit cpqhpc_cleanup(
void)
1461 dbg(
"unload_cpqphpd()\n");
1464 dbg(
"pci_unregister_driver\n");