diff options
Diffstat (limited to 'drivers/pci/hotplug/cpqphp_core.c')
-rw-r--r-- | drivers/pci/hotplug/cpqphp_core.c | 1100 |
1 files changed, 526 insertions, 574 deletions
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index c2e1bcbb28a7..075b4f4b6e0d 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -25,8 +25,7 @@ | |||
25 | * Send feedback to <greg@kroah.com> | 25 | * Send feedback to <greg@kroah.com> |
26 | * | 26 | * |
27 | * Jan 12, 2003 - Added 66/100/133MHz PCI-X support, | 27 | * Jan 12, 2003 - Added 66/100/133MHz PCI-X support, |
28 | * Torben Mathiasen <torben.mathiasen@hp.com> | 28 | * Torben Mathiasen <torben.mathiasen@hp.com> |
29 | * | ||
30 | */ | 29 | */ |
31 | 30 | ||
32 | #include <linux/module.h> | 31 | #include <linux/module.h> |
@@ -45,7 +44,6 @@ | |||
45 | 44 | ||
46 | #include "cpqphp.h" | 45 | #include "cpqphp.h" |
47 | #include "cpqphp_nvram.h" | 46 | #include "cpqphp_nvram.h" |
48 | #include <asm/pci_x86.h> | ||
49 | 47 | ||
50 | 48 | ||
51 | /* Global variables */ | 49 | /* Global variables */ |
@@ -53,6 +51,7 @@ int cpqhp_debug; | |||
53 | int cpqhp_legacy_mode; | 51 | int cpqhp_legacy_mode; |
54 | struct controller *cpqhp_ctrl_list; /* = NULL */ | 52 | struct controller *cpqhp_ctrl_list; /* = NULL */ |
55 | struct pci_func *cpqhp_slot_list[256]; | 53 | struct pci_func *cpqhp_slot_list[256]; |
54 | struct irq_routing_table *cpqhp_routing_table; | ||
56 | 55 | ||
57 | /* local variables */ | 56 | /* local variables */ |
58 | static void __iomem *smbios_table; | 57 | static void __iomem *smbios_table; |
@@ -78,33 +77,6 @@ MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); | |||
78 | 77 | ||
79 | #define CPQHPC_MODULE_MINOR 208 | 78 | #define CPQHPC_MODULE_MINOR 208 |
80 | 79 | ||
81 | static int one_time_init (void); | ||
82 | static int set_attention_status (struct hotplug_slot *slot, u8 value); | ||
83 | static int process_SI (struct hotplug_slot *slot); | ||
84 | static int process_SS (struct hotplug_slot *slot); | ||
85 | static int hardware_test (struct hotplug_slot *slot, u32 value); | ||
86 | static int get_power_status (struct hotplug_slot *slot, u8 *value); | ||
87 | static int get_attention_status (struct hotplug_slot *slot, u8 *value); | ||
88 | static int get_latch_status (struct hotplug_slot *slot, u8 *value); | ||
89 | static int get_adapter_status (struct hotplug_slot *slot, u8 *value); | ||
90 | static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
91 | static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
92 | |||
93 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | ||
94 | .owner = THIS_MODULE, | ||
95 | .set_attention_status = set_attention_status, | ||
96 | .enable_slot = process_SI, | ||
97 | .disable_slot = process_SS, | ||
98 | .hardware_test = hardware_test, | ||
99 | .get_power_status = get_power_status, | ||
100 | .get_attention_status = get_attention_status, | ||
101 | .get_latch_status = get_latch_status, | ||
102 | .get_adapter_status = get_adapter_status, | ||
103 | .get_max_bus_speed = get_max_bus_speed, | ||
104 | .get_cur_bus_speed = get_cur_bus_speed, | ||
105 | }; | ||
106 | |||
107 | |||
108 | static inline int is_slot64bit(struct slot *slot) | 80 | static inline int is_slot64bit(struct slot *slot) |
109 | { | 81 | { |
110 | return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0; | 82 | return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0; |
@@ -144,7 +116,7 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e | |||
144 | break; | 116 | break; |
145 | } | 117 | } |
146 | } | 118 | } |
147 | 119 | ||
148 | if (!status) | 120 | if (!status) |
149 | fp = NULL; | 121 | fp = NULL; |
150 | 122 | ||
@@ -171,7 +143,7 @@ static int init_SERR(struct controller * ctrl) | |||
171 | tempdword = ctrl->first_slot; | 143 | tempdword = ctrl->first_slot; |
172 | 144 | ||
173 | number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; | 145 | number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; |
174 | // Loop through slots | 146 | /* Loop through slots */ |
175 | while (number_of_slots) { | 147 | while (number_of_slots) { |
176 | physical_slot = tempdword; | 148 | physical_slot = tempdword; |
177 | writeb(0, ctrl->hpc_reg + SLOT_SERR); | 149 | writeb(0, ctrl->hpc_reg + SLOT_SERR); |
@@ -182,41 +154,42 @@ static int init_SERR(struct controller * ctrl) | |||
182 | return 0; | 154 | return 0; |
183 | } | 155 | } |
184 | 156 | ||
185 | 157 | static int init_cpqhp_routing_table(void) | |
186 | /* nice debugging output */ | ||
187 | static int pci_print_IRQ_route (void) | ||
188 | { | 158 | { |
189 | struct irq_routing_table *routing_table; | ||
190 | int len; | 159 | int len; |
191 | int loop; | ||
192 | |||
193 | u8 tbus, tdevice, tslot; | ||
194 | 160 | ||
195 | routing_table = pcibios_get_irq_routing_table(); | 161 | cpqhp_routing_table = pcibios_get_irq_routing_table(); |
196 | if (routing_table == NULL) { | 162 | if (cpqhp_routing_table == NULL) |
197 | err("No BIOS Routing Table??? Not good\n"); | ||
198 | return -ENOMEM; | 163 | return -ENOMEM; |
199 | } | ||
200 | 164 | ||
201 | len = (routing_table->size - sizeof(struct irq_routing_table)) / | 165 | len = cpqhp_routing_table_length(); |
202 | sizeof(struct irq_info); | ||
203 | // Make sure I got at least one entry | ||
204 | if (len == 0) { | 166 | if (len == 0) { |
205 | kfree(routing_table); | 167 | kfree(cpqhp_routing_table); |
168 | cpqhp_routing_table = NULL; | ||
206 | return -1; | 169 | return -1; |
207 | } | 170 | } |
208 | 171 | ||
209 | dbg("bus dev func slot\n"); | 172 | return 0; |
173 | } | ||
174 | |||
175 | /* nice debugging output */ | ||
176 | static void pci_print_IRQ_route(void) | ||
177 | { | ||
178 | int len; | ||
179 | int loop; | ||
180 | u8 tbus, tdevice, tslot; | ||
181 | |||
182 | len = cpqhp_routing_table_length(); | ||
210 | 183 | ||
184 | dbg("bus dev func slot\n"); | ||
211 | for (loop = 0; loop < len; ++loop) { | 185 | for (loop = 0; loop < len; ++loop) { |
212 | tbus = routing_table->slots[loop].bus; | 186 | tbus = cpqhp_routing_table->slots[loop].bus; |
213 | tdevice = routing_table->slots[loop].devfn; | 187 | tdevice = cpqhp_routing_table->slots[loop].devfn; |
214 | tslot = routing_table->slots[loop].slot; | 188 | tslot = cpqhp_routing_table->slots[loop].slot; |
215 | dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot); | 189 | dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot); |
216 | 190 | ||
217 | } | 191 | } |
218 | kfree(routing_table); | 192 | return; |
219 | return 0; | ||
220 | } | 193 | } |
221 | 194 | ||
222 | 195 | ||
@@ -242,9 +215,9 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, | |||
242 | void __iomem *p_max; | 215 | void __iomem *p_max; |
243 | 216 | ||
244 | if (!smbios_table || !curr) | 217 | if (!smbios_table || !curr) |
245 | return(NULL); | 218 | return NULL; |
246 | 219 | ||
247 | // set p_max to the end of the table | 220 | /* set p_max to the end of the table */ |
248 | p_max = smbios_start + readw(smbios_table + ST_LENGTH); | 221 | p_max = smbios_start + readw(smbios_table + ST_LENGTH); |
249 | 222 | ||
250 | p_temp = curr; | 223 | p_temp = curr; |
@@ -253,20 +226,19 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, | |||
253 | while ((p_temp < p_max) && !bail) { | 226 | while ((p_temp < p_max) && !bail) { |
254 | /* Look for the double NULL terminator | 227 | /* Look for the double NULL terminator |
255 | * The first condition is the previous byte | 228 | * The first condition is the previous byte |
256 | * and the second is the curr */ | 229 | * and the second is the curr |
257 | if (!previous_byte && !(readb(p_temp))) { | 230 | */ |
231 | if (!previous_byte && !(readb(p_temp))) | ||
258 | bail = 1; | 232 | bail = 1; |
259 | } | ||
260 | 233 | ||
261 | previous_byte = readb(p_temp); | 234 | previous_byte = readb(p_temp); |
262 | p_temp++; | 235 | p_temp++; |
263 | } | 236 | } |
264 | 237 | ||
265 | if (p_temp < p_max) { | 238 | if (p_temp < p_max) |
266 | return p_temp; | 239 | return p_temp; |
267 | } else { | 240 | else |
268 | return NULL; | 241 | return NULL; |
269 | } | ||
270 | } | 242 | } |
271 | 243 | ||
272 | 244 | ||
@@ -292,21 +264,18 @@ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start, | |||
292 | if (!smbios_table) | 264 | if (!smbios_table) |
293 | return NULL; | 265 | return NULL; |
294 | 266 | ||
295 | if (!previous) { | 267 | if (!previous) |
296 | previous = smbios_start; | 268 | previous = smbios_start; |
297 | } else { | 269 | else |
298 | previous = get_subsequent_smbios_entry(smbios_start, | 270 | previous = get_subsequent_smbios_entry(smbios_start, |
299 | smbios_table, previous); | 271 | smbios_table, previous); |
300 | } | ||
301 | 272 | ||
302 | while (previous) { | 273 | while (previous) |
303 | if (readb(previous + SMBIOS_GENERIC_TYPE) != type) { | 274 | if (readb(previous + SMBIOS_GENERIC_TYPE) != type) |
304 | previous = get_subsequent_smbios_entry(smbios_start, | 275 | previous = get_subsequent_smbios_entry(smbios_start, |
305 | smbios_table, previous); | 276 | smbios_table, previous); |
306 | } else { | 277 | else |
307 | break; | 278 | break; |
308 | } | ||
309 | } | ||
310 | 279 | ||
311 | return previous; | 280 | return previous; |
312 | } | 281 | } |
@@ -322,144 +291,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
322 | kfree(slot); | 291 | kfree(slot); |
323 | } | 292 | } |
324 | 293 | ||
325 | #define SLOT_NAME_SIZE 10 | ||
326 | |||
327 | static int ctrl_slot_setup(struct controller *ctrl, | ||
328 | void __iomem *smbios_start, | ||
329 | void __iomem *smbios_table) | ||
330 | { | ||
331 | struct slot *slot; | ||
332 | struct hotplug_slot *hotplug_slot; | ||
333 | struct hotplug_slot_info *hotplug_slot_info; | ||
334 | u8 number_of_slots; | ||
335 | u8 slot_device; | ||
336 | u8 slot_number; | ||
337 | u8 ctrl_slot; | ||
338 | u32 tempdword; | ||
339 | char name[SLOT_NAME_SIZE]; | ||
340 | void __iomem *slot_entry= NULL; | ||
341 | int result = -ENOMEM; | ||
342 | |||
343 | dbg("%s\n", __func__); | ||
344 | |||
345 | tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); | ||
346 | |||
347 | number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; | ||
348 | slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; | ||
349 | slot_number = ctrl->first_slot; | ||
350 | |||
351 | while (number_of_slots) { | ||
352 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | ||
353 | if (!slot) | ||
354 | goto error; | ||
355 | |||
356 | slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)), | ||
357 | GFP_KERNEL); | ||
358 | if (!slot->hotplug_slot) | ||
359 | goto error_slot; | ||
360 | hotplug_slot = slot->hotplug_slot; | ||
361 | |||
362 | hotplug_slot->info = | ||
363 | kzalloc(sizeof(*(hotplug_slot->info)), | ||
364 | GFP_KERNEL); | ||
365 | if (!hotplug_slot->info) | ||
366 | goto error_hpslot; | ||
367 | hotplug_slot_info = hotplug_slot->info; | ||
368 | |||
369 | slot->ctrl = ctrl; | ||
370 | slot->bus = ctrl->bus; | ||
371 | slot->device = slot_device; | ||
372 | slot->number = slot_number; | ||
373 | dbg("slot->number = %u\n", slot->number); | ||
374 | |||
375 | slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, | ||
376 | slot_entry); | ||
377 | |||
378 | while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != | ||
379 | slot->number)) { | ||
380 | slot_entry = get_SMBIOS_entry(smbios_start, | ||
381 | smbios_table, 9, slot_entry); | ||
382 | } | ||
383 | |||
384 | slot->p_sm_slot = slot_entry; | ||
385 | |||
386 | init_timer(&slot->task_event); | ||
387 | slot->task_event.expires = jiffies + 5 * HZ; | ||
388 | slot->task_event.function = cpqhp_pushbutton_thread; | ||
389 | |||
390 | //FIXME: these capabilities aren't used but if they are | ||
391 | // they need to be correctly implemented | ||
392 | slot->capabilities |= PCISLOT_REPLACE_SUPPORTED; | ||
393 | slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED; | ||
394 | |||
395 | if (is_slot64bit(slot)) | ||
396 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; | ||
397 | if (is_slot66mhz(slot)) | ||
398 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; | ||
399 | if (ctrl->speed == PCI_SPEED_66MHz) | ||
400 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; | ||
401 | |||
402 | ctrl_slot = | ||
403 | slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4); | ||
404 | |||
405 | // Check presence | ||
406 | slot->capabilities |= | ||
407 | ((((~tempdword) >> 23) | | ||
408 | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02; | ||
409 | // Check the switch state | ||
410 | slot->capabilities |= | ||
411 | ((~tempdword & 0xFF) >> ctrl_slot) & 0x01; | ||
412 | // Check the slot enable | ||
413 | slot->capabilities |= | ||
414 | ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; | ||
415 | |||
416 | /* register this slot with the hotplug pci core */ | ||
417 | hotplug_slot->release = &release_slot; | ||
418 | hotplug_slot->private = slot; | ||
419 | snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); | ||
420 | hotplug_slot->ops = &cpqphp_hotplug_slot_ops; | ||
421 | |||
422 | hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot); | ||
423 | hotplug_slot_info->attention_status = | ||
424 | cpq_get_attention_status(ctrl, slot); | ||
425 | hotplug_slot_info->latch_status = | ||
426 | cpq_get_latch_status(ctrl, slot); | ||
427 | hotplug_slot_info->adapter_status = | ||
428 | get_presence_status(ctrl, slot); | ||
429 | |||
430 | dbg("registering bus %d, dev %d, number %d, " | ||
431 | "ctrl->slot_device_offset %d, slot %d\n", | ||
432 | slot->bus, slot->device, | ||
433 | slot->number, ctrl->slot_device_offset, | ||
434 | slot_number); | ||
435 | result = pci_hp_register(hotplug_slot, | ||
436 | ctrl->pci_dev->bus, | ||
437 | slot->device, | ||
438 | name); | ||
439 | if (result) { | ||
440 | err("pci_hp_register failed with error %d\n", result); | ||
441 | goto error_info; | ||
442 | } | ||
443 | |||
444 | slot->next = ctrl->slot; | ||
445 | ctrl->slot = slot; | ||
446 | |||
447 | number_of_slots--; | ||
448 | slot_device++; | ||
449 | slot_number++; | ||
450 | } | ||
451 | |||
452 | return 0; | ||
453 | error_info: | ||
454 | kfree(hotplug_slot_info); | ||
455 | error_hpslot: | ||
456 | kfree(hotplug_slot); | ||
457 | error_slot: | ||
458 | kfree(slot); | ||
459 | error: | ||
460 | return result; | ||
461 | } | ||
462 | |||
463 | static int ctrl_slot_cleanup (struct controller * ctrl) | 294 | static int ctrl_slot_cleanup (struct controller * ctrl) |
464 | { | 295 | { |
465 | struct slot *old_slot, *next_slot; | 296 | struct slot *old_slot, *next_slot; |
@@ -476,36 +307,32 @@ static int ctrl_slot_cleanup (struct controller * ctrl) | |||
476 | 307 | ||
477 | cpqhp_remove_debugfs_files(ctrl); | 308 | cpqhp_remove_debugfs_files(ctrl); |
478 | 309 | ||
479 | //Free IRQ associated with hot plug device | 310 | /* Free IRQ associated with hot plug device */ |
480 | free_irq(ctrl->interrupt, ctrl); | 311 | free_irq(ctrl->interrupt, ctrl); |
481 | //Unmap the memory | 312 | /* Unmap the memory */ |
482 | iounmap(ctrl->hpc_reg); | 313 | iounmap(ctrl->hpc_reg); |
483 | //Finally reclaim PCI mem | 314 | /* Finally reclaim PCI mem */ |
484 | release_mem_region(pci_resource_start(ctrl->pci_dev, 0), | 315 | release_mem_region(pci_resource_start(ctrl->pci_dev, 0), |
485 | pci_resource_len(ctrl->pci_dev, 0)); | 316 | pci_resource_len(ctrl->pci_dev, 0)); |
486 | 317 | ||
487 | return(0); | 318 | return 0; |
488 | } | 319 | } |
489 | 320 | ||
490 | 321 | ||
491 | //============================================================================ | 322 | /** |
492 | // function: get_slot_mapping | 323 | * get_slot_mapping - determine logical slot mapping for PCI device |
493 | // | 324 | * |
494 | // Description: Attempts to determine a logical slot mapping for a PCI | 325 | * Won't work for more than one PCI-PCI bridge in a slot. |
495 | // device. Won't work for more than one PCI-PCI bridge | 326 | * |
496 | // in a slot. | 327 | * @bus_num - bus number of PCI device |
497 | // | 328 | * @dev_num - device number of PCI device |
498 | // Input: u8 bus_num - bus number of PCI device | 329 | * @slot - Pointer to u8 where slot number will be returned |
499 | // u8 dev_num - device number of PCI device | 330 | * |
500 | // u8 *slot - Pointer to u8 where slot number will | 331 | * Output: SUCCESS or FAILURE |
501 | // be returned | 332 | */ |
502 | // | ||
503 | // Output: SUCCESS or FAILURE | ||
504 | //============================================================================= | ||
505 | static int | 333 | static int |
506 | get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) | 334 | get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) |
507 | { | 335 | { |
508 | struct irq_routing_table *PCIIRQRoutingInfoLength; | ||
509 | u32 work; | 336 | u32 work; |
510 | long len; | 337 | long len; |
511 | long loop; | 338 | long loop; |
@@ -516,36 +343,25 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) | |||
516 | 343 | ||
517 | bridgeSlot = 0xFF; | 344 | bridgeSlot = 0xFF; |
518 | 345 | ||
519 | PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table(); | 346 | len = cpqhp_routing_table_length(); |
520 | if (!PCIIRQRoutingInfoLength) | ||
521 | return -1; | ||
522 | |||
523 | len = (PCIIRQRoutingInfoLength->size - | ||
524 | sizeof(struct irq_routing_table)) / sizeof(struct irq_info); | ||
525 | // Make sure I got at least one entry | ||
526 | if (len == 0) { | ||
527 | kfree(PCIIRQRoutingInfoLength); | ||
528 | return -1; | ||
529 | } | ||
530 | |||
531 | for (loop = 0; loop < len; ++loop) { | 347 | for (loop = 0; loop < len; ++loop) { |
532 | tbus = PCIIRQRoutingInfoLength->slots[loop].bus; | 348 | tbus = cpqhp_routing_table->slots[loop].bus; |
533 | tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3; | 349 | tdevice = cpqhp_routing_table->slots[loop].devfn >> 3; |
534 | tslot = PCIIRQRoutingInfoLength->slots[loop].slot; | 350 | tslot = cpqhp_routing_table->slots[loop].slot; |
535 | 351 | ||
536 | if ((tbus == bus_num) && (tdevice == dev_num)) { | 352 | if ((tbus == bus_num) && (tdevice == dev_num)) { |
537 | *slot = tslot; | 353 | *slot = tslot; |
538 | kfree(PCIIRQRoutingInfoLength); | ||
539 | return 0; | 354 | return 0; |
540 | } else { | 355 | } else { |
541 | /* Did not get a match on the target PCI device. Check | 356 | /* Did not get a match on the target PCI device. Check |
542 | * if the current IRQ table entry is a PCI-to-PCI bridge | 357 | * if the current IRQ table entry is a PCI-to-PCI |
543 | * device. If so, and it's secondary bus matches the | 358 | * bridge device. If so, and it's secondary bus |
544 | * bus number for the target device, I need to save the | 359 | * matches the bus number for the target device, I need |
545 | * bridge's slot number. If I can not find an entry for | 360 | * to save the bridge's slot number. If I can not find |
546 | * the target device, I will have to assume it's on the | 361 | * an entry for the target device, I will have to |
547 | * other side of the bridge, and assign it the bridge's | 362 | * assume it's on the other side of the bridge, and |
548 | * slot. */ | 363 | * assign it the bridge's slot. |
364 | */ | ||
549 | bus->number = tbus; | 365 | bus->number = tbus; |
550 | pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), | 366 | pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), |
551 | PCI_CLASS_REVISION, &work); | 367 | PCI_CLASS_REVISION, &work); |
@@ -555,25 +371,23 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) | |||
555 | PCI_DEVFN(tdevice, 0), | 371 | PCI_DEVFN(tdevice, 0), |
556 | PCI_PRIMARY_BUS, &work); | 372 | PCI_PRIMARY_BUS, &work); |
557 | // See if bridge's secondary bus matches target bus. | 373 | // See if bridge's secondary bus matches target bus. |
558 | if (((work >> 8) & 0x000000FF) == (long) bus_num) { | 374 | if (((work >> 8) & 0x000000FF) == (long) bus_num) |
559 | bridgeSlot = tslot; | 375 | bridgeSlot = tslot; |
560 | } | ||
561 | } | 376 | } |
562 | } | 377 | } |
563 | 378 | ||
564 | } | 379 | } |
565 | 380 | ||
566 | // If we got here, we didn't find an entry in the IRQ mapping table | 381 | /* If we got here, we didn't find an entry in the IRQ mapping table for |
567 | // for the target PCI device. If we did determine that the target | 382 | * the target PCI device. If we did determine that the target device |
568 | // device is on the other side of a PCI-to-PCI bridge, return the | 383 | * is on the other side of a PCI-to-PCI bridge, return the slot number |
569 | // slot number for the bridge. | 384 | * for the bridge. |
385 | */ | ||
570 | if (bridgeSlot != 0xFF) { | 386 | if (bridgeSlot != 0xFF) { |
571 | *slot = bridgeSlot; | 387 | *slot = bridgeSlot; |
572 | kfree(PCIIRQRoutingInfoLength); | ||
573 | return 0; | 388 | return 0; |
574 | } | 389 | } |
575 | kfree(PCIIRQRoutingInfoLength); | 390 | /* Couldn't find an entry in the routing table for this PCI device */ |
576 | // Couldn't find an entry in the routing table for this PCI device | ||
577 | return -1; | 391 | return -1; |
578 | } | 392 | } |
579 | 393 | ||
@@ -591,32 +405,32 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, | |||
591 | u8 hp_slot; | 405 | u8 hp_slot; |
592 | 406 | ||
593 | if (func == NULL) | 407 | if (func == NULL) |
594 | return(1); | 408 | return 1; |
595 | 409 | ||
596 | hp_slot = func->device - ctrl->slot_device_offset; | 410 | hp_slot = func->device - ctrl->slot_device_offset; |
597 | 411 | ||
598 | // Wait for exclusive access to hardware | 412 | /* Wait for exclusive access to hardware */ |
599 | mutex_lock(&ctrl->crit_sect); | 413 | mutex_lock(&ctrl->crit_sect); |
600 | 414 | ||
601 | if (status == 1) { | 415 | if (status == 1) |
602 | amber_LED_on (ctrl, hp_slot); | 416 | amber_LED_on (ctrl, hp_slot); |
603 | } else if (status == 0) { | 417 | else if (status == 0) |
604 | amber_LED_off (ctrl, hp_slot); | 418 | amber_LED_off (ctrl, hp_slot); |
605 | } else { | 419 | else { |
606 | // Done with exclusive hardware access | 420 | /* Done with exclusive hardware access */ |
607 | mutex_unlock(&ctrl->crit_sect); | 421 | mutex_unlock(&ctrl->crit_sect); |
608 | return(1); | 422 | return 1; |
609 | } | 423 | } |
610 | 424 | ||
611 | set_SOGO(ctrl); | 425 | set_SOGO(ctrl); |
612 | 426 | ||
613 | // Wait for SOBS to be unset | 427 | /* Wait for SOBS to be unset */ |
614 | wait_for_ctrl_irq (ctrl); | 428 | wait_for_ctrl_irq (ctrl); |
615 | 429 | ||
616 | // Done with exclusive hardware access | 430 | /* Done with exclusive hardware access */ |
617 | mutex_unlock(&ctrl->crit_sect); | 431 | mutex_unlock(&ctrl->crit_sect); |
618 | 432 | ||
619 | return(0); | 433 | return 0; |
620 | } | 434 | } |
621 | 435 | ||
622 | 436 | ||
@@ -719,7 +533,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value) | |||
719 | 533 | ||
720 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | 534 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); |
721 | 535 | ||
722 | return cpqhp_hardware_test(ctrl, value); | 536 | return cpqhp_hardware_test(ctrl, value); |
723 | } | 537 | } |
724 | 538 | ||
725 | 539 | ||
@@ -738,7 +552,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
738 | { | 552 | { |
739 | struct slot *slot = hotplug_slot->private; | 553 | struct slot *slot = hotplug_slot->private; |
740 | struct controller *ctrl = slot->ctrl; | 554 | struct controller *ctrl = slot->ctrl; |
741 | 555 | ||
742 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | 556 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); |
743 | 557 | ||
744 | *value = cpq_get_attention_status(ctrl, slot); | 558 | *value = cpq_get_attention_status(ctrl, slot); |
@@ -793,6 +607,230 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp | |||
793 | return 0; | 607 | return 0; |
794 | } | 608 | } |
795 | 609 | ||
610 | static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { | ||
611 | .set_attention_status = set_attention_status, | ||
612 | .enable_slot = process_SI, | ||
613 | .disable_slot = process_SS, | ||
614 | .hardware_test = hardware_test, | ||
615 | .get_power_status = get_power_status, | ||
616 | .get_attention_status = get_attention_status, | ||
617 | .get_latch_status = get_latch_status, | ||
618 | .get_adapter_status = get_adapter_status, | ||
619 | .get_max_bus_speed = get_max_bus_speed, | ||
620 | .get_cur_bus_speed = get_cur_bus_speed, | ||
621 | }; | ||
622 | |||
623 | #define SLOT_NAME_SIZE 10 | ||
624 | |||
625 | static int ctrl_slot_setup(struct controller *ctrl, | ||
626 | void __iomem *smbios_start, | ||
627 | void __iomem *smbios_table) | ||
628 | { | ||
629 | struct slot *slot; | ||
630 | struct hotplug_slot *hotplug_slot; | ||
631 | struct hotplug_slot_info *hotplug_slot_info; | ||
632 | u8 number_of_slots; | ||
633 | u8 slot_device; | ||
634 | u8 slot_number; | ||
635 | u8 ctrl_slot; | ||
636 | u32 tempdword; | ||
637 | char name[SLOT_NAME_SIZE]; | ||
638 | void __iomem *slot_entry= NULL; | ||
639 | int result = -ENOMEM; | ||
640 | |||
641 | dbg("%s\n", __func__); | ||
642 | |||
643 | tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); | ||
644 | |||
645 | number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; | ||
646 | slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; | ||
647 | slot_number = ctrl->first_slot; | ||
648 | |||
649 | while (number_of_slots) { | ||
650 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | ||
651 | if (!slot) | ||
652 | goto error; | ||
653 | |||
654 | slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)), | ||
655 | GFP_KERNEL); | ||
656 | if (!slot->hotplug_slot) | ||
657 | goto error_slot; | ||
658 | hotplug_slot = slot->hotplug_slot; | ||
659 | |||
660 | hotplug_slot->info = kzalloc(sizeof(*(hotplug_slot->info)), | ||
661 | GFP_KERNEL); | ||
662 | if (!hotplug_slot->info) | ||
663 | goto error_hpslot; | ||
664 | hotplug_slot_info = hotplug_slot->info; | ||
665 | |||
666 | slot->ctrl = ctrl; | ||
667 | slot->bus = ctrl->bus; | ||
668 | slot->device = slot_device; | ||
669 | slot->number = slot_number; | ||
670 | dbg("slot->number = %u\n", slot->number); | ||
671 | |||
672 | slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, | ||
673 | slot_entry); | ||
674 | |||
675 | while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != | ||
676 | slot->number)) { | ||
677 | slot_entry = get_SMBIOS_entry(smbios_start, | ||
678 | smbios_table, 9, slot_entry); | ||
679 | } | ||
680 | |||
681 | slot->p_sm_slot = slot_entry; | ||
682 | |||
683 | init_timer(&slot->task_event); | ||
684 | slot->task_event.expires = jiffies + 5 * HZ; | ||
685 | slot->task_event.function = cpqhp_pushbutton_thread; | ||
686 | |||
687 | /*FIXME: these capabilities aren't used but if they are | ||
688 | * they need to be correctly implemented | ||
689 | */ | ||
690 | slot->capabilities |= PCISLOT_REPLACE_SUPPORTED; | ||
691 | slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED; | ||
692 | |||
693 | if (is_slot64bit(slot)) | ||
694 | slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; | ||
695 | if (is_slot66mhz(slot)) | ||
696 | slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; | ||
697 | if (ctrl->speed == PCI_SPEED_66MHz) | ||
698 | slot->capabilities |= PCISLOT_66_MHZ_OPERATION; | ||
699 | |||
700 | ctrl_slot = | ||
701 | slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4); | ||
702 | |||
703 | /* Check presence */ | ||
704 | slot->capabilities |= | ||
705 | ((((~tempdword) >> 23) | | ||
706 | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02; | ||
707 | /* Check the switch state */ | ||
708 | slot->capabilities |= | ||
709 | ((~tempdword & 0xFF) >> ctrl_slot) & 0x01; | ||
710 | /* Check the slot enable */ | ||
711 | slot->capabilities |= | ||
712 | ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; | ||
713 | |||
714 | /* register this slot with the hotplug pci core */ | ||
715 | hotplug_slot->release = &release_slot; | ||
716 | hotplug_slot->private = slot; | ||
717 | snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); | ||
718 | hotplug_slot->ops = &cpqphp_hotplug_slot_ops; | ||
719 | |||
720 | hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot); | ||
721 | hotplug_slot_info->attention_status = | ||
722 | cpq_get_attention_status(ctrl, slot); | ||
723 | hotplug_slot_info->latch_status = | ||
724 | cpq_get_latch_status(ctrl, slot); | ||
725 | hotplug_slot_info->adapter_status = | ||
726 | get_presence_status(ctrl, slot); | ||
727 | |||
728 | dbg("registering bus %d, dev %d, number %d, " | ||
729 | "ctrl->slot_device_offset %d, slot %d\n", | ||
730 | slot->bus, slot->device, | ||
731 | slot->number, ctrl->slot_device_offset, | ||
732 | slot_number); | ||
733 | result = pci_hp_register(hotplug_slot, | ||
734 | ctrl->pci_dev->bus, | ||
735 | slot->device, | ||
736 | name); | ||
737 | if (result) { | ||
738 | err("pci_hp_register failed with error %d\n", result); | ||
739 | goto error_info; | ||
740 | } | ||
741 | |||
742 | slot->next = ctrl->slot; | ||
743 | ctrl->slot = slot; | ||
744 | |||
745 | number_of_slots--; | ||
746 | slot_device++; | ||
747 | slot_number++; | ||
748 | } | ||
749 | |||
750 | return 0; | ||
751 | error_info: | ||
752 | kfree(hotplug_slot_info); | ||
753 | error_hpslot: | ||
754 | kfree(hotplug_slot); | ||
755 | error_slot: | ||
756 | kfree(slot); | ||
757 | error: | ||
758 | return result; | ||
759 | } | ||
760 | |||
761 | static int one_time_init(void) | ||
762 | { | ||
763 | int loop; | ||
764 | int retval = 0; | ||
765 | |||
766 | if (initialized) | ||
767 | return 0; | ||
768 | |||
769 | power_mode = 0; | ||
770 | |||
771 | retval = init_cpqhp_routing_table(); | ||
772 | if (retval) | ||
773 | goto error; | ||
774 | |||
775 | if (cpqhp_debug) | ||
776 | pci_print_IRQ_route(); | ||
777 | |||
778 | dbg("Initialize + Start the notification mechanism \n"); | ||
779 | |||
780 | retval = cpqhp_event_start_thread(); | ||
781 | if (retval) | ||
782 | goto error; | ||
783 | |||
784 | dbg("Initialize slot lists\n"); | ||
785 | for (loop = 0; loop < 256; loop++) | ||
786 | cpqhp_slot_list[loop] = NULL; | ||
787 | |||
788 | /* FIXME: We also need to hook the NMI handler eventually. | ||
789 | * this also needs to be worked with Christoph | ||
790 | * register_NMI_handler(); | ||
791 | */ | ||
792 | /* Map rom address */ | ||
793 | cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); | ||
794 | if (!cpqhp_rom_start) { | ||
795 | err ("Could not ioremap memory region for ROM\n"); | ||
796 | retval = -EIO; | ||
797 | goto error; | ||
798 | } | ||
799 | |||
800 | /* Now, map the int15 entry point if we are on compaq specific | ||
801 | * hardware | ||
802 | */ | ||
803 | compaq_nvram_init(cpqhp_rom_start); | ||
804 | |||
805 | /* Map smbios table entry point structure */ | ||
806 | smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, | ||
807 | cpqhp_rom_start + ROM_PHY_LEN); | ||
808 | if (!smbios_table) { | ||
809 | err ("Could not find the SMBIOS pointer in memory\n"); | ||
810 | retval = -EIO; | ||
811 | goto error_rom_start; | ||
812 | } | ||
813 | |||
814 | smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), | ||
815 | readw(smbios_table + ST_LENGTH)); | ||
816 | if (!smbios_start) { | ||
817 | err ("Could not ioremap memory region taken from SMBIOS values\n"); | ||
818 | retval = -EIO; | ||
819 | goto error_smbios_start; | ||
820 | } | ||
821 | |||
822 | initialized = 1; | ||
823 | |||
824 | return retval; | ||
825 | |||
826 | error_smbios_start: | ||
827 | iounmap(smbios_start); | ||
828 | error_rom_start: | ||
829 | iounmap(cpqhp_rom_start); | ||
830 | error: | ||
831 | return retval; | ||
832 | } | ||
833 | |||
796 | static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 834 | static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
797 | { | 835 | { |
798 | u8 num_of_slots = 0; | 836 | u8 num_of_slots = 0; |
@@ -815,7 +853,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
815 | return err; | 853 | return err; |
816 | } | 854 | } |
817 | 855 | ||
818 | // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery | 856 | /* Need to read VID early b/c it's used to differentiate CPQ and INTC |
857 | * discovery | ||
858 | */ | ||
819 | rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); | 859 | rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); |
820 | if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) { | 860 | if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) { |
821 | err(msg_HPC_non_compaq_or_intel); | 861 | err(msg_HPC_non_compaq_or_intel); |
@@ -832,217 +872,209 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
832 | } | 872 | } |
833 | 873 | ||
834 | /* Check for the proper subsytem ID's | 874 | /* Check for the proper subsytem ID's |
835 | * Intel uses a different SSID programming model than Compaq. | 875 | * Intel uses a different SSID programming model than Compaq. |
836 | * For Intel, each SSID bit identifies a PHP capability. | 876 | * For Intel, each SSID bit identifies a PHP capability. |
837 | * Also Intel HPC's may have RID=0. | 877 | * Also Intel HPC's may have RID=0. |
838 | */ | 878 | */ |
839 | if ((pdev->revision > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) { | 879 | if ((pdev->revision <= 2) && (vendor_id != PCI_VENDOR_ID_INTEL)) { |
840 | // TODO: This code can be made to support non-Compaq or Intel subsystem IDs | 880 | err(msg_HPC_not_supported); |
841 | rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); | 881 | return -ENODEV; |
842 | if (rc) { | 882 | } |
843 | err("%s : pci_read_config_word failed\n", __func__); | ||
844 | goto err_disable_device; | ||
845 | } | ||
846 | dbg("Subsystem Vendor ID: %x\n", subsystem_vid); | ||
847 | if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { | ||
848 | err(msg_HPC_non_compaq_or_intel); | ||
849 | rc = -ENODEV; | ||
850 | goto err_disable_device; | ||
851 | } | ||
852 | 883 | ||
853 | ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); | 884 | /* TODO: This code can be made to support non-Compaq or Intel |
854 | if (!ctrl) { | 885 | * subsystem IDs |
855 | err("%s : out of memory\n", __func__); | 886 | */ |
856 | rc = -ENOMEM; | 887 | rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); |
857 | goto err_disable_device; | 888 | if (rc) { |
858 | } | 889 | err("%s : pci_read_config_word failed\n", __func__); |
890 | goto err_disable_device; | ||
891 | } | ||
892 | dbg("Subsystem Vendor ID: %x\n", subsystem_vid); | ||
893 | if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { | ||
894 | err(msg_HPC_non_compaq_or_intel); | ||
895 | rc = -ENODEV; | ||
896 | goto err_disable_device; | ||
897 | } | ||
859 | 898 | ||
860 | rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); | 899 | ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); |
861 | if (rc) { | 900 | if (!ctrl) { |
862 | err("%s : pci_read_config_word failed\n", __func__); | 901 | err("%s : out of memory\n", __func__); |
863 | goto err_free_ctrl; | 902 | rc = -ENOMEM; |
864 | } | 903 | goto err_disable_device; |
904 | } | ||
865 | 905 | ||
866 | info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid); | 906 | rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); |
867 | 907 | if (rc) { | |
868 | /* Set Vendor ID, so it can be accessed later from other functions */ | 908 | err("%s : pci_read_config_word failed\n", __func__); |
869 | ctrl->vendor_id = vendor_id; | 909 | goto err_free_ctrl; |
870 | 910 | } | |
871 | switch (subsystem_vid) { | ||
872 | case PCI_VENDOR_ID_COMPAQ: | ||
873 | if (pdev->revision >= 0x13) { /* CIOBX */ | ||
874 | ctrl->push_flag = 1; | ||
875 | ctrl->slot_switch_type = 1; | ||
876 | ctrl->push_button = 1; | ||
877 | ctrl->pci_config_space = 1; | ||
878 | ctrl->defeature_PHP = 1; | ||
879 | ctrl->pcix_support = 1; | ||
880 | ctrl->pcix_speed_capability = 1; | ||
881 | pci_read_config_byte(pdev, 0x41, &bus_cap); | ||
882 | if (bus_cap & 0x80) { | ||
883 | dbg("bus max supports 133MHz PCI-X\n"); | ||
884 | ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; | ||
885 | break; | ||
886 | } | ||
887 | if (bus_cap & 0x40) { | ||
888 | dbg("bus max supports 100MHz PCI-X\n"); | ||
889 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | ||
890 | break; | ||
891 | } | ||
892 | if (bus_cap & 20) { | ||
893 | dbg("bus max supports 66MHz PCI-X\n"); | ||
894 | ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; | ||
895 | break; | ||
896 | } | ||
897 | if (bus_cap & 10) { | ||
898 | dbg("bus max supports 66MHz PCI\n"); | ||
899 | ctrl->speed_capability = PCI_SPEED_66MHz; | ||
900 | break; | ||
901 | } | ||
902 | |||
903 | break; | ||
904 | } | ||
905 | |||
906 | switch (subsystem_deviceid) { | ||
907 | case PCI_SUB_HPC_ID: | ||
908 | /* Original 6500/7000 implementation */ | ||
909 | ctrl->slot_switch_type = 1; | ||
910 | ctrl->speed_capability = PCI_SPEED_33MHz; | ||
911 | ctrl->push_button = 0; | ||
912 | ctrl->pci_config_space = 1; | ||
913 | ctrl->defeature_PHP = 1; | ||
914 | ctrl->pcix_support = 0; | ||
915 | ctrl->pcix_speed_capability = 0; | ||
916 | break; | ||
917 | case PCI_SUB_HPC_ID2: | ||
918 | /* First Pushbutton implementation */ | ||
919 | ctrl->push_flag = 1; | ||
920 | ctrl->slot_switch_type = 1; | ||
921 | ctrl->speed_capability = PCI_SPEED_33MHz; | ||
922 | ctrl->push_button = 1; | ||
923 | ctrl->pci_config_space = 1; | ||
924 | ctrl->defeature_PHP = 1; | ||
925 | ctrl->pcix_support = 0; | ||
926 | ctrl->pcix_speed_capability = 0; | ||
927 | break; | ||
928 | case PCI_SUB_HPC_ID_INTC: | ||
929 | /* Third party (6500/7000) */ | ||
930 | ctrl->slot_switch_type = 1; | ||
931 | ctrl->speed_capability = PCI_SPEED_33MHz; | ||
932 | ctrl->push_button = 0; | ||
933 | ctrl->pci_config_space = 1; | ||
934 | ctrl->defeature_PHP = 1; | ||
935 | ctrl->pcix_support = 0; | ||
936 | ctrl->pcix_speed_capability = 0; | ||
937 | break; | ||
938 | case PCI_SUB_HPC_ID3: | ||
939 | /* First 66 Mhz implementation */ | ||
940 | ctrl->push_flag = 1; | ||
941 | ctrl->slot_switch_type = 1; | ||
942 | ctrl->speed_capability = PCI_SPEED_66MHz; | ||
943 | ctrl->push_button = 1; | ||
944 | ctrl->pci_config_space = 1; | ||
945 | ctrl->defeature_PHP = 1; | ||
946 | ctrl->pcix_support = 0; | ||
947 | ctrl->pcix_speed_capability = 0; | ||
948 | break; | ||
949 | case PCI_SUB_HPC_ID4: | ||
950 | /* First PCI-X implementation, 100MHz */ | ||
951 | ctrl->push_flag = 1; | ||
952 | ctrl->slot_switch_type = 1; | ||
953 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | ||
954 | ctrl->push_button = 1; | ||
955 | ctrl->pci_config_space = 1; | ||
956 | ctrl->defeature_PHP = 1; | ||
957 | ctrl->pcix_support = 1; | ||
958 | ctrl->pcix_speed_capability = 0; | ||
959 | break; | ||
960 | default: | ||
961 | err(msg_HPC_not_supported); | ||
962 | rc = -ENODEV; | ||
963 | goto err_free_ctrl; | ||
964 | } | ||
965 | break; | ||
966 | 911 | ||
967 | case PCI_VENDOR_ID_INTEL: | 912 | info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid); |
968 | /* Check for speed capability (0=33, 1=66) */ | 913 | |
969 | if (subsystem_deviceid & 0x0001) { | 914 | /* Set Vendor ID, so it can be accessed later from other |
970 | ctrl->speed_capability = PCI_SPEED_66MHz; | 915 | * functions |
971 | } else { | 916 | */ |
972 | ctrl->speed_capability = PCI_SPEED_33MHz; | 917 | ctrl->vendor_id = vendor_id; |
973 | } | 918 | |
974 | 919 | switch (subsystem_vid) { | |
975 | /* Check for push button */ | 920 | case PCI_VENDOR_ID_COMPAQ: |
976 | if (subsystem_deviceid & 0x0002) { | 921 | if (pdev->revision >= 0x13) { /* CIOBX */ |
977 | /* no push button */ | 922 | ctrl->push_flag = 1; |
978 | ctrl->push_button = 0; | 923 | ctrl->slot_switch_type = 1; |
979 | } else { | 924 | ctrl->push_button = 1; |
980 | /* push button supported */ | 925 | ctrl->pci_config_space = 1; |
981 | ctrl->push_button = 1; | 926 | ctrl->defeature_PHP = 1; |
982 | } | 927 | ctrl->pcix_support = 1; |
983 | 928 | ctrl->pcix_speed_capability = 1; | |
984 | /* Check for slot switch type (0=mechanical, 1=not mechanical) */ | 929 | pci_read_config_byte(pdev, 0x41, &bus_cap); |
985 | if (subsystem_deviceid & 0x0004) { | 930 | if (bus_cap & 0x80) { |
986 | /* no switch */ | 931 | dbg("bus max supports 133MHz PCI-X\n"); |
987 | ctrl->slot_switch_type = 0; | 932 | ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; |
988 | } else { | ||
989 | /* switch */ | ||
990 | ctrl->slot_switch_type = 1; | ||
991 | } | ||
992 | |||
993 | /* PHP Status (0=De-feature PHP, 1=Normal operation) */ | ||
994 | if (subsystem_deviceid & 0x0008) { | ||
995 | ctrl->defeature_PHP = 1; // PHP supported | ||
996 | } else { | ||
997 | ctrl->defeature_PHP = 0; // PHP not supported | ||
998 | } | ||
999 | |||
1000 | /* Alternate Base Address Register Interface (0=not supported, 1=supported) */ | ||
1001 | if (subsystem_deviceid & 0x0010) { | ||
1002 | ctrl->alternate_base_address = 1; // supported | ||
1003 | } else { | ||
1004 | ctrl->alternate_base_address = 0; // not supported | ||
1005 | } | ||
1006 | |||
1007 | /* PCI Config Space Index (0=not supported, 1=supported) */ | ||
1008 | if (subsystem_deviceid & 0x0020) { | ||
1009 | ctrl->pci_config_space = 1; // supported | ||
1010 | } else { | ||
1011 | ctrl->pci_config_space = 0; // not supported | ||
1012 | } | ||
1013 | |||
1014 | /* PCI-X support */ | ||
1015 | if (subsystem_deviceid & 0x0080) { | ||
1016 | /* PCI-X capable */ | ||
1017 | ctrl->pcix_support = 1; | ||
1018 | /* Frequency of operation in PCI-X mode */ | ||
1019 | if (subsystem_deviceid & 0x0040) { | ||
1020 | /* 133MHz PCI-X if bit 7 is 1 */ | ||
1021 | ctrl->pcix_speed_capability = 1; | ||
1022 | } else { | ||
1023 | /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */ | ||
1024 | /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */ | ||
1025 | ctrl->pcix_speed_capability = 0; | ||
1026 | } | ||
1027 | } else { | ||
1028 | /* Conventional PCI */ | ||
1029 | ctrl->pcix_support = 0; | ||
1030 | ctrl->pcix_speed_capability = 0; | ||
1031 | } | ||
1032 | break; | 933 | break; |
934 | } | ||
935 | if (bus_cap & 0x40) { | ||
936 | dbg("bus max supports 100MHz PCI-X\n"); | ||
937 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | ||
938 | break; | ||
939 | } | ||
940 | if (bus_cap & 20) { | ||
941 | dbg("bus max supports 66MHz PCI-X\n"); | ||
942 | ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; | ||
943 | break; | ||
944 | } | ||
945 | if (bus_cap & 10) { | ||
946 | dbg("bus max supports 66MHz PCI\n"); | ||
947 | ctrl->speed_capability = PCI_SPEED_66MHz; | ||
948 | break; | ||
949 | } | ||
950 | |||
951 | break; | ||
952 | } | ||
1033 | 953 | ||
1034 | default: | 954 | switch (subsystem_deviceid) { |
1035 | err(msg_HPC_not_supported); | 955 | case PCI_SUB_HPC_ID: |
1036 | rc = -ENODEV; | 956 | /* Original 6500/7000 implementation */ |
1037 | goto err_free_ctrl; | 957 | ctrl->slot_switch_type = 1; |
958 | ctrl->speed_capability = PCI_SPEED_33MHz; | ||
959 | ctrl->push_button = 0; | ||
960 | ctrl->pci_config_space = 1; | ||
961 | ctrl->defeature_PHP = 1; | ||
962 | ctrl->pcix_support = 0; | ||
963 | ctrl->pcix_speed_capability = 0; | ||
964 | break; | ||
965 | case PCI_SUB_HPC_ID2: | ||
966 | /* First Pushbutton implementation */ | ||
967 | ctrl->push_flag = 1; | ||
968 | ctrl->slot_switch_type = 1; | ||
969 | ctrl->speed_capability = PCI_SPEED_33MHz; | ||
970 | ctrl->push_button = 1; | ||
971 | ctrl->pci_config_space = 1; | ||
972 | ctrl->defeature_PHP = 1; | ||
973 | ctrl->pcix_support = 0; | ||
974 | ctrl->pcix_speed_capability = 0; | ||
975 | break; | ||
976 | case PCI_SUB_HPC_ID_INTC: | ||
977 | /* Third party (6500/7000) */ | ||
978 | ctrl->slot_switch_type = 1; | ||
979 | ctrl->speed_capability = PCI_SPEED_33MHz; | ||
980 | ctrl->push_button = 0; | ||
981 | ctrl->pci_config_space = 1; | ||
982 | ctrl->defeature_PHP = 1; | ||
983 | ctrl->pcix_support = 0; | ||
984 | ctrl->pcix_speed_capability = 0; | ||
985 | break; | ||
986 | case PCI_SUB_HPC_ID3: | ||
987 | /* First 66 Mhz implementation */ | ||
988 | ctrl->push_flag = 1; | ||
989 | ctrl->slot_switch_type = 1; | ||
990 | ctrl->speed_capability = PCI_SPEED_66MHz; | ||
991 | ctrl->push_button = 1; | ||
992 | ctrl->pci_config_space = 1; | ||
993 | ctrl->defeature_PHP = 1; | ||
994 | ctrl->pcix_support = 0; | ||
995 | ctrl->pcix_speed_capability = 0; | ||
996 | break; | ||
997 | case PCI_SUB_HPC_ID4: | ||
998 | /* First PCI-X implementation, 100MHz */ | ||
999 | ctrl->push_flag = 1; | ||
1000 | ctrl->slot_switch_type = 1; | ||
1001 | ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; | ||
1002 | ctrl->push_button = 1; | ||
1003 | ctrl->pci_config_space = 1; | ||
1004 | ctrl->defeature_PHP = 1; | ||
1005 | ctrl->pcix_support = 1; | ||
1006 | ctrl->pcix_speed_capability = 0; | ||
1007 | break; | ||
1008 | default: | ||
1009 | err(msg_HPC_not_supported); | ||
1010 | rc = -ENODEV; | ||
1011 | goto err_free_ctrl; | ||
1038 | } | 1012 | } |
1013 | break; | ||
1014 | |||
1015 | case PCI_VENDOR_ID_INTEL: | ||
1016 | /* Check for speed capability (0=33, 1=66) */ | ||
1017 | if (subsystem_deviceid & 0x0001) | ||
1018 | ctrl->speed_capability = PCI_SPEED_66MHz; | ||
1019 | else | ||
1020 | ctrl->speed_capability = PCI_SPEED_33MHz; | ||
1021 | |||
1022 | /* Check for push button */ | ||
1023 | if (subsystem_deviceid & 0x0002) | ||
1024 | ctrl->push_button = 0; | ||
1025 | else | ||
1026 | ctrl->push_button = 1; | ||
1027 | |||
1028 | /* Check for slot switch type (0=mechanical, 1=not mechanical) */ | ||
1029 | if (subsystem_deviceid & 0x0004) | ||
1030 | ctrl->slot_switch_type = 0; | ||
1031 | else | ||
1032 | ctrl->slot_switch_type = 1; | ||
1033 | |||
1034 | /* PHP Status (0=De-feature PHP, 1=Normal operation) */ | ||
1035 | if (subsystem_deviceid & 0x0008) | ||
1036 | ctrl->defeature_PHP = 1; /* PHP supported */ | ||
1037 | else | ||
1038 | ctrl->defeature_PHP = 0; /* PHP not supported */ | ||
1039 | |||
1040 | /* Alternate Base Address Register Interface | ||
1041 | * (0=not supported, 1=supported) | ||
1042 | */ | ||
1043 | if (subsystem_deviceid & 0x0010) | ||
1044 | ctrl->alternate_base_address = 1; | ||
1045 | else | ||
1046 | ctrl->alternate_base_address = 0; | ||
1047 | |||
1048 | /* PCI Config Space Index (0=not supported, 1=supported) */ | ||
1049 | if (subsystem_deviceid & 0x0020) | ||
1050 | ctrl->pci_config_space = 1; | ||
1051 | else | ||
1052 | ctrl->pci_config_space = 0; | ||
1053 | |||
1054 | /* PCI-X support */ | ||
1055 | if (subsystem_deviceid & 0x0080) { | ||
1056 | ctrl->pcix_support = 1; | ||
1057 | if (subsystem_deviceid & 0x0040) | ||
1058 | /* 133MHz PCI-X if bit 7 is 1 */ | ||
1059 | ctrl->pcix_speed_capability = 1; | ||
1060 | else | ||
1061 | /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */ | ||
1062 | /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */ | ||
1063 | ctrl->pcix_speed_capability = 0; | ||
1064 | } else { | ||
1065 | /* Conventional PCI */ | ||
1066 | ctrl->pcix_support = 0; | ||
1067 | ctrl->pcix_speed_capability = 0; | ||
1068 | } | ||
1069 | break; | ||
1039 | 1070 | ||
1040 | } else { | 1071 | default: |
1041 | err(msg_HPC_not_supported); | 1072 | err(msg_HPC_not_supported); |
1042 | return -ENODEV; | 1073 | rc = -ENODEV; |
1074 | goto err_free_ctrl; | ||
1043 | } | 1075 | } |
1044 | 1076 | ||
1045 | // Tell the user that we found one. | 1077 | /* Tell the user that we found one. */ |
1046 | info("Initializing the PCI hot plug controller residing on PCI bus %d\n", | 1078 | info("Initializing the PCI hot plug controller residing on PCI bus %d\n", |
1047 | pdev->bus->number); | 1079 | pdev->bus->number); |
1048 | 1080 | ||
@@ -1087,7 +1119,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1087 | if (rc) { | 1119 | if (rc) { |
1088 | goto err_free_bus; | 1120 | goto err_free_bus; |
1089 | } | 1121 | } |
1090 | 1122 | ||
1091 | dbg("pdev = %p\n", pdev); | 1123 | dbg("pdev = %p\n", pdev); |
1092 | dbg("pci resource start %llx\n", (unsigned long long)pci_resource_start(pdev, 0)); | 1124 | dbg("pci resource start %llx\n", (unsigned long long)pci_resource_start(pdev, 0)); |
1093 | dbg("pci resource len %llx\n", (unsigned long long)pci_resource_len(pdev, 0)); | 1125 | dbg("pci resource len %llx\n", (unsigned long long)pci_resource_len(pdev, 0)); |
@@ -1109,7 +1141,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1109 | goto err_free_mem_region; | 1141 | goto err_free_mem_region; |
1110 | } | 1142 | } |
1111 | 1143 | ||
1112 | // Check for 66Mhz operation | 1144 | /* Check for 66Mhz operation */ |
1113 | ctrl->speed = get_controller_speed(ctrl); | 1145 | ctrl->speed = get_controller_speed(ctrl); |
1114 | 1146 | ||
1115 | 1147 | ||
@@ -1120,7 +1152,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1120 | * | 1152 | * |
1121 | ********************************************************/ | 1153 | ********************************************************/ |
1122 | 1154 | ||
1123 | // find the physical slot number of the first hot plug slot | 1155 | /* find the physical slot number of the first hot plug slot */ |
1124 | 1156 | ||
1125 | /* Get slot won't work for devices behind bridges, but | 1157 | /* Get slot won't work for devices behind bridges, but |
1126 | * in this case it will always be called for the "base" | 1158 | * in this case it will always be called for the "base" |
@@ -1137,7 +1169,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1137 | goto err_iounmap; | 1169 | goto err_iounmap; |
1138 | } | 1170 | } |
1139 | 1171 | ||
1140 | // Store PCI Config Space for all devices on this bus | 1172 | /* Store PCI Config Space for all devices on this bus */ |
1141 | rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK)); | 1173 | rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK)); |
1142 | if (rc) { | 1174 | if (rc) { |
1143 | err("%s: unable to save PCI configuration data, error %d\n", | 1175 | err("%s: unable to save PCI configuration data, error %d\n", |
@@ -1148,7 +1180,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1148 | /* | 1180 | /* |
1149 | * Get IO, memory, and IRQ resources for new devices | 1181 | * Get IO, memory, and IRQ resources for new devices |
1150 | */ | 1182 | */ |
1151 | // The next line is required for cpqhp_find_available_resources | 1183 | /* The next line is required for cpqhp_find_available_resources */ |
1152 | ctrl->interrupt = pdev->irq; | 1184 | ctrl->interrupt = pdev->irq; |
1153 | if (ctrl->interrupt < 0x10) { | 1185 | if (ctrl->interrupt < 0x10) { |
1154 | cpqhp_legacy_mode = 1; | 1186 | cpqhp_legacy_mode = 1; |
@@ -1182,7 +1214,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1182 | __func__, rc); | 1214 | __func__, rc); |
1183 | goto err_iounmap; | 1215 | goto err_iounmap; |
1184 | } | 1216 | } |
1185 | 1217 | ||
1186 | /* Mask all general input interrupts */ | 1218 | /* Mask all general input interrupts */ |
1187 | writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK); | 1219 | writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK); |
1188 | 1220 | ||
@@ -1196,12 +1228,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1196 | goto err_iounmap; | 1228 | goto err_iounmap; |
1197 | } | 1229 | } |
1198 | 1230 | ||
1199 | /* Enable Shift Out interrupt and clear it, also enable SERR on power fault */ | 1231 | /* Enable Shift Out interrupt and clear it, also enable SERR on power |
1232 | * fault | ||
1233 | */ | ||
1200 | temp_word = readw(ctrl->hpc_reg + MISC); | 1234 | temp_word = readw(ctrl->hpc_reg + MISC); |
1201 | temp_word |= 0x4006; | 1235 | temp_word |= 0x4006; |
1202 | writew(temp_word, ctrl->hpc_reg + MISC); | 1236 | writew(temp_word, ctrl->hpc_reg + MISC); |
1203 | 1237 | ||
1204 | // Changed 05/05/97 to clear all interrupts at start | 1238 | /* Changed 05/05/97 to clear all interrupts at start */ |
1205 | writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR); | 1239 | writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR); |
1206 | 1240 | ||
1207 | ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); | 1241 | ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); |
@@ -1216,13 +1250,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1216 | cpqhp_ctrl_list = ctrl; | 1250 | cpqhp_ctrl_list = ctrl; |
1217 | } | 1251 | } |
1218 | 1252 | ||
1219 | // turn off empty slots here unless command line option "ON" set | 1253 | /* turn off empty slots here unless command line option "ON" set |
1220 | // Wait for exclusive access to hardware | 1254 | * Wait for exclusive access to hardware |
1255 | */ | ||
1221 | mutex_lock(&ctrl->crit_sect); | 1256 | mutex_lock(&ctrl->crit_sect); |
1222 | 1257 | ||
1223 | num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; | 1258 | num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; |
1224 | 1259 | ||
1225 | // find first device number for the ctrl | 1260 | /* find first device number for the ctrl */ |
1226 | device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; | 1261 | device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; |
1227 | 1262 | ||
1228 | while (num_of_slots) { | 1263 | while (num_of_slots) { |
@@ -1234,23 +1269,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1234 | hp_slot = func->device - ctrl->slot_device_offset; | 1269 | hp_slot = func->device - ctrl->slot_device_offset; |
1235 | dbg("hp_slot: %d\n", hp_slot); | 1270 | dbg("hp_slot: %d\n", hp_slot); |
1236 | 1271 | ||
1237 | // We have to save the presence info for these slots | 1272 | /* We have to save the presence info for these slots */ |
1238 | temp_word = ctrl->ctrl_int_comp >> 16; | 1273 | temp_word = ctrl->ctrl_int_comp >> 16; |
1239 | func->presence_save = (temp_word >> hp_slot) & 0x01; | 1274 | func->presence_save = (temp_word >> hp_slot) & 0x01; |
1240 | func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; | 1275 | func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; |
1241 | 1276 | ||
1242 | if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { | 1277 | if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) |
1243 | func->switch_save = 0; | 1278 | func->switch_save = 0; |
1244 | } else { | 1279 | else |
1245 | func->switch_save = 0x10; | 1280 | func->switch_save = 0x10; |
1246 | } | ||
1247 | 1281 | ||
1248 | if (!power_mode) { | 1282 | if (!power_mode) |
1249 | if (!func->is_a_board) { | 1283 | if (!func->is_a_board) { |
1250 | green_LED_off(ctrl, hp_slot); | 1284 | green_LED_off(ctrl, hp_slot); |
1251 | slot_disable(ctrl, hp_slot); | 1285 | slot_disable(ctrl, hp_slot); |
1252 | } | 1286 | } |
1253 | } | ||
1254 | 1287 | ||
1255 | device++; | 1288 | device++; |
1256 | num_of_slots--; | 1289 | num_of_slots--; |
@@ -1258,7 +1291,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1258 | 1291 | ||
1259 | if (!power_mode) { | 1292 | if (!power_mode) { |
1260 | set_SOGO(ctrl); | 1293 | set_SOGO(ctrl); |
1261 | // Wait for SOBS to be unset | 1294 | /* Wait for SOBS to be unset */ |
1262 | wait_for_ctrl_irq(ctrl); | 1295 | wait_for_ctrl_irq(ctrl); |
1263 | } | 1296 | } |
1264 | 1297 | ||
@@ -1269,7 +1302,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1269 | goto err_free_irq; | 1302 | goto err_free_irq; |
1270 | } | 1303 | } |
1271 | 1304 | ||
1272 | // Done with exclusive hardware access | 1305 | /* Done with exclusive hardware access */ |
1273 | mutex_unlock(&ctrl->crit_sect); | 1306 | mutex_unlock(&ctrl->crit_sect); |
1274 | 1307 | ||
1275 | cpqhp_create_debugfs_files(ctrl); | 1308 | cpqhp_create_debugfs_files(ctrl); |
@@ -1291,77 +1324,6 @@ err_disable_device: | |||
1291 | return rc; | 1324 | return rc; |
1292 | } | 1325 | } |
1293 | 1326 | ||
1294 | |||
1295 | static int one_time_init(void) | ||
1296 | { | ||
1297 | int loop; | ||
1298 | int retval = 0; | ||
1299 | |||
1300 | if (initialized) | ||
1301 | return 0; | ||
1302 | |||
1303 | power_mode = 0; | ||
1304 | |||
1305 | retval = pci_print_IRQ_route(); | ||
1306 | if (retval) | ||
1307 | goto error; | ||
1308 | |||
1309 | dbg("Initialize + Start the notification mechanism \n"); | ||
1310 | |||
1311 | retval = cpqhp_event_start_thread(); | ||
1312 | if (retval) | ||
1313 | goto error; | ||
1314 | |||
1315 | dbg("Initialize slot lists\n"); | ||
1316 | for (loop = 0; loop < 256; loop++) { | ||
1317 | cpqhp_slot_list[loop] = NULL; | ||
1318 | } | ||
1319 | |||
1320 | // FIXME: We also need to hook the NMI handler eventually. | ||
1321 | // this also needs to be worked with Christoph | ||
1322 | // register_NMI_handler(); | ||
1323 | |||
1324 | // Map rom address | ||
1325 | cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); | ||
1326 | if (!cpqhp_rom_start) { | ||
1327 | err ("Could not ioremap memory region for ROM\n"); | ||
1328 | retval = -EIO; | ||
1329 | goto error; | ||
1330 | } | ||
1331 | |||
1332 | /* Now, map the int15 entry point if we are on compaq specific hardware */ | ||
1333 | compaq_nvram_init(cpqhp_rom_start); | ||
1334 | |||
1335 | /* Map smbios table entry point structure */ | ||
1336 | smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, | ||
1337 | cpqhp_rom_start + ROM_PHY_LEN); | ||
1338 | if (!smbios_table) { | ||
1339 | err ("Could not find the SMBIOS pointer in memory\n"); | ||
1340 | retval = -EIO; | ||
1341 | goto error_rom_start; | ||
1342 | } | ||
1343 | |||
1344 | smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), | ||
1345 | readw(smbios_table + ST_LENGTH)); | ||
1346 | if (!smbios_start) { | ||
1347 | err ("Could not ioremap memory region taken from SMBIOS values\n"); | ||
1348 | retval = -EIO; | ||
1349 | goto error_smbios_start; | ||
1350 | } | ||
1351 | |||
1352 | initialized = 1; | ||
1353 | |||
1354 | return retval; | ||
1355 | |||
1356 | error_smbios_start: | ||
1357 | iounmap(smbios_start); | ||
1358 | error_rom_start: | ||
1359 | iounmap(cpqhp_rom_start); | ||
1360 | error: | ||
1361 | return retval; | ||
1362 | } | ||
1363 | |||
1364 | |||
1365 | static void __exit unload_cpqphpd(void) | 1327 | static void __exit unload_cpqphpd(void) |
1366 | { | 1328 | { |
1367 | struct pci_func *next; | 1329 | struct pci_func *next; |
@@ -1381,10 +1343,10 @@ static void __exit unload_cpqphpd(void) | |||
1381 | if (ctrl->hpc_reg) { | 1343 | if (ctrl->hpc_reg) { |
1382 | u16 misc; | 1344 | u16 misc; |
1383 | rc = read_slot_enable (ctrl); | 1345 | rc = read_slot_enable (ctrl); |
1384 | 1346 | ||
1385 | writeb(0, ctrl->hpc_reg + SLOT_SERR); | 1347 | writeb(0, ctrl->hpc_reg + SLOT_SERR); |
1386 | writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK); | 1348 | writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK); |
1387 | 1349 | ||
1388 | misc = readw(ctrl->hpc_reg + MISC); | 1350 | misc = readw(ctrl->hpc_reg + MISC); |
1389 | misc &= 0xFFFD; | 1351 | misc &= 0xFFFD; |
1390 | writew(misc, ctrl->hpc_reg + MISC); | 1352 | writew(misc, ctrl->hpc_reg + MISC); |
@@ -1464,38 +1426,34 @@ static void __exit unload_cpqphpd(void) | |||
1464 | } | 1426 | } |
1465 | } | 1427 | } |
1466 | 1428 | ||
1467 | // Stop the notification mechanism | 1429 | /* Stop the notification mechanism */ |
1468 | if (initialized) | 1430 | if (initialized) |
1469 | cpqhp_event_stop_thread(); | 1431 | cpqhp_event_stop_thread(); |
1470 | 1432 | ||
1471 | //unmap the rom address | 1433 | /* unmap the rom address */ |
1472 | if (cpqhp_rom_start) | 1434 | if (cpqhp_rom_start) |
1473 | iounmap(cpqhp_rom_start); | 1435 | iounmap(cpqhp_rom_start); |
1474 | if (smbios_start) | 1436 | if (smbios_start) |
1475 | iounmap(smbios_start); | 1437 | iounmap(smbios_start); |
1476 | } | 1438 | } |
1477 | 1439 | ||
1478 | |||
1479 | |||
1480 | static struct pci_device_id hpcd_pci_tbl[] = { | 1440 | static struct pci_device_id hpcd_pci_tbl[] = { |
1481 | { | 1441 | { |
1482 | /* handle any PCI Hotplug controller */ | 1442 | /* handle any PCI Hotplug controller */ |
1483 | .class = ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), | 1443 | .class = ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), |
1484 | .class_mask = ~0, | 1444 | .class_mask = ~0, |
1485 | 1445 | ||
1486 | /* no matter who makes it */ | 1446 | /* no matter who makes it */ |
1487 | .vendor = PCI_ANY_ID, | 1447 | .vendor = PCI_ANY_ID, |
1488 | .device = PCI_ANY_ID, | 1448 | .device = PCI_ANY_ID, |
1489 | .subvendor = PCI_ANY_ID, | 1449 | .subvendor = PCI_ANY_ID, |
1490 | .subdevice = PCI_ANY_ID, | 1450 | .subdevice = PCI_ANY_ID, |
1491 | 1451 | ||
1492 | }, { /* end: all zeroes */ } | 1452 | }, { /* end: all zeroes */ } |
1493 | }; | 1453 | }; |
1494 | 1454 | ||
1495 | MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl); | 1455 | MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl); |
1496 | 1456 | ||
1497 | |||
1498 | |||
1499 | static struct pci_driver cpqhpc_driver = { | 1457 | static struct pci_driver cpqhpc_driver = { |
1500 | .name = "compaq_pci_hotplug", | 1458 | .name = "compaq_pci_hotplug", |
1501 | .id_table = hpcd_pci_tbl, | 1459 | .id_table = hpcd_pci_tbl, |
@@ -1503,8 +1461,6 @@ static struct pci_driver cpqhpc_driver = { | |||
1503 | /* remove: cpqhpc_remove_one, */ | 1461 | /* remove: cpqhpc_remove_one, */ |
1504 | }; | 1462 | }; |
1505 | 1463 | ||
1506 | |||
1507 | |||
1508 | static int __init cpqhpc_init(void) | 1464 | static int __init cpqhpc_init(void) |
1509 | { | 1465 | { |
1510 | int result; | 1466 | int result; |
@@ -1518,7 +1474,6 @@ static int __init cpqhpc_init(void) | |||
1518 | return result; | 1474 | return result; |
1519 | } | 1475 | } |
1520 | 1476 | ||
1521 | |||
1522 | static void __exit cpqhpc_cleanup(void) | 1477 | static void __exit cpqhpc_cleanup(void) |
1523 | { | 1478 | { |
1524 | dbg("unload_cpqphpd()\n"); | 1479 | dbg("unload_cpqphpd()\n"); |
@@ -1529,8 +1484,5 @@ static void __exit cpqhpc_cleanup(void) | |||
1529 | cpqhp_shutdown_debugfs(); | 1484 | cpqhp_shutdown_debugfs(); |
1530 | } | 1485 | } |
1531 | 1486 | ||
1532 | |||
1533 | module_init(cpqhpc_init); | 1487 | module_init(cpqhpc_init); |
1534 | module_exit(cpqhpc_cleanup); | 1488 | module_exit(cpqhpc_cleanup); |
1535 | |||
1536 | |||