📄 ibmphp_core.c
字号:
if (flag) ibmphp_lock_operations (); if (hotplug_slot && value) { pslot = (struct slot *) hotplug_slot->private; if (pslot) { memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!(SLOT_LATCH (myslot.status)) && (SLOT_PRESENT (myslot.status))) { rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status)); if (!rc) *value = SLOT_SPEED (myslot.ext_status); } else *value = MAX_ADAPTER_NONE; } } if (flag) ibmphp_unlock_operations (); debug("get_max_adapter_speed_1 - Exit rc[%d] value[%x]\n", rc, *value); return rc;}static int get_bus_name (struct hotplug_slot *hotplug_slot, char * value){ int rc = -ENODEV; struct slot *pslot = NULL; debug ("get_bus_name - Entry hotplug_slot[%lx]\n", (ulong)hotplug_slot); ibmphp_lock_operations (); if (hotplug_slot) { pslot = (struct slot *) hotplug_slot->private; if (pslot) { rc = 0; snprintf (value, 100, "Bus %x", pslot->bus); } } else rc = -ENODEV; ibmphp_unlock_operations (); debug ("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value); return rc;}*//******************************************************************************* * This routine will initialize the ops data structure used in the validate * function. It will also power off empty slots that are powered on since BIOS * leaves those on, albeit disconnected ******************************************************************************/static int __init init_ops (void){ struct slot *slot_cur; struct list_head *tmp; int retval; int rc; list_for_each (tmp, &ibmphp_slot_head) { slot_cur = list_entry (tmp, struct slot, ibm_slot_list); if (!slot_cur) return -ENODEV; debug ("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number); if (slot_cur->ctrl->revision == 0xFF) if (get_ctrl_revision (slot_cur, &slot_cur->ctrl->revision)) return -1; if (slot_cur->bus_on->current_speed == 0xFF) if (get_cur_bus_info (&slot_cur)) return -1; if (slot_cur->ctrl->options == 0xFF) if (get_hpc_options (slot_cur, &slot_cur->ctrl->options)) return -1; retval = slot_update (&slot_cur); if (retval) return retval; debug ("status = %x\n", slot_cur->status); debug ("ext_status = %x\n", slot_cur->ext_status); debug ("SLOT_POWER = %x\n", SLOT_POWER (slot_cur->status)); debug ("SLOT_PRESENT = %x\n", SLOT_PRESENT (slot_cur->status)); debug ("SLOT_LATCH = %x\n", SLOT_LATCH (slot_cur->status)); if ((SLOT_PWRGD (slot_cur->status)) && !(SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) { debug ("BEFORE POWER OFF COMMAND\n"); rc = power_off (slot_cur); if (rc) return rc; /* retval = slot_update (&slot_cur); * if (retval) * return retval; * ibmphp_update_slot_info (slot_cur); */ } } init_flag = 0; return 0;}/* This operation will check whether the slot is within the bounds and * the operation is valid to perform on that slot * Parameters: slot, operation * Returns: 0 or error codes */static int validate (struct slot *slot_cur, int opn){ int number; int retval; if (!slot_cur) return -ENODEV; number = slot_cur->number; if ((number > max_slots) || (number < 0)) return -EBADSLT; debug ("slot_number in validate is %d\n", slot_cur->number); retval = slot_update (&slot_cur); if (retval) return retval; switch (opn) { case ENABLE: if (!(SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) return 0; break; case DISABLE: if ((SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) return 0; break; default: break; } err ("validate failed....\n"); return -EINVAL;}/******************************************************************************** * This routine is for updating the data structures in the hotplug core * Parameters: struct slot * Returns: 0 or error *******************************************************************************/int ibmphp_update_slot_info (struct slot *slot_cur){ struct hotplug_slot_info *info; int rc; u8 bus_speed; u8 mode; info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); if (!info) { err ("out of system memory\n"); return -ENOMEM; } info->power_status = SLOT_PWRGD (slot_cur->status); info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status); info->latch_status = SLOT_LATCH (slot_cur->status); if (!SLOT_PRESENT (slot_cur->status)) { info->adapter_status = 0;// info->max_adapter_speed_status = MAX_ADAPTER_NONE; } else { info->adapter_status = 1;// get_max_adapter_speed_1 (slot_cur->hotplug_slot, &info->max_adapter_speed_status, 0); } bus_speed = slot_cur->bus_on->current_speed; mode = slot_cur->bus_on->current_bus_mode; switch (bus_speed) { case BUS_SPEED_33: break; case BUS_SPEED_66: if (mode == BUS_MODE_PCIX) bus_speed += 0x01; else if (mode == BUS_MODE_PCI) ; else bus_speed = PCI_SPEED_UNKNOWN; break; case BUS_SPEED_100: case BUS_SPEED_133: bus_speed += 0x01; break; default: bus_speed = PCI_SPEED_UNKNOWN; } info->cur_bus_speed = bus_speed; info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed; // To do: bus_names rc = pci_hp_change_slot_info (slot_cur->hotplug_slot, info); kfree (info); return rc;}/****************************************************************************** * This function will return the pci_func, given bus and devfunc, or NULL. It * is called from visit routines ******************************************************************************/static struct pci_func *ibm_slot_find (u8 busno, u8 device, u8 function){ struct pci_func *func_cur; struct slot *slot_cur; struct list_head * tmp; list_for_each (tmp, &ibmphp_slot_head) { slot_cur = list_entry (tmp, struct slot, ibm_slot_list); if (slot_cur->func) { func_cur = slot_cur->func; while (func_cur) { if ((func_cur->busno == busno) && (func_cur->device == device) && (func_cur->function == function)) return func_cur; func_cur = func_cur->next; } } } return NULL;}/************************************************************* * This routine frees up memory used by struct slot, including * the pointers to pci_func, bus, hotplug_slot, controller, * and deregistering from the hotplug core *************************************************************/static void free_slots (void){ struct slot *slot_cur; struct list_head * tmp; struct list_head * next; debug ("%s -- enter\n", __FUNCTION__); list_for_each_safe (tmp, next, &ibmphp_slot_head) { slot_cur = list_entry (tmp, struct slot, ibm_slot_list); pci_hp_deregister (slot_cur->hotplug_slot); } debug ("%s -- exit\n", __FUNCTION__);}static void ibm_unconfigure_device(struct pci_func *func){ struct pci_dev *temp; u8 j; debug("inside %s\n", __FUNCTION__); debug("func->device = %x, func->function = %x\n", func->device, func->function); debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); for (j = 0; j < 0x08; j++) { temp = pci_find_slot(func->busno, (func->device << 3) | j); if (temp) pci_remove_bus_device(temp); }}/* * The following function is to fix kernel bug regarding * getting bus entries, here we manually add those primary * bus entries to kernel bus structure whenever apply */static u8 bus_structure_fixup (u8 busno){ struct pci_bus *bus; struct pci_dev *dev; u16 l; if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num (busno))) return 1; bus = kmalloc (sizeof (*bus), GFP_KERNEL); if (!bus) { err ("%s - out of memory\n", __FUNCTION__); return 1; } dev = kmalloc (sizeof (*dev), GFP_KERNEL); if (!dev) { kfree (bus); err ("%s - out of memory\n", __FUNCTION__); return 1; } bus->number = busno; bus->ops = ibmphp_pci_bus->ops; dev->bus = bus; for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) { if (!pci_read_config_word (dev, PCI_VENDOR_ID, &l) && l != 0x0000 && l != 0xffff) { debug ("%s - Inside bus_struture_fixup()\n", __FUNCTION__); pci_scan_bus (busno, ibmphp_pci_bus->ops, NULL); break; } } kfree (dev); kfree (bus); return 0;}static int ibm_configure_device (struct pci_func *func){ unsigned char bus; struct pci_bus *child; int num; int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ if (!(bus_structure_fixup (func->busno))) flag = 1; if (func->dev == NULL) func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { struct pci_bus *bus = pci_find_bus(0, func->busno); if (!bus) return 0; num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function)); if (num) pci_bus_add_devices(bus); func->dev = pci_find_slot(func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { err ("ERROR... : pci_dev still NULL\n"); return 0; } } if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { pci_read_config_byte (func->dev, PCI_SECONDARY_BUS, &bus); child = (struct pci_bus *) pci_add_new_bus (func->dev->bus, (func->dev), bus); pci_do_scan_bus (child); } return 0;}/******************************************************* * Returns whether the bus is empty or not *******************************************************/static int is_bus_empty (struct slot * slot_cur){ int rc; struct slot * tmp_slot; u8 i = slot_cur->bus_on->slot_min; while (i <= slot_cur->bus_on->slot_max) { if (i == slot_cur->number) { i++; continue; } tmp_slot = ibmphp_get_slot_from_physical_num (i); if (!tmp_slot) return 0; rc = slot_update (&tmp_slot); if (rc) return 0; if (SLOT_PRESENT (tmp_slot->status) && SLOT_PWRGD (tmp_slot->status)) return 0; i++; } return 1;}/*********************************************************** * If the HPC permits and the bus currently empty, tries to set the * bus speed and mode at the maximum card and bus capability * Parameters: slot * Returns: bus is set (0) or error code ***********************************************************/static int set_bus (struct slot * slot_cur){ int rc; u8 speed; u8 cmd = 0x0; struct pci_dev *dev = NULL; int retval; debug ("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number); if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) { rc = slot_update (&slot_cur); if (rc) return rc; speed = SLOT_SPEED (slot_cur->ext_status); debug ("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed); switch (speed) { case HPC_SLOT_SPEED_33: cmd = HPC_BUS_33CONVMODE; break; case HPC_SLOT_SPEED_66: if (SLOT_PCIX (slot_cur->ext_status)) { if ((slot_cur->supported_speed >= BUS_SPEED_66) && (slot_cur->supported_bus_mode == BUS_MODE_PCIX)) cmd = HPC_BUS_66PCIXMODE; else if (!SLOT_BUS_MODE (slot_cur->ext_status)) /* if max slot/bus capability is 66 pci and there's no bus mode mismatch, then the adapter supports 66 pci */ cmd = HPC_BUS_66CONVMODE; else cmd = HPC_BUS_33CONVMODE; } else { if (slot_cur->supported_speed >= BUS_SPEED_66) cmd = HPC_BUS_66CONVMODE; else cmd = HPC_BUS_33CONVMODE; } break; case HPC_SLOT_SPEED_133: switch (slot_cur->supported_speed) { case BUS_SPEED_33: cmd = HPC_BUS_33CONVMODE; break; case BUS_SPEED_66: if (slot_cur->supported_bus_mode == BUS_MODE_PCIX) cmd = HPC_BUS_66PCIXMODE; else cmd = HPC_BUS_66CONVMODE; break; case BUS_SPEED_100: cmd = HPC_BUS_100PCIXMODE; break; case BUS_SPEED_133: /* This is to take care of the bug in CIOBX chip */ while ((dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 0x0101, dev)) != NULL) ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE); cmd = HPC_BUS_133PCIXMODE; break; default: err ("Wrong bus speed\n"); return -ENODEV; } break; default: err ("wrong slot speed\n"); return -ENODEV; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -