/* * IBM Hot Plug Controller Driver * * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation * * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2001-2003 IBM Corp. * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Send feedback to <gregkh@us.ibm.com> * */ #include <linux/init.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/wait.h>#include "../pci.h"#include <asm/pci_x86.h> /* for struct irq_routing_table */#include "ibmphp.h" #define attn_on(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)#define attn_off(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNOFF)#define attn_LED_blink(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_BLINKLED)#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev)#define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt) #define DRIVER_VERSION "0.6"#define DRIVER_DESC "IBM Hot Plug PCI Controller Driver" int ibmphp_debug; static bool debug;module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC (debug, "Debugging mode enabled or not");MODULE_LICENSE ("GPL");MODULE_DESCRIPTION (DRIVER_DESC); struct pci_bus *ibmphp_pci_bus;static int max_slots; static int irqs[16]; /* PIC mode IRQs we're using so far (in case MPS * tables don't provide default info for empty slots */ static int init_flag; /*static int get_max_adapter_speed_1 (struct hotplug_slot *, u8 *, u8); static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value){ return get_max_adapter_speed_1 (hs, value, 1);}*/static inline int get_cur_bus_info(struct slot **sl){ int rc = 1; struct slot * slot_cur = *sl; debug("options = %x\n", slot_cur->ctrl->options); debug("revision = %x\n", slot_cur->ctrl->revision); if (READ_BUS_STATUS(slot_cur->ctrl)) rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL); if (rc) return rc; slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED(slot_cur->busstatus); if (READ_BUS_MODE(slot_cur->ctrl)) slot_cur->bus_on->current_bus_mode = CURRENT_BUS_MODE(slot_cur->busstatus); else slot_cur->bus_on->current_bus_mode = 0xFF; debug("busstatus = %x, bus_speed = %x, bus_mode = %x\n", slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode); *sl = slot_cur; return 0;} static inline int slot_update(struct slot **sl){ int rc; rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL); if (rc) return rc; if (!init_flag) rc = get_cur_bus_info(sl); return rc;} static int __init get_max_slots (void){ struct slot * slot_cur; struct list_head * tmp; u8 slot_count = 0; list_for_each(tmp, &ibmphp_slot_head) { slot_cur = list_entry(tmp, struct slot, ibm_slot_list); /* sometimes the hot-pluggable slots start with 4 (not always from 1) */ slot_count = max(slot_count, slot_cur->number); } return slot_count;} /* This routine will put the correct slot->device information per slot. It's * called from initialization of the slot structures. It will also assign * interrupt numbers per each slot. * Parameters: struct slot * Returns 0 or errors */int ibmphp_init_devno(struct slot **cur_slot){ struct irq_routing_table *rtable; int len; int loop; int i; rtable = pcibios_get_irq_routing_table(); if (!rtable) { err("no BIOS routing table...\n"); return -ENOMEM; } len = (rtable->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); if (!len) { kfree(rtable); return -1; } for (loop = 0; loop < len; loop++) { if ((*cur_slot)->number == rtable->slots[loop].slot && (*cur_slot)->bus == rtable->slots[loop].bus) { struct io_apic_irq_attr irq_attr; (*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn); for (i = 0; i < 4; i++) (*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus, (int) (*cur_slot)->device, i, &irq_attr); debug("(*cur_slot)->irq[0] = %x\n", (*cur_slot)->irq[0]); debug("(*cur_slot)->irq[1] = %x\n", (*cur_slot)->irq[1]); debug("(*cur_slot)->irq[2] = %x\n", (*cur_slot)->irq[2]); debug("(*cur_slot)->irq[3] = %x\n", (*cur_slot)->irq[3]); debug("rtable->exclusive_irqs = %x\n", rtable->exclusive_irqs); debug("rtable->slots[loop].irq[0].bitmap = %x\n", rtable->slots[loop].irq[0].bitmap); debug("rtable->slots[loop].irq[1].bitmap = %x\n", rtable->slots[loop].irq[1].bitmap); debug("rtable->slots[loop].irq[2].bitmap = %x\n", rtable->slots[loop].irq[2].bitmap); debug("rtable->slots[loop].irq[3].bitmap = %x\n", rtable->slots[loop].irq[3].bitmap); debug("rtable->slots[loop].irq[0].link = %x\n", rtable->slots[loop].irq[0].link); debug("rtable->slots[loop].irq[1].link = %x\n", rtable->slots[loop].irq[1].link); debug("rtable->slots[loop].irq[2].link = %x\n", rtable->slots[loop].irq[2].link); debug("rtable->slots[loop].irq[3].link = %x\n", rtable->slots[loop].irq[3].link); debug("end of init_devno\n"); kfree(rtable); return 0; } } kfree(rtable); return -1;} static inline int power_on(struct slot *slot_cur){ u8 cmd = HPC_SLOT_ON; int retval; retval = ibmphp_hpc_writeslot(slot_cur, cmd); if (retval) { err("power on failed\n"); return retval; } if (CTLR_RESULT(slot_cur->ctrl->status)) { err("command not completed successfully in power_on\n"); return -EIO; } msleep(3000); /* For ServeRAID cards, and some 66 PCI */ return 0;} static inline int power_off(struct slot *slot_cur){ u8 cmd = HPC_SLOT_OFF; int retval; retval = ibmphp_hpc_writeslot(slot_cur, cmd); if (retval) { err("power off failed\n"); return retval; } if (CTLR_RESULT(slot_cur->ctrl->status)) { err("command not completed successfully in power_off\n"); retval = -EIO; } return retval;} static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value){ int rc = 0; struct slot *pslot; u8 cmd = 0x00; /* avoid compiler warning */ debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", (ulong) hotplug_slot, value); ibmphp_lock_operations(); if (hotplug_slot) { switch (value) { case HPC_SLOT_ATTN_OFF: cmd = HPC_SLOT_ATTNOFF; break; case HPC_SLOT_ATTN_ON: cmd = HPC_SLOT_ATTNON; break; case HPC_SLOT_ATTN_BLINK: cmd = HPC_SLOT_BLINKLED; break; default: rc = -ENODEV; err("set_attention_status - Error : invalid input [%x]\n", value); break; } if (rc == 0) { pslot = hotplug_slot->private; if (pslot) rc = ibmphp_hpc_writeslot(pslot, cmd); else rc = -ENODEV; } } else rc = -ENODEV; ibmphp_unlock_operations(); debug("set_attention_status - Exit rc[%d]\n", rc); return rc;} static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value){ int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status)); if (!rc) *value = SLOT_ATTN(myslot.status, myslot.ext_status); } } ibmphp_unlock_operations(); debug("get_attention_status - Exit rc[%d] value[%x]\n", rc, *value); return rc;} static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value){ int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) *value = SLOT_LATCH(myslot.status); } } ibmphp_unlock_operations(); debug("get_latch_status - Exit rc[%d] rc[%x] value[%x]\n", rc, rc, *value); return rc;} static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value){ int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) *value = SLOT_PWRGD(myslot.status); } } ibmphp_unlock_operations(); debug("get_power_status - Exit rc[%d] rc[%x] value[%x]\n", rc, rc, *value); return rc;} static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value){ int rc = -ENODEV; struct slot *pslot; u8 present; struct slot myslot; debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) { present = SLOT_PRESENT(myslot.status); if (present == HPC_SLOT_EMPTY) *value = 0; else *value = 1; } } } ibmphp_unlock_operations(); debug("get_adapter_present - Exit rc[%d] value[%x]\n", rc, *value); return rc;} static int get_max_bus_speed(struct slot *slot){ int rc; u8 mode = 0; enum pci_bus_speed speed; struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus; debug("%s - Entry slot[%p]\n", __func__, slot); ibmphp_lock_operations(); mode = slot->supported_bus_mode; speed = slot->supported_speed; ibmphp_unlock_operations(); switch (speed) { case BUS_SPEED_33: break; case BUS_SPEED_66: if (mode == BUS_MODE_PCIX) speed += 0x01; break; case BUS_SPEED_100: case BUS_SPEED_133: speed += 0x01; break; default: /* Note (will need to change): there would be soon 256, 512 also */ rc = -ENODEV; } if (!rc) bus->max_bus_speed = speed; debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed); return rc;} /*static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value, u8 flag){ int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); if (flag) ibmphp_lock_operations(); if (hotplug_slot && value) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, 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 = 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 BIOSLines 1–500 of 1374. Load more
/* * IBM Hot Plug Controller Driver * * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation * * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2001-2003 IBM Corp. * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Send feedback to <gregkh@us.ibm.com> * */ #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/wait.h> #include "../pci.h" #include <asm/pci_x86.h> /* for struct irq_routing_table */ #include "ibmphp.h" #define attn_on(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON) #define attn_off(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNOFF) #define attn_LED_blink(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_BLINKLED) #define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev) #define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt) #define DRIVER_VERSION "0.6" #define DRIVER_DESC "IBM Hot Plug PCI Controller Driver" int ibmphp_debug; static bool debug; module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC (debug, "Debugging mode enabled or not"); MODULE_LICENSE ("GPL"); MODULE_DESCRIPTION (DRIVER_DESC); struct pci_bus *ibmphp_pci_bus; static int max_slots; static int irqs[16]; /* PIC mode IRQs we're using so far (in case MPS * tables don't provide default info for empty slots */ static int init_flag; /* static int get_max_adapter_speed_1 (struct hotplug_slot *, u8 *, u8); static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value) { return get_max_adapter_speed_1 (hs, value, 1); } */ static inline int get_cur_bus_info(struct slot **sl) { int rc = 1; struct slot * slot_cur = *sl; debug("options = %x\n", slot_cur->ctrl->options); debug("revision = %x\n", slot_cur->ctrl->revision); if (READ_BUS_STATUS(slot_cur->ctrl)) rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL); if (rc) return rc; slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED(slot_cur->busstatus); if (READ_BUS_MODE(slot_cur->ctrl)) slot_cur->bus_on->current_bus_mode = CURRENT_BUS_MODE(slot_cur->busstatus); else slot_cur->bus_on->current_bus_mode = 0xFF; debug("busstatus = %x, bus_speed = %x, bus_mode = %x\n", slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode); *sl = slot_cur; return 0; } static inline int slot_update(struct slot **sl) { int rc; rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL); if (rc) return rc; if (!init_flag) rc = get_cur_bus_info(sl); return rc; } static int __init get_max_slots (void) { struct slot * slot_cur; struct list_head * tmp; u8 slot_count = 0; list_for_each(tmp, &ibmphp_slot_head) { slot_cur = list_entry(tmp, struct slot, ibm_slot_list); /* sometimes the hot-pluggable slots start with 4 (not always from 1) */ slot_count = max(slot_count, slot_cur->number); } return slot_count; } /* This routine will put the correct slot->device information per slot. It's * called from initialization of the slot structures. It will also assign * interrupt numbers per each slot. * Parameters: struct slot * Returns 0 or errors */ int ibmphp_init_devno(struct slot **cur_slot) { struct irq_routing_table *rtable; int len; int loop; int i; rtable = pcibios_get_irq_routing_table(); if (!rtable) { err("no BIOS routing table...\n"); return -ENOMEM; } len = (rtable->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); if (!len) { kfree(rtable); return -1; } for (loop = 0; loop < len; loop++) { if ((*cur_slot)->number == rtable->slots[loop].slot && (*cur_slot)->bus == rtable->slots[loop].bus) { struct io_apic_irq_attr irq_attr; (*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn); for (i = 0; i < 4; i++) (*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus, (int) (*cur_slot)->device, i, &irq_attr); debug("(*cur_slot)->irq[0] = %x\n", (*cur_slot)->irq[0]); debug("(*cur_slot)->irq[1] = %x\n", (*cur_slot)->irq[1]); debug("(*cur_slot)->irq[2] = %x\n", (*cur_slot)->irq[2]); debug("(*cur_slot)->irq[3] = %x\n", (*cur_slot)->irq[3]); debug("rtable->exclusive_irqs = %x\n", rtable->exclusive_irqs); debug("rtable->slots[loop].irq[0].bitmap = %x\n", rtable->slots[loop].irq[0].bitmap); debug("rtable->slots[loop].irq[1].bitmap = %x\n", rtable->slots[loop].irq[1].bitmap); debug("rtable->slots[loop].irq[2].bitmap = %x\n", rtable->slots[loop].irq[2].bitmap); debug("rtable->slots[loop].irq[3].bitmap = %x\n", rtable->slots[loop].irq[3].bitmap); debug("rtable->slots[loop].irq[0].link = %x\n", rtable->slots[loop].irq[0].link); debug("rtable->slots[loop].irq[1].link = %x\n", rtable->slots[loop].irq[1].link); debug("rtable->slots[loop].irq[2].link = %x\n", rtable->slots[loop].irq[2].link); debug("rtable->slots[loop].irq[3].link = %x\n", rtable->slots[loop].irq[3].link); debug("end of init_devno\n"); kfree(rtable); return 0; } } kfree(rtable); return -1; } static inline int power_on(struct slot *slot_cur) { u8 cmd = HPC_SLOT_ON; int retval; retval = ibmphp_hpc_writeslot(slot_cur, cmd); if (retval) { err("power on failed\n"); return retval; } if (CTLR_RESULT(slot_cur->ctrl->status)) { err("command not completed successfully in power_on\n"); return -EIO; } msleep(3000); /* For ServeRAID cards, and some 66 PCI */ return 0; } static inline int power_off(struct slot *slot_cur) { u8 cmd = HPC_SLOT_OFF; int retval; retval = ibmphp_hpc_writeslot(slot_cur, cmd); if (retval) { err("power off failed\n"); return retval; } if (CTLR_RESULT(slot_cur->ctrl->status)) { err("command not completed successfully in power_off\n"); retval = -EIO; } return retval; } static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) { int rc = 0; struct slot *pslot; u8 cmd = 0x00; /* avoid compiler warning */ debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", (ulong) hotplug_slot, value); ibmphp_lock_operations(); if (hotplug_slot) { switch (value) { case HPC_SLOT_ATTN_OFF: cmd = HPC_SLOT_ATTNOFF; break; case HPC_SLOT_ATTN_ON: cmd = HPC_SLOT_ATTNON; break; case HPC_SLOT_ATTN_BLINK: cmd = HPC_SLOT_BLINKLED; break; default: rc = -ENODEV; err("set_attention_status - Error : invalid input [%x]\n", value); break; } if (rc == 0) { pslot = hotplug_slot->private; if (pslot) rc = ibmphp_hpc_writeslot(pslot, cmd); else rc = -ENODEV; } } else rc = -ENODEV; ibmphp_unlock_operations(); debug("set_attention_status - Exit rc[%d]\n", rc); return rc; } static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) { int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status)); if (!rc) *value = SLOT_ATTN(myslot.status, myslot.ext_status); } } ibmphp_unlock_operations(); debug("get_attention_status - Exit rc[%d] value[%x]\n", rc, *value); return rc; } static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) { int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) *value = SLOT_LATCH(myslot.status); } } ibmphp_unlock_operations(); debug("get_latch_status - Exit rc[%d] rc[%x] value[%x]\n", rc, rc, *value); return rc; } static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) { int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) *value = SLOT_PWRGD(myslot.status); } } ibmphp_unlock_operations(); debug("get_power_status - Exit rc[%d] rc[%x] value[%x]\n", rc, rc, *value); return rc; } static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) { int rc = -ENODEV; struct slot *pslot; u8 present; struct slot myslot; debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!rc) { present = SLOT_PRESENT(myslot.status); if (present == HPC_SLOT_EMPTY) *value = 0; else *value = 1; } } } ibmphp_unlock_operations(); debug("get_adapter_present - Exit rc[%d] value[%x]\n", rc, *value); return rc; } static int get_max_bus_speed(struct slot *slot) { int rc; u8 mode = 0; enum pci_bus_speed speed; struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus; debug("%s - Entry slot[%p]\n", __func__, slot); ibmphp_lock_operations(); mode = slot->supported_bus_mode; speed = slot->supported_speed; ibmphp_unlock_operations(); switch (speed) { case BUS_SPEED_33: break; case BUS_SPEED_66: if (mode == BUS_MODE_PCIX) speed += 0x01; break; case BUS_SPEED_100: case BUS_SPEED_133: speed += 0x01; break; default: /* Note (will need to change): there would be soon 256, 512 also */ rc = -ENODEV; } if (!rc) bus->max_bus_speed = speed; debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed); return rc; } /* static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value, u8 flag) { int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); if (flag) ibmphp_lock_operations(); if (hotplug_slot && value) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, 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 = 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