xref: /illumos-gate/usr/src/uts/common/io/cardbus/cardbus.c (revision 98677c366f39bc9e671513615d9b1a2c6f15621d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Copyright (c)  * Copyright (c) 2001 Tadpole Technology plc
28  * All rights reserved.
29  * From "@(#)pcicfg.c   1.31    99/06/18 SMI"
30  */
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
33 
34 /*
35  * Cardbus module
36  */
37 
38 #include <sys/conf.h>
39 #include <sys/modctl.h>
40 
41 #include <sys/pci.h>
42 
43 #include <sys/ddi.h>
44 #include <sys/sunndi.h>
45 #include <sys/ddi_impldefs.h>
46 
47 #include <sys/hotplug/hpcsvc.h>
48 
49 #include <sys/pctypes.h>
50 #include <sys/pcmcia.h>
51 #include <sys/sservice.h>
52 #include <sys/note.h>
53 
54 #include <sys/pci/pci_types.h>
55 #include <sys/pci/pci_sc.h>
56 
57 #include <sys/pcic_reg.h>
58 #include <sys/pcic_var.h>
59 #include <sys/pcmcia.h>
60 
61 #ifdef sparc
62 #include <sys/ddi_subrdefs.h>
63 #elif defined(__x86) || defined(__amd64)
64 #include <sys/pci_intr_lib.h>
65 #include <sys/mach_intr.h>
66 #endif
67 
68 #include "cardbus.h"
69 #include "cardbus_parse.h"
70 #include "cardbus_hp.h"
71 #include "cardbus_cfg.h"
72 
73 static int cardbus_command_default = PCI_COMM_SERR_ENABLE |
74 				PCI_COMM_WAIT_CYC_ENAB |
75 				PCI_COMM_PARITY_DETECT |
76 				PCI_COMM_ME | PCI_COMM_MAE |
77 				PCI_COMM_IO;
78 
79 static int cardbus_next_instance = 0;
80 static int cardbus_count = 0;
81 static int number_of_cardbus_cards = 0;
82 
83 static int cardbus_bus_map(dev_info_t *dip, dev_info_t *rdip,
84 		ddi_map_req_t *mp, off_t offset, off_t len, caddr_t *vaddrp);
85 static void pcirp2rp(const pci_regspec_t *pci_rp, struct regspec *rp);
86 
87 static int cardbus_ctlops(dev_info_t *, dev_info_t *,
88 			ddi_ctl_enum_t, void *arg, void *);
89 static void cardbus_init_child_regs(dev_info_t *child);
90 static int cardbus_initchild(dev_info_t *, dev_info_t *,
91 			dev_info_t *, void *);
92 static int cardbus_name_child(dev_info_t *, char *, int);
93 static void cardbus_removechild(dev_info_t *dip);
94 
95 static int cardbus_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
96 		ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg,
97 		ddi_dma_handle_t *handlep);
98 static int cardbus_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
99 		ddi_dma_handle_t handle);
100 static int cardbus_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
101 		ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
102 		ddi_dma_cookie_t *cp, uint_t *ccountp);
103 static int cardbus_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
104 		ddi_dma_handle_t handle);
105 static int cardbus_dma_flush(dev_info_t *dip, dev_info_t *rdip,
106 		ddi_dma_handle_t handle, off_t off, size_t len,
107 		uint_t cache_flags);
108 static int cardbus_dma_win(dev_info_t *dip, dev_info_t *rdip,
109 		ddi_dma_handle_t handle, uint_t win, off_t *offp,
110 		size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp);
111 static int cardbus_dma_map(dev_info_t *dip, dev_info_t *rdip,
112 		struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep);
113 
114 static int cardbus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
115 		ddi_prop_op_t prop_op, int mod_flags,
116 		char *name, caddr_t valuep, int *lengthp);
117 
118 static int cardbus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
119 		char *eventname, ddi_eventcookie_t *cookiep);
120 static int cardbus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
121 		ddi_eventcookie_t cookie, void (*callback)(dev_info_t *dip,
122 		ddi_eventcookie_t cookie, void *arg, void *bus_impldata),
123 		void *arg, ddi_callback_id_t *cb_id);
124 static int cardbus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id);
125 static int cardbus_post_event(dev_info_t *dip, dev_info_t *rdip,
126 		ddi_eventcookie_t cookie, void *bus_impldata);
127 
128 static int cardbus_intr_ops(dev_info_t *dip, dev_info_t *rdip,
129 		ddi_intr_op_t intr_op,
130 		ddi_intr_handle_impl_t *hdlp, void *result);
131 
132 static int check_token(char *token, int *len);
133 static char *find_token(char **cp, int *l, char *endc);
134 static int parse_token(char *token);
135 static int token_to_hex(char *token, unsigned *val, int len);
136 static int token_to_dec(char *token, unsigned *val, int len);
137 static void cardbus_add_prop(struct cb_deviceset_props *cdsp, int type,
138 		char *name, caddr_t vp, int len);
139 static void cardbus_add_stringprop(struct cb_deviceset_props *cdsp,
140 		char *name, char *vp, int len);
141 static void cardbus_prop_free(ddi_prop_t *propp);
142 static void cardbus_devprops_free(struct cb_deviceset_props *cbdp);
143 static int cardbus_parse_devprop(cbus_t *cbp, char *cp);
144 static void cardbus_device_props(cbus_t *cbp);
145 
146 static void cardbus_expand_busrange(dev_info_t *dip);
147 
148 static int cardbus_convert_properties(dev_info_t *dip);
149 static void cardbus_revert_properties(dev_info_t *dip);
150 
151 /*
152  * driver global data
153  */
154 kmutex_t cardbus_list_mutex; /* Protects the probe handle list */
155 void *cardbus_state;
156 int cardbus_latency_timer = 0x40;
157 int cardbus_debug = 0;
158 
159 /*
160  * Module linkage information for the kernel.
161  */
162 extern struct mod_ops mod_miscops;
163 static struct modlmisc modlmisc = {
164 	&mod_miscops,
165 	"Cardbus Configurator support %I%",
166 };
167 
168 static struct modlinkage modlinkage = {
169 	MODREV_1,
170 	&modlmisc,
171 	NULL
172 };
173 
174 int
175 _init(void)
176 {
177 	int error;
178 
179 	error =  ddi_soft_state_init(&cardbus_state, sizeof (cbus_t), 0);
180 	if (error != 0)
181 		return (error);
182 
183 	mutex_init(&cardbus_list_mutex, NULL, MUTEX_DRIVER, NULL);
184 	if ((error = mod_install(&modlinkage)) != 0) {
185 		mutex_destroy(&cardbus_list_mutex);
186 	}
187 
188 	return (error);
189 }
190 
191 int
192 _fini(void)
193 {
194 	int error;
195 	if ((error = mod_remove(&modlinkage)) == 0) {
196 		mutex_destroy(&cardbus_list_mutex);
197 		ddi_soft_state_fini(&cardbus_state);
198 	}
199 	return (error);
200 }
201 
202 int
203 _info(struct modinfo *modinfop)
204 {
205 	return (mod_info(&modlinkage, modinfop));
206 }
207 
208 static
209 struct bus_ops cardbusbus_ops = {
210 	BUSO_REV,
211 	cardbus_bus_map,
212 	NULL,
213 	NULL,
214 	NULL,
215 	i_ddi_map_fault,
216 	cardbus_dma_map,
217 	cardbus_dma_allochdl,
218 	cardbus_dma_freehdl,
219 	cardbus_dma_bindhdl,
220 	cardbus_dma_unbindhdl,
221 	cardbus_dma_flush,
222 	cardbus_dma_win,
223 	ddi_dma_mctl,
224 	cardbus_ctlops,			/* (*bus_ctl)();		*/
225 	cardbus_prop_op,
226 	cardbus_get_eventcookie,	/* (*bus_get_eventcookie)();	*/
227 	cardbus_add_eventcall,		/* (*bus_add_eventcall)();	*/
228 	cardbus_remove_eventcall,	/* (*bus_remove_eventcall)();	*/
229 	cardbus_post_event,		/* (*bus_post_event)();		*/
230 	NULL,				/* (*bus_intr_ctl)();		*/
231 	NULL,				/* (*bus_config)();		*/
232 	NULL,				/* (*bus_unconfig)();		*/
233 	NULL,				/* (*bus_fm_init)();		*/
234 	NULL,				/* (*bus_fm_fini)();		*/
235 	NULL,				/* (*bus_enter)();		*/
236 	NULL,				/* (*bus_exit)();		*/
237 	NULL,				/* (*bus_power)();		*/
238 	cardbus_intr_ops		/* (*bus_intr_op)();		*/
239 };
240 
241 #define	CB_EVENT_TAG_INSERT	0
242 #define	CB_EVENT_TAG_REMOVE	1
243 
244 static ndi_event_definition_t cb_ndi_event_defs[] = {
245 	{ CB_EVENT_TAG_INSERT, DDI_DEVI_INSERT_EVENT, EPL_INTERRUPT, 0 },
246 	{ CB_EVENT_TAG_REMOVE, DDI_DEVI_REMOVE_EVENT, EPL_INTERRUPT, 0 }
247 };
248 
249 #define	CB_N_NDI_EVENTS \
250 	(sizeof (cb_ndi_event_defs) / sizeof (cb_ndi_event_defs[0]))
251 
252 #ifdef sparc
253 struct busnum_ctrl {
254 	int	rv;
255 	dev_info_t *dip;
256 	cardbus_bus_range_t *range;
257 };
258 
259 static int
260 cardbus_claim_pci_busnum(dev_info_t *dip, void *arg)
261 {
262 	cardbus_bus_range_t pci_bus_range;
263 	struct busnum_ctrl *ctrl;
264 	ndi_ra_request_t req;
265 	char bus_type[16] = "(unknown)";
266 	int len;
267 	uint64_t base;
268 	uint64_t retlen;
269 
270 	ctrl = (struct busnum_ctrl *)arg;
271 
272 	/* check if this is a PCI bus node */
273 	len = sizeof (bus_type);
274 	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF,
275 	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
276 	    "device_type",
277 	    (caddr_t)&bus_type, &len) != DDI_SUCCESS)
278 		return (0);	/* (DDI_WALK_PRUNECHILD); */
279 
280 	if ((strcmp(bus_type, "pci") != 0) &&
281 	    (strcmp(bus_type, "pciex") != 0)) /* it is not a pci bus type */
282 		return (0);	/* (DDI_WALK_PRUNECHILD); */
283 
284 	/* look for the bus-range property */
285 	len = sizeof (struct cardbus_bus_range);
286 	if (ddi_getlongprop_buf(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
287 	    "bus-range", (caddr_t)&pci_bus_range, &len) == DDI_SUCCESS) {
288 		cardbus_err(dip, 1, "cardbus_claim_pci_busnum: %u -> %u \n",
289 			pci_bus_range.lo, pci_bus_range.hi);
290 		if ((pci_bus_range.lo >= ctrl->range->lo) &&
291 		    (pci_bus_range.hi <= ctrl->range->hi)) {
292 			cardbus_err(dip, 1,
293 			    "cardbus_claim_pci_busnum: claim %u -> %u \n",
294 			    pci_bus_range.lo, pci_bus_range.hi);
295 
296 			/* claim the bus range from the bus resource map */
297 			bzero((caddr_t)&req, sizeof (req));
298 			req.ra_addr = (uint64_t)pci_bus_range.lo;
299 			req.ra_flags |= NDI_RA_ALLOC_SPECIFIED;
300 			req.ra_len = (uint64_t)pci_bus_range.hi -
301 			    (uint64_t)pci_bus_range.lo + 1;
302 
303 			if (ndi_ra_alloc(ctrl->dip, &req, &base, &retlen,
304 			    NDI_RA_TYPE_PCI_BUSNUM, 0) == NDI_SUCCESS)
305 				return (0);	/* (DDI_WALK_PRUNECHILD); */
306 		}
307 	}
308 
309 	/*
310 	 * never Error return.
311 	 */
312 	ctrl->rv = DDI_SUCCESS;
313 	return (DDI_WALK_TERMINATE);
314 }
315 
316 static void
317 cardbus_walk_node_child(dev_info_t *parent,
318 	int (*f)(dev_info_t *, void *), void *arg)
319 {
320 	dev_info_t *dip;
321 	int ret;
322 
323 	for (dip = ddi_get_child(parent); dip;
324 	    dip = ddi_get_next_sibling(dip)) {
325 
326 		ret = (*f) (dip, arg);
327 		if (ret)
328 			return;
329 	}
330 }
331 
332 static void cardbus_fix_hostbridge_busrange(dev_info_t *dip)
333 {
334 	cardbus_bus_range_t bus_range;
335 	struct busnum_ctrl ctrl;
336 
337 	uint64_t next_bus;
338 	uint64_t blen;
339 	ndi_ra_request_t req;
340 	int	len;
341 
342 	cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange\n");
343 
344 	bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
345 	req.ra_len = 1;
346 	if (ndi_ra_alloc(dip, &req,
347 	    &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
348 	    0) != NDI_SUCCESS) {
349 		(void) ndi_ra_map_destroy(dip, NDI_RA_TYPE_PCI_BUSNUM);
350 
351 		if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_BUSNUM)
352 		    == NDI_FAILURE) {
353 			cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange "
354 			    "NDI_RA_TYPE_PCI_BUSNUM setup fail\n");
355 			return;
356 		}
357 
358 		bus_range.lo = 0;
359 		(void) ddi_getlongprop_buf(DDI_DEV_T_NONE, dip,
360 		DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus_range, &len);
361 		bus_range.hi = 255;
362 
363 		(void) ndi_ra_free(dip,
364 		    (uint64_t)bus_range.lo + 1,
365 		    (uint64_t)bus_range.hi - (uint64_t)bus_range.lo,
366 		    NDI_RA_TYPE_PCI_BUSNUM, 0);
367 
368 		ctrl.rv = DDI_SUCCESS;
369 		ctrl.dip = dip;
370 		ctrl.range = &bus_range;
371 
372 		cardbus_walk_node_child(dip, cardbus_claim_pci_busnum,
373 		    (void*)&ctrl);
374 
375 		if (ctrl.rv != DDI_SUCCESS)
376 			cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange "
377 			    "cardbus_walk_node_child fails\n");
378 
379 		(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
380 			    "bus-range", (int *)&bus_range, 2);
381 
382 	} else {
383 		cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange "
384 		    "already set up %x\n", (int)next_bus);
385 		(void) ndi_ra_free(dip, next_bus, (uint64_t)1,
386 		    NDI_RA_TYPE_PCI_BUSNUM, 0);
387 	}
388 }
389 
390 static dev_info_t *
391 cardbus_find_hsbridge_dip(dev_info_t *dip)
392 {
393 	dev_info_t *pdip;
394 
395 	pdip = ddi_get_parent(dip);
396 	while (pdip) {
397 		if (ddi_get_parent(pdip) == ddi_root_node())
398 			break;
399 		pdip = ddi_get_parent(pdip);
400 	}
401 
402 	return (pdip);
403 }
404 #endif /* sparc */
405 
406 /*
407  * Attach a device to the cardbus infrastructure.
408  */
409 int
410 cardbus_attach(dev_info_t *dip, cb_nexus_cb_t *nex_ops)
411 {
412 	cbus_t *cbp;
413 	int cb_instance;
414 	anp_t *anp = (anp_t *)ddi_get_driver_private(dip);
415 	struct dev_info *devi = DEVI(dip);
416 
417 	mutex_enter(&cardbus_list_mutex);
418 
419 	/*
420 	 * Make sure that it is not already initialized.
421 	 */
422 	if (ddi_prop_exists(DDI_DEV_T_ANY, dip,
423 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
424 	    "cbus-instance") == 1) {
425 		cmn_err(CE_WARN,
426 		    "%s%d: cardbus instance already initialized!\n",
427 		    ddi_driver_name(dip), ddi_get_instance(dip));
428 		    mutex_exit(&cardbus_list_mutex);
429 		return (DDI_FAILURE);
430 	}
431 
432 	/*
433 	 * initialize soft state structure for the bus instance.
434 	 */
435 	cb_instance = cardbus_next_instance++;
436 
437 	if (ddi_soft_state_zalloc(cardbus_state, cb_instance) != DDI_SUCCESS) {
438 		cmn_err(CE_WARN, "%s%d: can't allocate cardbus soft state\n",
439 		    ddi_driver_name(dip), ddi_get_instance(dip));
440 		mutex_exit(&cardbus_list_mutex);
441 		return (DDI_FAILURE);
442 	}
443 
444 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
445 	cbp->cb_instance = cb_instance;
446 	cbp->cb_dip = dip;
447 	mutex_init(&cbp->cb_mutex, NULL, MUTEX_DRIVER, NULL);
448 
449 	/*
450 	 * Save the instance number of the soft state structure for
451 	 * this bus as a devinfo property.
452 	 */
453 	if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
454 	    "cbus-instance", (caddr_t)&cb_instance,
455 	    sizeof (cb_instance)) != DDI_SUCCESS) {
456 		cmn_err(CE_WARN,
457 		    "%s%d: failed to add the property 'cbus-instance'",
458 		    ddi_driver_name(dip), ddi_get_instance(dip));
459 		ddi_soft_state_free(cardbus_state, cb_instance);
460 		mutex_exit(&cardbus_list_mutex);
461 		return (DDI_FAILURE);
462 	}
463 
464 	cbp->cb_nex_ops = nex_ops;
465 	/*
466 	 * TODO - Should probably be some sort of locking on the devinfo here.
467 	 */
468 	cbp->orig_dopsp = devi->devi_ops;
469 	cbp->orig_bopsp = devi->devi_ops->devo_bus_ops;
470 	cbp->cb_dops = *devi->devi_ops;
471 	devi->devi_ops = &cbp->cb_dops;
472 
473 	if (ndi_event_alloc_hdl(dip, *anp->an_iblock, &cbp->cb_ndi_event_hdl,
474 	    NDI_SLEEP) == NDI_SUCCESS) {
475 		cbp->cb_ndi_events.ndi_n_events = CB_N_NDI_EVENTS;
476 		cbp->cb_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
477 		cbp->cb_ndi_events.ndi_event_defs = cb_ndi_event_defs;
478 		if (ndi_event_bind_set(cbp->cb_ndi_event_hdl,
479 		    &cbp->cb_ndi_events,
480 		    NDI_SLEEP) != NDI_SUCCESS) {
481 			cardbus_err(dip, 1,
482 			    "cardbus_attach: ndi_event_bind_set failed\n");
483 		}
484 	}
485 
486 	/*
487 	 * Check for device initialization property.
488 	 */
489 	cardbus_device_props(cbp);
490 
491 	if (cardbus_init_hotplug(cbp) != DDI_SUCCESS) {
492 		ddi_soft_state_free(cardbus_state, cb_instance);
493 		mutex_exit(&cardbus_list_mutex);
494 		return (DDI_FAILURE);
495 	}
496 
497 #ifdef sparc
498 	/* a hack to fix the bus-range problem on pci root nodes */
499 	{
500 		dev_info_t *hs_dip;
501 
502 		hs_dip = cardbus_find_hsbridge_dip(dip);
503 		cardbus_fix_hostbridge_busrange(hs_dip);
504 	}
505 #endif
506 
507 	cardbus_expand_busrange(dip);
508 	cardbus_count++;
509 	mutex_exit(&cardbus_list_mutex);
510 	return (DDI_SUCCESS);
511 }
512 
513 #ifdef TODO
514 static int
515 cardbus_detach(dev_info_t *dip)
516 {
517 	int cb_instance;
518 	cbus_t *cbp;
519 
520 	mutex_enter(&cardbus_list_mutex);
521 	/* get the instance number for the cardbus soft state data */
522 	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
523 			DDI_PROP_DONTPASS, "cbus-instance", -1);
524 	if (cb_instance < 0) {
525 		mutex_exit(&cardbus_list_mutex);
526 		return (DDI_FAILURE); /* no instance is setup for this bus */
527 	}
528 
529 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
530 
531 	if (cbp->cb_dsp) {
532 		struct cb_deviceset_props *cbdp, *ncbdp;
533 
534 		cbdp = cbp->cb_dsp;
535 		while (cbdp) {
536 			ncbdp = cbdp->next;
537 			cardbus_devprops_free(cbdp);
538 			cbdp = ncbdp;
539 		}
540 	}
541 	/*
542 	 * Unregister the bus with the HPS.
543 	 *
544 	 * (Note: It is assumed that the HPS framework uninstalls
545 	 *  event handlers for all the hot plug slots on this bus.)
546 	 */
547 	(void) hpc_nexus_unregister_bus(dip);
548 
549 	if (cbp->cb_ndi_event_hdl != NULL) {
550 		(void) ndi_event_unbind_set(cbp->cb_ndi_event_hdl,
551 		    &cbp->cb_ndi_events, NDI_SLEEP);
552 		ndi_event_free_hdl(cbp->cb_ndi_event_hdl);
553 	}
554 
555 	mutex_destroy(&cbp->cb_mutex);
556 	if (cbp->nexus_path)
557 		kmem_free(cbp->nexus_path, strlen(cbp->nexus_path) + 1);
558 	if (cbp->name)
559 		kmem_free(cbp->name, strlen(cbp->name) + 1);
560 
561 	ddi_soft_state_free(cardbus_state, cb_instance);
562 
563 	/* remove the 'cbus-instance' property from the devinfo node */
564 	(void) ddi_prop_remove(DDI_DEV_T_ANY, dip, "cbus-instance");
565 
566 	ASSERT(cardbus_count != 0);
567 	--cardbus_count;
568 
569 	mutex_exit(&cardbus_list_mutex);
570 	return (DDI_SUCCESS);
571 }
572 #endif
573 
574 boolean_t
575 cardbus_load_cardbus(dev_info_t *dip, uint_t socket, uint32_t pc_base)
576 {
577 #ifndef HOTPLUG
578 	struct cardbus_config_ctrl ctrl;
579 	int circular_count;
580 #endif
581 	int cb_instance;
582 	cbus_t *cbp;
583 	struct dev_info *devi = DEVI(dip);
584 
585 	_NOTE(ARGUNUSED(socket, pc_base))
586 
587 #if defined(CARDBUS_DEBUG)
588 	cardbus_err(dip, 6, "cardbus_load_cardbus\n");
589 #endif
590 
591 	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
592 			DDI_PROP_DONTPASS, "cbus-instance", -1);
593 	ASSERT(cb_instance >= 0);
594 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
595 
596 	if (cbp->fatal_problem)
597 		return (B_FALSE);
598 
599 	if (cardbus_convert_properties(dip) == DDI_FAILURE)
600 		return (B_FALSE);
601 
602 	number_of_cardbus_cards++;
603 	devi->devi_ops->devo_bus_ops = &cardbusbus_ops;
604 
605 #ifdef HOTPLUG
606 	mutex_enter(&cbp->cb_mutex);
607 	cbp->card_present = B_TRUE;
608 
609 	(void) hpc_slot_event_notify(cbp->slot_handle,
610 	    HPC_EVENT_SLOT_INSERTION, 0);
611 	(void) hpc_slot_event_notify(cbp->slot_handle,
612 	    HPC_EVENT_SLOT_POWER_ON, 0);
613 	(void) hpc_slot_event_notify(cbp->slot_handle,
614 	    HPC_EVENT_SLOT_CONFIGURE, 0);
615 
616 	mutex_exit(&cbp->cb_mutex);
617 #else
618 	if (cardbus_configure(cbp) != PCICFG_SUCCESS) {
619 #if defined(CARDBUS_DEBUG)
620 		cardbus_err(dip, 6, "cardbus_configure failed\n");
621 #endif
622 		return (B_FALSE);
623 	}
624 
625 	ctrl.rv = NDI_SUCCESS;
626 	ctrl.busno = cardbus_primary_busno(dip);
627 	ctrl.op = PCICFG_OP_ONLINE;
628 	ctrl.dip = NULL;
629 	ctrl.flags = PCICFG_FLAGS_CONTINUE;
630 
631 	/*
632 	 * The child of the dip is the cardbus dip. The child of the
633 	 * cardbus dip is the device itself
634 	 */
635 #if defined(CARDBUS_DEBUG)
636 	cardbus_err(dip, 8, "cardbus_load_cardbus: calling cbus_configure\n");
637 #endif
638 	ndi_devi_enter(dip, &circular_count);
639 	ddi_walk_devs(ddi_get_child(dip), cbus_configure, (void *)&ctrl);
640 	ndi_devi_exit(dip, circular_count);
641 
642 	if (ctrl.rv != NDI_SUCCESS) {
643 		cardbus_err(dip, 1,
644 		    "cardbus_load_cardbus (%s%d): failed to attach (%d)\n",
645 		    ctrl.dip ? ddi_driver_name(ctrl.dip) : "Unknown",
646 		    ctrl.dip ? ddi_get_instance(ctrl.dip) : 0,
647 		    ctrl.rv);
648 
649 		/*
650 		 * Returning error here will cause the pcic_load_cardbus() call
651 		 * to fail. This will invoke pcic_unload_cardbus() which calls
652 		 * cardbus_unload_cardbus() below.
653 		 */
654 		return (B_FALSE);
655 	}
656 #endif
657 
658 #if defined(CARDBUS_DEBUG)
659 	cardbus_err(dip, 7, "cardbus_load_cardbus: returning TRUE\n");
660 #endif
661 
662 	return (B_TRUE);
663 }
664 
665 /*
666  * Unload the cardbus module
667  */
668 void
669 cardbus_unload_cardbus(dev_info_t *dip)
670 {
671 	int	cb_instance;
672 #ifndef HOTPLUG
673 	int	prim_bus = cardbus_primary_busno(dip);
674 	int	rval;
675 #endif
676 	cbus_t *cbp;
677 	struct dev_info *devi = DEVI(dip);
678 
679 	cardbus_err(dip, 6, "cardbus_unload_cardbus\n");
680 
681 	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
682 	    DDI_PROP_DONTPASS, "cbus-instance", -1);
683 	ASSERT(cb_instance >= 0);
684 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
685 
686 	if (number_of_cardbus_cards == 0)
687 		return;
688 
689 #ifdef HOTPLUG
690 	mutex_enter(&cbp->cb_mutex);
691 	cbp->card_present = B_FALSE;
692 
693 	(void) hpc_slot_event_notify(cbp->slot_handle,
694 	    HPC_EVENT_SLOT_POWER_OFF, 0);
695 	(void) hpc_slot_event_notify(cbp->slot_handle,
696 	    HPC_EVENT_SLOT_REMOVAL, 0);
697 
698 	mutex_exit(&cbp->cb_mutex);
699 #else
700 
701 	cardbus_err(dip, 8,
702 	    "cardbus_unload_cardbus: calling cardbus_unconfigure_node\n");
703 
704 	rval = cardbus_unconfigure_node(dip, prim_bus, B_TRUE);
705 
706 	if (rval != NDI_SUCCESS) {
707 		cardbus_err(dip, 4,
708 		    "cardbus_unload_cardbus: "
709 		    "cardbus_unconfigure_node failed\n");
710 		number_of_cardbus_cards--;
711 		cbp->fatal_problem = B_TRUE;
712 		cmn_err(CE_WARN,
713 		    "cardbus(%s%d): Failed to remove device tree: "
714 		    "Slot disabled",
715 		    ddi_get_name(dip), ddi_get_instance(dip));
716 		return;
717 	}
718 
719 	(void) cardbus_unconfigure(cbp);
720 #endif
721 
722 	/*
723 	 * Inform the lower drivers that the card has been removed
724 	 */
725 	if (cbp->cb_ndi_event_hdl != NULL) {
726 		ddi_eventcookie_t cookie;
727 		if (ndi_event_retrieve_cookie(cbp->cb_ndi_event_hdl, dip,
728 		    DDI_DEVI_REMOVE_EVENT, &cookie, 0) == NDI_SUCCESS) {
729 			(void) ndi_event_run_callbacks(cbp->cb_ndi_event_hdl,
730 			    dip, cookie, NULL);
731 		}
732 	}
733 
734 	devi->devi_ops->devo_bus_ops = cbp->orig_bopsp;
735 	--number_of_cardbus_cards;
736 
737 	cardbus_revert_properties(dip);
738 }
739 
740 boolean_t
741 cardbus_can_suspend(dev_info_t *dip)
742 {
743 #ifdef HOTPLUG
744 	cbus_t *cbp;
745 	int	cb_instance;
746 
747 	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
748 	    DDI_PROP_DONTPASS, "cbus-instance", -1);
749 	ASSERT(cb_instance >= 0);
750 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
751 	if (cbp->ostate == AP_OSTATE_UNCONFIGURED)
752 		return (B_TRUE);
753 #endif
754 	return (B_FALSE);
755 }
756 
757 static int
758 cardbus_convert_properties(dev_info_t *dip)
759 {
760 	struct pcm_regs *pcic_avail_p, *old_avail_p;
761 	pci_regspec_t *cb_avail_p, *new_avail_p;
762 	pcic_ranges_t *pcic_range_p, *old_range_p;
763 	cardbus_range_t *cb_range_p, *new_range_p;
764 	int range_len, range_entries, i;
765 	int avail_len, avail_entries;
766 
767 #if defined(CARDBUS_DEBUG)
768 	cardbus_err(dip, 6, "cardbus_convert_properties\n");
769 #endif
770 
771 	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
772 	    "#address-cells", 3) != DDI_SUCCESS) {
773 		cardbus_err(dip, 1, "cardbus_convert_properties: "
774 		    "failed to update #address-cells property\n");
775 		return (DDI_FAILURE);
776 	}
777 	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
778 	    "#size-cells", 2) != DDI_SUCCESS) {
779 		cardbus_err(dip, 1, "cardbus_convert_properties: "
780 		    "failed to update #size-cells property\n");
781 		return (DDI_FAILURE);
782 	}
783 
784 	if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "available",
785 	    (caddr_t)&pcic_avail_p, &avail_len) != DDI_PROP_SUCCESS) {
786 		cardbus_err(dip, 1, "cardbus_convert_properties: "
787 		    "no available property for pcmcia\n");
788 	} else {
789 		avail_entries = avail_len / sizeof (struct pcm_regs);
790 		cb_avail_p = kmem_alloc(sizeof (pci_regspec_t) * avail_entries,
791 		    KM_SLEEP);
792 
793 		old_avail_p = pcic_avail_p;
794 		new_avail_p = cb_avail_p;
795 		for (i = 0; i < avail_entries;
796 		    i++, old_avail_p++, new_avail_p++) {
797 			new_avail_p->pci_phys_hi = old_avail_p->phys_hi;
798 			new_avail_p->pci_phys_mid = 0;
799 			new_avail_p->pci_phys_low = old_avail_p->phys_lo;
800 			new_avail_p->pci_size_hi = 0;
801 			new_avail_p->pci_size_low = old_avail_p->phys_len;
802 		}
803 
804 		(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
805 		    "available",
806 		    (int *)cb_avail_p,
807 		    (sizeof (pci_regspec_t) * avail_entries)/sizeof (int));
808 
809 		kmem_free(pcic_avail_p, avail_len);
810 		kmem_free(cb_avail_p, sizeof (pci_regspec_t) * avail_entries);
811 	}
812 
813 	if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "ranges",
814 	    (caddr_t)&pcic_range_p, &range_len) != DDI_PROP_SUCCESS) {
815 		cardbus_err(dip, 1, "cardbus_convert_properties: "
816 		    "no ranges property for pcmcia\n");
817 	} else {
818 		range_entries = range_len / sizeof (pcic_ranges_t);
819 		cb_range_p = kmem_alloc(
820 		    sizeof (cardbus_range_t) * range_entries, KM_SLEEP);
821 
822 		old_range_p = pcic_range_p;
823 		new_range_p = cb_range_p;
824 		for (i = 0; i < range_entries;
825 		    i++, old_range_p++, new_range_p++) {
826 			new_range_p->child_hi =
827 			    old_range_p->pcic_range_caddrhi;
828 			new_range_p->child_mid = 0;
829 			new_range_p->child_lo =
830 			    old_range_p->pcic_range_caddrlo;
831 			new_range_p->parent_hi =
832 			    old_range_p->pcic_range_paddrhi;
833 			new_range_p->parent_mid =
834 			    old_range_p->pcic_range_paddrmid;
835 			new_range_p->parent_lo =
836 			    old_range_p->pcic_range_paddrlo;
837 			new_range_p->size_hi = 0;
838 			new_range_p->size_lo = old_range_p->pcic_range_size;
839 		}
840 
841 		(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
842 		    (int *)cb_range_p,
843 		    (sizeof (cardbus_range_t) * range_entries)/sizeof (int));
844 
845 		kmem_free(pcic_range_p, range_len);
846 		kmem_free(cb_range_p, sizeof (cardbus_range_t) * range_entries);
847 	}
848 
849 	return (DDI_SUCCESS);
850 }
851 
852 static void
853 cardbus_revert_properties(dev_info_t *dip)
854 {
855 #if defined(CARDBUS_DEBUG)
856 	cardbus_err(dip, 6, "cardbus_revert_properties\n");
857 #endif
858 
859 	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "#address-cells");
860 
861 	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "#size-cells");
862 
863 	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "available");
864 }
865 
866 static int
867 cardbus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
868 		ddi_prop_op_t prop_op, int mod_flags,
869 		char *name, caddr_t valuep, int *lengthp)
870 {
871 #if defined(CARDBUS_DEBUG)
872 	if ((ch_dip != dip) || (cardbus_debug >= 9))
873 		cardbus_err(dip, 6,
874 		    "cardbus_prop_op(%s) (dip=0x%p, op=%d, name=%s)\n",
875 		    ddi_driver_name(ch_dip), (void *) dip, prop_op, name);
876 #endif
877 	return (impl_ddi_bus_prop_op(dev, dip, ch_dip, prop_op,
878 	    mod_flags, name, valuep, lengthp));
879 }
880 
881 static int
882 cardbus_ctlops(dev_info_t *dip, dev_info_t *rdip,
883 	ddi_ctl_enum_t ctlop, void *arg, void *result)
884 {
885 	pci_regspec_t *regs;
886 	int	totreg, reglen;
887 	const char	*dname = ddi_driver_name(dip);
888 
889 	ASSERT(number_of_cardbus_cards != 0);
890 
891 	cardbus_err(dip, 6,
892 	    "cardbus_ctlops(%p, %p, %d, %p, %p)\n",
893 	    (void *)dip, (void *)rdip, ctlop, (void *)arg, (void *)result);
894 
895 	switch (ctlop) {
896 	case DDI_CTLOPS_UNINITCHILD:
897 		cardbus_removechild((dev_info_t *)arg);
898 		return (DDI_SUCCESS);
899 
900 	default:
901 		/*
902 		 * Do Nothing
903 		 */
904 		cardbus_err(dip, 8,
905 		    "cardbus_ctlops: Unsupported DDI_CTLOP %d\n", ctlop);
906 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
907 
908 	case DDI_CTLOPS_SIDDEV:		/* see ddi_dev_is_sid(9F) */
909 		return (DDI_SUCCESS);
910 
911 	case DDI_CTLOPS_SLAVEONLY:	/* see ddi_slaveonly(9F) */
912 		return (DDI_FAILURE);	/* cardbus */
913 
914 	case DDI_CTLOPS_REGSIZE:
915 	case DDI_CTLOPS_NREGS:
916 		if (rdip == (dev_info_t *)NULL) {
917 			*(int *)result = 0;
918 			return (DDI_FAILURE);
919 		}
920 		break;
921 
922 	case DDI_CTLOPS_IOMIN:
923 		/*
924 		 * If we are using the streaming cache, align at
925 		 * least on a cache line boundary. Otherwise use
926 		 * whatever alignment is passed in.
927 		 */
928 
929 		if (arg) {
930 			int	val = *((int *)result);
931 
932 #ifdef  PCI_SBUF_LINE_SIZE
933 			val = maxbit(val, PCI_SBUF_LINE_SIZE);
934 #else
935 			val = maxbit(val, 64);
936 #endif
937 			*((int *)result) = val;
938 		}
939 		return (DDI_SUCCESS);
940 
941 	case DDI_CTLOPS_INITCHILD:
942 		return (cardbus_initchild(rdip, dip, (dev_info_t *)arg,
943 					result));
944 
945 	case DDI_CTLOPS_REPORTDEV:
946 		if (rdip == (dev_info_t *)0)
947 			return (DDI_FAILURE);
948 
949 		if (strcmp("pcs", ddi_node_name(rdip)) == 0)
950 			cardbus_err(dip, 1,
951 			    "cardbus_ctlops: PCCard socket %d at %s@%s\n",
952 			    ddi_get_instance(rdip),
953 			    dname, ddi_get_name_addr(dip));
954 		else {
955 			pci_regspec_t *pci_rp;
956 			dev_info_t *next;
957 			int	length;
958 
959 			if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
960 			    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
961 			    (uint_t *)&length) != DDI_PROP_SUCCESS)
962 				return (DDI_FAILURE);
963 
964 			if (pci_rp->pci_phys_hi == 0)
965 				cardbus_err(dip, 1, "%s%d at %s@%s\n",
966 				    ddi_driver_name(rdip),
967 				    ddi_get_instance(rdip),
968 				    dname, ddi_get_name_addr(dip));
969 			else {
970 				uint8_t bus, device, function;
971 				int32_t val32;
972 				char	*ptr, buf[128];
973 
974 				bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
975 				device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
976 				function = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
977 
978 				ptr = buf;
979 				(void) sprintf(ptr, "  "
980 				    "Bus %3d Device %2d Function %2d",
981 				    bus, device, function);
982 				ptr = &ptr[strlen(ptr)];
983 
984 				val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
985 				    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
986 				    "vendor-id", -1);
987 				if (val32 != -1) {
988 					(void) sprintf(ptr, " Vendor 0x%04x",
989 					    val32);
990 					ptr = &ptr[strlen(ptr)];
991 				}
992 				val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
993 				    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
994 				    "device-id", -1);
995 				if (val32 != -1) {
996 					(void) sprintf(ptr, " Device 0x%04x",
997 					    val32);
998 					ptr = &ptr[strlen(ptr)];
999 				}
1000 				val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
1001 				    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1002 				    "class-code", -1);
1003 				if (val32 != -1) {
1004 					const char	*name;
1005 
1006 					if ((name = ddi_get_name(rdip)) !=
1007 					    NULL)
1008 						(void) sprintf(ptr, " Name %s",
1009 						    name);
1010 					else
1011 						(void) sprintf(ptr,
1012 						    " Class 0x%x", val32 >> 8);
1013 					ptr = &ptr[strlen(ptr)];
1014 				}
1015 
1016 				*ptr++ = '\n';
1017 				ASSERT(((caddr_t)ptr - (caddr_t)buf) <
1018 					sizeof (buf));
1019 				*ptr = '\0';
1020 
1021 				cardbus_err(dip, 1, buf);
1022 			}
1023 			ddi_prop_free(pci_rp);
1024 
1025 			for (next = ddi_get_child(rdip); next;
1026 			    next = ddi_get_next_sibling(next))
1027 				(void) cardbus_ctlops(next, next,
1028 				    DDI_CTLOPS_REPORTDEV, arg, result);
1029 		}
1030 		return (DDI_SUCCESS);
1031 	}
1032 	*(int *)result = 0;
1033 
1034 	if (ddi_getlongprop(DDI_DEV_T_NONE, rdip,
1035 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
1036 	    (caddr_t)&regs, &reglen) != DDI_SUCCESS)
1037 		return (DDI_FAILURE);
1038 
1039 	totreg = reglen / sizeof (pci_regspec_t);
1040 	if (ctlop == DDI_CTLOPS_NREGS) {
1041 		cardbus_err(dip, 6,
1042 		    "cardbus_ctlops, returning NREGS = %d\n", totreg);
1043 		*(int *)result = totreg;
1044 	} else if (ctlop == DDI_CTLOPS_REGSIZE) {
1045 		const int	rn = *(int *)arg;
1046 		if (rn > totreg)
1047 			return (DDI_FAILURE);
1048 		cardbus_err(dip, 6,
1049 		    "cardbus_ctlops, returning REGSIZE(%d) = %d\n",
1050 		    rn, regs[rn].pci_size_low);
1051 		*(off_t *)result = regs[rn].pci_size_low;
1052 	}
1053 	kmem_free(regs, reglen);
1054 	return (DDI_SUCCESS);
1055 }
1056 
1057 static void
1058 cardbus_init_child_regs(dev_info_t *child)
1059 {
1060 	ddi_acc_handle_t config_handle;
1061 	uint16_t command_preserve, command;
1062 #if !defined(__i386) && !defined(__amd64)
1063 	uint8_t bcr;
1064 #endif
1065 	uint8_t header_type;
1066 	uint8_t min_gnt, latency_timer;
1067 	uint_t n;
1068 
1069 	/*
1070 	 * Map the child configuration space to for initialization.
1071 	 *
1072 	 *  Set the latency-timer register to values appropriate
1073 	 *  for the devices on the bus (based on other devices
1074 	 *  MIN_GNT and MAX_LAT registers.
1075 	 *
1076 	 *  Set the fast back-to-back enable bit in the command
1077 	 *  register if it's supported and all devices on the bus
1078 	 *  have the capability.
1079 	 *
1080 	 */
1081 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
1082 		return;
1083 
1084 	cardbus_err(child, 6, "cardbus_init_child_regs()\n");
1085 
1086 	/*
1087 	 * Determine the configuration header type.
1088 	 */
1089 	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
1090 
1091 	/*
1092 	 * Support for "command-preserve" property.  Note that we
1093 	 * add PCI_COMM_BACK2BACK_ENAB to the bits to be preserved
1094 	 * since the obp will set this if the device supports and
1095 	 * all targets on the same bus support it.  Since psycho
1096 	 * doesn't support PCI_COMM_BACK2BACK_ENAB, it will never
1097 	 * be set.  This is just here in case future revs do support
1098 	 * PCI_COMM_BACK2BACK_ENAB.
1099 	 */
1100 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1101 	    DDI_PROP_DONTPASS,
1102 	    "command-preserve", 0);
1103 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
1104 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
1105 	command |= (cardbus_command_default & ~command_preserve);
1106 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
1107 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
1108 
1109 #if !defined(__i386) && !defined(__amd64)
1110 	/*
1111 	 * If the device has a bus control register then program it
1112 	 * based on the settings in the command register.
1113 	 */
1114 	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
1115 		bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
1116 		if (cardbus_command_default & PCI_COMM_PARITY_DETECT)
1117 			bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
1118 		if (cardbus_command_default & PCI_COMM_SERR_ENABLE)
1119 			bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
1120 		bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
1121 		pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
1122 	}
1123 #endif
1124 
1125 	/*
1126 	 * Initialize cache-line-size configuration register if needed.
1127 	 */
1128 	if (ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1129 	    "cache-line-size", 0) == 0) {
1130 
1131 		pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
1132 		    PCI_CACHE_LINE_SIZE);
1133 		n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
1134 		if (n != 0)
1135 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
1136 				"cache-line-size", n);
1137 	}
1138 
1139 	/*
1140 	 * Initialize latency timer registers if needed.
1141 	 */
1142 	if (ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1143 	    "latency-timer", 0) == 0) {
1144 
1145 		if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
1146 			latency_timer = cardbus_latency_timer;
1147 			pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
1148 					latency_timer);
1149 		} else {
1150 			min_gnt = pci_config_get8(config_handle,
1151 						PCI_CONF_MIN_G);
1152 
1153 			/*
1154 			 * Cardbus os only 33Mhz
1155 			 */
1156 			if (min_gnt != 0) {
1157 				latency_timer = min_gnt * 8;
1158 			}
1159 		}
1160 		pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
1161 				latency_timer);
1162 		n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
1163 		if (n != 0)
1164 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
1165 				"latency-timer", n);
1166 	}
1167 
1168 	pci_config_teardown(&config_handle);
1169 }
1170 
1171 static int
1172 cardbus_initchild(dev_info_t *rdip, dev_info_t *dip, dev_info_t *child,
1173 		void *result)
1174 {
1175 	char	name[MAXNAMELEN];
1176 	const char	*dname = ddi_driver_name(dip);
1177 	const struct cb_ops *cop;
1178 
1179 	_NOTE(ARGUNUSED(rdip, result))
1180 
1181 	cardbus_err(child, 6, "cardbus_initchild\n");
1182 
1183 	/*
1184 	 * Name the child
1185 	 */
1186 	if (cardbus_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
1187 		return (DDI_FAILURE);
1188 
1189 	ddi_set_name_addr(child, name);
1190 	ddi_set_parent_data(child, NULL);
1191 
1192 	if (ndi_dev_is_persistent_node(child) == 0) {
1193 		/*
1194 		 * Try to merge the properties from this prototype
1195 		 * node into real h/w nodes.
1196 		 */
1197 		if (ndi_merge_node(child, cardbus_name_child) == DDI_SUCCESS) {
1198 			/*
1199 			 * Merged ok - return failure to remove the node.
1200 			 */
1201 			cardbus_removechild(child);
1202 			return (DDI_FAILURE);
1203 		}
1204 		/*
1205 		 * The child was not merged into a h/w node,
1206 		 * but there's not much we can do with it other
1207 		 * than return failure to cause the node to be removed.
1208 		 */
1209 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
1210 		    ddi_driver_name(child), ddi_get_name_addr(child),
1211 		    ddi_driver_name(child));
1212 		cardbus_removechild(child);
1213 		return (DDI_NOT_WELL_FORMED);
1214 	}
1215 	cop = DEVI(dip)->devi_ops->devo_cb_ops;
1216 
1217 	if ((cop == NULL) || (!(cop->cb_flag & D_HOTPLUG))) {
1218 		cmn_err(CE_WARN, "%s: driver doesn't support HOTPLUG\n", dname);
1219 		return (DDI_FAILURE);
1220 	}
1221 
1222 	cardbus_init_child_regs(child);
1223 
1224 	/*
1225 	 * Create ppd if needed.
1226 	 */
1227 	if (ddi_get_parent_data(child) == NULL) {
1228 		struct cardbus_parent_private_data *ppd;
1229 
1230 #ifdef sparc
1231 		ppd = (struct cardbus_parent_private_data *)
1232 		kmem_zalloc(sizeof (struct cardbus_parent_private_data),
1233 		    KM_SLEEP);
1234 
1235 #elif defined(__x86) || defined(__amd64)
1236 		ppd = (struct cardbus_parent_private_data *)
1237 		    kmem_zalloc(sizeof (struct cardbus_parent_private_data)
1238 			+ sizeof (struct intrspec), KM_SLEEP);
1239 
1240 		ppd->ppd.par_intr = (struct intrspec *)(ppd + 1);
1241 		(ppd->ppd.par_intr)->intrspec_pri = 0;
1242 		(ppd->ppd.par_intr)->intrspec_vec = 0;
1243 		(ppd->ppd.par_intr)->intrspec_func = (uint_t (*)()) 0;
1244 #endif
1245 
1246 		if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
1247 		    "interrupts", -1) != -1)
1248 			ppd->ppd.par_nintr = 1;
1249 
1250 		ppd->code = CB_PPD_CODE;
1251 
1252 		cardbus_err(child, 5,
1253 		    "cardbus_initchild: Creating empty ppd\n");
1254 		ppd->ppd.par_nreg = 0;
1255 		ppd->ppd.par_reg = NULL;
1256 
1257 		ddi_set_parent_data(child, (caddr_t)ppd);
1258 	}
1259 
1260 	return (DDI_SUCCESS);
1261 }
1262 
1263 static int
1264 cardbus_name_child(dev_info_t *child, char *name, int namelen)
1265 {
1266 	pci_regspec_t *pci_rp;
1267 	char	**unit_addr;
1268 	uint_t n;
1269 	int	bus, device, func;
1270 
1271 	/*
1272 	 * Pseudo nodes indicate a prototype node with per-instance
1273 	 * properties to be merged into the real h/w device node.
1274 	 * The interpretation of the unit-address is DD[,F]
1275 	 * where DD is the device id and F is the function.
1276 	 */
1277 	if (ndi_dev_is_persistent_node(child) == 0) {
1278 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
1279 		    DDI_PROP_DONTPASS,
1280 		    "unit-address", &unit_addr, &n) != DDI_PROP_SUCCESS) {
1281 			cmn_err(CE_WARN, "cannot name node from %s.conf",
1282 			    ddi_driver_name(child));
1283 			return (DDI_FAILURE);
1284 		}
1285 		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
1286 			cmn_err(CE_WARN, "unit-address property in %s.conf"
1287 			    " not well-formed", ddi_driver_name(child));
1288 			ddi_prop_free(unit_addr);
1289 			return (DDI_FAILURE);
1290 		}
1291 		(void) snprintf(name, namelen, "%s", *unit_addr);
1292 		ddi_prop_free(unit_addr);
1293 		return (DDI_SUCCESS);
1294 	}
1295 
1296 	/*
1297 	 * Get the address portion of the node name based on
1298 	 * the function and device number.
1299 	 */
1300 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1301 	    "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) {
1302 		return (DDI_FAILURE);
1303 	}
1304 
1305 	bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1306 	device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1307 	func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1308 	ddi_prop_free(pci_rp);
1309 
1310 	if (func != 0)
1311 		(void) snprintf(name, namelen, "%x,%x", device, func);
1312 	else
1313 		(void) snprintf(name, namelen, "%x", device);
1314 
1315 	cardbus_err(child, 8,
1316 	    "cardbus_name_child: system init done [%x][%x][%x]"
1317 	    " for %s [%s] nodeid: %x @%s\n",
1318 	    bus, device, func,
1319 	    ddi_get_name(child), ddi_get_name_addr(child),
1320 	    DEVI(child)->devi_nodeid, name);
1321 
1322 	return (DDI_SUCCESS);
1323 }
1324 
1325 static void
1326 cardbus_removechild(dev_info_t *dip)
1327 {
1328 	struct cardbus_parent_private_data *ppd;
1329 
1330 	ddi_set_name_addr(dip, NULL);
1331 	impl_rem_dev_props(dip);
1332 	ppd = (struct cardbus_parent_private_data *)ddi_get_parent_data(dip);
1333 	if (ppd && (ppd->code == CB_PPD_CODE)) {
1334 		if (ppd->ppd.par_reg && (ppd->ppd.par_nreg > 0))
1335 			kmem_free((caddr_t)ppd->ppd.par_reg,
1336 			    ppd->ppd.par_nreg * sizeof (struct regspec));
1337 #ifdef sparc
1338 		kmem_free(ppd, sizeof (struct cardbus_parent_private_data));
1339 #elif defined(__x86) || defined(__amd64)
1340 		kmem_free(ppd, sizeof (struct cardbus_parent_private_data) +
1341 		    sizeof (struct intrspec));
1342 #endif
1343 		cardbus_err(dip, 5,
1344 		    "cardbus_removechild: ddi_set_parent_data(NULL)\n");
1345 		ddi_set_parent_data(dip, NULL);
1346 	}
1347 }
1348 
1349 
1350 static char	cb_bnamestr[] = "binding_name";
1351 static char	cb_venidstr[] = "VendorID";
1352 static char	cb_devidstr[] = "DeviceID";
1353 static char	cb_nnamestr[] = "nodename";
1354 
1355 static cb_props_parse_tree_t cb_props_parse_tree[] = {
1356 	{ cb_bnamestr, PT_STATE_STRING_VAR },
1357 	{ cb_venidstr, PT_STATE_HEX_VAR },
1358 	{ cb_devidstr, PT_STATE_HEX_VAR } };
1359 
1360 static int
1361 check_token(char *token, int *len)
1362 {
1363 	int	state = PT_STATE_DEC_VAR;
1364 	int	sl = strlen(token), il = 1;
1365 	char	c;
1366 
1367 	if (token[0] == '0' && token[2] && (token[1] == 'x' || token[1] ==
1368 	    'X')) {
1369 		state = PT_STATE_HEX_VAR;
1370 		token += 2;
1371 	}
1372 
1373 	while (c = *token++) {
1374 		if (isdigit(c))
1375 			continue;
1376 		if (c == PARSE_COMMA) {
1377 			il++;
1378 			if (token[0] == '0' && token[2] && isx(token[1])) {
1379 				state = PT_STATE_HEX_VAR;
1380 				token += 2;
1381 			}
1382 			continue;
1383 		}
1384 		if (!isxdigit(c)) {
1385 			*len = sl;
1386 			return (PT_STATE_STRING_VAR);
1387 		}
1388 		state = PT_STATE_HEX_VAR;
1389 	}
1390 	*len = il;
1391 	return (state);
1392 }
1393 
1394 
1395 static char *
1396 find_token(char **cp, int *l, char *endc)
1397 {
1398 	char	*cpp = *cp;
1399 
1400 	while ((**cp && (isalpha(**cp) || isxdigit(**cp) ||
1401 	    (**cp == PARSE_UNDERSCORE) ||
1402 	    (**cp == PARSE_COMMA) ||
1403 	    (**cp == PARSE_DASH)))) {
1404 		(*cp)++;
1405 		(*l)++;
1406 	}
1407 
1408 	*endc = **cp;
1409 	**cp = NULL;
1410 
1411 	return (cpp);
1412 }
1413 
1414 static int
1415 parse_token(char *token)
1416 {
1417 	cb_props_parse_tree_t *pt = cb_props_parse_tree;
1418 	int	k = sizeof (cb_props_parse_tree) /
1419 	    sizeof (cb_props_parse_tree_t);
1420 
1421 	while (k--) {
1422 		if (strcmp((char *)token, pt->token) == 0)
1423 			return (pt->state);
1424 		pt++;
1425 	}
1426 
1427 	return (PT_STATE_UNKNOWN);
1428 }
1429 
1430 static int
1431 token_to_hex(char *token, unsigned *val, int len)
1432 {
1433 	uchar_t c;
1434 
1435 	*val = 0;
1436 	if (token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) {
1437 		token += 2;
1438 	}
1439 
1440 	while (*token) {
1441 		if (!isxdigit(*token)) {
1442 			if (*token == PARSE_COMMA) {
1443 				if (!(--len))
1444 					return (1);
1445 				val++;
1446 				*val = 0;
1447 				token++;
1448 				if (token[0] == '0' && (token[1] == 'x' ||
1449 				    token[1] == 'X')) {
1450 					token += 2;
1451 				}
1452 				continue;
1453 			}
1454 			return (0);
1455 		}
1456 		c = toupper(*token);
1457 		if (c >= 'A')
1458 			c = c - 'A' + 10 + '0';
1459 		*val = ((*val * 16) + (c - '0'));
1460 		token++;
1461 	}
1462 
1463 	return (1);
1464 }
1465 
1466 static int
1467 token_to_dec(char *token, unsigned *val, int len)
1468 {
1469 	*val = 0;
1470 
1471 	while (*token) {
1472 		if (!isdigit(*token)) {
1473 			if (*token == PARSE_COMMA) {
1474 				if (!(--len))
1475 					return (1);
1476 				val++;
1477 				*val = 0;
1478 				token++;
1479 				continue;
1480 			}
1481 			return (0);
1482 		}
1483 		*val = ((*val * 10) + (*token - '0'));
1484 		token++;
1485 	}
1486 
1487 	return (1);
1488 }
1489 
1490 static void
1491 cardbus_add_prop(struct cb_deviceset_props *cdsp, int type, char *name,
1492 		caddr_t vp, int len)
1493 {
1494 	ddi_prop_t *propp;
1495 	int	pnlen = strlen(name) + 1;
1496 
1497 	propp = (ddi_prop_t *)kmem_zalloc(sizeof (ddi_prop_t), KM_SLEEP);
1498 	propp->prop_name = (char *)kmem_alloc(pnlen, KM_SLEEP);
1499 	propp->prop_val = vp;
1500 	bcopy(name, propp->prop_name, pnlen);
1501 	propp->prop_len = len;
1502 	propp->prop_flags = type;
1503 	propp->prop_next = cdsp->prop_list;
1504 	cdsp->prop_list = propp;
1505 }
1506 
1507 static void
1508 cardbus_add_stringprop(struct cb_deviceset_props *cdsp, char *name,
1509 		char *vp, int len)
1510 {
1511 	char	*nstr = kmem_zalloc(len + 1, KM_SLEEP);
1512 
1513 	bcopy(vp, nstr, len);
1514 	cardbus_add_prop(cdsp, DDI_PROP_TYPE_STRING, name, (caddr_t)nstr,
1515 	    len + 1);
1516 }
1517 
1518 static void
1519 cardbus_prop_free(ddi_prop_t *propp)
1520 {
1521 	if (propp->prop_len) {
1522 		switch (propp->prop_flags) {
1523 		case DDI_PROP_TYPE_STRING:
1524 			kmem_free(propp->prop_val, propp->prop_len);
1525 			break;
1526 		case DDI_PROP_TYPE_INT:
1527 			kmem_free(propp->prop_val,
1528 			    propp->prop_len * sizeof (int));
1529 			break;
1530 		}
1531 	}
1532 	kmem_free(propp->prop_name, strlen(propp->prop_name) + 1);
1533 	kmem_free(propp, sizeof (ddi_prop_t *));
1534 }
1535 
1536 static void
1537 cardbus_devprops_free(struct cb_deviceset_props *cbdp)
1538 {
1539 	ddi_prop_t *propp, *npropp;
1540 
1541 	propp = cbdp->prop_list;
1542 	while (propp) {
1543 		npropp = propp->prop_next;
1544 		cardbus_prop_free(propp);
1545 		propp = npropp;
1546 	}
1547 	if (cbdp->nodename)
1548 		kmem_free(cbdp->nodename, strlen(cbdp->nodename) + 1);
1549 	if (cbdp->binding_name)
1550 		kmem_free(cbdp->binding_name, strlen(cbdp->binding_name) +
1551 		    1);
1552 	kmem_free(cbdp, sizeof (*cbdp));
1553 }
1554 
1555 /*
1556  * Format of "cb-device-init-props" property:
1557  * Anything before the semi-colon is an identifying equate, anything
1558  * after the semi-colon is a setting equate.
1559  *
1560  * "binding_name=xXxXxX VendorID=NNNN DeviceID=NNNN; nodename=NewName
1561  * 					Prop=PropVal"
1562  *
1563  */
1564 static int
1565 cardbus_parse_devprop(cbus_t *cbp, char *cp)
1566 {
1567 	int	state = PT_STATE_TOKEN, qm = 0, em = 0, smc = 0, l = 0;
1568 	int	length;
1569 	char	*token = "beginning of line";
1570 	char	*ptoken = NULL, *quote;
1571 	char	eq = NULL;
1572 	struct cb_deviceset_props *cdsp;
1573 
1574 	cdsp = (struct cb_deviceset_props *)kmem_zalloc(sizeof (*cdsp),
1575 	    KM_SLEEP);
1576 	length = strlen(cp);
1577 
1578 	while ((*cp) && (l < length)) {
1579 		/*
1580 		 * Check for escaped characters
1581 		 */
1582 		if (*cp == PARSE_ESCAPE) {
1583 			char	*cpp = cp, *cppp = cp + 1;
1584 
1585 			em = 1;
1586 
1587 			if (!qm) {
1588 				cmn_err(CE_CONT, "cardbus_parse_devprop: "
1589 				    "escape not allowed outside "
1590 				    "of quotes at [%s]\n", token);
1591 				return (DDI_FAILURE);
1592 
1593 			} /* if (!qm) */
1594 
1595 			while (*cppp)
1596 				*cpp++ = *cppp++;
1597 
1598 			l++;
1599 
1600 			*cpp = NULL;
1601 		} /* PARSE_ESCAPE */
1602 
1603 		/*
1604 		 * Check for quoted strings
1605 		 */
1606 		if (!em && (*cp == PARSE_QUOTE)) {
1607 			qm ^= 1;
1608 			if (qm) {
1609 				quote = cp + 1;
1610 			} else {
1611 				*cp = NULL;
1612 				if (state == PT_STATE_CHECK) {
1613 					if (strcmp(token, cb_nnamestr) == 0) {
1614 						cdsp->nodename = kmem_alloc(
1615 						    strlen(quote) + 1,
1616 						    KM_SLEEP);
1617 						(void) strcpy(cdsp->nodename,
1618 						    quote);
1619 					} else
1620 						cardbus_add_stringprop(cdsp,
1621 						    token, quote,
1622 						    strlen(quote));
1623 				} else if (state != PT_STATE_STRING_VAR) {
1624 					cmn_err(CE_CONT,
1625 					    "cardbus_parse_devprop: "
1626 					    "unexpected string [%s] after "
1627 					    "[%s]\n", quote, token);
1628 					return (DDI_FAILURE);
1629 				} else {
1630 					if (strcmp(token, cb_bnamestr) == 0) {
1631 						cdsp->binding_name = kmem_alloc(
1632 						    strlen(quote) + 1,
1633 						    KM_SLEEP);
1634 						(void) strcpy(
1635 						    cdsp->binding_name, quote);
1636 					}
1637 				}
1638 				state = PT_STATE_TOKEN;
1639 			} /* if (qm) */
1640 		} /* PARSE_QUOTE */
1641 
1642 		em = 0;
1643 
1644 		if (!qm && (*cp == PARSE_SEMICOLON)) {
1645 			smc = 1;
1646 		}
1647 
1648 		/*
1649 		 * Check for tokens
1650 		 */
1651 		else if (!qm && (isalpha(*cp) || isxdigit(*cp))) {
1652 			int	tl;
1653 			unsigned	*intp;
1654 			ptoken = token;
1655 			token = find_token(&cp, &l, &eq);
1656 
1657 			switch (state) {
1658 			case PT_STATE_TOKEN:
1659 				if (smc) {
1660 					if (eq == PARSE_EQUALS)
1661 						state = PT_STATE_CHECK;
1662 					else
1663 						cardbus_add_prop(cdsp,
1664 						    DDI_PROP_TYPE_ANY,
1665 						    token,
1666 						    NULL, 0);
1667 				} else if (eq == PARSE_EQUALS)
1668 					switch (state = parse_token(token)) {
1669 					case PT_STATE_UNKNOWN:
1670 						cmn_err(CE_CONT,
1671 						    "cardbus_parse_devprop: "
1672 						    "unknown token [%s]\n",
1673 						    token);
1674 						state = PT_STATE_TOKEN;
1675 					} /* switch (parse_token) */
1676 				else
1677 					state = PT_STATE_TOKEN;
1678 				break;
1679 
1680 			case PT_STATE_CHECK:
1681 				switch (check_token(token, &tl)) {
1682 				case PT_STATE_DEC_VAR:
1683 					intp = (unsigned *)kmem_alloc(
1684 					    sizeof (int)*tl,
1685 					    KM_SLEEP);
1686 					if (token_to_dec(token, intp, tl))
1687 						cardbus_add_prop(cdsp,
1688 						    DDI_PROP_TYPE_INT, ptoken,
1689 						    (caddr_t)intp, tl);
1690 					else
1691 						kmem_free(intp,
1692 						    sizeof (int)*tl);
1693 					break;
1694 				case PT_STATE_HEX_VAR:
1695 					intp = (unsigned *)kmem_alloc(
1696 					    sizeof (int)*tl,
1697 					    KM_SLEEP);
1698 					if (token_to_hex(token, intp, tl))
1699 						cardbus_add_prop(cdsp,
1700 						    DDI_PROP_TYPE_INT,
1701 						    ptoken,
1702 						    (caddr_t)intp, tl);
1703 					else
1704 						kmem_free(intp,
1705 						    sizeof (int)*tl);
1706 					break;
1707 				case PT_STATE_STRING_VAR:
1708 					if (strcmp(ptoken, cb_nnamestr) == 0) {
1709 						cdsp->nodename = kmem_alloc(
1710 						    tl + 1, KM_SLEEP);
1711 						(void) strcpy(cdsp->nodename,
1712 						    token);
1713 					} else
1714 						cardbus_add_stringprop(cdsp,
1715 						    ptoken, token, tl);
1716 					break;
1717 				}
1718 				state = PT_STATE_TOKEN;
1719 				break;
1720 
1721 			case PT_STATE_HEX_VAR:
1722 				if (strcmp(ptoken, cb_venidstr) == 0) {
1723 					uint_t val;
1724 					if (token_to_hex(token, &val, 1))
1725 						cdsp->venid = val;
1726 				} else if (strcmp(ptoken, cb_devidstr) == 0) {
1727 					uint_t val;
1728 					if (token_to_hex(token, &val, 1))
1729 						cdsp->devid = val;
1730 				}
1731 				state = PT_STATE_TOKEN;
1732 				break;
1733 
1734 			case PT_STATE_DEC_VAR:
1735 				if (strcmp(ptoken, cb_venidstr) == 0) {
1736 					uint_t val;
1737 					if (token_to_dec(token, &val, 1))
1738 						cdsp->venid = val;
1739 				} else if (strcmp(ptoken, cb_devidstr) == 0) {
1740 					uint_t val;
1741 					if (token_to_dec(token, &val, 1))
1742 						cdsp->devid = val;
1743 				}
1744 				state = PT_STATE_TOKEN;
1745 				break;
1746 
1747 			case PT_STATE_STRING_VAR:
1748 				if (strcmp(ptoken, cb_bnamestr) == 0) {
1749 					cdsp->binding_name = kmem_alloc(
1750 					    strlen(token) + 1, KM_SLEEP);
1751 					(void) strcpy(cdsp->binding_name,
1752 					    token);
1753 				}
1754 				state = PT_STATE_TOKEN;
1755 				break;
1756 
1757 			default:
1758 				cmn_err(CE_CONT, "cardbus_parse_devprop: "
1759 				    "unknown state machine state = %d\n",
1760 				    state);
1761 
1762 				cardbus_devprops_free(cdsp);
1763 				return (DDI_FAILURE);
1764 			} /* switch (state) */
1765 			if (eq == PARSE_SEMICOLON)
1766 				smc = 1;
1767 		}
1768 		cp++;
1769 		l++;
1770 	} /* while (*cp) */
1771 
1772 	if (qm) {
1773 		cmn_err(CE_CONT, "cb_props_parse_line: unterminated "
1774 		    "string = [%s]\n", quote);
1775 		cardbus_devprops_free(cdsp);
1776 		return (DDI_FAILURE);
1777 	}
1778 
1779 	if (state != PT_STATE_TOKEN) {
1780 		cmn_err(CE_CONT, "cardbus_parse_devprop: token [%s] "
1781 		    "requires value\n", token);
1782 		cardbus_devprops_free(cdsp);
1783 		return (DDI_FAILURE);
1784 	}
1785 
1786 	if (cdsp->venid == 0 || cdsp->devid == 0) {
1787 		cmn_err(CE_CONT, "cardbus_parse_devprop: Entry "
1788 		    "requires VendorID and DeviceID\n");
1789 		cardbus_devprops_free(cdsp);
1790 		return (DDI_FAILURE);
1791 	}
1792 
1793 	cdsp->next = cbp->cb_dsp;
1794 	cbp->cb_dsp = cdsp;
1795 	return (DDI_SUCCESS);
1796 }
1797 
1798 static void
1799 cardbus_device_props(cbus_t *cbp)
1800 {
1801 	char	**prop_array;
1802 	uint_t i, n;
1803 
1804 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, cbp->cb_dip,
1805 	    DDI_PROP_DONTPASS,
1806 	    "cb-device-init-props", &prop_array,
1807 	    &n) != DDI_PROP_SUCCESS)
1808 		return;
1809 
1810 	for (i = 0; i < n; i++)
1811 		(void) cardbus_parse_devprop(cbp, prop_array[i]);
1812 
1813 	ddi_prop_free(prop_array);
1814 }
1815 
1816 
1817 #include <vm/seg_kmem.h>
1818 extern int	pf_is_memory(pfn_t);
1819 #define	BUSTYPE_TO_PFN(btype, pfn) (((btype) << 19) | ((pfn) & 0x7FFFF))
1820 
1821 static int
1822 cardbus_rootnex_map_regspec(ddi_map_req_t *mp, caddr_t *vaddrp,
1823 			uint_t mapping_attr)
1824 {
1825 	ulong_t base;
1826 	caddr_t kaddr;
1827 	pgcnt_t npages;
1828 	pfn_t	pfn;
1829 	uint_t	pgoffset;
1830 	struct regspec *rp = mp->map_obj.rp;
1831 
1832 	/* base addr */
1833 	base = (ulong_t)rp->regspec_addr & (~MMU_PAGEOFFSET);
1834 
1835 	/*
1836 	 * Take the bustype and the physical page base within the
1837 	 * bus space and turn it into a 28 bit page frame number.
1838 	 */
1839 	pfn = BUSTYPE_TO_PFN(rp->regspec_bustype, mmu_btop(base));
1840 
1841 	/*
1842 	 * Do a quick sanity check to make sure we are in I/O space.
1843 	 */
1844 	if (pf_is_memory(pfn))
1845 		return (DDI_ME_INVAL);
1846 
1847 	if (rp->regspec_size == 0) {
1848 		cardbus_err(NULL, 1,
1849 		    "cardbus_rootnex_map_regspec: zero regspec_size\n");
1850 		return (DDI_ME_INVAL);
1851 	}
1852 
1853 	if (mp->map_flags & DDI_MF_DEVICE_MAPPING)
1854 		*vaddrp = (caddr_t)pfn;
1855 	else {
1856 		pgoffset = (ulong_t)rp->regspec_addr & MMU_PAGEOFFSET;
1857 		npages = mmu_btopr(rp->regspec_size + pgoffset);
1858 
1859 		cardbus_err(NULL, 8,
1860 		    "cardbus_rootnex_map_regspec: "
1861 		    "Mapping %lu pages physical %x.%lx ",
1862 		    npages, rp->regspec_bustype, base);
1863 
1864 		kaddr = vmem_alloc(heap_arena, ptob(npages), VM_NOSLEEP);
1865 		if (kaddr == NULL)
1866 			return (DDI_ME_NORESOURCES);
1867 
1868 		/*
1869 		 * Now map in the pages we've allocated...
1870 		 */
1871 		hat_devload(kas.a_hat, kaddr, ptob(npages), pfn,
1872 		    mp->map_prot | mapping_attr, HAT_LOAD_LOCK);
1873 
1874 		*vaddrp = kaddr + pgoffset;
1875 	}
1876 
1877 	cardbus_err(NULL, 8,
1878 	    "cardbus_rootnex_map_regspec: at virtual %p\n", (void *)*vaddrp);
1879 	return (0);
1880 }
1881 
1882 static int
1883 cardbus_rootnex_unmap_regspec(ddi_map_req_t *mp, caddr_t *vaddrp)
1884 {
1885 	caddr_t addr = *vaddrp;
1886 	pgcnt_t npages;
1887 	uint_t  pgoffset;
1888 	caddr_t base;
1889 	struct regspec *rp;
1890 
1891 	if (mp->map_flags & DDI_MF_DEVICE_MAPPING)
1892 		return (0);
1893 
1894 	rp = mp->map_obj.rp;
1895 	pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET;
1896 
1897 	if (rp->regspec_size == 0) {
1898 		cardbus_err(NULL, 1,
1899 		    "cardbus_rootnex_unmap_regspec: zero regspec_size\n");
1900 		return (DDI_ME_INVAL);
1901 	}
1902 
1903 	base = addr - pgoffset;
1904 	npages = mmu_btopr(rp->regspec_size + pgoffset);
1905 	hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK);
1906 	vmem_free(heap_arena, base, ptob(npages));
1907 
1908 	/*
1909 	 * Destroy the pointer - the mapping has logically gone
1910 	 */
1911 	*vaddrp = (caddr_t)0;
1912 
1913 	return (0);
1914 }
1915 
1916 static int
1917 cardbus_rootnex_map_handle(ddi_map_req_t *mp)
1918 {
1919 	ddi_acc_hdl_t *hp;
1920 	uint_t hat_flags;
1921 	register struct regspec *rp;
1922 
1923 	/*
1924 	 * Set up the hat_flags for the mapping.
1925 	 */
1926 	hp = mp->map_handlep;
1927 
1928 	switch (hp->ah_acc.devacc_attr_endian_flags) {
1929 	case DDI_NEVERSWAP_ACC:
1930 		hat_flags = HAT_NEVERSWAP | HAT_STRICTORDER;
1931 		break;
1932 	case DDI_STRUCTURE_BE_ACC:
1933 		hat_flags = HAT_STRUCTURE_BE;
1934 		break;
1935 	case DDI_STRUCTURE_LE_ACC:
1936 		hat_flags = HAT_STRUCTURE_LE;
1937 		break;
1938 	default:
1939 		return (DDI_REGS_ACC_CONFLICT);
1940 	}
1941 
1942 	switch (hp->ah_acc.devacc_attr_dataorder) {
1943 	case DDI_STRICTORDER_ACC:
1944 		break;
1945 	case DDI_UNORDERED_OK_ACC:
1946 		hat_flags |= HAT_UNORDERED_OK;
1947 		break;
1948 	case DDI_MERGING_OK_ACC:
1949 		hat_flags |= HAT_MERGING_OK;
1950 		break;
1951 	case DDI_LOADCACHING_OK_ACC:
1952 		hat_flags |= HAT_LOADCACHING_OK;
1953 		break;
1954 	case DDI_STORECACHING_OK_ACC:
1955 		hat_flags |= HAT_STORECACHING_OK;
1956 		break;
1957 	default:
1958 		return (DDI_FAILURE);
1959 	}
1960 
1961 	rp = mp->map_obj.rp;
1962 	if (rp->regspec_size == 0)
1963 		return (DDI_ME_INVAL);
1964 
1965 	hp->ah_hat_flags = hat_flags;
1966 	hp->ah_pfn = mmu_btop((ulong_t)rp->regspec_addr & (~MMU_PAGEOFFSET));
1967 	hp->ah_pnum = mmu_btopr(rp->regspec_size +
1968 	    (ulong_t)rp->regspec_addr & MMU_PAGEOFFSET);
1969 	return (DDI_SUCCESS);
1970 }
1971 
1972 static int
1973 cardbus_rootnex_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
1974 		off_t offset, off_t len, caddr_t *vaddrp)
1975 {
1976 	struct regspec *rp, tmp_reg;
1977 	ddi_map_req_t mr = *mp;	/* Get private copy of request */
1978 	int	error;
1979 	uint_t mapping_attr;
1980 	ddi_acc_hdl_t *hp = NULL;
1981 
1982 	mp = &mr;
1983 
1984 	switch (mp->map_op)  {
1985 	case DDI_MO_MAP_LOCKED:
1986 	case DDI_MO_UNMAP:
1987 	case DDI_MO_MAP_HANDLE:
1988 		break;
1989 	default:
1990 		cardbus_err(dip, 1,
1991 		    "cardbus_rootnex_map: unimplemented map op %d.",
1992 		    mp->map_op);
1993 		return (DDI_ME_UNIMPLEMENTED);
1994 	}
1995 
1996 	if (mp->map_flags & DDI_MF_USER_MAPPING)  {
1997 		cardbus_err(dip, 1,
1998 		    "cardbus_rootnex_map: unimplemented map type: user.");
1999 		return (DDI_ME_UNIMPLEMENTED);
2000 	}
2001 
2002 	/*
2003 	 * First, if given an rnumber, convert it to a regspec...
2004 	 * (Presumably, this is on behalf of a child of the root node)
2005 	 */
2006 
2007 	if (mp->map_type == DDI_MT_RNUMBER)  {
2008 
2009 		int	rnumber = mp->map_obj.rnumber;
2010 
2011 		rp = i_ddi_rnumber_to_regspec(rdip, rnumber);
2012 		if (rp == (struct regspec *)0)  {
2013 			cardbus_err(dip, 1,
2014 			    "cardbus_rootnex_map: Out of "
2015 			    "range rnumber <%d>, device <%s>",
2016 			    rnumber, ddi_get_name(rdip));
2017 			return (DDI_ME_RNUMBER_RANGE);
2018 		}
2019 
2020 		/*
2021 		 * Convert the given ddi_map_req_t from rnumber to regspec...
2022 		 */
2023 
2024 		mp->map_type = DDI_MT_REGSPEC;
2025 		mp->map_obj.rp = rp;
2026 	}
2027 
2028 	/*
2029 	 * Adjust offset and length correspnding to called values...
2030 	 */
2031 
2032 	tmp_reg = *(mp->map_obj.rp);	/* Preserve underlying data */
2033 	rp = mp->map_obj.rp = &tmp_reg;	/* Use tmp_reg in request */
2034 
2035 	rp->regspec_addr += (uint_t)offset;
2036 	if (len != 0)
2037 		rp->regspec_size = (uint_t)len;
2038 
2039 	/*
2040 	 * Apply any parent ranges at this level, if applicable.
2041 	 * (This is where nexus specific regspec translation takes place.
2042 	 * Use of this function is implicit agreement that translation is
2043 	 * provided via ddi_apply_range.)
2044 	 */
2045 	cardbus_err(dip, 1, "ppd: %p, %p\n",
2046 	    (void *) DEVI_PD(dip), (void *) DEVI_PD(rdip));
2047 
2048 	cardbus_err(dip, 8,
2049 	    "cardbus_rootnex_map: applying range of parent "
2050 	    "<%s> to child <%s>...\n", ddi_get_name(dip), ddi_get_name(rdip));
2051 
2052 	if ((error = i_ddi_apply_range(dip, rdip, mp->map_obj.rp)) != 0)
2053 		return (error);
2054 
2055 	switch (mp->map_op)  {
2056 	case DDI_MO_MAP_LOCKED:
2057 		/*
2058 		 * Set up the locked down kernel mapping to the regspec...
2059 		 */
2060 
2061 		/*
2062 		 * If we were passed an access handle we need to determine
2063 		 * the "endian-ness" of the mapping and fill in the handle.
2064 		 */
2065 		if (mp->map_handlep) {
2066 			hp = mp->map_handlep;
2067 			switch (hp->ah_acc.devacc_attr_endian_flags) {
2068 			case DDI_NEVERSWAP_ACC:
2069 				mapping_attr = HAT_NEVERSWAP | HAT_STRICTORDER;
2070 				break;
2071 			case DDI_STRUCTURE_BE_ACC:
2072 				mapping_attr = HAT_STRUCTURE_BE;
2073 				break;
2074 			case DDI_STRUCTURE_LE_ACC:
2075 				mapping_attr = HAT_STRUCTURE_LE;
2076 				break;
2077 			default:
2078 				return (DDI_REGS_ACC_CONFLICT);
2079 			}
2080 
2081 			switch (hp->ah_acc.devacc_attr_dataorder) {
2082 			case DDI_STRICTORDER_ACC:
2083 				break;
2084 			case DDI_UNORDERED_OK_ACC:
2085 				mapping_attr |= HAT_UNORDERED_OK;
2086 				break;
2087 			case DDI_MERGING_OK_ACC:
2088 				mapping_attr |= HAT_MERGING_OK;
2089 				break;
2090 			case DDI_LOADCACHING_OK_ACC:
2091 				mapping_attr |= HAT_LOADCACHING_OK;
2092 				break;
2093 			case DDI_STORECACHING_OK_ACC:
2094 				mapping_attr |= HAT_STORECACHING_OK;
2095 				break;
2096 			default:
2097 				return (DDI_REGS_ACC_CONFLICT);
2098 			}
2099 		} else {
2100 			mapping_attr = HAT_NEVERSWAP | HAT_STRICTORDER;
2101 		}
2102 
2103 		/*
2104 		 * Set up the mapping.
2105 		 */
2106 		error = cardbus_rootnex_map_regspec(mp, vaddrp, mapping_attr);
2107 
2108 		/*
2109 		 * Fill in the access handle if needed.
2110 		 */
2111 		if (hp) {
2112 			hp->ah_addr = *vaddrp;
2113 			hp->ah_hat_flags = mapping_attr;
2114 			if (error == 0)
2115 				impl_acc_hdl_init(hp);
2116 		}
2117 		return (error);
2118 
2119 	case DDI_MO_UNMAP:
2120 		/*
2121 		 * Release mapping...
2122 		 */
2123 		return (cardbus_rootnex_unmap_regspec(mp, vaddrp));
2124 
2125 	case DDI_MO_MAP_HANDLE:
2126 		return (cardbus_rootnex_map_handle(mp));
2127 
2128 	}
2129 
2130 	return (DDI_ME_UNIMPLEMENTED);
2131 }
2132 
2133 /*
2134  * dip an ancestor of rdip. Allocate space on dip for rdip
2135  */
2136 static int
2137 cardbus_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
2138 		off_t offset, off_t len, caddr_t *vaddrp)
2139 {
2140 	register dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent;
2141 	int	rc;
2142 
2143 	cardbus_err(dip, 9,
2144 	    "cardbus_bus_map(dip=0x%p, rdip=0x%p)\n",
2145 	    (void *) dip, (void *) rdip);
2146 
2147 	if (pdip == NULL)
2148 		return (DDI_FAILURE);
2149 
2150 	/* A child has asked us to set something up */
2151 	cardbus_err(dip, 9,
2152 	    "cardbus_bus_map(%s) calling %s - 0x%p, "
2153 	    "offset 0x%x, len 0x%x\n",
2154 	    ddi_driver_name(rdip),
2155 	    ddi_driver_name(pdip),
2156 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_map,
2157 	    (int)offset, (int)len);
2158 
2159 	rc = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
2160 	    (pdip, rdip, mp, offset, len, vaddrp);
2161 	/* rc = ddi_map(dip, mp, offset, len, vaddrp); */
2162 
2163 	if (rc != DDI_SUCCESS)
2164 		cardbus_err(rdip, 8, "cardbus_bus_map failed, rc = %d\n", rc);
2165 	else {
2166 		cardbus_err(rdip, 9, "cardbus_bus_map OK\n");
2167 		return (DDI_SUCCESS);
2168 	}
2169 
2170 	if (mp->map_type == DDI_MT_RNUMBER) {
2171 		int	rnumber = mp->map_obj.rnumber;
2172 		uint_t length;
2173 		pci_regspec_t *pci_rp;
2174 		struct regspec regspec;
2175 		ddi_map_req_t p_map_request;
2176 
2177 #if defined(CARDBUS_DEBUG)
2178 		if (cardbus_debug >= 9)
2179 			cardbus_dump_family_tree(dip);
2180 #endif
2181 
2182 		cardbus_err(rdip, 8,
2183 		    "cardbus_bus_map rnumber is %d\n", rnumber);
2184 
2185 		if (rnumber < 0)
2186 			return (DDI_ME_RNUMBER_RANGE);
2187 
2188 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
2189 		    DDI_PROP_DONTPASS, "reg",
2190 		    (int **)&pci_rp,
2191 		    &length) != DDI_PROP_SUCCESS)
2192 			return (DDI_FAILURE);
2193 
2194 		/*
2195 		 * I think this is bogus. You will never get a length of
2196 		 * zero if the lookup succeeds.
2197 		 */
2198 		if (length == 0) {
2199 			return (DDI_FAILURE);
2200 		}
2201 
2202 		/* cardbus_dump_reg(rdip, pci_rp, length); */
2203 
2204 		/* config space should have mapped in OK earlier */
2205 		ASSERT(rnumber > 0);
2206 		/* use as offset into assigned-addresses not reg */
2207 
2208 		if (rnumber >= length)
2209 			return (DDI_ME_RNUMBER_RANGE);
2210 
2211 		pci_rp += rnumber;
2212 
2213 		pcirp2rp(pci_rp, &regspec);
2214 		ddi_prop_free(pci_rp-rnumber);
2215 
2216 		regspec.regspec_addr += offset;
2217 		if (len)
2218 			regspec.regspec_size = len;
2219 
2220 		cardbus_err(dip, 1,
2221 		    "regspec: bustype 0x%x, addr 0x%x, size 0x%x\n",
2222 		    regspec.regspec_bustype,
2223 		    regspec.regspec_addr,
2224 		    regspec.regspec_size);
2225 
2226 		ASSERT(regspec.regspec_size > 0);
2227 
2228 		p_map_request = *mp;
2229 		p_map_request.map_type = DDI_MT_REGSPEC;
2230 		p_map_request.map_obj.rp = &regspec;
2231 
2232 		rc = cardbus_rootnex_map(dip, rdip, &p_map_request, 0, 0,
2233 		    vaddrp);
2234 		if (rc != DDI_SUCCESS)
2235 			cardbus_err(rdip, 8,
2236 			    "cardbus_bus_map(regspec): ddi_map failed, "
2237 			    "rc = %d\n", rc);
2238 		else {
2239 			cardbus_err(rdip, 7,
2240 			    "cardbus_bus_map(regspec): ddi_map OK\n");
2241 			return (DDI_SUCCESS);
2242 		}
2243 	}
2244 	return (rc);
2245 }
2246 
2247 static void
2248 pcirp2rp(const pci_regspec_t *pci_rp, struct regspec *rp)
2249 {
2250 	/* bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi); */
2251 	if (PCI_REG_ADDR_G(pci_rp->pci_phys_hi) ==
2252 	    PCI_REG_ADDR_G(PCI_ADDR_IO)) {
2253 		/* I/O */
2254 		rp->regspec_bustype = 1;
2255 	} else {
2256 		/* memory */
2257 		rp->regspec_bustype = 0;
2258 	}
2259 	rp->regspec_addr = pci_rp->pci_phys_low;
2260 	rp->regspec_size = pci_rp->pci_size_low;
2261 }
2262 
2263 static int
2264 cardbus_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
2265 		int (*waitfp)(caddr_t), caddr_t arg,
2266 		ddi_dma_handle_t *handlep)
2267 {
2268 	dev_info_t *pdip = ddi_get_parent(dip);
2269 
2270 	cardbus_err(dip, 10,
2271 	    "cardbus_dma_allochdl(dip=0x%p, rdip=0x%p)\n",
2272 	    (void *) dip, (void *) rdip);
2273 
2274 	if (pdip == NULL)
2275 		return (DDI_FAILURE);
2276 
2277 	cardbus_err(dip, 11,
2278 	    "cardbus_dma_allochdl calling %s - 0x%p\n",
2279 	    ddi_driver_name(pdip),
2280 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_allochdl);
2281 
2282 	return (ddi_dma_allochdl(dip, rdip, attr, waitfp, arg, handlep));
2283 }
2284 
2285 static int
2286 cardbus_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
2287 		ddi_dma_handle_t handle)
2288 {
2289 	dev_info_t *pdip = ddi_get_parent(dip);
2290 
2291 	cardbus_err(dip, 10,
2292 	    "cardbus_dma_freehdl(dip=0x%p, rdip=0x%p)\n",
2293 	    (void *) dip, (void *) rdip);
2294 
2295 	if (pdip == NULL)
2296 		return (DDI_FAILURE);
2297 
2298 	cardbus_err(dip, 11,
2299 	    "cardbus_dma_freehdl calling %s - 0x%p\n",
2300 	    ddi_driver_name(pdip),
2301 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_freehdl);
2302 
2303 	return (ddi_dma_freehdl(dip, rdip, handle));
2304 }
2305 
2306 static int
2307 cardbus_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
2308 		ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
2309 		ddi_dma_cookie_t *cp, uint_t *ccountp)
2310 {
2311 	dev_info_t *pdip = ddi_get_parent(dip);
2312 
2313 	cardbus_err(dip, 10,
2314 	    "cardbus_dma_bindhdl(dip=0x%p, rdip=0x%p)\n",
2315 	    (void *) dip, (void *) rdip);
2316 
2317 	if (pdip == NULL)
2318 		return (DDI_FAILURE);
2319 
2320 	cardbus_err(dip, 11,
2321 	    "cardbus_dma_bindhdl calling %s - 0x%p\n",
2322 	    ddi_driver_name(pdip),
2323 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_bindhdl);
2324 
2325 	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_bindhdl(pdip,
2326 	    rdip, handle, dmareq, cp, ccountp));
2327 }
2328 
2329 static int
2330 cardbus_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
2331 		ddi_dma_handle_t handle)
2332 {
2333 	dev_info_t *pdip = ddi_get_parent(dip);
2334 
2335 	cardbus_err(dip, 10,
2336 	    "cardbus_dma_unbindhdl(dip=0x%p, rdip=0x%p)\n",
2337 	    (void *) dip, (void *) rdip);
2338 
2339 	if (pdip == NULL)
2340 		return (DDI_FAILURE);
2341 
2342 	cardbus_err(dip, 11,
2343 	    "cardbus_dma_unbindhdl calling %s - 0x%p\n",
2344 	    ddi_driver_name(pdip),
2345 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl);
2346 
2347 	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl(pdip,
2348 	    rdip, handle));
2349 }
2350 
2351 static int
2352 cardbus_dma_flush(dev_info_t *dip, dev_info_t *rdip,
2353 		ddi_dma_handle_t handle, off_t off, size_t len,
2354 		uint_t cache_flags)
2355 {
2356 	dev_info_t *pdip = ddi_get_parent(dip);
2357 
2358 	cardbus_err(dip, 10,
2359 	    "cardbus_dma_flush(dip=0x%p, rdip=0x%p)\n",
2360 	    (void *) dip, (void *) rdip);
2361 
2362 	if (pdip == NULL)
2363 		return (DDI_FAILURE);
2364 
2365 	cardbus_err(dip, 11,
2366 	    "cardbus_dma_flush calling %s - 0x%p\n",
2367 	    ddi_driver_name(pdip),
2368 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_flush);
2369 
2370 	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_flush(pdip, rdip,
2371 	    handle, off, len, cache_flags));
2372 }
2373 
2374 static int
2375 cardbus_dma_win(dev_info_t *dip, dev_info_t *rdip,
2376 		ddi_dma_handle_t handle, uint_t win, off_t *offp,
2377 		size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
2378 {
2379 	dev_info_t *pdip = ddi_get_parent(dip);
2380 	cardbus_err(dip, 6,
2381 	    "cardbus_dma_win(dip=0x%p, rdip=0x%p)\n",
2382 	    (void *) dip, (void *) rdip);
2383 
2384 	if (pdip == NULL)
2385 		return (DDI_FAILURE);
2386 
2387 	cardbus_err(dip, 8,
2388 	    "cardbus_dma_win calling %s - 0x%p\n",
2389 	    ddi_driver_name(pdip),
2390 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_win);
2391 
2392 	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_win(pdip, rdip,
2393 	    handle, win, offp, lenp, cookiep, ccountp));
2394 }
2395 
2396 static int
2397 cardbus_dma_map(dev_info_t *dip, dev_info_t *rdip,
2398 		struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
2399 {
2400 	dev_info_t *pdip = ddi_get_parent(dip);
2401 
2402 	cardbus_err(dip, 10,
2403 	    "cardbus_dma_map(dip=0x%p, rdip=0x%p)\n",
2404 	    (void *) dip, (void *) rdip);
2405 
2406 	if (pdip == NULL)
2407 		return (DDI_FAILURE);
2408 
2409 	cardbus_err(dip, 11,
2410 	    "cardbus_dma_map calling %s - 0x%p\n",
2411 	    ddi_driver_name(pdip),
2412 	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_map);
2413 
2414 	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_map(pdip, rdip,
2415 	    dmareqp, handlep));
2416 }
2417 
2418 static int
2419 cardbus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
2420 		char *eventname, ddi_eventcookie_t *cookiep)
2421 {
2422 	cbus_t *cbp;
2423 	int	cb_instance;
2424 	int	rc;
2425 
2426 	/*
2427 	 * get the soft state structure for the bus instance.
2428 	 */
2429 	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2430 	    DDI_PROP_DONTPASS, "cbus-instance", -1);
2431 	ASSERT(cb_instance >= 0);
2432 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
2433 
2434 	cardbus_err(dip, 6, "cardbus_get_eventcookie %s\n", eventname);
2435 
2436 	ASSERT(number_of_cardbus_cards != 0);
2437 
2438 	if (cbp->cb_ndi_event_hdl == NULL) {
2439 		/*
2440 		 * We can't handle up (probably called at the attachment
2441 		 * point) so pass it on up
2442 		 */
2443 		dev_info_t *pdip = ddi_get_parent(dip);
2444 		cardbus_err(dip, 8,
2445 		    "cardbus_get_eventcookie calling %s - 0x%p\n",
2446 		    ddi_driver_name(pdip),
2447 		    (void *)
2448 		    DEVI(pdip)->devi_ops->devo_bus_ops->bus_get_eventcookie);
2449 		return (DEVI(pdip)->devi_ops->devo_bus_ops->
2450 		    bus_get_eventcookie(pdip, rdip, eventname, cookiep));
2451 	}
2452 
2453 	cardbus_err(dip, 8,
2454 	    "cardbus_get_eventcookie calling ndi_event_retrieve_cookie\n");
2455 
2456 	rc = ndi_event_retrieve_cookie(cbp->cb_ndi_event_hdl, rdip, eventname,
2457 	    cookiep, NDI_EVENT_NOPASS);
2458 
2459 	cardbus_err(dip, 7,
2460 	    "cardbus_get_eventcookie rc %d cookie %p\n", rc, (void *)*cookiep);
2461 	return (rc);
2462 }
2463 
2464 static int
2465 cardbus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
2466 		ddi_eventcookie_t cookie, void (*callback)(dev_info_t *dip,
2467 		ddi_eventcookie_t cookie, void *arg, void *bus_impldata),
2468 		void *arg, ddi_callback_id_t *cb_id)
2469 {
2470 	cbus_t *cbp;
2471 	int	cb_instance;
2472 	int	rc;
2473 
2474 	/*
2475 	 * get the soft state structure for the bus instance.
2476 	 */
2477 	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2478 	    DDI_PROP_DONTPASS, "cbus-instance", -1);
2479 	ASSERT(cb_instance >= 0);
2480 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
2481 
2482 	cardbus_err(dip, 6, "cardbus_add_eventcall\n");
2483 
2484 	ASSERT(number_of_cardbus_cards != 0);
2485 
2486 	if (cbp->cb_ndi_event_hdl == NULL) {
2487 		/*
2488 		 * We can't handle up (probably called at the attachment
2489 		 * point) so pass it on up
2490 		 */
2491 		dev_info_t *pdip = ddi_get_parent(dip);
2492 		cardbus_err(dip, 8,
2493 		    "cardbus_add_eventcall calling %s - 0x%p\n",
2494 		    ddi_driver_name(pdip),
2495 		    (void *)
2496 		    DEVI(pdip)->devi_ops->devo_bus_ops->bus_add_eventcall);
2497 		return (DEVI(pdip)->devi_ops->devo_bus_ops->
2498 		    bus_add_eventcall(pdip, rdip, cookie, callback,
2499 		    arg, cb_id));
2500 	}
2501 
2502 	cardbus_err(dip, 8,
2503 	    "cardbus_add_eventcall calling ndi_event_add_callback\n");
2504 
2505 	rc = ndi_event_add_callback(cbp->cb_ndi_event_hdl, rdip, cookie,
2506 	    callback, arg, NDI_EVENT_NOPASS, cb_id);
2507 	cardbus_err(dip, 7,
2508 	    "cardbus_add_eventcall rc %d cookie %p\n", rc, (void *)cookie);
2509 	return (rc);
2510 }
2511 
2512 static int
2513 cardbus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
2514 {
2515 	cbus_t *cbp;
2516 	int	cb_instance;
2517 
2518 	/*
2519 	 * get the soft state structure for the bus instance.
2520 	 */
2521 	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2522 	    DDI_PROP_DONTPASS, "cbus-instance", -1);
2523 	ASSERT(cb_instance >= 0);
2524 	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
2525 
2526 	cardbus_err(dip, 6, "cardbus_remove_eventcall\n");
2527 
2528 	ASSERT(number_of_cardbus_cards != 0);
2529 
2530 	if (cbp->cb_ndi_event_hdl == NULL) {
2531 		/*
2532 		 * We can't handle up (probably called at the attachment
2533 		 * point) so pass it on up
2534 		 */
2535 		dev_info_t *pdip = ddi_get_parent(dip);
2536 		cardbus_err(dip, 8,
2537 		    "cardbus_remove_eventcall calling %s - 0x%p\n",
2538 		    ddi_driver_name(pdip),
2539 		    (void *)
2540 		    DEVI(pdip)->devi_ops->devo_bus_ops->bus_remove_eventcall);
2541 		return (DEVI(pdip)->devi_ops->devo_bus_ops->
2542 		    bus_remove_eventcall(pdip, cb_id));
2543 	}
2544 
2545 	return (ndi_event_remove_callback(cbp->cb_ndi_event_hdl, cb_id));
2546 }
2547 
2548 static int
2549 cardbus_post_event(dev_info_t *dip, dev_info_t *rdip,
2550 		ddi_eventcookie_t cookie, void *bus_impldata)
2551 {
2552 	_NOTE(ARGUNUSED(rdip, cookie, bus_impldata))
2553 	cardbus_err(dip, 1, "cardbus_post_event()\n");
2554 	return (DDI_FAILURE);
2555 }
2556 
2557 #ifdef sparc
2558 
2559 static int cardbus_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2560 		ddi_intr_handle_impl_t *hdlp);
2561 static int cardbus_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2562 		ddi_intr_handle_impl_t *hdlp);
2563 static int cardbus_enable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2564 		ddi_intr_handle_impl_t *hdlp);
2565 static int cardbus_disable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2566 		ddi_intr_handle_impl_t *hdlp);
2567 
2568 /*ARGSUSED*/
2569 static int
2570 cardbus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
2571 	ddi_intr_handle_impl_t *hdlp, void *result)
2572 {
2573 	int ret = DDI_SUCCESS;
2574 
2575 #if defined(CARDBUS_DEBUG)
2576 	cardbus_err(dip, 8, "cardbus_intr_ops() intr_op=%d\n", (int)intr_op);
2577 #endif
2578 
2579 	switch (intr_op) {
2580 	case DDI_INTROP_GETCAP:
2581 		*(int *)result = DDI_INTR_FLAG_LEVEL;
2582 		break;
2583 	case DDI_INTROP_ALLOC:
2584 		*(int *)result = hdlp->ih_scratch1;
2585 		break;
2586 	case DDI_INTROP_FREE:
2587 		break;
2588 	case DDI_INTROP_GETPRI:
2589 		*(int *)result = hdlp->ih_pri ?
2590 		    hdlp->ih_pri : cardbus_get_class_pil(rdip);
2591 		break;
2592 	case DDI_INTROP_SETPRI:
2593 		break;
2594 	case DDI_INTROP_ADDISR:
2595 	case DDI_INTROP_REMISR:
2596 		if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) {
2597 			cardbus_err(dip, 1, "Only fixed interrupts\n");
2598 			return (DDI_FAILURE);
2599 		}
2600 		break;
2601 	case DDI_INTROP_ENABLE:
2602 		ret = cardbus_enable_intr_impl(dip, rdip, hdlp);
2603 		break;
2604 	case DDI_INTROP_DISABLE:
2605 		ret = cardbus_disable_intr_impl(dip, rdip, hdlp);
2606 		break;
2607 	case DDI_INTROP_NINTRS:
2608 	case DDI_INTROP_NAVAIL:
2609 		*(int *)result = i_ddi_get_nintrs(rdip);
2610 		break;
2611 	case DDI_INTROP_SUPPORTED_TYPES:
2612 		*(int *)result = i_ddi_get_nintrs(rdip) ?
2613 		    DDI_INTR_TYPE_FIXED : 0;
2614 		break;
2615 	default:
2616 		ret = DDI_ENOTSUP;
2617 		break;
2618 	}
2619 
2620 	return (ret);
2621 }
2622 
2623 static int
2624 cardbus_enable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2625 		ddi_intr_handle_impl_t *hdlp)
2626 {
2627 	anp_t *anp = (anp_t *)ddi_get_driver_private(dip);
2628 	set_irq_handler_t sih;
2629 	uint_t socket = 0; /* We only support devices */
2630 			    /* with one socket per function */
2631 
2632 	ASSERT(anp != NULL);
2633 
2634 	cardbus_err(dip, 9,
2635 	    "cardbus_enable_intr_impl, intr=0x%p, arg1=0x%p, arg2=0x%p"
2636 	    "rdip=0x%p(%s)\n",
2637 	    (void *) hdlp->ih_cb_func,
2638 	    hdlp->ih_cb_arg1, hdlp->ih_cb_arg2,
2639 	    (void *) rdip, ddi_driver_name(rdip));
2640 
2641 	if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) {
2642 		cardbus_err(dip, 1, "Only fixed interrupts\n");
2643 		return (DDI_FAILURE);
2644 	}
2645 
2646 	sih.socket = socket;
2647 	sih.handler_id = (uint64_t)rdip;
2648 	sih.handler = (f_tt *)hdlp->ih_cb_func;
2649 	sih.arg1 = hdlp->ih_cb_arg1;
2650 	sih.arg2 = hdlp->ih_cb_arg2;
2651 	sih.irq = cardbus_get_class_pil(rdip);
2652 
2653 	if ((*anp->an_if->pcif_set_interrupt)(dip, &sih) != SUCCESS)
2654 		return (DDI_FAILURE);
2655 
2656 	return (DDI_SUCCESS);
2657 }
2658 
2659 static int
2660 cardbus_disable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2661 		ddi_intr_handle_impl_t *hdlp)
2662 {
2663 	anp_t *anp = (anp_t *)ddi_get_driver_private(dip);
2664 	clear_irq_handler_t cih;
2665 	uint_t socket = 0; /* We only support devices with 1 socket per */
2666 			    /* function. */
2667 
2668 	ASSERT(anp != NULL);
2669 
2670 	cardbus_err(dip, 9,
2671 	    "cardbus_disable_intr_impl, intr=0x%p, arg1=0x%p, arg2=0x%p"
2672 	    "rdip=0x%p(%s%d)\n",
2673 	    (void *) hdlp->ih_cb_func,
2674 	    hdlp->ih_cb_arg1, hdlp->ih_cb_arg2,
2675 	    (void *) rdip, ddi_driver_name(rdip), ddi_get_instance(rdip));
2676 
2677 	if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) {
2678 		cardbus_err(dip, 1, "Only fixed interrupts\n");
2679 		return (DDI_FAILURE);
2680 	}
2681 
2682 	cih.socket = socket;
2683 	cih.handler_id = (uint64_t)rdip;
2684 	cih.handler = (f_tt *)hdlp->ih_cb_func;
2685 
2686 	if ((*anp->an_if->pcif_clr_interrupt)(dip, &cih) != SUCCESS)
2687 		return (DDI_FAILURE);
2688 
2689 	return (DDI_SUCCESS);
2690 }
2691 
2692 #elif defined(__x86) || defined(__amd64)
2693 static int
2694 cardbus_intr_ops(dev_info_t *dip, dev_info_t *rdip,
2695 		ddi_intr_op_t op, ddi_intr_handle_impl_t *hdlp,
2696 		void *result)
2697 {
2698 	_NOTE(ARGUNUSED(dip));
2699 	return i_ddi_intr_ops(ddi_get_parent(rdip), ddi_get_parent(rdip),
2700 			op, (void *)hdlp, result);
2701 }
2702 
2703 #endif /* ifdef sparc */
2704 
2705 #if defined(CARDBUS_DEBUG)
2706 static int	cardbus_do_pprintf = 0;
2707 #endif
2708 
2709 /*PRINTFLIKE3*/
2710 void
2711 cardbus_err(dev_info_t *dip, int level, const char *fmt, ...)
2712 {
2713 	if (cardbus_debug && (level <= cardbus_debug)) {
2714 		va_list adx;
2715 		int	instance;
2716 		char	buf[256];
2717 		const char	*name;
2718 		char	*nl = "";
2719 #if !defined(CARDBUS_DEBUG)
2720 		int	ce;
2721 		char	qmark = 0;
2722 
2723 		if (level <= 3)
2724 			ce = CE_WARN;
2725 		else
2726 			ce = CE_CONT;
2727 		if (level == 4)
2728 			qmark = 1;
2729 #endif
2730 
2731 		if (dip) {
2732 			instance = ddi_get_instance(dip);
2733 			/* name = ddi_binding_name(dip); */
2734 			name = ddi_driver_name(dip);
2735 		} else {
2736 			instance = 0;
2737 			name = "";
2738 		}
2739 
2740 		va_start(adx, fmt);
2741 		/* vcmn_err(ce, fmt, adx); */
2742 		/* vprintf(fmt, adx); */
2743 		/* prom_vprintf(fmt, adx); */
2744 		(void) vsprintf(buf, fmt, adx);
2745 		va_end(adx);
2746 
2747 		if (buf[strlen(buf) - 1] != '\n')
2748 			nl = "\n";
2749 
2750 #if defined(CARDBUS_DEBUG)
2751 		if (cardbus_do_pprintf) {
2752 			if (dip) {
2753 				if (instance >= 0)
2754 					prom_printf("%s(%d),0x%p: %s%s",
2755 					    name, instance, dip, buf, nl);
2756 				else
2757 					prom_printf("%s,0x%p: %s%s", name,
2758 					    dip, buf, nl);
2759 			} else
2760 				prom_printf("%s%s", buf, nl);
2761 		} else {
2762 			if (dip) {
2763 				if (instance >= 0)
2764 					cmn_err(CE_CONT, "%s(%d),0x%p: %s%s",
2765 					    name, instance, (void *) dip,
2766 					    buf, nl);
2767 				else
2768 					cmn_err(CE_CONT, "%s,0x%p: %s%s",
2769 					    name, (void *) dip, buf, nl);
2770 			} else
2771 				cmn_err(CE_CONT, "%s%s", buf, nl);
2772 		}
2773 #else
2774 		if (dip)
2775 			cmn_err(ce, qmark ? "?%s%d: %s%s" : "%s%d: %s%s",
2776 			    name, instance, buf, nl);
2777 		else
2778 			cmn_err(ce, qmark ? "?%s%s" : "%s%s", buf, nl);
2779 #endif
2780 	}
2781 }
2782 
2783 static void cardbus_expand_busrange(dev_info_t *dip)
2784 {
2785 	dev_info_t *pdip;
2786 	cardbus_bus_range_t *bus_range;
2787 	int len;
2788 
2789 	pdip = ddi_get_parent(dip);
2790 
2791 	if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, "bus-range",
2792 	    (caddr_t)&bus_range, &len) == DDI_PROP_SUCCESS) {
2793 		ndi_ra_request_t req;
2794 		uint64_t next_bus, blen;
2795 		uint32_t ret;
2796 		ddi_acc_handle_t handle;
2797 
2798 		if (bus_range->lo != bus_range->hi)
2799 			cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2800 			    "%u -> %u\n", bus_range->lo, bus_range->hi);
2801 		else {
2802 
2803 			bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
2804 			req.ra_addr = bus_range->lo + 1;
2805 			req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
2806 			req.ra_len = 12;
2807 
2808 			while ((req.ra_len > 0) &&
2809 			    (ret = ndi_ra_alloc(ddi_get_parent(pdip), &req,
2810 			    &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
2811 			    NDI_RA_PASS)) != NDI_SUCCESS)
2812 				req.ra_len--;
2813 
2814 			if (ret != NDI_SUCCESS) {
2815 				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2816 				    "fail to allocate bus number\n");
2817 				goto exit;
2818 			}
2819 
2820 			bus_range->hi = bus_range->lo + req.ra_len;
2821 			if (ndi_prop_update_int_array(DDI_DEV_T_NONE, pdip,
2822 			    "bus-range", (int *)bus_range, 2) != DDI_SUCCESS) {
2823 				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2824 				    "fail to update bus-range property\n");
2825 				goto exit;
2826 			}
2827 
2828 			if (pci_config_setup(pdip, &handle) != DDI_SUCCESS) {
2829 				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2830 				    "fail to pci_config_setup\n");
2831 				goto exit;
2832 			}
2833 
2834 			pci_config_put8(handle, PCI_BCNF_SECBUS, bus_range->lo);
2835 			pci_config_put8(handle, PCI_BCNF_SUBBUS, bus_range->hi);
2836 
2837 			cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2838 			    "parent dip %u -> %u\n",
2839 			    pci_config_get8(handle, PCI_BCNF_SECBUS),
2840 			    pci_config_get8(handle, PCI_BCNF_SUBBUS));
2841 			pci_config_teardown(&handle);
2842 
2843 			if (ndi_ra_map_setup(pdip, NDI_RA_TYPE_PCI_BUSNUM)
2844 			    != NDI_SUCCESS) {
2845 				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2846 				    "fail to ndi_ra_map_setup of bus number\n");
2847 				goto exit;
2848 			}
2849 
2850 			(void) ndi_ra_free(pdip,
2851 			    (uint64_t)bus_range->lo + 1, req.ra_len,
2852 			    NDI_RA_TYPE_PCI_BUSNUM, 0);
2853 		}
2854 
2855 		bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
2856 		req.ra_len = 2;
2857 
2858 		while ((req.ra_len > 0) &&
2859 		    (ret = ndi_ra_alloc(pdip, &req,
2860 		    &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
2861 		    0)) != NDI_SUCCESS)
2862 			req.ra_len--;
2863 
2864 		cardbus_err(dip, 1, "cardbus_expand_busrange: "
2865 		    "cardbus dip base %u length %d\n",
2866 		    (int)next_bus, (int)req.ra_len);
2867 
2868 		if (ret != NDI_SUCCESS) {
2869 			cardbus_err(dip, 1, "cardbus_expand_busrange: "
2870 			    "fail to allocate bus number of length %d "
2871 			    "from parent\n",
2872 			    (int)req.ra_len);
2873 			goto exit;
2874 		}
2875 
2876 		if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_BUSNUM)
2877 		    != NDI_SUCCESS) {
2878 			cardbus_err(dip, 1, "cardbus_expand_busrange: "
2879 			    "fail to ndi_ra_map_setup of bus numbers\n");
2880 			goto exit;
2881 		}
2882 
2883 		(void) ndi_ra_free(dip,
2884 		    (uint64_t)next_bus, req.ra_len,
2885 		    NDI_RA_TYPE_PCI_BUSNUM, 0);
2886 exit:
2887 		kmem_free(bus_range, len);
2888 
2889 	} else
2890 		cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2891 		    "parent dip doesn't have busrange prop\n");
2892 }
2893