From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S270591AbTGNO1s (ORCPT ); Mon, 14 Jul 2003 10:27:48 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S270584AbTGNO1s (ORCPT ); Mon, 14 Jul 2003 10:27:48 -0400 Received: from fmr03.intel.com ([143.183.121.5]:37349 "EHLO hermes.sc.intel.com") by vger.kernel.org with ESMTP id S270680AbTGNOQH (ORCPT ); Mon, 14 Jul 2003 10:16:07 -0400 Date: Mon, 14 Jul 2003 07:30:52 -0700 From: Dely Sy Message-Id: <200307141430.h6EEUqn25375@unix-os.sc.intel.com> To: linux-kernel@vger.kernel.org Subject: [Patch] 2/4 PCI Hot-plug driver patch for 2.5.74 kernel Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org diff -Nru a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c --- a/drivers/pci/hotplug/cpqphp_ctrl.c 2003-07-02 13:45:17.000000000 -0700 +++ b/drivers/pci/hotplug/cpqphp_ctrl.c 2003-07-07 09:32:21.000000000 -0700 @@ -38,9 +38,12 @@ #include #include #include "cpqphp.h" +#include "phprm.h" -static u32 configure_new_device(struct controller* ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources); -static int configure_new_function(struct controller* ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources); +static u32 configure_new_device(struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); +static int configure_new_function( struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); static void interrupt_event_handler(struct controller *ctrl); static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ @@ -76,54 +79,59 @@ } -//FIXME: The following line needs to be somewhere else... -#define WRONG_BUS_FREQUENCY 0x07 -static u8 handle_switch_change(u8 change, struct controller * ctrl) +u8 handle_switch_change(unsigned int change, void *inst_id) { + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; int hp_slot; u8 rc = 0; - u16 temp_word; + u8 getstatus; struct pci_func *func; struct event_info *taskInfo; if (!change) return 0; - // Switch Change - dbg("cpqsbd: Switch interrupt received.\n"); + /* Switch Change */ + dbg("cpqphp: Switch interrupt received.\n"); - for (hp_slot = 0; hp_slot < 6; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_ctlr_slots; hp_slot++) { if (change & (0x1L << hp_slot)) { - //********************************* - // this one changed. - //********************************* + /********************************* + * this one changed. + *********************************/ func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); - //this is the structure that tells the worker thread - //what to do + /* + * this is the structure that tells the worker thread + * what to do + */ taskInfo = &(ctrl->event_queue[ctrl->next_event]); ctrl->next_event = (ctrl->next_event + 1) % 10; taskInfo->hp_slot = hp_slot; rc++; + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->first_device_num); + if (!p_slot) + return 0; - temp_word = ctrl->ctrl_int_comp >> 16; - func->presence_save = (temp_word >> hp_slot) & 0x01; - func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; - - if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { - //********************************* - // Switch opened - //********************************* + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + + if (!getstatus) { + /********************************* + * Switch opened + *********************************/ + info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); func->switch_save = 0; taskInfo->event_type = INT_SWITCH_OPEN; } else { - //********************************* - // Switch closed - //********************************* - + /********************************* + * Switch closed + *********************************/ + info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); func->switch_save = 0x10; taskInfo->event_type = INT_SWITCH_CLOSE; @@ -131,54 +139,37 @@ } } - return rc; -} - - -/* - * cpqhp_find_slot - */ -struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device) -{ - struct slot *slot; - - if (!ctrl) - return NULL; - - slot = ctrl->slot; - - while (slot && (slot->device != device)) { - slot = slot->next; - } + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ - return slot; + return rc; } - -static u8 handle_presence_change(u16 change, struct controller * ctrl) +u8 handle_presence_change(unsigned int change, void *inst_id) { + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; int hp_slot; u8 rc = 0; u8 temp_byte; - u16 temp_word; struct pci_func *func; struct event_info *taskInfo; - struct slot *p_slot; + int push_button = !(ctrl->ctlrcap & 0x0002); if (!change) return 0; - //********************************* - // Presence Change - //********************************* - dbg("cpqsbd: Presence/Notify input change.\n"); + /********************************* + * Presence Change + **********************************/ + dbg("cpqphp: Presence/Notify input change.\n"); dbg(" Changed bits are 0x%4.4x\n", change ); - for (hp_slot = 0; hp_slot < 6; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_ctlr_slots; hp_slot++) { if (change & (0x0101 << hp_slot)) { - //********************************* - // this one changed. - //********************************* + /********************************* + * this one changed. + *********************************/ func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); taskInfo = &(ctrl->event_queue[ctrl->next_event]); @@ -186,72 +177,74 @@ taskInfo->hp_slot = hp_slot; rc++; - - p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->first_device_num); + if (!p_slot) return 0; - // If the switch closed, must be a button - // If not in button mode, nevermind - if (func->switch_save && (ctrl->push_button == 1)) { - temp_word = ctrl->ctrl_int_comp >> 16; - temp_byte = (temp_word >> hp_slot) & 0x01; - temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02; + /* + * If the switch closed, must be a button + * If not in button mode, nevermind + */ + if (func->switch_save && push_button) { + /* phphpc_get_adapter_status (p_slot, &temp_byte); */ + p_slot->hpc_ops->get_adapter_status(p_slot, &temp_byte); if (temp_byte != func->presence_save) { - //********************************* - // button Pressed (doesn't do anything) - //********************************* - dbg("hp_slot %d button pressed\n", hp_slot); + /********************************* + * button Pressed (doesn't do anything) + *********************************/ + info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_BUTTON_PRESS; } else { - //********************************* - // button Released - TAKE ACTION!!!! - //********************************* - dbg("hp_slot %d button released\n", hp_slot); + /********************************* + * button Released - TAKE ACTION!!!! + *********************************/ + info("Button released on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_BUTTON_RELEASE; - // Cancel if we are still blinking + /* Cancel if we are still blinking */ if ((p_slot->state == BLINKINGON_STATE) || (p_slot->state == BLINKINGOFF_STATE)) { taskInfo->event_type = INT_BUTTON_CANCEL; - dbg("hp_slot %d button cancel\n", hp_slot); + info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); } else if ((p_slot->state == POWERON_STATE) || (p_slot->state == POWEROFF_STATE)) { - //info(msg_button_ignore, p_slot->number); taskInfo->event_type = INT_BUTTON_IGNORE; - dbg("hp_slot %d button ignore\n", hp_slot); + info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); } } } else { - // Switch is open, assume a presence change - // Save the presence state - temp_word = ctrl->ctrl_int_comp >> 16; - func->presence_save = (temp_word >> hp_slot) & 0x01; - func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; - - if ((!(ctrl->ctrl_int_comp & (0x010000 << hp_slot))) || - (!(ctrl->ctrl_int_comp & (0x01000000 << hp_slot)))) { - //********************************* - // Present - //********************************* + /* + * Switch is open, assume a presence change + * Save the presence state + */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + if (func->presence_save) { + /********************************* + * Present + *********************************/ taskInfo->event_type = INT_PRESENCE_ON; } else { - //********************************* - // Not Present - //********************************* + /********************************* + * Not Present + *********************************/ taskInfo->event_type = INT_PRESENCE_OFF; } } } } + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + return rc; } - -static u8 handle_power_fault(u8 change, struct controller * ctrl) +u8 handle_power_fault(unsigned int change, void *inst_id) { + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; int hp_slot; u8 rc = 0; struct pci_func *func; @@ -260,17 +253,16 @@ if (!change) return 0; - //********************************* - // power fault - //********************************* + /********************************* + * power fault + *********************************/ + dbg("cpqphp: Power fault interrupt received.\n"); - info("power fault interrupt\n"); - - for (hp_slot = 0; hp_slot < 6; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_ctlr_slots; hp_slot++) { if (change & (0x01 << hp_slot)) { - //********************************* - // this one changed. - //********************************* + /********************************* + * this one changed. + *********************************/ func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); taskInfo = &(ctrl->event_queue[ctrl->next_event]); @@ -278,37 +270,51 @@ taskInfo->hp_slot = hp_slot; rc++; + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->first_device_num); + if (!p_slot) + return 0; - if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) { - //********************************* - // power fault Cleared - //********************************* + if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { + /********************************* + * power fault Cleared + *********************************/ + info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); func->status = 0x00; - taskInfo->event_type = INT_POWER_FAULT_CLEAR; } else { - //********************************* - // power fault - //********************************* + /********************************* + * power fault + *********************************/ + info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_POWER_FAULT; if (ctrl->rev < 4) { - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - set_SOGO (ctrl); - - // this is a fatal condition, we want to crash the - // machine to protect from data corruption - // simulated_NMI shouldn't ever return - //FIXME - //simulated_NMI(hp_slot, ctrl); - - //The following code causes a software crash just in - //case simulated_NMI did return - //FIXME - //panic(msg_power_fault); + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->update_hpc(p_slot); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + /* + * this is a fatal condition, we want to crash the + * machine to protect from data corruption + * simulated_NMI shouldn't ever return + * FIXME + * simulated_NMI(hp_slot, ctrl); + */ + + /* + * The following code causes a software crash just in + * case simulated_NMI did return + * FIXME + * panic(msg_power_fault); + */ } else { - // set power fault status for this board + /* set power fault status for this board */ func->status = 0xFF; info("power fault bit %x set\n", hp_slot); } @@ -316,6 +322,9 @@ } } + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + return rc; } @@ -342,7 +351,7 @@ while (out_of_order) { out_of_order = 0; - // Special case for swapping list head + /* Special case for swapping list head */ if (((*head)->next) && ((*head)->length > (*head)->next->length)) { out_of_order++; @@ -365,7 +374,7 @@ } else current_res = current_res->next; } - } // End of out_of_order loop + } /* End of out_of_order loop */ return(0); } @@ -393,7 +402,7 @@ while (out_of_order) { out_of_order = 0; - // Special case for swapping list head + /* Special case for swapping list head */ if (((*head)->next) && ((*head)->length < (*head)->next->length)) { out_of_order++; @@ -416,7 +425,7 @@ } else current_res = current_res->next; } - } // End of out_of_order loop + } /* End of out_of_order loop */ return(0); } @@ -452,14 +461,18 @@ return(NULL); - // If we got here, there the bridge requires some of the resource, but - // we may be able to split some off of the front + /* + * If we got here, there the bridge requires some of the resource, but + * we may be able to split some off of the front + */ node = *head; if (node->length & (alignment -1)) { - // this one isn't an aligned length, so we'll make a new entry - // and split it up. + /* + * this one isn't an aligned length, so we'll make a new entry + * and split it up. + */ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!split_node) @@ -473,7 +486,7 @@ node->length -= temp_dword; node->base += split_node->length; - // Put it in the list + /* Put it in the list */ *head = split_node; split_node->next = node; } @@ -482,7 +495,7 @@ return(NULL); } - // Now unlink it + /* Now unlink it */ if (*head == node) { *head = node->next; node->next = NULL; @@ -534,7 +547,7 @@ } if (node->base & (alignment - 1)) { - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ temp_dword = (node->base | (alignment-1)) + 1; if ((node->length - (temp_dword - node->base)) < alignment) { kfree(node); @@ -546,7 +559,7 @@ } if (node->length & (alignment - 1)) { - // There's stuff in use after this node + /* There's stuff in use after this node */ kfree(node); return(NULL); } @@ -569,7 +582,7 @@ { struct pci_resource *prevnode; struct pci_resource *node; - struct pci_resource *split_node; + struct pci_resource *split_node = NULL; u32 temp_dword; if (!(*head)) @@ -586,11 +599,13 @@ continue; if (node->base & (size - 1)) { - // this one isn't base aligned properly - // so we'll make a new entry and split it up + /* + * this one isn't base aligned properly + * so we'll make a new entry and split it up + */ temp_dword = (node->base | (size-1)) + 1; - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ if ((node->length - (temp_dword - node->base)) < size) continue; @@ -604,15 +619,17 @@ node->base = temp_dword; node->length -= split_node->length; - // Put it in the list + /* Put it in the list */ split_node->next = node->next; node->next = split_node; - } // End of non-aligned base + } /* End of non-aligned base */ - // Don't need to check if too small since we already did + /* Don't need to check if too small since we already did */ if (node->length > size) { - // this one is longer than we need - // so we'll make a new entry and split it up + /* + * this one is longer than we need + * so we'll make a new entry and split it up + */ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!split_node) @@ -622,17 +639,19 @@ split_node->length = node->length - size; node->length = size; - // Put it in the list + /* Put it in the list */ split_node->next = node->next; node->next = split_node; - } // End of too big on top end + } /* End of too big on top end */ - // For IO make sure it's not in the ISA aliasing space + /* For IO make sure it's not in the ISA aliasing space */ if (node->base & 0x300L) continue; - // If we got here, then it is the right size - // Now take it out of the list + /* + * If we got here, then it is the right size + * Now take it out of the list + */ if (*head == node) { *head = node->next; } else { @@ -643,7 +662,7 @@ prevnode->next = node->next; } node->next = NULL; - // Stop looping + /* Stop looping */ break; } @@ -657,6 +676,8 @@ * Gets the largest node that is at least "size" big from the * list pointed to by head. It aligns the node on top and bottom * to "size" alignment before returning it. + * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M + * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. */ static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size) { @@ -664,6 +685,8 @@ struct pci_resource *temp; struct pci_resource *split_node; u32 temp_dword; + u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 }; + int i; if (!(*head)) return(NULL); @@ -676,17 +699,21 @@ for (max = *head;max; max = max->next) { - // If not big enough we could probably just bail, - // instead we'll continue to the next. + /* + * If not big enough we could probably just bail, + * instead we'll continue to the next. + */ if (max->length < size) continue; if (max->base & (size - 1)) { - // this one isn't base aligned properly - // so we'll make a new entry and split it up + /* + * this one isn't base aligned properly + * so we'll make a new entry and split it up + */ temp_dword = (max->base | (size-1)) + 1; - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ if ((max->length - (temp_dword - max->base)) < size) continue; @@ -700,14 +727,16 @@ max->base = temp_dword; max->length -= split_node->length; - // Put it next in the list + /* Put it next in the list */ split_node->next = max->next; max->next = split_node; } if ((max->base + max->length) & (size - 1)) { - // this one isn't end aligned properly at the top - // so we'll make a new entry and split it up + /* + * this one isn't end aligned properly at the top + * so we'll make a new entry and split it up + */ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!split_node) @@ -718,16 +747,31 @@ - split_node->base; max->length -= split_node->length; - // Put it in the list + /* Put it in the list */ split_node->next = max->next; max->next = split_node; } - // Make sure it didn't shrink too much when we aligned it + /* Make sure it didn't shrink too much when we aligned it */ if (max->length < size) continue; - // Now take it out of the list + for ( i = 0; max_size[i] > size; i++) { + if (max->length > max_size[i]) { + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + break; + split_node->base = max->base + max_size[i]; + split_node->length = max->length - max_size[i]; + max->length = max_size[i]; + /* Put it next in the list */ + split_node->next = max->next; + max->next = split_node; + break; + } + } + + /* Now take it out of the list */ temp = (struct pci_resource*) *head; if (temp == max) { *head = max->next; @@ -743,7 +787,7 @@ return(max); } - // If we get here, we couldn't find one + /* If we get here, we couldn't find one */ return(NULL); } @@ -781,11 +825,13 @@ if (node->base & (size - 1)) { dbg("%s: not aligned\n", __FUNCTION__); - // this one isn't base aligned properly - // so we'll make a new entry and split it up + /* + * this one isn't base aligned properly + * so we'll make a new entry and split it up + */ temp_dword = (node->base | (size-1)) + 1; - // Short circuit if adjusted size is too small + /* Short circuit if adjusted size is too small */ if ((node->length - (temp_dword - node->base)) < size) continue; @@ -799,16 +845,18 @@ node->base = temp_dword; node->length -= split_node->length; - // Put it in the list + /* Put it in the list */ split_node->next = node->next; node->next = split_node; - } // End of non-aligned base + } /* End of non-aligned base */ - // Don't need to check if too small since we already did + /* Don't need to check if too small since we already did */ if (node->length > size) { dbg("%s: too big\n", __FUNCTION__); - // this one is longer than we need - // so we'll make a new entry and split it up + /* + * this one is longer than we need + * so we'll make a new entry and split it up + */ split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!split_node) @@ -818,14 +866,16 @@ split_node->length = node->length - size; node->length = size; - // Put it in the list + /* Put it in the list */ split_node->next = node->next; node->next = split_node; - } // End of too big on top end + } /* End of too big on top end */ dbg("%s: got one!!!\n", __FUNCTION__); - // If we got here, then it is the right size - // Now take it out of the list + /* + * If we got here, then it is the right size + * Now take it out of the list + */ if (*head == node) { *head = node->next; } else { @@ -836,7 +886,7 @@ prevnode->next = node->next; } node->next = NULL; - // Stop looping + /* Stop looping */ break; } return(node); @@ -873,7 +923,7 @@ while (out_of_order) { out_of_order = 0; - // Special case for swapping list head + /* Special case for swapping list head */ if (((*head)->next) && ((*head)->base > (*head)->next->base)) { node1 = *head; @@ -896,13 +946,13 @@ } else node1 = node1->next; } - } // End of out_of_order loop + } /* End of out_of_order loop */ node1 = *head; while (node1 && node1->next) { if ((node1->base + node1->length) == node1->next->base) { - // Combine + /* Combine */ dbg("8..\n"); node1->length += node1->next->length; node2 = node1->next; @@ -916,79 +966,6 @@ } -irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs) -{ - struct controller *ctrl = data; - u8 schedule_flag = 0; - u8 reset; - u16 misc; - u32 Diff; - u32 temp_dword; - - - misc = readw(ctrl->hpc_reg + MISC); - //********************************* - // Check to see if it was our interrupt - //********************************* - if (!(misc & 0x000C)) { - return IRQ_NONE; - } - - if (misc & 0x0004) { - //********************************* - // Serial Output interrupt Pending - //********************************* - - // Clear the interrupt - misc |= 0x0004; - writew(misc, ctrl->hpc_reg + MISC); - - // Read to clear posted writes - misc = readw(ctrl->hpc_reg + MISC); - - dbg ("%s - waking up\n", __FUNCTION__); - wake_up_interruptible(&ctrl->queue); - } - - if (misc & 0x0008) { - // General-interrupt-input interrupt Pending - Diff = readl(ctrl->hpc_reg + INT_INPUT_CLEAR) ^ ctrl->ctrl_int_comp; - - ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); - - // Clear the interrupt - writel(Diff, ctrl->hpc_reg + INT_INPUT_CLEAR); - - // Read it back to clear any posted writes - temp_dword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); - - if (!Diff) { - // Clear all interrupts - writel(0xFFFFFFFF, ctrl->hpc_reg + INT_INPUT_CLEAR); - } - - schedule_flag += handle_switch_change((u8)(Diff & 0xFFL), ctrl); - schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl); - schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl); - } - - reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); - if (reset & 0x40) { - /* Bus reset has completed */ - reset &= 0xCF; - writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE); - reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); - wake_up_interruptible(&ctrl->queue); - } - - if (schedule_flag) { - up(&event_semaphore); - dbg("Signal event_semaphore\n"); - } - return IRQ_HANDLED; -} - - /** * cpqhp_slot_create - Creates a node and adds it to the proper bus. * @busnumber - bus where new node is to be located @@ -1003,8 +980,10 @@ new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL); if (new_slot == NULL) { - // I'm not dead yet! - // You will be. + /* + * I'm not dead yet! + * You will be. + */ return(new_slot); } @@ -1151,11 +1130,13 @@ } -// DJZ: I don't think is_bridge will work as is. -//FIXME +/* + * DJZ: I don't think is_bridge will work as is. + * FIXME + */ static int is_bridge(struct pci_func * func) { - // Check the header type + /* Check the header type */ if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) return 1; else @@ -1169,214 +1150,6 @@ /** - * board_replaced - Called after a board has been replaced in the system. - * - * This is only used if we don't have resources for hot add - * Turns power on for the board - * Checks to see if board is the same - * If board is same, reconfigures it - * If board isn't same, turns it back off. - * - */ -static u32 board_replaced(struct pci_func * func, struct controller * ctrl) -{ - u8 hp_slot; - u8 temp_byte; - u8 adapter_speed; - u32 index; - u32 rc = 0; - u32 src = 8; - - hp_slot = func->device - ctrl->slot_device_offset; - - if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)) { - //********************************* - // The switch is open. - //********************************* - rc = INTERLOCK_OPEN; - } else if (is_slot_enabled (ctrl, hp_slot)) { - //********************************* - // The board is already on - //********************************* - rc = CARD_FUNCTIONING; - } else { - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - adapter_speed = get_adapter_speed(ctrl, hp_slot); - if (ctrl->speed != adapter_speed) - if (set_controller_speed(ctrl, adapter_speed, hp_slot)) - rc = WRONG_BUS_FREQUENCY; - - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); - - if (rc) - return(rc); - - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - slot_enable (ctrl, hp_slot); - green_LED_blink (ctrl, hp_slot); - - amber_LED_off (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); - - // Wait for ~1 second because of hot plug spec - long_delay(1*HZ); - - // Check for a power fault - if (func->status == 0xFF) { - // power fault occurred, but it was benign - rc = POWER_FAILURE; - func->status = 0; - } else - rc = cpqhp_valid_replace(ctrl, func); - - if (!rc) { - // It must be the same board - - rc = cpqhp_configure_board(ctrl, func); - - if (rc || src) { - // If configuration fails, turn it off - // Get slot won't work for devices behind bridges, but - // in this case it will always be called for the "base" - // bus/dev/func of an adapter. - - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); - - if (rc) - return(rc); - else - return(1); - } - - func->status = 0; - func->switch_save = 0x10; - - index = 1; - while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) { - rc |= cpqhp_configure_board(ctrl, func); - index++; - } - - if (rc) { - // If configuration fails, turn it off - // Get slot won't work for devices behind bridges, but - // in this case it will always be called for the "base" - // bus/dev/func of an adapter. - - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); - - return(rc); - } - // Done configuring so turn LED on full time - - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - green_LED_on (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); - rc = 0; - } else { - // Something is wrong - - // Get slot won't work for devices behind bridges, but - // in this case it will always be called for the "base" - // bus/dev/func of an adapter. - - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); - } - - } - return(rc); - -} - - -/** * board_added - Called after a board has been added to the system. * * Turns power on for the board @@ -1386,131 +1159,105 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) { u8 hp_slot; - u8 temp_byte; - u8 adapter_speed; int index; u32 temp_register = 0xFFFFFFFF; u32 rc = 0; - struct pci_func *new_slot = NULL; + struct pci_func *new_func = NULL; struct slot *p_slot; struct resource_lists res_lists; + enum pci_bus_speed adapter_speed, bus_speed; + p_slot = cpqhp_find_slot(ctrl, func->device); hp_slot = func->device - ctrl->slot_device_offset; - dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", - __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); - - set_SOGO(ctrl); + dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - adapter_speed = get_adapter_speed(ctrl, hp_slot); - if (ctrl->speed != adapter_speed) - if (set_controller_speed(ctrl, adapter_speed, hp_slot)) - rc = WRONG_BUS_FREQUENCY; - - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); + /* + * 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 Mhz, 3 = PCI-X 100 Mhz, + * 4 = PCI-X 133 Mhz, 0xAC = ACPI (unknown) + */ + if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { + err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); + return WRONG_BUS_FREQUENCY; + } - if (rc) - return(rc); - - p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); + if (rc || bus_speed == PCI_SPEED_UNKNOWN) { + err("%s: Can't get bus operation speed\n", __FUNCTION__); + return WRONG_BUS_FREQUENCY; + } - // turn on board and blink green LED + if (adapter_speed != bus_speed) { + if ((ctrl->pci_dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) && + (ctrl->rev >= 0x13)) { + if (p_slot->hpc_ops->set_controller_speed(p_slot, adapter_speed)) + return WRONG_BUS_FREQUENCY; + } else if (adapter_speed < bus_speed) { + err("%s: speeds of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + } - // Wait for exclusive access to hardware - dbg("%s: before down\n", __FUNCTION__); + /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - dbg("%s: after down\n", __FUNCTION__); - - dbg("%s: before slot_enable\n", __FUNCTION__); - slot_enable (ctrl, hp_slot); - dbg("%s: before green_LED_blink\n", __FUNCTION__); - green_LED_blink (ctrl, hp_slot); + /* turn on board */ + p_slot->hpc_ops->power_on_slot(p_slot); - dbg("%s: before amber_LED_blink\n", __FUNCTION__); - amber_LED_off (ctrl, hp_slot); + /* blink green LED, turn off Amber LEDs */ + p_slot->hpc_ops->green_led_blink(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); - dbg("%s: before set_SOGO\n", __FUNCTION__); - set_SOGO(ctrl); + p_slot->hpc_ops->update_hpc(p_slot); + dbg("%s: after update_hpc\n", __FUNCTION__); - // Wait for SOBS to be unset - dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__); - wait_for_ctrl_irq (ctrl); - dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); - - // Done with exclusive hardware access - dbg("%s: before up\n", __FUNCTION__); + /* Done with exclusive hardware access */ up(&ctrl->crit_sect); - dbg("%s: after up\n", __FUNCTION__); - // Wait for ~1 second because of hot plug spec + /* Wait for ~1 second because of hot plug spec */ dbg("%s: before long_delay\n", __FUNCTION__); long_delay(1*HZ); dbg("%s: after long_delay\n", __FUNCTION__); dbg("%s: func status = %x\n", __FUNCTION__, func->status); - // Check for a power fault + /* Check for a power fault */ if (func->status == 0xFF) { - // power fault occurred, but it was benign + /* + * power fault occurred, but it was benign + */ temp_register = 0xFFFFFFFF; dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); rc = POWER_FAILURE; func->status = 0; } else { - // Get vendor/device ID u32 + /* Get vendor/device ID u32 */ ctrl->pci_bus->number = func->bus; rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register); - dbg("%s: pci_read_config_dword returns %d\n", __FUNCTION__, rc); + dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc); dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); if (rc != 0) { - // Something's wrong here + /* Something's wrong here */ temp_register = 0xFFFFFFFF; dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); } - // Preset return code. It will be changed later if things go okay. + /* Preset return code. It will be changed later if things go okay. */ rc = NO_ADAPTER_PRESENT; } - // All F's is an empty slot or an invalid board - if (temp_register != 0xFFFFFFFF) { // Check for a board in the slot + /* All F's is an empty slot or an invalid board */ + if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */ res_lists.io_head = ctrl->io_head; res_lists.mem_head = ctrl->mem_head; res_lists.p_mem_head = ctrl->p_mem_head; res_lists.bus_head = ctrl->bus_head; res_lists.irqs = NULL; - rc = configure_new_device(ctrl, func, 0, &res_lists); - + rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0); dbg("%s: back from configure_new_device\n", __FUNCTION__); + ctrl->io_head = res_lists.io_head; ctrl->mem_head = res_lists.mem_head; ctrl->p_mem_head = res_lists.p_mem_head; @@ -1522,66 +1269,67 @@ cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); if (rc) { - // Wait for exclusive access to hardware + /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); + /* turn off slot */ + p_slot->hpc_ops->power_off_slot(p_slot); - set_SOGO(ctrl); + /* turn on Amber LED */ + /* turn off Green LED */ + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + p_slot->hpc_ops->update_hpc(p_slot); - // Done with exclusive hardware access + /* Done with exclusive hardware access */ up(&ctrl->crit_sect); + return(rc); - } else { - cpqhp_save_slot_config(ctrl, func); } - + cpqhp_save_slot_config(ctrl, func); func->status = 0; func->switch_save = 0x10; func->is_a_board = 0x01; - //next, we will instantiate the linux pci_dev structures (with appropriate driver notification, if already present) - dbg("%s: configure linux pci_dev structure\n", __FUNCTION__); + /* next, we will instantiate the linux pci_dev structures + * (with appropriate driver notification, if already present) + */ index = 0; do { - new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++); - if (new_slot && !new_slot->pci_dev) { - cpqhp_configure_device(ctrl, new_slot); + new_func = cpqhp_slot_find(ctrl->bus, func->device, index++); + if (new_func && !new_func->pci_dev) { + dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__); + cpqhp_configure_device(ctrl, new_func); } - } while (new_slot); + } while (new_func); - // Wait for exclusive access to hardware + /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - green_LED_on (ctrl, hp_slot); - - set_SOGO(ctrl); + p_slot->hpc_ops->green_led_on(p_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + p_slot->hpc_ops->update_hpc(p_slot); - // Done with exclusive hardware access + /* Done with exclusive hardware access */ up(&ctrl->crit_sect); + } else { - // Wait for exclusive access to hardware + /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); + /* turn off slot */ + p_slot->hpc_ops->power_off_slot(p_slot); - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + /* turn on Amber LED */ + /* turn off Green LED */ + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + + p_slot->hpc_ops->update_hpc(p_slot); - // Done with exclusive hardware access + /* Done with exclusive hardware access */ up(&ctrl->crit_sect); return(rc); @@ -1594,16 +1342,16 @@ * remove_board - Turns off slot and LED's * */ -static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl) +static u32 remove_board(struct pci_func *func, struct controller *ctrl) { int index; u8 skip = 0; u8 device; u8 hp_slot; - u8 temp_byte; u32 rc; struct resource_lists res_lists; struct pci_func *temp_func; + struct slot *p_slot; if (func == NULL) return(1); @@ -1614,62 +1362,60 @@ device = func->device; hp_slot = func->device - ctrl->slot_device_offset; + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->first_device_num); + dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); - // When we get here, it is safe to change base Address Registers. - // We will attempt to save the base Address Register Lengths - if (replace_flag || !ctrl->add_support) - rc = cpqhp_save_base_addr_length(ctrl, func); - else if (!func->bus_head && !func->mem_head && - !func->p_mem_head && !func->io_head) { - // Here we check to see if we've saved any of the board's - // resources already. If so, we'll skip the attempt to - // determine what's being used. + if ((ctrl->add_support) && + !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) { + /* + * Here we check to see if we've saved any of the board's + * resources already. If so, we'll skip the attempt to + * determine what's being used. */ index = 0; - temp_func = cpqhp_slot_find(func->bus, func->device, index++); - while (temp_func) { + + temp_func = func; + + while ((temp_func = cpqhp_slot_find(temp_func->bus, temp_func->device, index++))) { if (temp_func->bus_head || temp_func->mem_head || temp_func->p_mem_head || temp_func->io_head) { skip = 1; break; } - temp_func = cpqhp_slot_find(temp_func->bus, temp_func->device, index++); } if (!skip) - rc = cpqhp_save_used_resources(ctrl, func); + rc = cpqhp_save_used_resources(ctrl, func, DISABLE_CARD); } - // Change status to shutdown + /* Change status to shutdown */ if (func->is_a_board) func->status = 0x01; func->configured = 0; - // Wait for exclusive access to hardware + /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); + /* turn off Green LED */ + p_slot->hpc_ops->green_led_off(p_slot); - // turn off SERR for slot - temp_byte = readb(ctrl->hpc_reg + SLOT_SERR); - temp_byte &= ~(0x01 << hp_slot); - writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR); + /* turn off the slot */ + /* phphpc_power_off_slot(p_slot); */ + p_slot->hpc_ops->power_off_slot(p_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + p_slot->hpc_ops->update_hpc(p_slot); - // Done with exclusive hardware access + /* Done with exclusive hardware access */ up(&ctrl->crit_sect); - if (!replace_flag && ctrl->add_support) { + if (ctrl->add_support) { while (func) { res_lists.io_head = ctrl->io_head; res_lists.mem_head = ctrl->mem_head; res_lists.p_mem_head = ctrl->p_mem_head; res_lists.bus_head = ctrl->bus_head; + dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", func->bus, func->device, func->function); + cpqhp_return_board_resources(func, &res_lists); ctrl->io_head = res_lists.io_head; @@ -1683,18 +1429,20 @@ cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); if (is_bridge(func)) { + info("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); bridge_slot_remove(func); } else + info("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); slot_remove(func); func = cpqhp_slot_find(ctrl->bus, device, 0); } - // Setup slot structure with entry for empty slot + /* Setup slot structure with entry for empty slot */ func = cpqhp_slot_create(ctrl->bus); if (func == NULL) { - // Out of memory + /* Out of memory */ return(1); } @@ -1718,20 +1466,21 @@ } -// this is the main worker thread +/* this is the main worker thread */ static int event_thread(void* data) { struct controller *ctrl; + lock_kernel(); daemonize("phpd_event"); - unlock_kernel(); while (1) { dbg("!!!!event_thread sleeping\n"); down_interruptible (&event_semaphore); dbg("event_thread woken finished = %d\n", event_finished); - if (event_finished) break; + if (event_finished || signal_pending(current)) + break; /* Do stuff here */ if (pushbutton_pending) cpqhp_pushbutton_thread(pushbutton_pending); @@ -1775,7 +1524,7 @@ } -static int update_slot_info (struct controller *ctrl, struct slot *slot) +static int update_slot_info (struct slot *slot) { struct hotplug_slot_info *info; int result; @@ -1784,11 +1533,13 @@ if (!info) return -ENOMEM; - info->power_status = get_slot_enabled(ctrl, slot); - info->attention_status = cpq_get_attention_status(ctrl, slot); - info->latch_status = cpq_get_latch_status(ctrl, slot); - info->adapter_status = get_presence_status(ctrl, slot); + slot->hpc_ops->get_power_status(slot, &(info->power_status)); + slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); + slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); + slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); + result = pci_hp_change_slot_info(slot->hotplug_slot, info); + kfree (info); return result; } @@ -1799,13 +1550,13 @@ int change = 1; struct pci_func *func; u8 hp_slot; + u8 getstatus; struct slot *p_slot; while (change) { change = 0; for (loop = 0; loop < 10; loop++) { - //dbg("loop %d\n", loop); if (ctrl->event_queue[loop].event_type != 0) { hp_slot = ctrl->event_queue[loop].hp_slot; @@ -1827,90 +1578,104 @@ dbg("button cancel\n"); del_timer(&p_slot->task_event); - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - if (p_slot->state == BLINKINGOFF_STATE) { - // slot is on - // turn on green LED - dbg("turn on green LED\n"); - green_LED_on (ctrl, hp_slot); - } else if (p_slot->state == BLINKINGON_STATE) { - // slot is off - // turn off green LED - dbg("turn off green LED\n"); - green_LED_off (ctrl, hp_slot); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + p_slot->hpc_ops->update_hpc(p_slot); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + break; + case BLINKINGON_STATE: + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + p_slot->hpc_ops->update_hpc(p_slot); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + break; + default: + warn("Not a valid state\n"); + return; } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - - amber_LED_off (ctrl, hp_slot); - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - - // Done with exclusive hardware access - up(&ctrl->crit_sect); } - // ***********button Released (No action on press...) + /*********** button Released (No action on press...) */ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { dbg("button release\n"); + p_slot->hp_slot = hp_slot; + p_slot->ctrl = ctrl; - if (is_slot_enabled (ctrl, hp_slot)) { - // slot is on + /* phphpc_get_power_status (p_slot, &getstatus); */ + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + + if (getstatus) { + /* slot is on */ dbg("slot is on\n"); p_slot->state = BLINKINGOFF_STATE; info(msg_button_off, p_slot->number); } else { - // slot is off + /* slot is off */ dbg("slot is off\n"); p_slot->state = BLINKINGON_STATE; info(msg_button_on, p_slot->number); } - // Wait for exclusive access to hardware + + /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - - dbg("blink green LED and turn off amber\n"); - - amber_LED_off (ctrl, hp_slot); - green_LED_blink (ctrl, hp_slot); - - set_SOGO(ctrl); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + p_slot->hpc_ops->update_hpc(p_slot); - // Done with exclusive hardware access + /* Done with exclusive hardware access */ up(&ctrl->crit_sect); + init_timer(&p_slot->task_event); - p_slot->hp_slot = hp_slot; - p_slot->ctrl = ctrl; -// p_slot->physical_slot = physical_slot; - p_slot->task_event.expires = jiffies + 5 * HZ; // 5 second delay - p_slot->task_event.function = pushbutton_helper_thread; + p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ + p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; p_slot->task_event.data = (u32) p_slot; - dbg("add_timer p_slot = %p\n", p_slot); + dbg("add_timer p_slot = %p\n", (void *) p_slot); add_timer(&p_slot->task_event); } - // ***********POWER FAULT + /* ***********POWER FAULT*****************/ else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { dbg("power fault\n"); + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } else { /* refresh notification */ if (p_slot) - update_slot_info(ctrl, p_slot); + update_slot_info(p_slot); } ctrl->event_queue[loop].event_type = 0; change = 1; } - } // End of FOR loop + } /* End of FOR loop */ } return; @@ -1926,63 +1691,55 @@ */ void cpqhp_pushbutton_thread (unsigned long slot) { - u8 hp_slot; - u8 device; - struct pci_func *func; struct slot *p_slot = (struct slot *) slot; - struct controller *ctrl = (struct controller *) p_slot->ctrl; + u8 getstatus; pushbutton_pending = 0; - hp_slot = p_slot->hp_slot; - device = p_slot->device; + if (!p_slot) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return; + } + + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (is_slot_enabled (ctrl, hp_slot)) { + if (getstatus) { p_slot->state = POWEROFF_STATE; - // power Down board - func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); - dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl); - if (!func) { - dbg("Error! func NULL in %s\n", __FUNCTION__); - return ; - } - - if (func != NULL && ctrl != NULL) { - if (cpqhp_process_SS(ctrl, func) != 0) { - amber_LED_on (ctrl, hp_slot); - green_LED_on (ctrl, hp_slot); - - set_SOGO(ctrl); + dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - } - } + if (cpqhp_process_SS(p_slot)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); + + /* Turn on the LED */ + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_on(p_slot); + + p_slot->hpc_ops->update_hpc(p_slot); + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + + } p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; - // slot is off + dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); - dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl); - if (!func) { - dbg("Error! func NULL in %s\n", __FUNCTION__); - return ; - } - - if (func != NULL && ctrl != NULL) { - if (cpqhp_process_SI(ctrl, func) != 0) { - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - - set_SOGO(ctrl); + if (cpqhp_process_SI(p_slot)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - } - } + /* Turn off the green LED */ + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + + p_slot->hpc_ops->update_hpc(p_slot); + + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } p_slot->state = STATIC_STATE; } @@ -1990,132 +1747,144 @@ } -int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func) +int cpqhp_process_SI (struct slot *p_slot) { - u8 device, hp_slot; - u16 temp_word; - u32 tempdword; + u8 getstatus = 0; int rc; - struct slot* p_slot; - int physical_slot = 0; + struct pci_func *func; - if (!ctrl) - return(1); + func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); + if (!func) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return (1); + } - tempdword = 0; + /* Check to see if (latch closed, card present, power off) */ + down(&p_slot->ctrl->crit_sect); - device = func->device; - hp_slot = device - ctrl->slot_device_offset; - p_slot = cpqhp_find_slot(ctrl, device); - if (p_slot) { - physical_slot = p_slot->number; + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (rc || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); } - // Check to see if the interlock is closed - tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); - - if (tempdword & (0x01 << hp_slot)) { - return(1); + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || !getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); } - if (func->is_a_board) { - rc = board_replaced(func, ctrl); - } else { - // add board - slot_remove(func); + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || getstatus) { + info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + up(&p_slot->ctrl->crit_sect); - func = cpqhp_slot_create(ctrl->bus); - if (func == NULL) { - return(1); - } + /* add board */ + slot_remove(func); - func->bus = ctrl->bus; - func->device = device; - func->function = 0; - func->configured = 0; - func->is_a_board = 1; - - // We have to save the presence info for these slots - temp_word = ctrl->ctrl_int_comp >> 16; - func->presence_save = (temp_word >> hp_slot) & 0x01; - func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; + func = cpqhp_slot_create(p_slot->bus); + if (func == NULL) + return (1); - if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { - func->switch_save = 0; - } else { - func->switch_save = 0x10; - } + func->bus = p_slot->bus; + func->device = p_slot->device; + func->function = 0; + func->configured = 0; + func->is_a_board = 1; - rc = board_added(func, ctrl); - if (rc) { - if (is_bridge(func)) { - bridge_slot_remove(func); - } else - slot_remove(func); + /* We have to save the presence info for these slots */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + + func->switch_save = !getstatus? 0x10:0; - // Setup slot structure with entry for empty slot - func = cpqhp_slot_create(ctrl->bus); + rc = board_added(func, p_slot->ctrl); + if (rc) { + if (is_bridge(func)) + bridge_slot_remove(func); + else + slot_remove(func); - if (func == NULL) { - // Out of memory - return(1); - } + /* Setup slot structure with entry for empty slot */ + func = cpqhp_slot_create(p_slot->bus); + if (func == NULL) + return (1); /* Out of memory */ - func->bus = ctrl->bus; - func->device = device; - func->function = 0; - func->configured = 0; - func->is_a_board = 0; - - // We have to save the presence info for these slots - temp_word = ctrl->ctrl_int_comp >> 16; - func->presence_save = (temp_word >> hp_slot) & 0x01; - func->presence_save |= - (temp_word >> (hp_slot + 7)) & 0x02; + func->bus = p_slot->bus; + func->device = p_slot->device; + func->function = 0; + func->configured = 0; + func->is_a_board = 1; - if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { - func->switch_save = 0; - } else { - func->switch_save = 0x10; - } - } - } + /* We have to save the presence info for these slots */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (rc) { - dbg("%s: rc = %d\n", __FUNCTION__, rc); + func->switch_save = !getstatus? 0x10:0; } if (p_slot) - update_slot_info(ctrl, p_slot); + update_slot_info(p_slot); return rc; } -int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func) +int cpqhp_process_SS (struct slot *p_slot) { - u8 device, class_code, header_type, BCR; + u8 class_code, header_type, BCR; u8 index = 0; - u8 replace_flag; + u8 getstatus = 0; u32 rc = 0; + int ret = 0; unsigned int devfn; - struct slot* p_slot; - struct pci_bus *pci_bus = ctrl->pci_bus; - int physical_slot=0; - - device = func->device; - func = cpqhp_slot_find(ctrl->bus, device, index++); - p_slot = cpqhp_find_slot(ctrl, device); - if (p_slot) { - physical_slot = p_slot->number; + struct pci_bus *pci_bus = p_slot->ctrl->pci_bus; + struct pci_func *func; + + if (!p_slot->ctrl) + return (1); + + /* Check to see if (latch closed, card present, power on) */ + down(&p_slot->ctrl->crit_sect); + + ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + + ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); } - // Make sure there are no video controllers here + ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + up(&p_slot->ctrl->crit_sect); + + func = cpqhp_slot_find(p_slot->bus, p_slot->device, index++); + + /* + * Make sure there are no video controllers here + * for all func of p_slot + */ while (func && !rc) { pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); - // Check the Class Code + /* Check the Class Code */ rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); if (rc) return rc; @@ -2124,213 +1893,40 @@ /* Display/Video adapter (not supported) */ rc = REMOVE_NOT_SUPPORTED; } else { - // See if it's a bridge + /* See if it's a bridge */ rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if (rc) return rc; - // If it's a bridge, check the VGA Enable bit + /* If it's a bridge, check the VGA Enable bit */ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); if (rc) return rc; - // If the VGA Enable bit is set, remove isn't supported + /* If the VGA Enable bit is set, remove isn't supported */ if (BCR & PCI_BRIDGE_CTL_VGA) { rc = REMOVE_NOT_SUPPORTED; } } } - func = cpqhp_slot_find(ctrl->bus, device, index++); + func = cpqhp_slot_find(p_slot->bus, p_slot->device, index++); } - func = cpqhp_slot_find(ctrl->bus, device, 0); + func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); if ((func != NULL) && !rc) { - //FIXME: Replace flag should be passed into process_SS - replace_flag = !(ctrl->add_support); - rc = remove_board(func, replace_flag, ctrl); - } else if (!rc) { + rc = remove_board(func, p_slot->ctrl); + } else if (!rc) rc = 1; - } if (p_slot) - update_slot_info(ctrl, p_slot); + update_slot_info(p_slot); return(rc); } - -/** - * hardware_test - runs hardware tests - * - * For hot plug ctrl folks to play with. - * test_num is the number entered in the GUI - * - */ -int cpqhp_hardware_test(struct controller *ctrl, int test_num) -{ - u32 save_LED; - u32 work_LED; - int loop; - int num_of_slots; - - num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f; - - switch (test_num) { - case 1: - // Do stuff here! - - // Do that funky LED thing - save_LED = readl(ctrl->hpc_reg + LED_CONTROL); // so we can restore them later - work_LED = 0x01010101; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - for (loop = 0; loop < num_of_slots; loop++) { - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - - work_LED = 0x01010000; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - for (loop = 0; loop < num_of_slots; loop++) { - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - work_LED = 0x00000101; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - for (loop = 0; loop < num_of_slots; loop++) { - work_LED = work_LED >> 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((2*HZ)/10); - } - - - work_LED = 0x01010000; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - for (loop = 0; loop < num_of_slots; loop++) { - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((3*HZ)/10); - work_LED = work_LED >> 16; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - - set_SOGO(ctrl); - - // Wait for SOGO interrupt - wait_for_ctrl_irq (ctrl); - - // Get ready for next iteration - long_delay((3*HZ)/10); - work_LED = work_LED << 16; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - work_LED = work_LED << 1; - writel(work_LED, ctrl->hpc_reg + LED_CONTROL); - } - - writel (save_LED, ctrl->hpc_reg + LED_CONTROL); // put it back the way it was - - set_SOGO(ctrl); - - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); - break; - case 2: - // Do other stuff here! - break; - case 3: - // and more... - break; - } - return 0; -} - - /** * configure_new_device - Configures the PCI header information of one board. * @@ -2343,26 +1939,30 @@ * */ static u32 configure_new_device (struct controller * ctrl, struct pci_func * func, - u8 behind_bridge, struct resource_lists * resources) + u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev) { u8 temp_byte, function, max_functions, stop_it; int rc; u32 ID; struct pci_func *new_slot; + struct pci_bus lpci_bus, *pci_bus; int index; new_slot = func; dbg("%s\n", __FUNCTION__); - // Check for Multi-function device - ctrl->pci_bus->number = func->bus; - rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + + /* Check for Multi-function device */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); if (rc) { dbg("%s: rc = %d\n", __FUNCTION__, rc); return rc; } - if (temp_byte & 0x80) // Multi-function device + if (temp_byte & 0x80) /* Multi-function device */ max_functions = 8; else max_functions = 1; @@ -2370,7 +1970,7 @@ function = 0; do { - rc = configure_new_function(ctrl, new_slot, behind_bridge, resources); + rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev); if (rc) { dbg("configure_new_function failed %d\n",rc); @@ -2390,20 +1990,21 @@ stop_it = 0; - // The following loop skips to the next present function - // and creates a board structure + /* + * The following loop skips to the next present function + * and creates a board structure + */ while ((function < max_functions) && (!stop_it)) { - pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); - - if (ID == 0xFFFFFFFF) { // There's nothing there. + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); + if (ID == 0xFFFFFFFF) { /* There's nothing there. */ function++; - } else { // There's something there - // Setup slot structure. + } else { /* There's something there */ + /* Setup slot structure. */ new_slot = cpqhp_slot_create(func->bus); if (new_slot == NULL) { - // Out of memory + /* Out of memory */ return(1); } @@ -2443,16 +2044,13 @@ * */ static int configure_new_function (struct controller * ctrl, struct pci_func * func, - u8 behind_bridge, struct resource_lists * resources) + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev) { int cloop; - u8 IRQ; u8 temp_byte; u8 device; u8 class_code; - u16 command; u16 temp_word; - u32 temp_dword; u32 rc; u32 temp_register; u32 base; @@ -2468,82 +2066,86 @@ struct pci_resource *hold_bus_node; struct irq_mapping irqs; struct pci_func *new_slot; - struct pci_bus *pci_bus; + struct pci_bus lpci_bus, *pci_bus; struct resource_lists temp_resources; - pci_bus = ctrl->pci_bus; + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); - // Check for Bridge + /* Check for Bridge */ rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); if (rc) return rc; - if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge - // set Primary bus - dbg("set Primary bus = %d\n", func->bus); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); + if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + /* set Primary bus */ + dbg("set Primary bus = 0x%x\n", func->bus); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); if (rc) return rc; - // find range of busses to use - dbg("find ranges of buses to use\n"); - bus_node = get_max_resource(&resources->bus_head, 1); + /* find range of busses to use */ + bus_node = get_max_resource(&resources->bus_head, 1L); - // If we don't have any busses to allocate, we can't continue - if (!bus_node) + /* If we don't have any busses to allocate, we can't continue */ + if (!bus_node) { + err("Got NO bus resource to use\n"); return -ENOMEM; + } + dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); - // set Secondary bus - temp_byte = bus_node->base; - dbg("set Secondary bus = %d\n", bus_node->base); - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); + /* set Secondary bus */ + temp_byte = (u8)bus_node->base; + dbg("set Secondary bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); if (rc) return rc; - // set subordinate bus - temp_byte = bus_node->base + bus_node->length - 1; - dbg("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1); + /* set subordinate bus */ + temp_byte = (u8)(bus_node->base + bus_node->length - 1); + dbg("set subordinate bus = 0x%x\n", temp_byte); rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); if (rc) return rc; - // set subordinate Latency Timer and base Latency Timer - temp_byte = 0x40; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); - if (rc) - return rc; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); + /* Set HP parameters (Cache Line Size, Latency Timer) */ + rc = phprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); if (rc) return rc; - // set Cache Line size - temp_byte = 0x08; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); - if (rc) - return rc; - - // Setup the IO, memory, and prefetchable windows + /* Setup the IO, memory, and prefetchable windows */ - io_node = get_max_resource(&(resources->io_head), 0x1000); - if (!io_node) + io_node = get_max_resource(&(resources->io_head), 0x1000L); + if (io_node) { + dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next); + } else return -ENOMEM; - mem_node = get_max_resource(&(resources->mem_head), 0x100000); - if (!mem_node) + + mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + if (mem_node) { + dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next); + } else return -ENOMEM; - p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000); - if (!p_mem_node) + + if (resources->p_mem_head) + p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); + else { + /* + * In some platform implementation, MEM and PMEM are not + * distinguished, and hence ACPI _CRS has only MEM entries + * for both MEM and PMEM. + */ + dbg("using MEM for PMEM\n"); + p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + } + if (p_mem_node) { + dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next); + } else return -ENOMEM; - dbg("Setup the IO, memory, and prefetchable windows\n"); - dbg("io_node\n"); - dbg("(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next); - dbg("mem_node\n"); - dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next); - dbg("p_mem_node\n"); - dbg("(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next); - // set up the IRQ info + /* set up the IRQ info */ if (!resources->irqs) { irqs.barber_pole = 0; irqs.interrupt[0] = 0; @@ -2560,16 +2162,20 @@ irqs.valid_INT = resources->irqs->valid_INT; } - // set up resource lists that are now aligned on top and bottom - // for anything behind the bridge. + /* + * set up resource lists that are now aligned on top and bottom + * for anything behind the bridge. + */ temp_resources.bus_head = bus_node; temp_resources.io_head = io_node; temp_resources.mem_head = mem_node; temp_resources.p_mem_head = p_mem_node; temp_resources.irqs = &irqs; - // Make copies of the nodes we are going to pass down so that - // if there is a problem,we can just use these to free resources + /* + * Make copies of the nodes we are going to pass down so that + * if there is a problem,we can just use these to free resources + */ hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); @@ -2594,35 +2200,42 @@ bus_node->length -= 1; bus_node->next = NULL; - // If we have IO resources copy them and fill in the bridge's - // IO range registers + /* + * If we have IO resources copy them and fill in the bridge's + * IO range registers + */ if (io_node) { memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); io_node->next = NULL; - // set IO base and Limit registers - temp_byte = io_node->base >> 8; + /* set IO base and Limit registers */ + RES_CHECK(io_node->base, 8); + temp_byte = (u8)(io_node->base >> 8); rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); - - temp_byte = (io_node->base + io_node->length - 1) >> 8; + RES_CHECK(io_node->base + io_node->length - 1, 8); + temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); } else { kfree(hold_IO_node); hold_IO_node = NULL; } - // If we have memory resources copy them and fill in the bridge's - // memory range registers. Otherwise, fill in the range - // registers with values that disable them. + /* + * If we have memory resources copy them and fill in the bridge's + * memory range registers. Otherwise, fill in the range + * registers with values that disable them. + */ if (mem_node) { memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); mem_node->next = NULL; - // set Mem base and Limit registers - temp_word = mem_node->base >> 16; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + /* set Mem base and Limit registers */ + RES_CHECK(mem_node->base, 16); + temp_word = (u32)(mem_node->base >> 16); - temp_word = (mem_node->base + mem_node->length - 1) >> 16; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + RES_CHECK(mem_node->base + mem_node->length - 1, 16); + temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16); rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); } else { temp_word = 0xFFFF; @@ -2635,19 +2248,24 @@ hold_mem_node = NULL; } - // If we have prefetchable memory resources copy them and - // fill in the bridge's memory range registers. Otherwise, - // fill in the range registers with values that disable them. + /* + * If we have prefetchable memory resources copy them and + * fill in the bridge's memory range registers. Otherwise, + * fill in the range registers with values that disable them. + */ if (p_mem_node) { memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); p_mem_node->next = NULL; - // set Pre Mem base and Limit registers - temp_word = p_mem_node->base >> 16; + /* set Pre Mem base and Limit registers */ + RES_CHECK(p_mem_node->base, 16); + temp_word = (u32)(p_mem_node->base >> 16); rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); - temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16; + RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16); + temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16); rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + } else { temp_word = 0xFFFF; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); @@ -2659,26 +2277,27 @@ hold_p_mem_node = NULL; } - // Adjust this to compensate for extra adjustment in first loop + /* Adjust this to compensate for extra adjustment in first loop */ irqs.barber_pole--; rc = 0; - // Here we actually find the devices and configure them + /* Here we actually find the devices and configure them */ for (device = 0; (device <= 0x1F) && !rc; device++) { irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; ID = 0xFFFFFFFF; pci_bus->number = hold_bus_node->base; - pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), 0x00, &ID); + pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + pci_bus->number = func->bus; - if (ID != 0xFFFFFFFF) { // device Present - // Setup slot structure. + if (ID != 0xFFFFFFFF) { /* device Present */ + /* Setup slot structure. */ new_slot = cpqhp_slot_create(hold_bus_node->base); if (new_slot == NULL) { - // Out of memory + /* Out of memory */ rc = -ENOMEM; continue; } @@ -2689,10 +2308,10 @@ new_slot->is_a_board = 1; new_slot->status = 0; - rc = configure_new_device(ctrl, new_slot, 1, &temp_resources); + rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device); dbg("configure_new_device rc=0x%x\n",rc); - } // End of IF (device in slot?) - } // End of FOR loop + } /* End of IF (device in slot?) */ + } /* End of FOR loop */ if (rc) { cpqhp_destroy_resource_list(&temp_resources); @@ -2703,7 +2322,8 @@ return_resource(&(resources->p_mem_head), hold_p_mem_node); return(rc); } - // save the interrupt routing information + + /* save the interrupt routing information */ if (resources->irqs) { resources->irqs->interrupt[0] = irqs.interrupt[0]; resources->irqs->interrupt[1] = irqs.interrupt[1]; @@ -2711,129 +2331,136 @@ resources->irqs->interrupt[3] = irqs.interrupt[3]; resources->irqs->valid_INT = irqs.valid_INT; } else if (!behind_bridge) { - // We need to hook up the interrupts here + /* We need to hook up the interrupts here */ for (cloop = 0; cloop < 4; cloop++) { if (irqs.valid_INT & (0x01 << cloop)) { rc = cpqhp_set_irq(func->bus, func->device, 0x0A + cloop, irqs.interrupt[cloop]); if (rc) { cpqhp_destroy_resource_list (&temp_resources); - - return_resource(&(resources-> bus_head), hold_bus_node); - return_resource(&(resources-> io_head), hold_IO_node); - return_resource(&(resources-> mem_head), hold_mem_node); - return_resource(&(resources-> p_mem_head), hold_p_mem_node); + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); return rc; } } - } // end of for loop + } /* end of for loop */ } - // Return unused bus resources - // First use the temporary node to store information for the board + + /* Return unused bus resources */ + /* First use the temporary node to store information for the board */ if (hold_bus_node && bus_node && temp_resources.bus_head) { hold_bus_node->length = bus_node->base - hold_bus_node->base; hold_bus_node->next = func->bus_head; func->bus_head = hold_bus_node; - temp_byte = temp_resources.bus_head->base - 1; + temp_byte = (u8)(temp_resources.bus_head->base - 1); - // set subordinate bus + /* set subordinate bus */ + dbg("re-set subordinate bus = 0x%x\n", temp_byte); rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); if (temp_resources.bus_head->length == 0) { kfree(temp_resources.bus_head); temp_resources.bus_head = NULL; } else { + dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", + func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); return_resource(&(resources->bus_head), temp_resources.bus_head); } } - // If we have IO space available and there is some left, - // return the unused portion + /* If we have IO space available and there is some left, + return the unused portion */ if (hold_IO_node && temp_resources.io_head) { io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), &hold_IO_node, 0x1000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (io_node) { hold_IO_node->base = io_node->base + io_node->length; - temp_byte = (hold_IO_node->base) >> 8; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_IO_BASE, temp_byte); + RES_CHECK(hold_IO_node->base, 8); + temp_byte = (u8)((hold_IO_node->base) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); return_resource(&(resources->io_head), io_node); } io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (io_node) { - // First use the temporary node to store information for the board + /* First use the temporary node to store information for the board */ hold_IO_node->length = io_node->base - hold_IO_node->base; - // If we used any, add it to the board's list + /* If we used any, add it to the board's list */ if (hold_IO_node->length) { hold_IO_node->next = func->io_head; func->io_head = hold_IO_node; - temp_byte = (io_node->base - 1) >> 8; + RES_CHECK(io_node->base - 1, 8); + temp_byte = (u8)((io_node->base - 1) >> 8); rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); return_resource(&(resources->io_head), io_node); } else { - // it doesn't need any IO - temp_word = 0x0000; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_IO_LIMIT, temp_word); + /* it doesn't need any IO */ + temp_byte = 0x00; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); return_resource(&(resources->io_head), io_node); kfree(hold_IO_node); } } else { - // it used most of the range + /* it used most of the range */ hold_IO_node->next = func->io_head; func->io_head = hold_IO_node; } } else if (hold_IO_node) { - // it used the whole range + /* it used the whole range */ hold_IO_node->next = func->io_head; func->io_head = hold_IO_node; } - // If we have memory space available and there is some left, - // return the unused portion + + /* If we have memory space available and there is some left, + return the unused portion */ if (hold_mem_node && temp_resources.mem_head) { - mem_node = do_pre_bridge_resource_split(&(temp_resources. mem_head), - &hold_mem_node, 0x100000); + mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (mem_node) { hold_mem_node->base = mem_node->base + mem_node->length; - temp_word = (hold_mem_node->base) >> 16; + RES_CHECK(hold_mem_node->base, 16); + temp_word = (u32)((hold_mem_node->base) >> 16); rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); return_resource(&(resources->mem_head), mem_node); } - mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000); + mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (mem_node) { - // First use the temporary node to store information for the board + /* First use the temporary node to store information for the board */ hold_mem_node->length = mem_node->base - hold_mem_node->base; if (hold_mem_node->length) { hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; - // configure end address - temp_word = (mem_node->base - 1) >> 16; + /* configure end address */ + RES_CHECK(mem_node->base - 1, 16); + temp_word = (u32)((mem_node->base - 1) >> 16); rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); - // Return unused resources to the pool + /* Return unused resources to the pool */ return_resource(&(resources->mem_head), mem_node); } else { - // it doesn't need any Mem + /* it doesn't need any Mem */ temp_word = 0x0000; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); @@ -2841,49 +2468,52 @@ kfree(hold_mem_node); } } else { - // it used most of the range + /* it used most of the range */ hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; } } else if (hold_mem_node) { - // it used the whole range + /* it used the whole range */ hold_mem_node->next = func->mem_head; func->mem_head = hold_mem_node; } - // If we have prefetchable memory space available and there is some - // left at the end, return the unused portion + + /* If we have prefetchable memory space available and there is some + left at the end, return the unused portion */ if (hold_p_mem_node && temp_resources.p_mem_head) { p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), - &hold_p_mem_node, 0x100000); + &hold_p_mem_node, 0x100000L); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (p_mem_node) { hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; - temp_word = (hold_p_mem_node->base) >> 16; + RES_CHECK(hold_p_mem_node->base, 16); + temp_word = (u32)((hold_p_mem_node->base) >> 16); rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); return_resource(&(resources->p_mem_head), p_mem_node); } - p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000); + p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); - // Check if we were able to split something off + /* Check if we were able to split something off */ if (p_mem_node) { - // First use the temporary node to store information for the board + /* First use the temporary node to store information for the board */ hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; - // If we used any, add it to the board's list + /* If we used any, add it to the board's list */ if (hold_p_mem_node->length) { hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; - temp_word = (p_mem_node->base - 1) >> 16; + RES_CHECK(p_mem_node->base - 1, 16); + temp_word = (u32)((p_mem_node->base - 1) >> 16); rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); return_resource(&(resources->p_mem_head), p_mem_node); } else { - // it doesn't need any PMem + /* it doesn't need any PMem */ temp_word = 0x0000; rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); @@ -2891,189 +2521,167 @@ kfree(hold_p_mem_node); } } else { - // it used the most of the range + /* it used the most of the range */ hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; } } else if (hold_p_mem_node) { - // it used the whole range + /* it used the whole range */ hold_p_mem_node->next = func->p_mem_head; func->p_mem_head = hold_p_mem_node; } - // We should be configuring an IRQ and the bridge's base address - // registers if it needs them. Although we have never seen such - // a device - - // enable card - command = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command); - - // set Bridge Control Register - command = 0x07; // = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command); + + /* We should be configuring an IRQ and the bridge's base address + registers if it needs them. Although we have never seen such + a device */ + + phprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + + info("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { - // Standard device + /* Standard device */ + u64 base64; rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); - if (class_code == PCI_BASE_CLASS_DISPLAY) { - // Display (video) adapter (not supported) - return(DEVICE_TYPE_NOT_SUPPORTED); - } - // Figure out IO and memory needs - for (cloop = 0x10; cloop <= 0x24; cloop += 4) { + if (class_code == PCI_BASE_CLASS_DISPLAY) + return (DEVICE_TYPE_NOT_SUPPORTED); + + /* Figure out IO and memory needs */ + for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { temp_register = 0xFFFFFFFF; - dbg("CND: bus=%d, devfn=%d, offset=%d\n", pci_bus->number, devfn, cloop); rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); - rc = pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register); - dbg("CND: base = 0x%x\n", temp_register); - - if (temp_register) { // If this register is implemented - if ((temp_register & 0x03L) == 0x01) { - // Map IO - - // set base = amount of IO space - base = temp_register & 0xFFFFFFFC; - base = ~base + 1; - - dbg("CND: length = 0x%x\n", base); - io_node = get_io_resource(&(resources->io_head), base); - dbg("Got io_node start = %8.8x, length = %8.8x next (%p)\n", - io_node->base, io_node->length, io_node->next); - dbg("func (%p) io_head (%p)\n", func, func->io_head); - - // allocate the resource to the board - if (io_node) { - base = io_node->base; - - io_node->next = func->io_head; - func->io_head = io_node; - } else - return -ENOMEM; - } else if ((temp_register & 0x0BL) == 0x08) { - // Map prefetchable memory - base = temp_register & 0xFFFFFFF0; - base = ~base + 1; - - dbg("CND: length = 0x%x\n", base); - p_mem_node = get_resource(&(resources->p_mem_head), base); - - // allocate the resource to the board - if (p_mem_node) { - base = p_mem_node->base; - - p_mem_node->next = func->p_mem_head; - func->p_mem_head = p_mem_node; - } else - return -ENOMEM; - } else if ((temp_register & 0x0BL) == 0x00) { - // Map memory - base = temp_register & 0xFFFFFFF0; - base = ~base + 1; + dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, func->bus, func->device, func->function); - dbg("CND: length = 0x%x\n", base); - mem_node = get_resource(&(resources->mem_head), base); + if (!temp_register) + continue; - // allocate the resource to the board - if (mem_node) { - base = mem_node->base; + base64 = 0L; + if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) { + /* Map IO */ + + /* set base = amount of IO space */ + base = temp_register & 0xFFFFFFFC; + base = ~base + 1; + + dbg("NEED IO length(0x%x)\n", base); + io_node = get_io_resource(&(resources->io_head),(ulong)base); + + /* allocate the resource to the board */ + if (io_node) { + dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length); + base = (u32)io_node->base; + io_node->next = func->io_head; + func->io_head = io_node; + } else { + err("Got NO IO resource(length=0x%x)\n", base); + return -ENOMEM; + } + } else { /* map MEM */ + int prefetchable = 1; + struct pci_resource **res_node = &func->p_mem_head; + char *res_type_str = "PMEM"; + u32 temp_register2; + + if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) { + prefetchable = 0; + res_node = &func->mem_head; + res_type_str++; + } - mem_node->next = func->mem_head; - func->mem_head = mem_node; - } else - return -ENOMEM; - } else if ((temp_register & 0x0BL) == 0x04) { - // Map memory - base = temp_register & 0xFFFFFFF0; - base = ~base + 1; + base = temp_register & 0xFFFFFFF0; + base = ~base + 1; - dbg("CND: length = 0x%x\n", base); - mem_node = get_resource(&(resources->mem_head), base); + switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base); + + if (prefetchable && resources->p_mem_head) + mem_node=get_resource(&(resources->p_mem_head), (ulong)base); + else { + if (prefetchable) + dbg("using MEM for PMEM\n"); + mem_node=get_resource(&(resources->mem_head), (ulong)base); + } - // allocate the resource to the board + /* allocate the resource to the board */ if (mem_node) { - base = mem_node->base; + base = (u32)mem_node->base; + mem_node->next = *res_node; + *res_node = mem_node; + dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, mem_node->length); + } else { + err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base); + return -ENOMEM; + } + break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); + + dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, temp_register, base); + + if (prefetchable && resources->p_mem_head) + mem_node = get_resource(&(resources->p_mem_head), (ulong)base); + else { + if (prefetchable) + dbg("using MEM for PMEM\n"); + mem_node = get_resource(&(resources->mem_head), (ulong)base); + } - mem_node->next = func->mem_head; - func->mem_head = mem_node; - } else + /* allocate the resource to the board */ + if (mem_node) { + base64 = mem_node->base; + mem_node->next = *res_node; + *res_node = mem_node; + dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), (u32)base64, mem_node->length); + } else { + err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base); return -ENOMEM; - } else if ((temp_register & 0x0BL) == 0x06) { - // Those bits are reserved, we can't handle this - return(1); - } else { - // Requesting space below 1M - return(NOT_ENOUGH_RESOURCES); + } + break; + default: + dbg("reserved BAR type=0x%x\n", temp_register); + break; } - rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base); - - // Check for 64-bit base - if ((temp_register & 0x07L) == 0x04) { - cloop += 4; - - // Upper 32 bits of address always zero on today's systems - // FIXME this is probably not true on Alpha and ia64??? - base = 0; - rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base); - } } - } // End of base register loop - // Figure out which interrupt pin this function uses - rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte); + if (base64) { + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); - // If this function needs an interrupt and we are behind a bridge - // and the pin is tied to something that's alread mapped, - // set this one the same - if (temp_byte && resources->irqs && - (resources->irqs->valid_INT & - (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { - // We have to share with something already set up - IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03]; - } else { - // Program IRQ based on card type - rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + cloop += 4; + base64 >>= 32; + + if (base64) { + dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64); + base64 = 0x0L; + } + + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); - if (class_code == PCI_BASE_CLASS_STORAGE) { - IRQ = cpqhp_disk_irq; } else { - IRQ = cpqhp_nic_irq; + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); + } - } + } /* End of base register loop */ - // IRQ Line - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); + /* disable ROM base Address */ + temp_word = 0x00L; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); - if (!behind_bridge) { - rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); - if (rc) - return(1); - } else { - //TBD - this code may also belong in the other clause of this If statement - resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ; - resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03; - } - - // Latency Timer - temp_byte = 0x40; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); - - // Cache Line size - temp_byte = 0x08; - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); - - // disable ROM base Address - temp_dword = 0x00L; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_dword); - - // enable card - temp_word = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, temp_word); - } // End of Not-A-Bridge else + /* Set HP parameters (Cache Line Size, Latency Timer) */ + rc = phprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); + if (rc) + return rc; + + phprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL); + + info("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); + } /* End of Not-A-Bridge else */ else { - // It's some strange type of PCI adapter (Cardbus?) + /* It's some strange type of PCI adapter (Cardbus?) */ return(DEVICE_TYPE_NOT_SUPPORTED); }