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