lkml.org 
[lkml]   [2003]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[Patch] 3/4 PCI Hot-plug driver patch for 2.5.74 kernel
    Part 3 of 4 PCI Hot-plug driver patch for 2.5.74 kernel

    diff -Nru a/drivers/pci/hotplug/cpqphp_hpc.c b/drivers/pci/hotplug/cpqphp_hpc.c
    --- a/drivers/pci/hotplug/cpqphp_hpc.c 1969-12-31 16:00:00.000000000 -0800
    +++ b/drivers/pci/hotplug/cpqphp_hpc.c 2003-07-07 09:32:22.000000000 -0700
    @@ -0,0 +1,1203 @@
    +/*
    + * Compaq PCI Hot Plug Driver
    + *
    + * Copyright (c) 1995,2001 Compaq Computer Corporation
    + *
    + * 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 <dely.l.sy@intel.com>
    + *
    + */
    +
    +#include <linux/config.h>
    +#include <linux/kernel.h>
    +#include <linux/module.h>
    +#include <linux/types.h>
    +#include <linux/slab.h>
    +#include <linux/vmalloc.h>
    +#include <linux/interrupt.h>
    +#include <linux/spinlock.h>
    +#include <linux/pci.h>
    +#include <linux/delay.h> /* for delays */
    +#include <asm/system.h>
    +#include "cpqphp.h"
    +
    +#ifdef DEBUG
    +#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
    +#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */
    +#define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */
    +#define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */
    +#define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT)
    +#define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE)
    +/* Redefine this flagword to set debug level */
    +#define DEBUG_LEVEL DBG_K_STANDARD
    +
    +#define DEFINE_DBG_BUFFER char __dbg_str_buf[256];
    +
    +#define DBG_PRINT( dbg_flags, args... ) \
    + do { \
    + if ( DEBUG_LEVEL & ( dbg_flags ) ) \
    + { \
    + int len; \
    + len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \
    + __FILE__, __LINE__, __FUNCTION__ ); \
    + sprintf( __dbg_str_buf + len, args ); \
    + printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \
    + } \
    + } while (0)
    +
    +#define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]");
    +#define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]");
    +#else
    +#define DEFINE_DBG_BUFFER
    +#define DBG_ENTER_ROUTINE
    +#define DBG_LEAVE_ROUTINE
    +#endif /* DEBUG */
    +
    +struct ctrl_reg { /* offset */
    + u8 slot_RST; /* 0x00 */
    + u8 slot_enable; /* 0x01 */
    + u16 misc; /* 0x02 */
    + u32 led_control; /* 0x04 */
    + u32 int_input_clear; /* 0x08 */
    + u32 int_mask; /* 0x0a */
    + u8 reserved0; /* 0x10 */
    + u8 reserved1; /* 0x11 */
    + u8 reserved2; /* 0x12 */
    + u8 gen_output_AB; /* 0x13 */
    + u32 non_int_input; /* 0x14 */
    + u32 reserved3; /* 0x18 */
    + u32 reserved4; /* 0x1a */
    + u32 reserved5; /* 0x20 */
    + u8 reserved6; /* 0x24 */
    + u8 reserved7; /* 0x25 */
    + u16 reserved8; /* 0x26 */
    + u8 slot_mask; /* 0x28 */
    + u8 reserved9; /* 0x29 */
    + u8 reserved10; /* 0x2a */
    + u8 reserved11; /* 0x2b */
    + u8 slot_SERR; /* 0x2c */
    + u8 slot_power; /* 0x2d */
    + u8 reserved12; /* 0x2e */
    + u8 reserved13; /* 0x2f */
    + u8 next_curr_freq; /* 0x30 */
    + u8 reset_freq_mode; /* 0x31 */
    +
    +} __attribute__ ((packed));
    +
    +/* offsets to the controller registers based on the above structure layout */
    +enum ctrl_offsets {
    + SLOT_RST = offsetof(struct ctrl_reg, slot_RST),
    + SLOT_ENABLE = offsetof(struct ctrl_reg, slot_enable),
    + MISC = offsetof(struct ctrl_reg, misc),
    + LED_CONTROL = offsetof(struct ctrl_reg, led_control),
    + INT_INPUT_CLEAR = offsetof(struct ctrl_reg, int_input_clear),
    + INT_MASK = offsetof(struct ctrl_reg, int_mask),
    + CTRL_RESERVED0 = offsetof(struct ctrl_reg, reserved0),
    + CTRL_RESERVED1 = offsetof(struct ctrl_reg, reserved1),
    + CTRL_RESERVED2 = offsetof(struct ctrl_reg, reserved1),
    + GEN_OUTPUT_AB = offsetof(struct ctrl_reg, gen_output_AB),
    + NON_INT_INPUT = offsetof(struct ctrl_reg, non_int_input),
    + CTRL_RESERVED3 = offsetof(struct ctrl_reg, reserved3),
    + CTRL_RESERVED4 = offsetof(struct ctrl_reg, reserved4),
    + CTRL_RESERVED5 = offsetof(struct ctrl_reg, reserved5),
    + CTRL_RESERVED6 = offsetof(struct ctrl_reg, reserved6),
    + CTRL_RESERVED7 = offsetof(struct ctrl_reg, reserved7),
    + CTRL_RESERVED8 = offsetof(struct ctrl_reg, reserved8),
    + SLOT_MASK = offsetof(struct ctrl_reg, slot_mask),
    + CTRL_RESERVED9 = offsetof(struct ctrl_reg, reserved9),
    + CTRL_RESERVED10 = offsetof(struct ctrl_reg, reserved10),
    + CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11),
    + SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR),
    + SLOT_POWER = offsetof(struct ctrl_reg, slot_power),
    + CTRL_RESERVED12 = offsetof(struct ctrl_reg, reserved12),
    + CTRL_RESERVED13 = offsetof(struct ctrl_reg, reserved13),
    + NEXT_CURR_FREQ = offsetof(struct ctrl_reg, next_curr_freq),
    + RESET_FREQ_MODE = offsetof(struct ctrl_reg, reset_freq_mode),
    +};
    +
    +
    +struct sema_struct {
    + struct semaphore crit_sect;
    + int owner_id;
    + int count;
    +};
    +
    +struct php_ctlr_state_s {
    + struct php_ctlr_state_s *pnext;
    + struct pci_dev *pci_dev;
    + unsigned int irq;
    + struct sema_struct hwlock;
    + unsigned long flags; /* spinlock's */
    + u32 ctrl_int_comp; /* interrupt comparator */
    + u32 first_device_num;
    + u32 num_slots;
    + u16 ctlrcap;
    + php_intr_callback_t switch_change_callback;
    + php_intr_callback_t presence_change_callback;
    + php_intr_callback_t power_fault_callback;
    + void *callback_instance_id;
    + void *creg; /* Ptr to controller register space */
    +};
    +
    +
    +spinlock_t hpc_event_lock;
    +
    +DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
    +static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */
    +static int ctlr_seq_num = 0; /* Controller sequenc # */
    +
    +static irqreturn_t hpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
    +
    +static wait_queue_head_t delay_wait_q_head;
    +
    +/* delay in jiffies to wait */
    +static void longdelay(int delay)
    +{
    + init_waitqueue_head(&delay_wait_q_head);
    +
    + interruptible_sleep_on_timeout(&delay_wait_q_head, delay);
    +}
    +
    +static void cpqhpc_set_SOGO (struct slot *slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u16 misc;
    +
    + misc = readw(php_ctlr->creg + MISC);
    + misc = (misc | 0x0001) & 0xFFFB;
    + writew(misc, php_ctlr->creg + MISC);
    +}
    +
    +static int cpqhpc_wait_for_SOBS (struct slot *slot)
    +{
    + DECLARE_WAITQUEUE(wait, current);
    + int retval = 0;
    +
    + DBG_ENTER_ROUTINE
    +
    + add_wait_queue(&slot->ctrl->queue, &wait);
    + set_current_state(TASK_INTERRUPTIBLE);
    + schedule_timeout(2*HZ);
    + set_current_state(TASK_RUNNING);
    + remove_wait_queue(&slot->ctrl->queue, &wait);
    + if (signal_pending(current))
    + retval = -EINTR;
    +
    + DBG_LEAVE_ROUTINE
    + return retval;
    +}
    +
    +static void hpc_update_hpc(struct slot *slot)
    +{
    + cpqhpc_set_SOGO(slot);
    + cpqhpc_wait_for_SOBS(slot);
    +}
    +
    +static int hpc_get_attention_status(struct slot *slot, u8 *status)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 led_control;
    +
    + DBG_ENTER_ROUTINE
    +
    + led_control = readl(php_ctlr->creg + LED_CONTROL);
    + led_control &= (0x01010000L << slot->hp_slot);
    + *status = led_control ? 1 : 0;
    +
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_get_power_status(struct slot * slot, u8 *status)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u8 slot_enable;
    +
    + DBG_ENTER_ROUTINE
    +
    + slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
    + slot_enable &= (0x01L << slot->hp_slot);
    + *status = slot_enable ? 1 : 0;
    +
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_get_latch_status(struct slot *slot, u8 *status)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 latch_status;
    +
    + DBG_ENTER_ROUTINE
    +
    + latch_status = (readl(php_ctlr->creg + INT_INPUT_CLEAR) & (0x01L << slot->hp_slot));
    + *status = (latch_status == 0) ? 1 : 0;
    +
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_get_adapter_status(struct slot *slot, u8 *status)
    +{
    + u8 presence_save = 0;
    + u32 tempdword;
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    +
    + DBG_ENTER_ROUTINE
    +
    + tempdword = readl(php_ctlr->creg + INT_INPUT_CLEAR);
    + presence_save = (u8) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> slot->hp_slot) & 0x02;
    +
    + *status = (presence_save != 0) ? 1 : 0;
    +
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_query_power_fault(struct slot * slot)
    +{
    + u32 status;
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 tempdword;
    +
    + DBG_ENTER_ROUTINE
    +
    + tempdword = readl(php_ctlr->creg + INT_INPUT_CLEAR);
    + status = (tempdword & (0x00000100 << slot->hp_slot));
    +
    + DBG_LEAVE_ROUTINE
    + /* Note: Logic 0 => fault */
    + return status ? 0 : 1;
    +}
    +
    +/*
    + * change to call set_led_state()
    + */
    +
    +static void hpc_set_attention_status(struct slot *slot, u8 status)
    +{
    + struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 led_control;
    +
    + switch (status) {
    + case 0:
    + led_control = readl(php_ctlr->creg + LED_CONTROL);
    + led_control &= ~(0x01010000L << slot->hp_slot);
    + writel(led_control, php_ctlr->creg + LED_CONTROL);
    + break;
    + case 1:
    + led_control = readl(php_ctlr->creg + LED_CONTROL);
    + led_control |= (0x01010000L << slot->hp_slot);
    + writel(led_control, php_ctlr->creg + LED_CONTROL);
    + break;
    + }
    +}
    +
    +static void hpc_green_led_on(struct slot * slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 led_control;
    +
    + led_control = readl(php_ctlr->creg + LED_CONTROL);
    + led_control |= 0x0101L << slot->hp_slot;
    + writel(led_control, php_ctlr->creg + LED_CONTROL);
    +
    +}
    +
    +static void hpc_green_led_off(struct slot * slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 led_control;
    +
    + led_control = readl(php_ctlr->creg + LED_CONTROL);
    + led_control &= ~(0x0101L << slot->hp_slot);
    + writel(led_control, php_ctlr->creg + LED_CONTROL);
    +
    +}
    +
    +static void hpc_green_led_blink(struct slot * slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 led_control;
    +
    + led_control = readl(php_ctlr->creg + LED_CONTROL);
    + led_control &= ~(0x0101L << slot->hp_slot);
    + led_control |= (0x0001L << slot->hp_slot);
    + writel(led_control, php_ctlr->creg + LED_CONTROL);
    +
    +}
    +
    +/*
    + * 0: all 4 variables set
    + * 1: no physical_slot_num
    + */
    +int phphpc_get_ctlr_slot_config(struct controller *ctrl,
    + int *num_ctlr_slots, /* number of slots in this HPC */
    + int *first_device_num, /* PCI dev num of the first slot in this HPC */
    + int *physical_slot_num, /* phy slot num of the first slot in this HPC */
    + int *updown, /* physical_slot_num increament: 1 or -1 */
    + int *flags)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
    +
    + DBG_ENTER_ROUTINE
    +
    + * first_device_num = php_ctlr->first_device_num;
    + *num_ctlr_slots = php_ctlr->num_slots;
    +
    + /* this HPC does not conform to SHPC and provides no physical_slot_num. */
    + *physical_slot_num = -1;
    +
    + *updown = 1; /* could be -1 in SHPC */
    + *flags = 1;
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static void hpc_release_ctlr(struct controller *ctrl)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
    + struct php_ctlr_state_s *p, *p_prev;
    +
    + DBG_ENTER_ROUTINE
    +
    + if (php_ctlr->irq) {
    + free_irq(php_ctlr->irq, ctrl);
    + php_ctlr->irq = 0;
    + }
    +
    + if (php_ctlr->pci_dev) {
    + iounmap((void *) pci_resource_start(php_ctlr->pci_dev, 0));
    + release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
    + php_ctlr->pci_dev = 0;
    + }
    +
    + p = php_ctlr_list_head;
    + p_prev = NULL;
    + while (p) {
    + if (p == php_ctlr) {
    + if (p_prev)
    + p_prev->pnext = p->pnext;
    + else
    + php_ctlr_list_head = p->pnext;
    + break;
    + } else {
    + p_prev = p;
    + p = p->pnext;
    + }
    + }
    +
    + kfree(php_ctlr);
    +
    + DBG_LEAVE_ROUTINE
    +}
    +
    +static int hpc_power_on_slot(struct slot * slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u8 slot_enable;
    +
    + DBG_ENTER_ROUTINE
    +
    + slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
    + slot_enable |= (0x01 << slot->hp_slot);
    + writeb(slot_enable, php_ctlr->creg + SLOT_ENABLE);
    +
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_power_off_slot(struct slot * slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u8 slot_enable;
    +
    + DBG_ENTER_ROUTINE
    +
    + slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
    + slot_enable &= ~(0x01 << slot->hp_slot);
    + writeb(slot_enable, php_ctlr->creg + SLOT_ENABLE);
    +
    + DBG_LEAVE_ROUTINE
    +
    + return 0;
    +}
    +
    +static void hpc_enable_msl_interrupt(struct slot *slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 rc;
    + u16 misc;
    +
    + DBG_ENTER_ROUTINE
    +
    + if (php_ctlr->creg) {
    + rc = readb(php_ctlr->creg + SLOT_ENABLE);
    +
    + writeb(rc, php_ctlr->creg + SLOT_SERR);
    + writel(0xFFFFFFC0L | ~rc, php_ctlr->creg + INT_MASK);
    +
    + misc = readw(php_ctlr->creg + MISC);
    + misc &= 0xFFFD;
    + writew(misc, php_ctlr->creg + MISC);
    + }
    +
    + DBG_LEAVE_ROUTINE
    +}
    +
    +static u32 hpc_get_slot_capability(struct slot *slot)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 slot_state = 0, temp;
    + u8 slot_enable;
    +
    + DBG_ENTER_ROUTINE
    +
    + temp = readl(php_ctlr->creg + INT_INPUT_CLEAR);
    +
    + /* Check presence */
    + slot_state |= ((((~temp) >> 23) | ((~temp) >> 15)) >> slot->hp_slot) & 0x02;
    + /* Check the switch state */
    + slot_state |= ((~temp & 0xFF) >> slot->hp_slot) & 0x01;
    + /* Check the slot enable */
    + slot_enable = readb(php_ctlr->creg + SLOT_ENABLE);
    + slot_state |= ((slot_enable << 2) >> slot->hp_slot) & 0x04;
    +
    + return slot_state;
    +
    + DBG_LEAVE_ROUTINE
    +}
    +
    +static irqreturn_t hpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
    +{
    + struct controller *ctrl = (struct controller *)dev_id;
    + struct php_ctlr_state_s *php_ctlr;
    + u8 schedule_flag = 0;
    + u32 Diff;
    + u32 temp_dword;
    + u16 misc;
    + u8 reset;
    +
    + if (!ctrl || !(php_ctlr = ctrl->hpc_ctlr_handle) || !php_ctlr->creg)
    + return IRQ_NONE;
    +
    + /* Check to see if it was our interrupt */
    + misc = readw(php_ctlr->creg + MISC);
    + if (!(misc & 0x000C))
    + return IRQ_NONE;
    +
    + if (misc & 0x0004) {
    + /* Serial Output interrupt Pending */
    + misc |= 0x0004; /* Clear the interrupt */
    + writew(misc, php_ctlr->creg + MISC);
    + misc = readw(php_ctlr->creg + MISC); /* Read to clear posted writes */
    + wake_up_interruptible(&ctrl->queue);
    + }
    +
    + if (misc & 0x0008) {
    + /* General-interrupt-input interrupt Pending */
    + Diff = readl(php_ctlr->creg + INT_INPUT_CLEAR) ^ php_ctlr->ctrl_int_comp;
    +
    + php_ctlr->ctrl_int_comp = readl(php_ctlr->creg + INT_INPUT_CLEAR);
    +
    + writel(Diff, php_ctlr->creg + INT_INPUT_CLEAR); /* Clear the interrupt */
    +
    + /* Read it back to clear any posted writes */
    + temp_dword = readl(php_ctlr->creg + INT_INPUT_CLEAR);
    +
    + if (!Diff)
    + writel(0xFFFFFFFF, php_ctlr->creg + INT_INPUT_CLEAR); /* Clear all interrupts */
    +
    + if (php_ctlr->switch_change_callback)
    + schedule_flag += php_ctlr->switch_change_callback(
    + (Diff & 0xFFL), php_ctlr->callback_instance_id);
    + if (php_ctlr->presence_change_callback)
    + schedule_flag += php_ctlr->presence_change_callback(
    + ((Diff & 0xFFFF0000L) >> 16), php_ctlr->callback_instance_id);
    + if (php_ctlr->power_fault_callback)
    + schedule_flag += php_ctlr->power_fault_callback(
    + ((Diff & 0xFF00L) >> 8), php_ctlr->callback_instance_id);
    + }
    +
    + /* Setting bus speed is applicable only to Compaq HPC with rev >= 0x13
    + * or with subsystem_device == PCI_SUB_HPC_ID4
    + */
    + if ((ctrl->pci_dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) &&
    + ((ctrl->rev >= 0x13) || (ctrl->pci_dev->subsystem_device == PCI_SUB_HPC_ID4))) {
    + reset = readb(php_ctlr->creg + RESET_FREQ_MODE);
    + if (reset & 0x40) {
    + /* Bus reset has completed */
    + reset &= 0xCF;
    + writeb(reset, php_ctlr->creg + RESET_FREQ_MODE);
    + reset = readb(php_ctlr->creg + RESET_FREQ_MODE);
    + wake_up_interruptible(&ctrl->queue);
    + }
    + }
    + return IRQ_HANDLED;
    +}
    +
    +int phphpc_get_ctrl_cap(struct controller *ctrl, u16 * pctlrcap, u8 * prev)
    +{
    + u16 vendor_id;
    + u16 subsystem_vid;
    + u16 subsystem_did;
    + u32 rc;
    + u8 bus_cap;
    + struct pci_dev *pdev;
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
    +
    + DBG_ENTER_ROUTINE
    +
    + if (!ctrl->hpc_ctlr_handle) {
    + err("Process %d: Invalid HPC controller handle!\n", current->pid);
    + return -1;
    + }
    +
    + if (!pctlrcap) {
    + err("Process %d: Invalid HPC ctrlcap pointer passed in!\n", current->pid);
    + return -1;
    + }
    +
    + if (!prev) {
    + err("Process %d: Invalid HPC rev pointer passed in!\n", current->pid);
    + return -1;
    + }
    +
    + dbg("Pass in ctlrcap = %x\n", *pctlrcap);
    +
    + if (!php_ctlr->pci_dev) {
    + err("Process %d: Invalid HPC controller pci_dev!\n", current->pid);
    + return -1;
    + }
    +
    + pdev = php_ctlr->pci_dev;
    +
    + /* Need to read VID early b/c it's used to differentiate CPQ and INTC discovery */
    + vendor_id = pdev->vendor;
    + if ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL)) {
    + err ("%s: HPC controller(vendor=%x) not supported by this driver!\n", __FUNCTION__, vendor_id);
    + return -1;
    + }
    +
    + rc = pci_read_config_byte(pdev, PCI_REVISION_ID, prev);
    + dbg("Vendor ID: %x revision: %x\n", vendor_id, *prev);
    + if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!(*prev)))) {
    + err("%s: Unsupported revision of HPC controller found!\n", __FUNCTION__);
    + return -1;
    + }
    +
    + /*
    + * 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 ((*prev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
    + subsystem_vid = pdev->subsystem_vendor;
    + subsystem_did = pdev->subsystem_device;
    + dbg("Sub-Vendor ID: %x, Sub-Device ID: %x\n", subsystem_vid, subsystem_did);
    + if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
    + err("%s: HPC controller not supported by this driver!\n", __FUNCTION__);
    + return -1;
    + }
    +
    + /* Set Default values of "0" for everything */
    + *pctlrcap = 0;
    +
    + /*
    + * Interpretation of bit pattern in *pctlrcap
    + * Based on Intel PHPC SSVID/SID Programming Model
    + * Bit 0 Speed_capability: 0 = 33MHz, 1 = 66MHz
    + * Bit 1 Push_button : 0 = pushbutton present, 1 = no pushbutton
    + * Bit 2 Slot_switch_type: 0 = switch present, 1 = no switch
    + * Bit 3 DeFeature PHP: 0 = PHP not supported, 1 = PHP supported
    + * Bit 4 Alternate_base_address: 0 = not supported, 1 = supported
    + * Bit 5 PCI_config_space: Index/data access to working registers
    + * 0 = not supported, 1 = supported
    + * Bit 6 PCIX_speed: 0 = 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
    + * 1 = 133MHz PCI-X if Bit 7 is 1
    + * Bit 7 PCIX_support: 0 = conventional PCI, 1 = PCI-X
    + * Bit 8-15 Reserved
    + */
    + if (subsystem_vid == PCI_VENDOR_ID_COMPAQ) {
    + switch ( *prev >= 0x13) {
    + case 0:
    + if (subsystem_did == PCI_SUB_HPC_ID) {
    + *pctlrcap = 0x2A; /* sw, 33, no pb, no pcix */
    + break;
    + } else if (subsystem_did == PCI_SUB_HPC_ID2) {
    + *pctlrcap = 0x28; /* sw, 33, pb, no pcix */
    + break;
    + } else if (subsystem_did == PCI_SUB_HPC_ID_INTC) {
    + *pctlrcap = 0x2A; /* sw, 33, no pb, no pcix */
    + break;
    + } else if (subsystem_did == PCI_SUB_HPC_ID3) {
    + *pctlrcap = 0x29; /* sw, 66, pb, no pcix */
    + break;
    + } else if (subsystem_did == PCI_SUB_HPC_ID4) {
    + *pctlrcap = 0xA8; /* sw, 100, pb, pcix */
    + break;
    + } else {
    + err("%s: unsupported Sub-Device ID: %x\n", __FUNCTION__, subsystem_did);
    + php_ctlr->ctlrcap = 0;
    + return -1;
    + }
    + case 1: /* True for CIOBX */
    + pci_read_config_byte(pdev, 0x41, &bus_cap);
    + if (bus_cap & 0x80) {
    + *pctlrcap = 0xE8; /* sw, 133, pb, pcix */
    + break;
    + } else if (bus_cap & 0x40) {
    + *pctlrcap = 0xA8; /* sw, 100, pb, pcix */
    + break;
    + } else if (bus_cap & 0x20) {
    + *pctlrcap = 0xA9; /* sw, 66, pb, pcix */
    + break;
    + } else if (bus_cap & 0x10) {
    + *pctlrcap = 0x29; /* sw, 100, pb, no pcix */
    + break;
    + } else {
    + *pctlrcap = 0xA9; /* default to sw, 66, pb, pcix */
    + break;
    + }
    + }
    + } else if (subsystem_vid == PCI_VENDOR_ID_INTEL) {
    + *pctlrcap = subsystem_did;
    + } else
    + err("%s: unsupported Sub-Vendor ID: %x\n", __FUNCTION__, subsystem_vid);
    +
    + php_ctlr->ctlrcap = *pctlrcap;
    + }
    +
    + dbg("ctlrcap = %x\n", *pctlrcap);
    +
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
    +{
    + enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    +
    + DBG_ENTER_ROUTINE
    + if (!slot->ctrl->hpc_ctlr_handle) {
    + err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
    + return -1;
    + }
    +
    + /* PCI-X support */
    + if (php_ctlr->ctlrcap & 0x0080) {
    + /* Frequency of operation in PCI-X mode */
    + if (php_ctlr->ctlrcap & 0x0040) {
    + bus_speed = PCI_SPEED_133MHz_PCIX;
    + } else {
    + if (php_ctlr->ctlrcap & 0x0001)
    + bus_speed = PCI_SPEED_66MHz_PCIX;
    + else
    + bus_speed = PCI_SPEED_100MHz_PCIX;
    + }
    + } else {
    + if (php_ctlr->ctlrcap & 0x0001)
    + bus_speed = PCI_SPEED_66MHz;
    + else
    + bus_speed = PCI_SPEED_33MHz;
    + }
    +
    + *value = bus_speed;
    +
    + dbg("Supported bus speed = %d\n", bus_speed);
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
    +{
    + u8 adapter_speed = PCI_SPEED_UNKNOWN;
    + u8 m66cap, pcixcap1, pcixcap2;
    + u8 temp_byte;
    +
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    +
    + DBG_ENTER_ROUTINE
    + if (!slot->ctrl->hpc_ctlr_handle) {
    + err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
    + return -1;
    + }
    +
    + if (slot->hp_slot >= php_ctlr->num_slots) {
    + err("%s: Invalid HPC slot number!\n", __FUNCTION__);
    + return -1;
    + }
    +
    + down(&slot->ctrl->crit_sect);
    +
    + /* turn on board without attaching to the bus */
    + temp_byte = readb(php_ctlr->creg + SLOT_POWER);
    + temp_byte |= (0x01 << slot->hp_slot);
    + writeb(temp_byte, php_ctlr->creg + SLOT_POWER);
    +
    + hpc_update_hpc(slot);
    +
    + /* Change bits in slot power register to force another shift out */
    + /* NOTE: this is to work around the timer bug */
    + temp_byte = readb(php_ctlr->creg + SLOT_POWER);
    + writeb(0x00, php_ctlr->creg + SLOT_POWER);
    + writeb(temp_byte, php_ctlr->creg + SLOT_POWER);
    +
    + hpc_update_hpc(slot);
    +
    + longdelay(6 * (HZ / 10));
    +
    + m66cap = readl(php_ctlr->creg + NON_INT_INPUT) & 0xff;
    + pcixcap1 = (readl(php_ctlr->creg + NON_INT_INPUT) >> 8) & 0xff;
    + pcixcap2 = (readl(php_ctlr->creg + NON_INT_INPUT) >> 16) & 0xff;
    + dbg("m66cap = %x\n", m66cap);
    +
    + if (php_ctlr->ctlrcap & PCIXSupport) {
    + if ((pcixcap1 >> slot->hp_slot) & 1) {
    + if ((pcixcap2 >> slot->hp_slot) & 1)
    + adapter_speed = PCI_SPEED_133MHz_PCIX;
    + else
    + adapter_speed = PCI_SPEED_66MHz_PCIX;
    + } else {
    + if ((m66cap >> slot->hp_slot) & 1)
    + adapter_speed = PCI_SPEED_66MHz;
    + else
    + adapter_speed = PCI_SPEED_33MHz;
    + }
    + } else {
    + if ((m66cap >> slot->hp_slot) & 1)
    + adapter_speed = PCI_SPEED_66MHz;
    + else
    + adapter_speed = PCI_SPEED_33MHz;
    + }
    +
    + /* turn off board without attaching to the bus */
    + temp_byte = readb(php_ctlr->creg + SLOT_POWER);
    + temp_byte &= ~(0x01 << slot->hp_slot);
    + writeb(temp_byte, php_ctlr->creg + SLOT_POWER);
    +
    + hpc_update_hpc(slot);
    +
    + /* Done with exclusive hardware access */
    + up(&slot->ctrl->crit_sect);
    +
    + *value = adapter_speed;
    + dbg("Adapter speed = %d\n", adapter_speed);
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
    +{
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    + u32 pci_misc_config;
    + enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
    + u16 temp_word;
    + u32 temp_dword;
    + struct pci_dev *dev;
    + u8 curr_freq;
    + struct controller *ctrl;
    +
    + DBG_ENTER_ROUTINE
    + if (!slot->ctrl->hpc_ctlr_handle || !php_ctlr->pci_dev) {
    + err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
    + return -1;
    + }
    +
    + ctrl = slot->ctrl;
    +
    + if ((php_ctlr->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
    + (php_ctlr->pci_dev->device == PCI_INTC_P64H2_DID)) {
    +
    + /*
    + * For P64H2 hpc, bus speed is determined by P64H2_HUB
    + * Let's find P64H2_HUB on this bus.
    + */
    + dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_INTC_P64H2_HUB_PCI, PCI_ANY_ID, PCI_ANY_ID, NULL);
    + if (dev == NULL)
    + info("Can't find VID-0x8086 DID-0x1460\n");
    +
    + while (dev != NULL) {
    + pci_read_config_word(dev, 0x40, &temp_word);
    + pci_read_config_dword(dev, 0x18, &temp_dword);
    + dbg("%s: bus=%x dev=%x, CNF=%x, BNUM=%x\n", __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), temp_word, temp_dword);
    + if (((temp_dword & 0x0000ff00) >> 8) == php_ctlr->pci_dev->bus->number) {
    + if ((temp_word & 0x0100) == 0x0100) {
    + if ((temp_word & 0x00c0) == 0x00c0)
    + bus_speed = PCI_SPEED_133MHz_PCIX;
    + else if ((temp_word & 0x0080) == 0x0080)
    + bus_speed = PCI_SPEED_100MHz_PCIX;
    + else if ((temp_word & 0x0040) == 0x0040)
    + bus_speed = PCI_SPEED_66MHz_PCIX;
    + } else {
    + if ((temp_word & 0x0040) == 0x0040)
    + bus_speed = PCI_SPEED_66MHz;
    + else if ((temp_word & 0x00c0) == 0)
    + bus_speed = PCI_SPEED_33MHz;
    + }
    + break;
    + }
    + dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_INTC_P64H2_HUB_PCI, PCI_ANY_ID, PCI_ANY_ID, dev);
    + }
    + } else {
    + if (php_ctlr->ctlrcap & PCIXSupport) {
    + if ((ctrl->pci_dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) &&
    + ((ctrl->rev >= 0x13) || (ctrl->pci_dev->subsystem_device == PCI_SUB_HPC_ID4))) {
    + /* for Compaq CIOBX or PCI_SUB_HPC_ID4 */
    + curr_freq = readb(php_ctlr->creg + NEXT_CURR_FREQ);
    + if ((curr_freq & 0xB0) == 0xB0)
    + bus_speed = PCI_SPEED_133MHz_PCIX;
    + else if ((curr_freq & 0xA0) == 0xA0)
    + bus_speed = PCI_SPEED_100MHz_PCIX;
    + else if ((curr_freq & 0x90) == 0x90)
    + bus_speed = PCI_SPEED_66MHz_PCIX;
    + else if ((curr_freq & 0x10) == 0x10)
    + bus_speed = PCI_SPEED_66MHz;
    + else bus_speed = PCI_SPEED_33MHz;
    + } else { /* all others */
    +
    + pci_read_config_dword(php_ctlr->pci_dev, 0x40, &pci_misc_config);
    + /* Read HPC PCI Misc. Configuration at offset 40h */
    +
    + dbg("HPC PCI Misc Config = %x\n", pci_misc_config);
    +
    + if (pci_misc_config & 0x00200000) { /* Bit 21 of PCI Misc. Config. */
    + if (readw(php_ctlr->creg + MISC) & 0x8000) { /* Bit 31 - 133 MHZ Prescale indicator */
    + if (readw(php_ctlr->creg + MISC) & 0x0040) /* Bit 22 - frequency range bit */
    + bus_speed = PCI_SPEED_133MHz_PCIX;
    + else
    + bus_speed = PCI_SPEED_100MHz_PCIX;
    + } else
    + bus_speed = PCI_SPEED_66MHz_PCIX;
    + } else {
    + if (readw(php_ctlr->creg + MISC) & 0x0800) /* Bit 27 - 66MHZ Prescale indicator */
    + bus_speed = PCI_SPEED_66MHz;
    + else
    + bus_speed = PCI_SPEED_33MHz;
    + }
    + }
    + } else {
    + if (readw(php_ctlr->creg + MISC) & 0x0800) /* Bit 27 - 66MHZ Prescale indicator */
    + bus_speed = PCI_SPEED_66MHz;
    + else
    + bus_speed = PCI_SPEED_33MHz;
    + }
    + }
    +
    + *value = bus_speed;
    + dbg("Current bus speed = %d\n", bus_speed);
    + DBG_LEAVE_ROUTINE
    + return 0;
    +}
    +
    +static int hpc_set_controller_speed (struct slot *slot, enum pci_bus_speed value)
    +{
    + struct slot *p_slot;
    + struct controller *ctrl;
    + u8 reg, adapter_speed;
    + u8 slot_power, hp_slot;
    + u16 reg16;
    + u32 leds;
    +
    + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
    +
    + DBG_ENTER_ROUTINE
    + if (!slot->ctrl->hpc_ctlr_handle) {
    + err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
    + return -1;
    + }
    +
    + ctrl = slot->ctrl;
    + hp_slot = slot->hp_slot;
    + slot_power = readb(php_ctlr->creg + SLOT_POWER);
    + leds = readl(php_ctlr->creg + LED_CONTROL);
    + adapter_speed = value;
    +
    + /* We don't allow freq/mode changes if we find another adapter running
    + * in another slot on this controller */
    + for(p_slot = ctrl->slot; p_slot; p_slot = p_slot->next) {
    + if (p_slot->device == (hp_slot + ctrl->slot_device_offset))
    + continue;
    + if (!p_slot->hotplug_slot && !p_slot->hotplug_slot->info)
    + continue;
    + if (p_slot->hotplug_slot->info->adapter_status == 0)
    + continue;
    + /* If another adapter is running on the same segment but at a
    + * lower speed/mode, we allow the new adapter to function at
    + * this rate if supported */
    + if (ctrl->speed < adapter_speed)
    + return 0;
    +
    + return 1;
    + }
    +
    + /* We try to set the max speed supported by both the adapter and
    + * controller */
    + if (ctrl->speed_capability < adapter_speed) {
    + if (ctrl->speed == ctrl->speed_capability)
    + return 0;
    + adapter_speed = ctrl->speed_capability;
    + }
    +
    + writel(0x0L, php_ctlr->creg + LED_CONTROL);
    + writeb(0x00, php_ctlr->creg + SLOT_ENABLE);
    +
    + hpc_update_hpc(slot);
    +
    + if (adapter_speed != PCI_SPEED_133MHz_PCIX)
    + reg = 0xF5;
    + else
    + reg = 0xF4;
    + pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
    +
    + reg16 = readw(php_ctlr->creg + NEXT_CURR_FREQ);
    + reg16 &= ~0x000F;
    + switch(adapter_speed) {
    + case(PCI_SPEED_133MHz_PCIX):
    + reg = 0x75;
    + reg16 |= 0xB;
    + break;
    + case(PCI_SPEED_100MHz_PCIX):
    + reg = 0x74;
    + reg16 |= 0xA;
    + break;
    + case(PCI_SPEED_66MHz_PCIX):
    + reg = 0x73;
    + reg16 |= 0x9;
    + break;
    + case(PCI_SPEED_66MHz):
    + reg = 0x73;
    + reg16 |= 0x1;
    + break;
    + default: /* 33MHz PCI 2.2 */
    + reg = 0x71;
    + break;
    +
    + }
    + reg16 |= 0xB << 12;
    + writew(reg16, php_ctlr->creg + NEXT_CURR_FREQ);
    +
    + mdelay(5);
    +
    + /* Reenable interrupts */
    + writel(0, php_ctlr->creg + INT_MASK);
    +
    + pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
    +
    + /* Restart state machine */
    + reg = ~0xF;
    + pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
    + pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
    +
    + /* Only if mode change...*/
    + if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
    + ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz)))
    + hpc_update_hpc(slot);
    +
    + mdelay(1100);
    +
    + /* Restore LED/Slot state */
    + writel(leds, php_ctlr->creg + LED_CONTROL);
    + writeb(slot_power, php_ctlr->creg + SLOT_ENABLE);
    +
    + hpc_update_hpc(slot);
    +
    + ctrl->speed = adapter_speed;
    + slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
    +
    + info("Successfully changed frequency/mode for adapter in slot %d\n",
    + slot->number);
    + return 0;
    +}
    +
    +static struct hpc_ops cpqphp_hpc_ops = {
    + .power_on_slot = hpc_power_on_slot,
    + .power_off_slot = hpc_power_off_slot,
    + .set_attention_status = hpc_set_attention_status,
    + .get_power_status = hpc_get_power_status,
    + .get_attention_status = hpc_get_attention_status,
    + .get_latch_status = hpc_get_latch_status,
    + .get_adapter_status = hpc_get_adapter_status,
    +
    + .get_max_bus_speed = hpc_get_max_bus_speed,
    + .get_cur_bus_speed = hpc_get_cur_bus_speed,
    + .get_adapter_speed = hpc_get_adapter_speed,
    + .set_controller_speed = hpc_set_controller_speed,
    +
    + .get_slot_capability = hpc_get_slot_capability,
    + .query_power_fault = hpc_query_power_fault,
    + .green_led_on = hpc_green_led_on,
    + .green_led_off = hpc_green_led_off,
    + .green_led_blink = hpc_green_led_blink,
    +
    + .enable_msl_interrupt = hpc_enable_msl_interrupt,
    + .update_hpc = hpc_update_hpc,
    + .release_ctlr = hpc_release_ctlr,
    +};
    +
    +int phphpc_init(struct controller * ctrl,
    + struct pci_dev * pdev,
    + php_intr_callback_t switch_change_callback,
    + php_intr_callback_t presence_change_callback,
    + php_intr_callback_t power_fault_callback)
    +{
    + struct php_ctlr_state_s *php_ctlr, *p;
    + void *instance_id = ctrl;
    + unsigned long psw;
    + int rc;
    + u16 temp_word, misc;
    + static int first = 1;
    +
    + DBG_ENTER_ROUTINE
    + php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
    +
    + if (!php_ctlr) { /* allocate controller state data */
    + err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
    + goto abort;
    + }
    +
    + memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
    +
    + php_ctlr->pci_dev = pdev; /* save pci_dev in context */
    +
    + if (first) {
    + spin_lock_init(&hpc_event_lock);
    + first = 0;
    + }
    +
    + dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq);
    + for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
    + if (pci_resource_len(pdev, rc) > 0)
    + dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
    + pci_resource_start(pdev, rc), pci_resource_len(pdev, rc));
    + info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device);
    +
    + if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), MY_NAME)) {
    + err("%s: cannot reserve MMIO region\n", __FUNCTION__);
    + goto abort_free_ctlr;
    + }
    +
    + php_ctlr->creg = (struct ctrl_reg *)
    + ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
    + if (!php_ctlr->creg) {
    + err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
    + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
    + goto abort_free_ctlr;
    + }
    +
    + init_MUTEX(&ctrl->crit_sect);
    + /* setup wait queue */
    + init_waitqueue_head(&ctrl->queue);
    +
    + /* find the IRQ */
    + php_ctlr->irq = pdev->irq;
    + dbg("HPC interrupt = %d\n", php_ctlr->irq);
    +
    + /* Save interrupt callback info */
    + php_ctlr->switch_change_callback = switch_change_callback;
    + php_ctlr->presence_change_callback = presence_change_callback;
    + php_ctlr->power_fault_callback = power_fault_callback;
    + php_ctlr->callback_instance_id = instance_id;
    +
    + /* return PCI Controller Info */
    + php_ctlr->first_device_num = readb(php_ctlr->creg + SLOT_MASK) >> 4;
    + php_ctlr->num_slots = readb(php_ctlr->creg + SLOT_MASK) & 0xF;
    +
    + /* Mask all general input interrupts */
    + writel(0xFFFFFFFFL, php_ctlr->creg + INT_MASK);
    +
    + /*Disable interrupts */
    + spin_lock_irqsave(&hpc_event_lock, psw);
    +
    + /*this code installs the interrupt handler */
    + rc = request_irq(php_ctlr->irq, hpc_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
    + dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
    +
    + if ((php_ctlr->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
    + (php_ctlr->pci_dev->device == PCI_INTC_P64H2_DID)) {
    + /*
    + * If this is the Intel Tiger IA64 platform, Read the ABAR config
    + * space register and clear bit 14 to assure HPC uses normal
    + * interrupts, NOT SCI interrupt.
    + */
    + rc = pci_read_config_word(pdev, 0x80, &temp_word);
    + dbg("ABAR reads %x\n", temp_word);
    + temp_word = temp_word & 0xBFFF;
    + rc |= pci_write_config_word(pdev, 0x80, temp_word);
    + pci_read_config_word(pdev, 0x80, &temp_word);
    + if (rc || (temp_word & ~0xBFFF))
    + err("Unable to set ABAR[%x] rc = %d\n", temp_word, rc);
    + else
    + dbg("ABAR set to %x\n", temp_word);
    + }
    +
    + /* Re-enable interrupts */
    + spin_unlock_irqrestore(&hpc_event_lock, psw);
    +
    + /* Enable Shift Out interrupt and clear it, also */
    + /* enable SERR on power fault */
    + misc = readw(php_ctlr->creg + MISC);
    + misc |= 0x6006;
    + writew(misc, php_ctlr->creg + MISC);
    +
    + /* Changed 05/05/97 to clear all interrupts at start */
    + writel(0xFFFFFFFF, php_ctlr->creg + INT_INPUT_CLEAR);
    +
    + php_ctlr->ctrl_int_comp = readl(php_ctlr->creg + INT_INPUT_CLEAR);
    +
    + writel(0x0L, php_ctlr->creg + INT_MASK);
    + /*
    + * Initialize the per slot SERR for unexpected switch open to 0
    + * If the bit is et to 1, slot switch interrupt causes the SERR# pin
    + * to be asserted.
    + */
    + writeb(0, php_ctlr->creg + SLOT_SERR);
    +
    + /* Add this HPC instance into the HPC list */
    + /* TO DO: Do we need to spinlock this? */
    + if (php_ctlr_list_head == 0) {
    + php_ctlr_list_head = php_ctlr;
    + p = php_ctlr_list_head;
    + p->pnext = 0;
    + } else {
    + p = php_ctlr_list_head;
    +
    + while (p->pnext)
    + p = p->pnext;
    +
    + p->pnext = php_ctlr;
    + }
    +
    + ctlr_seq_num++;
    + ctrl->hpc_ctlr_handle = php_ctlr;
    + ctrl->hpc_ops = &cpqphp_hpc_ops;
    +
    + DBG_LEAVE_ROUTINE
    + return 0;
    +
    + /* We end up here for the many possible ways to fail this API. */
    +abort_free_ctlr:
    + kfree(php_ctlr);
    +abort:
    + DBG_LEAVE_ROUTINE
    + return -1;
    +}
    diff -Nru a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
    --- a/drivers/pci/hotplug/cpqphp_pci.c 2003-07-02 13:56:02.000000000 -0700
    +++ b/drivers/pci/hotplug/cpqphp_pci.c 2003-07-07 09:32:23.000000000 -0700
    @@ -36,50 +36,9 @@
    #include <linux/pci.h>
    #include "../pci.h"
    #include "cpqphp.h"
    -#include "cpqphp_nvram.h"
    -#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependent we are... */
    -
    -
    -u8 cpqhp_nic_irq;
    -u8 cpqhp_disk_irq;
    -
    -static u16 unused_IRQ;
    -
    -/*
    - * detect_HRT_floating_pointer
    - *
    - * find the Hot Plug Resource Table in the specified region of memory.
    - *
    - */
    -static void *detect_HRT_floating_pointer(void *begin, void *end)
    -{
    - void *fp;
    - void *endp;
    - u8 temp1, temp2, temp3, temp4;
    - int status = 0;
    -
    - endp = (end - sizeof(struct hrt) + 1);
    -
    - for (fp = begin; fp <= endp; fp += 16) {
    - temp1 = readb(fp + SIG0);
    - temp2 = readb(fp + SIG1);
    - temp3 = readb(fp + SIG2);
    - temp4 = readb(fp + SIG3);
    - if (temp1 == '$' &&
    - temp2 == 'H' &&
    - temp3 == 'R' &&
    - temp4 == 'T') {
    - status = 1;
    - break;
    - }
    - }
    -
    - if (!status)
    - fp = NULL;
    -
    - dbg("Discovered Hotplug Resource Table at %p\n", fp);
    - return fp;
    -}
    +#ifndef CONFIG_IA64
    +#include "../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
    +#endif


    int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
    @@ -93,7 +52,7 @@

    /* No pci device, we need to create it then */
    if (func->pci_dev == NULL) {
    - dbg("INFO: pci_dev still null\n");
    + dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);

    num = pci_scan_slot(ctrl->pci_dev->bus, PCI_DEVFN(func->device, func->function));
    if (num)
    @@ -118,29 +77,37 @@

    int cpqhp_unconfigure_device(struct pci_func* func)
    {
    + int rc = 0;
    int j;
    -
    +
    +
    dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function);

    for (j=0; j<8 ; j++) {
    struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j);
    - if (temp)
    + if (temp) {
    pci_remove_bus_device(temp);
    + }
    }
    - return 0;
    + return rc;
    }

    static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value)
    {
    u32 vendID = 0;
    + int rc;
    +
    + rc = pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID);

    - if (pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
    + if (rc == -1)
    return -1;
    if (vendID == 0xffffffff)
    return -1;
    - return pci_bus_read_config_dword (bus, devfn, offset, value);
    -}

    + rc = pci_bus_read_config_dword (bus, devfn, offset, value);
    +
    + return rc;
    +}

    /*
    * cpqhp_set_irq
    @@ -151,6 +118,7 @@
    */
    int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
    {
    +#if defined(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM) && defined(CONFIG_X86)
    int rc;
    u16 temp_word;
    struct pci_dev fakedev;
    @@ -166,60 +134,53 @@
    if (!rc)
    return !rc;

    - // set the Edge Level Control Register (ELCR)
    + /* set the Edge Level Control Register (ELCR) */
    temp_word = inb(0x4d0);
    temp_word |= inb(0x4d1) << 8;

    temp_word |= 0x01 << irq_num;

    - // This should only be for x86 as it sets the Edge Level Control Register
    + /* This should only be for x86 as it sets the Edge Level Control Register */
    outb((u8) (temp_word & 0xFF), 0x4d0);
    outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
    -
    +#endif
    return 0;
    }


    -/*
    - * WTF??? This function isn't in the code, yet a function calls it, but the
    - * compiler optimizes it away? strange. Here as a placeholder to keep the
    - * compiler happy.
    - */
    -static int PCI_ScanBusNonBridge (u8 bus, u8 device)
    -{
    - return 0;
    -}

    -static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num)
    +static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 * bus_num, u8 * dev_num)
    {
    u8 tdevice;
    u32 work;
    u8 tbus;
    + struct pci_bus lpci_bus, *pci_bus;

    - ctrl->pci_bus->number = bus_num;
    + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
    + pci_bus = &lpci_bus;
    + pci_bus->number = *bus_num;

    - for (tdevice = 0; tdevice < 0xFF; tdevice++) {
    - //Scan for access first
    - if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
    + for (tdevice = 0; tdevice < 0x100; tdevice++) {
    + if (PCI_RefinedAccessConfig (pci_bus, tdevice, 0x08, &work) == -1)
    continue;
    - dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
    - //Yep we got one. Not a bridge ?
    + dbg("Looking for nonbridge bus_num %d dev_num %d\n", *bus_num, tdevice);
    if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) {
    *dev_num = tdevice;
    dbg("found it !\n");
    return 0;
    }
    }
    - for (tdevice = 0; tdevice < 0xFF; tdevice++) {
    - //Scan for access first
    - if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
    + for (tdevice = 0; tdevice < 0x100; tdevice++) {
    + if (PCI_RefinedAccessConfig (pci_bus, tdevice, 0x08, &work) == -1)
    continue;
    - dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
    - //Yep we got one. bridge ?
    + dbg("Looking for bridge bus_num %d dev_num %d\n", *bus_num, tdevice);
    if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
    - pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
    - dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
    - if (PCI_ScanBusNonBridge(tbus, tdevice) == 0)
    + pci_bus_read_config_byte(pci_bus, tdevice, PCI_SECONDARY_BUS, &tbus);
    +
    + dbg("Found a new bus %d on bus %d device %d\n", tbus, *bus_num, tdevice);
    + dbg("Recurse on the new bus %d\n", tbus);
    + *bus_num = tbus;
    + if (PCI_ScanBusForNonBridge(ctrl, bus_num, dev_num) == 0)
    return 0;
    }
    }
    @@ -227,75 +188,59 @@
    return -1;
    }

    -
    -static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge)
    +static int PCI_GetBusDevHelper(struct controller *ctrl, u8 * bus_num, u8 * dev_num,
    + struct slot *slot, u8 nobridge)
    {
    - struct irq_routing_table *PCIIRQRoutingInfoLength;
    - long len;
    long loop;
    u32 work;
    + u8 tbus, tdevice;
    + struct pci_bus lpci_bus, *pci_bus;
    + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
    + pci_bus = &lpci_bus;
    +
    + dbg("GetBusDev: bus %d dev %d func %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
    + for (loop = 0; loop < 8; ++loop) {
    + tbus = slot->bus;
    + tdevice = slot->device << 3 | loop;
    +
    + *bus_num = tbus;
    + *dev_num = tdevice;
    + pci_bus->number = tbus;

    - u8 tbus, tdevice, tslot;
    + pci_bus_read_config_dword(pci_bus, *dev_num, PCI_VENDOR_ID, &work);

    - PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();
    - if (!PCIIRQRoutingInfoLength)
    - return -1;
    + if (!nobridge || (work == 0xffffffff)) {
    + dbg("GetBusDev: nodev bus %d dev %d func %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
    + return 0;
    + }

    - len = (PCIIRQRoutingInfoLength->size -
    - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
    - // Make sure I got at least one entry
    - if (len == 0) {
    - if (PCIIRQRoutingInfoLength != NULL)
    - kfree(PCIIRQRoutingInfoLength );
    - return -1;
    - }
    + dbg("bus_num %d dev_num %d func_num %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);

    - for (loop = 0; loop < len; ++loop) {
    - tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
    - tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn;
    - tslot = PCIIRQRoutingInfoLength->slots[loop].slot;
    + pci_bus_read_config_dword(pci_bus, *dev_num, PCI_CLASS_REVISION, &work);

    - if (tslot == slot) {
    - *bus_num = tbus;
    - *dev_num = tdevice;
    - ctrl->pci_bus->number = tbus;
    - pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
    - if (!nobridge || (work == 0xffffffff)) {
    - if (PCIIRQRoutingInfoLength != NULL)
    - kfree(PCIIRQRoutingInfoLength );
    - return 0;
    - }
    + dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);

    - dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
    - pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
    - dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);
    -
    - if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
    - pci_bus_read_config_byte (ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
    - dbg("Scan bus for Non Bridge: bus %d\n", tbus);
    - if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
    - *bus_num = tbus;
    - if (PCIIRQRoutingInfoLength != NULL)
    - kfree(PCIIRQRoutingInfoLength );
    - return 0;
    - }
    - } else {
    - if (PCIIRQRoutingInfoLength != NULL)
    - kfree(PCIIRQRoutingInfoLength );
    - return 0;
    - }
    + if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {

    - }
    + pci_bus_read_config_byte(pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
    +
    + dbg("Scan bus for Non Bridge: bus %d\n", tbus);
    + *bus_num = tbus;
    + if (PCI_ScanBusForNonBridge(ctrl, bus_num, dev_num) == 0)
    + return 0;
    + else
    + dbg("no Non Bridge under bus %d\n", tbus);
    + } else
    + return 0;
    }
    - if (PCIIRQRoutingInfoLength != NULL)
    - kfree(PCIIRQRoutingInfoLength );
    +
    + dbg("GetBusDev: fail bus %d dev %d func %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7);
    return -1;
    }

    -
    -int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot)
    +int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, struct slot *slot)
    {
    - return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0); //plain (bridges allowed)
    + return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0); /*plain (bridges allowed) */
    }


    @@ -311,9 +256,9 @@
    *
    * returns 0 if success
    */
    -int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
    +int cpqhp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
    {
    - long rc;
    + int rc;
    u8 class_code;
    u8 header_type;
    u32 ID;
    @@ -329,36 +274,46 @@
    int cloop = 0;
    int stop_it;
    int index;
    + int is_hot_plug = num_ctlr_slots || first_device_num;
    + struct pci_bus lpci_bus, *pci_bus;
    + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
    + pci_bus = &lpci_bus;

    - // Decide which slots are supported
    + dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num);

    + /* Decide which slots are supported */
    if (is_hot_plug) {
    - //*********************************
    - // is_hot_plug is the slot mask
    - //*********************************
    - FirstSupported = is_hot_plug >> 4;
    - LastSupported = FirstSupported + (is_hot_plug & 0x0F) - 1;
    + /*********************************
    + is_hot_plug is the slot mask
    + *********************************/
    + FirstSupported = first_device_num;
    + LastSupported = FirstSupported + num_ctlr_slots - 1;
    } else {
    FirstSupported = 0;
    LastSupported = 0x1F;
    }

    - // Save PCI configuration space for all devices in supported slots
    - ctrl->pci_bus->number = busnumber;
    + dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported);
    +
    + /* Save PCI configuration space for all devices in supported slots */
    + pci_bus->number = busnumber;
    for (device = FirstSupported; device <= LastSupported; device++) {
    ID = 0xFFFFFFFF;
    - rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
    + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);

    - if (ID != 0xFFFFFFFF) { // device in slot
    - rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
    + if (ID != 0xFFFFFFFF) { /* device in slot */
    + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code);
    +
    if (rc)
    return rc;

    - rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
    + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type);
    if (rc)
    return rc;

    - // If multi-function device, set max_functions to 8
    + dbg("class_code = %x, header_type = %x\n", class_code, header_type);
    +
    + /* If multi-function device, set max_functions to 8 */
    if (header_type & 0x80)
    max_functions = 8;
    else
    @@ -369,33 +324,36 @@
    do {
    DevError = 0;

    - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // P-P Bridge
    - // Recurse the subordinate bus
    - // get the subordinate bus number
    - rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
    + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
    + /* Recurse the subordinate bus
    + get the subordinate bus number */
    + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus);
    if (rc) {
    return rc;
    } else {
    sub_bus = (int) secondary_bus;

    - // Save secondary bus cfg spc
    - // with this recursive call.
    - rc = cpqhp_save_config(ctrl, sub_bus, 0);
    + /* Save secondary bus cfg spc
    + with this recursive call. */
    + rc = cpqhp_save_config(ctrl, sub_bus, 0, 0);
    if (rc)
    return rc;
    - ctrl->pci_bus->number = busnumber;
    }
    }

    index = 0;
    new_slot = cpqhp_slot_find(busnumber, device, index++);
    - while (new_slot &&
    - (new_slot->function != (u8) function))
    - new_slot = cpqhp_slot_find(busnumber, device, index++);

    + dbg("new_slot = %p\n", new_slot);
    +
    + while (new_slot && (new_slot->function != (u8) function)) {
    + new_slot = cpqhp_slot_find(busnumber, device, index++);
    + dbg("new_slot = %p\n", new_slot);
    + }
    if (!new_slot) {
    - // Setup slot structure.
    + /* Setup slot structure. */
    new_slot = cpqhp_slot_create(busnumber);
    + dbg("new_slot = %p\n", new_slot);

    if (new_slot == NULL)
    return(1);
    @@ -406,12 +364,15 @@
    new_slot->function = (u8) function;
    new_slot->is_a_board = 1;
    new_slot->switch_save = 0x10;
    - // In case of unsupported board
    + /* In case of unsupported board */
    new_slot->status = DevError;
    new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
    + dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);

    for (cloop = 0; cloop < 0x20; cloop++) {
    - rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
    + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot->config_space [cloop]));
    +
    + /*dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */
    if (rc)
    return rc;
    }
    @@ -420,35 +381,40 @@

    stop_it = 0;

    - // this loop skips to the next present function
    - // reading in Class Code and Header type.
    + /* this loop skips to the next present function
    + reading in Class Code and Header type. */

    while ((function < max_functions)&&(!stop_it)) {
    - rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
    - if (ID == 0xFFFFFFFF) { // nothing there.
    + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID);
    +
    + if (ID == 0xFFFFFFFF) { /* nothing there. */
    function++;
    - } else { // Something there
    - rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
    + dbg("Nothing there\n");
    + } else { /* Something there */
    +
    + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code);
    if (rc)
    return rc;

    - rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
    + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type);
    if (rc)
    return rc;

    + dbg("class_code = %x, header_type = %x\n", class_code, header_type);
    stop_it++;
    }
    }

    } while (function < max_functions);
    - } // End of IF (device in slot?)
    + } /* End of IF (device in slot?) */
    else if (is_hot_plug) {
    - // Setup slot structure with entry for empty slot
    + /* Setup slot structure with entry for empty slot */
    new_slot = cpqhp_slot_create(busnumber);

    if (new_slot == NULL) {
    return(1);
    }
    + dbg("new_slot = %p\n", new_slot);

    new_slot->bus = (u8) busnumber;
    new_slot->device = (u8) device;
    @@ -457,7 +423,7 @@
    new_slot->presence_save = 0;
    new_slot->switch_save = 0;
    }
    - } // End of FOR loop
    + } /* End of FOR loop */

    return(0);
    }
    @@ -473,7 +439,7 @@
    */
    int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)
    {
    - long rc;
    + int rc;
    u8 class_code;
    u8 header_type;
    u32 ID;
    @@ -483,17 +449,21 @@
    int function;
    int cloop = 0;
    int stop_it;
    + struct pci_bus lpci_bus, *pci_bus;
    + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
    + pci_bus = &lpci_bus;
    + pci_bus->number = new_slot->bus;

    ID = 0xFFFFFFFF;

    - ctrl->pci_bus->number = new_slot->bus;
    - pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
    + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
    +
    + if (ID != 0xFFFFFFFF) { /* device in slot */
    + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);

    - if (ID != 0xFFFFFFFF) { // device in slot
    - pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
    - pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
    + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);

    - if (header_type & 0x80) // Multi-function device
    + if (header_type & 0x80) /* Multi-function device */
    max_functions = 8;
    else
    max_functions = 1;
    @@ -501,49 +471,47 @@
    function = 0;

    do {
    - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
    - // Recurse the subordinate bus
    - pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
    + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
    + /* Recurse the subordinate bus */
    + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);

    sub_bus = (int) secondary_bus;

    - // Save the config headers for the secondary bus.
    - rc = cpqhp_save_config(ctrl, sub_bus, 0);
    + /* Save the config headers for the secondary bus. */
    + rc = cpqhp_save_config(ctrl, sub_bus, 0, 0);
    +
    if (rc)
    return(rc);
    - ctrl->pci_bus->number = new_slot->bus;

    - } // End of IF
    + } /* End of IF */

    new_slot->status = 0;

    for (cloop = 0; cloop < 0x20; cloop++) {
    - pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
    + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot->config_space [cloop]));
    }

    function++;

    stop_it = 0;

    - // this loop skips to the next present function
    - // reading in the Class Code and the Header type.
    + /* this loop skips to the next present function
    + reading in the Class Code and the Header type. */

    while ((function < max_functions) && (!stop_it)) {
    - pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);
    + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);

    - if (ID == 0xFFFFFFFF) { // nothing there.
    + if (ID == 0xFFFFFFFF) { /* nothing there. */
    function++;
    - } else { // Something there
    - pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
    -
    - pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
    -
    + } else { /* Something there */
    + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);
    + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);
    stop_it++;
    }
    }

    } while (function < max_functions);
    - } // End of IF (device in slot?)
    + } /* End of IF (device in slot?) */
    else {
    return(2);
    }
    @@ -553,136 +521,6 @@


    /*
    - * cpqhp_save_base_addr_length
    - *
    - * Saves the length of all base address registers for the
    - * specified slot. this is for hot plug REPLACE
    - *
    - * returns 0 if success
    - */
    -int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)
    -{
    - u8 cloop;
    - u8 header_type;
    - u8 secondary_bus;
    - u8 type;
    - int sub_bus;
    - u32 temp_register;
    - u32 base;
    - u32 rc;
    - struct pci_func *next;
    - int index = 0;
    - struct pci_bus *pci_bus = ctrl->pci_bus;
    - unsigned int devfn;
    -
    - func = cpqhp_slot_find(func->bus, func->device, index++);
    -
    - while (func != NULL) {
    - pci_bus->number = func->bus;
    - devfn = PCI_DEVFN(func->device, func->function);
    -
    - // Check for Bridge
    - pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
    -
    - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
    - // PCI-PCI Bridge
    - pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
    -
    - sub_bus = (int) secondary_bus;
    -
    - next = cpqhp_slot_list[sub_bus];
    -
    - while (next != NULL) {
    - rc = cpqhp_save_base_addr_length(ctrl, next);
    -
    - if (rc)
    - return(rc);
    -
    - next = next->next;
    - }
    - pci_bus->number = func->bus;
    -
    - //FIXME: this loop is duplicated in the non-bridge case. The two could be rolled together
    - // Figure out IO and memory base lengths
    - for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
    - temp_register = 0xFFFFFFFF;
    - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
    - pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
    -
    - if (base) { // If this register is implemented
    - if (base & 0x01L) {
    - // IO base
    - // set base = amount of IO space requested
    - base = base & 0xFFFFFFFE;
    - base = (~base) + 1;
    -
    - type = 1;
    - } else {
    - // memory base
    - base = base & 0xFFFFFFF0;
    - base = (~base) + 1;
    -
    - type = 0;
    - }
    - } else {
    - base = 0x0L;
    - type = 0;
    - }
    -
    - // Save information in slot structure
    - func->base_length[(cloop - 0x10) >> 2] =
    - base;
    - func->base_type[(cloop - 0x10) >> 2] = type;
    -
    - } // End of base register loop
    -
    -
    - } else if ((header_type & 0x7F) == 0x00) { // PCI-PCI Bridge
    - // Figure out IO and memory base lengths
    - for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
    - temp_register = 0xFFFFFFFF;
    - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
    - pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
    -
    - if (base) { // If this register is implemented
    - if (base & 0x01L) {
    - // IO base
    - // base = amount of IO space requested
    - base = base & 0xFFFFFFFE;
    - base = (~base) + 1;
    -
    - type = 1;
    - } else {
    - // memory base
    - // base = amount of memory space requested
    - base = base & 0xFFFFFFF0;
    - base = (~base) + 1;
    -
    - type = 0;
    - }
    - } else {
    - base = 0x0L;
    - type = 0;
    - }
    -
    - // Save information in slot structure
    - func->base_length[(cloop - 0x10) >> 2] = base;
    - func->base_type[(cloop - 0x10) >> 2] = type;
    -
    - } // End of base register loop
    -
    - } else { // Some other unknown header type
    - }
    -
    - // find the next device in this slot
    - func = cpqhp_slot_find(func->bus, func->device, index++);
    - }
    -
    - return(0);
    -}
    -
    -
    -/*
    * cpqhp_save_used_resources
    *
    * Stores used resource information for existing boards. this is
    @@ -690,50 +528,62 @@
    * this function is for hot plug ADD
    *
    * returns 0 if success
    + * if disable == 1(DISABLE_CARD),
    + * it loops for all functions of the slot and disables them.
    + * else, it just get resources of the function and return.
    */
    -int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)
    +int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable)
    {
    u8 cloop;
    u8 header_type;
    u8 secondary_bus;
    u8 temp_byte;
    - u8 b_base;
    - u8 b_length;
    u16 command;
    u16 save_command;
    - u16 w_base;
    - u16 w_length;
    + u16 w_base, w_length;
    u32 temp_register;
    u32 save_base;
    - u32 base;
    + u32 base, length;
    + u64 base64 = 0;
    int index = 0;
    - struct pci_resource *mem_node;
    - struct pci_resource *p_mem_node;
    + unsigned int devfn;
    + struct pci_resource *mem_node = NULL;
    + struct pci_resource *p_mem_node = NULL;
    + struct pci_resource *t_mem_node;
    struct pci_resource *io_node;
    struct pci_resource *bus_node;
    - struct pci_bus *pci_bus = ctrl->pci_bus;
    - unsigned int devfn;
    + struct pci_bus lpci_bus, *pci_bus;
    + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
    + pci_bus = &lpci_bus;

    - func = cpqhp_slot_find(func->bus, func->device, index++);
    + if (disable)
    + func = cpqhp_slot_find(func->bus, func->device, index++);

    while ((func != NULL) && func->is_a_board) {
    pci_bus->number = func->bus;
    devfn = PCI_DEVFN(func->device, func->function);

    - // Save the command register
    + /* Save the command register */
    pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command);

    - // disable card
    - command = 0x00;
    - pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command);
    + if (disable) {
    + /* disable card */
    + command = 0x00;
    +
    + pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
    + }

    - // Check for Bridge
    + /* Check for Bridge */
    pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);

    - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
    - // Clear Bridge Control Register
    - command = 0x00;
    - pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
    + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
    + dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);
    + if (disable) {
    + /* Clear Bridge Control Register */
    + command = 0x00;
    + pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
    + }
    +
    pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
    pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);

    @@ -741,661 +591,290 @@
    if (!bus_node)
    return -ENOMEM;

    - bus_node->base = secondary_bus;
    - bus_node->length = temp_byte - secondary_bus + 1;
    + bus_node->base = (ulong)secondary_bus;
    + bus_node->length = (ulong)(temp_byte - secondary_bus + 1);

    bus_node->next = func->bus_head;
    func->bus_head = bus_node;

    - // Save IO base and Limit registers
    - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &b_base);
    - pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &b_length);
    + /* Save IO base and Limit registers */
    + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte);
    + base = temp_byte;
    + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
    + length = temp_byte;

    - if ((b_base <= b_length) && (save_command & 0x01)) {
    + if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
    io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    if (!io_node)
    return -ENOMEM;

    - io_node->base = (b_base & 0xF0) << 8;
    - io_node->length = (b_length - b_base + 0x10) << 8;
    + io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
    + io_node->length = (ulong)(length - base + 0x10) << 8;

    io_node->next = func->io_head;
    func->io_head = io_node;
    }

    - // Save memory base and Limit registers
    + /* Save memory base and Limit registers */
    pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
    pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);

    - if ((w_base <= w_length) && (save_command & 0x02)) {
    + if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
    mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    if (!mem_node)
    return -ENOMEM;

    - mem_node->base = w_base << 16;
    - mem_node->length = (w_length - w_base + 0x10) << 16;
    + mem_node->base = (ulong)w_base << 16;
    + mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;

    mem_node->next = func->mem_head;
    func->mem_head = mem_node;
    }
    -
    - // Save prefetchable memory base and Limit registers
    + /* Save prefetchable memory base and Limit registers */
    pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
    pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);

    - if ((w_base <= w_length) && (save_command & 0x02)) {
    + if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
    p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    if (!p_mem_node)
    return -ENOMEM;

    - p_mem_node->base = w_base << 16;
    - p_mem_node->length = (w_length - w_base + 0x10) << 16;
    + p_mem_node->base = (ulong)w_base << 16;
    + p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;

    p_mem_node->next = func->p_mem_head;
    func->p_mem_head = p_mem_node;
    }
    - // Figure out IO and memory base lengths
    - for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
    +
    + /* Figure out IO and memory base lengths
    + P2P BAR is not for children though... */
    + for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_1; cloop += 4) {
    pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);

    temp_register = 0xFFFFFFFF;
    pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
    - pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
    + pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);

    - temp_register = base;
    + if (!disable) {
    + pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base);
    + }

    - if (base) { // If this register is implemented
    - if (((base & 0x03L) == 0x01)
    - && (save_command & 0x01)) {
    - // IO base
    - // set temp_register = amount of IO space requested
    - temp_register = base & 0xFFFFFFFE;
    - temp_register = (~temp_register) + 1;
    -
    - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!io_node)
    - return -ENOMEM;
    -
    - io_node->base =
    - save_base & (~0x03L);
    - io_node->length = temp_register;
    + if (!temp_register)
    + continue;

    - io_node->next = func->io_head;
    - func->io_head = io_node;
    + base = temp_register;
    +
    + if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) {
    + /* IO base */
    + /* set temp_register = amount of IO space requested */
    + base = base & 0xFFFFFFFCL;
    + base = (~base) + 1;
    +
    + io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
    + if (!io_node)
    + return -ENOMEM;
    +
    + io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
    + io_node->length = (ulong)base;
    + dbg("sur: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length);
    +
    + io_node->next = func->io_head;
    + func->io_head = io_node;
    + } else { /* map Memory */
    + int prefetchable = 1;
    + char *res_type_str = "PMEM";
    + u32 temp_register2;
    +
    + t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
    + if (!t_mem_node)
    + return -ENOMEM;
    +
    + if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
    + prefetchable = 0;
    + mem_node = t_mem_node;
    + res_type_str++;
    } else
    - if (((base & 0x0BL) == 0x08)
    - && (save_command & 0x02)) {
    - // prefetchable memory base
    - temp_register = base & 0xFFFFFFF0;
    - temp_register = (~temp_register) + 1;
    -
    - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!p_mem_node)
    - return -ENOMEM;
    + p_mem_node = t_mem_node;

    - p_mem_node->base = save_base & (~0x0FL);
    - p_mem_node->length = temp_register;
    + base = base & 0xFFFFFFF0L;
    + base = (~base) + 1;

    - p_mem_node->next = func->p_mem_head;
    - func->p_mem_head = p_mem_node;
    - } else
    - if (((base & 0x0BL) == 0x00)
    - && (save_command & 0x02)) {
    - // prefetchable memory base
    - temp_register = base & 0xFFFFFFF0;
    - temp_register = (~temp_register) + 1;
    -
    - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!mem_node)
    - return -ENOMEM;
    + switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
    + case PCI_BASE_ADDRESS_MEM_TYPE_32:
    + if (prefetchable) {
    + p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
    + p_mem_node->length = (ulong)base;
    + dbg("sur: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
    +
    + p_mem_node->next = func->p_mem_head;
    + func->p_mem_head = p_mem_node;
    + } else {
    + mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
    + mem_node->length = (ulong)base;
    + dbg("sur: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
    +
    + mem_node->next = func->mem_head;
    + func->mem_head = mem_node;
    + }
    + break;
    + case PCI_BASE_ADDRESS_MEM_TYPE_64:
    + pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
    +
    + base64 = temp_register2;
    + base64 = (base64 << 32) | save_base;
    +
    + if (temp_register2) {
    + dbg("sur: 64 %s high dword of base64(0x%x:%x) masked to 0\n", res_type_str, temp_register2, (u32)base64);
    + base64 &= 0x00000000FFFFFFFFL;
    + }
    +
    + if (prefetchable) {
    + p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
    + p_mem_node->length = base;
    + dbg("sur: 64 %s base=0x%x(len=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
    +
    + p_mem_node->next = func->p_mem_head;
    + func->p_mem_head = p_mem_node;
    + } else {
    + mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
    + mem_node->length = base;
    + dbg("sur: 64 %s base=0x%x(len=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
    +
    + mem_node->next = func->mem_head;
    + func->mem_head = mem_node;
    + }
    + cloop += 4;
    + break;
    + default:
    + dbg("asur: reserved BAR type=0x%x\n", temp_register);
    + break;

    - mem_node->base = save_base & (~0x0FL);
    - mem_node->length = temp_register;
    + }
    + }
    + } /* End of base register loop */
    + } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
    + dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command);

    - mem_node->next = func->mem_head;
    - func->mem_head = mem_node;
    - } else
    - return(1);
    - }
    - } // End of base register loop
    - } else if ((header_type & 0x7F) == 0x00) { // Standard header
    - // Figure out IO and memory base lengths
    - for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
    + /* Figure out IO and memory base lengths */
    + for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
    pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);

    temp_register = 0xFFFFFFFF;
    - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
    - pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
    -
    - temp_register = base;
    -
    - if (base) { // If this register is implemented
    - if (((base & 0x03L) == 0x01)
    - && (save_command & 0x01)) {
    - // IO base
    - // set temp_register = amount of IO space requested
    - temp_register = base & 0xFFFFFFFE;
    - temp_register = (~temp_register) + 1;
    -
    - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!io_node)
    - return -ENOMEM;
    -
    - io_node->base = save_base & (~0x01L);
    - io_node->length = temp_register;
    -
    - io_node->next = func->io_head;
    - func->io_head = io_node;
    - } else
    - if (((base & 0x0BL) == 0x08)
    - && (save_command & 0x02)) {
    - // prefetchable memory base
    - temp_register = base & 0xFFFFFFF0;
    - temp_register = (~temp_register) + 1;
    -
    - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!p_mem_node)
    - return -ENOMEM;
    -
    - p_mem_node->base = save_base & (~0x0FL);
    - p_mem_node->length = temp_register;
    -
    - p_mem_node->next = func->p_mem_head;
    - func->p_mem_head = p_mem_node;
    - } else
    - if (((base & 0x0BL) == 0x00)
    - && (save_command & 0x02)) {
    - // prefetchable memory base
    - temp_register = base & 0xFFFFFFF0;
    - temp_register = (~temp_register) + 1;
    -
    - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!mem_node)
    - return -ENOMEM;
    -
    - mem_node->base = save_base & (~0x0FL);
    - mem_node->length = temp_register;

    - mem_node->next = func->mem_head;
    - func->mem_head = mem_node;
    - } else
    - return(1);
    - }
    - } // End of base register loop
    - } else { // Some other unknown header type
    - }
    -
    - // find the next device in this slot
    - func = cpqhp_slot_find(func->bus, func->device, index++);
    - }
    -
    - return(0);
    -}
    -
    -
    -/*
    - * cpqhp_configure_board
    - *
    - * Copies saved configuration information to one slot.
    - * this is called recursively for bridge devices.
    - * this is for hot plug REPLACE!
    - *
    - * returns 0 if success
    - */
    -int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)
    -{
    - int cloop;
    - u8 header_type;
    - u8 secondary_bus;
    - int sub_bus;
    - struct pci_func *next;
    - u32 temp;
    - u32 rc;
    - int index = 0;
    - struct pci_bus *pci_bus = ctrl->pci_bus;
    - unsigned int devfn;
    -
    - func = cpqhp_slot_find(func->bus, func->device, index++);
    -
    - while (func != NULL) {
    - pci_bus->number = func->bus;
    - devfn = PCI_DEVFN(func->device, func->function);
    -
    - // Start at the top of config space so that the control
    - // registers are programmed last
    - for (cloop = 0x3C; cloop > 0; cloop -= 4) {
    - pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
    - }
    -
    - pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
    -
    - // If this is a bridge device, restore subordinate devices
    - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
    - pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
    -
    - sub_bus = (int) secondary_bus;
    -
    - next = cpqhp_slot_list[sub_bus];
    -
    - while (next != NULL) {
    - rc = cpqhp_configure_board(ctrl, next);
    -
    - if (rc)
    - return rc;
    -
    - next = next->next;
    - }
    - } else {
    -
    - // Check all the base Address Registers to make sure
    - // they are the same. If not, the board is different.
    -
    - for (cloop = 16; cloop < 40; cloop += 4) {
    - pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);
    + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
    + pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);

    - if (temp != func->config_space[cloop >> 2]) {
    - dbg("Config space compare failure!!! offset = %x\n", cloop);
    - dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);
    - dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop >> 2]);
    - return 1;
    + if (!disable) {
    + pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base);
    }
    - }
    - }
    -
    - func->configured = 1;
    -
    - func = cpqhp_slot_find(func->bus, func->device, index++);
    - }
    -
    - return 0;
    -}

    + if (!temp_register)
    + continue;

    -/*
    - * cpqhp_valid_replace
    - *
    - * this function checks to see if a board is the same as the
    - * one it is replacing. this check will detect if the device's
    - * vendor or device id's are the same
    - *
    - * returns 0 if the board is the same nonzero otherwise
    - */
    -int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func)
    -{
    - u8 cloop;
    - u8 header_type;
    - u8 secondary_bus;
    - u8 type;
    - u32 temp_register = 0;
    - u32 base;
    - u32 rc;
    - struct pci_func *next;
    - int index = 0;
    - struct pci_bus *pci_bus = ctrl->pci_bus;
    - unsigned int devfn;
    -
    - if (!func->is_a_board)
    - return(ADD_NOT_SUPPORTED);
    -
    - func = cpqhp_slot_find(func->bus, func->device, index++);
    -
    - while (func != NULL) {
    - pci_bus->number = func->bus;
    - devfn = PCI_DEVFN(func->device, func->function);
    -
    - pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
    -
    - // No adapter present
    - if (temp_register == 0xFFFFFFFF)
    - return(NO_ADAPTER_PRESENT);
    -
    - if (temp_register != func->config_space[0])
    - return(ADAPTER_NOT_SAME);
    -
    - // Check for same revision number and class code
    - pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
    -
    - // Adapter not the same
    - if (temp_register != func->config_space[0x08 >> 2])
    - return(ADAPTER_NOT_SAME);
    -
    - // Check for Bridge
    - pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
    -
    - if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge
    - // In order to continue checking, we must program the
    - // bus registers in the bridge to respond to accesses
    - // for it's subordinate bus(es)
    -
    - temp_register = func->config_space[0x18 >> 2];
    - pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
    -
    - secondary_bus = (temp_register >> 8) & 0xFF;
    -
    - next = cpqhp_slot_list[secondary_bus];
    -
    - while (next != NULL) {
    - rc = cpqhp_valid_replace(ctrl, next);
    -
    - if (rc)
    - return(rc);
    -
    - next = next->next;
    - }
    -
    - }
    - // Check to see if it is a standard config header
    - else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
    - // Check subsystem vendor and ID
    - pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
    -
    - if (temp_register != func->config_space[0x2C >> 2]) {
    - // If it's a SMART-2 and the register isn't filled
    - // in, ignore the difference because
    - // they just have an old rev of the firmware
    -
    - if (!((func->config_space[0] == 0xAE100E11)
    - && (temp_register == 0x00L)))
    - return(ADAPTER_NOT_SAME);
    - }
    - // Figure out IO and memory base lengths
    - for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
    - temp_register = 0xFFFFFFFF;
    - pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
    - pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
    - if (base) { // If this register is implemented
    - if (base & 0x01L) {
    - // IO base
    - // set base = amount of IO space requested
    - base = base & 0xFFFFFFFE;
    - base = (~base) + 1;
    + base = temp_register;
    +
    + if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) {
    + /* IO base */
    + /* set temp_register = amount of IO space requested */
    + base = base & 0xFFFFFFFCL;
    + base = (~base) + 1;
    +
    + io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
    + if (!io_node)
    + return -ENOMEM;
    +
    + io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
    + io_node->length = (ulong)base;
    + dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length);
    +
    + io_node->next = func->io_head;
    + func->io_head = io_node;
    + } else { /* map Memory */
    + int prefetchable = 1;
    + char *res_type_str = "PMEM";
    + u32 temp_register2;
    +
    + t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL);
    + if (!t_mem_node)
    + return -ENOMEM;
    +
    + if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
    + prefetchable = 0;
    + mem_node = t_mem_node;
    + res_type_str++;
    + } else
    + p_mem_node = t_mem_node;

    - type = 1;
    - } else {
    - // memory base
    - base = base & 0xFFFFFFF0;
    - base = (~base) + 1;
    + base = base & 0xFFFFFFF0L;
    + base = (~base) + 1;

    - type = 0;
    + switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
    + case PCI_BASE_ADDRESS_MEM_TYPE_32:
    + if (prefetchable) {
    + p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
    + p_mem_node->length = (ulong)base;
    + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
    +
    + p_mem_node->next = func->p_mem_head;
    + func->p_mem_head = p_mem_node;
    + } else {
    + mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
    + mem_node->length = (ulong)base;
    + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
    +
    + mem_node->next = func->mem_head;
    + func->mem_head = mem_node;
    + }
    + break;
    + case PCI_BASE_ADDRESS_MEM_TYPE_64:
    + pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
    +
    + base64 = temp_register2;
    + base64 = (base64 << 32) | save_base;
    +
    + if (temp_register2) {
    + dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", res_type_str, temp_register2, (u32)base64);
    + base64 &= 0x00000000FFFFFFFFL;
    + }
    +
    + if (prefetchable) {
    + p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
    + p_mem_node->length = base;
    + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, p_mem_node->base, p_mem_node->length);
    +
    + p_mem_node->next = func->p_mem_head;
    + func->p_mem_head = p_mem_node;
    + } else {
    + mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
    + mem_node->length = base;
    + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, mem_node->base, mem_node->length);
    +
    + mem_node->next = func->mem_head;
    + func->mem_head = mem_node;
    + }
    + cloop += 4;
    + break;
    + default:
    + dbg("asur: reserved BAR type=0x%x\n", temp_register);
    + break;
    }
    - } else {
    - base = 0x0L;
    - type = 0;
    - }
    -
    - // Check information in slot structure
    - if (func->base_length[(cloop - 0x10) >> 2] != base)
    - return(ADAPTER_NOT_SAME);
    -
    - if (func->base_type[(cloop - 0x10) >> 2] != type)
    - return(ADAPTER_NOT_SAME);
    -
    - } // End of base register loop
    -
    - } // End of (type 0 config space) else
    - else {
    - // this is not a type 0 or 1 config space header so
    - // we don't know how to do it
    - return(DEVICE_TYPE_NOT_SUPPORTED);
    + }
    + } /* End of base register loop */
    + } else { /* Some other unknown header type */
    + dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device);
    }

    - // Get the next function
    + /* find the next device in this slot */
    + if (!disable)
    + break;
    func = cpqhp_slot_find(func->bus, func->device, index++);
    }

    -
    return(0);
    }


    /*
    - * cpqhp_find_available_resources
    - *
    - * Finds available memory, IO, and IRQ resources for programming
    - * devices which may be added to the system
    - * this function is for hot plug ADD!
    - *
    - * returns 0 if success
    - */
    -int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start)
    -{
    - u8 temp;
    - u8 populated_slot;
    - u8 bridged_slot;
    - void *one_slot;
    - struct pci_func *func = NULL;
    - int i = 10, index;
    - u32 temp_dword, rc;
    - struct pci_resource *mem_node;
    - struct pci_resource *p_mem_node;
    - struct pci_resource *io_node;
    - struct pci_resource *bus_node;
    - void *rom_resource_table;
    -
    - rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff);
    - dbg("rom_resource_table = %p\n", rom_resource_table);
    -
    - if (rom_resource_table == NULL) {
    - return -ENODEV;
    - }
    - // Sum all resources and setup resource maps
    - unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
    - dbg("unused_IRQ = %x\n", unused_IRQ);
    -
    - temp = 0;
    - while (unused_IRQ) {
    - if (unused_IRQ & 1) {
    - cpqhp_disk_irq = temp;
    - break;
    - }
    - unused_IRQ = unused_IRQ >> 1;
    - temp++;
    - }
    -
    - dbg("cpqhp_disk_irq= %d\n", cpqhp_disk_irq);
    - unused_IRQ = unused_IRQ >> 1;
    - temp++;
    -
    - while (unused_IRQ) {
    - if (unused_IRQ & 1) {
    - cpqhp_nic_irq = temp;
    - break;
    - }
    - unused_IRQ = unused_IRQ >> 1;
    - temp++;
    - }
    -
    - dbg("cpqhp_nic_irq= %d\n", cpqhp_nic_irq);
    - unused_IRQ = readl(rom_resource_table + PCIIRQ);
    -
    - temp = 0;
    -
    - if (!cpqhp_nic_irq) {
    - cpqhp_nic_irq = ctrl->cfgspc_irq;
    - }
    -
    - if (!cpqhp_disk_irq) {
    - cpqhp_disk_irq = ctrl->cfgspc_irq;
    - }
    -
    - dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
    -
    - rc = compaq_nvram_load(rom_start, ctrl);
    - if (rc)
    - return rc;
    -
    - one_slot = rom_resource_table + sizeof (struct hrt);
    -
    - i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
    - dbg("number_of_entries = %d\n", i);
    -
    - if (!readb(one_slot + SECONDARY_BUS)) {
    - return(1);
    - }
    -
    - dbg("dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n");
    -
    - while (i && readb(one_slot + SECONDARY_BUS)) {
    - u8 dev_func = readb(one_slot + DEV_FUNC);
    - u8 primary_bus = readb(one_slot + PRIMARY_BUS);
    - u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
    - u8 max_bus = readb(one_slot + MAX_BUS);
    - u16 io_base = readw(one_slot + IO_BASE);
    - u16 io_length = readw(one_slot + IO_LENGTH);
    - u16 mem_base = readw(one_slot + MEM_BASE);
    - u16 mem_length = readw(one_slot + MEM_LENGTH);
    - u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
    - u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
    -
    - dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
    - dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
    - primary_bus, secondary_bus, max_bus);
    -
    - // If this entry isn't for our controller's bus, ignore it
    - if (primary_bus != ctrl->bus) {
    - i--;
    - one_slot += sizeof (struct slot_rt);
    - continue;
    - }
    - // find out if this entry is for an occupied slot
    - ctrl->pci_bus->number = primary_bus;
    - pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
    - dbg("temp_D_word = %x\n", temp_dword);
    -
    - if (temp_dword != 0xFFFFFFFF) {
    - index = 0;
    - func = cpqhp_slot_find(primary_bus, dev_func >> 3, 0);
    -
    - while (func && (func->function != (dev_func & 0x07))) {
    - dbg("func = %p (bus, dev, fun) = (%d, %d, %d)\n", func, primary_bus, dev_func >> 3, index);
    - func = cpqhp_slot_find(primary_bus, dev_func >> 3, index++);
    - }
    -
    - // If we can't find a match, skip this table entry
    - if (!func) {
    - i--;
    - one_slot += sizeof (struct slot_rt);
    - continue;
    - }
    - // this may not work and shouldn't be used
    - if (secondary_bus != primary_bus)
    - bridged_slot = 1;
    - else
    - bridged_slot = 0;
    -
    - populated_slot = 1;
    - } else {
    - populated_slot = 0;
    - bridged_slot = 0;
    - }
    -
    -
    - // If we've got a valid IO base, use it
    -
    - temp_dword = io_base + io_length;
    -
    - if ((io_base) && (temp_dword < 0x10000)) {
    - io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!io_node)
    - return -ENOMEM;
    -
    - io_node->base = io_base;
    - io_node->length = io_length;
    -
    - dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
    - dbg("populated slot =%d \n", populated_slot);
    - if (!populated_slot) {
    - io_node->next = ctrl->io_head;
    - ctrl->io_head = io_node;
    - } else {
    - io_node->next = func->io_head;
    - func->io_head = io_node;
    - }
    - }
    -
    - // If we've got a valid memory base, use it
    - temp_dword = mem_base + mem_length;
    - if ((mem_base) && (temp_dword < 0x10000)) {
    - mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!mem_node)
    - return -ENOMEM;
    -
    - mem_node->base = mem_base << 16;
    -
    - mem_node->length = mem_length << 16;
    -
    - dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
    - dbg("populated slot =%d \n", populated_slot);
    - if (!populated_slot) {
    - mem_node->next = ctrl->mem_head;
    - ctrl->mem_head = mem_node;
    - } else {
    - mem_node->next = func->mem_head;
    - func->mem_head = mem_node;
    - }
    - }
    -
    - // If we've got a valid prefetchable memory base, and
    - // the base + length isn't greater than 0xFFFF
    - temp_dword = pre_mem_base + pre_mem_length;
    - if ((pre_mem_base) && (temp_dword < 0x10000)) {
    - p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!p_mem_node)
    - return -ENOMEM;
    -
    - p_mem_node->base = pre_mem_base << 16;
    -
    - p_mem_node->length = pre_mem_length << 16;
    - dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
    - dbg("populated slot =%d \n", populated_slot);
    -
    - if (!populated_slot) {
    - p_mem_node->next = ctrl->p_mem_head;
    - ctrl->p_mem_head = p_mem_node;
    - } else {
    - p_mem_node->next = func->p_mem_head;
    - func->p_mem_head = p_mem_node;
    - }
    - }
    -
    - // If we've got a valid bus number, use it
    - // The second condition is to ignore bus numbers on
    - // populated slots that don't have PCI-PCI bridges
    - if (secondary_bus && (secondary_bus != primary_bus)) {
    - bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
    - if (!bus_node)
    - return -ENOMEM;
    -
    - bus_node->base = secondary_bus;
    - bus_node->length = max_bus - secondary_bus + 1;
    - dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
    - dbg("populated slot =%d \n", populated_slot);
    - if (!populated_slot) {
    - bus_node->next = ctrl->bus_head;
    - ctrl->bus_head = bus_node;
    - } else {
    - bus_node->next = func->bus_head;
    - func->bus_head = bus_node;
    - }
    - }
    -
    - i--;
    - one_slot += sizeof (struct slot_rt);
    - }
    -
    - // If all of the following fail, we don't have any resources for
    - // hot plug add
    - rc = 1;
    - rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
    - rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
    - rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
    - rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
    -
    - return(rc);
    -}
    -
    -
    -/*
    * cpqhp_return_board_resources
    *
    * this routine returns all resources allocated to a board to
    diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
    --- a/drivers/pci/hotplug/Kconfig 2003-07-02 13:46:17.000000000 -0700
    +++ b/drivers/pci/hotplug/Kconfig 2003-07-07 09:32:25.000000000 -0700
    @@ -47,11 +47,11 @@
    When in doubt, say N.

    config HOTPLUG_PCI_COMPAQ
    - tristate "Compaq PCI Hotplug driver"
    - depends on HOTPLUG_PCI && X86
    + tristate "Compaq/Intel PCI Hotplug driver"
    + depends on HOTPLUG_PCI
    help
    Say Y here if you have a motherboard with a Compaq PCI Hotplug
    - controller.
    + controller or equivalent Intel controller.

    This code is also available as a module ( = code which can be
    inserted in and removed from the running kernel whenever you want).
    @@ -60,9 +60,19 @@

    When in doubt, say N.

    +config HOTPLUG_PCI_COMPAQ_PHPRM_LEGACY
    + bool "Non-ACPI: Use Hotplug Resource Table ($HRT) for resource information"
    + depends on HOTPLUG_PCI_COMPAQ
    + help
    + Say Y here if Hotplug resource/configuration information is provided
    + by platform BIOS $HRT, not by ACPI.
    + Some ACPI compliant platforms may use this too if $HRT is provided.
    +
    + When in doubt, say N.
    +
    config HOTPLUG_PCI_COMPAQ_NVRAM
    bool "Save configuration into NVRAM on Compaq servers"
    - depends on HOTPLUG_PCI_COMPAQ
    + depends on HOTPLUG_PCI_COMPAQ_PHPRM_LEGACY
    help
    Say Y here if you have a Compaq server that has a PCI Hotplug
    controller. This will allow the PCI Hotplug driver to store the PCI
    diff -Nru a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
    --- a/drivers/pci/hotplug/Makefile 2003-07-02 13:51:13.000000000 -0700
    +++ b/drivers/pci/hotplug/Makefile 2003-07-07 09:32:25.000000000 -0700
    @@ -3,7 +3,7 @@
    #

    obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
    -obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
    +obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
    obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
    obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
    obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
    @@ -20,7 +20,8 @@
    cpqphp-objs := cpqphp_core.o \
    cpqphp_ctrl.o \
    cpqphp_sysfs.o \
    - cpqphp_pci.o
    + cpqphp_pci.o \
    + cpqphp_hpc.o

    ibmphp-objs := ibmphp_core.o \
    ibmphp_ebda.o \
    @@ -40,6 +41,13 @@
    endif
    endif

    +ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_PHPRM_LEGACY),y)
    + cpqphp-objs += phprm_legacy.o
    +else
    + cpqphp-objs += phprm_acpi.o
    + EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi -I$(TOPDIR)/drivers/acpi/include -DPHP_ACPI
    +endif
    +
    ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
    cpqphp-objs += cpqphp_nvram.o
    endif
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:46    [W:0.238 / U:30.220 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site