1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Compaq Hot Plug Controller Driver 4 * 5 * Copyright (C) 1995,2001 Compaq Computer Corporation 6 * Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com> 7 * Copyright (C) 2001 IBM Corp. 8 * 9 * All rights reserved. 10 * 11 * Send feedback to <greg@kroah.com> 12 * 13 * Jan 12, 2003 - Added 66/100/133MHz PCI-X support, 14 * Torben Mathiasen <torben.mathiasen@hp.com> 15 */ 16 17 #include <linux/module.h> 18 #include <linux/moduleparam.h> 19 #include <linux/kernel.h> 20 #include <linux/types.h> 21 #include <linux/proc_fs.h> 22 #include <linux/slab.h> 23 #include <linux/workqueue.h> 24 #include <linux/pci.h> 25 #include <linux/pci_hotplug.h> 26 #include <linux/init.h> 27 #include <linux/interrupt.h> 28 29 #include <linux/uaccess.h> 30 31 #include "cpqphp.h" 32 #include "cpqphp_nvram.h" 33 34 35 /* Global variables */ 36 int cpqhp_debug; 37 int cpqhp_legacy_mode; 38 struct controller *cpqhp_ctrl_list; /* = NULL */ 39 struct pci_func *cpqhp_slot_list[256]; 40 struct irq_routing_table *cpqhp_routing_table; 41 42 /* local variables */ 43 static void __iomem *smbios_table; 44 static void __iomem *smbios_start; 45 static void __iomem *cpqhp_rom_start; 46 static bool power_mode; 47 static bool debug; 48 static int initialized; 49 50 #define DRIVER_VERSION "0.9.8" 51 #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>" 52 #define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver" 53 54 MODULE_AUTHOR(DRIVER_AUTHOR); 55 MODULE_DESCRIPTION(DRIVER_DESC); 56 MODULE_LICENSE("GPL"); 57 58 module_param(power_mode, bool, 0644); 59 MODULE_PARM_DESC(power_mode, "Power mode enabled or not"); 60 61 module_param(debug, bool, 0644); 62 MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); 63 64 #define CPQHPC_MODULE_MINOR 208 65 66 static inline int is_slot64bit(struct slot *slot) 67 { 68 return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0; 69 } 70 71 static inline int is_slot66mhz(struct slot *slot) 72 { 73 return (readb(slot->p_sm_slot + SMBIOS_SLOT_TYPE) == 0x0E) ? 1 : 0; 74 } 75 76 /** 77 * detect_SMBIOS_pointer - find the System Management BIOS Table in mem region. 78 * @begin: begin pointer for region to be scanned. 79 * @end: end pointer for region to be scanned. 80 * 81 * Returns pointer to the head of the SMBIOS tables (or %NULL). 82 */ 83 static void __iomem *detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end) 84 { 85 void __iomem *fp; 86 void __iomem *endp; 87 u8 temp1, temp2, temp3, temp4; 88 int status = 0; 89 90 endp = (end - sizeof(u32) + 1); 91 92 for (fp = begin; fp <= endp; fp += 16) { 93 temp1 = readb(fp); 94 temp2 = readb(fp+1); 95 temp3 = readb(fp+2); 96 temp4 = readb(fp+3); 97 if (temp1 == '_' && 98 temp2 == 'S' && 99 temp3 == 'M' && 100 temp4 == '_') { 101 status = 1; 102 break; 103 } 104 } 105 106 if (!status) 107 fp = NULL; 108 109 dbg("Discovered SMBIOS Entry point at %p\n", fp); 110 111 return fp; 112 } 113 114 /** 115 * init_SERR - Initializes the per slot SERR generation. 116 * @ctrl: controller to use 117 * 118 * For unexpected switch opens 119 */ 120 static int init_SERR(struct controller *ctrl) 121 { 122 u32 tempdword; 123 u32 number_of_slots; 124 125 if (!ctrl) 126 return 1; 127 128 tempdword = ctrl->first_slot; 129 130 number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; 131 /* Loop through slots */ 132 while (number_of_slots) { 133 writeb(0, ctrl->hpc_reg + SLOT_SERR); 134 tempdword++; 135 number_of_slots--; 136 } 137 138 return 0; 139 } 140 141 static int init_cpqhp_routing_table(void) 142 { 143 int len; 144 145 cpqhp_routing_table = pcibios_get_irq_routing_table(); 146 if (cpqhp_routing_table == NULL) 147 return -ENOMEM; 148 149 len = cpqhp_routing_table_length(); 150 if (len == 0) { 151 kfree(cpqhp_routing_table); 152 cpqhp_routing_table = NULL; 153 return -1; 154 } 155 156 return 0; 157 } 158 159 /* nice debugging output */ 160 static void pci_print_IRQ_route(void) 161 { 162 int len; 163 int loop; 164 u8 tbus, tdevice, tslot; 165 166 len = cpqhp_routing_table_length(); 167 168 dbg("bus dev func slot\n"); 169 for (loop = 0; loop < len; ++loop) { 170 tbus = cpqhp_routing_table->slots[loop].bus; 171 tdevice = cpqhp_routing_table->slots[loop].devfn; 172 tslot = cpqhp_routing_table->slots[loop].slot; 173 dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot); 174 175 } 176 } 177 178 179 /** 180 * get_subsequent_smbios_entry: get the next entry from bios table. 181 * @smbios_start: where to start in the SMBIOS table 182 * @smbios_table: location of the SMBIOS table 183 * @curr: %NULL or pointer to previously returned structure 184 * 185 * Gets the first entry if previous == NULL; 186 * otherwise, returns the next entry. 187 * Uses global SMBIOS Table pointer. 188 * 189 * Returns a pointer to an SMBIOS structure or NULL if none found. 190 */ 191 static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, 192 void __iomem *smbios_table, 193 void __iomem *curr) 194 { 195 u8 bail = 0; 196 u8 previous_byte = 1; 197 void __iomem *p_temp; 198 void __iomem *p_max; 199 200 if (!smbios_table || !curr) 201 return NULL; 202 203 /* set p_max to the end of the table */ 204 p_max = smbios_start + readw(smbios_table + ST_LENGTH); 205 206 p_temp = curr; 207 p_temp += readb(curr + SMBIOS_GENERIC_LENGTH); 208 209 while ((p_temp < p_max) && !bail) { 210 /* Look for the double NULL terminator 211 * The first condition is the previous byte 212 * and the second is the curr 213 */ 214 if (!previous_byte && !(readb(p_temp))) 215 bail = 1; 216 217 previous_byte = readb(p_temp); 218 p_temp++; 219 } 220 221 if (p_temp < p_max) 222 return p_temp; 223 else 224 return NULL; 225 } 226 227 228 /** 229 * get_SMBIOS_entry - return the requested SMBIOS entry or %NULL 230 * @smbios_start: where to start in the SMBIOS table 231 * @smbios_table: location of the SMBIOS table 232 * @type: SMBIOS structure type to be returned 233 * @previous: %NULL or pointer to previously returned structure 234 * 235 * Gets the first entry of the specified type if previous == %NULL; 236 * Otherwise, returns the next entry of the given type. 237 * Uses global SMBIOS Table pointer. 238 * Uses get_subsequent_smbios_entry. 239 * 240 * Returns a pointer to an SMBIOS structure or %NULL if none found. 241 */ 242 static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start, 243 void __iomem *smbios_table, 244 u8 type, 245 void __iomem *previous) 246 { 247 if (!smbios_table) 248 return NULL; 249 250 if (!previous) 251 previous = smbios_start; 252 else 253 previous = get_subsequent_smbios_entry(smbios_start, 254 smbios_table, previous); 255 256 while (previous) 257 if (readb(previous + SMBIOS_GENERIC_TYPE) != type) 258 previous = get_subsequent_smbios_entry(smbios_start, 259 smbios_table, previous); 260 else 261 break; 262 263 return previous; 264 } 265 266 static int ctrl_slot_cleanup(struct controller *ctrl) 267 { 268 struct slot *old_slot, *next_slot; 269 270 old_slot = ctrl->slot; 271 ctrl->slot = NULL; 272 273 while (old_slot) { 274 next_slot = old_slot->next; 275 pci_hp_deregister(&old_slot->hotplug_slot); 276 kfree(old_slot); 277 old_slot = next_slot; 278 } 279 280 cpqhp_remove_debugfs_files(ctrl); 281 282 /* Free IRQ associated with hot plug device */ 283 free_irq(ctrl->interrupt, ctrl); 284 /* Unmap the memory */ 285 iounmap(ctrl->hpc_reg); 286 /* Finally reclaim PCI mem */ 287 release_mem_region(pci_resource_start(ctrl->pci_dev, 0), 288 pci_resource_len(ctrl->pci_dev, 0)); 289 290 return 0; 291 } 292 293 294 /** 295 * get_slot_mapping - determine logical slot mapping for PCI device 296 * 297 * Won't work for more than one PCI-PCI bridge in a slot. 298 * 299 * @bus: pointer to the PCI bus structure 300 * @bus_num: bus number of PCI device 301 * @dev_num: device number of PCI device 302 * @slot: Pointer to u8 where slot number will be returned 303 * 304 * Output: SUCCESS or FAILURE 305 */ 306 static int 307 get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) 308 { 309 u32 work; 310 long len; 311 long loop; 312 313 u8 tbus, tdevice, tslot, bridgeSlot; 314 315 dbg("%s: %p, %d, %d, %p\n", __func__, bus, bus_num, dev_num, slot); 316 317 bridgeSlot = 0xFF; 318 319 len = cpqhp_routing_table_length(); 320 for (loop = 0; loop < len; ++loop) { 321 tbus = cpqhp_routing_table->slots[loop].bus; 322 tdevice = cpqhp_routing_table->slots[loop].devfn >> 3; 323 tslot = cpqhp_routing_table->slots[loop].slot; 324 325 if ((tbus == bus_num) && (tdevice == dev_num)) { 326 *slot = tslot; 327 return 0; 328 } else { 329 /* Did not get a match on the target PCI device. Check 330 * if the current IRQ table entry is a PCI-to-PCI 331 * bridge device. If so, and it's secondary bus 332 * matches the bus number for the target device, I need 333 * to save the bridge's slot number. If I can not find 334 * an entry for the target device, I will have to 335 * assume it's on the other side of the bridge, and 336 * assign it the bridge's slot. 337 */ 338 bus->number = tbus; 339 pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), 340 PCI_CLASS_REVISION, &work); 341 342 if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { 343 pci_bus_read_config_dword(bus, 344 PCI_DEVFN(tdevice, 0), 345 PCI_PRIMARY_BUS, &work); 346 // See if bridge's secondary bus matches target bus. 347 if (((work >> 8) & 0x000000FF) == (long) bus_num) 348 bridgeSlot = tslot; 349 } 350 } 351 352 } 353 354 /* If we got here, we didn't find an entry in the IRQ mapping table for 355 * the target PCI device. If we did determine that the target device 356 * is on the other side of a PCI-to-PCI bridge, return the slot number 357 * for the bridge. 358 */ 359 if (bridgeSlot != 0xFF) { 360 *slot = bridgeSlot; 361 return 0; 362 } 363 /* Couldn't find an entry in the routing table for this PCI device */ 364 return -1; 365 } 366 367 368 /** 369 * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off 370 * @ctrl: struct controller to use 371 * @func: PCI device/function info 372 * @status: LED control flag: 1 = LED on, 0 = LED off 373 */ 374 static int 375 cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, 376 u32 status) 377 { 378 u8 hp_slot; 379 380 if (func == NULL) 381 return 1; 382 383 hp_slot = func->device - ctrl->slot_device_offset; 384 385 /* Wait for exclusive access to hardware */ 386 mutex_lock(&ctrl->crit_sect); 387 388 if (status == 1) 389 amber_LED_on(ctrl, hp_slot); 390 else if (status == 0) 391 amber_LED_off(ctrl, hp_slot); 392 else { 393 /* Done with exclusive hardware access */ 394 mutex_unlock(&ctrl->crit_sect); 395 return 1; 396 } 397 398 set_SOGO(ctrl); 399 400 /* Wait for SOBS to be unset */ 401 wait_for_ctrl_irq(ctrl); 402 403 /* Done with exclusive hardware access */ 404 mutex_unlock(&ctrl->crit_sect); 405 406 return 0; 407 } 408 409 410 /** 411 * set_attention_status - Turns the Amber LED for a slot on or off 412 * @hotplug_slot: slot to change LED on 413 * @status: LED control flag 414 */ 415 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 416 { 417 struct pci_func *slot_func; 418 struct slot *slot = to_slot(hotplug_slot); 419 struct controller *ctrl = slot->ctrl; 420 u8 bus; 421 u8 devfn; 422 u8 device; 423 u8 function; 424 425 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 426 427 if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) 428 return -ENODEV; 429 430 device = devfn >> 3; 431 function = devfn & 0x7; 432 dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); 433 434 slot_func = cpqhp_slot_find(bus, device, function); 435 if (!slot_func) 436 return -ENODEV; 437 438 return cpqhp_set_attention_status(ctrl, slot_func, status); 439 } 440 441 442 static int process_SI(struct hotplug_slot *hotplug_slot) 443 { 444 struct pci_func *slot_func; 445 struct slot *slot = to_slot(hotplug_slot); 446 struct controller *ctrl = slot->ctrl; 447 u8 bus; 448 u8 devfn; 449 u8 device; 450 u8 function; 451 452 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 453 454 if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) 455 return -ENODEV; 456 457 device = devfn >> 3; 458 function = devfn & 0x7; 459 dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); 460 461 slot_func = cpqhp_slot_find(bus, device, function); 462 if (!slot_func) 463 return -ENODEV; 464 465 slot_func->bus = bus; 466 slot_func->device = device; 467 slot_func->function = function; 468 slot_func->configured = 0; 469 dbg("board_added(%p, %p)\n", slot_func, ctrl); 470 return cpqhp_process_SI(ctrl, slot_func); 471 } 472 473 474 static int process_SS(struct hotplug_slot *hotplug_slot) 475 { 476 struct pci_func *slot_func; 477 struct slot *slot = to_slot(hotplug_slot); 478 struct controller *ctrl = slot->ctrl; 479 u8 bus; 480 u8 devfn; 481 u8 device; 482 u8 function; 483 484 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 485 486 if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) 487 return -ENODEV; 488 489 device = devfn >> 3; 490 function = devfn & 0x7; 491 dbg("bus, dev, fn = %d, %d, %d\n", bus, device, function); 492 493 slot_func = cpqhp_slot_find(bus, device, function); 494 if (!slot_func) 495 return -ENODEV; 496 497 dbg("In %s, slot_func = %p, ctrl = %p\n", __func__, slot_func, ctrl); 498 return cpqhp_process_SS(ctrl, slot_func); 499 } 500 501 502 static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value) 503 { 504 struct slot *slot = to_slot(hotplug_slot); 505 struct controller *ctrl = slot->ctrl; 506 507 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 508 509 return cpqhp_hardware_test(ctrl, value); 510 } 511 512 513 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 514 { 515 struct slot *slot = to_slot(hotplug_slot); 516 struct controller *ctrl = slot->ctrl; 517 518 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 519 520 *value = get_slot_enabled(ctrl, slot); 521 return 0; 522 } 523 524 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) 525 { 526 struct slot *slot = to_slot(hotplug_slot); 527 struct controller *ctrl = slot->ctrl; 528 529 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 530 531 *value = cpq_get_attention_status(ctrl, slot); 532 return 0; 533 } 534 535 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) 536 { 537 struct slot *slot = to_slot(hotplug_slot); 538 struct controller *ctrl = slot->ctrl; 539 540 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 541 542 *value = cpq_get_latch_status(ctrl, slot); 543 544 return 0; 545 } 546 547 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) 548 { 549 struct slot *slot = to_slot(hotplug_slot); 550 struct controller *ctrl = slot->ctrl; 551 552 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); 553 554 *value = get_presence_status(ctrl, slot); 555 556 return 0; 557 } 558 559 static const struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { 560 .set_attention_status = set_attention_status, 561 .enable_slot = process_SI, 562 .disable_slot = process_SS, 563 .hardware_test = hardware_test, 564 .get_power_status = get_power_status, 565 .get_attention_status = get_attention_status, 566 .get_latch_status = get_latch_status, 567 .get_adapter_status = get_adapter_status, 568 }; 569 570 #define SLOT_NAME_SIZE 10 571 572 static int ctrl_slot_setup(struct controller *ctrl, 573 void __iomem *smbios_start, 574 void __iomem *smbios_table) 575 { 576 struct slot *slot; 577 struct pci_bus *bus = ctrl->pci_bus; 578 u8 number_of_slots; 579 u8 slot_device; 580 u8 slot_number; 581 u8 ctrl_slot; 582 u32 tempdword; 583 char name[SLOT_NAME_SIZE]; 584 void __iomem *slot_entry = NULL; 585 int result; 586 587 dbg("%s\n", __func__); 588 589 tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); 590 591 number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; 592 slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; 593 slot_number = ctrl->first_slot; 594 595 while (number_of_slots) { 596 slot = kzalloc(sizeof(*slot), GFP_KERNEL); 597 if (!slot) { 598 result = -ENOMEM; 599 goto error; 600 } 601 602 slot->ctrl = ctrl; 603 slot->bus = ctrl->bus; 604 slot->device = slot_device; 605 slot->number = slot_number; 606 dbg("slot->number = %u\n", slot->number); 607 608 slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, 609 slot_entry); 610 611 while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != 612 slot->number)) { 613 slot_entry = get_SMBIOS_entry(smbios_start, 614 smbios_table, 9, slot_entry); 615 } 616 617 slot->p_sm_slot = slot_entry; 618 619 timer_setup(&slot->task_event, cpqhp_pushbutton_thread, 0); 620 slot->task_event.expires = jiffies + 5 * HZ; 621 622 /*FIXME: these capabilities aren't used but if they are 623 * they need to be correctly implemented 624 */ 625 slot->capabilities |= PCISLOT_REPLACE_SUPPORTED; 626 slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED; 627 628 if (is_slot64bit(slot)) 629 slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; 630 if (is_slot66mhz(slot)) 631 slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; 632 if (bus->cur_bus_speed == PCI_SPEED_66MHz) 633 slot->capabilities |= PCISLOT_66_MHZ_OPERATION; 634 635 ctrl_slot = 636 slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4); 637 638 /* Check presence */ 639 slot->capabilities |= 640 ((((~tempdword) >> 23) | 641 ((~tempdword) >> 15)) >> ctrl_slot) & 0x02; 642 /* Check the switch state */ 643 slot->capabilities |= 644 ((~tempdword & 0xFF) >> ctrl_slot) & 0x01; 645 /* Check the slot enable */ 646 slot->capabilities |= 647 ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; 648 649 /* register this slot with the hotplug pci core */ 650 snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); 651 slot->hotplug_slot.ops = &cpqphp_hotplug_slot_ops; 652 653 dbg("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n", 654 slot->bus, slot->device, 655 slot->number, ctrl->slot_device_offset, 656 slot_number); 657 result = pci_hp_register(&slot->hotplug_slot, 658 ctrl->pci_dev->bus, 659 slot->device, 660 name); 661 if (result) { 662 err("pci_hp_register failed with error %d\n", result); 663 goto error_slot; 664 } 665 666 slot->next = ctrl->slot; 667 ctrl->slot = slot; 668 669 number_of_slots--; 670 slot_device++; 671 slot_number++; 672 } 673 674 return 0; 675 error_slot: 676 kfree(slot); 677 error: 678 return result; 679 } 680 681 static int one_time_init(void) 682 { 683 int loop; 684 int retval = 0; 685 686 if (initialized) 687 return 0; 688 689 power_mode = 0; 690 691 retval = init_cpqhp_routing_table(); 692 if (retval) 693 goto error; 694 695 if (cpqhp_debug) 696 pci_print_IRQ_route(); 697 698 dbg("Initialize + Start the notification mechanism\n"); 699 700 retval = cpqhp_event_start_thread(); 701 if (retval) 702 goto error; 703 704 dbg("Initialize slot lists\n"); 705 for (loop = 0; loop < 256; loop++) 706 cpqhp_slot_list[loop] = NULL; 707 708 /* FIXME: We also need to hook the NMI handler eventually. 709 * this also needs to be worked with Christoph 710 * register_NMI_handler(); 711 */ 712 /* Map rom address */ 713 cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); 714 if (!cpqhp_rom_start) { 715 err("Could not ioremap memory region for ROM\n"); 716 retval = -EIO; 717 goto error; 718 } 719 720 /* Now, map the int15 entry point if we are on compaq specific 721 * hardware 722 */ 723 compaq_nvram_init(cpqhp_rom_start); 724 725 /* Map smbios table entry point structure */ 726 smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, 727 cpqhp_rom_start + ROM_PHY_LEN); 728 if (!smbios_table) { 729 err("Could not find the SMBIOS pointer in memory\n"); 730 retval = -EIO; 731 goto error_rom_start; 732 } 733 734 smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), 735 readw(smbios_table + ST_LENGTH)); 736 if (!smbios_start) { 737 err("Could not ioremap memory region taken from SMBIOS values\n"); 738 retval = -EIO; 739 goto error_smbios_start; 740 } 741 742 initialized = 1; 743 744 return retval; 745 746 error_smbios_start: 747 iounmap(smbios_start); 748 error_rom_start: 749 iounmap(cpqhp_rom_start); 750 error: 751 return retval; 752 } 753 754 static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 755 { 756 u8 num_of_slots = 0; 757 u8 hp_slot = 0; 758 u8 device; 759 u8 bus_cap; 760 u16 temp_word; 761 u16 vendor_id; 762 u16 subsystem_vid; 763 u16 subsystem_deviceid; 764 u32 rc; 765 struct controller *ctrl; 766 struct pci_func *func; 767 struct pci_bus *bus; 768 int err; 769 770 err = pci_enable_device(pdev); 771 if (err) { 772 printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n", 773 pci_name(pdev), err); 774 return err; 775 } 776 777 bus = pdev->subordinate; 778 if (!bus) { 779 pci_notice(pdev, "the device is not a bridge, skipping\n"); 780 rc = -ENODEV; 781 goto err_disable_device; 782 } 783 784 /* Need to read VID early b/c it's used to differentiate CPQ and INTC 785 * discovery 786 */ 787 vendor_id = pdev->vendor; 788 if ((vendor_id != PCI_VENDOR_ID_COMPAQ) && 789 (vendor_id != PCI_VENDOR_ID_INTEL)) { 790 err(msg_HPC_non_compaq_or_intel); 791 rc = -ENODEV; 792 goto err_disable_device; 793 } 794 dbg("Vendor ID: %x\n", vendor_id); 795 796 dbg("revision: %d\n", pdev->revision); 797 if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) { 798 err(msg_HPC_rev_error); 799 rc = -ENODEV; 800 goto err_disable_device; 801 } 802 803 /* Check for the proper subsystem IDs 804 * Intel uses a different SSID programming model than Compaq. 805 * For Intel, each SSID bit identifies a PHP capability. 806 * Also Intel HPCs may have RID=0. 807 */ 808 if ((pdev->revision <= 2) && (vendor_id != PCI_VENDOR_ID_INTEL)) { 809 err(msg_HPC_not_supported); 810 rc = -ENODEV; 811 goto err_disable_device; 812 } 813 814 /* TODO: This code can be made to support non-Compaq or Intel 815 * subsystem IDs 816 */ 817 subsystem_vid = pdev->subsystem_vendor; 818 dbg("Subsystem Vendor ID: %x\n", subsystem_vid); 819 if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { 820 err(msg_HPC_non_compaq_or_intel); 821 rc = -ENODEV; 822 goto err_disable_device; 823 } 824 825 ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); 826 if (!ctrl) { 827 rc = -ENOMEM; 828 goto err_disable_device; 829 } 830 831 subsystem_deviceid = pdev->subsystem_device; 832 833 info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid); 834 835 /* Set Vendor ID, so it can be accessed later from other 836 * functions 837 */ 838 ctrl->vendor_id = vendor_id; 839 840 switch (subsystem_vid) { 841 case PCI_VENDOR_ID_COMPAQ: 842 if (pdev->revision >= 0x13) { /* CIOBX */ 843 ctrl->push_flag = 1; 844 ctrl->slot_switch_type = 1; 845 ctrl->push_button = 1; 846 ctrl->pci_config_space = 1; 847 ctrl->defeature_PHP = 1; 848 ctrl->pcix_support = 1; 849 ctrl->pcix_speed_capability = 1; 850 pci_read_config_byte(pdev, 0x41, &bus_cap); 851 if (bus_cap & 0x80) { 852 dbg("bus max supports 133MHz PCI-X\n"); 853 bus->max_bus_speed = PCI_SPEED_133MHz_PCIX; 854 break; 855 } 856 if (bus_cap & 0x40) { 857 dbg("bus max supports 100MHz PCI-X\n"); 858 bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; 859 break; 860 } 861 if (bus_cap & 0x20) { 862 dbg("bus max supports 66MHz PCI-X\n"); 863 bus->max_bus_speed = PCI_SPEED_66MHz_PCIX; 864 break; 865 } 866 if (bus_cap & 0x10) { 867 dbg("bus max supports 66MHz PCI\n"); 868 bus->max_bus_speed = PCI_SPEED_66MHz; 869 break; 870 } 871 872 break; 873 } 874 875 switch (subsystem_deviceid) { 876 case PCI_SUB_HPC_ID: 877 /* Original 6500/7000 implementation */ 878 ctrl->slot_switch_type = 1; 879 bus->max_bus_speed = PCI_SPEED_33MHz; 880 ctrl->push_button = 0; 881 ctrl->pci_config_space = 1; 882 ctrl->defeature_PHP = 1; 883 ctrl->pcix_support = 0; 884 ctrl->pcix_speed_capability = 0; 885 break; 886 case PCI_SUB_HPC_ID2: 887 /* First Pushbutton implementation */ 888 ctrl->push_flag = 1; 889 ctrl->slot_switch_type = 1; 890 bus->max_bus_speed = PCI_SPEED_33MHz; 891 ctrl->push_button = 1; 892 ctrl->pci_config_space = 1; 893 ctrl->defeature_PHP = 1; 894 ctrl->pcix_support = 0; 895 ctrl->pcix_speed_capability = 0; 896 break; 897 case PCI_SUB_HPC_ID_INTC: 898 /* Third party (6500/7000) */ 899 ctrl->slot_switch_type = 1; 900 bus->max_bus_speed = PCI_SPEED_33MHz; 901 ctrl->push_button = 0; 902 ctrl->pci_config_space = 1; 903 ctrl->defeature_PHP = 1; 904 ctrl->pcix_support = 0; 905 ctrl->pcix_speed_capability = 0; 906 break; 907 case PCI_SUB_HPC_ID3: 908 /* First 66 Mhz implementation */ 909 ctrl->push_flag = 1; 910 ctrl->slot_switch_type = 1; 911 bus->max_bus_speed = PCI_SPEED_66MHz; 912 ctrl->push_button = 1; 913 ctrl->pci_config_space = 1; 914 ctrl->defeature_PHP = 1; 915 ctrl->pcix_support = 0; 916 ctrl->pcix_speed_capability = 0; 917 break; 918 case PCI_SUB_HPC_ID4: 919 /* First PCI-X implementation, 100MHz */ 920 ctrl->push_flag = 1; 921 ctrl->slot_switch_type = 1; 922 bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; 923 ctrl->push_button = 1; 924 ctrl->pci_config_space = 1; 925 ctrl->defeature_PHP = 1; 926 ctrl->pcix_support = 1; 927 ctrl->pcix_speed_capability = 0; 928 break; 929 default: 930 err(msg_HPC_not_supported); 931 rc = -ENODEV; 932 goto err_free_ctrl; 933 } 934 break; 935 936 case PCI_VENDOR_ID_INTEL: 937 /* Check for speed capability (0=33, 1=66) */ 938 if (subsystem_deviceid & 0x0001) 939 bus->max_bus_speed = PCI_SPEED_66MHz; 940 else 941 bus->max_bus_speed = PCI_SPEED_33MHz; 942 943 /* Check for push button */ 944 if (subsystem_deviceid & 0x0002) 945 ctrl->push_button = 0; 946 else 947 ctrl->push_button = 1; 948 949 /* Check for slot switch type (0=mechanical, 1=not mechanical) */ 950 if (subsystem_deviceid & 0x0004) 951 ctrl->slot_switch_type = 0; 952 else 953 ctrl->slot_switch_type = 1; 954 955 /* PHP Status (0=De-feature PHP, 1=Normal operation) */ 956 if (subsystem_deviceid & 0x0008) 957 ctrl->defeature_PHP = 1; /* PHP supported */ 958 else 959 ctrl->defeature_PHP = 0; /* PHP not supported */ 960 961 /* Alternate Base Address Register Interface 962 * (0=not supported, 1=supported) 963 */ 964 if (subsystem_deviceid & 0x0010) 965 ctrl->alternate_base_address = 1; 966 else 967 ctrl->alternate_base_address = 0; 968 969 /* PCI Config Space Index (0=not supported, 1=supported) */ 970 if (subsystem_deviceid & 0x0020) 971 ctrl->pci_config_space = 1; 972 else 973 ctrl->pci_config_space = 0; 974 975 /* PCI-X support */ 976 if (subsystem_deviceid & 0x0080) { 977 ctrl->pcix_support = 1; 978 if (subsystem_deviceid & 0x0040) 979 /* 133MHz PCI-X if bit 7 is 1 */ 980 ctrl->pcix_speed_capability = 1; 981 else 982 /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */ 983 /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */ 984 ctrl->pcix_speed_capability = 0; 985 } else { 986 /* Conventional PCI */ 987 ctrl->pcix_support = 0; 988 ctrl->pcix_speed_capability = 0; 989 } 990 break; 991 992 default: 993 err(msg_HPC_not_supported); 994 rc = -ENODEV; 995 goto err_free_ctrl; 996 } 997 998 /* Tell the user that we found one. */ 999 info("Initializing the PCI hot plug controller residing on PCI bus %d\n", 1000 pdev->bus->number); 1001 1002 dbg("Hotplug controller capabilities:\n"); 1003 dbg(" speed_capability %d\n", bus->max_bus_speed); 1004 dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? 1005 "switch present" : "no switch"); 1006 dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? 1007 "PHP supported" : "PHP not supported"); 1008 dbg(" alternate_base_address %s\n", ctrl->alternate_base_address ? 1009 "supported" : "not supported"); 1010 dbg(" pci_config_space %s\n", ctrl->pci_config_space ? 1011 "supported" : "not supported"); 1012 dbg(" pcix_speed_capability %s\n", ctrl->pcix_speed_capability ? 1013 "supported" : "not supported"); 1014 dbg(" pcix_support %s\n", ctrl->pcix_support ? 1015 "supported" : "not supported"); 1016 1017 ctrl->pci_dev = pdev; 1018 pci_set_drvdata(pdev, ctrl); 1019 1020 /* make our own copy of the pci bus structure, 1021 * as we like tweaking it a lot */ 1022 ctrl->pci_bus = kmemdup(pdev->bus, sizeof(*ctrl->pci_bus), GFP_KERNEL); 1023 if (!ctrl->pci_bus) { 1024 err("out of memory\n"); 1025 rc = -ENOMEM; 1026 goto err_free_ctrl; 1027 } 1028 1029 ctrl->bus = pdev->bus->number; 1030 ctrl->rev = pdev->revision; 1031 dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, 1032 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); 1033 1034 mutex_init(&ctrl->crit_sect); 1035 init_waitqueue_head(&ctrl->queue); 1036 1037 /* initialize our threads if they haven't already been started up */ 1038 rc = one_time_init(); 1039 if (rc) 1040 goto err_free_bus; 1041 1042 dbg("pdev = %p\n", pdev); 1043 dbg("pci resource start %llx\n", (unsigned long long)pci_resource_start(pdev, 0)); 1044 dbg("pci resource len %llx\n", (unsigned long long)pci_resource_len(pdev, 0)); 1045 1046 if (!request_mem_region(pci_resource_start(pdev, 0), 1047 pci_resource_len(pdev, 0), MY_NAME)) { 1048 err("cannot reserve MMIO region\n"); 1049 rc = -ENOMEM; 1050 goto err_free_bus; 1051 } 1052 1053 ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), 1054 pci_resource_len(pdev, 0)); 1055 if (!ctrl->hpc_reg) { 1056 err("cannot remap MMIO region %llx @ %llx\n", 1057 (unsigned long long)pci_resource_len(pdev, 0), 1058 (unsigned long long)pci_resource_start(pdev, 0)); 1059 rc = -ENODEV; 1060 goto err_free_mem_region; 1061 } 1062 1063 /* Check for 66Mhz operation */ 1064 bus->cur_bus_speed = get_controller_speed(ctrl); 1065 1066 1067 /******************************************************** 1068 * 1069 * Save configuration headers for this and 1070 * subordinate PCI buses 1071 * 1072 ********************************************************/ 1073 1074 /* find the physical slot number of the first hot plug slot */ 1075 1076 /* Get slot won't work for devices behind bridges, but 1077 * in this case it will always be called for the "base" 1078 * bus/dev/func of a slot. 1079 * CS: this is leveraging the PCIIRQ routing code from the kernel 1080 * (pci-pc.c: get_irq_routing_table) */ 1081 rc = get_slot_mapping(ctrl->pci_bus, pdev->bus->number, 1082 (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), 1083 &(ctrl->first_slot)); 1084 dbg("get_slot_mapping: first_slot = %d, returned = %d\n", 1085 ctrl->first_slot, rc); 1086 if (rc) { 1087 err(msg_initialization_err, rc); 1088 goto err_iounmap; 1089 } 1090 1091 /* Store PCI Config Space for all devices on this bus */ 1092 rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK)); 1093 if (rc) { 1094 err("%s: unable to save PCI configuration data, error %d\n", 1095 __func__, rc); 1096 goto err_iounmap; 1097 } 1098 1099 /* 1100 * Get IO, memory, and IRQ resources for new devices 1101 */ 1102 /* The next line is required for cpqhp_find_available_resources */ 1103 ctrl->interrupt = pdev->irq; 1104 if (ctrl->interrupt < 0x10) { 1105 cpqhp_legacy_mode = 1; 1106 dbg("System seems to be configured for Full Table Mapped MPS mode\n"); 1107 } 1108 1109 ctrl->cfgspc_irq = 0; 1110 pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq); 1111 1112 rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start); 1113 ctrl->add_support = !rc; 1114 if (rc) { 1115 dbg("cpqhp_find_available_resources = 0x%x\n", rc); 1116 err("unable to locate PCI configuration resources for hot plug add.\n"); 1117 goto err_iounmap; 1118 } 1119 1120 /* 1121 * Finish setting up the hot plug ctrl device 1122 */ 1123 ctrl->slot_device_offset = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; 1124 dbg("NumSlots %d\n", ctrl->slot_device_offset); 1125 1126 ctrl->next_event = 0; 1127 1128 /* Setup the slot information structures */ 1129 rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table); 1130 if (rc) { 1131 err(msg_initialization_err, 6); 1132 err("%s: unable to save PCI configuration data, error %d\n", 1133 __func__, rc); 1134 goto err_iounmap; 1135 } 1136 1137 /* Mask all general input interrupts */ 1138 writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK); 1139 1140 /* set up the interrupt */ 1141 dbg("HPC interrupt = %d\n", ctrl->interrupt); 1142 if (request_irq(ctrl->interrupt, cpqhp_ctrl_intr, 1143 IRQF_SHARED, MY_NAME, ctrl)) { 1144 err("Can't get irq %d for the hotplug pci controller\n", 1145 ctrl->interrupt); 1146 rc = -ENODEV; 1147 goto err_iounmap; 1148 } 1149 1150 /* Enable Shift Out interrupt and clear it, also enable SERR on power 1151 * fault 1152 */ 1153 temp_word = readw(ctrl->hpc_reg + MISC); 1154 temp_word |= 0x4006; 1155 writew(temp_word, ctrl->hpc_reg + MISC); 1156 1157 /* Changed 05/05/97 to clear all interrupts at start */ 1158 writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR); 1159 1160 ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); 1161 1162 writel(0x0L, ctrl->hpc_reg + INT_MASK); 1163 1164 if (!cpqhp_ctrl_list) { 1165 cpqhp_ctrl_list = ctrl; 1166 ctrl->next = NULL; 1167 } else { 1168 ctrl->next = cpqhp_ctrl_list; 1169 cpqhp_ctrl_list = ctrl; 1170 } 1171 1172 /* turn off empty slots here unless command line option "ON" set 1173 * Wait for exclusive access to hardware 1174 */ 1175 mutex_lock(&ctrl->crit_sect); 1176 1177 num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; 1178 1179 /* find first device number for the ctrl */ 1180 device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; 1181 1182 while (num_of_slots) { 1183 dbg("num_of_slots: %d\n", num_of_slots); 1184 func = cpqhp_slot_find(ctrl->bus, device, 0); 1185 if (!func) 1186 break; 1187 1188 hp_slot = func->device - ctrl->slot_device_offset; 1189 dbg("hp_slot: %d\n", hp_slot); 1190 1191 /* We have to save the presence info for these slots */ 1192 temp_word = ctrl->ctrl_int_comp >> 16; 1193 func->presence_save = (temp_word >> hp_slot) & 0x01; 1194 func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; 1195 1196 if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) 1197 func->switch_save = 0; 1198 else 1199 func->switch_save = 0x10; 1200 1201 if (!power_mode) 1202 if (!func->is_a_board) { 1203 green_LED_off(ctrl, hp_slot); 1204 slot_disable(ctrl, hp_slot); 1205 } 1206 1207 device++; 1208 num_of_slots--; 1209 } 1210 1211 if (!power_mode) { 1212 set_SOGO(ctrl); 1213 /* Wait for SOBS to be unset */ 1214 wait_for_ctrl_irq(ctrl); 1215 } 1216 1217 rc = init_SERR(ctrl); 1218 if (rc) { 1219 err("init_SERR failed\n"); 1220 mutex_unlock(&ctrl->crit_sect); 1221 goto err_free_irq; 1222 } 1223 1224 /* Done with exclusive hardware access */ 1225 mutex_unlock(&ctrl->crit_sect); 1226 1227 cpqhp_create_debugfs_files(ctrl); 1228 1229 return 0; 1230 1231 err_free_irq: 1232 free_irq(ctrl->interrupt, ctrl); 1233 err_iounmap: 1234 iounmap(ctrl->hpc_reg); 1235 err_free_mem_region: 1236 release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 1237 err_free_bus: 1238 kfree(ctrl->pci_bus); 1239 err_free_ctrl: 1240 kfree(ctrl); 1241 err_disable_device: 1242 pci_disable_device(pdev); 1243 return rc; 1244 } 1245 1246 static void __exit unload_cpqphpd(void) 1247 { 1248 struct pci_func *next; 1249 struct pci_func *TempSlot; 1250 int loop; 1251 u32 rc; 1252 struct controller *ctrl; 1253 struct controller *tctrl; 1254 struct pci_resource *res; 1255 struct pci_resource *tres; 1256 1257 rc = compaq_nvram_store(cpqhp_rom_start); 1258 1259 ctrl = cpqhp_ctrl_list; 1260 1261 while (ctrl) { 1262 if (ctrl->hpc_reg) { 1263 u16 misc; 1264 rc = read_slot_enable(ctrl); 1265 1266 writeb(0, ctrl->hpc_reg + SLOT_SERR); 1267 writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK); 1268 1269 misc = readw(ctrl->hpc_reg + MISC); 1270 misc &= 0xFFFD; 1271 writew(misc, ctrl->hpc_reg + MISC); 1272 } 1273 1274 ctrl_slot_cleanup(ctrl); 1275 1276 res = ctrl->io_head; 1277 while (res) { 1278 tres = res; 1279 res = res->next; 1280 kfree(tres); 1281 } 1282 1283 res = ctrl->mem_head; 1284 while (res) { 1285 tres = res; 1286 res = res->next; 1287 kfree(tres); 1288 } 1289 1290 res = ctrl->p_mem_head; 1291 while (res) { 1292 tres = res; 1293 res = res->next; 1294 kfree(tres); 1295 } 1296 1297 res = ctrl->bus_head; 1298 while (res) { 1299 tres = res; 1300 res = res->next; 1301 kfree(tres); 1302 } 1303 1304 kfree(ctrl->pci_bus); 1305 1306 tctrl = ctrl; 1307 ctrl = ctrl->next; 1308 kfree(tctrl); 1309 } 1310 1311 for (loop = 0; loop < 256; loop++) { 1312 next = cpqhp_slot_list[loop]; 1313 while (next != NULL) { 1314 res = next->io_head; 1315 while (res) { 1316 tres = res; 1317 res = res->next; 1318 kfree(tres); 1319 } 1320 1321 res = next->mem_head; 1322 while (res) { 1323 tres = res; 1324 res = res->next; 1325 kfree(tres); 1326 } 1327 1328 res = next->p_mem_head; 1329 while (res) { 1330 tres = res; 1331 res = res->next; 1332 kfree(tres); 1333 } 1334 1335 res = next->bus_head; 1336 while (res) { 1337 tres = res; 1338 res = res->next; 1339 kfree(tres); 1340 } 1341 1342 TempSlot = next; 1343 next = next->next; 1344 kfree(TempSlot); 1345 } 1346 } 1347 1348 /* Stop the notification mechanism */ 1349 if (initialized) 1350 cpqhp_event_stop_thread(); 1351 1352 /* unmap the rom address */ 1353 if (cpqhp_rom_start) 1354 iounmap(cpqhp_rom_start); 1355 if (smbios_start) 1356 iounmap(smbios_start); 1357 } 1358 1359 static const struct pci_device_id hpcd_pci_tbl[] = { 1360 { 1361 /* handle any PCI Hotplug controller */ 1362 .class = ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), 1363 .class_mask = ~0, 1364 1365 /* no matter who makes it */ 1366 .vendor = PCI_ANY_ID, 1367 .device = PCI_ANY_ID, 1368 .subvendor = PCI_ANY_ID, 1369 .subdevice = PCI_ANY_ID, 1370 1371 }, { /* end: all zeroes */ } 1372 }; 1373 1374 MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl); 1375 1376 static struct pci_driver cpqhpc_driver = { 1377 .name = "compaq_pci_hotplug", 1378 .id_table = hpcd_pci_tbl, 1379 .probe = cpqhpc_probe, 1380 /* remove: cpqhpc_remove_one, */ 1381 }; 1382 1383 static int __init cpqhpc_init(void) 1384 { 1385 int result; 1386 1387 cpqhp_debug = debug; 1388 1389 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 1390 cpqhp_initialize_debugfs(); 1391 result = pci_register_driver(&cpqhpc_driver); 1392 dbg("pci_register_driver = %d\n", result); 1393 return result; 1394 } 1395 1396 static void __exit cpqhpc_cleanup(void) 1397 { 1398 dbg("unload_cpqphpd()\n"); 1399 unload_cpqphpd(); 1400 1401 dbg("pci_unregister_driver\n"); 1402 pci_unregister_driver(&cpqhpc_driver); 1403 cpqhp_shutdown_debugfs(); 1404 } 1405 1406 module_init(cpqhpc_init); 1407 module_exit(cpqhpc_cleanup); 1408