📄 ibmphp_core.c
字号:
debug ("setting bus speed for slot %d, cmd %x\n", slot_cur->number, cmd); retval = ibmphp_hpc_writeslot (slot_cur, cmd); if (retval) { err ("setting bus speed failed\n"); return retval; } if (CTLR_RESULT (slot_cur->ctrl->status)) { err ("command not completed successfully in set_bus\n"); return -EIO; } } /* This is for x440, once Brandon fixes the firmware, will not need this delay */ long_delay (1 * HZ); debug ("%s -Exit\n", __FUNCTION__); return 0;}/* This routine checks the bus limitations that the slot is on from the BIOS. * This is used in deciding whether or not to power up the slot. * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on * same bus) * Parameters: slot * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus */static int check_limitations (struct slot *slot_cur){ u8 i; struct slot * tmp_slot; u8 count = 0; u8 limitation = 0; for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) { tmp_slot = ibmphp_get_slot_from_physical_num (i); if (!tmp_slot) return -ENODEV; if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) count++; } get_cur_bus_info (&slot_cur); switch (slot_cur->bus_on->current_speed) { case BUS_SPEED_33: limitation = slot_cur->bus_on->slots_at_33_conv; break; case BUS_SPEED_66: if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX) limitation = slot_cur->bus_on->slots_at_66_pcix; else limitation = slot_cur->bus_on->slots_at_66_conv; break; case BUS_SPEED_100: limitation = slot_cur->bus_on->slots_at_100_pcix; break; case BUS_SPEED_133: limitation = slot_cur->bus_on->slots_at_133_pcix; break; } if ((count + 1) > limitation) return -EINVAL; return 0;}static inline void print_card_capability (struct slot *slot_cur){ info ("capability of the card is "); if ((slot_cur->ext_status & CARD_INFO) == PCIX133) info (" 133 MHz PCI-X\n"); else if ((slot_cur->ext_status & CARD_INFO) == PCIX66) info (" 66 MHz PCI-X\n"); else if ((slot_cur->ext_status & CARD_INFO) == PCI66) info (" 66 MHz PCI\n"); else info (" 33 MHz PCI\n");}/* This routine will power on the slot, configure the device(s) and find the * drivers for them. * Parameters: hotplug_slot * Returns: 0 or failure codes */static int enable_slot (struct hotplug_slot *hs){ int rc, i, rcpr; struct slot *slot_cur; u8 function; struct pci_func *tmp_func; ibmphp_lock_operations (); debug ("ENABLING SLOT........\n"); slot_cur = (struct slot *) hs->private; if ((rc = validate (slot_cur, ENABLE))) { err ("validate function failed\n"); goto error_nopower; } attn_LED_blink (slot_cur); rc = set_bus (slot_cur); if (rc) { err ("was not able to set the bus\n"); goto error_nopower; } /*-----------------debugging------------------------------*/ get_cur_bus_info (&slot_cur); debug ("the current bus speed right after set_bus = %x\n", slot_cur->bus_on->current_speed); /*----------------------------------------------------------*/ rc = check_limitations (slot_cur); if (rc) { err ("Adding this card exceeds the limitations of this bus.\n"); err ("(i.e., >1 133MHz cards running on same bus, or " ">2 66 PCI cards running on same bus\n."); err ("Try hot-adding into another bus\n"); rc = -EINVAL; goto error_nopower; } rc = power_on (slot_cur); if (rc) { err ("something wrong when powering up... please see below for details\n"); /* need to turn off before on, otherwise, blinking overwrites */ attn_off(slot_cur); attn_on (slot_cur); if (slot_update (&slot_cur)) { attn_off (slot_cur); attn_on (slot_cur); rc = -ENODEV; goto exit; } /* Check to see the error of why it failed */ if ((SLOT_POWER (slot_cur->status)) && !(SLOT_PWRGD (slot_cur->status))) err ("power fault occurred trying to power up\n"); else if (SLOT_BUS_SPEED (slot_cur->status)) { err ("bus speed mismatch occurred. please check current bus speed and card capability\n"); print_card_capability (slot_cur); } else if (SLOT_BUS_MODE (slot_cur->ext_status)) { err ("bus mode mismatch occurred. please check current bus mode and card capability\n"); print_card_capability (slot_cur); } ibmphp_update_slot_info (slot_cur); goto exit; } debug ("after power_on\n"); /*-----------------------debugging---------------------------*/ get_cur_bus_info (&slot_cur); debug ("the current bus speed right after power_on = %x\n", slot_cur->bus_on->current_speed); /*----------------------------------------------------------*/ rc = slot_update (&slot_cur); if (rc) goto error_power; rc = -EINVAL; if (SLOT_POWER (slot_cur->status) && !(SLOT_PWRGD (slot_cur->status))) { err ("power fault occurred trying to power up...\n"); goto error_power; } if (SLOT_POWER (slot_cur->status) && (SLOT_BUS_SPEED (slot_cur->status))) { err ("bus speed mismatch occurred. please check current bus speed and card capability\n"); print_card_capability (slot_cur); goto error_power; } /* Don't think this case will happen after above checks... but just in case, for paranoia sake */ if (!(SLOT_POWER (slot_cur->status))) { err ("power on failed...\n"); goto error_power; } slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL); if (!slot_cur->func) { /* We cannot do update_slot_info here, since no memory for * kmalloc n.e.ways, and update_slot_info allocates some */ err ("out of system memory\n"); rc = -ENOMEM; goto error_power; } memset (slot_cur->func, 0, sizeof (struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; for (i = 0; i < 4; i++) slot_cur->func->irq[i] = slot_cur->irq[i]; debug ("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n", slot_cur->bus, slot_cur->device); if (ibmphp_configure_card (slot_cur->func, slot_cur->number)) { err ("configure_card was unsuccessful...\n"); ibmphp_unconfigure_card (&slot_cur, 1); /* true because don't need to actually deallocate resources, just remove references */ debug ("after unconfigure_card\n"); slot_cur->func = NULL; rc = -ENOMEM; goto error_power; } function = 0x00; do { tmp_func = ibm_slot_find (slot_cur->bus, slot_cur->func->device, function++); if (tmp_func && !(tmp_func->dev)) ibm_configure_device (tmp_func); } while (tmp_func); attn_off (slot_cur); if (slot_update (&slot_cur)) { rc = -EFAULT; goto exit; } ibmphp_print_test (); rc = ibmphp_update_slot_info (slot_cur);exit: ibmphp_unlock_operations(); return rc;error_nopower: attn_off (slot_cur); /* need to turn off if was blinking b4 */ attn_on (slot_cur);error_cont: rcpr = slot_update (&slot_cur); if (rcpr) { rc = rcpr; goto exit; } ibmphp_update_slot_info (slot_cur); goto exit;error_power: attn_off (slot_cur); /* need to turn off if was blinking b4 */ attn_on (slot_cur); rcpr = power_off (slot_cur); if (rcpr) { rc = rcpr; goto exit; } goto error_cont;}/*************************************************************** HOT REMOVING ADAPTER CARD ** INPUT: POINTER TO THE HOTPLUG SLOT STRUCTURE ** OUTPUT: SUCCESS 0 ; FAILURE: UNCONFIGURE , VALIDATE * DISABLE POWER , ***************************************************************/static int ibmphp_disable_slot (struct hotplug_slot *hotplug_slot){ struct slot *slot = hotplug_slot->private; int rc; ibmphp_lock_operations(); rc = ibmphp_do_disable_slot(slot); ibmphp_unlock_operations(); return rc;}int ibmphp_do_disable_slot (struct slot *slot_cur){ int rc; u8 flag; debug ("DISABLING SLOT...\n"); if ((slot_cur == NULL) || (slot_cur->ctrl == NULL)) { return -ENODEV; } flag = slot_cur->flag; slot_cur->flag = TRUE; if (flag == TRUE) { rc = validate (slot_cur, DISABLE); /* checking if powered off already & valid slot # */ if (rc) goto error; } attn_LED_blink (slot_cur); if (slot_cur->func == NULL) { /* We need this for fncs's that were there on bootup */ slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL); if (!slot_cur->func) { err ("out of system memory\n"); rc = -ENOMEM; goto error; } memset (slot_cur->func, 0, sizeof (struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; } ibm_unconfigure_device(slot_cur->func); /* If we got here from latch suddenly opening on operating card or a power fault, there's no power to the card, so cannot read from it to determine what resources it occupied. This operation is forbidden anyhow. The best we can do is remove it from kernel lists at least */ if (!flag) { attn_off (slot_cur); return 0; } rc = ibmphp_unconfigure_card (&slot_cur, 0); slot_cur->func = NULL; debug ("in disable_slot. after unconfigure_card\n"); if (rc) { err ("could not unconfigure card.\n"); goto error; } rc = ibmphp_hpc_writeslot (slot_cur, HPC_SLOT_OFF); if (rc) goto error; attn_off (slot_cur); rc = slot_update (&slot_cur); if (rc) goto exit; rc = ibmphp_update_slot_info (slot_cur); ibmphp_print_test ();exit: return rc;error: /* Need to turn off if was blinking b4 */ attn_off (slot_cur); attn_on (slot_cur); if (slot_update (&slot_cur)) { rc = -EFAULT; goto exit; } if (flag) ibmphp_update_slot_info (slot_cur); goto exit;}struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { .owner = THIS_MODULE, .set_attention_status = set_attention_status, .enable_slot = enable_slot, .disable_slot = ibmphp_disable_slot, .hardware_test = NULL, .get_power_status = get_power_status, .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_present, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed,/* .get_max_adapter_speed = get_max_adapter_speed, .get_bus_name_status = get_bus_name,*/};static void ibmphp_unload (void){ free_slots (); debug ("after slots\n"); ibmphp_free_resources (); debug ("after resources\n"); ibmphp_free_bus_info_queue (); debug ("after bus info\n"); ibmphp_free_ebda_hpc_queue (); debug ("after ebda hpc\n"); ibmphp_free_ebda_pci_rsrc_queue (); debug ("after ebda pci rsrc\n"); kfree (ibmphp_pci_bus);}static int __init ibmphp_init (void){ struct pci_bus *bus; int i = 0; int rc = 0; init_flag = 1; info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); ibmphp_pci_bus = kmalloc (sizeof (*ibmphp_pci_bus), GFP_KERNEL); if (!ibmphp_pci_bus) { err ("out of memory\n"); rc = -ENOMEM; goto exit; } bus = pci_find_bus(0, 0); if (!bus) { err ("Can't find the root pci bus, can not continue\n"); rc = -ENODEV; goto error; } memcpy (ibmphp_pci_bus, bus, sizeof (*ibmphp_pci_bus)); ibmphp_debug = debug; ibmphp_hpc_initvars (); for (i = 0; i < 16; i++) irqs[i] = 0; if ((rc = ibmphp_access_ebda ())) goto error; debug ("after ibmphp_access_ebda ()\n"); if ((rc = ibmphp_rsrc_init ())) goto error; debug ("AFTER Resource & EBDA INITIALIZATIONS\n"); max_slots = get_max_slots (); if ((rc = ibmphp_register_pci ())) goto error; if (init_ops ()) { rc = -ENODEV; goto error; } ibmphp_print_test (); if ((rc = ibmphp_hpc_start_poll_thread ())) { goto error; } /* lock ourselves into memory with a module * count of -1 so that no one can unload us. */ module_put(THIS_MODULE);exit: return rc;error: ibmphp_unload (); goto exit;}static void __exit ibmphp_exit (void){ ibmphp_hpc_stop_poll_thread (); debug ("after polling\n"); ibmphp_unload (); debug ("done\n");}module_init (ibmphp_init);module_exit (ibmphp_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -