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