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