1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright 2023 Oxide Computer Company 28 */ 29 30 /* 31 * ********************************************************************** 32 * Extension module for PCI nexus drivers to support PCI Hot Plug feature. 33 * 34 * DESCRIPTION: 35 * This module basically implements "devctl" and Attachment Point device 36 * nodes for hot plug operations. The cb_ops functions needed for access 37 * to these device nodes are also implemented. For hotplug operations 38 * on Attachment Points it interacts with the hotplug services (HPS) 39 * framework. A pci nexus driver would simply call pcihp_init() in its 40 * attach() function and pcihp_uninit() call in its detach() function. 41 * ********************************************************************** 42 */ 43 44 #include <sys/conf.h> 45 #include <sys/kmem.h> 46 #include <sys/debug.h> 47 #include <sys/modctl.h> 48 #include <sys/autoconf.h> 49 #include <sys/ddi.h> 50 #include <sys/sunddi.h> 51 #include <sys/sunndi.h> 52 #include <sys/ddi_impldefs.h> 53 #include <sys/ndi_impldefs.h> 54 #include <sys/ddipropdefs.h> 55 #include <sys/open.h> 56 #include <sys/file.h> 57 #include <sys/stat.h> 58 #include <sys/pci.h> 59 #include <sys/pci_impl.h> 60 #include <sys/devctl.h> 61 #include <sys/hotplug/hpcsvc.h> 62 #include <sys/hotplug/pci/pcicfg.h> 63 #include <sys/hotplug/pci/pcihp.h> 64 #include <sys/sysevent.h> 65 #include <sys/sysevent/eventdefs.h> 66 #include <sys/sysevent/dr.h> 67 #include <sys/fs/dv_node.h> 68 69 /* 70 * NOTE: 71 * This module depends on PCI Configurator module (misc/pcicfg), 72 * Hot Plug Services framework module (misc/hpcsvc) and Bus Resource 73 * Allocator module (misc/busra). 74 */ 75 76 /* 77 * ************************************************************************ 78 * *** Implementation specific data structures/definitions. *** 79 * ************************************************************************ 80 */ 81 82 /* soft state */ 83 typedef enum { PCIHP_SOFT_STATE_CLOSED, PCIHP_SOFT_STATE_OPEN, 84 PCIHP_SOFT_STATE_OPEN_EXCL } pcihp_soft_state_t; 85 86 #define PCI_MAX_DEVS 32 /* max. number of devices on a pci bus */ 87 88 /* the following correspond to sysevent defined subclasses */ 89 #define PCIHP_DR_AP_STATE_CHANGE 0 90 #define PCIHP_DR_REQ 1 91 92 /* pcihp_get_soft_state() command argument */ 93 #define PCIHP_DR_NOOP 0 94 #define PCIHP_DR_BUS_CONFIGURE 1 95 #define PCIHP_DR_BUS_UNCONFIGURE 2 96 #define PCIHP_DR_SLOT_ENTER 4 97 #define PCIHP_DR_SLOT_EXIT 8 98 99 /* hot plug bus state */ 100 enum { PCIHP_BUS_INITIALIZING, PCIHP_BUS_UNCONFIGURED, 101 PCIHP_BUS_CONFIGURED }; 102 103 /* 104 * Soft state structure associated with each hot plug pci bus instance. 105 */ 106 typedef struct pcihp { 107 struct pcihp *nextp; 108 109 /* devinfo pointer to the pci bus node */ 110 dev_info_t *dip; 111 112 /* soft state flags: PCIHP_SOFT_STATE_* */ 113 pcihp_soft_state_t soft_state; 114 115 /* global mutex to serialize exclusive access to the bus */ 116 kmutex_t mutex; 117 118 /* slot information structure */ 119 struct pcihp_slotinfo { 120 hpc_slot_t slot_hdl; /* HPS slot handle */ 121 ap_rstate_t rstate; /* state of Receptacle */ 122 ap_ostate_t ostate; /* state of the Occupant */ 123 ap_condition_t condition; /* condition of the occupant */ 124 time32_t last_change; /* XXX needed? */ 125 uint32_t event_mask; /* last event mask registered */ 126 char *name; /* slot logical name */ 127 uint_t slot_flags; 128 uint16_t slot_type; /* slot type: pci or cpci */ 129 uint16_t slot_capabilities; /* 64bit, etc. */ 130 int hs_csr_location; /* Location of HS_CSR */ 131 kmutex_t slot_mutex; /* mutex to serialize hotplug */ 132 /* operations on the slot */ 133 } slotinfo[PCI_MAX_DEVS]; 134 135 /* misc. bus attributes */ 136 uint_t bus_flags; 137 uint_t bus_state; 138 uint_t slots_active; 139 } pcihp_t; 140 141 /* 142 * Bit definitions for slot_flags field: 143 * 144 * PCIHP_SLOT_AUTO_CFG_EN This flags is set if nexus can do auto 145 * configuration of hot plugged card on this slot 146 * if the hardware reports the hot plug events. 147 * 148 * PCIHP_SLOT_DISABLED Slot is disabled for hotplug operations. 149 * 150 * PCIHP_SLOT_NOT_HEALTHY HEALTHY# signal is not OK on this slot. 151 */ 152 #define PCIHP_SLOT_AUTO_CFG_EN 0x1 153 #define PCIHP_SLOT_DISABLED 0x2 154 #define PCIHP_SLOT_NOT_HEALTHY 0x4 155 #define PCIHP_SLOT_DEV_NON_HOTPLUG 0x8 156 #define PCIHP_SLOT_ENUM_INS_PENDING 0x10 157 #define PCIHP_SLOT_ENUM_EXT_PENDING 0x20 158 159 /* 160 * Bit definitions for bus_flags field: 161 * 162 * PCIHP_BUS_66MHZ Bus is running at 66Mhz. 163 */ 164 #define PCIHP_BUS_66MHZ 0x1 165 #define PCIHP_BUS_ENUM_RADIAL 0x2 166 167 #define PCIHP_DEVICES_STR "/devices" 168 169 /* 170 * control structure for tree walk during configure/unconfigure operation. 171 */ 172 struct pcihp_config_ctrl { 173 int pci_dev; /* PCI device number for the slot */ 174 uint_t flags; /* control flags (see below) */ 175 int op; /* operation: PCIHP_ONLINE or PCIHP_OFFLINE */ 176 int rv; /* return error code */ 177 dev_info_t *dip; /* dip at which the (first) error occurred */ 178 hpc_occupant_info_t *occupant; 179 }; 180 181 /* 182 * control flags for configure/unconfigure operations on the tree. 183 * 184 * PCIHP_CFG_CONTINUE continue the operation ignoring errors 185 */ 186 #define PCIHP_CFG_CONTINUE 0x1 187 188 #define PCIHP_ONLINE 1 189 #define PCIHP_OFFLINE 0 190 191 192 /* Leaf ops (hotplug controls for target devices) */ 193 static int pcihp_open(dev_t *, int, int, cred_t *); 194 static int pcihp_close(dev_t, int, int, cred_t *); 195 static int pcihp_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 196 197 #ifdef DEBUG 198 static int pcihp_debug = 0; 199 #define PCIHP_DEBUG(args) if (pcihp_debug >= 1) cmn_err args 200 #define PCIHP_DEBUG2(args) if (pcihp_debug >= 2) cmn_err args 201 #else 202 #define PCIHP_DEBUG(args) 203 #define PCIHP_DEBUG2(args) 204 #endif 205 206 /* 207 * We process ENUM# event one device at a time ie. as soon as we detect 208 * that a device has the right ENUM# conditions, we return. If the following 209 * variable is set to non-zero, we scan all the devices on the bus 210 * for ENUM# conditions. 211 */ 212 static int pcihp_enum_scan_all = 0; 213 /* 214 * If HSC driver cannot determine the board type (for example: it may not 215 * be possible to differentiate between a Basic Hotswap, Non Hotswap or 216 * Non-friendly Full hotswap board), the default board type is assigned 217 * to be as defined by the following variable. 218 */ 219 static int pcihp_cpci_board_type = HPC_BOARD_CPCI_NON_HS; 220 static int pcihp_cpci_led_blink = 30; 221 /* 222 * It was noted that the blue LED when written on/off would cause INS/EXT 223 * bit to be set causing an extra interrupt. Although the cPCI specifications 224 * does not imply this, this behavior is seen with some FHS silicons. 225 * Also, handling the INS/EXT bit would control the LED being On/Off. 226 * Until the behavior is confirmed, this flag could be used to enable or 227 * disable handling the LED. 228 * 0 means the silicons handles the LED behavior via the INS/EXT bit. 229 * 1 means the software must explicitly do the LED behavior. 230 */ 231 static int pcihp_cpci_blue_led = 1; 232 233 /* static functions */ 234 static pcihp_t *pcihp_create_soft_state(dev_info_t *dip); 235 static void pcihp_destroy_soft_state(dev_info_t *dip); 236 static pcihp_t *pcihp_get_soft_state(dev_info_t *dip, int cmd, int *rv); 237 static int pcihp_configure_ap(pcihp_t *pcihp_p, int pci_dev); 238 static int pcihp_unconfigure_ap(pcihp_t *pcihp_p, int pci_dev); 239 static int pcihp_new_slot_state(dev_info_t *, hpc_slot_t, 240 hpc_slot_info_t *, int); 241 static int pcihp_configure(dev_info_t *, void *); 242 static bool_t pcihp_check_status(dev_info_t *); 243 static int pcihp_event_handler(caddr_t, uint_t); 244 static dev_info_t *pcihp_devi_find(dev_info_t *dip, uint_t dev, uint_t func); 245 static int pcihp_match_dev(dev_info_t *dip, void *hdl); 246 static int pcihp_get_hs_csr(struct pcihp_slotinfo *, ddi_acc_handle_t, 247 uint8_t *); 248 static void pcihp_set_hs_csr(struct pcihp_slotinfo *, ddi_acc_handle_t, 249 uint8_t *); 250 static int pcihp_get_hs_csr_location(ddi_acc_handle_t); 251 static int pcihp_handle_enum(pcihp_t *, int, int, int); 252 static void pcihp_hs_csr_op(pcihp_t *, int, int); 253 static int pcihp_enum_slot(pcihp_t *, struct pcihp_slotinfo *, int, int, int); 254 static int pcihp_handle_enum_extraction(pcihp_t *, int, int, int); 255 static int pcihp_handle_enum_insertion(pcihp_t *, int, int, int); 256 static int pcihp_add_dummy_reg_property(dev_info_t *, uint_t, uint_t, uint_t); 257 static int pcihp_config_setup(dev_info_t **, ddi_acc_handle_t *, 258 dev_info_t **, int, pcihp_t *); 259 static void pcihp_config_teardown(ddi_acc_handle_t *, 260 dev_info_t **, int, pcihp_t *); 261 static int pcihp_get_board_type(struct pcihp_slotinfo *); 262 /* sysevent function */ 263 static void pcihp_gen_sysevent(char *, int, int, dev_info_t *, int); 264 265 static int pcihp_list_occupants(dev_info_t *, void *); 266 static int pcihp_indirect_map(dev_info_t *dip); 267 268 #if 0 269 static void pcihp_probe_slot_state(dev_info_t *, int, hpc_slot_state_t *); 270 #endif 271 272 int pcihp_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 273 int flags, char *name, caddr_t valuep, int *lengthp); 274 275 struct cb_ops pcihp_cb_ops = { 276 pcihp_open, /* open */ 277 pcihp_close, /* close */ 278 nodev, /* strategy */ 279 nodev, /* print */ 280 nodev, /* dump */ 281 nodev, /* read */ 282 nodev, /* write */ 283 pcihp_ioctl, /* ioctl */ 284 nodev, /* devmap */ 285 nodev, /* mmap */ 286 nodev, /* segmap */ 287 nochpoll, /* poll */ 288 pcihp_prop_op, /* cb_prop_op */ 289 NULL, /* streamtab */ 290 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 291 CB_REV, /* rev */ 292 nodev, /* int (*cb_aread)() */ 293 nodev /* int (*cb_awrite)() */ 294 }; 295 296 /* 297 * local data 298 */ 299 300 int pcihp_autocfg_enabled = 1; /* auto config is enabled by default */ 301 302 static kmutex_t pcihp_mutex; /* mutex to protect the following data */ 303 static pcihp_t *pcihp_head = NULL; 304 305 static kmutex_t pcihp_open_mutex; /* mutex to protect open/close/uninit */ 306 static int pci_devlink_flags = 0; 307 308 /* 309 * Module linkage information for the kernel. 310 */ 311 extern struct mod_ops mod_miscops; 312 static struct modlmisc modlmisc = { 313 &mod_miscops, 314 "PCI nexus hotplug support", 315 }; 316 317 static struct modlinkage modlinkage = { 318 MODREV_1, 319 &modlmisc, 320 NULL 321 }; 322 323 int 324 _init(void) 325 { 326 int error; 327 328 mutex_init(&pcihp_mutex, NULL, MUTEX_DRIVER, NULL); 329 mutex_init(&pcihp_open_mutex, NULL, MUTEX_DRIVER, NULL); 330 if ((error = mod_install(&modlinkage)) != 0) { 331 mutex_destroy(&pcihp_open_mutex); 332 mutex_destroy(&pcihp_mutex); 333 } 334 335 return (error); 336 } 337 338 int 339 _fini(void) 340 { 341 return (EBUSY); 342 } 343 344 int 345 _info(struct modinfo *modinfop) 346 { 347 return (mod_info(&modlinkage, modinfop)); 348 } 349 350 static pcihp_t * 351 pcihp_create_soft_state( 352 dev_info_t *dip) 353 { 354 pcihp_t *pcihp_p; 355 356 pcihp_p = kmem_zalloc(sizeof (struct pcihp), KM_SLEEP); 357 358 pcihp_p->dip = dip; 359 mutex_init(&pcihp_p->mutex, NULL, MUTEX_DRIVER, NULL); 360 361 mutex_enter(&pcihp_mutex); 362 pcihp_p->nextp = pcihp_head; 363 pcihp_head = pcihp_p; 364 pcihp_p->bus_state = PCIHP_BUS_INITIALIZING; 365 pcihp_p->slots_active = 0; 366 mutex_exit(&pcihp_mutex); 367 368 return (pcihp_p); 369 } 370 371 static void 372 pcihp_destroy_soft_state( 373 dev_info_t *dip) 374 { 375 pcihp_t *p; 376 pcihp_t **pp; 377 378 mutex_enter(&pcihp_mutex); 379 pp = &pcihp_head; 380 while ((p = *pp) != NULL) { 381 if (p->dip == dip) { 382 *pp = p->nextp; 383 kmem_free(p, sizeof (struct pcihp)); 384 break; 385 } 386 pp = &(p->nextp); 387 } 388 mutex_exit(&pcihp_mutex); 389 } 390 391 /* 392 * This function should be imported by client nexus drivers as their 393 * devo_getinfo() entry point. 394 */ 395 396 /* ARGSUSED */ 397 int 398 pcihp_info( 399 dev_info_t *dip, 400 ddi_info_cmd_t cmd, 401 void *arg, 402 void **result) 403 { 404 pcihp_t *pcihp_p; 405 major_t major; 406 minor_t minor; 407 int instance; 408 409 major = getmajor((dev_t)arg); 410 minor = getminor((dev_t)arg); 411 instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor); 412 413 switch (cmd) { 414 default: 415 return (DDI_FAILURE); 416 417 case DDI_INFO_DEVT2INSTANCE: 418 *result = (void *)(intptr_t)instance; 419 return (DDI_SUCCESS); 420 421 case DDI_INFO_DEVT2DEVINFO: 422 mutex_enter(&pcihp_mutex); 423 pcihp_p = pcihp_head; 424 while (pcihp_p != NULL) { 425 if (ddi_driver_major(pcihp_p->dip) == 426 major && ddi_get_instance(pcihp_p->dip) == 427 instance) { 428 *result = (void *)pcihp_p->dip; 429 mutex_exit(&pcihp_mutex); 430 return (DDI_SUCCESS); 431 } 432 pcihp_p = pcihp_p->nextp; 433 } 434 mutex_exit(&pcihp_mutex); 435 return (DDI_FAILURE); 436 } 437 } 438 439 /* 440 * This function retrieves the hot plug soft state and performs the 441 * following primitive commands while the soft state is locked: 442 * mark the bus unconfigured, increment slot activity, decrement 443 * slot activity and noop. 444 */ 445 446 /* ARGSUSED */ 447 static pcihp_t * 448 pcihp_get_soft_state( 449 dev_info_t *dip, int cmd, int *rv) 450 { 451 pcihp_t *pcihp_p; 452 453 *rv = PCIHP_SUCCESS; 454 mutex_enter(&pcihp_mutex); 455 pcihp_p = pcihp_head; 456 while (pcihp_p != NULL) { 457 if (pcihp_p->dip == dip) { 458 switch (cmd) { 459 case PCIHP_DR_BUS_UNCONFIGURE: 460 if (pcihp_p->slots_active == 0) 461 pcihp_p->bus_state = 462 PCIHP_BUS_UNCONFIGURED; 463 else 464 *rv = PCIHP_FAILURE; 465 break; 466 case PCIHP_DR_SLOT_ENTER: 467 if (pcihp_p->bus_state == 468 PCIHP_BUS_UNCONFIGURED) 469 *rv = PCIHP_FAILURE; 470 else 471 pcihp_p->slots_active++; 472 break; 473 case PCIHP_DR_SLOT_EXIT: 474 ASSERT(pcihp_p->slots_active > 0); 475 if (pcihp_p->slots_active == 0) 476 cmn_err(CE_PANIC, 477 "pcihp (%s%d): mismatched slot" 478 " activity", 479 ddi_driver_name(dip), 480 ddi_get_instance(dip)); 481 else 482 pcihp_p->slots_active--; 483 break; 484 case PCIHP_DR_NOOP: 485 break; 486 default: 487 *rv = PCIHP_FAILURE; 488 break; 489 } 490 mutex_exit(&pcihp_mutex); 491 return (pcihp_p); 492 } 493 pcihp_p = pcihp_p->nextp; 494 } 495 mutex_exit(&pcihp_mutex); 496 497 return (NULL); 498 } 499 500 /* ARGSUSED3 */ 501 static int 502 pcihp_open(dev_t *devp, int flags, int otyp, cred_t *credp) 503 { 504 dev_info_t *self; 505 pcihp_t *pcihp_p; 506 minor_t minor; 507 int pci_dev; 508 int rv; 509 510 /* 511 * Make sure the open is for the right file type. 512 */ 513 if (otyp != OTYP_CHR) 514 return (EINVAL); 515 516 mutex_enter(&pcihp_open_mutex); 517 /* 518 * Get the soft state structure. 519 */ 520 if (pcihp_info(NULL, DDI_INFO_DEVT2DEVINFO, (void *)*devp, 521 (void **)&self) != DDI_SUCCESS) { 522 mutex_exit(&pcihp_open_mutex); 523 return (ENXIO); 524 } 525 526 pcihp_p = pcihp_get_soft_state(self, PCIHP_DR_NOOP, &rv); 527 ASSERT(pcihp_p != NULL); 528 529 mutex_enter(&pcihp_p->mutex); 530 531 /* 532 * If the pci_dev is valid then the minor device is an 533 * AP. Otherwise it is ":devctl" minor device. 534 */ 535 minor = getminor(*devp); 536 pci_dev = PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor); 537 if (pci_dev < PCI_MAX_DEVS) { 538 struct pcihp_slotinfo *slotinfop; 539 540 slotinfop = &pcihp_p->slotinfo[pci_dev]; 541 if (slotinfop->slot_hdl == NULL) { 542 mutex_exit(&pcihp_p->mutex); 543 mutex_exit(&pcihp_open_mutex); 544 return (ENXIO); 545 } 546 } 547 548 /* 549 * Handle the open by tracking the device state. 550 * 551 * Note: Needs review w.r.t exclusive access to AP or the bus. 552 * Currently in the pci plug-in we don't use EXCL open at all 553 * so the code below implements EXCL access on the bus. 554 */ 555 556 /* enforce exclusive access to the bus */ 557 if ((pcihp_p->soft_state == PCIHP_SOFT_STATE_OPEN_EXCL) || 558 ((flags & FEXCL) && 559 (pcihp_p->soft_state != PCIHP_SOFT_STATE_CLOSED))) { 560 mutex_exit(&pcihp_p->mutex); 561 mutex_exit(&pcihp_open_mutex); 562 return (EBUSY); 563 } 564 565 if (flags & FEXCL) 566 pcihp_p->soft_state = PCIHP_SOFT_STATE_OPEN_EXCL; 567 else 568 pcihp_p->soft_state = PCIHP_SOFT_STATE_OPEN; 569 570 mutex_exit(&pcihp_p->mutex); 571 mutex_exit(&pcihp_open_mutex); 572 573 return (0); 574 } 575 576 /* ARGSUSED */ 577 static int 578 pcihp_close(dev_t dev, int flags, int otyp, cred_t *credp) 579 { 580 dev_info_t *self; 581 pcihp_t *pcihp_p; 582 int rv; 583 584 if (otyp != OTYP_CHR) 585 return (EINVAL); 586 587 mutex_enter(&pcihp_open_mutex); 588 589 if (pcihp_info(NULL, DDI_INFO_DEVT2DEVINFO, (void *)dev, 590 (void **)&self) != DDI_SUCCESS) { 591 mutex_exit(&pcihp_open_mutex); 592 return (ENXIO); 593 } 594 595 pcihp_p = pcihp_get_soft_state(self, PCIHP_DR_NOOP, &rv); 596 ASSERT(pcihp_p != NULL); 597 598 mutex_enter(&pcihp_p->mutex); 599 pcihp_p->soft_state = PCIHP_SOFT_STATE_CLOSED; 600 mutex_exit(&pcihp_p->mutex); 601 602 mutex_exit(&pcihp_open_mutex); 603 604 return (0); 605 } 606 607 static int 608 pcihp_list_occupants(dev_info_t *dip, void *hdl) 609 { 610 int pci_dev; 611 struct pcihp_config_ctrl *ctrl = (struct pcihp_config_ctrl *)hdl; 612 pci_regspec_t *pci_rp; 613 int length; 614 major_t major; 615 616 /* 617 * Get the PCI device number information from the devinfo 618 * node. Since the node may not have the address field 619 * setup (this is done in the DDI_INITCHILD of the parent) 620 * we look up the 'reg' property to decode that information. 621 */ 622 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 623 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, 624 (uint_t *)&length) != DDI_PROP_SUCCESS) { 625 ctrl->rv = DDI_FAILURE; 626 ctrl->dip = dip; 627 return (DDI_WALK_TERMINATE); 628 } 629 630 /* get the pci device id information */ 631 pci_dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 632 633 /* 634 * free the memory allocated by ddi_prop_lookup_int_array 635 */ 636 ddi_prop_free(pci_rp); 637 638 /* 639 * Match the node for the device number of the slot. 640 */ 641 if (pci_dev == ctrl->pci_dev) { /* node is a match */ 642 643 major = ddi_driver_major(dip); 644 645 /* 646 * If the node is not yet attached, then don't list it 647 * as an occupant. This is valid, since nothing can be 648 * consuming it until it is attached, and cfgadm will 649 * ask for the property explicitly which will cause it 650 * to be re-freshed right before checking with rcm. 651 */ 652 if ((major == -1) || !i_ddi_devi_attached(dip)) 653 return (DDI_WALK_PRUNECHILD); 654 655 /* 656 * If we have used all our occupants then print mesage 657 * and terminate walk. 658 */ 659 if (ctrl->occupant->i >= HPC_MAX_OCCUPANTS) { 660 cmn_err(CE_WARN, 661 "pcihp (%s%d): unable to list all occupants", 662 ddi_driver_name(ddi_get_parent(dip)), 663 ddi_get_instance(ddi_get_parent(dip))); 664 return (DDI_WALK_TERMINATE); 665 } 666 667 /* 668 * No need to hold the dip as ddi_walk_devs 669 * has already arranged that for us. 670 */ 671 ctrl->occupant->id[ctrl->occupant->i] = 672 kmem_alloc(sizeof (char[MAXPATHLEN]), KM_SLEEP); 673 (void) ddi_pathname(dip, 674 (char *)ctrl->occupant->id[ctrl->occupant->i]); 675 ctrl->occupant->i++; 676 } 677 678 /* 679 * continue the walk to the next sibling to look for a match 680 * or to find other nodes if this card is a multi-function card. 681 */ 682 return (DDI_WALK_PRUNECHILD); 683 } 684 685 static void 686 pcihp_create_occupant_props_nolock(dev_info_t *self, dev_t dev, int pci_dev) 687 { 688 struct pcihp_config_ctrl ctrl; 689 hpc_occupant_info_t *occupant; 690 int i; 691 692 occupant = kmem_alloc(sizeof (hpc_occupant_info_t), KM_SLEEP); 693 occupant->i = 0; 694 695 ctrl.flags = 0; 696 ctrl.dip = NULL; 697 ctrl.rv = NDI_SUCCESS; 698 ctrl.pci_dev = pci_dev; 699 ctrl.op = 55; /* should define DRYRUN */ 700 ctrl.occupant = occupant; 701 702 ddi_walk_devs(ddi_get_child(self), pcihp_list_occupants, 703 (void *)&ctrl); 704 705 if (occupant->i == 0) { 706 /* no occupants right now, need to create stub property */ 707 char *c[] = { "" }; 708 (void) ddi_prop_update_string_array(dev, self, "pci-occupant", 709 c, 1); 710 } else { 711 (void) ddi_prop_update_string_array(dev, self, "pci-occupant", 712 occupant->id, occupant->i); 713 } 714 for (i = 0; i < occupant->i; i++) { 715 kmem_free(occupant->id[i], sizeof (char[MAXPATHLEN])); 716 } 717 718 kmem_free(occupant, sizeof (hpc_occupant_info_t)); 719 } 720 721 static void 722 pcihp_create_occupant_props(dev_info_t *self, dev_t dev, int pci_dev) 723 { 724 ndi_devi_enter(self); 725 pcihp_create_occupant_props_nolock(self, dev, pci_dev); 726 ndi_devi_exit(self); 727 } 728 729 static void 730 pcihp_delete_occupant_props(dev_info_t *dip, dev_t dev) 731 { 732 if (ddi_prop_remove(dev, dip, "pci-occupant") 733 != DDI_PROP_SUCCESS) 734 return; /* add error handling */ 735 736 } 737 738 /* 739 * pcihp_ioctl: devctl hotplug controls 740 */ 741 /* ARGSUSED */ 742 static int 743 pcihp_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 744 int *rvalp) 745 { 746 pcihp_t *pcihp_p; 747 dev_info_t *self; 748 struct devctl_iocdata *dcp; 749 uint_t bus_state; 750 int rv = 0; 751 int pci_dev; 752 struct pcihp_slotinfo *slotinfop; 753 hpc_slot_state_t rstate; 754 devctl_ap_state_t ap_state; 755 struct hpc_control_data hpc_ctrldata; 756 struct hpc_led_info led_info; 757 time_t time; 758 int state_locking; 759 int state_unlocking; 760 int rval; 761 char *pathname = NULL; 762 763 /* 764 * read devctl ioctl data before soft state retrieval 765 */ 766 if ((cmd != DEVCTL_AP_CONTROL) && 767 ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) 768 return (EFAULT); 769 770 if (pcihp_info(NULL, DDI_INFO_DEVT2DEVINFO, (void *)dev, 771 (void **)&self) != DDI_SUCCESS) { 772 if (cmd != DEVCTL_AP_CONTROL) 773 ndi_dc_freehdl(dcp); 774 return (ENXIO); 775 } 776 777 switch (cmd) { 778 case DEVCTL_AP_INSERT: 779 case DEVCTL_AP_REMOVE: 780 case DEVCTL_AP_CONNECT: 781 case DEVCTL_AP_DISCONNECT: 782 case DEVCTL_AP_CONFIGURE: 783 case DEVCTL_AP_UNCONFIGURE: 784 case DEVCTL_AP_GETSTATE: 785 case DEVCTL_AP_CONTROL: 786 state_locking = PCIHP_DR_SLOT_ENTER; 787 state_unlocking = PCIHP_DR_SLOT_EXIT; 788 break; 789 default: 790 state_locking = PCIHP_DR_NOOP; 791 state_unlocking = PCIHP_DR_NOOP; 792 break; 793 } 794 795 pcihp_p = pcihp_get_soft_state(self, state_locking, &rval); 796 ASSERT(pcihp_p != NULL); 797 798 if (rval == PCIHP_FAILURE) { 799 (void) ddi_pathname(pcihp_p->dip, pathname); 800 PCIHP_DEBUG((CE_WARN, "Hot Plug bus %s instance is unconfigured" 801 " while slot activity is requested\n", pathname)); 802 if (cmd != DEVCTL_AP_CONTROL) 803 ndi_dc_freehdl(dcp); 804 return (EBUSY); 805 } 806 807 /* 808 * For attachment points the lower 8 bits of the minor number is the 809 * PCI device number. 810 */ 811 pci_dev = PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(getminor(dev)); 812 813 /* 814 * We can use the generic implementation for these ioctls 815 */ 816 switch (cmd) { 817 case DEVCTL_DEVICE_GETSTATE: 818 case DEVCTL_DEVICE_ONLINE: 819 case DEVCTL_DEVICE_OFFLINE: 820 case DEVCTL_BUS_GETSTATE: 821 rv = ndi_devctl_ioctl(self, cmd, arg, mode, 0); 822 ndi_dc_freehdl(dcp); 823 return (rv); 824 default: 825 break; 826 } 827 828 switch (cmd) { 829 830 case DEVCTL_DEVICE_RESET: 831 rv = ENOTSUP; 832 break; 833 834 case DEVCTL_BUS_QUIESCE: 835 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) 836 if (bus_state == BUS_QUIESCED) 837 break; 838 (void) ndi_set_bus_state(self, BUS_QUIESCED); 839 break; 840 841 case DEVCTL_BUS_UNQUIESCE: 842 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) 843 if (bus_state == BUS_ACTIVE) 844 break; 845 (void) ndi_set_bus_state(self, BUS_ACTIVE); 846 break; 847 848 case DEVCTL_BUS_RESET: 849 rv = ENOTSUP; 850 break; 851 852 case DEVCTL_BUS_RESETALL: 853 rv = ENOTSUP; 854 break; 855 856 case DEVCTL_AP_CONNECT: 857 case DEVCTL_AP_DISCONNECT: 858 /* 859 * CONNECT(DISCONNECT) the hot plug slot to(from) the bus. 860 * 861 * For cPCI slots this operation is a nop so the HPC 862 * driver may return success if it is a valid operation. 863 */ 864 case DEVCTL_AP_INSERT: 865 case DEVCTL_AP_REMOVE: 866 /* 867 * Prepare the slot for INSERT/REMOVE operation. 868 */ 869 870 /* 871 * check for valid request: 872 * 1. It is a hotplug slot. 873 * 2. The slot has no occupant that is in 874 * the 'configured' state. 875 */ 876 if (pci_dev >= PCI_MAX_DEVS) { 877 rv = ENXIO; 878 break; 879 } 880 slotinfop = &pcihp_p->slotinfo[pci_dev]; 881 882 mutex_enter(&slotinfop->slot_mutex); 883 884 if ((slotinfop->slot_hdl == NULL) || 885 (slotinfop->slot_flags & PCIHP_SLOT_DISABLED)) { 886 rv = ENXIO; 887 mutex_exit(&slotinfop->slot_mutex); 888 break; 889 } 890 891 /* the slot occupant must be in the UNCONFIGURED state */ 892 if (slotinfop->ostate != AP_OSTATE_UNCONFIGURED) { 893 rv = EINVAL; 894 mutex_exit(&slotinfop->slot_mutex); 895 break; 896 } 897 /* 898 * Call the HPC driver to perform the operation on the slot. 899 */ 900 901 switch (cmd) { 902 case DEVCTL_AP_INSERT: 903 rv = hpc_nexus_insert(slotinfop->slot_hdl, NULL, 0); 904 break; 905 case DEVCTL_AP_REMOVE: 906 rv = hpc_nexus_remove(slotinfop->slot_hdl, NULL, 0); 907 break; 908 case DEVCTL_AP_CONNECT: 909 rv = hpc_nexus_connect(slotinfop->slot_hdl, NULL, 0); 910 if (rv == HPC_SUCCESS) { 911 slotinfop->rstate = AP_RSTATE_CONNECTED; 912 913 if (drv_getparm(TIME, (void *)&time) != 914 DDI_SUCCESS) 915 slotinfop->last_change = (time_t)-1; 916 else 917 slotinfop->last_change = (time32_t)time; 918 919 slotinfop = &pcihp_p->slotinfo[pci_dev]; 920 pcihp_gen_sysevent(slotinfop->name, 921 PCIHP_DR_AP_STATE_CHANGE, 922 SE_NO_HINT, pcihp_p->dip, 923 KM_SLEEP); 924 } 925 break; 926 case DEVCTL_AP_DISCONNECT: 927 rv = hpc_nexus_disconnect(slotinfop->slot_hdl, NULL, 0); 928 if (rv == HPC_SUCCESS) { 929 slotinfop->rstate = AP_RSTATE_DISCONNECTED; 930 931 if (drv_getparm(TIME, (void *)&time) != 932 DDI_SUCCESS) 933 slotinfop->last_change = (time_t)-1; 934 else 935 slotinfop->last_change = (time32_t)time; 936 937 slotinfop = &pcihp_p->slotinfo[pci_dev]; 938 pcihp_gen_sysevent(slotinfop->name, 939 PCIHP_DR_AP_STATE_CHANGE, 940 SE_NO_HINT, pcihp_p->dip, 941 KM_SLEEP); 942 } 943 break; 944 } 945 mutex_exit(&slotinfop->slot_mutex); 946 947 switch (rv) { 948 case HPC_ERR_INVALID: 949 rv = ENXIO; 950 break; 951 case HPC_ERR_NOTSUPPORTED: 952 rv = ENOTSUP; 953 break; 954 case HPC_ERR_FAILED: 955 rv = EIO; 956 break; 957 } 958 959 break; 960 961 case DEVCTL_AP_CONFIGURE: 962 /* 963 * ************************************** 964 * CONFIGURE the occupant in the slot. 965 * ************************************** 966 */ 967 slotinfop = &pcihp_p->slotinfo[pci_dev]; 968 969 mutex_enter(&slotinfop->slot_mutex); 970 971 rv = pcihp_configure_ap(pcihp_p, pci_dev); 972 if (rv == HPC_SUCCESS) { 973 pcihp_gen_sysevent(slotinfop->name, 974 PCIHP_DR_AP_STATE_CHANGE, 975 SE_NO_HINT, pcihp_p->dip, KM_SLEEP); 976 pcihp_create_occupant_props(self, dev, pci_dev); 977 } 978 mutex_exit(&slotinfop->slot_mutex); 979 980 break; 981 982 case DEVCTL_AP_UNCONFIGURE: 983 /* 984 * ************************************** 985 * UNCONFIGURE the occupant in the slot. 986 * ************************************** 987 */ 988 slotinfop = &pcihp_p->slotinfo[pci_dev]; 989 990 mutex_enter(&slotinfop->slot_mutex); 991 992 rv = pcihp_unconfigure_ap(pcihp_p, pci_dev); 993 994 if (rv == HPC_SUCCESS) { 995 pcihp_gen_sysevent(slotinfop->name, 996 PCIHP_DR_AP_STATE_CHANGE, 997 SE_NO_HINT, pcihp_p->dip, KM_SLEEP); 998 pcihp_delete_occupant_props(pcihp_p->dip, dev); 999 } 1000 mutex_exit(&slotinfop->slot_mutex); 1001 1002 break; 1003 1004 case DEVCTL_AP_GETSTATE: 1005 { 1006 int mutex_held; 1007 1008 /* 1009 * return the state of Attachment Point. 1010 * 1011 * If the occupant is in UNCONFIGURED state then 1012 * we should get the receptacle state from the 1013 * HPC driver because the receptacle state 1014 * maintained in the nexus may not be accurate. 1015 */ 1016 1017 /* 1018 * check for valid request: 1019 * 1. It is a hotplug slot. 1020 */ 1021 slotinfop = &pcihp_p->slotinfo[pci_dev]; 1022 1023 /* try to acquire the slot mutex */ 1024 mutex_held = mutex_tryenter(&slotinfop->slot_mutex); 1025 1026 if (pci_dev >= PCI_MAX_DEVS || slotinfop->slot_hdl == NULL) { 1027 rv = ENXIO; 1028 if (mutex_held) { 1029 mutex_exit(&slotinfop->slot_mutex); 1030 } 1031 break; 1032 } 1033 1034 if (slotinfop->ostate == AP_OSTATE_UNCONFIGURED) { 1035 if (hpc_nexus_control(slotinfop->slot_hdl, 1036 HPC_CTRL_GET_SLOT_STATE, (caddr_t)&rstate) != 0) { 1037 rv = EIO; 1038 if (mutex_held) 1039 mutex_exit(&slotinfop->slot_mutex); 1040 break; 1041 } 1042 slotinfop->rstate = (ap_rstate_t)rstate; 1043 } 1044 1045 ap_state.ap_rstate = slotinfop->rstate; 1046 ap_state.ap_ostate = slotinfop->ostate; 1047 ap_state.ap_condition = slotinfop->condition; 1048 ap_state.ap_last_change = slotinfop->last_change; 1049 ap_state.ap_error_code = 0; /* XXX */ 1050 if (mutex_held) 1051 ap_state.ap_in_transition = 0; /* AP is not busy */ 1052 else 1053 ap_state.ap_in_transition = 1; /* AP is busy */ 1054 1055 if (mutex_held) 1056 mutex_exit(&slotinfop->slot_mutex); 1057 1058 /* copy the return-AP-state information to the user space */ 1059 if (ndi_dc_return_ap_state(&ap_state, dcp) != NDI_SUCCESS) 1060 rv = EFAULT; 1061 1062 break; 1063 1064 } 1065 case DEVCTL_AP_CONTROL: 1066 /* 1067 * HPC control functions: 1068 * HPC_CTRL_ENABLE_SLOT/HPC_CTRL_DISABLE_SLOT 1069 * Changes the state of the slot and preserves 1070 * the state across the reboot. 1071 * HPC_CTRL_ENABLE_AUTOCFG/HPC_CTRL_DISABLE_AUTOCFG 1072 * Enables or disables the auto configuration 1073 * of hot plugged occupant if the hardware 1074 * supports notification of the hot plug 1075 * events. 1076 * HPC_CTRL_GET_LED_STATE/HPC_CTRL_SET_LED_STATE 1077 * Controls the state of an LED. 1078 * HPC_CTRL_GET_SLOT_INFO 1079 * Get slot information data structure 1080 * (hpc_slot_info_t). 1081 * HPC_CTRL_GET_BOARD_TYPE 1082 * Get board type information (hpc_board_type_t). 1083 * HPC_CTRL_GET_CARD_INFO 1084 * Get card information (hpc_card_info_t). 1085 * 1086 * These control functions are used by the cfgadm plug-in 1087 * to implement "-x" and "-v" options. 1088 */ 1089 1090 /* copy user ioctl data first */ 1091 switch (ddi_model_convert_from(mode & FMODELS)) { 1092 case DDI_MODEL_ILP32: { 1093 struct hpc_control32_data hpc_ctrldata32; 1094 1095 if (copyin((void *)arg, (void *)&hpc_ctrldata32, 1096 sizeof (struct hpc_control32_data)) != 0) { 1097 rv = EFAULT; 1098 break; 1099 } 1100 hpc_ctrldata.cmd = hpc_ctrldata32.cmd; 1101 hpc_ctrldata.data = 1102 (void *)(intptr_t)hpc_ctrldata32.data; 1103 break; 1104 } 1105 case DDI_MODEL_NONE: 1106 if (copyin((void *)arg, (void *)&hpc_ctrldata, 1107 sizeof (struct hpc_control_data)) != 0) { 1108 rv = EFAULT; 1109 } 1110 break; 1111 default: 1112 rv = EFAULT; 1113 break; 1114 } 1115 if (rv == EFAULT) 1116 break; 1117 /* 1118 * check for valid request: 1119 * 1. It is a hotplug slot. 1120 */ 1121 slotinfop = &pcihp_p->slotinfo[pci_dev]; 1122 1123 mutex_enter(&slotinfop->slot_mutex); 1124 1125 if (pci_dev >= PCI_MAX_DEVS || slotinfop->slot_hdl == NULL) { 1126 rv = ENXIO; 1127 mutex_exit(&slotinfop->slot_mutex); 1128 break; 1129 } 1130 1131 switch (hpc_ctrldata.cmd) { 1132 1133 case HPC_CTRL_GET_LED_STATE: 1134 /* copy the led info from the user space */ 1135 if (copyin(hpc_ctrldata.data, (void *)&led_info, 1136 sizeof (hpc_led_info_t)) != 0) { 1137 rv = EFAULT; 1138 break; 1139 } 1140 1141 /* get the state of LED information */ 1142 if (hpc_nexus_control(slotinfop->slot_hdl, 1143 HPC_CTRL_GET_LED_STATE, (caddr_t)&led_info) != 0) { 1144 1145 if (rv != ENOTSUP) 1146 rv = EIO; 1147 1148 break; 1149 } 1150 1151 /* copy the led info to the user space */ 1152 if (copyout((void *)&led_info, hpc_ctrldata.data, 1153 sizeof (hpc_led_info_t)) != 0) { 1154 rv = EFAULT; 1155 break; 1156 } 1157 1158 break; 1159 1160 case HPC_CTRL_SET_LED_STATE: 1161 /* copy the led info from the user space */ 1162 if (copyin(hpc_ctrldata.data, (void *)&led_info, 1163 sizeof (hpc_led_info_t)) != 0) { 1164 rv = EFAULT; 1165 break; 1166 } 1167 1168 /* set the state of an LED */ 1169 rv = hpc_nexus_control(slotinfop->slot_hdl, 1170 HPC_CTRL_SET_LED_STATE, (caddr_t)&led_info); 1171 1172 /* 1173 * If the Hotswap Controller does not support 1174 * LED management (as you would find typically 1175 * in the cPCI industry), then we handle the 1176 * blue LED on/off/blink operations, just in 1177 * case it helps slot identification. 1178 */ 1179 if ((rv == HPC_ERR_NOTSUPPORTED) && 1180 (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI)) { 1181 if (led_info.led != HPC_ATTN_LED) 1182 break; 1183 1184 switch (led_info.state) { 1185 case HPC_LED_OFF: 1186 pcihp_hs_csr_op(pcihp_p, 1187 pci_dev, 1188 HPC_EVENT_SLOT_BLUE_LED_OFF); 1189 rv = 0; 1190 break; 1191 case HPC_LED_ON: 1192 /* 1193 * Please note that leaving 1194 * LED ON could be dangerous 1195 * as it means it is Ok to 1196 * remove the board, which 1197 * is not what we want to 1198 * convey. So it is upto the 1199 * user to take care of this 1200 * situation and usage. 1201 * 1202 * Normally, a Blink command 1203 * is more appropriate for 1204 * identifying a board. 1205 */ 1206 pcihp_hs_csr_op(pcihp_p, 1207 pci_dev, 1208 HPC_EVENT_SLOT_BLUE_LED_ON); 1209 rv = 0; 1210 break; 1211 case HPC_LED_BLINK: 1212 { 1213 int bl; 1214 1215 for (bl = 0; bl < 2; bl++) { 1216 pcihp_hs_csr_op(pcihp_p, 1217 pci_dev, 1218 HPC_EVENT_SLOT_BLUE_LED_ON); 1219 delay(pcihp_cpci_led_blink); 1220 pcihp_hs_csr_op(pcihp_p, 1221 pci_dev, 1222 HPC_EVENT_SLOT_BLUE_LED_OFF); 1223 delay(pcihp_cpci_led_blink); 1224 } 1225 rv = 0; 1226 break; 1227 } 1228 default: 1229 break; 1230 } 1231 } 1232 1233 if (rv == HPC_ERR_FAILED) 1234 rv = EIO; 1235 break; 1236 1237 case HPC_CTRL_ENABLE_SLOT: 1238 1239 /* 1240 * If slot already enabled, do not send a duplicate 1241 * control message to the HPC driver. 1242 */ 1243 if ((slotinfop->slot_flags & PCIHP_SLOT_DISABLED) == 0) 1244 break; 1245 1246 /* tell the HPC driver also */ 1247 if (hpc_nexus_control(slotinfop->slot_hdl, 1248 HPC_CTRL_ENABLE_SLOT, NULL) != HPC_SUCCESS) { 1249 rv = EIO; 1250 break; 1251 } 1252 1253 /* 1254 * Enable the slot for hotplug operations. 1255 */ 1256 slotinfop->slot_flags &= ~PCIHP_SLOT_DISABLED; 1257 1258 slotinfop->condition = AP_COND_UNKNOWN; 1259 1260 /* XXX need to preserve this state across reboot? */ 1261 1262 break; 1263 1264 case HPC_CTRL_DISABLE_SLOT: 1265 1266 /* Do not disable if occupant configured */ 1267 if (slotinfop->ostate == AP_OSTATE_CONFIGURED) { 1268 rv = EAGAIN; 1269 break; 1270 } 1271 1272 /* tell the HPC driver also */ 1273 if (hpc_nexus_control(slotinfop->slot_hdl, 1274 HPC_CTRL_DISABLE_SLOT, NULL) != HPC_SUCCESS) { 1275 rv = EIO; 1276 break; 1277 } 1278 1279 /* 1280 * Disable the slot for hotplug operations. 1281 */ 1282 slotinfop->slot_flags |= PCIHP_SLOT_DISABLED; 1283 1284 slotinfop->condition = AP_COND_UNUSABLE; 1285 1286 /* XXX need to preserve this state across reboot? */ 1287 1288 break; 1289 1290 case HPC_CTRL_ENABLE_AUTOCFG: 1291 /* 1292 * Enable auto configuration on this slot. 1293 */ 1294 slotinfop->slot_flags |= PCIHP_SLOT_AUTO_CFG_EN; 1295 1296 /* tell the HPC driver also */ 1297 (void) hpc_nexus_control(slotinfop->slot_hdl, 1298 HPC_CTRL_ENABLE_AUTOCFG, NULL); 1299 1300 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) 1301 pcihp_hs_csr_op(pcihp_p, pci_dev, 1302 HPC_EVENT_ENABLE_ENUM); 1303 break; 1304 1305 case HPC_CTRL_DISABLE_AUTOCFG: 1306 /* 1307 * Disable auto configuration on this slot. 1308 */ 1309 slotinfop->slot_flags &= ~PCIHP_SLOT_AUTO_CFG_EN; 1310 1311 /* tell the HPC driver also */ 1312 (void) hpc_nexus_control(slotinfop->slot_hdl, 1313 HPC_CTRL_DISABLE_AUTOCFG, NULL); 1314 1315 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) 1316 pcihp_hs_csr_op(pcihp_p, pci_dev, 1317 HPC_EVENT_DISABLE_ENUM); 1318 break; 1319 1320 case HPC_CTRL_GET_BOARD_TYPE: 1321 { 1322 hpc_board_type_t board_type; 1323 1324 /* 1325 * Get board type data structure, hpc_board_type_t. 1326 */ 1327 board_type = pcihp_get_board_type(slotinfop); 1328 if (board_type == -1) { 1329 rv = ENXIO; 1330 break; 1331 } 1332 1333 /* copy the board type info to the user space */ 1334 if (copyout((void *)&board_type, hpc_ctrldata.data, 1335 sizeof (hpc_board_type_t)) != 0) { 1336 rv = ENXIO; 1337 break; 1338 } 1339 1340 break; 1341 } 1342 1343 case HPC_CTRL_GET_SLOT_INFO: 1344 { 1345 hpc_slot_info_t slot_info; 1346 1347 /* 1348 * Get slot information structure, hpc_slot_info_t. 1349 */ 1350 slot_info.version = HPC_SLOT_INFO_VERSION; 1351 slot_info.slot_type = slotinfop->slot_type; 1352 slot_info.pci_slot_capabilities = 1353 slotinfop->slot_capabilities; 1354 slot_info.pci_dev_num = (uint16_t)pci_dev; 1355 (void) strcpy(slot_info.pci_slot_name, slotinfop->name); 1356 1357 /* copy the slot info structure to the user space */ 1358 if (copyout((void *)&slot_info, hpc_ctrldata.data, 1359 sizeof (hpc_slot_info_t)) != 0) { 1360 rv = EFAULT; 1361 break; 1362 } 1363 1364 break; 1365 } 1366 1367 case HPC_CTRL_GET_CARD_INFO: 1368 { 1369 hpc_card_info_t card_info; 1370 ddi_acc_handle_t handle; 1371 dev_info_t *cdip; 1372 1373 /* 1374 * Get card information structure, hpc_card_info_t. 1375 */ 1376 1377 /* verify that the card is configured */ 1378 if ((slotinfop->ostate != AP_OSTATE_CONFIGURED) || 1379 ((cdip = pcihp_devi_find(self, 1380 pci_dev, 0)) == NULL)) { 1381 /* 1382 * either the card is not present or 1383 * it is not configured. 1384 */ 1385 rv = ENXIO; 1386 break; 1387 } 1388 1389 /* 1390 * If declared failed, don't allow Config operations. 1391 * Otherwise, if good or failing, it is assumed Ok 1392 * to get config data. 1393 */ 1394 if (slotinfop->condition == AP_COND_FAILED) { 1395 rv = EIO; 1396 break; 1397 } 1398 1399 /* get the information from the PCI config header */ 1400 /* for the function 0. */ 1401 if (pci_config_setup(cdip, &handle) != DDI_SUCCESS) { 1402 rv = EIO; 1403 break; 1404 } 1405 card_info.prog_class = pci_config_get8(handle, 1406 PCI_CONF_PROGCLASS); 1407 card_info.base_class = pci_config_get8(handle, 1408 PCI_CONF_BASCLASS); 1409 card_info.sub_class = pci_config_get8(handle, 1410 PCI_CONF_SUBCLASS); 1411 card_info.header_type = pci_config_get8(handle, 1412 PCI_CONF_HEADER); 1413 pci_config_teardown(&handle); 1414 1415 /* copy the card info structure to the user space */ 1416 if (copyout((void *)&card_info, hpc_ctrldata.data, 1417 sizeof (hpc_card_info_t)) != 0) { 1418 rv = EFAULT; 1419 break; 1420 } 1421 1422 break; 1423 } 1424 1425 default: 1426 rv = EINVAL; 1427 break; 1428 } 1429 1430 mutex_exit(&slotinfop->slot_mutex); 1431 1432 break; 1433 1434 default: 1435 rv = ENOTTY; 1436 } 1437 1438 if (cmd != DEVCTL_AP_CONTROL) 1439 ndi_dc_freehdl(dcp); 1440 1441 (void) pcihp_get_soft_state(self, state_unlocking, &rval); 1442 1443 return (rv); 1444 } 1445 1446 /* 1447 * ************************************** 1448 * CONFIGURE the occupant in the slot. 1449 * ************************************** 1450 */ 1451 static int 1452 pcihp_configure_ap(pcihp_t *pcihp_p, int pci_dev) 1453 { 1454 dev_info_t *self = pcihp_p->dip; 1455 int rv = HPC_SUCCESS; 1456 struct pcihp_slotinfo *slotinfop; 1457 hpc_slot_state_t rstate; 1458 struct pcihp_config_ctrl ctrl; 1459 time_t time; 1460 1461 /* 1462 * check for valid request: 1463 * 1. It is a hotplug slot. 1464 * 2. The receptacle is in the CONNECTED state. 1465 */ 1466 slotinfop = &pcihp_p->slotinfo[pci_dev]; 1467 1468 1469 1470 if ((pci_dev >= PCI_MAX_DEVS) || (slotinfop->slot_hdl == NULL) || 1471 (slotinfop->slot_flags & PCIHP_SLOT_DISABLED)) { 1472 1473 return (ENXIO); 1474 } 1475 1476 /* 1477 * If the occupant is already in (partially?) configured 1478 * state then call the ndi_devi_online() on the device 1479 * subtree(s) for this attachment point. 1480 */ 1481 1482 if (slotinfop->ostate == AP_OSTATE_CONFIGURED) { 1483 ctrl.flags = PCIHP_CFG_CONTINUE; 1484 ctrl.rv = NDI_SUCCESS; 1485 ctrl.dip = NULL; 1486 ctrl.pci_dev = pci_dev; 1487 ctrl.op = PCIHP_ONLINE; 1488 1489 ndi_devi_enter(self); 1490 ddi_walk_devs(ddi_get_child(self), pcihp_configure, 1491 (void *)&ctrl); 1492 ndi_devi_exit(self); 1493 1494 if (ctrl.rv != NDI_SUCCESS) { 1495 /* 1496 * one or more of the devices are not 1497 * onlined. How is this to be reported? 1498 */ 1499 cmn_err(CE_WARN, 1500 "pcihp (%s%d): failed to attach one or" 1501 " more drivers for the card in the slot %s", 1502 ddi_driver_name(self), ddi_get_instance(self), 1503 slotinfop->name); 1504 /* rv = EFAULT; */ 1505 } 1506 /* tell HPC driver that the occupant is configured */ 1507 (void) hpc_nexus_control(slotinfop->slot_hdl, 1508 HPC_CTRL_DEV_CONFIGURED, NULL); 1509 1510 if (drv_getparm(TIME, (void *)&time) != DDI_SUCCESS) 1511 slotinfop->last_change = (time_t)-1; 1512 else 1513 slotinfop->last_change = (time32_t)time; 1514 1515 1516 return (rv); 1517 } 1518 1519 /* 1520 * Occupant is in the UNCONFIGURED state. 1521 */ 1522 1523 /* Check if the receptacle is in the CONNECTED state. */ 1524 if (hpc_nexus_control(slotinfop->slot_hdl, 1525 HPC_CTRL_GET_SLOT_STATE, (caddr_t)&rstate) != 0) { 1526 1527 return (ENXIO); 1528 } 1529 1530 if (rstate == HPC_SLOT_EMPTY) { 1531 /* error. slot is empty */ 1532 1533 return (ENXIO); 1534 } 1535 1536 if (rstate != HPC_SLOT_CONNECTED) { 1537 /* error. either the slot is empty or connect failed */ 1538 1539 return (ENXIO); 1540 } 1541 1542 slotinfop->rstate = AP_RSTATE_CONNECTED; /* record rstate */ 1543 1544 /* Turn INS and LED off, and start configuration. */ 1545 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 1546 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_SLOT_CONFIGURE); 1547 if (pcihp_cpci_blue_led) 1548 pcihp_hs_csr_op(pcihp_p, pci_dev, 1549 HPC_EVENT_SLOT_BLUE_LED_OFF); 1550 slotinfop->slot_flags &= ~PCIHP_SLOT_ENUM_INS_PENDING; 1551 } 1552 1553 (void) hpc_nexus_control(slotinfop->slot_hdl, 1554 HPC_CTRL_DEV_CONFIG_START, NULL); 1555 1556 /* 1557 * Call the configurator to configure the card. 1558 */ 1559 if (pcicfg_configure(self, pci_dev, PCICFG_ALL_FUNC, 0) 1560 != PCICFG_SUCCESS) { 1561 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 1562 if (pcihp_cpci_blue_led) 1563 pcihp_hs_csr_op(pcihp_p, pci_dev, 1564 HPC_EVENT_SLOT_BLUE_LED_ON); 1565 pcihp_hs_csr_op(pcihp_p, pci_dev, 1566 HPC_EVENT_SLOT_UNCONFIGURE); 1567 } 1568 /* tell HPC driver occupant configure Error */ 1569 (void) hpc_nexus_control(slotinfop->slot_hdl, 1570 HPC_CTRL_DEV_CONFIG_FAILURE, NULL); 1571 1572 return (EIO); 1573 } 1574 1575 /* record the occupant state as CONFIGURED */ 1576 slotinfop->ostate = AP_OSTATE_CONFIGURED; 1577 slotinfop->condition = AP_COND_OK; 1578 1579 /* now, online all the devices in the AP */ 1580 ctrl.flags = PCIHP_CFG_CONTINUE; 1581 ctrl.rv = NDI_SUCCESS; 1582 ctrl.dip = NULL; 1583 ctrl.pci_dev = pci_dev; 1584 ctrl.op = PCIHP_ONLINE; 1585 1586 ndi_devi_enter(self); 1587 ddi_walk_devs(ddi_get_child(self), pcihp_configure, (void *)&ctrl); 1588 ndi_devi_exit(self); 1589 1590 if (ctrl.rv != NDI_SUCCESS) { 1591 /* 1592 * one or more of the devices are not 1593 * ONLINE'd. How is this to be 1594 * reported? 1595 */ 1596 cmn_err(CE_WARN, 1597 "pcihp (%s%d): failed to attach one or" 1598 " more drivers for the card in the slot %s", 1599 ddi_driver_name(pcihp_p->dip), 1600 ddi_get_instance(pcihp_p->dip), 1601 slotinfop->name); 1602 /* rv = EFAULT; */ 1603 } 1604 /* store HS_CSR location. No events, jut a read operation. */ 1605 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) 1606 pcihp_hs_csr_op(pcihp_p, pci_dev, -1); 1607 1608 /* tell HPC driver that the occupant is configured */ 1609 (void) hpc_nexus_control(slotinfop->slot_hdl, 1610 HPC_CTRL_DEV_CONFIGURED, NULL); 1611 1612 1613 return (rv); 1614 } 1615 1616 /* 1617 * ************************************** 1618 * UNCONFIGURE the occupant in the slot. 1619 * ************************************** 1620 */ 1621 static int 1622 pcihp_unconfigure_ap(pcihp_t *pcihp_p, int pci_dev) 1623 { 1624 dev_info_t *self = pcihp_p->dip; 1625 int rv = HPC_SUCCESS; 1626 struct pcihp_slotinfo *slotinfop; 1627 struct pcihp_config_ctrl ctrl; 1628 time_t time; 1629 1630 /* 1631 * check for valid request: 1632 * 1. It is a hotplug slot. 1633 * 2. The occupant is in the CONFIGURED state. 1634 */ 1635 slotinfop = &pcihp_p->slotinfo[pci_dev]; 1636 1637 1638 1639 if ((pci_dev >= PCI_MAX_DEVS) || (slotinfop->slot_hdl == NULL) || 1640 (slotinfop->slot_flags & PCIHP_SLOT_DISABLED)) { 1641 1642 return (ENXIO); 1643 } 1644 /* 1645 * The following may not need to be there, as we should 1646 * support unconfiguring of boards and free resources 1647 * even when the board is not hotswappable. But this is 1648 * the only way, we may be able to tell the system 1649 * administrator that it is not a hotswap board since 1650 * disconnect operation is never called. 1651 * This way we help the system administrator from not 1652 * accidentally removing a non hotswap board and 1653 * possibly destroying it. May be this behavior can 1654 * be a default, and can be enabled or disabled via 1655 * a global flag. 1656 */ 1657 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 1658 if (slotinfop->slot_flags & PCIHP_SLOT_DEV_NON_HOTPLUG) { 1659 /* Operation unsupported if no HS board/slot */ 1660 return (ENOTSUP); 1661 } 1662 } 1663 1664 /* 1665 * If the occupant is in the CONFIGURED state then 1666 * call the configurator to unconfigure the slot. 1667 */ 1668 if (slotinfop->ostate == AP_OSTATE_CONFIGURED) { 1669 1670 /* 1671 * since potential state change is imminent mask 1672 * enum events to prevent the slot from being re-configured 1673 */ 1674 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_DISABLE_ENUM); 1675 1676 /* 1677 * Detach all the drivers for the devices in the 1678 * slot. Call pcihp_configure() to do this. 1679 */ 1680 ctrl.flags = 0; 1681 ctrl.rv = NDI_SUCCESS; 1682 ctrl.dip = NULL; 1683 ctrl.pci_dev = pci_dev; 1684 ctrl.op = PCIHP_OFFLINE; 1685 1686 (void) devfs_clean(self, NULL, DV_CLEAN_FORCE); 1687 ndi_devi_enter(self); 1688 ddi_walk_devs(ddi_get_child(self), pcihp_configure, 1689 (void *)&ctrl); 1690 ndi_devi_exit(self); 1691 1692 if (ctrl.rv != NDI_SUCCESS) { 1693 /* 1694 * Failed to detach one or more drivers 1695 * Restore the state of drivers which 1696 * are offlined during this operation. 1697 */ 1698 ctrl.flags = 0; 1699 ctrl.rv = NDI_SUCCESS; 1700 ctrl.dip = NULL; 1701 ctrl.pci_dev = pci_dev; 1702 ctrl.op = PCIHP_ONLINE; 1703 1704 ndi_devi_enter(self); 1705 ddi_walk_devs(ddi_get_child(self), 1706 pcihp_configure, (void *)&ctrl); 1707 ndi_devi_exit(self); 1708 1709 /* tell HPC driver that the occupant is Busy */ 1710 (void) hpc_nexus_control(slotinfop->slot_hdl, 1711 HPC_CTRL_DEV_UNCONFIG_FAILURE, NULL); 1712 1713 rv = EBUSY; 1714 } else { 1715 (void) hpc_nexus_control(slotinfop->slot_hdl, 1716 HPC_CTRL_DEV_UNCONFIG_START, NULL); 1717 1718 if (pcicfg_unconfigure(self, pci_dev, 1719 PCICFG_ALL_FUNC, 0) == PCICFG_SUCCESS) { 1720 /* 1721 * Now that resources are freed, 1722 * clear EXT and Turn LED ON. 1723 */ 1724 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 1725 pcihp_hs_csr_op(pcihp_p, pci_dev, 1726 HPC_EVENT_SLOT_UNCONFIGURE); 1727 if (pcihp_cpci_blue_led) 1728 pcihp_hs_csr_op(pcihp_p, 1729 pci_dev, 1730 HPC_EVENT_SLOT_BLUE_LED_ON); 1731 slotinfop->hs_csr_location = 0; 1732 slotinfop->slot_flags &= 1733 ~(PCIHP_SLOT_DEV_NON_HOTPLUG| 1734 PCIHP_SLOT_ENUM_EXT_PENDING); 1735 } 1736 slotinfop->ostate = AP_OSTATE_UNCONFIGURED; 1737 slotinfop->condition = AP_COND_UNKNOWN; 1738 /* 1739 * send the notification of state change 1740 * to the HPC driver. 1741 */ 1742 (void) hpc_nexus_control(slotinfop->slot_hdl, 1743 HPC_CTRL_DEV_UNCONFIGURED, 1744 NULL); 1745 } else { 1746 /* tell HPC driver occupant unconfigure Error */ 1747 (void) hpc_nexus_control(slotinfop->slot_hdl, 1748 HPC_CTRL_DEV_UNCONFIG_FAILURE, NULL); 1749 1750 rv = EIO; 1751 } 1752 } 1753 } 1754 1755 if (drv_getparm(TIME, (void *)&time) != DDI_SUCCESS) 1756 slotinfop->last_change = (time_t)-1; 1757 else 1758 slotinfop->last_change = (time32_t)time; 1759 1760 1761 1762 /* unmask enum events again */ 1763 if ((slotinfop->slot_flags & PCIHP_SLOT_AUTO_CFG_EN) == 0) { 1764 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_ENABLE_ENUM); 1765 } 1766 1767 return (rv); 1768 } 1769 1770 /* 1771 * Accessor function to return pointer to the pci hotplug 1772 * cb_ops structure. 1773 */ 1774 struct cb_ops * 1775 pcihp_get_cb_ops() 1776 { 1777 return (&pcihp_cb_ops); 1778 } 1779 1780 /* 1781 * Setup function to initialize hot plug feature. Returns DDI_SUCCESS 1782 * for successful initialization, otherwise it returns DDI_FAILURE. 1783 * 1784 * It is assumed that this this function is called from the attach() 1785 * entry point of the PCI nexus driver. 1786 */ 1787 1788 int 1789 pcihp_init(dev_info_t *dip) 1790 { 1791 pcihp_t *pcihp_p; 1792 int i; 1793 caddr_t enum_data; 1794 int enum_size; 1795 int rv; 1796 1797 mutex_enter(&pcihp_open_mutex); 1798 1799 /* 1800 * Make sure that it is not already initialized. 1801 */ 1802 if (pcihp_get_soft_state(dip, PCIHP_DR_NOOP, &rv) != NULL) { 1803 cmn_err(CE_WARN, "%s%d: pcihp instance already initialized!", 1804 ddi_driver_name(dip), ddi_get_instance(dip)); 1805 goto cleanup; 1806 } 1807 1808 /* 1809 * Initialize soft state structure for the bus instance. 1810 */ 1811 if ((pcihp_p = pcihp_create_soft_state(dip)) == NULL) { 1812 cmn_err(CE_WARN, "%s%d: can't allocate pcihp structure", 1813 ddi_driver_name(dip), ddi_get_instance(dip)); 1814 goto cleanup; 1815 } 1816 1817 pcihp_p->soft_state = PCIHP_SOFT_STATE_CLOSED; 1818 /* XXX if bus is running at 66Mhz then set PCI_BUS_66MHZ bit */ 1819 pcihp_p->bus_flags = 0; /* XXX FIX IT */ 1820 1821 /* 1822 * If a platform wishes to implement Radial ENUM# routing 1823 * a property "enum-impl" must be presented to us with a 1824 * string value "radial". 1825 * This helps us not go for polling operation (default) 1826 * during a ENUM# event. 1827 */ 1828 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, "enum-impl", 1829 (caddr_t)&enum_data, &enum_size) == DDI_PROP_SUCCESS) { 1830 if (strcmp(enum_data, "radial") == 0) { 1831 pcihp_p->bus_flags |= PCIHP_BUS_ENUM_RADIAL; 1832 } 1833 kmem_free(enum_data, enum_size); 1834 } 1835 1836 for (i = 0; i < PCI_MAX_DEVS; i++) { 1837 /* initialize slot mutex */ 1838 mutex_init(&pcihp_p->slotinfo[i].slot_mutex, NULL, 1839 MUTEX_DRIVER, NULL); 1840 } 1841 1842 /* 1843 * register the bus instance with the HPS framework. 1844 */ 1845 if (hpc_nexus_register_bus(dip, pcihp_new_slot_state, 0) != 0) { 1846 cmn_err(CE_WARN, "%s%d: failed to register the bus with HPS", 1847 ddi_driver_name(dip), ddi_get_instance(dip)); 1848 goto cleanup1; 1849 } 1850 1851 /* 1852 * Create the "devctl" minor for hot plug support. The minor 1853 * number for "devctl" node is in the same format as the AP 1854 * minor nodes. 1855 */ 1856 if (ddi_create_minor_node(dip, "devctl", S_IFCHR, 1857 PCIHP_AP_MINOR_NUM(ddi_get_instance(dip), PCIHP_DEVCTL_MINOR), 1858 DDI_NT_NEXUS, 0) != DDI_SUCCESS) 1859 goto cleanup2; 1860 1861 /* 1862 * Setup resource maps for this bus node. (Note: This can 1863 * be done from the attach(9E) of the nexus itself.) 1864 */ 1865 (void) pci_resource_setup(dip); 1866 1867 pcihp_p->bus_state = PCIHP_BUS_CONFIGURED; 1868 1869 mutex_exit(&pcihp_open_mutex); 1870 1871 return (DDI_SUCCESS); 1872 1873 cleanup2: 1874 (void) hpc_nexus_unregister_bus(dip); 1875 cleanup1: 1876 for (i = 0; i < PCI_MAX_DEVS; i++) 1877 mutex_destroy(&pcihp_p->slotinfo[i].slot_mutex); 1878 pcihp_destroy_soft_state(dip); 1879 cleanup: 1880 mutex_exit(&pcihp_open_mutex); 1881 return (DDI_FAILURE); 1882 } 1883 1884 /* 1885 * pcihp_uninit() 1886 * 1887 * The bus instance is going away, cleanup any data associated with 1888 * the management of hot plug slots. It is assumed that this function 1889 * is called from detach() routine of the PCI nexus driver. Also, 1890 * it is assumed that no devices on the bus are in the configured state. 1891 */ 1892 int 1893 pcihp_uninit(dev_info_t *dip) 1894 { 1895 pcihp_t *pcihp_p; 1896 int i, j; 1897 int rv; 1898 1899 mutex_enter(&pcihp_open_mutex); 1900 /* get a pointer to the soft state structure */ 1901 pcihp_p = pcihp_get_soft_state(dip, PCIHP_DR_BUS_UNCONFIGURE, &rv); 1902 ASSERT(pcihp_p != NULL); 1903 1904 /* slot mutexes should prevent any configure/unconfigure access */ 1905 for (i = 0; i < PCI_MAX_DEVS; i++) { 1906 if (!mutex_tryenter(&pcihp_p->slotinfo[i].slot_mutex)) { 1907 for (j = 0; j < i; j++) { 1908 mutex_exit(&pcihp_p->slotinfo[j].slot_mutex); 1909 } 1910 mutex_exit(&pcihp_open_mutex); 1911 return (DDI_FAILURE); 1912 } 1913 } 1914 1915 if ((pcihp_p->soft_state != PCIHP_SOFT_STATE_CLOSED) || 1916 (rv == PCIHP_FAILURE)) { 1917 cmn_err(CE_WARN, "%s%d: pcihp instance is busy", 1918 ddi_driver_name(dip), ddi_get_instance(dip)); 1919 for (i = 0; i < PCI_MAX_DEVS; i++) { 1920 mutex_exit(&pcihp_p->slotinfo[i].slot_mutex); 1921 } 1922 mutex_exit(&pcihp_open_mutex); 1923 return (DDI_FAILURE); 1924 } 1925 1926 /* 1927 * Unregister the bus with the HPS. 1928 * 1929 * (Note: It is assumed that the HPS framework uninstalls 1930 * event handlers for all the hot plug slots on this bus.) 1931 */ 1932 (void) hpc_nexus_unregister_bus(dip); 1933 1934 /* Free up any kmem_alloc'd memory for slot info table. */ 1935 for (i = 0; i < PCI_MAX_DEVS; i++) { 1936 /* free up slot name strings */ 1937 if (pcihp_p->slotinfo[i].name != NULL) 1938 kmem_free(pcihp_p->slotinfo[i].name, 1939 strlen(pcihp_p->slotinfo[i].name) + 1); 1940 } 1941 1942 /* destroy slot mutexes */ 1943 for (i = 0; i < PCI_MAX_DEVS; i++) 1944 mutex_destroy(&pcihp_p->slotinfo[i].slot_mutex); 1945 1946 ddi_remove_minor_node(dip, NULL); 1947 1948 /* free up the soft state structure */ 1949 pcihp_destroy_soft_state(dip); 1950 1951 /* 1952 * Destroy resource maps for this bus node. (Note: This can 1953 * be done from the detach(9E) of the nexus itself.) 1954 */ 1955 (void) pci_resource_destroy(dip); 1956 1957 mutex_exit(&pcihp_open_mutex); 1958 1959 return (DDI_SUCCESS); 1960 } 1961 1962 /* 1963 * pcihp_new_slot_state() 1964 * 1965 * This function is called by the HPS when it finds a hot plug 1966 * slot is added or being removed from the hot plug framework. 1967 * It returns 0 for success and HPC_ERR_FAILED for errors. 1968 */ 1969 static int 1970 pcihp_new_slot_state(dev_info_t *dip, hpc_slot_t hdl, 1971 hpc_slot_info_t *slot_info, int slot_state) 1972 { 1973 pcihp_t *pcihp_p; 1974 struct pcihp_slotinfo *slotinfop; 1975 int pci_dev; 1976 minor_t ap_minor; 1977 major_t ap_major; 1978 int rv = 0; 1979 time_t time; 1980 int auto_enable = 1; 1981 int rval; 1982 1983 /* get a pointer to the soft state structure */ 1984 pcihp_p = pcihp_get_soft_state(dip, PCIHP_DR_SLOT_ENTER, &rval); 1985 ASSERT(pcihp_p != NULL); 1986 1987 if (rval == PCIHP_FAILURE) { 1988 PCIHP_DEBUG((CE_WARN, "pcihp instance is unconfigured" 1989 " while slot activity is requested\n")); 1990 return (HPC_ERR_FAILED); 1991 } 1992 1993 pci_dev = slot_info->pci_dev_num; 1994 slotinfop = &pcihp_p->slotinfo[pci_dev]; 1995 1996 mutex_enter(&slotinfop->slot_mutex); 1997 1998 switch (slot_state) { 1999 2000 case HPC_SLOT_ONLINE: 2001 2002 /* 2003 * Make sure the slot is not already ONLINE (paranoia?). 2004 * (Note: Should this be simply an ASSERTION?) 2005 */ 2006 if (slotinfop->slot_hdl != NULL) { 2007 PCIHP_DEBUG((CE_WARN, 2008 "pcihp (%s%d): pci slot (dev %x) already ONLINE!!", 2009 ddi_driver_name(dip), ddi_get_instance(dip), 2010 pci_dev)); 2011 rv = HPC_ERR_FAILED; 2012 break; 2013 } 2014 2015 /* 2016 * Add the hot plug slot to the bus. 2017 */ 2018 2019 /* create the AP minor node */ 2020 ap_minor = PCIHP_AP_MINOR_NUM(ddi_get_instance(dip), pci_dev); 2021 if (ddi_create_minor_node(dip, slot_info->pci_slot_name, 2022 S_IFCHR, ap_minor, 2023 DDI_NT_PCI_ATTACHMENT_POINT, 0) == DDI_FAILURE) { 2024 cmn_err(CE_WARN, 2025 "pcihp (%s%d): ddi_create_minor_node failed" 2026 " for pci dev %x", ddi_driver_name(dip), 2027 ddi_get_instance(dip), pci_dev); 2028 rv = HPC_ERR_FAILED; 2029 break; 2030 } 2031 2032 /* save the slot handle */ 2033 slotinfop->slot_hdl = hdl; 2034 2035 /* setup event handler for all hardware events on the slot */ 2036 ap_major = ddi_driver_major(dip); 2037 if (hpc_install_event_handler(hdl, -1, pcihp_event_handler, 2038 (caddr_t)makedevice(ap_major, ap_minor)) != 0) { 2039 cmn_err(CE_WARN, 2040 "pcihp (%s%d): install event handler failed" 2041 " for pci dev %x", ddi_driver_name(dip), 2042 ddi_get_instance(dip), pci_dev); 2043 rv = HPC_ERR_FAILED; 2044 break; 2045 } 2046 slotinfop->event_mask = (uint32_t)0xFFFFFFFF; 2047 2048 pcihp_create_occupant_props(dip, makedevice(ap_major, 2049 ap_minor), pci_dev); 2050 2051 /* set default auto configuration enabled flag for this slot */ 2052 slotinfop->slot_flags = pcihp_autocfg_enabled; 2053 2054 /* copy the slot information */ 2055 slotinfop->name = 2056 kmem_alloc(strlen(slot_info->pci_slot_name) + 1, KM_SLEEP); 2057 (void) strcpy(slotinfop->name, slot_info->pci_slot_name); 2058 slotinfop->slot_type = slot_info->slot_type; 2059 slotinfop->hs_csr_location = 0; 2060 slotinfop->slot_capabilities = slot_info->pci_slot_capabilities; 2061 if (slot_info->slot_flags & HPC_SLOT_NO_AUTO_ENABLE) 2062 auto_enable = 0; 2063 2064 if (slot_info->slot_flags & HPC_SLOT_CREATE_DEVLINK) { 2065 pci_devlink_flags |= (1 << pci_dev); 2066 (void) ddi_prop_update_int(DDI_DEV_T_NONE, 2067 dip, "ap-names", pci_devlink_flags); 2068 } 2069 2070 PCIHP_DEBUG((CE_NOTE, 2071 "pcihp (%s%d): pci slot (dev %x) ONLINE\n", 2072 ddi_driver_name(dip), ddi_get_instance(dip), pci_dev)); 2073 2074 /* 2075 * The slot may have an occupant that was configured 2076 * at boot time. If we find a devinfo node in the tree 2077 * for this slot (i.e pci device number) then we 2078 * record the occupant state as CONFIGURED. 2079 */ 2080 if (pcihp_devi_find(dip, pci_dev, 0) != NULL) { 2081 /* we have a configured occupant */ 2082 slotinfop->ostate = AP_OSTATE_CONFIGURED; 2083 slotinfop->rstate = AP_RSTATE_CONNECTED; 2084 slotinfop->condition = AP_COND_OK; 2085 2086 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2087 /* this will set slot flags too. */ 2088 (void) pcihp_get_board_type(slotinfop); 2089 pcihp_hs_csr_op(pcihp_p, pci_dev, 2090 HPC_EVENT_SLOT_CONFIGURE); 2091 if (pcihp_cpci_blue_led) 2092 pcihp_hs_csr_op(pcihp_p, pci_dev, 2093 HPC_EVENT_SLOT_BLUE_LED_OFF); 2094 /* ENUM# enabled by default for cPCI devices */ 2095 slotinfop->slot_flags |= PCIHP_SLOT_AUTO_CFG_EN; 2096 slotinfop->slot_flags &= 2097 ~PCIHP_SLOT_ENUM_INS_PENDING; 2098 } 2099 2100 /* tell HPC driver that the occupant is configured */ 2101 (void) hpc_nexus_control(slotinfop->slot_hdl, 2102 HPC_CTRL_DEV_CONFIGURED, NULL); 2103 2104 /* 2105 * Tell sysevent listeners that slot has 2106 * changed state. At minimum, this is useful 2107 * when a PCI-E Chassis (containing Occupants) is 2108 * hotplugged. In this case, the following will 2109 * announce that the Occupant in the Receptacle 2110 * in the Chassis had a state-change. 2111 */ 2112 pcihp_gen_sysevent(slotinfop->name, 2113 PCIHP_DR_AP_STATE_CHANGE, SE_NO_HINT, 2114 pcihp_p->dip, KM_SLEEP); 2115 } else { 2116 struct pcihp_config_ctrl ctrl; 2117 2118 slotinfop->ostate = AP_OSTATE_UNCONFIGURED; 2119 slotinfop->rstate = AP_RSTATE_EMPTY; 2120 slotinfop->condition = AP_COND_UNKNOWN; 2121 2122 if (!auto_enable) { /* no further action */ 2123 break; 2124 } 2125 2126 /* 2127 * We enable power to the slot and try to 2128 * configure if there is any card present. 2129 * 2130 * Note: This case is possible if the BIOS or 2131 * firmware doesn't enable the slots during 2132 * soft reboot. 2133 */ 2134 if (hpc_nexus_connect(slotinfop->slot_hdl, 2135 NULL, 0) != HPC_SUCCESS) 2136 break; 2137 2138 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2139 pcihp_hs_csr_op(pcihp_p, pci_dev, 2140 HPC_EVENT_SLOT_CONFIGURE); 2141 if (pcihp_cpci_blue_led) 2142 pcihp_hs_csr_op(pcihp_p, pci_dev, 2143 HPC_EVENT_SLOT_BLUE_LED_OFF); 2144 slotinfop->slot_flags |= PCIHP_SLOT_AUTO_CFG_EN; 2145 slotinfop->slot_flags &= 2146 ~PCIHP_SLOT_ENUM_INS_PENDING; 2147 } 2148 2149 (void) hpc_nexus_control(slotinfop->slot_hdl, 2150 HPC_CTRL_DEV_CONFIG_START, NULL); 2151 2152 /* 2153 * Call the configurator to configure the card. 2154 */ 2155 if (pcicfg_configure(dip, pci_dev, PCICFG_ALL_FUNC, 0) 2156 != PCICFG_SUCCESS) { 2157 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2158 if (pcihp_cpci_blue_led) 2159 pcihp_hs_csr_op(pcihp_p, 2160 pci_dev, 2161 HPC_EVENT_SLOT_BLUE_LED_ON); 2162 pcihp_hs_csr_op(pcihp_p, pci_dev, 2163 HPC_EVENT_SLOT_UNCONFIGURE); 2164 } 2165 2166 /* tell HPC driver occupant configure Error */ 2167 (void) hpc_nexus_control(slotinfop->slot_hdl, 2168 HPC_CTRL_DEV_CONFIG_FAILURE, NULL); 2169 2170 /* 2171 * call HPC driver to turn off the power for 2172 * the slot. 2173 */ 2174 (void) hpc_nexus_disconnect(slotinfop->slot_hdl, 2175 NULL, 0); 2176 } else { 2177 /* record the occupant state as CONFIGURED */ 2178 slotinfop->ostate = AP_OSTATE_CONFIGURED; 2179 slotinfop->rstate = AP_RSTATE_CONNECTED; 2180 slotinfop->condition = AP_COND_OK; 2181 2182 /* now, online all the devices in the AP */ 2183 ctrl.flags = PCIHP_CFG_CONTINUE; 2184 ctrl.rv = NDI_SUCCESS; 2185 ctrl.dip = NULL; 2186 ctrl.pci_dev = pci_dev; 2187 ctrl.op = PCIHP_ONLINE; 2188 /* 2189 * the following sets slot_flags and 2190 * hs_csr_location too. 2191 */ 2192 (void) pcihp_get_board_type(slotinfop); 2193 2194 ndi_devi_enter(dip); 2195 ddi_walk_devs(ddi_get_child(dip), 2196 pcihp_configure, (void *)&ctrl); 2197 ndi_devi_exit(dip); 2198 2199 if (ctrl.rv != NDI_SUCCESS) { 2200 /* 2201 * one or more of the devices are not 2202 * ONLINE'd. How is this to be 2203 * reported? 2204 */ 2205 cmn_err(CE_WARN, 2206 "pcihp (%s%d): failed to attach" 2207 " one or more drivers for the" 2208 " card in the slot %s", 2209 ddi_driver_name(dip), 2210 ddi_get_instance(dip), 2211 slotinfop->name); 2212 } 2213 2214 /* tell HPC driver the Occupant is Configured */ 2215 (void) hpc_nexus_control(slotinfop->slot_hdl, 2216 HPC_CTRL_DEV_CONFIGURED, NULL); 2217 2218 /* 2219 * Tell sysevent listeners that slot has 2220 * changed state. At minimum, this is useful 2221 * when a PCI-E Chassis (containing Occupants) 2222 * is hotplugged. In this case, the following 2223 * will announce that the Occupant in the 2224 * Receptacle in the Chassis had a state-change. 2225 */ 2226 pcihp_gen_sysevent(slotinfop->name, 2227 PCIHP_DR_AP_STATE_CHANGE, SE_NO_HINT, 2228 pcihp_p->dip, KM_SLEEP); 2229 } 2230 } 2231 2232 break; 2233 2234 case HPC_SLOT_OFFLINE: 2235 /* 2236 * A hot plug slot is being removed from the bus. 2237 * Make sure there is no occupant configured on the 2238 * slot before removing the AP minor node. 2239 */ 2240 if (slotinfop->ostate != AP_OSTATE_UNCONFIGURED) { 2241 cmn_err(CE_WARN, "pcihp (%s%d): Card is still in " 2242 "configured state for pci dev %x", 2243 ddi_driver_name(dip), ddi_get_instance(dip), 2244 pci_dev); 2245 rv = HPC_ERR_FAILED; 2246 break; 2247 } 2248 2249 /* 2250 * If the AP device is in open state then return 2251 * error. 2252 */ 2253 if (pcihp_p->soft_state != PCIHP_SOFT_STATE_CLOSED) { 2254 rv = HPC_ERR_FAILED; 2255 break; 2256 } 2257 if (slot_info->slot_flags & HPC_SLOT_CREATE_DEVLINK) { 2258 pci_devlink_flags &= ~(1 << pci_dev); 2259 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, 2260 "ap-names", pci_devlink_flags); 2261 } 2262 2263 /* remove the minor node */ 2264 ddi_remove_minor_node(dip, slotinfop->name); 2265 2266 /* free up the memory for the name string */ 2267 kmem_free(slotinfop->name, strlen(slotinfop->name) + 1); 2268 2269 /* update the slot info data */ 2270 slotinfop->name = NULL; 2271 slotinfop->slot_hdl = NULL; 2272 2273 PCIHP_DEBUG((CE_NOTE, 2274 "pcihp (%s%d): pci slot (dev %x) OFFLINE\n", 2275 ddi_driver_name(dip), ddi_get_instance(dip), 2276 slot_info->pci_dev_num)); 2277 2278 break; 2279 default: 2280 cmn_err(CE_WARN, 2281 "pcihp_new_slot_state: unknown slot_state %d", slot_state); 2282 rv = HPC_ERR_FAILED; 2283 } 2284 2285 if (rv == 0) { 2286 if (drv_getparm(TIME, (void *)&time) != DDI_SUCCESS) 2287 slotinfop->last_change = (time_t)-1; 2288 else 2289 slotinfop->last_change = (time32_t)time; 2290 } 2291 2292 mutex_exit(&slotinfop->slot_mutex); 2293 2294 (void) pcihp_get_soft_state(dip, PCIHP_DR_SLOT_EXIT, &rval); 2295 2296 return (rv); 2297 } 2298 2299 /* 2300 * Event handler. It is assumed that this function is called from 2301 * a kernel context only. 2302 * 2303 * Parameters: 2304 * slot_arg AP minor number. 2305 * event_mask Event that occurred. 2306 */ 2307 2308 static int 2309 pcihp_event_handler(caddr_t slot_arg, uint_t event_mask) 2310 { 2311 dev_t ap_dev = (dev_t)slot_arg; 2312 dev_info_t *self; 2313 pcihp_t *pcihp_p; 2314 int pci_dev; 2315 int rv = HPC_EVENT_CLAIMED; 2316 struct pcihp_slotinfo *slotinfop; 2317 struct pcihp_config_ctrl ctrl; 2318 int rval; 2319 int hint; 2320 hpc_slot_state_t rstate; 2321 struct hpc_led_info led_info; 2322 2323 /* 2324 * Get the soft state structure. 2325 */ 2326 if (pcihp_info(NULL, DDI_INFO_DEVT2DEVINFO, (void *)ap_dev, 2327 (void **)&self) != DDI_SUCCESS) 2328 return (ENXIO); 2329 2330 pcihp_p = pcihp_get_soft_state(self, PCIHP_DR_SLOT_ENTER, &rval); 2331 ASSERT(pcihp_p != NULL); 2332 2333 if (rval == PCIHP_FAILURE) { 2334 PCIHP_DEBUG((CE_WARN, "pcihp instance is unconfigured" 2335 " while slot activity is requested\n")); 2336 return (-1); 2337 } 2338 2339 /* get the PCI device number for the slot */ 2340 pci_dev = PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(getminor(ap_dev)); 2341 2342 slotinfop = &pcihp_p->slotinfo[pci_dev]; 2343 2344 /* 2345 * All the events that may be handled in interrupt context should be 2346 * free of any mutex usage. 2347 */ 2348 switch (event_mask) { 2349 2350 case HPC_EVENT_CLEAR_ENUM: 2351 /* 2352 * Check and clear ENUM# interrupt status. This may be 2353 * called by the Hotswap controller driver when it is 2354 * operating in a full hotswap system where the 2355 * platform may not have control on globally disabling ENUM#. 2356 * In such cases, the intent is to clear interrupt and 2357 * process the interrupt in non-interrupt context. 2358 * This is the first part of the ENUM# event processing. 2359 */ 2360 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): ENUM# is generated" 2361 " on the bus (for slot %s ?)", 2362 ddi_driver_name(pcihp_p->dip), 2363 ddi_get_instance(pcihp_p->dip), slotinfop->name)); 2364 2365 /* this is the only event coming through in interrupt context */ 2366 rv = pcihp_handle_enum(pcihp_p, pci_dev, PCIHP_CLEAR_ENUM, 2367 KM_NOSLEEP); 2368 2369 (void) pcihp_get_soft_state(self, PCIHP_DR_SLOT_EXIT, &rval); 2370 2371 return (rv); 2372 default: 2373 break; 2374 } 2375 2376 mutex_enter(&slotinfop->slot_mutex); 2377 2378 if (hpc_nexus_control(slotinfop->slot_hdl, 2379 HPC_CTRL_GET_SLOT_STATE, (caddr_t)&rstate) != 0) 2380 rv = HPC_ERR_FAILED; 2381 2382 slotinfop->rstate = (ap_rstate_t)rstate; 2383 2384 switch (event_mask) { 2385 2386 case HPC_EVENT_SLOT_INSERTION: 2387 /* 2388 * A card is inserted in the slot. Just report this 2389 * event and return. 2390 */ 2391 cmn_err(CE_NOTE, "pcihp (%s%d): card is inserted" 2392 " in the slot %s (pci dev %x)", 2393 ddi_driver_name(pcihp_p->dip), 2394 ddi_get_instance(pcihp_p->dip), 2395 slotinfop->name, pci_dev); 2396 2397 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2398 2399 break; 2400 2401 case HPC_EVENT_SLOT_CONFIGURE: 2402 /* 2403 * Configure the occupant that is just inserted in the slot. 2404 * The receptacle may or may not be in the connected state. If 2405 * the receptacle is not connected and the auto configuration 2406 * is enabled on this slot then connect the slot. If auto 2407 * configuration is enabled then configure the card. 2408 */ 2409 if ((slotinfop->slot_flags & PCIHP_SLOT_AUTO_CFG_EN) == 0) { 2410 /* 2411 * auto configuration is disabled. Tell someone 2412 * like RCM about this hotplug event? 2413 */ 2414 cmn_err(CE_NOTE, "pcihp (%s%d): SLOT_CONFIGURE event" 2415 " occurred for pci dev %x (slot %s)," 2416 " Slot disabled for auto-configuration.", 2417 ddi_driver_name(pcihp_p->dip), 2418 ddi_get_instance(pcihp_p->dip), pci_dev, 2419 slotinfop->name); 2420 2421 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2422 2423 break; 2424 } 2425 2426 if (slotinfop->ostate == AP_OSTATE_CONFIGURED) { 2427 cmn_err(CE_WARN, "pcihp (%s%d): SLOT_CONFIGURE event" 2428 " re-occurred for pci dev %x (slot %s),", 2429 ddi_driver_name(pcihp_p->dip), 2430 ddi_get_instance(pcihp_p->dip), pci_dev, 2431 slotinfop->name); 2432 mutex_exit(&slotinfop->slot_mutex); 2433 2434 (void) pcihp_get_soft_state(self, PCIHP_DR_SLOT_EXIT, 2435 &rval); 2436 2437 return (EAGAIN); 2438 } 2439 2440 /* 2441 * Auto configuration is enabled. First, make sure the 2442 * receptacle is in the CONNECTED state. 2443 */ 2444 if ((rv = hpc_nexus_connect(slotinfop->slot_hdl, 2445 NULL, 0)) == HPC_SUCCESS) { 2446 /* record rstate */ 2447 slotinfop->rstate = AP_RSTATE_CONNECTED; 2448 } 2449 2450 /* Clear INS and Turn LED Off and start configuring. */ 2451 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2452 pcihp_hs_csr_op(pcihp_p, pci_dev, 2453 HPC_EVENT_SLOT_CONFIGURE); 2454 if (pcihp_cpci_blue_led) 2455 pcihp_hs_csr_op(pcihp_p, pci_dev, 2456 HPC_EVENT_SLOT_BLUE_LED_OFF); 2457 } 2458 2459 (void) hpc_nexus_control(slotinfop->slot_hdl, 2460 HPC_CTRL_DEV_CONFIG_START, NULL); 2461 2462 /* 2463 * Call the configurator to configure the card. 2464 */ 2465 if (pcicfg_configure(pcihp_p->dip, pci_dev, PCICFG_ALL_FUNC, 0) 2466 != PCICFG_SUCCESS) { 2467 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2468 if (pcihp_cpci_blue_led) 2469 pcihp_hs_csr_op(pcihp_p, pci_dev, 2470 HPC_EVENT_SLOT_BLUE_LED_ON); 2471 pcihp_hs_csr_op(pcihp_p, pci_dev, 2472 HPC_EVENT_SLOT_UNCONFIGURE); 2473 } 2474 /* failed to configure the card */ 2475 cmn_err(CE_WARN, "pcihp (%s%d): failed to configure" 2476 " the card in the slot %s", 2477 ddi_driver_name(pcihp_p->dip), 2478 ddi_get_instance(pcihp_p->dip), 2479 slotinfop->name); 2480 /* failed to configure; disconnect the slot */ 2481 if (hpc_nexus_disconnect(slotinfop->slot_hdl, 2482 NULL, 0) == HPC_SUCCESS) { 2483 slotinfop->rstate = AP_RSTATE_DISCONNECTED; 2484 } 2485 2486 /* tell HPC driver occupant configure Error */ 2487 (void) hpc_nexus_control(slotinfop->slot_hdl, 2488 HPC_CTRL_DEV_CONFIG_FAILURE, NULL); 2489 } else { 2490 /* record the occupant state as CONFIGURED */ 2491 slotinfop->ostate = AP_OSTATE_CONFIGURED; 2492 slotinfop->condition = AP_COND_OK; 2493 2494 /* now, online all the devices in the AP */ 2495 ctrl.flags = PCIHP_CFG_CONTINUE; 2496 ctrl.rv = NDI_SUCCESS; 2497 ctrl.dip = NULL; 2498 ctrl.pci_dev = pci_dev; 2499 ctrl.op = PCIHP_ONLINE; 2500 (void) pcihp_get_board_type(slotinfop); 2501 2502 ndi_devi_enter(pcihp_p->dip); 2503 ddi_walk_devs(ddi_get_child(pcihp_p->dip), 2504 pcihp_configure, (void *)&ctrl); 2505 ndi_devi_exit(pcihp_p->dip); 2506 2507 if (ctrl.rv != NDI_SUCCESS) { 2508 /* 2509 * one or more of the devices are not 2510 * ONLINE'd. How is this to be 2511 * reported? 2512 */ 2513 cmn_err(CE_WARN, 2514 "pcihp (%s%d): failed to attach one or" 2515 " more drivers for the card in" 2516 " the slot %s", 2517 ddi_driver_name(pcihp_p->dip), 2518 ddi_get_instance(pcihp_p->dip), 2519 slotinfop->name); 2520 } 2521 2522 /* tell HPC driver that the occupant is configured */ 2523 (void) hpc_nexus_control(slotinfop->slot_hdl, 2524 HPC_CTRL_DEV_CONFIGURED, NULL); 2525 2526 cmn_err(CE_NOTE, "pcihp (%s%d): card is CONFIGURED" 2527 " in the slot %s (pci dev %x)", 2528 ddi_driver_name(pcihp_p->dip), 2529 ddi_get_instance(pcihp_p->dip), 2530 slotinfop->name, pci_dev); 2531 } 2532 2533 break; 2534 2535 case HPC_EVENT_SLOT_UNCONFIGURE: 2536 /* 2537 * Unconfigure the occupant in this slot. 2538 */ 2539 if ((slotinfop->slot_flags & PCIHP_SLOT_AUTO_CFG_EN) == 0) { 2540 /* 2541 * auto configuration is disabled. Tell someone 2542 * like RCM about this hotplug event? 2543 */ 2544 cmn_err(CE_NOTE, "pcihp (%s%d): SLOT_UNCONFIGURE event" 2545 " for pci dev %x (slot %s) ignored," 2546 " Slot disabled for auto-configuration.", 2547 ddi_driver_name(pcihp_p->dip), 2548 ddi_get_instance(pcihp_p->dip), pci_dev, 2549 slotinfop->name); 2550 2551 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2552 2553 break; 2554 } 2555 2556 if (slotinfop->ostate == AP_OSTATE_UNCONFIGURED) { 2557 cmn_err(CE_WARN, "pcihp (%s%d): SLOT_UNCONFIGURE " 2558 "event re-occurred for pci dev %x (slot %s),", 2559 ddi_driver_name(pcihp_p->dip), 2560 ddi_get_instance(pcihp_p->dip), pci_dev, 2561 slotinfop->name); 2562 mutex_exit(&slotinfop->slot_mutex); 2563 2564 (void) pcihp_get_soft_state(self, PCIHP_DR_SLOT_EXIT, 2565 &rval); 2566 2567 return (EAGAIN); 2568 } 2569 /* 2570 * If the occupant is in the CONFIGURED state then 2571 * call the configurator to unconfigure the slot. 2572 */ 2573 if (slotinfop->ostate == AP_OSTATE_CONFIGURED) { 2574 /* 2575 * Detach all the drivers for the devices in the 2576 * slot. Call pcihp_configure() to offline the 2577 * devices. 2578 */ 2579 ctrl.flags = 0; 2580 ctrl.rv = NDI_SUCCESS; 2581 ctrl.dip = NULL; 2582 ctrl.pci_dev = pci_dev; 2583 ctrl.op = PCIHP_OFFLINE; 2584 2585 (void) devfs_clean(pcihp_p->dip, NULL, DV_CLEAN_FORCE); 2586 ndi_devi_enter(pcihp_p->dip); 2587 ddi_walk_devs(ddi_get_child(pcihp_p->dip), 2588 pcihp_configure, (void *)&ctrl); 2589 ndi_devi_exit(pcihp_p->dip); 2590 2591 if (ctrl.rv != NDI_SUCCESS) { 2592 /* 2593 * Failed to detach one or more drivers. 2594 * Restore the status for the drivers 2595 * which are offlined during this step. 2596 */ 2597 ctrl.flags = PCIHP_CFG_CONTINUE; 2598 ctrl.rv = NDI_SUCCESS; 2599 ctrl.dip = NULL; 2600 ctrl.pci_dev = pci_dev; 2601 ctrl.op = PCIHP_ONLINE; 2602 2603 ndi_devi_enter(pcihp_p->dip); 2604 ddi_walk_devs(ddi_get_child(pcihp_p->dip), 2605 pcihp_configure, (void *)&ctrl); 2606 ndi_devi_exit(pcihp_p->dip); 2607 rv = HPC_ERR_FAILED; 2608 } else { 2609 (void) hpc_nexus_control(slotinfop->slot_hdl, 2610 HPC_CTRL_DEV_UNCONFIG_START, NULL); 2611 2612 if (pcicfg_unconfigure(pcihp_p->dip, pci_dev, 2613 PCICFG_ALL_FUNC, 0) == PCICFG_SUCCESS) { 2614 2615 /* Resources freed. Turn LED on. Clear EXT. */ 2616 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2617 if (pcihp_cpci_blue_led) 2618 pcihp_hs_csr_op(pcihp_p, 2619 pci_dev, 2620 HPC_EVENT_SLOT_BLUE_LED_ON); 2621 pcihp_hs_csr_op(pcihp_p, pci_dev, 2622 HPC_EVENT_SLOT_UNCONFIGURE); 2623 slotinfop->hs_csr_location = 0; 2624 slotinfop->slot_flags &= 2625 ~PCIHP_SLOT_DEV_NON_HOTPLUG; 2626 } 2627 slotinfop->ostate = 2628 AP_OSTATE_UNCONFIGURED; 2629 slotinfop->condition = AP_COND_UNKNOWN; 2630 /* 2631 * send the notification of state change 2632 * to the HPC driver. 2633 */ 2634 (void) hpc_nexus_control( 2635 slotinfop->slot_hdl, 2636 HPC_CTRL_DEV_UNCONFIGURED, NULL); 2637 /* disconnect the slot */ 2638 if (hpc_nexus_disconnect( 2639 slotinfop->slot_hdl, 2640 NULL, 0) == HPC_SUCCESS) { 2641 slotinfop->rstate = 2642 AP_RSTATE_DISCONNECTED; 2643 } 2644 2645 cmn_err(CE_NOTE, 2646 "pcihp (%s%d): card is UNCONFIGURED" 2647 " in the slot %s (pci dev %x)", 2648 ddi_driver_name(pcihp_p->dip), 2649 ddi_get_instance(pcihp_p->dip), 2650 slotinfop->name, pci_dev); 2651 } else { 2652 /* tell HPC driver occupant is Busy */ 2653 (void) hpc_nexus_control( 2654 slotinfop->slot_hdl, 2655 HPC_CTRL_DEV_UNCONFIG_FAILURE, 2656 NULL); 2657 2658 rv = HPC_ERR_FAILED; 2659 } 2660 } 2661 } 2662 2663 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2664 2665 break; 2666 2667 case HPC_EVENT_SLOT_REMOVAL: 2668 /* 2669 * Card is removed from the slot. The card must have been 2670 * unconfigured before this event. 2671 */ 2672 if (slotinfop->ostate != AP_OSTATE_UNCONFIGURED) { 2673 slotinfop->condition = AP_COND_FAILED; 2674 cmn_err(CE_WARN, "pcihp (%s%d): card is removed" 2675 " from the slot %s", 2676 ddi_driver_name(pcihp_p->dip), 2677 ddi_get_instance(pcihp_p->dip), 2678 slotinfop->name); 2679 } else { 2680 slotinfop->condition = AP_COND_UNKNOWN; 2681 cmn_err(CE_NOTE, "pcihp (%s%d): card is removed" 2682 " from the slot %s", 2683 ddi_driver_name(pcihp_p->dip), 2684 ddi_get_instance(pcihp_p->dip), 2685 slotinfop->name); 2686 } 2687 2688 slotinfop->rstate = AP_RSTATE_EMPTY; 2689 2690 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2691 2692 break; 2693 2694 case HPC_EVENT_SLOT_POWER_ON: 2695 /* 2696 * Slot is connected to the bus. i.e the card is powered 2697 * on. Are there any error conditions to be checked? 2698 */ 2699 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): card is powered" 2700 " on in the slot %s", 2701 ddi_driver_name(pcihp_p->dip), 2702 ddi_get_instance(pcihp_p->dip), 2703 slotinfop->name)); 2704 2705 slotinfop->rstate = AP_RSTATE_CONNECTED; /* record rstate */ 2706 2707 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2708 2709 break; 2710 2711 case HPC_EVENT_SLOT_POWER_OFF: 2712 /* 2713 * Slot is disconnected from the bus. i.e the card is powered 2714 * off. Are there any error conditions to be checked? 2715 */ 2716 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): card is powered" 2717 " off in the slot %s", 2718 ddi_driver_name(pcihp_p->dip), 2719 ddi_get_instance(pcihp_p->dip), 2720 slotinfop->name)); 2721 2722 slotinfop->rstate = AP_RSTATE_DISCONNECTED; /* record rstate */ 2723 2724 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2725 2726 break; 2727 2728 case HPC_EVENT_SLOT_LATCH_SHUT: 2729 /* 2730 * Latch on the slot is closed. 2731 */ 2732 cmn_err(CE_NOTE, "pcihp (%s%d): latch is shut for the slot %s", 2733 ddi_driver_name(pcihp_p->dip), 2734 ddi_get_instance(pcihp_p->dip), 2735 slotinfop->name); 2736 2737 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2738 2739 break; 2740 2741 case HPC_EVENT_SLOT_LATCH_OPEN: 2742 /* 2743 * Latch on the slot is open. 2744 */ 2745 cmn_err(CE_NOTE, "pcihp (%s%d): latch is open for the slot %s", 2746 ddi_driver_name(pcihp_p->dip), 2747 ddi_get_instance(pcihp_p->dip), 2748 slotinfop->name); 2749 2750 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2751 2752 break; 2753 2754 case HPC_EVENT_PROCESS_ENUM: 2755 /* 2756 * HSC knows the device number of the slot where the 2757 * ENUM# was triggered. 2758 * Now finish the necessary actions to be taken on that 2759 * slot. Please note that the interrupt is already cleared. 2760 * This is the second(last) part of the ENUM# event processing. 2761 */ 2762 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): processing ENUM#" 2763 " for slot %s", 2764 ddi_driver_name(pcihp_p->dip), 2765 ddi_get_instance(pcihp_p->dip), 2766 slotinfop->name)); 2767 2768 mutex_exit(&slotinfop->slot_mutex); 2769 rv = pcihp_enum_slot(pcihp_p, slotinfop, pci_dev, 2770 PCIHP_HANDLE_ENUM, KM_SLEEP); 2771 mutex_enter(&slotinfop->slot_mutex); 2772 2773 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2774 2775 break; 2776 2777 case HPC_EVENT_BUS_ENUM: 2778 /* 2779 * Same as HPC_EVENT_SLOT_ENUM as defined the PSARC doc. 2780 * This term is used for better clarity of its usage. 2781 * 2782 * ENUM signal occurred on the bus. It may be from this 2783 * slot or any other hotplug slot on the bus. 2784 * 2785 * It is NOT recommended that the hotswap controller uses 2786 * event without queuing as NDI and other DDI calls may not 2787 * necessarily be invokable in interrupt context. 2788 * Hence the hotswap controller driver should use the 2789 * CLEAR_ENUM event which returns the slot device number 2790 * and then call HPC_EVENT_PROCESS_ENUM event with queuing. 2791 * 2792 * This can be used when the hotswap controller is 2793 * implementing a polled event mechanism to do the 2794 * necessary actions in a single call. 2795 */ 2796 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): ENUM# is generated" 2797 " on the bus (for slot %s ?)", 2798 ddi_driver_name(pcihp_p->dip), 2799 ddi_get_instance(pcihp_p->dip), 2800 slotinfop->name)); 2801 2802 mutex_exit(&slotinfop->slot_mutex); 2803 rv = pcihp_handle_enum(pcihp_p, pci_dev, PCIHP_HANDLE_ENUM, 2804 KM_SLEEP); 2805 mutex_enter(&slotinfop->slot_mutex); 2806 2807 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2808 2809 break; 2810 2811 case HPC_EVENT_SLOT_BLUE_LED_ON: 2812 2813 /* 2814 * Request to turn Hot Swap Blue LED on. 2815 */ 2816 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): Request To Turn On Blue " 2817 "LED on the bus (for slot %s ?)", 2818 ddi_driver_name(pcihp_p->dip), 2819 ddi_get_instance(pcihp_p->dip), 2820 slotinfop->name)); 2821 2822 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_SLOT_BLUE_LED_ON); 2823 break; 2824 2825 case HPC_EVENT_DISABLE_ENUM: 2826 /* 2827 * Disable ENUM# which disables auto configuration on this slot 2828 */ 2829 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2830 pcihp_hs_csr_op(pcihp_p, pci_dev, 2831 HPC_EVENT_DISABLE_ENUM); 2832 slotinfop->slot_flags &= ~PCIHP_SLOT_AUTO_CFG_EN; 2833 } 2834 break; 2835 2836 case HPC_EVENT_ENABLE_ENUM: 2837 /* 2838 * Enable ENUM# which enables auto configuration on this slot. 2839 */ 2840 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 2841 pcihp_hs_csr_op(pcihp_p, pci_dev, 2842 HPC_EVENT_ENABLE_ENUM); 2843 slotinfop->slot_flags |= PCIHP_SLOT_AUTO_CFG_EN; 2844 } 2845 break; 2846 2847 case HPC_EVENT_SLOT_BLUE_LED_OFF: 2848 2849 /* 2850 * Request to turn Hot Swap Blue LED off. 2851 */ 2852 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): Request To Turn Off Blue " 2853 "LED on the bus (for slot %s ?)", 2854 ddi_driver_name(pcihp_p->dip), 2855 ddi_get_instance(pcihp_p->dip), 2856 slotinfop->name)); 2857 2858 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_SLOT_BLUE_LED_OFF); 2859 2860 break; 2861 2862 case HPC_EVENT_SLOT_NOT_HEALTHY: 2863 /* 2864 * HEALTHY# signal on this slot is not OK. 2865 */ 2866 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): HEALTHY# signal is not OK" 2867 " for this slot %s", 2868 ddi_driver_name(pcihp_p->dip), 2869 ddi_get_instance(pcihp_p->dip), 2870 slotinfop->name)); 2871 2872 /* record the state in slot_flags field */ 2873 slotinfop->slot_flags |= PCIHP_SLOT_NOT_HEALTHY; 2874 slotinfop->condition = AP_COND_FAILED; 2875 2876 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2877 2878 break; 2879 2880 case HPC_EVENT_SLOT_HEALTHY_OK: 2881 /* 2882 * HEALTHY# signal on this slot is OK now. 2883 */ 2884 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): HEALTHY# signal is OK now" 2885 " for this slot %s", 2886 ddi_driver_name(pcihp_p->dip), 2887 ddi_get_instance(pcihp_p->dip), 2888 slotinfop->name)); 2889 2890 /* update the state in slot_flags field */ 2891 slotinfop->slot_flags &= ~PCIHP_SLOT_NOT_HEALTHY; 2892 slotinfop->condition = AP_COND_OK; 2893 2894 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2895 2896 break; 2897 2898 case HPC_EVENT_SLOT_ATTN: 2899 /* 2900 * Attention button is pressed. 2901 */ 2902 if (((slotinfop->slot_flags & PCIHP_SLOT_AUTO_CFG_EN) == 0) || 2903 (slotinfop->slot_flags & PCIHP_SLOT_DISABLED)) { 2904 /* 2905 * either auto-conifiguration or the slot is disabled, 2906 * ignore this event. 2907 */ 2908 break; 2909 } 2910 2911 if (slotinfop->ostate == AP_OSTATE_UNCONFIGURED) 2912 hint = SE_INCOMING_RES; 2913 else 2914 hint = SE_OUTGOING_RES; 2915 2916 if (ddi_getprop(DDI_DEV_T_ANY, pcihp_p->dip, DDI_PROP_DONTPASS, 2917 "inkernel-autoconfig", 0) == 0) { 2918 pcihp_gen_sysevent(slotinfop->name, PCIHP_DR_REQ, hint, 2919 pcihp_p->dip, KM_SLEEP); 2920 break; 2921 } 2922 2923 if ((slotinfop->ostate == AP_OSTATE_UNCONFIGURED) && 2924 (slotinfop->rstate != AP_RSTATE_EMPTY) && 2925 (slotinfop->condition != AP_COND_FAILED)) { 2926 if (slotinfop->rstate == AP_RSTATE_DISCONNECTED) { 2927 rv = hpc_nexus_connect(slotinfop->slot_hdl, 2928 NULL, 0); 2929 if (rv == HPC_SUCCESS) 2930 slotinfop->rstate = AP_RSTATE_CONNECTED; 2931 else 2932 break; 2933 } 2934 2935 rv = pcihp_configure_ap(pcihp_p, pci_dev); 2936 2937 } else if ((slotinfop->ostate == AP_OSTATE_CONFIGURED) && 2938 (slotinfop->rstate == AP_RSTATE_CONNECTED) && 2939 (slotinfop->condition != AP_COND_FAILED)) { 2940 rv = pcihp_unconfigure_ap(pcihp_p, pci_dev); 2941 2942 if (rv != HPC_SUCCESS) 2943 break; 2944 2945 rv = hpc_nexus_disconnect(slotinfop->slot_hdl, 2946 NULL, 0); 2947 if (rv == HPC_SUCCESS) 2948 slotinfop->rstate = AP_RSTATE_DISCONNECTED; 2949 } 2950 2951 break; 2952 2953 case HPC_EVENT_SLOT_POWER_FAULT: 2954 /* 2955 * Power fault is detected. 2956 */ 2957 cmn_err(CE_NOTE, "pcihp (%s%d): power-fault" 2958 " for this slot %s", 2959 ddi_driver_name(pcihp_p->dip), 2960 ddi_get_instance(pcihp_p->dip), 2961 slotinfop->name); 2962 2963 /* turn on ATTN led */ 2964 led_info.led = HPC_ATTN_LED; 2965 led_info.state = HPC_LED_ON; 2966 rv = hpc_nexus_control(slotinfop->slot_hdl, 2967 HPC_CTRL_SET_LED_STATE, (caddr_t)&led_info); 2968 2969 if (slotinfop->rstate == AP_RSTATE_CONNECTED) 2970 (void) hpc_nexus_disconnect(slotinfop->slot_hdl, 2971 NULL, 0); 2972 2973 slotinfop->condition = AP_COND_FAILED; 2974 2975 pcihp_gen_sysevent(slotinfop->name, PCIHP_DR_AP_STATE_CHANGE, 2976 SE_NO_HINT, pcihp_p->dip, KM_SLEEP); 2977 2978 break; 2979 2980 default: 2981 cmn_err(CE_NOTE, "pcihp (%s%d): unknown event %x" 2982 " for this slot %s", 2983 ddi_driver_name(pcihp_p->dip), 2984 ddi_get_instance(pcihp_p->dip), event_mask, 2985 slotinfop->name); 2986 2987 /* +++ HOOK for RCM to report this hotplug event? +++ */ 2988 2989 break; 2990 } 2991 2992 mutex_exit(&slotinfop->slot_mutex); 2993 2994 (void) pcihp_get_soft_state(self, PCIHP_DR_SLOT_EXIT, &rval); 2995 2996 return (rv); 2997 } 2998 2999 /* 3000 * This function is called to online or offline the devices for an 3001 * attachment point. If the PCI device number of the node matches 3002 * with the device number of the specified hot plug slot then 3003 * the operation is performed. 3004 */ 3005 static int 3006 pcihp_configure(dev_info_t *dip, void *hdl) 3007 { 3008 int pci_dev; 3009 struct pcihp_config_ctrl *ctrl = (struct pcihp_config_ctrl *)hdl; 3010 int rv; 3011 pci_regspec_t *pci_rp; 3012 int length; 3013 3014 /* 3015 * Get the PCI device number information from the devinfo 3016 * node. Since the node may not have the address field 3017 * setup (this is done in the DDI_INITCHILD of the parent) 3018 * we look up the 'reg' property to decode that information. 3019 */ 3020 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 3021 "reg", (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) { 3022 ctrl->rv = DDI_FAILURE; 3023 ctrl->dip = dip; 3024 return (DDI_WALK_TERMINATE); 3025 } 3026 3027 /* get the pci device id information */ 3028 pci_dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 3029 3030 /* 3031 * free the memory allocated by ddi_prop_lookup_int_array 3032 */ 3033 ddi_prop_free(pci_rp); 3034 3035 /* 3036 * Match the node for the device number of the slot. 3037 */ 3038 if (pci_dev == ctrl->pci_dev) { /* node is a match */ 3039 if (ctrl->op == PCIHP_ONLINE) { 3040 /* it is CONFIGURE operation */ 3041 3042 /* skip this device if it is disabled or faulty */ 3043 if (pcihp_check_status(dip) == B_FALSE) { 3044 return (DDI_WALK_PRUNECHILD); 3045 } 3046 3047 rv = ndi_devi_online(dip, NDI_ONLINE_ATTACH|NDI_CONFIG); 3048 } else { 3049 /* 3050 * it is UNCONFIGURE operation. 3051 */ 3052 rv = ndi_devi_offline(dip, NDI_UNCONFIG); 3053 } 3054 if (rv != NDI_SUCCESS) { 3055 /* failed to attach/detach the driver(s) */ 3056 ctrl->rv = rv; 3057 ctrl->dip = dip; 3058 /* terminate the search if specified */ 3059 if (!(ctrl->flags & PCIHP_CFG_CONTINUE)) 3060 return (DDI_WALK_TERMINATE); 3061 } 3062 } 3063 3064 /* 3065 * continue the walk to the next sibling to look for a match 3066 * or to find other nodes if this card is a multi-function card. 3067 */ 3068 return (DDI_WALK_PRUNECHILD); 3069 } 3070 3071 /* 3072 * Check the device for a 'status' property. A conforming device 3073 * should have a status of "okay", "disabled", "fail", or "fail-xxx". 3074 * 3075 * Return FALSE for a conforming device that is disabled or faulted. 3076 * Return TRUE in every other case. 3077 */ 3078 static bool_t 3079 pcihp_check_status(dev_info_t *dip) 3080 { 3081 char *status_prop; 3082 bool_t rv = B_TRUE; 3083 3084 /* try to get the 'status' property */ 3085 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 3086 "status", &status_prop) == DDI_PROP_SUCCESS) { 3087 3088 /* 3089 * test if the status is "disabled", "fail", or 3090 * "fail-xxx". 3091 */ 3092 if (strcmp(status_prop, "disabled") == 0) { 3093 rv = B_FALSE; 3094 PCIHP_DEBUG((CE_NOTE, 3095 "pcihp (%s%d): device is in disabled state", 3096 ddi_driver_name(dip), ddi_get_instance(dip))); 3097 } else if (strncmp(status_prop, "fail", 4) == 0) { 3098 rv = B_FALSE; 3099 cmn_err(CE_WARN, 3100 "pcihp (%s%d): device is in fault state (%s)", 3101 ddi_driver_name(dip), ddi_get_instance(dip), 3102 status_prop); 3103 } 3104 3105 ddi_prop_free(status_prop); 3106 } 3107 3108 return (rv); 3109 } 3110 3111 /* control structure used to find a device in the devinfo tree */ 3112 struct pcihp_find_ctrl { 3113 uint_t device; 3114 uint_t function; 3115 dev_info_t *dip; 3116 }; 3117 3118 static dev_info_t * 3119 pcihp_devi_find(dev_info_t *dip, uint_t device, uint_t function) 3120 { 3121 struct pcihp_find_ctrl ctrl; 3122 3123 ctrl.device = device; 3124 ctrl.function = function; 3125 ctrl.dip = NULL; 3126 3127 ndi_devi_enter(dip); 3128 ddi_walk_devs(ddi_get_child(dip), pcihp_match_dev, (void *)&ctrl); 3129 ndi_devi_exit(dip); 3130 3131 return (ctrl.dip); 3132 } 3133 3134 static int 3135 pcihp_match_dev(dev_info_t *dip, void *hdl) 3136 { 3137 struct pcihp_find_ctrl *ctrl = (struct pcihp_find_ctrl *)hdl; 3138 pci_regspec_t *pci_rp; 3139 int length; 3140 int pci_dev; 3141 int pci_func; 3142 3143 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 3144 "reg", (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) { 3145 ctrl->dip = NULL; 3146 return (DDI_WALK_TERMINATE); 3147 } 3148 3149 /* get the PCI device address info */ 3150 pci_dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 3151 pci_func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 3152 3153 /* 3154 * free the memory allocated by ddi_prop_lookup_int_array 3155 */ 3156 ddi_prop_free(pci_rp); 3157 3158 3159 if ((pci_dev == ctrl->device) && (pci_func == ctrl->function)) { 3160 /* found the match for the specified device address */ 3161 ctrl->dip = dip; 3162 return (DDI_WALK_TERMINATE); 3163 } 3164 3165 /* 3166 * continue the walk to the next sibling to look for a match. 3167 */ 3168 return (DDI_WALK_PRUNECHILD); 3169 } 3170 3171 #if 0 3172 /* 3173 * Probe the configuration space of the slot to determine the receptacle 3174 * state. There may not be any devinfo tree created for this slot. 3175 */ 3176 static void 3177 pcihp_probe_slot_state(dev_info_t *dip, int dev, hpc_slot_state_t *rstatep) 3178 { 3179 /* XXX FIX IT */ 3180 } 3181 #endif 3182 3183 /* 3184 * This routine is called when a ENUM# assertion is detected for a bus. 3185 * Since ENUM# may be bussed, the slot that asserted ENUM# may not be known. 3186 * The HPC Driver passes the handle of a slot that is its best guess. 3187 * If the best guess slot is the one that asserted ENUM#, the proper handling 3188 * will be done. If its not, all possible slots will be locked at until 3189 * one that is asserting ENUM is found. 3190 * Also, indicate to the HSC to turn on ENUM# after it is serviced, 3191 * incase if it was disabled by the HSC due to the nature of asynchronous 3192 * delivery of interrupt by the framework. 3193 * 3194 * opcode has the following meanings. 3195 * PCIHP_CLEAR_ENUM = just clear interrupt and return the PCI device no. if 3196 * success, else return -1. 3197 * PCIHP_HANDLE_ENUM = clear interrupt and handle interrupt also. 3198 * 3199 */ 3200 static int 3201 pcihp_handle_enum(pcihp_t *pcihp_p, int favorite_pci_dev, int opcode, 3202 int kmflag) 3203 { 3204 struct pcihp_slotinfo *slotinfop; 3205 int pci_dev, rc, event_serviced = 0; 3206 3207 /* 3208 * Handle ENUM# condition for the "favorite" slot first. 3209 */ 3210 slotinfop = &pcihp_p->slotinfo[favorite_pci_dev]; 3211 if (slotinfop) { 3212 /* 3213 * First try the "favorite" pci device. This is the device 3214 * associated with the handle passed by the HPC Driver. 3215 */ 3216 rc = pcihp_enum_slot(pcihp_p, slotinfop, favorite_pci_dev, 3217 opcode, kmflag); 3218 if (rc != HPC_EVENT_UNCLAIMED) { /* indicates success */ 3219 event_serviced = 1; 3220 /* This MUST be a non-DEBUG feature. */ 3221 if (! pcihp_enum_scan_all) { 3222 return (rc); 3223 } 3224 } 3225 } 3226 3227 /* 3228 * If ENUM# is implemented as a radial signal, then there is no 3229 * need to further poll the slots. 3230 */ 3231 if (pcihp_p->bus_flags & PCIHP_BUS_ENUM_RADIAL) 3232 goto enum_service_check; 3233 3234 /* 3235 * If the "favorite" pci device didn't assert ENUM#, then 3236 * try the rest. Once we find and handle a device that asserted 3237 * ENUM#, then we will terminate the walk by returning unless 3238 * scan-all flag is set. 3239 */ 3240 for (pci_dev = 0; pci_dev < PCI_MAX_DEVS; pci_dev++) { 3241 if (pci_dev != favorite_pci_dev) { 3242 slotinfop = &pcihp_p->slotinfo[pci_dev]; 3243 if (slotinfop == NULL) { 3244 continue; 3245 } 3246 /* Only CPCI devices support ENUM# generation. */ 3247 if (!(slotinfop->slot_type & HPC_SLOT_TYPE_CPCI)) 3248 continue; 3249 rc = pcihp_enum_slot(pcihp_p, slotinfop, pci_dev, 3250 opcode, kmflag); 3251 if (rc != HPC_EVENT_UNCLAIMED) { 3252 event_serviced = 1; 3253 /* This MUST be a non-DEBUG feature. */ 3254 if (! pcihp_enum_scan_all) 3255 break; 3256 } 3257 } 3258 } 3259 3260 enum_service_check: 3261 if (event_serviced) { 3262 return (rc); 3263 } 3264 3265 /* No ENUM# event found, Return */ 3266 return (HPC_EVENT_UNCLAIMED); 3267 } 3268 3269 /* 3270 * This routine attempts to handle a possible ENUM# assertion case for a 3271 * specified slot. This only works for adapters that implement Hot Swap 3272 * Friendly Silicon. If the slot's HS_CSR is read and it specifies ENUM# 3273 * has been asserted, either the insertion or removal handlers will be 3274 * called. 3275 */ 3276 static int 3277 pcihp_enum_slot(pcihp_t *pcihp_p, struct pcihp_slotinfo *slotinfop, int pci_dev, 3278 int opcode, int kmflag) 3279 { 3280 ddi_acc_handle_t handle; 3281 dev_info_t *dip, *new_child = NULL; 3282 int result, rv = -1; 3283 uint8_t hs_csr; 3284 3285 if (pcihp_config_setup(&dip, &handle, &new_child, pci_dev, 3286 pcihp_p) != DDI_SUCCESS) { 3287 return (HPC_EVENT_UNCLAIMED); 3288 } 3289 3290 /* 3291 * Read the device's HS_CSR. 3292 */ 3293 result = pcihp_get_hs_csr(slotinfop, handle, (uint8_t *)&hs_csr); 3294 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): hs_csr = %x, flags = %x", 3295 ddi_driver_name(pcihp_p->dip), ddi_get_instance(pcihp_p->dip), 3296 hs_csr, slotinfop->slot_flags)); 3297 /* 3298 * we teardown our device map here, because in case of an 3299 * extraction event, our nodes would be freed and a teardown 3300 * will cause problems. 3301 */ 3302 pcihp_config_teardown(&handle, &new_child, pci_dev, pcihp_p); 3303 3304 if (result == PCIHP_SUCCESS) { 3305 3306 /* If ENUM# is masked, then it is not us. Some other device */ 3307 if ((hs_csr & HS_CSR_EIM) && (opcode == PCIHP_CLEAR_ENUM)) 3308 return (HPC_EVENT_UNCLAIMED); 3309 /* 3310 * This device supports Full Hot Swap and implements 3311 * the Hot Swap Control and Status Register. 3312 */ 3313 if ((hs_csr & HS_CSR_INS) || 3314 (slotinfop->slot_flags & PCIHP_SLOT_ENUM_INS_PENDING)) { 3315 /* handle insertion ENUM */ 3316 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): " 3317 "Handle Insertion ENUM (INS) " 3318 "on the bus (for slot %s ?)", 3319 ddi_driver_name(pcihp_p->dip), 3320 ddi_get_instance(pcihp_p->dip), 3321 slotinfop->name)); 3322 3323 /* 3324 * generate sysevent 3325 */ 3326 3327 if (opcode == PCIHP_CLEAR_ENUM) 3328 pcihp_gen_sysevent(slotinfop->name, 3329 PCIHP_DR_REQ, 3330 SE_INCOMING_RES, pcihp_p->dip, 3331 kmflag); 3332 3333 rv = pcihp_handle_enum_insertion(pcihp_p, pci_dev, 3334 opcode, kmflag); 3335 3336 } else if ((hs_csr & HS_CSR_EXT) || 3337 (slotinfop->slot_flags & PCIHP_SLOT_ENUM_EXT_PENDING)) { 3338 /* handle extraction ENUM */ 3339 PCIHP_DEBUG((CE_NOTE, "pcihp (%s%d): " 3340 "Handle Extraction ENUM (EXT) " 3341 "on the bus (for slot %s ?)", 3342 ddi_driver_name(pcihp_p->dip), 3343 ddi_get_instance(pcihp_p->dip), 3344 slotinfop->name)); 3345 3346 /* 3347 * generate sysevent 3348 */ 3349 3350 if (opcode == PCIHP_CLEAR_ENUM) 3351 pcihp_gen_sysevent(slotinfop->name, 3352 PCIHP_DR_REQ, 3353 SE_OUTGOING_RES, 3354 pcihp_p->dip, 3355 kmflag); 3356 3357 rv = pcihp_handle_enum_extraction(pcihp_p, pci_dev, 3358 opcode, kmflag); 3359 } 3360 if (opcode == PCIHP_CLEAR_ENUM) { 3361 if (rv == PCIHP_SUCCESS) 3362 rv = pci_dev; 3363 else 3364 rv = HPC_EVENT_UNCLAIMED; 3365 } 3366 } 3367 3368 return (rv); 3369 } 3370 3371 /* 3372 * This routine is called when a ENUM# caused by lifting the lever 3373 * is detected. If the occupant is configured, it will be unconfigured. 3374 * If the occupant is already unconfigured or is successfully unconfigured, 3375 * the blue LED on the adapter is illuminated which means its OK to remove. 3376 * Please note that the lock must be released before invoking the 3377 * generic AP unconfigure function. 3378 */ 3379 static int 3380 pcihp_handle_enum_extraction(pcihp_t *pcihp_p, int pci_dev, int opcode, 3381 int kmflag) 3382 { 3383 struct pcihp_slotinfo *slotinfop; 3384 int rv = PCIHP_FAILURE; 3385 3386 slotinfop = &pcihp_p->slotinfo[pci_dev]; 3387 3388 /* 3389 * It was observed that, clearing the EXT bit turned the LED ON. 3390 * This is a BIG problem in case if the unconfigure operation 3391 * failed because the board was busy. 3392 * In order to avoid this confusing situation (LED ON but the board 3393 * is not unconfigured), we instead decided not to clear EXT but 3394 * disable further ENUM# from this slot. Disabling ENUM# clears 3395 * the interrupt. 3396 * Finally before returning we clear the interrupt and enable 3397 * ENUM# back again from this slot. 3398 */ 3399 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_DISABLE_ENUM); 3400 if (opcode == PCIHP_CLEAR_ENUM) { 3401 slotinfop->slot_flags |= PCIHP_SLOT_ENUM_EXT_PENDING; 3402 return (PCIHP_SUCCESS); 3403 } 3404 3405 mutex_enter(&slotinfop->slot_mutex); 3406 rv = pcihp_unconfigure_ap(pcihp_p, pci_dev); 3407 mutex_exit(&slotinfop->slot_mutex); 3408 if (rv != HPC_SUCCESS && rv != EBUSY) { 3409 cmn_err(CE_NOTE, "%s%d: PCI device %x Failed on Unconfigure", 3410 ddi_driver_name(pcihp_p->dip), 3411 ddi_get_instance(pcihp_p->dip), pci_dev); 3412 } 3413 if (rv == EBUSY) 3414 cmn_err(CE_NOTE, "%s%d: PCI device %x Busy", 3415 ddi_driver_name(pcihp_p->dip), 3416 ddi_get_instance(pcihp_p->dip), pci_dev); 3417 if (rv) { 3418 if (pcihp_cpci_blue_led) 3419 pcihp_hs_csr_op(pcihp_p, pci_dev, 3420 HPC_EVENT_SLOT_BLUE_LED_OFF); 3421 } 3422 /* 3423 * we must clear interrupt in case the unconfigure didn't do it 3424 * due to a duplicate interrupt. Extraction is success. 3425 */ 3426 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_SLOT_UNCONFIGURE); 3427 3428 if (!rv) { 3429 /* 3430 * Sys Event Notification. 3431 */ 3432 pcihp_gen_sysevent(slotinfop->name, PCIHP_DR_AP_STATE_CHANGE, 3433 SE_HINT_REMOVE, pcihp_p->dip, kmflag); 3434 } 3435 3436 /* 3437 * Enable interrupts back from this board. 3438 * This could potentially be problematic in case if the user is 3439 * quick enough to extract the board. 3440 * But we must do it just in case if the switch is closed again. 3441 */ 3442 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_ENABLE_ENUM); 3443 slotinfop->slot_flags &= ~PCIHP_SLOT_ENUM_EXT_PENDING; 3444 return (rv); 3445 } 3446 3447 /* 3448 * This routine is called when a ENUM# caused by when an adapter insertion 3449 * is detected. If the occupant is successfully configured (i.e. PCI resources 3450 * successfully assigned, the blue LED is left off, otherwise if configuration 3451 * is not successful, the blue LED is illuminated. 3452 * Please note that the lock must be released before invoking the 3453 * generic AP configure function. 3454 */ 3455 static int 3456 pcihp_handle_enum_insertion(pcihp_t *pcihp_p, int pci_dev, int opcode, 3457 int kmflag) 3458 { 3459 struct pcihp_slotinfo *slotinfop; 3460 int rv = PCIHP_FAILURE; 3461 minor_t ap_minor; 3462 major_t ap_major; 3463 3464 slotinfop = &pcihp_p->slotinfo[pci_dev]; 3465 slotinfop->hs_csr_location = 0; 3466 /* we clear the interrupt here. This is a must here. */ 3467 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_SLOT_CONFIGURE); 3468 /* 3469 * disable further interrupt from this board till it is 3470 * configured. 3471 */ 3472 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_DISABLE_ENUM); 3473 if (opcode == PCIHP_CLEAR_ENUM) { 3474 slotinfop->slot_flags |= PCIHP_SLOT_ENUM_INS_PENDING; 3475 return (PCIHP_SUCCESS); 3476 } 3477 3478 if ((slotinfop->slot_flags & PCIHP_SLOT_AUTO_CFG_EN) == 3479 PCIHP_SLOT_AUTO_CFG_EN) { 3480 mutex_enter(&slotinfop->slot_mutex); 3481 rv = pcihp_configure_ap(pcihp_p, pci_dev); 3482 mutex_exit(&slotinfop->slot_mutex); 3483 if (rv != HPC_SUCCESS) { /* configure failed */ 3484 cmn_err(CE_NOTE, "%s%d: PCI device %x Failed on" 3485 " Configure", ddi_driver_name(pcihp_p->dip), 3486 ddi_get_instance(pcihp_p->dip), pci_dev); 3487 if (pcihp_cpci_blue_led) 3488 pcihp_hs_csr_op(pcihp_p, pci_dev, 3489 HPC_EVENT_SLOT_BLUE_LED_ON); 3490 } 3491 3492 /* pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_CLEAR_ENUM); */ 3493 pcihp_hs_csr_op(pcihp_p, pci_dev, HPC_EVENT_ENABLE_ENUM); 3494 3495 if (!rv) { 3496 ap_major = ddi_driver_major(pcihp_p->dip); 3497 ap_minor = PCIHP_AP_MINOR_NUM( 3498 ddi_get_instance(pcihp_p->dip), pci_dev); 3499 pcihp_create_occupant_props(pcihp_p->dip, 3500 makedevice(ap_major, ap_minor), pci_dev); 3501 3502 /* 3503 * Sys Event Notification. 3504 */ 3505 pcihp_gen_sysevent(slotinfop->name, 3506 PCIHP_DR_AP_STATE_CHANGE, 3507 SE_HINT_INSERT, pcihp_p->dip, kmflag); 3508 } 3509 3510 } else 3511 rv = PCIHP_SUCCESS; 3512 slotinfop->slot_flags &= ~PCIHP_SLOT_ENUM_INS_PENDING; 3513 return (rv); 3514 } 3515 3516 /* 3517 * Read the Hot Swap Control and Status Register (HS_CSR) and 3518 * place the result in the location pointed to be hs_csr. 3519 */ 3520 static int 3521 pcihp_get_hs_csr(struct pcihp_slotinfo *slotinfop, 3522 ddi_acc_handle_t config_handle, uint8_t *hs_csr) 3523 { 3524 if (slotinfop->hs_csr_location == -1) 3525 return (PCIHP_FAILURE); 3526 3527 if (slotinfop->hs_csr_location == 0) { 3528 slotinfop->hs_csr_location = 3529 pcihp_get_hs_csr_location(config_handle); 3530 3531 if (slotinfop->hs_csr_location == -1) 3532 return (PCIHP_FAILURE); 3533 } 3534 *hs_csr = pci_config_get8(config_handle, slotinfop->hs_csr_location); 3535 return (PCIHP_SUCCESS); 3536 } 3537 3538 /* 3539 * Write the Hot Swap Control and Status Register (HS_CSR) with 3540 * the value being pointed at by hs_csr. 3541 */ 3542 static void 3543 pcihp_set_hs_csr(struct pcihp_slotinfo *slotinfop, 3544 ddi_acc_handle_t config_handle, uint8_t *hs_csr) 3545 { 3546 if (slotinfop->hs_csr_location == -1) 3547 return; 3548 if (slotinfop->hs_csr_location == 0) { 3549 slotinfop->hs_csr_location = 3550 pcihp_get_hs_csr_location(config_handle); 3551 if (slotinfop->hs_csr_location == -1) 3552 return; 3553 } 3554 pci_config_put8(config_handle, slotinfop->hs_csr_location, *hs_csr); 3555 PCIHP_DEBUG((CE_NOTE, "hs_csr wrote %x, read %x", *hs_csr, 3556 pci_config_get8(config_handle, slotinfop->hs_csr_location))); 3557 } 3558 3559 static int 3560 pcihp_get_hs_csr_location(ddi_acc_handle_t config_handle) 3561 { 3562 uint8_t cap_id; 3563 uint_t cap_id_loc; 3564 uint16_t status; 3565 int location = -1; 3566 #define PCI_STAT_ECP_SUPP 0x10 3567 3568 /* 3569 * Need to check the Status register for ECP support first. 3570 * Also please note that for type 1 devices, the 3571 * offset could change. Should support type 1 next. 3572 */ 3573 status = pci_config_get16(config_handle, PCI_CONF_STAT); 3574 if (!(status & PCI_STAT_ECP_SUPP)) { 3575 PCIHP_DEBUG((CE_NOTE, "No Ext Capabilities for device\n")); 3576 return (-1); 3577 } 3578 cap_id_loc = pci_config_get8(config_handle, PCI_CONF_EXTCAP); 3579 3580 /* 3581 * Walk the list of capabilities, but don't walk past the end 3582 * of the Configuration Space Header. 3583 */ 3584 while ((cap_id_loc) && (cap_id_loc < PCI_CONF_HDR_SIZE)) { 3585 3586 cap_id = pci_config_get8(config_handle, cap_id_loc); 3587 3588 if (cap_id == CPCI_HOTSWAP_CAPID) { 3589 location = cap_id_loc + PCI_ECP_HS_CSR; 3590 break; 3591 } 3592 cap_id_loc = pci_config_get8(config_handle, 3593 cap_id_loc + 1); 3594 } 3595 return (location); 3596 } 3597 3598 static int 3599 pcihp_add_dummy_reg_property(dev_info_t *dip, 3600 uint_t bus, uint_t device, uint_t func) 3601 { 3602 pci_regspec_t dummy_reg; 3603 3604 bzero(&dummy_reg, sizeof (dummy_reg)); 3605 3606 dummy_reg.pci_phys_hi = PCIHP_MAKE_REG_HIGH(bus, device, func, 0); 3607 3608 return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 3609 "reg", (int *)&dummy_reg, sizeof (pci_regspec_t)/sizeof (int))); 3610 } 3611 3612 static void 3613 pcihp_hs_csr_op(pcihp_t *pcihp_p, int pci_dev, int event) 3614 { 3615 struct pcihp_slotinfo *slotinfop; 3616 ddi_acc_handle_t config_handle; 3617 dev_info_t *dip, *new_child = NULL; 3618 uint8_t hs_csr; 3619 int result; 3620 3621 slotinfop = &pcihp_p->slotinfo[pci_dev]; 3622 3623 if (pcihp_config_setup(&dip, &config_handle, &new_child, pci_dev, 3624 pcihp_p) != DDI_SUCCESS) { 3625 return; 3626 } 3627 3628 result = pcihp_get_hs_csr(slotinfop, config_handle, (uint8_t *)&hs_csr); 3629 if ((result != PCIHP_SUCCESS) || (event == -1)) { 3630 pcihp_config_teardown(&config_handle, &new_child, pci_dev, 3631 pcihp_p); 3632 return; 3633 } 3634 3635 hs_csr &= 0xf; 3636 switch (event) { 3637 case HPC_EVENT_SLOT_BLUE_LED_ON: 3638 hs_csr |= HS_CSR_LOO; 3639 break; 3640 case HPC_EVENT_SLOT_BLUE_LED_OFF: 3641 hs_csr &= ~HS_CSR_LOO; 3642 break; 3643 case HPC_EVENT_SLOT_CONFIGURE: 3644 hs_csr |= HS_CSR_INS; /* clear INS */ 3645 break; 3646 case HPC_EVENT_CLEAR_ENUM: 3647 hs_csr |= (HS_CSR_INS | HS_CSR_EXT); 3648 break; 3649 case HPC_EVENT_SLOT_UNCONFIGURE: 3650 hs_csr |= HS_CSR_EXT; /* clear EXT */ 3651 break; 3652 case HPC_EVENT_ENABLE_ENUM: 3653 hs_csr &= ~HS_CSR_EIM; 3654 break; 3655 case HPC_EVENT_DISABLE_ENUM: 3656 hs_csr |= HS_CSR_EIM; 3657 break; 3658 case HPC_EVENT_SLOT_NOT_HEALTHY: 3659 case HPC_EVENT_SLOT_HEALTHY_OK: 3660 default: 3661 break; 3662 } 3663 pcihp_set_hs_csr(slotinfop, config_handle, (uint8_t *)&hs_csr); 3664 pcihp_config_teardown(&config_handle, &new_child, pci_dev, pcihp_p); 3665 } 3666 3667 static int 3668 pcihp_config_setup(dev_info_t **dip, ddi_acc_handle_t *handle, 3669 dev_info_t **new_child, int pci_dev, pcihp_t *pcihp_p) 3670 { 3671 dev_info_t *pdip = pcihp_p->dip; 3672 int bus, len, rc = DDI_SUCCESS; 3673 struct pcihp_slotinfo *slotinfop; 3674 hpc_slot_state_t rstate; 3675 ddi_acc_hdl_t *hp; 3676 pci_bus_range_t pci_bus_range; 3677 3678 slotinfop = &pcihp_p->slotinfo[pci_dev]; 3679 3680 /* 3681 * If declared failed, don't allow Config operations. 3682 * Otherwise, if good or failing, it is assumed Ok 3683 * to get config data. 3684 */ 3685 if (slotinfop->condition == AP_COND_FAILED) { 3686 return (PCIHP_FAILURE); 3687 } 3688 /* 3689 * check to see if there is a hardware present first. 3690 * If no hardware present, no need to probe this slot. 3691 * We can do this first probably as a first step towards 3692 * safeguarding from accidental removal (we don't support it!). 3693 */ 3694 if (hpc_nexus_control(slotinfop->slot_hdl, HPC_CTRL_GET_SLOT_STATE, 3695 (caddr_t)&rstate) != 0) { 3696 return (DDI_FAILURE); 3697 } 3698 3699 if (rstate != HPC_SLOT_CONNECTED) { 3700 /* error. slot must be connected */ 3701 return (DDI_FAILURE); 3702 } 3703 *new_child = NULL; 3704 3705 /* 3706 * If there is no dip then we need to see if an 3707 * adapter has just been hot plugged. 3708 */ 3709 len = sizeof (pci_bus_range_t); 3710 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, pdip, 3711 0, "bus-range", 3712 (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) { 3713 3714 return (PCIHP_FAILURE); 3715 } 3716 3717 /* primary bus number of this bus node */ 3718 bus = pci_bus_range.lo; 3719 3720 if (ndi_devi_alloc(pdip, DEVI_PSEUDO_NEXNAME, 3721 (pnode_t)DEVI_SID_NODEID, dip) != NDI_SUCCESS) { 3722 3723 PCIHP_DEBUG((CE_NOTE, "Failed to alloc probe node\n")); 3724 return (PCIHP_FAILURE); 3725 } 3726 3727 if (pcihp_add_dummy_reg_property(*dip, bus, 3728 pci_dev, 0) != DDI_SUCCESS) { 3729 3730 (void) ndi_devi_free(*dip); 3731 return (PCIHP_FAILURE); 3732 } 3733 3734 /* 3735 * Probe for a device. Possibly a non (c)PCI board could be sitting 3736 * here which would never respond to PCI config cycles - in which 3737 * case we return. Eventually a configure operation would fail. 3738 */ 3739 if (pci_config_setup(*dip, handle) != DDI_SUCCESS) { 3740 cmn_err(CE_WARN, "Cannot set config space map for" 3741 " pci device number %d", pci_dev); 3742 (void) ndi_devi_free(*dip); 3743 return (PCIHP_FAILURE); 3744 } 3745 3746 /* 3747 * See if there is any PCI HW at this location 3748 * by reading the Vendor ID. If it returns with 0xffff 3749 * then there is no hardware at this location. 3750 */ 3751 if (pcihp_indirect_map(*dip) == DDI_SUCCESS) { 3752 if (pci_config_get16(*handle, 0) == 0xffff) { 3753 pci_config_teardown(handle); 3754 (void) ndi_devi_free(*dip); 3755 return (PCIHP_FAILURE); 3756 } 3757 } else { 3758 /* Check if mapping is OK */ 3759 hp = impl_acc_hdl_get(*handle); 3760 3761 if (ddi_peek16(*dip, (int16_t *)(hp->ah_addr), 3762 (int16_t *)0) != DDI_SUCCESS) { 3763 #ifdef DEBUG 3764 cmn_err(CE_WARN, "Cannot Map PCI config space for " 3765 "device number %d", pci_dev); 3766 #endif 3767 pci_config_teardown(handle); 3768 (void) ndi_devi_free(*dip); 3769 return (PCIHP_FAILURE); 3770 } 3771 } 3772 3773 *new_child = *dip; 3774 return (rc); 3775 3776 } 3777 3778 static void 3779 pcihp_config_teardown(ddi_acc_handle_t *handle, 3780 dev_info_t **new_child, int pci_dev, pcihp_t *pcihp_p) 3781 { 3782 struct pcihp_slotinfo *slotinfop = &pcihp_p->slotinfo[pci_dev]; 3783 3784 pci_config_teardown(handle); 3785 if (*new_child) { 3786 (void) ndi_devi_free(*new_child); 3787 /* 3788 * If occupant not configured, reset HS_CSR location 3789 * so that we reprobe. This covers cases where 3790 * the receptacle had a status change without a 3791 * notification to the framework. 3792 */ 3793 if (slotinfop->ostate != AP_OSTATE_CONFIGURED) 3794 slotinfop->hs_csr_location = 0; 3795 } 3796 } 3797 3798 static int 3799 pcihp_get_board_type(struct pcihp_slotinfo *slotinfop) 3800 { 3801 hpc_board_type_t board_type; 3802 3803 /* 3804 * Get board type data structure, hpc_board_type_t. 3805 */ 3806 if (hpc_nexus_control(slotinfop->slot_hdl, HPC_CTRL_GET_BOARD_TYPE, 3807 (caddr_t)&board_type) != 0) { 3808 3809 cmn_err(CE_WARN, "Cannot Get Board Type.."); 3810 return (-1); 3811 } 3812 3813 /* 3814 * We expect the Hotswap Controller to tell us if the board is 3815 * a hotswap board or not, as it probably cannot differentiate 3816 * between a basic hotswap board, a non hotswap board and a 3817 * hotswap nonfriendly board. 3818 * So here is the logic to differentiate between the various 3819 * types of cPCI boards. 3820 * In case if the HSC returns board type as unknown, we assign 3821 * the default board type as defined by a configurable variable 3822 * for a BHS, nonfriendly FHS and non HS board. 3823 */ 3824 if (slotinfop->slot_type & HPC_SLOT_TYPE_CPCI) { 3825 if (slotinfop->hs_csr_location > 0) 3826 board_type = HPC_BOARD_CPCI_FULL_HS; 3827 else { 3828 if (board_type == HPC_BOARD_CPCI_HS) { 3829 if (slotinfop->hs_csr_location == -1) 3830 board_type = HPC_BOARD_CPCI_BASIC_HS; 3831 } 3832 if (board_type == HPC_BOARD_UNKNOWN) { 3833 if (slotinfop->hs_csr_location == -1) { 3834 board_type = pcihp_cpci_board_type; 3835 } else if (slotinfop->hs_csr_location != 0) { 3836 board_type = HPC_BOARD_CPCI_FULL_HS; 3837 } 3838 } 3839 } 3840 /* 3841 * If board type is a non hotswap board, then we must 3842 * deny a unconfigure operation. So set this flag. 3843 * Strictly speaking, there is no reason not to disallow 3844 * a unconfigure operation on nonhotswap boards. But this 3845 * is the only way we can prevent a user from accidentally 3846 * removing the board and damaging it. 3847 */ 3848 if (board_type == HPC_BOARD_CPCI_NON_HS) 3849 slotinfop->slot_flags |= PCIHP_SLOT_DEV_NON_HOTPLUG; 3850 else 3851 slotinfop->slot_flags &= ~PCIHP_SLOT_DEV_NON_HOTPLUG; 3852 } 3853 return (board_type); 3854 } 3855 3856 3857 /* 3858 * Generate the System Event with a possible hint. 3859 */ 3860 static void 3861 pcihp_gen_sysevent(char *slot_name, int event_sub_class, int hint, 3862 dev_info_t *self, int kmflag) 3863 { 3864 3865 int err; 3866 char *ev_subclass = NULL; 3867 sysevent_id_t eid; 3868 nvlist_t *ev_attr_list = NULL; 3869 char attach_pnt[MAXPATHLEN]; 3870 3871 /* 3872 * Minor device name (AP) will be bus path 3873 * concatenated with slot name 3874 */ 3875 3876 (void) strcpy(attach_pnt, PCIHP_DEVICES_STR); 3877 (void) ddi_pathname(self, attach_pnt + strlen(PCIHP_DEVICES_STR)); 3878 (void) strcat(attach_pnt, ":"); 3879 (void) strcat(attach_pnt, slot_name); 3880 err = nvlist_alloc(&ev_attr_list, NV_UNIQUE_NAME_TYPE, kmflag); 3881 if (err != 0) { 3882 cmn_err(CE_WARN, 3883 "%s%d: Failed to allocate memory " 3884 "for event attributes%s", ddi_driver_name(self), 3885 ddi_get_instance(self), ESC_DR_AP_STATE_CHANGE); 3886 return; 3887 } 3888 3889 switch (event_sub_class) { 3890 3891 /* event sub class: ESC_DR_AP_STATE_CHANGE */ 3892 case PCIHP_DR_AP_STATE_CHANGE: 3893 3894 ev_subclass = ESC_DR_AP_STATE_CHANGE; 3895 3896 switch (hint) { 3897 3898 case SE_NO_HINT: /* fall through */ 3899 case SE_HINT_INSERT: /* fall through */ 3900 case SE_HINT_REMOVE: 3901 3902 3903 err = nvlist_add_string(ev_attr_list, DR_HINT, 3904 SE_HINT2STR(hint)); 3905 3906 if (err != 0) { 3907 cmn_err(CE_WARN, "%s%d: Failed to add attr [%s]" 3908 " for %s event", ddi_driver_name(self), 3909 ddi_get_instance(self), 3910 DR_HINT, ESC_DR_AP_STATE_CHANGE); 3911 nvlist_free(ev_attr_list); 3912 return; 3913 } 3914 break; 3915 3916 default: 3917 cmn_err(CE_WARN, "%s%d: Unknown hint on sysevent", 3918 ddi_driver_name(self), ddi_get_instance(self)); 3919 nvlist_free(ev_attr_list); 3920 return; 3921 } 3922 3923 break; 3924 3925 /* event sub class: ESC_DR_REQ */ 3926 case PCIHP_DR_REQ: 3927 3928 ev_subclass = ESC_DR_REQ; 3929 3930 switch (hint) { 3931 3932 case SE_INVESTIGATE_RES: /* fall through */ 3933 case SE_INCOMING_RES: /* fall through */ 3934 case SE_OUTGOING_RES: /* fall through */ 3935 3936 err = nvlist_add_string(ev_attr_list, DR_REQ_TYPE, 3937 SE_REQ2STR(hint)); 3938 3939 if (err != 0) { 3940 cmn_err(CE_WARN, 3941 "%s%d: Failed to add attr [%s] " 3942 "for %s event", ddi_driver_name(self), 3943 ddi_get_instance(self), 3944 DR_REQ_TYPE, ESC_DR_REQ); 3945 nvlist_free(ev_attr_list); 3946 return; 3947 } 3948 break; 3949 3950 default: 3951 cmn_err(CE_WARN, "%s%d: Unknown hint on sysevent", 3952 ddi_driver_name(self), ddi_get_instance(self)); 3953 nvlist_free(ev_attr_list); 3954 return; 3955 } 3956 3957 break; 3958 3959 default: 3960 cmn_err(CE_WARN, "%s%d: Unknown Event subclass", 3961 ddi_driver_name(self), ddi_get_instance(self)); 3962 nvlist_free(ev_attr_list); 3963 return; 3964 } 3965 3966 /* 3967 * Add attachment point as attribute (common attribute) 3968 */ 3969 3970 err = nvlist_add_string(ev_attr_list, DR_AP_ID, attach_pnt); 3971 3972 if (err != 0) { 3973 cmn_err(CE_WARN, "%s%d: Failed to add attr [%s] for %s event", 3974 ddi_driver_name(self), ddi_get_instance(self), 3975 DR_AP_ID, EC_DR); 3976 nvlist_free(ev_attr_list); 3977 return; 3978 } 3979 3980 3981 /* 3982 * Log this event with sysevent framework. 3983 */ 3984 3985 err = ddi_log_sysevent(self, DDI_VENDOR_SUNW, EC_DR, 3986 ev_subclass, ev_attr_list, &eid, 3987 ((kmflag == KM_SLEEP) ? DDI_SLEEP : DDI_NOSLEEP)); 3988 if (err != 0) { 3989 cmn_err(CE_WARN, "%s%d: Failed to log %s event", 3990 ddi_driver_name(self), ddi_get_instance(self), EC_DR); 3991 } 3992 3993 nvlist_free(ev_attr_list); 3994 } 3995 3996 int 3997 pcihp_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 3998 int flags, char *name, caddr_t valuep, int *lengthp) 3999 { 4000 int pci_dev; 4001 4002 if (dev == DDI_DEV_T_ANY) 4003 goto skip; 4004 4005 if (strcmp(name, "pci-occupant") == 0) { 4006 pci_dev = PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(getminor(dev)); 4007 pcihp_create_occupant_props(dip, dev, pci_dev); 4008 } 4009 /* other cases... */ 4010 skip: 4011 return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp)); 4012 } 4013 4014 /* 4015 * this function is called only for SPARC platforms, where we may have 4016 * a mix n' match of direct vs indirectly mapped configuration space. 4017 * On x86, this function should always return success since the configuration 4018 * space is always indirect mapped. 4019 */ 4020 /*ARGSUSED*/ 4021 static int 4022 pcihp_indirect_map(dev_info_t *dip) 4023 { 4024 #if defined(__sparc) 4025 int rc = DDI_FAILURE; 4026 4027 if (ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), 0, 4028 PCI_DEV_CONF_MAP_PROP, DDI_FAILURE) != DDI_FAILURE) 4029 rc = DDI_SUCCESS; 4030 else 4031 if (ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), 4032 0, PCI_BUS_CONF_MAP_PROP, DDI_FAILURE) != DDI_FAILURE) 4033 rc = DDI_SUCCESS; 4034 return (rc); 4035 #else 4036 return (DDI_SUCCESS); 4037 #endif 4038 } 4039