1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright (c)  * Copyright (c) 2001 Tadpole Technology plc
  28  * All rights reserved.
  29  * From "@(#)pcicfg.c   1.31    99/06/18 SMI"
  30  */
  31 
  32 /*
  33  * Cardbus hotplug module
  34  */
  35 
  36 #include <sys/open.h>
  37 #include <sys/file.h>
  38 #include <sys/stat.h>
  39 #include <sys/ddi.h>
  40 #include <sys/sunndi.h>
  41 
  42 #include <sys/note.h>
  43 
  44 #include <sys/pci.h>
  45 
  46 #include <sys/hotplug/hpcsvc.h>
  47 #include <sys/hotplug/pci/pcicfg.h>
  48 #include <sys/pcic_reg.h>
  49 
  50 #include "cardbus.h"
  51 #include "cardbus_hp.h"
  52 #include "cardbus_cfg.h"
  53 
  54 /*
  55  * ************************************************************************
  56  * *** Implementation specific data structures/definitions.             ***
  57  * ************************************************************************
  58  */
  59 
  60 #ifndef HPC_MAX_OCCUPANTS
  61 #define HPC_MAX_OCCUPANTS 8
  62 typedef struct hpc_occupant_info {
  63         int     i;
  64         char    *id[HPC_MAX_OCCUPANTS];
  65 } hpc_occupant_info_t;
  66 #endif
  67 
  68 #define PCICFG_FLAGS_CONTINUE   0x1
  69 
  70 #define PCICFG_OP_ONLINE        0x1
  71 #define PCICFG_OP_OFFLINE       0x0
  72 
  73 #define CBHP_DEVCTL_MINOR       255
  74 
  75 #define AP_MINOR_NUM_TO_CB_INSTANCE(x)  ((x) & 0xFF)
  76 #define AP_MINOR_NUM(x)         (((uint_t)(3) << 8) | ((x) & 0xFF))
  77 #define AP_IS_CB_MINOR(x)       (((x)>>8) == (3))
  78 
  79 extern int cardbus_debug;
  80 extern int number_of_cardbus_cards;
  81 
  82 static int cardbus_autocfg_enabled = 1; /* auto config is enabled by default */
  83 
  84 /* static functions */
  85 static int cardbus_event_handler(caddr_t slot_arg, uint_t event_mask);
  86 static int cardbus_pci_control(caddr_t ops_arg, hpc_slot_t slot_hdl,
  87                                 int request, caddr_t arg);
  88 static int cardbus_new_slot_state(dev_info_t *dip, hpc_slot_t hdl,
  89                                 hpc_slot_info_t *slot_info, int slot_state);
  90 static int cardbus_list_occupants(dev_info_t *dip, void *hdl);
  91 static void create_occupant_props(dev_info_t *self, dev_t dev);
  92 static void delete_occupant_props(dev_info_t *dip, dev_t dev);
  93 static int cardbus_configure_ap(cbus_t *cbp);
  94 static int cardbus_unconfigure_ap(cbus_t *cbp);
  95 static int cbus_unconfigure(dev_info_t *devi, int prim_bus);
  96 void cardbus_dump_pci_config(dev_info_t *dip);
  97 void cardbus_dump_pci_node(dev_info_t *dip);
  98 
  99 int
 100 cardbus_init_hotplug(cbus_t *cbp)
 101 {
 102         char tbuf[MAXNAMELEN];
 103         hpc_slot_info_t slot_info;
 104         hpc_slot_ops_t  *slot_ops;
 105         hpc_slot_t      slhandle;       /* HPS slot handle */
 106 
 107         /*
 108          *  register the bus instance with the HPS framework.
 109          */
 110         if (hpc_nexus_register_bus(cbp->cb_dip,
 111             cardbus_new_slot_state, 0) != 0) {
 112                 cmn_err(CE_WARN, "%s%d: failed to register the bus with HPS\n",
 113                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance);
 114                 return (DDI_FAILURE);
 115         }
 116 
 117         (void) sprintf(cbp->ap_id, "slot%d", cbp->cb_instance);
 118         (void) ddi_pathname(cbp->cb_dip, tbuf);
 119         cbp->nexus_path = kmem_alloc(strlen(tbuf) + 1, KM_SLEEP);
 120         (void) strcpy(cbp->nexus_path, tbuf);
 121         cardbus_err(cbp->cb_dip, 8,
 122             "cardbus_init_hotplug: nexus_path set to %s", cbp->nexus_path);
 123 
 124         slot_ops = hpc_alloc_slot_ops(KM_SLEEP);
 125         cbp->slot_ops = slot_ops;
 126 
 127         /*
 128          * Fill in the slot information structure that
 129          * describes the slot.
 130          */
 131         slot_info.version = HPC_SLOT_INFO_VERSION;
 132         slot_info.slot_type = HPC_SLOT_TYPE_PCI;
 133         slot_info.slot.pci.device_number = 0;
 134         slot_info.slot.pci.slot_capabilities = 0;
 135 
 136         (void) strcpy(slot_info.slot.pci.slot_logical_name, cbp->ap_id);
 137 
 138         slot_ops->hpc_version = HPC_SLOT_OPS_VERSION;
 139         slot_ops->hpc_op_connect = NULL;
 140         slot_ops->hpc_op_disconnect = NULL;
 141         slot_ops->hpc_op_insert = NULL;
 142         slot_ops->hpc_op_remove = NULL;
 143         slot_ops->hpc_op_control = cardbus_pci_control;
 144 
 145         if (hpc_slot_register(cbp->cb_dip, cbp->nexus_path, &slot_info,
 146             &slhandle, slot_ops, (caddr_t)cbp, 0) != 0) {
 147                 /*
 148                  * If the slot can not be registered,
 149                  * then the slot_ops need to be freed.
 150                  */
 151                 cmn_err(CE_WARN,
 152                     "cbp%d Unable to Register Slot %s", cbp->cb_instance,
 153                     slot_info.slot.pci.slot_logical_name);
 154 
 155                 (void) hpc_nexus_unregister_bus(cbp->cb_dip);
 156                 hpc_free_slot_ops(slot_ops);
 157                 cbp->slot_ops = NULL;
 158                 return (DDI_FAILURE);
 159         }
 160 
 161         ASSERT(slhandle == cbp->slot_handle);
 162 
 163         cardbus_err(cbp->cb_dip, 8,
 164             "cardbus_init_hotplug: slot_handle 0x%p", cbp->slot_handle);
 165         return (DDI_SUCCESS);
 166 }
 167 
 168 static int
 169 cardbus_event_handler(caddr_t slot_arg, uint_t event_mask)
 170 {
 171         int ap_minor = (int)((uintptr_t)slot_arg);
 172         cbus_t *cbp;
 173         int cb_instance;
 174         int rv = HPC_EVENT_CLAIMED;
 175 
 176         cb_instance = AP_MINOR_NUM_TO_CB_INSTANCE(ap_minor);
 177 
 178         ASSERT(cb_instance >= 0);
 179         cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
 180         mutex_enter(&cbp->cb_mutex);
 181 
 182         switch (event_mask) {
 183 
 184         case HPC_EVENT_SLOT_INSERTION:
 185                 /*
 186                  * A card is inserted in the slot. Just report this
 187                  * event and return.
 188                  */
 189                 cardbus_err(cbp->cb_dip, 7,
 190                     "cardbus_event_handler(%s%d): card is inserted",
 191                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance);
 192 
 193                 break;
 194 
 195         case HPC_EVENT_SLOT_CONFIGURE:
 196                 /*
 197                  * Configure the occupant that is just inserted in the slot.
 198                  * The receptacle may or may not be in the connected state. If
 199                  * the receptacle is not connected and the auto configuration
 200                  * is enabled on this slot then connect the slot. If auto
 201                  * configuration is enabled then configure the card.
 202                  */
 203                 if (!(cbp->auto_config)) {
 204                         /*
 205                          * auto configuration is disabled.
 206                          */
 207                         cardbus_err(cbp->cb_dip, 7,
 208                             "cardbus_event_handler(%s%d): "
 209                             "SLOT_CONFIGURE event occured (slot %s)",
 210                             ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 211                             cbp->name);
 212 
 213                         break;
 214                 }
 215 
 216                 cardbus_err(cbp->cb_dip, 7,
 217                     "cardbus_event_handler(%s%d): configure event",
 218                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance);
 219 
 220                 if (cbp->ostate != AP_OSTATE_UNCONFIGURED) {
 221                         cmn_err(CE_WARN, "!slot%d already configured\n",
 222                             cbp->cb_instance);
 223                         break;
 224                 }
 225 
 226                 /*
 227                  * Auto configuration is enabled. First, make sure the
 228                  * receptacle is in the CONNECTED state.
 229                  */
 230                 if ((rv = hpc_nexus_connect(cbp->slot_handle,
 231                     NULL, 0)) == HPC_SUCCESS) {
 232                         cbp->rstate = AP_RSTATE_CONNECTED; /* record rstate */
 233                 }
 234 
 235                 if (cardbus_configure_ap(cbp) == HPC_SUCCESS)
 236                         create_occupant_props(cbp->cb_dip, makedevice(
 237                             ddi_driver_major((cbp->cb_dip)), ap_minor));
 238                 else
 239                         rv = HPC_ERR_FAILED;
 240 
 241                 break;
 242 
 243         case HPC_EVENT_SLOT_UNCONFIGURE:
 244                 /*
 245                  * Unconfigure the occupant in this slot.
 246                  */
 247                 if (!(cbp->auto_config)) {
 248                         /*
 249                          * auto configuration is disabled.
 250                          */
 251                         cardbus_err(cbp->cb_dip, 7,
 252                             "cardbus_event_handler(%s%d): "
 253                             "SLOT_UNCONFIGURE event"
 254                             " occured - auto-conf disabled (slot %s)",
 255                             ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 256                             cbp->name);
 257 
 258                         break;
 259                 }
 260 
 261                 cardbus_err(cbp->cb_dip, 7,
 262                     "cardbus_event_handler(%s%d): SLOT_UNCONFIGURE event"
 263                     " occured (slot %s)",
 264                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 265                     cbp->name);
 266 
 267                 if (cardbus_unconfigure_ap(cbp) != HPC_SUCCESS)
 268                         rv = HPC_ERR_FAILED;
 269 
 270                 DEVI(cbp->cb_dip)->devi_ops->devo_bus_ops = cbp->orig_bopsp;
 271                 --number_of_cardbus_cards;
 272                 break;
 273 
 274         case HPC_EVENT_SLOT_REMOVAL:
 275                 /*
 276                  * Card is removed from the slot. The card must have been
 277                  * unconfigured before this event.
 278                  */
 279                 if (cbp->ostate != AP_OSTATE_UNCONFIGURED) {
 280                         cardbus_err(cbp->cb_dip, 1,
 281                             "cardbus_event_handler(%s%d): "
 282                             "card is removed from"
 283                             " the slot %s before doing unconfigure!!",
 284                             ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 285                             cbp->name);
 286 
 287                         break;
 288                 }
 289 
 290                 cardbus_err(cbp->cb_dip, 7,
 291                     "cardbus_event_handler(%s%d): "
 292                     "card is removed from the slot %s",
 293                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 294                     cbp->name);
 295 
 296                 break;
 297 
 298         case HPC_EVENT_SLOT_POWER_ON:
 299                 /*
 300                  * Slot is connected to the bus. i.e the card is powered
 301                  * on.
 302                  */
 303                 cardbus_err(cbp->cb_dip, 7,
 304                     "cardbus_event_handler(%s%d): "
 305                     "card is powered on in the slot %s",
 306                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 307                     cbp->name);
 308 
 309                 cbp->rstate = AP_RSTATE_CONNECTED; /* record rstate */
 310 
 311                 break;
 312 
 313         case HPC_EVENT_SLOT_POWER_OFF:
 314                 /*
 315                  * Slot is disconnected from the bus. i.e the card is powered
 316                  * off.
 317                  */
 318                 cardbus_err(cbp->cb_dip, 7,
 319                     "cardbus_event_handler(%s%d): "
 320                     "card is powered off in the slot %s",
 321                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 322                     cbp->name);
 323 
 324                 cbp->rstate = AP_RSTATE_DISCONNECTED; /* record rstate */
 325 
 326                 break;
 327 
 328         default:
 329                 cardbus_err(cbp->cb_dip, 4,
 330                     "cardbus_event_handler(%s%d): "
 331                     "unknown event %x for this slot %s",
 332                     ddi_driver_name(cbp->cb_dip), cbp->cb_instance,
 333                     event_mask, cbp->name);
 334 
 335                 break;
 336         }
 337 
 338         mutex_exit(&cbp->cb_mutex);
 339 
 340         return (rv);
 341 }
 342 
 343 static int
 344 cardbus_pci_control(caddr_t ops_arg, hpc_slot_t slot_hdl, int request,
 345                         caddr_t arg)
 346 {
 347         cbus_t *cbp;
 348         int rval = HPC_SUCCESS;
 349         hpc_led_info_t *hpc_led_info;
 350 
 351         _NOTE(ARGUNUSED(slot_hdl))
 352 
 353         cbp = (cbus_t *)ops_arg;
 354         ASSERT(mutex_owned(&cbp->cb_mutex));
 355 
 356         switch (request) {
 357 
 358         case HPC_CTRL_GET_SLOT_STATE: {
 359                 hpc_slot_state_t        *hpc_slot_state;
 360 
 361                 hpc_slot_state = (hpc_slot_state_t *)arg;
 362 
 363                 cardbus_err(cbp->cb_dip, 7,
 364                     "cardbus_pci_control() - "
 365                     "HPC_CTRL_GET_SLOT_STATE hpc_slot_state=0x%p",
 366                     (void *) hpc_slot_state);
 367 
 368                 if (cbp->card_present)
 369                         *hpc_slot_state = HPC_SLOT_CONNECTED;
 370                 else
 371                         *hpc_slot_state = HPC_SLOT_EMPTY;
 372 
 373                 break;
 374         }
 375 
 376         case HPC_CTRL_GET_BOARD_TYPE: {
 377                 hpc_board_type_t        *hpc_board_type;
 378 
 379                 hpc_board_type = (hpc_board_type_t *)arg;
 380 
 381                 cardbus_err(cbp->cb_dip, 7,
 382                     "cardbus_pci_control() - HPC_CTRL_GET_BOARD_TYPE");
 383 
 384                 /*
 385                  * The HPC driver does not know what board type
 386                  * is plugged in.
 387                  */
 388                 *hpc_board_type = HPC_BOARD_PCI_HOTPLUG;
 389 
 390                 break;
 391         }
 392 
 393         case HPC_CTRL_DEV_CONFIGURED:
 394         case HPC_CTRL_DEV_UNCONFIGURED:
 395                 cardbus_err(cbp->cb_dip, 5,
 396                     "cardbus_pci_control() - HPC_CTRL_DEV_%sCONFIGURED",
 397                     request == HPC_CTRL_DEV_UNCONFIGURED ? "UN" : "");
 398                 break;
 399 
 400         case HPC_CTRL_GET_LED_STATE:
 401                 hpc_led_info = (hpc_led_info_t *)arg;
 402                 cardbus_err(cbp->cb_dip, 5,
 403                     "cardbus_pci_control() - HPC_CTRL_GET_LED_STATE "
 404                     "led %d is %d",
 405                     hpc_led_info->led, cbp->leds[hpc_led_info->led]);
 406 
 407                 hpc_led_info->state = cbp->leds[hpc_led_info->led];
 408                 break;
 409 
 410         case HPC_CTRL_SET_LED_STATE:
 411                 hpc_led_info = (hpc_led_info_t *)arg;
 412 
 413                 cardbus_err(cbp->cb_dip, 4,
 414                     "cardbus_pci_control() - HPC_CTRL_SET_LED_STATE "
 415                     "led %d to %d",
 416                     hpc_led_info->led, hpc_led_info->state);
 417 
 418                 cbp->leds[hpc_led_info->led] = hpc_led_info->state;
 419                 break;
 420 
 421         case HPC_CTRL_ENABLE_AUTOCFG:
 422                 cardbus_err(cbp->cb_dip, 5,
 423                     "cardbus_pci_control() - HPC_CTRL_ENABLE_AUTOCFG");
 424 
 425                 /*
 426                  * Cardbus ALWAYS does auto config, from the slots point of
 427                  * view this is turning on the card and making sure it's ok.
 428                  * This is all done by the bridge driver before we see any
 429                  * indication.
 430                  */
 431                 break;
 432 
 433         case HPC_CTRL_DISABLE_AUTOCFG:
 434                 cardbus_err(cbp->cb_dip, 5,
 435                     "cardbus_pci_control() - HPC_CTRL_DISABLE_AUTOCFG");
 436                 break;
 437 
 438         case HPC_CTRL_DISABLE_ENUM:
 439         case HPC_CTRL_ENABLE_ENUM:
 440         default:
 441                 rval = HPC_ERR_NOTSUPPORTED;
 442                 break;
 443         }
 444 
 445         return (rval);
 446 }
 447 
 448 /*
 449  * cardbus_new_slot_state()
 450  *
 451  * This function is called by the HPS when it finds a hot plug
 452  * slot is added or being removed from the hot plug framework.
 453  * It returns 0 for success and HPC_ERR_FAILED for errors.
 454  */
 455 static int
 456 cardbus_new_slot_state(dev_info_t *dip, hpc_slot_t hdl,
 457                         hpc_slot_info_t *slot_info, int slot_state)
 458 {
 459         int cb_instance;
 460         cbus_t *cbp;
 461         int ap_minor;
 462         int rv = 0;
 463 
 464         cardbus_err(dip, 8,
 465             "cardbus_new_slot_state: slot_handle 0x%p", hdl);
 466 
 467         /*
 468          * get the soft state structure for the bus instance.
 469          */
 470         cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 471             DDI_PROP_DONTPASS, "cbus-instance", -1);
 472         ASSERT(cb_instance >= 0);
 473         cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
 474 
 475         mutex_enter(&cbp->cb_mutex);
 476 
 477         switch (slot_state) {
 478 
 479         case HPC_SLOT_ONLINE:
 480                 /*
 481                  * Make sure the slot is not already ONLINE
 482                  */
 483                 if (cbp->slot_handle != NULL) {
 484                         cardbus_err(dip, 4,
 485                             "cardbus_new_slot_state: "
 486                             "cardbus already ONLINE!!");
 487                         rv = HPC_ERR_FAILED;
 488                         break;
 489                 }
 490 
 491                 /*
 492                  * Add the hot plug slot to the bus.
 493                  */
 494 
 495                 /* create the AP minor node */
 496                 ap_minor = AP_MINOR_NUM(cb_instance);
 497                 if (ddi_create_minor_node(dip, slot_info->pci_slot_name,
 498                     S_IFCHR, ap_minor,
 499                     DDI_NT_PCI_ATTACHMENT_POINT,
 500                     0) == DDI_FAILURE) {
 501                         cardbus_err(dip, 4,
 502                             "cardbus_new_slot_state: "
 503                             "ddi_create_minor_node failed");
 504                         rv = HPC_ERR_FAILED;
 505                         break;
 506                 }
 507 
 508                 /* save the slot handle */
 509                 cbp->slot_handle = hdl;
 510 
 511                 /* setup event handler for all hardware events on the slot */
 512                 if (hpc_install_event_handler(hdl, -1, cardbus_event_handler,
 513                     (caddr_t)((long)ap_minor)) != 0) {
 514                         cardbus_err(dip, 4,
 515                             "cardbus_new_slot_state: "
 516                             "install event handler failed");
 517                         rv = HPC_ERR_FAILED;
 518                         break;
 519                 }
 520                 cbp->event_mask = (uint32_t)0xFFFFFFFF;
 521                 create_occupant_props(dip,
 522                     makedevice(ddi_name_to_major(ddi_get_name(dip)),
 523                     ap_minor));
 524 
 525                 /* set default auto configuration enabled flag for this slot */
 526                 cbp->auto_config = cardbus_autocfg_enabled;
 527 
 528                 /* copy the slot information */
 529                 cbp->name = (char *)kmem_alloc(strlen(slot_info->pci_slot_name)
 530                     + 1, KM_SLEEP);
 531                 (void) strcpy(cbp->name, slot_info->pci_slot_name);
 532                 cardbus_err(cbp->cb_dip, 10,
 533                     "cardbus_new_slot_state: cbp->name set to %s", cbp->name);
 534 
 535                 cardbus_err(dip, 4,
 536                     "Cardbus slot \"%s\" ONLINE\n", slot_info->pci_slot_name);
 537 
 538                 cbp->ostate = AP_OSTATE_UNCONFIGURED;
 539                 cbp->rstate = AP_RSTATE_EMPTY;
 540 
 541                 break;
 542 
 543         case HPC_SLOT_OFFLINE:
 544                 /*
 545                  * A hot plug slot is being removed from the bus.
 546                  * Make sure there is no occupant configured on the
 547                  * slot before removing the AP minor node.
 548                  */
 549                 if (cbp->ostate != AP_OSTATE_UNCONFIGURED) {
 550                         cmn_err(CE_WARN,
 551                             "cardbus: Card is still in configured state");
 552                         rv = HPC_ERR_FAILED;
 553                         break;
 554                 }
 555 
 556                 /*
 557                  * If the AP device is in open state then return
 558                  * error.
 559                  */
 560                 if (cbp->soft_state != PCIHP_SOFT_STATE_CLOSED) {
 561                         rv = HPC_ERR_FAILED;
 562                         break;
 563                 }
 564 
 565                 /* remove the minor node */
 566                 ddi_remove_minor_node(dip, cbp->name);
 567                 /* free up the memory for the name string */
 568                 kmem_free(cbp->name, strlen(cbp->name) + 1);
 569 
 570                 /* update the slot info data */
 571                 cbp->name = NULL;
 572                 cbp->slot_handle = NULL;
 573 
 574                 cardbus_err(dip, 6,
 575                     "cardbus_new_slot_state: Cardbus slot OFFLINE");
 576                 break;
 577 
 578         default:
 579                 cmn_err(CE_WARN,
 580                     "cardbus_new_slot_state: unknown slot_state %d\n",
 581                     slot_state);
 582                 rv = HPC_ERR_FAILED;
 583         }
 584 
 585         mutex_exit(&cbp->cb_mutex);
 586 
 587         return (rv);
 588 }
 589 
 590 static int
 591 cardbus_list_occupants(dev_info_t *dip, void *hdl)
 592 {
 593         hpc_occupant_info_t *occupant = (hpc_occupant_info_t *)hdl;
 594         char pn[MAXPATHLEN];
 595 
 596         /*
 597          * Ignore the attachment point and pcs.
 598          */
 599         if (strcmp(ddi_binding_name(dip), "pcs") == 0) {
 600                 return (DDI_WALK_CONTINUE);
 601         }
 602 
 603         (void) ddi_pathname(dip, pn);
 604 
 605         occupant->id[occupant->i] = kmem_alloc(strlen(pn) + 1, KM_SLEEP);
 606         (void) strcpy(occupant->id[occupant->i], pn);
 607 
 608         occupant->i++;
 609 
 610         /*
 611          * continue the walk to the next sibling to look for a match
 612          * or to find other nodes if this card is a multi-function card.
 613          */
 614         return (DDI_WALK_PRUNECHILD);
 615 }
 616 
 617 static void
 618 create_occupant_props(dev_info_t *self, dev_t dev)
 619 {
 620         hpc_occupant_info_t occupant;
 621         int i;
 622         int circular;
 623 
 624         occupant.i = 0;
 625 
 626         ndi_devi_enter(self, &circular);
 627         ddi_walk_devs(ddi_get_child(self), cardbus_list_occupants,
 628             (void *)&occupant);
 629         ndi_devi_exit(self, circular);
 630 
 631         if (occupant.i == 0) {
 632                 char *c[] = { "" };
 633                 cardbus_err(self, 1, "create_occupant_props: no occupant\n");
 634                 (void) ddi_prop_update_string_array(dev, self, "pci-occupant",
 635                     c, 1);
 636         } else {
 637                 cardbus_err(self, 1,
 638                     "create_occupant_props: %d occupant\n", occupant.i);
 639                 (void) ddi_prop_update_string_array(dev, self, "pci-occupant",
 640                     occupant.id, occupant.i);
 641         }
 642 
 643         for (i = 0; i < occupant.i; i++) {
 644                 kmem_free(occupant.id[i], strlen(occupant.id[i]) + 1);
 645         }
 646 }
 647 
 648 static void
 649 delete_occupant_props(dev_info_t *dip, dev_t dev)
 650 {
 651         if (ddi_prop_remove(dev, dip, "pci-occupant")
 652             != DDI_PROP_SUCCESS)
 653                 return; /* add error handling */
 654 
 655 }
 656 
 657 /*
 658  * **************************************
 659  * CONFIGURE the occupant in the slot.
 660  * **************************************
 661  */
 662 static int
 663 cardbus_configure_ap(cbus_t *cbp)
 664 {
 665         dev_info_t *self = cbp->cb_dip;
 666         int rv = HPC_SUCCESS;
 667         hpc_slot_state_t rstate;
 668         struct cardbus_config_ctrl ctrl;
 669         int circular_count;
 670 
 671         /*
 672          * check for valid request:
 673          *  1. It is a hotplug slot.
 674          *  2. The receptacle is in the CONNECTED state.
 675          */
 676         if (cbp->slot_handle == NULL || cbp->disabled) {
 677                 return (ENXIO);
 678         }
 679 
 680         /*
 681          * If the occupant is already in (partially) configured
 682          * state then call the ndi_devi_online() on the device
 683          * subtree(s) for this attachment point.
 684          */
 685 
 686         if (cbp->ostate == AP_OSTATE_CONFIGURED) {
 687                 ctrl.flags = PCICFG_FLAGS_CONTINUE;
 688                 ctrl.busno = cardbus_primary_busno(self);
 689                 ctrl.rv = NDI_SUCCESS;
 690                 ctrl.dip = NULL;
 691                 ctrl.op = PCICFG_OP_ONLINE;
 692 
 693                 ndi_devi_enter(self, &circular_count);
 694                 ddi_walk_devs(ddi_get_child(self),
 695                     cbus_configure, (void *)&ctrl);
 696                 ndi_devi_exit(self, circular_count);
 697 
 698                 if (cardbus_debug) {
 699                         cardbus_dump_pci_config(self);
 700                         cardbus_dump_pci_node(self);
 701                 }
 702 
 703                 if (ctrl.rv != NDI_SUCCESS) {
 704                         /*
 705                          * one or more of the devices are not
 706                          * onlined.
 707                          */
 708                         cmn_err(CE_WARN, "cardbus(%s%d): failed to attach "
 709                             "one or more drivers for the card in the slot %s",
 710                             ddi_driver_name(self), cbp->cb_instance,
 711                             cbp->name);
 712                 }
 713 
 714                 /* tell HPC driver that the occupant is configured */
 715                 (void) hpc_nexus_control(cbp->slot_handle,
 716                     HPC_CTRL_DEV_CONFIGURED, NULL);
 717                 return (rv);
 718         }
 719 
 720         /*
 721          * Occupant is in the UNCONFIGURED state.
 722          */
 723 
 724         /* Check if the receptacle is in the CONNECTED state. */
 725         if (hpc_nexus_control(cbp->slot_handle,
 726             HPC_CTRL_GET_SLOT_STATE, (caddr_t)&rstate) != 0) {
 727                 return (ENXIO);
 728         }
 729 
 730         if (rstate != HPC_SLOT_CONNECTED) {
 731                 /* error. either the slot is empty or connect failed */
 732                 return (ENXIO);
 733         }
 734 
 735         cbp->rstate = AP_RSTATE_CONNECTED; /* record rstate */
 736 
 737         /*
 738          * Call the configurator to configure the card.
 739          */
 740         if (cardbus_configure(cbp) != PCICFG_SUCCESS) {
 741                 return (EIO);
 742         }
 743 
 744         /* record the occupant state as CONFIGURED */
 745         cbp->ostate = AP_OSTATE_CONFIGURED;
 746         cbp->condition = AP_COND_OK;
 747 
 748         /* now, online all the devices in the AP */
 749         ctrl.flags = PCICFG_FLAGS_CONTINUE;
 750         ctrl.busno = cardbus_primary_busno(self);
 751         ctrl.rv = NDI_SUCCESS;
 752         ctrl.dip = NULL;
 753         ctrl.op = PCICFG_OP_ONLINE;
 754 
 755         ndi_devi_enter(self, &circular_count);
 756         ddi_walk_devs(ddi_get_child(self), cbus_configure, (void *)&ctrl);
 757         ndi_devi_exit(self, circular_count);
 758 
 759         if (cardbus_debug) {
 760                 cardbus_dump_pci_config(self);
 761                 cardbus_dump_pci_node(self);
 762         }
 763         if (ctrl.rv != NDI_SUCCESS) {
 764                 /*
 765                  * one or more of the devices are not
 766                  * ONLINE'd.
 767                  */
 768                 cmn_err(CE_WARN, "cbhp (%s%d): failed to attach one or"
 769                     " more drivers for the card in the slot %s",
 770                     ddi_driver_name(cbp->cb_dip),
 771                     cbp->cb_instance, cbp->name);
 772                 /* rv = EFAULT; */
 773         }
 774 
 775         /* tell HPC driver that the occupant is configured */
 776         (void) hpc_nexus_control(cbp->slot_handle,
 777             HPC_CTRL_DEV_CONFIGURED, NULL);
 778 
 779         return (rv);
 780 }
 781 
 782 /*
 783  * **************************************
 784  * UNCONFIGURE the occupant in the slot.
 785  * **************************************
 786  */
 787 static int
 788 cardbus_unconfigure_ap(cbus_t *cbp)
 789 {
 790         dev_info_t *self = cbp->cb_dip;
 791         int rv = HPC_SUCCESS, nrv;
 792 
 793         /*
 794          * check for valid request:
 795          *  1. It is a hotplug slot.
 796          *  2. The occupant is in the CONFIGURED state.
 797          */
 798 
 799         if (cbp->slot_handle == NULL || cbp->disabled) {
 800                 return (ENXIO);
 801         }
 802 
 803         /*
 804          * If the occupant is in the CONFIGURED state then
 805          * call the configurator to unconfigure the slot.
 806          */
 807         if (cbp->ostate == AP_OSTATE_CONFIGURED) {
 808                 /*
 809                  * Detach all the drivers for the devices in the
 810                  * slot.
 811                  */
 812                 nrv = cardbus_unconfigure_node(self,
 813                     cardbus_primary_busno(self),
 814                     B_TRUE);
 815 
 816                 if (nrv != NDI_SUCCESS) {
 817                         /*
 818                          * Failed to detach one or more drivers.
 819                          * Restore the status for the drivers
 820                          * which are offlined during this step.
 821                          */
 822                         cmn_err(CE_WARN,
 823                             "cbhp (%s%d): Failed to offline all devices"
 824                             " (slot %s)", ddi_driver_name(cbp->cb_dip),
 825                             cbp->cb_instance, cbp->name);
 826                         rv = EBUSY;
 827                 } else {
 828 
 829                         if (cardbus_unconfigure(cbp) == PCICFG_SUCCESS) {
 830                                 /*
 831                                  * Now that resources are freed,
 832                                  * clear EXT and Turn LED ON.
 833                                  */
 834                                 cbp->ostate = AP_OSTATE_UNCONFIGURED;
 835                                 cbp->condition = AP_COND_UNKNOWN;
 836                                 /*
 837                                  * send the notification of state change
 838                                  * to the HPC driver.
 839                                  */
 840                                 (void) hpc_nexus_control(cbp->slot_handle,
 841                                     HPC_CTRL_DEV_UNCONFIGURED, NULL);
 842                         } else {
 843                                 rv = EIO;
 844                         }
 845                 }
 846         }
 847 
 848         return (rv);
 849 }
 850 
 851 int
 852 cbus_configure(dev_info_t *dip, void *hdl)
 853 {
 854         pci_regspec_t *pci_rp;
 855         int length, rc;
 856         struct cardbus_config_ctrl *ctrl = (struct cardbus_config_ctrl *)hdl;
 857         uint8_t bus, device, function;
 858 
 859         /*
 860          * Ignore the attachment point and pcs.
 861          */
 862         if (strcmp(ddi_binding_name(dip), "hp_attachment") == 0 ||
 863             strcmp(ddi_binding_name(dip), "pcs") == 0) {
 864                 cardbus_err(dip, 8, "cbus_configure: Ignoring\n");
 865                 return (DDI_WALK_CONTINUE);
 866         }
 867 
 868         cardbus_err(dip, 6, "cbus_configure\n");
 869 
 870         ASSERT(ctrl->op == PCICFG_OP_ONLINE);
 871 
 872         /*
 873          * Get the PCI device number information from the devinfo
 874          * node. Since the node may not have the address field
 875          * setup (this is done in the DDI_INITCHILD of the parent)
 876          * we look up the 'reg' property to decode that information.
 877          */
 878         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
 879             DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
 880             (uint_t *)&length) != DDI_PROP_SUCCESS) {
 881                 /* Porbably not a real device, like PCS for example */
 882                 if (ddi_get_child(dip) == NULL)
 883                         return (DDI_WALK_PRUNECHILD);
 884 
 885                 cardbus_err(dip, 1, "cubs_configure: Don't configure device\n");
 886                 ctrl->rv = DDI_FAILURE;
 887                 ctrl->dip = dip;
 888                 return (DDI_WALK_TERMINATE);
 889         }
 890 
 891         if (pci_rp->pci_phys_hi == 0)
 892                 return (DDI_WALK_CONTINUE);
 893 
 894         /* get the pci device id information */
 895         bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
 896         device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
 897         function = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
 898 
 899         /*
 900          * free the memory allocated by ddi_prop_lookup_int_array
 901          */
 902         ddi_prop_free(pci_rp);
 903 
 904         if (bus <= ctrl->busno)
 905                 return (DDI_WALK_CONTINUE);
 906 
 907         cardbus_err(dip, 8,
 908             "cbus_configure on-line device at: "
 909             "[0x%x][0x%x][0x%x]\n", bus, device, function);
 910 
 911         rc = ndi_devi_online(dip, NDI_ONLINE_ATTACH|NDI_CONFIG);
 912 
 913         cardbus_err(dip, 7,
 914             "cbus_configure %s\n",
 915             rc == NDI_SUCCESS ? "Success": "Failure");
 916 
 917         if (rc != NDI_SUCCESS)
 918                 return (DDI_WALK_PRUNECHILD);
 919 
 920         return (DDI_WALK_CONTINUE);
 921 }
 922 
 923 int
 924 cardbus_unconfigure_node(dev_info_t *dip, int prim_bus, boolean_t top_bridge)
 925 {
 926         dev_info_t *child, *next;
 927 
 928         cardbus_err(dip, 6, "cardbus_unconfigure_node\n");
 929 
 930         /*
 931          * Ignore pcs.
 932          */
 933         if (strcmp(ddi_binding_name(dip), "pcs") == 0) {
 934                 cardbus_err(dip, 8, "cardbus_unconfigure_node: Ignoring\n");
 935                 return (NDI_SUCCESS);
 936         }
 937 
 938         /*
 939          * bottom up off-line
 940          */
 941         for (child = ddi_get_child(dip); child; child = next) {
 942                 int rc;
 943                 next = ddi_get_next_sibling(child);
 944                 rc = cardbus_unconfigure_node(child, prim_bus, B_FALSE);
 945                 if (rc != NDI_SUCCESS)
 946                         return (rc);
 947         }
 948 
 949         /*
 950          * Don't unconfigure the bridge itself.
 951          */
 952         if (top_bridge)
 953                 return (NDI_SUCCESS);
 954 
 955         if (cbus_unconfigure(dip, prim_bus) != NDI_SUCCESS) {
 956                 cardbus_err(dip, 1,
 957                     "cardbus_unconfigure_node: cardbus_unconfigure failed\n");
 958                 return (NDI_FAILURE);
 959         }
 960         return (NDI_SUCCESS);
 961 }
 962 
 963 /*
 964  * This will turn  resources allocated by cbus_configure()
 965  * and remove the device tree from the attachment point
 966  * and below.  The routine assumes the devices have their
 967  * drivers detached.
 968  */
 969 static int
 970 cbus_unconfigure(dev_info_t *devi, int prim_bus)
 971 {
 972         pci_regspec_t *pci_rp;
 973         uint_t bus, device, func, length;
 974         int ndi_flags = NDI_UNCONFIG;
 975 
 976         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, devi,
 977             DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
 978             &length) != DDI_PROP_SUCCESS) {
 979                 /*
 980                  * This cannot be one of our devices. If it's something like a
 981                  * SCSI device then the attempt to offline the HBA
 982                  * (which probably is one of our devices)
 983                  * will also do bottom up offlining. That
 984                  * will fail if this device is busy. So always
 985                  * return success here
 986                  * so that the walk will continue.
 987                  */
 988                 return (NDI_SUCCESS);
 989         }
 990 
 991         if (pci_rp->pci_phys_hi == 0)
 992                 return (NDI_FAILURE);
 993 
 994         bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
 995 
 996         if (bus <= prim_bus)
 997                 return (NDI_SUCCESS);
 998 
 999         device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1000         func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1001         ddi_prop_free(pci_rp);
1002 
1003         cardbus_err(devi, 8,
1004             "cbus_unconfigure: "
1005             "offline bus [0x%x] device [0x%x] function [%x]\n",
1006             bus, device, func);
1007         if (ndi_devi_offline(devi, ndi_flags) != NDI_SUCCESS) {
1008                 cardbus_err(devi, 1,
1009                     "Device [0x%x] function [%x] is busy\n", device, func);
1010                 return (NDI_FAILURE);
1011         }
1012 
1013         cardbus_err(devi, 9,
1014             "Tearing down device [0x%x] function [0x%x]\n", device, func);
1015 
1016         if (cardbus_teardown_device(devi) != PCICFG_SUCCESS) {
1017                 cardbus_err(devi, 1,
1018                     "Failed to tear down "
1019                     "device [0x%x] function [0x%x]\n", device, func);
1020                 return (NDI_FAILURE);
1021         }
1022 
1023         return (NDI_SUCCESS);
1024 }
1025 
1026 boolean_t
1027 cardbus_is_cb_minor(dev_t dev)
1028 {
1029         return (AP_IS_CB_MINOR(getminor(dev)) ? B_TRUE : B_FALSE);
1030 }
1031 
1032 int
1033 cardbus_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1034 {
1035         cbus_t *cbp;
1036         int minor;
1037 
1038         _NOTE(ARGUNUSED(credp))
1039 
1040         minor = getminor(*devp);
1041 
1042         /*
1043          * Make sure the open is for the right file type.
1044          */
1045         if (otyp != OTYP_CHR)
1046         return (EINVAL);
1047 
1048         /*
1049          * Get the soft state structure for the 'devctl' device.
1050          */
1051         cbp = (cbus_t *)ddi_get_soft_state(cardbus_state,
1052             AP_MINOR_NUM_TO_CB_INSTANCE(minor));
1053         if (cbp == NULL)
1054                 return (ENXIO);
1055 
1056         mutex_enter(&cbp->cb_mutex);
1057 
1058         /*
1059          * Handle the open by tracking the device state.
1060          *
1061          * Note: Needs review w.r.t exclusive access to AP or the bus.
1062          * Currently in the pci plug-in we don't use EXCL open at all
1063          * so the code below implements EXCL access on the bus.
1064          */
1065 
1066         /* enforce exclusive access to the bus */
1067         if ((cbp->soft_state == PCIHP_SOFT_STATE_OPEN_EXCL) ||
1068             ((flags & FEXCL) &&
1069             (cbp->soft_state != PCIHP_SOFT_STATE_CLOSED))) {
1070                 mutex_exit(&cbp->cb_mutex);
1071                 return (EBUSY);
1072         }
1073 
1074         if (flags & FEXCL)
1075                 cbp->soft_state = PCIHP_SOFT_STATE_OPEN_EXCL;
1076         else
1077                 cbp->soft_state = PCIHP_SOFT_STATE_OPEN;
1078 
1079         mutex_exit(&cbp->cb_mutex);
1080         return (0);
1081 }
1082 
1083 /*ARGSUSED*/
1084 int
1085 cardbus_close(dev_t dev, int flags, int otyp, cred_t *credp)
1086 {
1087         cbus_t *cbp;
1088         int minor;
1089 
1090         _NOTE(ARGUNUSED(credp))
1091 
1092         minor = getminor(dev);
1093 
1094         if (otyp != OTYP_CHR)
1095                 return (EINVAL);
1096 
1097         cbp = (cbus_t *)ddi_get_soft_state(cardbus_state,
1098             AP_MINOR_NUM_TO_CB_INSTANCE(minor));
1099         if (cbp == NULL)
1100                 return (ENXIO);
1101 
1102         mutex_enter(&cbp->cb_mutex);
1103         cbp->soft_state = PCIHP_SOFT_STATE_CLOSED;
1104         mutex_exit(&cbp->cb_mutex);
1105         return (0);
1106 }
1107 
1108 /*
1109  * cardbus_ioctl: devctl hotplug controls
1110  */
1111 /*ARGSUSED*/
1112 int
1113 cardbus_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1114                 int *rvalp)
1115 {
1116         cbus_t *cbp;
1117         dev_info_t *self;
1118         dev_info_t *child_dip = NULL;
1119         struct devctl_iocdata *dcp;
1120         uint_t bus_state;
1121         int rv = 0;
1122         int nrv = 0;
1123         int ap_minor;
1124         hpc_slot_state_t rstate;
1125         devctl_ap_state_t ap_state;
1126         struct hpc_control_data hpc_ctrldata;
1127         struct hpc_led_info led_info;
1128 
1129         _NOTE(ARGUNUSED(credp))
1130 
1131         ap_minor = getminor(dev);
1132         cbp = (cbus_t *)ddi_get_soft_state(cardbus_state,
1133             AP_MINOR_NUM_TO_CB_INSTANCE(ap_minor));
1134         if (cbp == NULL)
1135                 return (ENXIO);
1136 
1137         self = cbp->cb_dip;
1138         /*
1139          * read devctl ioctl data
1140          */
1141         if ((cmd != DEVCTL_AP_CONTROL) && ndi_dc_allochdl((void *)arg,
1142             &dcp) != NDI_SUCCESS)
1143                 return (EFAULT);
1144 
1145 #ifdef CARDBUS_DEBUG
1146 {
1147         char *cmd_name;
1148 
1149         switch (cmd) {
1150         case DEVCTL_DEVICE_GETSTATE: cmd_name = "DEVCTL_DEVICE_GETSTATE"; break;
1151         case DEVCTL_DEVICE_ONLINE: cmd_name = "DEVCTL_DEVICE_ONLINE"; break;
1152         case DEVCTL_DEVICE_OFFLINE: cmd_name = "DEVCTL_DEVICE_OFFLINE"; break;
1153         case DEVCTL_DEVICE_RESET: cmd_name = "DEVCTL_DEVICE_RESET"; break;
1154         case DEVCTL_BUS_QUIESCE: cmd_name = "DEVCTL_BUS_QUIESCE"; break;
1155         case DEVCTL_BUS_UNQUIESCE: cmd_name = "DEVCTL_BUS_UNQUIESCE"; break;
1156         case DEVCTL_BUS_RESET: cmd_name = "DEVCTL_BUS_RESET"; break;
1157         case DEVCTL_BUS_RESETALL: cmd_name = "DEVCTL_BUS_RESETALL"; break;
1158         case DEVCTL_BUS_GETSTATE: cmd_name = "DEVCTL_BUS_GETSTATE"; break;
1159         case DEVCTL_AP_CONNECT: cmd_name = "DEVCTL_AP_CONNECT"; break;
1160         case DEVCTL_AP_DISCONNECT: cmd_name = "DEVCTL_AP_DISCONNECT"; break;
1161         case DEVCTL_AP_INSERT: cmd_name = "DEVCTL_AP_INSERT"; break;
1162         case DEVCTL_AP_REMOVE: cmd_name = "DEVCTL_AP_REMOVE"; break;
1163         case DEVCTL_AP_CONFIGURE: cmd_name = "DEVCTL_AP_CONFIGURE"; break;
1164         case DEVCTL_AP_UNCONFIGURE: cmd_name = "DEVCTL_AP_UNCONFIGURE"; break;
1165         case DEVCTL_AP_GETSTATE: cmd_name = "DEVCTL_AP_GETSTATE"; break;
1166         case DEVCTL_AP_CONTROL: cmd_name = "DEVCTL_AP_CONTROL"; break;
1167         default: cmd_name = "Unknown"; break;
1168         }
1169         cardbus_err(cbp->cb_dip, 7,
1170             "cardbus_ioctl: cmd = 0x%x, \"%s\"", cmd, cmd_name);
1171 }
1172 #endif
1173 
1174         switch (cmd) {
1175         case DEVCTL_DEVICE_GETSTATE:
1176         case DEVCTL_DEVICE_ONLINE:
1177         case DEVCTL_DEVICE_OFFLINE:
1178         case DEVCTL_BUS_GETSTATE:
1179                 rv = ndi_devctl_ioctl(self, cmd, arg, mode, 0);
1180                 ndi_dc_freehdl(dcp);
1181                 return (rv);
1182         default:
1183                 break;
1184         }
1185 
1186         switch (cmd) {
1187         case DEVCTL_DEVICE_RESET:
1188                 rv = ENOTSUP;
1189                 break;
1190 
1191         case DEVCTL_BUS_QUIESCE:
1192                 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1193                         if (bus_state == BUS_QUIESCED)
1194                                 break;
1195                 (void) ndi_set_bus_state(self, BUS_QUIESCED);
1196                 break;
1197 
1198         case DEVCTL_BUS_UNQUIESCE:
1199                 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1200                         if (bus_state == BUS_ACTIVE)
1201                                 break;
1202                 (void) ndi_set_bus_state(self, BUS_ACTIVE);
1203                 break;
1204 
1205         case DEVCTL_BUS_RESET:
1206                 rv = ENOTSUP;
1207                 break;
1208 
1209         case DEVCTL_BUS_RESETALL:
1210                 rv = ENOTSUP;
1211                 break;
1212 
1213         case DEVCTL_AP_CONNECT:
1214         case DEVCTL_AP_DISCONNECT:
1215                 /*
1216                  * CONNECT(DISCONNECT) the hot plug slot to(from) the bus.
1217                  */
1218         case DEVCTL_AP_INSERT:
1219         case DEVCTL_AP_REMOVE:
1220                 /*
1221                  * Prepare the slot for INSERT/REMOVE operation.
1222                  */
1223 
1224                 /*
1225                  * check for valid request:
1226                  *      1. It is a hotplug slot.
1227                  *      2. The slot has no occupant that is in
1228                  *      the 'configured' state.
1229                  *
1230                  * The lower 8 bits of the minor number is the PCI
1231                  * device number for the slot.
1232                  */
1233                 if ((cbp->slot_handle == NULL) || cbp->disabled) {
1234                         rv = ENXIO;
1235                         break;
1236                 }
1237 
1238                 /* the slot occupant must be in the UNCONFIGURED state */
1239                 if (cbp->ostate != AP_OSTATE_UNCONFIGURED) {
1240                         rv = EINVAL;
1241                         break;
1242                 }
1243 
1244                 /*
1245                  * Call the HPC driver to perform the operation on the slot.
1246                  */
1247                 mutex_enter(&cbp->cb_mutex);
1248                 switch (cmd) {
1249                 case DEVCTL_AP_INSERT:
1250                         rv = hpc_nexus_insert(cbp->slot_handle, NULL, 0);
1251                         break;
1252                 case DEVCTL_AP_REMOVE:
1253                         rv = hpc_nexus_remove(cbp->slot_handle, NULL, 0);
1254                         break;
1255                 case DEVCTL_AP_CONNECT:
1256                         if ((rv = hpc_nexus_connect(cbp->slot_handle,
1257                             NULL, 0)) == 0)
1258                                 cbp->rstate = AP_RSTATE_CONNECTED;
1259                         break;
1260                 case DEVCTL_AP_DISCONNECT:
1261                         if ((rv = hpc_nexus_disconnect(cbp->slot_handle,
1262                             NULL, 0)) == 0)
1263                                 cbp->rstate = AP_RSTATE_DISCONNECTED;
1264                         break;
1265                 }
1266                 mutex_exit(&cbp->cb_mutex);
1267 
1268                 switch (rv) {
1269                 case HPC_ERR_INVALID:
1270                         rv = ENXIO;
1271                         break;
1272                 case HPC_ERR_NOTSUPPORTED:
1273                         rv = ENOTSUP;
1274                         break;
1275                 case HPC_ERR_FAILED:
1276                         rv = EIO;
1277                         break;
1278                 }
1279 
1280                 break;
1281 
1282         case DEVCTL_AP_CONFIGURE:
1283                 /*
1284                  * **************************************
1285                  * CONFIGURE the occupant in the slot.
1286                  * **************************************
1287                  */
1288 
1289                 mutex_enter(&cbp->cb_mutex);
1290                 if ((nrv = cardbus_configure_ap(cbp)) == HPC_SUCCESS) {
1291                         create_occupant_props(cbp->cb_dip, dev);
1292                 } else
1293                         rv = nrv;
1294                 mutex_exit(&cbp->cb_mutex);
1295                 break;
1296 
1297         case DEVCTL_AP_UNCONFIGURE:
1298                 /*
1299                  * **************************************
1300                  * UNCONFIGURE the occupant in the slot.
1301                  * **************************************
1302                  */
1303 
1304                 mutex_enter(&cbp->cb_mutex);
1305                 if ((nrv = cardbus_unconfigure_ap(cbp)) == HPC_SUCCESS) {
1306                         delete_occupant_props(cbp->cb_dip, dev);
1307                 } else
1308                         rv = nrv;
1309                 mutex_exit(&cbp->cb_mutex);
1310                 break;
1311 
1312         case DEVCTL_AP_GETSTATE:
1313             {
1314                 int mutex_held;
1315 
1316                 /*
1317                  * return the state of Attachment Point.
1318                  *
1319                  * If the occupant is in UNCONFIGURED state then
1320                  * we should get the receptacle state from the
1321                  * HPC driver because the receptacle state
1322                  * maintained in the nexus may not be accurate.
1323                  */
1324 
1325                 /*
1326                  * check for valid request:
1327                  *      1. It is a hotplug slot.
1328                  */
1329                 if (cbp->slot_handle == NULL) {
1330                         rv = ENXIO;
1331                         break;
1332                 }
1333 
1334                 /* try to acquire the slot mutex */
1335                 mutex_held = mutex_tryenter(&cbp->cb_mutex);
1336 
1337                 if (cbp->ostate == AP_OSTATE_UNCONFIGURED) {
1338                         if (hpc_nexus_control(cbp->slot_handle,
1339                             HPC_CTRL_GET_SLOT_STATE,
1340                             (caddr_t)&rstate) != 0) {
1341                                 rv = ENXIO;
1342                                 if (mutex_held)
1343                                         mutex_exit(&cbp->cb_mutex);
1344                                 break;
1345                         }
1346                         cbp->rstate = (ap_rstate_t)rstate;
1347                 }
1348 
1349                 ap_state.ap_rstate = cbp->rstate;
1350                 ap_state.ap_ostate = cbp->ostate;
1351                 ap_state.ap_condition = cbp->condition;
1352                 ap_state.ap_last_change = 0;
1353                 ap_state.ap_error_code = 0;
1354                 if (mutex_held)
1355                         ap_state.ap_in_transition = 0; /* AP is not busy */
1356                 else
1357                         ap_state.ap_in_transition = 1; /* AP is busy */
1358 
1359                 if (mutex_held)
1360                         mutex_exit(&cbp->cb_mutex);
1361 
1362                 /* copy the return-AP-state information to the user space */
1363                 if (ndi_dc_return_ap_state(&ap_state, dcp) != NDI_SUCCESS)
1364                         rv = ENXIO;
1365 
1366                 break;
1367 
1368             }
1369 
1370         case DEVCTL_AP_CONTROL:
1371                 /*
1372                  * HPC control functions:
1373                  *      HPC_CTRL_ENABLE_SLOT/HPC_CTRL_DISABLE_SLOT
1374                  *              Changes the state of the slot and preserves
1375                  *              the state across the reboot.
1376                  *      HPC_CTRL_ENABLE_AUTOCFG/HPC_CTRL_DISABLE_AUTOCFG
1377                  *              Enables or disables the auto configuration
1378                  *              of hot plugged occupant if the hardware
1379                  *              supports notification of the hot plug
1380                  *              events.
1381                  *      HPC_CTRL_GET_LED_STATE/HPC_CTRL_SET_LED_STATE
1382                  *              Controls the state of an LED.
1383                  *      HPC_CTRL_GET_SLOT_INFO
1384                  *              Get slot information data structure
1385                  *              (hpc_slot_info_t).
1386                  *      HPC_CTRL_GET_BOARD_TYPE
1387                  *              Get board type information (hpc_board_type_t).
1388                  *      HPC_CTRL_GET_CARD_INFO
1389                  *              Get card information (hpc_card_info_t).
1390                  *
1391                  * These control functions are used by the cfgadm plug-in
1392                  * to implement "-x" and "-v" options.
1393                  */
1394 
1395                 /* copy user ioctl data first */
1396 #ifdef _MULTI_DATAMODEL
1397                 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1398                         struct hpc_control32_data hpc_ctrldata32;
1399 
1400                         if (copyin((void *)arg, (void *)&hpc_ctrldata32,
1401                             sizeof (struct hpc_control32_data)) != 0) {
1402                                 rv = EFAULT;
1403                                 break;
1404                         }
1405                         hpc_ctrldata.cmd = hpc_ctrldata32.cmd;
1406                         hpc_ctrldata.data =
1407                             (void *)(intptr_t)hpc_ctrldata32.data;
1408                 }
1409 #else
1410                 if (copyin((void *)arg, (void *)&hpc_ctrldata,
1411                     sizeof (struct hpc_control_data)) != 0) {
1412                         rv = EFAULT;
1413                         break;
1414                 }
1415 #endif
1416 
1417 #ifdef CARDBUS_DEBUG
1418 {
1419                 char *hpc_name;
1420                 switch (hpc_ctrldata.cmd) {
1421                 case HPC_CTRL_GET_LED_STATE:
1422                         hpc_name = "HPC_CTRL_GET_LED_STATE";
1423                         break;
1424                 case HPC_CTRL_SET_LED_STATE:
1425                         hpc_name = "HPC_CTRL_SET_LED_STATE";
1426                         break;
1427                 case HPC_CTRL_ENABLE_SLOT:
1428                         hpc_name = "HPC_CTRL_ENABLE_SLOT";
1429                         break;
1430                 case HPC_CTRL_DISABLE_SLOT:
1431                         hpc_name = "HPC_CTRL_DISABLE_SLOT";
1432                         break;
1433                 case HPC_CTRL_ENABLE_AUTOCFG:
1434                         hpc_name = "HPC_CTRL_ENABLE_AUTOCFG";
1435                         break;
1436                 case HPC_CTRL_DISABLE_AUTOCFG:
1437                         hpc_name = "HPC_CTRL_DISABLE_AUTOCFG";
1438                         break;
1439                 case HPC_CTRL_GET_BOARD_TYPE:
1440                         hpc_name = "HPC_CTRL_GET_BOARD_TYPE";
1441                         break;
1442                 case HPC_CTRL_GET_SLOT_INFO:
1443                         hpc_name = "HPC_CTRL_GET_SLOT_INFO";
1444                         break;
1445                 case HPC_CTRL_GET_CARD_INFO:
1446                         hpc_name = "HPC_CTRL_GET_CARD_INFO";
1447                         break;
1448                 default: hpc_name = "Unknown"; break;
1449                 }
1450                 cardbus_err(cbp->cb_dip, 7,
1451                     "cardbus_ioctl: HP Control cmd 0x%x - \"%s\"",
1452                     hpc_ctrldata.cmd, hpc_name);
1453 }
1454 #endif
1455                 /*
1456                  * check for valid request:
1457                  *      1. It is a hotplug slot.
1458                  */
1459                 if (cbp->slot_handle == NULL) {
1460                         rv = ENXIO;
1461                         break;
1462                 }
1463 
1464                 mutex_enter(&cbp->cb_mutex);
1465                 switch (hpc_ctrldata.cmd) {
1466                 case HPC_CTRL_GET_LED_STATE:
1467                         /* copy the led info from the user space */
1468                         if (copyin(hpc_ctrldata.data, (void *)&led_info,
1469                             sizeof (hpc_led_info_t)) != 0) {
1470                                 rv = ENXIO;
1471                                 break;
1472                         }
1473 
1474                         /* get the state of LED information */
1475                         if (hpc_nexus_control(cbp->slot_handle,
1476                             HPC_CTRL_GET_LED_STATE,
1477                             (caddr_t)&led_info) != 0) {
1478                                 rv = ENXIO;
1479                                 break;
1480                         }
1481 
1482                         /* copy the led info to the user space */
1483                         if (copyout((void *)&led_info, hpc_ctrldata.data,
1484                             sizeof (hpc_led_info_t)) != 0) {
1485                                 rv = ENXIO;
1486                                 break;
1487                         }
1488                         break;
1489 
1490                 case HPC_CTRL_SET_LED_STATE:
1491                         /* copy the led info from the user space */
1492                         if (copyin(hpc_ctrldata.data, (void *)&led_info,
1493                             sizeof (hpc_led_info_t)) != 0) {
1494                                 rv = ENXIO;
1495                                 break;
1496                         }
1497 
1498                         /* set the state of an LED */
1499                         if (hpc_nexus_control(cbp->slot_handle,
1500                             HPC_CTRL_SET_LED_STATE,
1501                             (caddr_t)&led_info) != 0) {
1502                                 rv = ENXIO;
1503                                 break;
1504                         }
1505 
1506                         break;
1507 
1508                 case HPC_CTRL_ENABLE_SLOT:
1509                         /*
1510                          * Enable the slot for hotplug operations.
1511                          */
1512                         cbp->disabled = B_FALSE;
1513 
1514                         /* tell the HPC driver also */
1515                         (void) hpc_nexus_control(cbp->slot_handle,
1516                                 HPC_CTRL_ENABLE_SLOT, NULL);
1517 
1518                         break;
1519 
1520                 case HPC_CTRL_DISABLE_SLOT:
1521                         /*
1522                          * Disable the slot for hotplug operations.
1523                          */
1524                         cbp->disabled = B_TRUE;
1525 
1526                         /* tell the HPC driver also */
1527                         (void) hpc_nexus_control(cbp->slot_handle,
1528                                 HPC_CTRL_DISABLE_SLOT, NULL);
1529 
1530                         break;
1531 
1532                 case HPC_CTRL_ENABLE_AUTOCFG:
1533                         /*
1534                          * Enable auto configuration on this slot.
1535                          */
1536                         cbp->auto_config = B_TRUE;
1537 
1538                         /* tell the HPC driver also */
1539                         (void) hpc_nexus_control(cbp->slot_handle,
1540                                 HPC_CTRL_ENABLE_AUTOCFG, NULL);
1541                         break;
1542 
1543                 case HPC_CTRL_DISABLE_AUTOCFG:
1544                         /*
1545                          * Disable auto configuration on this slot.
1546                          */
1547                         cbp->auto_config = B_FALSE;
1548 
1549                         /* tell the HPC driver also */
1550                         (void) hpc_nexus_control(cbp->slot_handle,
1551                                 HPC_CTRL_DISABLE_AUTOCFG, NULL);
1552 
1553                         break;
1554 
1555                 case HPC_CTRL_GET_BOARD_TYPE:
1556                     {
1557                         hpc_board_type_t board_type;
1558 
1559                         /*
1560                          * Get board type data structure, hpc_board_type_t.
1561                          */
1562                         if (hpc_nexus_control(cbp->slot_handle,
1563                             HPC_CTRL_GET_BOARD_TYPE,
1564                             (caddr_t)&board_type) != 0) {
1565                                 rv = ENXIO;
1566                                 break;
1567                         }
1568 
1569                         /* copy the board type info to the user space */
1570                         if (copyout((void *)&board_type, hpc_ctrldata.data,
1571                             sizeof (hpc_board_type_t)) != 0) {
1572                                 rv = ENXIO;
1573                                 break;
1574                         }
1575 
1576                         break;
1577                     }
1578 
1579                 case HPC_CTRL_GET_SLOT_INFO:
1580                     {
1581                         hpc_slot_info_t slot_info;
1582 
1583                         /*
1584                          * Get slot information structure, hpc_slot_info_t.
1585                          */
1586                         slot_info.version = HPC_SLOT_INFO_VERSION;
1587                         slot_info.slot_type = 0;
1588                         slot_info.pci_slot_capabilities = 0;
1589                         slot_info.pci_dev_num =
1590                                 (uint16_t)AP_MINOR_NUM_TO_CB_INSTANCE(ap_minor);
1591                         (void) strcpy(slot_info.pci_slot_name, cbp->name);
1592 
1593                         /* copy the slot info structure to the user space */
1594                         if (copyout((void *)&slot_info, hpc_ctrldata.data,
1595                             sizeof (hpc_slot_info_t)) != 0) {
1596                                 rv = ENXIO;
1597                                 break;
1598                         }
1599 
1600                         break;
1601                     }
1602 
1603                 case HPC_CTRL_GET_CARD_INFO:
1604                     {
1605                         hpc_card_info_t card_info;
1606                         ddi_acc_handle_t handle;
1607 
1608                         /*
1609                          * Get card information structure, hpc_card_info_t.
1610                          */
1611 
1612                         if (cbp->card_present == B_FALSE) {
1613                                 rv = ENXIO;
1614                                 break;
1615                         }
1616                         /* verify that the card is configured */
1617                         if (cbp->ostate != AP_OSTATE_CONFIGURED) {
1618                                 /* either the card is not present or */
1619                                 /* it is not configured. */
1620                                 rv = ENXIO;
1621                                 break;
1622                         }
1623 
1624                         /* get the information from the PCI config header */
1625                         /* for the function 0. */
1626                         for (child_dip = ddi_get_child(cbp->cb_dip); child_dip;
1627                             child_dip = ddi_get_next_sibling(child_dip))
1628                                 if (strcmp("pcs", ddi_get_name(child_dip)))
1629                                         break;
1630 
1631                         if (!child_dip) {
1632                                 rv = ENXIO;
1633                                 break;
1634                         }
1635 
1636                         if (pci_config_setup(child_dip, &handle)
1637                             != DDI_SUCCESS) {
1638                                 rv = EIO;
1639                                 break;
1640                         }
1641                         card_info.prog_class = pci_config_get8(handle,
1642                                                         PCI_CONF_PROGCLASS);
1643                         card_info.base_class = pci_config_get8(handle,
1644                                                         PCI_CONF_BASCLASS);
1645                         card_info.sub_class = pci_config_get8(handle,
1646                                                         PCI_CONF_SUBCLASS);
1647                         card_info.header_type = pci_config_get8(handle,
1648                                                         PCI_CONF_HEADER);
1649                         pci_config_teardown(&handle);
1650 
1651                         /* copy the card info structure to the user space */
1652                         if (copyout((void *)&card_info, hpc_ctrldata.data,
1653                             sizeof (hpc_card_info_t)) != 0) {
1654                                 rv = ENXIO;
1655                                 break;
1656                         }
1657 
1658                         break;
1659                     }
1660 
1661                 default:
1662                         rv = EINVAL;
1663                         break;
1664                 }
1665 
1666                 mutex_exit(&cbp->cb_mutex);
1667                 break;
1668 
1669         default:
1670                 rv = ENOTTY;
1671         }
1672 
1673         if (cmd != DEVCTL_AP_CONTROL)
1674                 ndi_dc_freehdl(dcp);
1675 
1676         cardbus_err(cbp->cb_dip, 7,
1677             "cardbus_ioctl: rv = 0x%x", rv);
1678 
1679         return (rv);
1680 }
1681 
1682 struct cardbus_pci_desc {
1683         char    *name;
1684         ushort_t        offset;
1685         int     (*cfg_get_func)();
1686         char    *fmt;
1687 };
1688 
1689 static struct cardbus_pci_desc generic_pci_cfg[] = {
1690             { "VendorId    =", 0, (int(*)())pci_config_get16, "%s 0x%04x" },
1691             { "DeviceId    =", 2, (int(*)())pci_config_get16, "%s 0x%04x" },
1692             { "Command     =", 4, (int(*)())pci_config_get16, "%s 0x%04x" },
1693             { "Status      =", 6, (int(*)())pci_config_get16, "%s 0x%04x" },
1694             { "Latency     =", 0xd, (int(*)())pci_config_get8, "%s 0x%02x" },
1695             { "BASE0       =", 0x10, (int(*)())pci_config_get32, "%s 0x%08x" },
1696             { "BASE1       =", 0x14, (int(*)())pci_config_get32, "%s 0x%08x" },
1697             { "BASE2       =", 0x18, (int(*)())pci_config_get32, "%s 0x%08x" },
1698             { "BASE3       =", 0x1c, (int(*)())pci_config_get32, "%s 0x%08x" },
1699             { "BASE4       =", 0x20, (int(*)())pci_config_get32, "%s 0x%08x" },
1700             { "CIS Pointer =", 0x28, (int(*)())pci_config_get32, "%s 0x%08x" },
1701             { "ILINE       =", 0x3c, (int(*)())pci_config_get8, "%s 0x%02x" },
1702             { "IPIN        =", 0x3d, (int(*)())pci_config_get8, "%s 0x%02x" },
1703             { NULL, 0, NULL, NULL }
1704 };
1705 
1706 static struct cardbus_pci_desc cardbus_pci_cfg[] = {
1707             { "VendorId    =", 0, (int(*)())pci_config_get16, "%s 0x%04x" },
1708             { "DeviceId    =", 2, (int(*)())pci_config_get16, "%s 0x%04x" },
1709             { "Command     =", 4, (int(*)())pci_config_get16, "%s 0x%04x" },
1710             { "Status      =", 6, (int(*)())pci_config_get16, "%s 0x%04x" },
1711             { "CacheLineSz =", 0xc, (int(*)())pci_config_get8, "%s 0x%02x" },
1712             { "Latency     =", 0xd, (int(*)())pci_config_get8, "%s 0x%02x" },
1713             { "MemBase Addr=", 0x10, (int(*)())pci_config_get32, "%s 0x%08x" },
1714             { "Pri Bus     =", 0x18, (int(*)())pci_config_get8, "%s 0x%02x" },
1715             { "Sec Bus     =", 0x19, (int(*)())pci_config_get8, "%s 0x%02x" },
1716             { "Sub Bus     =", 0x1a, (int(*)())pci_config_get8, "%s 0x%02x" },
1717             { "CBus Latency=", 0x1b, (int(*)())pci_config_get8, "%s 0x%02x" },
1718             { "Mem0 Base   =", 0x1c, (int(*)())pci_config_get32, "%s 0x%08x" },
1719             { "Mem0 Limit  =", 0x20, (int(*)())pci_config_get32, "%s 0x%08x" },
1720             { "Mem1 Base   =", 0x24, (int(*)())pci_config_get32, "%s 0x%08x" },
1721             { "Mem1 Limit  =", 0x28, (int(*)())pci_config_get32, "%s 0x%08x" },
1722             { "I/O0 Base   =", 0x2c, (int(*)())pci_config_get32, "%s 0x%08x" },
1723             { "I/O0 Limit  =", 0x30, (int(*)())pci_config_get32, "%s 0x%08x" },
1724             { "I/O1 Base   =", 0x34, (int(*)())pci_config_get32, "%s 0x%08x" },
1725             { "I/O1 Limit  =", 0x38, (int(*)())pci_config_get32, "%s 0x%08x" },
1726             { "ILINE       =", 0x3c, (int(*)())pci_config_get8, "%s 0x%02x" },
1727             { "IPIN        =", 0x3d, (int(*)())pci_config_get8, "%s 0x%02x" },
1728             { "Bridge Ctrl =", 0x3e, (int(*)())pci_config_get16, "%s 0x%04x" },
1729             { "Legacy Addr =", 0x44, (int(*)())pci_config_get32, "%s 0x%08x" },
1730             { NULL, 0, NULL, NULL }
1731 };
1732 
1733 static void
1734 cardbus_dump(struct cardbus_pci_desc *spcfg, ddi_acc_handle_t handle)
1735 {
1736         int     i;
1737         for (i = 0; spcfg[i].name; i++) {
1738 
1739                 cmn_err(CE_NOTE, spcfg[i].fmt, spcfg[i].name,
1740                     spcfg[i].cfg_get_func(handle, spcfg[i].offset));
1741         }
1742 
1743 }
1744 
1745 void
1746 cardbus_dump_pci_node(dev_info_t *dip)
1747 {
1748         dev_info_t *next;
1749         struct cardbus_pci_desc *spcfg;
1750         ddi_acc_handle_t config_handle;
1751         uint32_t VendorId;
1752 
1753         cmn_err(CE_NOTE, "\nPCI leaf node of dip 0x%p:\n", (void *)dip);
1754         for (next = ddi_get_child(dip); next;
1755             next = ddi_get_next_sibling(next)) {
1756 
1757                 VendorId = ddi_getprop(DDI_DEV_T_ANY, next,
1758                     DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS,
1759                     "vendor-id", -1);
1760                 if (VendorId == -1) {
1761                         /* not a pci device */
1762                         continue;
1763                 }
1764 
1765                 if (pci_config_setup(next, &config_handle) != DDI_SUCCESS) {
1766                         cmn_err(CE_WARN, "!pcic child: non pci device\n");
1767                         continue;
1768                 }
1769 
1770                 spcfg = generic_pci_cfg;
1771                 cardbus_dump(spcfg, config_handle);
1772                 pci_config_teardown(&config_handle);
1773 
1774         }
1775 
1776 }
1777 
1778 void
1779 cardbus_dump_pci_config(dev_info_t *dip)
1780 {
1781         struct cardbus_pci_desc *spcfg;
1782         ddi_acc_handle_t config_handle;
1783 
1784         if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
1785                 cmn_err(CE_WARN,
1786                     "!pci_config_setup() failed on 0x%p", (void *)dip);
1787                 return;
1788         }
1789 
1790         spcfg = cardbus_pci_cfg;
1791         cardbus_dump(spcfg, config_handle);
1792 
1793         pci_config_teardown(&config_handle);
1794 }
1795 
1796 void
1797 cardbus_dump_socket(dev_info_t *dip)
1798 {
1799         ddi_acc_handle_t        iohandle;
1800         caddr_t         ioaddr;
1801         ddi_device_acc_attr_t attr;
1802         attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1803         attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
1804         attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1805         if (ddi_regs_map_setup(dip, 1,
1806             (caddr_t *)&ioaddr,
1807             0,
1808             4096,
1809             &attr, &iohandle) != DDI_SUCCESS) {
1810                 cmn_err(CE_WARN, "Failed to map address for 0x%p", (void *)dip);
1811                 return;
1812         }
1813 
1814         cmn_err(CE_NOTE, "////////////////////////////////////////");
1815         cmn_err(CE_NOTE, "SOCKET_EVENT  = [0x%x]",
1816             ddi_get32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_EVENT)));
1817         cmn_err(CE_NOTE, "SOCKET_MASK   = [0x%x]",
1818             ddi_get32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_MASK)));
1819         cmn_err(CE_NOTE, "SOCKET_STATE  = [0x%x]",
1820             ddi_get32(iohandle, (uint32_t *)(ioaddr+CB_PRESENT_STATE)));
1821         cmn_err(CE_NOTE, "////////////////////////////////////////");
1822 
1823         ddi_regs_map_free(&iohandle);
1824 
1825 }