1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * Copyright (c)  * Copyright (c) 2001 Tadpole Technology plc
28 * All rights reserved.
29 * From "@(#)pcicfg.c   1.31    99/06/18 SMI"
30 */
31
32#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
73static 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
79static int cardbus_next_instance = 0;
80static int cardbus_count = 0;
81int number_of_cardbus_cards = 0;
82
83static 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);
85static void pcirp2rp(const pci_regspec_t *pci_rp, struct regspec *rp);
86
87static int cardbus_ctlops(dev_info_t *, dev_info_t *,
88			ddi_ctl_enum_t, void *arg, void *);
89static void cardbus_init_child_regs(dev_info_t *child);
90static int cardbus_initchild(dev_info_t *, dev_info_t *,
91			dev_info_t *, void *);
92static int cardbus_name_child(dev_info_t *, char *, int);
93static void cardbus_removechild(dev_info_t *dip);
94
95static 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);
98static int cardbus_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
99		ddi_dma_handle_t handle);
100static 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);
103static int cardbus_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
104		ddi_dma_handle_t handle);
105static 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);
108static 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);
111static int cardbus_dma_map(dev_info_t *dip, dev_info_t *rdip,
112		struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep);
113
114static 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
118static int cardbus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
119		char *eventname, ddi_eventcookie_t *cookiep);
120static 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);
124static int cardbus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id);
125static int cardbus_post_event(dev_info_t *dip, dev_info_t *rdip,
126		ddi_eventcookie_t cookie, void *bus_impldata);
127
128static 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
132static int check_token(char *token, int *len);
133static char *find_token(char **cp, int *l, char *endc);
134static int parse_token(char *token);
135static int token_to_hex(char *token, unsigned *val, int len);
136static int token_to_dec(char *token, unsigned *val, int len);
137static void cardbus_add_prop(struct cb_deviceset_props *cdsp, int type,
138		char *name, caddr_t vp, int len);
139static void cardbus_add_stringprop(struct cb_deviceset_props *cdsp,
140		char *name, char *vp, int len);
141static void cardbus_prop_free(ddi_prop_t *propp);
142static void cardbus_devprops_free(struct cb_deviceset_props *cbdp);
143static int cardbus_parse_devprop(cbus_t *cbp, char *cp);
144static void cardbus_device_props(cbus_t *cbp);
145
146static void cardbus_expand_busrange(dev_info_t *dip);
147
148static int cardbus_convert_properties(dev_info_t *dip);
149static void cardbus_revert_properties(dev_info_t *dip);
150
151/*
152 * driver global data
153 */
154kmutex_t cardbus_list_mutex; /* Protects the probe handle list */
155void *cardbus_state;
156int cardbus_latency_timer = 0x40;
157int cardbus_debug = 0;
158
159/*
160 * Module linkage information for the kernel.
161 */
162extern struct mod_ops mod_miscops;
163static struct modlmisc modlmisc = {
164	&mod_miscops,
165	"Cardbus Configurator support",
166};
167
168static struct modlinkage modlinkage = {
169	MODREV_1,
170	&modlmisc,
171	NULL
172};
173
174int
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
191int
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
202int
203_info(struct modinfo *modinfop)
204{
205	return (mod_info(&modlinkage, modinfop));
206}
207
208static
209struct 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
244static 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
253struct busnum_ctrl {
254	int	rv;
255	dev_info_t *dip;
256	cardbus_bus_range_t *range;
257};
258
259static int
260cardbus_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
316static void
317cardbus_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
332static 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
390static dev_info_t *
391cardbus_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 */
409int
410cardbus_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
514static int
515cardbus_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
574boolean_t
575cardbus_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 */
668void
669cardbus_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
678	cardbus_err(dip, 6, "cardbus_unload_cardbus\n");
679
680	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
681	    DDI_PROP_DONTPASS, "cbus-instance", -1);
682	ASSERT(cb_instance >= 0);
683	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
684
685	if (number_of_cardbus_cards == 0)
686		return;
687
688#ifdef HOTPLUG
689	mutex_enter(&cbp->cb_mutex);
690	cbp->card_present = B_FALSE;
691
692	(void) hpc_slot_event_notify(cbp->slot_handle,
693	    HPC_EVENT_SLOT_POWER_OFF, 0);
694	(void) hpc_slot_event_notify(cbp->slot_handle,
695	    HPC_EVENT_SLOT_UNCONFIGURE, 0);
696	(void) hpc_slot_event_notify(cbp->slot_handle,
697	    HPC_EVENT_SLOT_REMOVAL, 0);
698
699	mutex_exit(&cbp->cb_mutex);
700#else
701
702	cardbus_err(dip, 8,
703	    "cardbus_unload_cardbus: calling cardbus_unconfigure_node\n");
704
705	rval = cardbus_unconfigure_node(dip, prim_bus, B_TRUE);
706
707	if (rval != NDI_SUCCESS) {
708		cardbus_err(dip, 4,
709		    "cardbus_unload_cardbus: "
710		    "cardbus_unconfigure_node failed\n");
711		number_of_cardbus_cards--;
712		cbp->fatal_problem = B_TRUE;
713		cmn_err(CE_WARN,
714		    "cardbus(%s%d): Failed to remove device tree: "
715		    "Slot disabled",
716		    ddi_get_name(dip), ddi_get_instance(dip));
717		return;
718	}
719
720	(void) cardbus_unconfigure(cbp);
721#endif
722
723	/*
724	 * Inform the lower drivers that the card has been removed
725	 */
726	if (cbp->cb_ndi_event_hdl != NULL) {
727		ddi_eventcookie_t cookie;
728		if (ndi_event_retrieve_cookie(cbp->cb_ndi_event_hdl, dip,
729		    DDI_DEVI_REMOVE_EVENT, &cookie, 0) == NDI_SUCCESS) {
730			(void) ndi_event_run_callbacks(cbp->cb_ndi_event_hdl,
731			    dip, cookie, NULL);
732		}
733	}
734
735	cardbus_revert_properties(dip);
736}
737
738static boolean_t
739is_32bit_pccard(dev_info_t *dip)
740{
741	int len;
742	char bus_type[16];
743
744	len = sizeof (bus_type);
745	if (ddi_prop_op(DDI_DEV_T_ANY, ddi_get_parent(dip),
746		PROP_LEN_AND_VAL_BUF,
747		DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
748		"device_type",
749		(caddr_t)&bus_type, &len) != DDI_SUCCESS)
750		return (B_FALSE);
751
752	if ((strcmp(bus_type, "pci") != 0) &&
753	    (strcmp(bus_type, "pciex") != 0) &&
754	    (strcmp(bus_type, "cardbus") != 0)) /* not of pci type */
755		return (B_FALSE);
756
757	return (B_TRUE);
758}
759
760void
761cardbus_save_children(dev_info_t *dip)
762{
763	for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
764		cardbus_save_children(ddi_get_child(dip));
765
766		if (strcmp("pcs", ddi_node_name(dip)) == 0)
767			continue;
768		if (!is_32bit_pccard(dip))
769			continue;
770		cardbus_err(dip, 1, "Saving device\n");
771		(void) pci_save_config_regs(dip);
772	}
773
774}
775
776void
777cardbus_restore_children(dev_info_t *dip)
778{
779	for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
780		cardbus_restore_children(ddi_get_child(dip));
781
782		if (strcmp("pcs", ddi_node_name(dip)) == 0)
783			continue;
784		if (!is_32bit_pccard(dip))
785			continue;
786		cardbus_err(dip, 1, "restoring device\n");
787		(void) pci_restore_config_regs(dip);
788	}
789
790}
791
792static int
793cardbus_convert_properties(dev_info_t *dip)
794{
795	struct pcm_regs *pcic_avail_p, *old_avail_p;
796	pci_regspec_t *cb_avail_p, *new_avail_p;
797	pcic_ranges_t *pcic_range_p, *old_range_p;
798	cardbus_range_t *cb_range_p, *new_range_p;
799	int range_len, range_entries, i;
800	int avail_len, avail_entries;
801
802#if defined(CARDBUS_DEBUG)
803	cardbus_err(dip, 6, "cardbus_convert_properties\n");
804#endif
805
806	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
807	    "#address-cells", 3) != DDI_SUCCESS) {
808		cardbus_err(dip, 1, "cardbus_convert_properties: "
809		    "failed to update #address-cells property\n");
810		return (DDI_FAILURE);
811	}
812	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
813	    "#size-cells", 2) != DDI_SUCCESS) {
814		cardbus_err(dip, 1, "cardbus_convert_properties: "
815		    "failed to update #size-cells property\n");
816		return (DDI_FAILURE);
817	}
818
819	if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "available",
820	    (caddr_t)&pcic_avail_p, &avail_len) != DDI_PROP_SUCCESS) {
821		cardbus_err(dip, 1, "cardbus_convert_properties: "
822		    "no available property for pcmcia\n");
823	} else {
824		avail_entries = avail_len / sizeof (struct pcm_regs);
825		cb_avail_p = kmem_alloc(sizeof (pci_regspec_t) * avail_entries,
826		    KM_SLEEP);
827
828		old_avail_p = pcic_avail_p;
829		new_avail_p = cb_avail_p;
830		for (i = 0; i < avail_entries;
831		    i++, old_avail_p++, new_avail_p++) {
832			new_avail_p->pci_phys_hi = old_avail_p->phys_hi;
833			new_avail_p->pci_phys_mid = 0;
834			new_avail_p->pci_phys_low = old_avail_p->phys_lo;
835			new_avail_p->pci_size_hi = 0;
836			new_avail_p->pci_size_low = old_avail_p->phys_len;
837		}
838
839		(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
840		    "available",
841		    (int *)cb_avail_p,
842		    (sizeof (pci_regspec_t) * avail_entries)/sizeof (int));
843
844		kmem_free(pcic_avail_p, avail_len);
845		kmem_free(cb_avail_p, sizeof (pci_regspec_t) * avail_entries);
846	}
847
848	if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "ranges",
849	    (caddr_t)&pcic_range_p, &range_len) != DDI_PROP_SUCCESS) {
850		cardbus_err(dip, 1, "cardbus_convert_properties: "
851		    "no ranges property for pcmcia\n");
852	} else {
853		range_entries = range_len / sizeof (pcic_ranges_t);
854		cb_range_p = kmem_alloc(
855		    sizeof (cardbus_range_t) * range_entries, KM_SLEEP);
856
857		old_range_p = pcic_range_p;
858		new_range_p = cb_range_p;
859		for (i = 0; i < range_entries;
860		    i++, old_range_p++, new_range_p++) {
861			new_range_p->child_hi =
862			    old_range_p->pcic_range_caddrhi;
863			new_range_p->child_mid = 0;
864			new_range_p->child_lo =
865			    old_range_p->pcic_range_caddrlo;
866			new_range_p->parent_hi =
867			    old_range_p->pcic_range_paddrhi;
868			new_range_p->parent_mid =
869			    old_range_p->pcic_range_paddrmid;
870			new_range_p->parent_lo =
871			    old_range_p->pcic_range_paddrlo;
872			new_range_p->size_hi = 0;
873			new_range_p->size_lo = old_range_p->pcic_range_size;
874		}
875
876		(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
877		    (int *)cb_range_p,
878		    (sizeof (cardbus_range_t) * range_entries)/sizeof (int));
879
880		kmem_free(pcic_range_p, range_len);
881		kmem_free(cb_range_p, sizeof (cardbus_range_t) * range_entries);
882	}
883
884	return (DDI_SUCCESS);
885}
886
887static void
888cardbus_revert_properties(dev_info_t *dip)
889{
890#if defined(CARDBUS_DEBUG)
891	cardbus_err(dip, 6, "cardbus_revert_properties\n");
892#endif
893
894	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "#address-cells");
895
896	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "#size-cells");
897
898	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "available");
899}
900
901static int
902cardbus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
903		ddi_prop_op_t prop_op, int mod_flags,
904		char *name, caddr_t valuep, int *lengthp)
905{
906#if defined(CARDBUS_DEBUG)
907	if ((ch_dip != dip) || (cardbus_debug >= 9))
908		cardbus_err(dip, 6,
909		    "cardbus_prop_op(%s) (dip=0x%p, op=%d, name=%s)\n",
910		    ddi_driver_name(ch_dip), (void *) dip, prop_op, name);
911#endif
912	return (impl_ddi_bus_prop_op(dev, dip, ch_dip, prop_op,
913	    mod_flags, name, valuep, lengthp));
914}
915
916static int
917cardbus_ctlops(dev_info_t *dip, dev_info_t *rdip,
918	ddi_ctl_enum_t ctlop, void *arg, void *result)
919{
920	pci_regspec_t *regs;
921	int	totreg, reglen;
922	const char	*dname = ddi_driver_name(dip);
923
924	ASSERT(number_of_cardbus_cards != 0);
925
926	cardbus_err(dip, 6,
927	    "cardbus_ctlops(%p, %p, %d, %p, %p)\n",
928	    (void *)dip, (void *)rdip, ctlop, (void *)arg, (void *)result);
929
930	switch (ctlop) {
931	case DDI_CTLOPS_UNINITCHILD:
932		cardbus_removechild((dev_info_t *)arg);
933		return (DDI_SUCCESS);
934	case DDI_CTLOPS_POWER:
935		return (DDI_SUCCESS);
936
937	default:
938		/*
939		 * Do Nothing
940		 */
941		cardbus_err(dip, 8,
942		    "cardbus_ctlops: Unsupported DDI_CTLOP %d\n", ctlop);
943		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
944
945	case DDI_CTLOPS_SIDDEV:		/* see ddi_dev_is_sid(9F) */
946		return (DDI_SUCCESS);
947
948	case DDI_CTLOPS_SLAVEONLY:	/* see ddi_slaveonly(9F) */
949		return (DDI_FAILURE);	/* cardbus */
950
951	case DDI_CTLOPS_REGSIZE:
952	case DDI_CTLOPS_NREGS:
953		if (rdip == (dev_info_t *)NULL) {
954			*(int *)result = 0;
955			return (DDI_FAILURE);
956		}
957		break;
958
959	case DDI_CTLOPS_IOMIN:
960		/*
961		 * If we are using the streaming cache, align at
962		 * least on a cache line boundary. Otherwise use
963		 * whatever alignment is passed in.
964		 */
965
966		if (arg) {
967			int	val = *((int *)result);
968
969#ifdef  PCI_SBUF_LINE_SIZE
970			val = maxbit(val, PCI_SBUF_LINE_SIZE);
971#else
972			val = maxbit(val, 64);
973#endif
974			*((int *)result) = val;
975		}
976		return (DDI_SUCCESS);
977
978	case DDI_CTLOPS_INITCHILD:
979		return (cardbus_initchild(rdip, dip, (dev_info_t *)arg,
980		    result));
981
982	case DDI_CTLOPS_REPORTDEV:
983		if (rdip == (dev_info_t *)0)
984			return (DDI_FAILURE);
985
986		if (strcmp("pcs", ddi_node_name(rdip)) == 0)
987			cardbus_err(dip, 1,
988			    "cardbus_ctlops: PCCard socket %d at %s@%s\n",
989			    ddi_get_instance(rdip),
990			    dname, ddi_get_name_addr(dip));
991		else {
992			pci_regspec_t *pci_rp;
993			dev_info_t *next;
994			int	length;
995
996			if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
997			    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
998			    (uint_t *)&length) != DDI_PROP_SUCCESS)
999				return (DDI_FAILURE);
1000
1001			if (pci_rp->pci_phys_hi == 0)
1002				cardbus_err(dip, 1, "%s%d at %s@%s\n",
1003				    ddi_driver_name(rdip),
1004				    ddi_get_instance(rdip),
1005				    dname, ddi_get_name_addr(dip));
1006			else {
1007				uint8_t bus, device, function;
1008				int32_t val32;
1009				char	*ptr, buf[128];
1010
1011				bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1012				device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1013				function = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1014
1015				ptr = buf;
1016				(void) sprintf(ptr, "  "
1017				    "Bus %3d Device %2d Function %2d",
1018				    bus, device, function);
1019				ptr = &ptr[strlen(ptr)];
1020
1021				val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
1022				    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1023				    "vendor-id", -1);
1024				if (val32 != -1) {
1025					(void) sprintf(ptr, " Vendor 0x%04x",
1026					    val32);
1027					ptr = &ptr[strlen(ptr)];
1028				}
1029				val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
1030				    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1031				    "device-id", -1);
1032				if (val32 != -1) {
1033					(void) sprintf(ptr, " Device 0x%04x",
1034					    val32);
1035					ptr = &ptr[strlen(ptr)];
1036				}
1037				val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
1038				    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1039				    "class-code", -1);
1040				if (val32 != -1) {
1041					const char	*name;
1042
1043					if ((name = ddi_get_name(rdip)) !=
1044					    NULL)
1045						(void) sprintf(ptr, " Name %s",
1046						    name);
1047					else
1048						(void) sprintf(ptr,
1049						    " Class 0x%x", val32 >> 8);
1050					ptr = &ptr[strlen(ptr)];
1051				}
1052
1053				*ptr++ = '\n';
1054				ASSERT(((caddr_t)ptr - (caddr_t)buf) <
1055				    sizeof (buf));
1056				*ptr = '\0';
1057
1058				cardbus_err(dip, 1, buf);
1059			}
1060			ddi_prop_free(pci_rp);
1061
1062			for (next = ddi_get_child(rdip); next;
1063			    next = ddi_get_next_sibling(next))
1064				(void) cardbus_ctlops(next, next,
1065				    DDI_CTLOPS_REPORTDEV, arg, result);
1066		}
1067		return (DDI_SUCCESS);
1068	}
1069	*(int *)result = 0;
1070
1071	if (ddi_getlongprop(DDI_DEV_T_NONE, rdip,
1072	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
1073	    (caddr_t)&regs, &reglen) != DDI_SUCCESS)
1074		return (DDI_FAILURE);
1075
1076	totreg = reglen / sizeof (pci_regspec_t);
1077	if (ctlop == DDI_CTLOPS_NREGS) {
1078		cardbus_err(dip, 6,
1079		    "cardbus_ctlops, returning NREGS = %d\n", totreg);
1080		*(int *)result = totreg;
1081	} else if (ctlop == DDI_CTLOPS_REGSIZE) {
1082		const int	rn = *(int *)arg;
1083		if (rn > totreg)
1084			return (DDI_FAILURE);
1085		cardbus_err(dip, 6,
1086		    "cardbus_ctlops, returning REGSIZE(%d) = %d\n",
1087		    rn, regs[rn].pci_size_low);
1088		*(off_t *)result = regs[rn].pci_size_low;
1089	}
1090	kmem_free(regs, reglen);
1091	return (DDI_SUCCESS);
1092}
1093
1094static void
1095cardbus_init_child_regs(dev_info_t *child)
1096{
1097	ddi_acc_handle_t config_handle;
1098	uint16_t command_preserve, command;
1099#if !defined(__i386) && !defined(__amd64)
1100	uint8_t bcr;
1101#endif
1102	uint8_t header_type;
1103	uint8_t min_gnt, latency_timer;
1104	uint_t n;
1105
1106	/*
1107	 * Map the child configuration space to for initialization.
1108	 *
1109	 *  Set the latency-timer register to values appropriate
1110	 *  for the devices on the bus (based on other devices
1111	 *  MIN_GNT and MAX_LAT registers.
1112	 *
1113	 *  Set the fast back-to-back enable bit in the command
1114	 *  register if it's supported and all devices on the bus
1115	 *  have the capability.
1116	 *
1117	 */
1118	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
1119		return;
1120
1121	cardbus_err(child, 6, "cardbus_init_child_regs()\n");
1122
1123	/*
1124	 * Determine the configuration header type.
1125	 */
1126	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
1127
1128	/*
1129	 * Support for "command-preserve" property.  Note that we
1130	 * add PCI_COMM_BACK2BACK_ENAB to the bits to be preserved
1131	 * since the obp will set this if the device supports and
1132	 * all targets on the same bus support it.  Since psycho
1133	 * doesn't support PCI_COMM_BACK2BACK_ENAB, it will never
1134	 * be set.  This is just here in case future revs do support
1135	 * PCI_COMM_BACK2BACK_ENAB.
1136	 */
1137	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1138	    DDI_PROP_DONTPASS,
1139	    "command-preserve", 0);
1140	command = pci_config_get16(config_handle, PCI_CONF_COMM);
1141	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
1142	command |= (cardbus_command_default & ~command_preserve);
1143	pci_config_put16(config_handle, PCI_CONF_COMM, command);
1144	command = pci_config_get16(config_handle, PCI_CONF_COMM);
1145
1146#if !defined(__i386) && !defined(__amd64)
1147	/*
1148	 * If the device has a bus control register then program it
1149	 * based on the settings in the command register.
1150	 */
1151	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
1152		bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
1153		if (cardbus_command_default & PCI_COMM_PARITY_DETECT)
1154			bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
1155		if (cardbus_command_default & PCI_COMM_SERR_ENABLE)
1156			bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
1157		bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
1158		pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
1159	}
1160#endif
1161
1162	/*
1163	 * Initialize cache-line-size configuration register if needed.
1164	 */
1165	if (ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1166	    "cache-line-size", 0) == 0) {
1167
1168		pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
1169		    PCI_CACHE_LINE_SIZE);
1170		n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
1171		if (n != 0)
1172			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
1173			    "cache-line-size", n);
1174	}
1175
1176	/*
1177	 * Initialize latency timer registers if needed.
1178	 */
1179	if (ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1180	    "latency-timer", 0) == 0) {
1181
1182		if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
1183			latency_timer = cardbus_latency_timer;
1184			pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
1185			    latency_timer);
1186		} else {
1187			min_gnt = pci_config_get8(config_handle,
1188			    PCI_CONF_MIN_G);
1189
1190			/*
1191			 * Cardbus os only 33Mhz
1192			 */
1193			if (min_gnt != 0) {
1194				latency_timer = min_gnt * 8;
1195			}
1196		}
1197		pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
1198		    latency_timer);
1199		n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
1200		if (n != 0)
1201			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
1202			"latency-timer", n);
1203	}
1204
1205	pci_config_teardown(&config_handle);
1206}
1207
1208static int
1209cardbus_initchild(dev_info_t *rdip, dev_info_t *dip, dev_info_t *child,
1210		void *result)
1211{
1212	char	name[MAXNAMELEN];
1213	const char	*dname = ddi_driver_name(dip);
1214	const struct cb_ops *cop;
1215
1216	_NOTE(ARGUNUSED(rdip, result))
1217
1218	cardbus_err(child, 6, "cardbus_initchild\n");
1219
1220	/*
1221	 * Name the child
1222	 */
1223	if (cardbus_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
1224		return (DDI_FAILURE);
1225
1226	ddi_set_name_addr(child, name);
1227	ddi_set_parent_data(child, NULL);
1228
1229	if (ndi_dev_is_persistent_node(child) == 0) {
1230		/*
1231		 * Try to merge the properties from this prototype
1232		 * node into real h/w nodes.
1233		 */
1234		if (ndi_merge_node(child, cardbus_name_child) == DDI_SUCCESS) {
1235			/*
1236			 * Merged ok - return failure to remove the node.
1237			 */
1238			cardbus_removechild(child);
1239			return (DDI_FAILURE);
1240		}
1241		/*
1242		 * The child was not merged into a h/w node,
1243		 * but there's not much we can do with it other
1244		 * than return failure to cause the node to be removed.
1245		 */
1246		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
1247		    ddi_driver_name(child), ddi_get_name_addr(child),
1248		    ddi_driver_name(child));
1249		cardbus_removechild(child);
1250		return (DDI_NOT_WELL_FORMED);
1251	}
1252	cop = DEVI(dip)->devi_ops->devo_cb_ops;
1253
1254	if ((cop == NULL) || (!(cop->cb_flag & D_HOTPLUG))) {
1255		cmn_err(CE_WARN, "%s: driver doesn't support HOTPLUG\n", dname);
1256		return (DDI_FAILURE);
1257	}
1258
1259	cardbus_init_child_regs(child);
1260
1261	/*
1262	 * Create ppd if needed.
1263	 */
1264	if (ddi_get_parent_data(child) == NULL) {
1265		struct cardbus_parent_private_data *ppd;
1266
1267#ifdef sparc
1268		ppd = (struct cardbus_parent_private_data *)
1269		    kmem_zalloc(sizeof (struct cardbus_parent_private_data),
1270		    KM_SLEEP);
1271
1272#elif defined(__x86) || defined(__amd64)
1273		ppd = (struct cardbus_parent_private_data *)
1274		    kmem_zalloc(sizeof (struct cardbus_parent_private_data)
1275		    + sizeof (struct intrspec), KM_SLEEP);
1276
1277		ppd->ppd.par_intr = (struct intrspec *)(ppd + 1);
1278		(ppd->ppd.par_intr)->intrspec_pri = 0;
1279		(ppd->ppd.par_intr)->intrspec_vec = 0;
1280		(ppd->ppd.par_intr)->intrspec_func = (uint_t (*)()) 0;
1281#endif
1282
1283		if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
1284		    "interrupts", -1) != -1)
1285			ppd->ppd.par_nintr = 1;
1286
1287		ppd->code = CB_PPD_CODE;
1288
1289		cardbus_err(child, 5,
1290		    "cardbus_initchild: Creating empty ppd\n");
1291		ppd->ppd.par_nreg = 0;
1292		ppd->ppd.par_reg = NULL;
1293
1294		ddi_set_parent_data(child, (caddr_t)ppd);
1295	}
1296
1297	return (DDI_SUCCESS);
1298}
1299
1300static int
1301cardbus_name_child(dev_info_t *child, char *name, int namelen)
1302{
1303	pci_regspec_t *pci_rp;
1304	char	**unit_addr;
1305	uint_t n;
1306	int	bus, device, func;
1307
1308	/*
1309	 * Pseudo nodes indicate a prototype node with per-instance
1310	 * properties to be merged into the real h/w device node.
1311	 * The interpretation of the unit-address is DD[,F]
1312	 * where DD is the device id and F is the function.
1313	 */
1314	if (ndi_dev_is_persistent_node(child) == 0) {
1315		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
1316		    DDI_PROP_DONTPASS,
1317		    "unit-address", &unit_addr, &n) != DDI_PROP_SUCCESS) {
1318			cmn_err(CE_WARN, "cannot name node from %s.conf",
1319			    ddi_driver_name(child));
1320			return (DDI_FAILURE);
1321		}
1322		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
1323			cmn_err(CE_WARN, "unit-address property in %s.conf"
1324			    " not well-formed", ddi_driver_name(child));
1325			ddi_prop_free(unit_addr);
1326			return (DDI_FAILURE);
1327		}
1328		(void) snprintf(name, namelen, "%s", *unit_addr);
1329		ddi_prop_free(unit_addr);
1330		return (DDI_SUCCESS);
1331	}
1332
1333	/*
1334	 * Get the address portion of the node name based on
1335	 * the function and device number.
1336	 */
1337	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1338	    "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) {
1339		return (DDI_FAILURE);
1340	}
1341
1342	bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1343	device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1344	func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1345	ddi_prop_free(pci_rp);
1346
1347	if (func != 0)
1348		(void) snprintf(name, namelen, "%x,%x", device, func);
1349	else
1350		(void) snprintf(name, namelen, "%x", device);
1351
1352	cardbus_err(child, 8,
1353	    "cardbus_name_child: system init done [%x][%x][%x]"
1354	    " for %s [%s] nodeid: %x @%s\n",
1355	    bus, device, func,
1356	    ddi_get_name(child), ddi_get_name_addr(child),
1357	    DEVI(child)->devi_nodeid, name);
1358
1359	return (DDI_SUCCESS);
1360}
1361
1362static void
1363cardbus_removechild(dev_info_t *dip)
1364{
1365	struct cardbus_parent_private_data *ppd;
1366
1367	ddi_set_name_addr(dip, NULL);
1368	impl_rem_dev_props(dip);
1369	ppd = (struct cardbus_parent_private_data *)ddi_get_parent_data(dip);
1370	if (ppd && (ppd->code == CB_PPD_CODE)) {
1371		if (ppd->ppd.par_reg && (ppd->ppd.par_nreg > 0))
1372			kmem_free((caddr_t)ppd->ppd.par_reg,
1373			    ppd->ppd.par_nreg * sizeof (struct regspec));
1374#ifdef sparc
1375		kmem_free(ppd, sizeof (struct cardbus_parent_private_data));
1376#elif defined(__x86) || defined(__amd64)
1377		kmem_free(ppd, sizeof (struct cardbus_parent_private_data) +
1378		    sizeof (struct intrspec));
1379#endif
1380		cardbus_err(dip, 5,
1381		    "cardbus_removechild: ddi_set_parent_data(NULL)\n");
1382		ddi_set_parent_data(dip, NULL);
1383	}
1384}
1385
1386
1387static char	cb_bnamestr[] = "binding_name";
1388static char	cb_venidstr[] = "VendorID";
1389static char	cb_devidstr[] = "DeviceID";
1390static char	cb_nnamestr[] = "nodename";
1391
1392static cb_props_parse_tree_t cb_props_parse_tree[] = {
1393	{ cb_bnamestr, PT_STATE_STRING_VAR },
1394	{ cb_venidstr, PT_STATE_HEX_VAR },
1395	{ cb_devidstr, PT_STATE_HEX_VAR } };
1396
1397static int
1398check_token(char *token, int *len)
1399{
1400	int	state = PT_STATE_DEC_VAR;
1401	int	sl = strlen(token), il = 1;
1402	char	c;
1403
1404	if (token[0] == '0' && token[2] && (token[1] == 'x' || token[1] ==
1405	    'X')) {
1406		state = PT_STATE_HEX_VAR;
1407		token += 2;
1408	}
1409
1410	while (c = *token++) {
1411		if (isdigit(c))
1412			continue;
1413		if (c == PARSE_COMMA) {
1414			il++;
1415			if (token[0] == '0' && token[2] && isx(token[1])) {
1416				state = PT_STATE_HEX_VAR;
1417				token += 2;
1418			}
1419			continue;
1420		}
1421		if (!isxdigit(c)) {
1422			*len = sl;
1423			return (PT_STATE_STRING_VAR);
1424		}
1425		state = PT_STATE_HEX_VAR;
1426	}
1427	*len = il;
1428	return (state);
1429}
1430
1431
1432static char *
1433find_token(char **cp, int *l, char *endc)
1434{
1435	char	*cpp = *cp;
1436
1437	while ((**cp && (isalpha(**cp) || isxdigit(**cp) ||
1438	    (**cp == PARSE_UNDERSCORE) ||
1439	    (**cp == PARSE_COMMA) ||
1440	    (**cp == PARSE_DASH)))) {
1441		(*cp)++;
1442		(*l)++;
1443	}
1444
1445	*endc = **cp;
1446	**cp = NULL;
1447
1448	return (cpp);
1449}
1450
1451static int
1452parse_token(char *token)
1453{
1454	cb_props_parse_tree_t *pt = cb_props_parse_tree;
1455	int	k = sizeof (cb_props_parse_tree) /
1456	    sizeof (cb_props_parse_tree_t);
1457
1458	while (k--) {
1459		if (strcmp((char *)token, pt->token) == 0)
1460			return (pt->state);
1461		pt++;
1462	}
1463
1464	return (PT_STATE_UNKNOWN);
1465}
1466
1467static int
1468token_to_hex(char *token, unsigned *val, int len)
1469{
1470	uchar_t c;
1471
1472	*val = 0;
1473	if (token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) {
1474		token += 2;
1475	}
1476
1477	while (*token) {
1478		if (!isxdigit(*token)) {
1479			if (*token == PARSE_COMMA) {
1480				if (!(--len))
1481					return (1);
1482				val++;
1483				*val = 0;
1484				token++;
1485				if (token[0] == '0' && (token[1] == 'x' ||
1486				    token[1] == 'X')) {
1487					token += 2;
1488				}
1489				continue;
1490			}
1491			return (0);
1492		}
1493		c = toupper(*token);
1494		if (c >= 'A')
1495			c = c - 'A' + 10 + '0';
1496		*val = ((*val * 16) + (c - '0'));
1497		token++;
1498	}
1499
1500	return (1);
1501}
1502
1503static int
1504token_to_dec(char *token, unsigned *val, int len)
1505{
1506	*val = 0;
1507
1508	while (*token) {
1509		if (!isdigit(*token)) {
1510			if (*token == PARSE_COMMA) {
1511				if (!(--len))
1512					return (1);
1513				val++;
1514				*val = 0;
1515				token++;
1516				continue;
1517			}
1518			return (0);
1519		}
1520		*val = ((*val * 10) + (*token - '0'));
1521		token++;
1522	}
1523
1524	return (1);
1525}
1526
1527static void
1528cardbus_add_prop(struct cb_deviceset_props *cdsp, int type, char *name,
1529		caddr_t vp, int len)
1530{
1531	ddi_prop_t *propp;
1532	int	pnlen = strlen(name) + 1;
1533
1534	propp = (ddi_prop_t *)kmem_zalloc(sizeof (ddi_prop_t), KM_SLEEP);
1535	propp->prop_name = (char *)kmem_alloc(pnlen, KM_SLEEP);
1536	propp->prop_val = vp;
1537	bcopy(name, propp->prop_name, pnlen);
1538	propp->prop_len = len;
1539	propp->prop_flags = type;
1540	propp->prop_next = cdsp->prop_list;
1541	cdsp->prop_list = propp;
1542}
1543
1544static void
1545cardbus_add_stringprop(struct cb_deviceset_props *cdsp, char *name,
1546		char *vp, int len)
1547{
1548	char	*nstr = kmem_zalloc(len + 1, KM_SLEEP);
1549
1550	bcopy(vp, nstr, len);
1551	cardbus_add_prop(cdsp, DDI_PROP_TYPE_STRING, name, (caddr_t)nstr,
1552	    len + 1);
1553}
1554
1555static void
1556cardbus_prop_free(ddi_prop_t *propp)
1557{
1558	if (propp->prop_len) {
1559		switch (propp->prop_flags) {
1560		case DDI_PROP_TYPE_STRING:
1561			kmem_free(propp->prop_val, propp->prop_len);
1562			break;
1563		case DDI_PROP_TYPE_INT:
1564			kmem_free(propp->prop_val,
1565			    propp->prop_len * sizeof (int));
1566			break;
1567		}
1568	}
1569	kmem_free(propp->prop_name, strlen(propp->prop_name) + 1);
1570	kmem_free(propp, sizeof (ddi_prop_t *));
1571}
1572
1573static void
1574cardbus_devprops_free(struct cb_deviceset_props *cbdp)
1575{
1576	ddi_prop_t *propp, *npropp;
1577
1578	propp = cbdp->prop_list;
1579	while (propp) {
1580		npropp = propp->prop_next;
1581		cardbus_prop_free(propp);
1582		propp = npropp;
1583	}
1584	if (cbdp->nodename)
1585		kmem_free(cbdp->nodename, strlen(cbdp->nodename) + 1);
1586	if (cbdp->binding_name)
1587		kmem_free(cbdp->binding_name, strlen(cbdp->binding_name) +
1588		    1);
1589	kmem_free(cbdp, sizeof (*cbdp));
1590}
1591
1592/*
1593 * Format of "cb-device-init-props" property:
1594 * Anything before the semi-colon is an identifying equate, anything
1595 * after the semi-colon is a setting equate.
1596 *
1597 * "binding_name=xXxXxX VendorID=NNNN DeviceID=NNNN; nodename=NewName
1598 * 					Prop=PropVal"
1599 *
1600 */
1601static int
1602cardbus_parse_devprop(cbus_t *cbp, char *cp)
1603{
1604	int	state = PT_STATE_TOKEN, qm = 0, em = 0, smc = 0, l = 0;
1605	int	length;
1606	char	*token = "beginning of line";
1607	char	*ptoken = NULL, *quote;
1608	char	eq = NULL;
1609	struct cb_deviceset_props *cdsp;
1610
1611	cdsp = (struct cb_deviceset_props *)kmem_zalloc(sizeof (*cdsp),
1612	    KM_SLEEP);
1613	length = strlen(cp);
1614
1615	while ((*cp) && (l < length)) {
1616		/*
1617		 * Check for escaped characters
1618		 */
1619		if (*cp == PARSE_ESCAPE) {
1620			char	*cpp = cp, *cppp = cp + 1;
1621
1622			em = 1;
1623
1624			if (!qm) {
1625				cmn_err(CE_CONT, "cardbus_parse_devprop: "
1626				    "escape not allowed outside "
1627				    "of quotes at [%s]\n", token);
1628				return (DDI_FAILURE);
1629
1630			} /* if (!qm) */
1631
1632			while (*cppp)
1633				*cpp++ = *cppp++;
1634
1635			l++;
1636
1637			*cpp = NULL;
1638		} /* PARSE_ESCAPE */
1639
1640		/*
1641		 * Check for quoted strings
1642		 */
1643		if (!em && (*cp == PARSE_QUOTE)) {
1644			qm ^= 1;
1645			if (qm) {
1646				quote = cp + 1;
1647			} else {
1648				*cp = NULL;
1649				if (state == PT_STATE_CHECK) {
1650					if (strcmp(token, cb_nnamestr) == 0) {
1651						cdsp->nodename = kmem_alloc(
1652						    strlen(quote) + 1,
1653						    KM_SLEEP);
1654						(void) strcpy(cdsp->nodename,
1655						    quote);
1656					} else
1657						cardbus_add_stringprop(cdsp,
1658						    token, quote,
1659						    strlen(quote));
1660				} else if (state != PT_STATE_STRING_VAR) {
1661					cmn_err(CE_CONT,
1662					    "cardbus_parse_devprop: "
1663					    "unexpected string [%s] after "
1664					    "[%s]\n", quote, token);
1665					return (DDI_FAILURE);
1666				} else {
1667					if (strcmp(token, cb_bnamestr) == 0) {
1668						cdsp->binding_name = kmem_alloc(
1669						    strlen(quote) + 1,
1670						    KM_SLEEP);
1671						(void) strcpy(
1672						    cdsp->binding_name, quote);
1673					}
1674				}
1675				state = PT_STATE_TOKEN;
1676			} /* if (qm) */
1677		} /* PARSE_QUOTE */
1678
1679		em = 0;
1680
1681		if (!qm && (*cp == PARSE_SEMICOLON)) {
1682			smc = 1;
1683		}
1684
1685		/*
1686		 * Check for tokens
1687		 */
1688		else if (!qm && (isalpha(*cp) || isxdigit(*cp))) {
1689			int	tl;
1690			unsigned	*intp;
1691			ptoken = token;
1692			token = find_token(&cp, &l, &eq);
1693
1694			switch (state) {
1695			case PT_STATE_TOKEN:
1696				if (smc) {
1697					if (eq == PARSE_EQUALS)
1698						state = PT_STATE_CHECK;
1699					else
1700						cardbus_add_prop(cdsp,
1701						    DDI_PROP_TYPE_ANY,
1702						    token,
1703						    NULL, 0);
1704				} else if (eq == PARSE_EQUALS)
1705					switch (state = parse_token(token)) {
1706					case PT_STATE_UNKNOWN:
1707						cmn_err(CE_CONT,
1708						    "cardbus_parse_devprop: "
1709						    "unknown token [%s]\n",
1710						    token);
1711						state = PT_STATE_TOKEN;
1712					} /* switch (parse_token) */
1713				else
1714					state = PT_STATE_TOKEN;
1715				break;
1716
1717			case PT_STATE_CHECK:
1718				switch (check_token(token, &tl)) {
1719				case PT_STATE_DEC_VAR:
1720					intp = (unsigned *)kmem_alloc(
1721					    sizeof (int)*tl,
1722					    KM_SLEEP);
1723					if (token_to_dec(token, intp, tl))
1724						cardbus_add_prop(cdsp,
1725						    DDI_PROP_TYPE_INT, ptoken,
1726						    (caddr_t)intp, tl);
1727					else
1728						kmem_free(intp,
1729						    sizeof (int)*tl);
1730					break;
1731				case PT_STATE_HEX_VAR:
1732					intp = (unsigned *)kmem_alloc(
1733					    sizeof (int)*tl,
1734					    KM_SLEEP);
1735					if (token_to_hex(token, intp, tl))
1736						cardbus_add_prop(cdsp,
1737						    DDI_PROP_TYPE_INT,
1738						    ptoken,
1739						    (caddr_t)intp, tl);
1740					else
1741						kmem_free(intp,
1742						    sizeof (int)*tl);
1743					break;
1744				case PT_STATE_STRING_VAR:
1745					if (strcmp(ptoken, cb_nnamestr) == 0) {
1746						cdsp->nodename = kmem_alloc(
1747						    tl + 1, KM_SLEEP);
1748						(void) strcpy(cdsp->nodename,
1749						    token);
1750					} else
1751						cardbus_add_stringprop(cdsp,
1752						    ptoken, token, tl);
1753					break;
1754				}
1755				state = PT_STATE_TOKEN;
1756				break;
1757
1758			case PT_STATE_HEX_VAR:
1759				if (strcmp(ptoken, cb_venidstr) == 0) {
1760					uint_t val;
1761					if (token_to_hex(token, &val, 1))
1762						cdsp->venid = val;
1763				} else if (strcmp(ptoken, cb_devidstr) == 0) {
1764					uint_t val;
1765					if (token_to_hex(token, &val, 1))
1766						cdsp->devid = val;
1767				}
1768				state = PT_STATE_TOKEN;
1769				break;
1770
1771			case PT_STATE_DEC_VAR:
1772				if (strcmp(ptoken, cb_venidstr) == 0) {
1773					uint_t val;
1774					if (token_to_dec(token, &val, 1))
1775						cdsp->venid = val;
1776				} else if (strcmp(ptoken, cb_devidstr) == 0) {
1777					uint_t val;
1778					if (token_to_dec(token, &val, 1))
1779						cdsp->devid = val;
1780				}
1781				state = PT_STATE_TOKEN;
1782				break;
1783
1784			case PT_STATE_STRING_VAR:
1785				if (strcmp(ptoken, cb_bnamestr) == 0) {
1786					cdsp->binding_name = kmem_alloc(
1787					    strlen(token) + 1, KM_SLEEP);
1788					(void) strcpy(cdsp->binding_name,
1789					    token);
1790				}
1791				state = PT_STATE_TOKEN;
1792				break;
1793
1794			default:
1795				cmn_err(CE_CONT, "cardbus_parse_devprop: "
1796				    "unknown state machine state = %d\n",
1797				    state);
1798
1799				cardbus_devprops_free(cdsp);
1800				return (DDI_FAILURE);
1801			} /* switch (state) */
1802			if (eq == PARSE_SEMICOLON)
1803				smc = 1;
1804		}
1805		cp++;
1806		l++;
1807	} /* while (*cp) */
1808
1809	if (qm) {
1810		cmn_err(CE_CONT, "cb_props_parse_line: unterminated "
1811		    "string = [%s]\n", quote);
1812		cardbus_devprops_free(cdsp);
1813		return (DDI_FAILURE);
1814	}
1815
1816	if (state != PT_STATE_TOKEN) {
1817		cmn_err(CE_CONT, "cardbus_parse_devprop: token [%s] "
1818		    "requires value\n", token);
1819		cardbus_devprops_free(cdsp);
1820		return (DDI_FAILURE);
1821	}
1822
1823	if (cdsp->venid == 0 || cdsp->devid == 0) {
1824		cmn_err(CE_CONT, "cardbus_parse_devprop: Entry "
1825		    "requires VendorID and DeviceID\n");
1826		cardbus_devprops_free(cdsp);
1827		return (DDI_FAILURE);
1828	}
1829
1830	cdsp->next = cbp->cb_dsp;
1831	cbp->cb_dsp = cdsp;
1832	return (DDI_SUCCESS);
1833}
1834
1835static void
1836cardbus_device_props(cbus_t *cbp)
1837{
1838	char	**prop_array;
1839	uint_t i, n;
1840
1841	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, cbp->cb_dip,
1842	    DDI_PROP_DONTPASS,
1843	    "cb-device-init-props", &prop_array,
1844	    &n) != DDI_PROP_SUCCESS)
1845		return;
1846
1847	for (i = 0; i < n; i++)
1848		(void) cardbus_parse_devprop(cbp, prop_array[i]);
1849
1850	ddi_prop_free(prop_array);
1851}
1852
1853static int
1854cardbus_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
1855		off_t offset, off_t len, caddr_t *vaddrp)
1856{
1857	register dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent;
1858	int	rc;
1859
1860	cardbus_err(dip, 9,
1861	    "cardbus_bus_map(dip=0x%p, rdip=0x%p)\n",
1862	    (void *) dip, (void *) rdip);
1863
1864	if (pdip == NULL)
1865		return (DDI_FAILURE);
1866
1867	/* A child has asked us to set something up */
1868	cardbus_err(dip, 9,
1869	    "cardbus_bus_map(%s) calling %s - 0x%p, "
1870	    "offset 0x%x, len 0x%x\n",
1871	    ddi_driver_name(rdip),
1872	    ddi_driver_name(pdip),
1873	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_map,
1874	    (int)offset, (int)len);
1875
1876	rc = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
1877	    (pdip, rdip, mp, offset, len, vaddrp);
1878	/* rc = ddi_map(dip, mp, offset, len, vaddrp); */
1879
1880	if (rc != DDI_SUCCESS) {
1881		cardbus_err(rdip, 8, "cardbus_bus_map failed, rc = %d\n", rc);
1882		return (DDI_FAILURE);
1883	} else {
1884		cardbus_err(rdip, 9, "cardbus_bus_map OK\n");
1885		return (DDI_SUCCESS);
1886	}
1887}
1888
1889static void
1890pcirp2rp(const pci_regspec_t *pci_rp, struct regspec *rp)
1891{
1892	/* bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi); */
1893	if (PCI_REG_ADDR_G(pci_rp->pci_phys_hi) ==
1894	    PCI_REG_ADDR_G(PCI_ADDR_IO)) {
1895		/* I/O */
1896		rp->regspec_bustype = 1;
1897	} else {
1898		/* memory */
1899		rp->regspec_bustype = 0;
1900	}
1901	rp->regspec_addr = pci_rp->pci_phys_low;
1902	rp->regspec_size = pci_rp->pci_size_low;
1903}
1904
1905static int
1906cardbus_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
1907		int (*waitfp)(caddr_t), caddr_t arg,
1908		ddi_dma_handle_t *handlep)
1909{
1910	dev_info_t *pdip = ddi_get_parent(dip);
1911
1912	cardbus_err(dip, 10,
1913	    "cardbus_dma_allochdl(dip=0x%p, rdip=0x%p)\n",
1914	    (void *) dip, (void *) rdip);
1915
1916	if (pdip == NULL)
1917		return (DDI_FAILURE);
1918
1919	cardbus_err(dip, 11,
1920	    "cardbus_dma_allochdl calling %s - 0x%p\n",
1921	    ddi_driver_name(pdip),
1922	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_allochdl);
1923
1924	return (ddi_dma_allochdl(dip, rdip, attr, waitfp, arg, handlep));
1925}
1926
1927static int
1928cardbus_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
1929		ddi_dma_handle_t handle)
1930{
1931	dev_info_t *pdip = ddi_get_parent(dip);
1932
1933	cardbus_err(dip, 10,
1934	    "cardbus_dma_freehdl(dip=0x%p, rdip=0x%p)\n",
1935	    (void *) dip, (void *) rdip);
1936
1937	if (pdip == NULL)
1938		return (DDI_FAILURE);
1939
1940	cardbus_err(dip, 11,
1941	    "cardbus_dma_freehdl calling %s - 0x%p\n",
1942	    ddi_driver_name(pdip),
1943	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_freehdl);
1944
1945	return (ddi_dma_freehdl(dip, rdip, handle));
1946}
1947
1948static int
1949cardbus_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
1950		ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
1951		ddi_dma_cookie_t *cp, uint_t *ccountp)
1952{
1953	dev_info_t *pdip = ddi_get_parent(dip);
1954
1955	cardbus_err(dip, 10,
1956	    "cardbus_dma_bindhdl(dip=0x%p, rdip=0x%p)\n",
1957	    (void *) dip, (void *) rdip);
1958
1959	if (pdip == NULL)
1960		return (DDI_FAILURE);
1961
1962	cardbus_err(dip, 11,
1963	    "cardbus_dma_bindhdl calling %s - 0x%p\n",
1964	    ddi_driver_name(pdip),
1965	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_bindhdl);
1966
1967	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_bindhdl(pdip,
1968	    rdip, handle, dmareq, cp, ccountp));
1969}
1970
1971static int
1972cardbus_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
1973		ddi_dma_handle_t handle)
1974{
1975	dev_info_t *pdip = ddi_get_parent(dip);
1976
1977	cardbus_err(dip, 10,
1978	    "cardbus_dma_unbindhdl(dip=0x%p, rdip=0x%p)\n",
1979	    (void *) dip, (void *) rdip);
1980
1981	if (pdip == NULL)
1982		return (DDI_FAILURE);
1983
1984	cardbus_err(dip, 11,
1985	    "cardbus_dma_unbindhdl calling %s - 0x%p\n",
1986	    ddi_driver_name(pdip),
1987	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl);
1988
1989	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl(pdip,
1990	    rdip, handle));
1991}
1992
1993static int
1994cardbus_dma_flush(dev_info_t *dip, dev_info_t *rdip,
1995		ddi_dma_handle_t handle, off_t off, size_t len,
1996		uint_t cache_flags)
1997{
1998	dev_info_t *pdip = ddi_get_parent(dip);
1999
2000	cardbus_err(dip, 10,
2001	    "cardbus_dma_flush(dip=0x%p, rdip=0x%p)\n",
2002	    (void *) dip, (void *) rdip);
2003
2004	if (pdip == NULL)
2005		return (DDI_FAILURE);
2006
2007	cardbus_err(dip, 11,
2008	    "cardbus_dma_flush calling %s - 0x%p\n",
2009	    ddi_driver_name(pdip),
2010	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_flush);
2011
2012	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_flush(pdip, rdip,
2013	    handle, off, len, cache_flags));
2014}
2015
2016static int
2017cardbus_dma_win(dev_info_t *dip, dev_info_t *rdip,
2018		ddi_dma_handle_t handle, uint_t win, off_t *offp,
2019		size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
2020{
2021	dev_info_t *pdip = ddi_get_parent(dip);
2022	cardbus_err(dip, 6,
2023	    "cardbus_dma_win(dip=0x%p, rdip=0x%p)\n",
2024	    (void *) dip, (void *) rdip);
2025
2026	if (pdip == NULL)
2027		return (DDI_FAILURE);
2028
2029	cardbus_err(dip, 8,
2030	    "cardbus_dma_win calling %s - 0x%p\n",
2031	    ddi_driver_name(pdip),
2032	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_win);
2033
2034	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_win(pdip, rdip,
2035	    handle, win, offp, lenp, cookiep, ccountp));
2036}
2037
2038static int
2039cardbus_dma_map(dev_info_t *dip, dev_info_t *rdip,
2040		struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
2041{
2042	dev_info_t *pdip = ddi_get_parent(dip);
2043
2044	cardbus_err(dip, 10,
2045	    "cardbus_dma_map(dip=0x%p, rdip=0x%p)\n",
2046	    (void *) dip, (void *) rdip);
2047
2048	if (pdip == NULL)
2049		return (DDI_FAILURE);
2050
2051	cardbus_err(dip, 11,
2052	    "cardbus_dma_map calling %s - 0x%p\n",
2053	    ddi_driver_name(pdip),
2054	    (void *) DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_map);
2055
2056	return (DEVI(pdip)->devi_ops->devo_bus_ops->bus_dma_map(pdip, rdip,
2057	    dmareqp, handlep));
2058}
2059
2060static int
2061cardbus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
2062		char *eventname, ddi_eventcookie_t *cookiep)
2063{
2064	cbus_t *cbp;
2065	int	cb_instance;
2066	int	rc;
2067
2068	/*
2069	 * get the soft state structure for the bus instance.
2070	 */
2071	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2072	    DDI_PROP_DONTPASS, "cbus-instance", -1);
2073	ASSERT(cb_instance >= 0);
2074	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
2075
2076	cardbus_err(dip, 6, "cardbus_get_eventcookie %s\n", eventname);
2077
2078	ASSERT(number_of_cardbus_cards != 0);
2079
2080	if (cbp->cb_ndi_event_hdl == NULL) {
2081		/*
2082		 * We can't handle up (probably called at the attachment
2083		 * point) so pass it on up
2084		 */
2085		dev_info_t *pdip = ddi_get_parent(dip);
2086		cardbus_err(dip, 8,
2087		    "cardbus_get_eventcookie calling %s - 0x%p\n",
2088		    ddi_driver_name(pdip),
2089		    (void *)
2090		    DEVI(pdip)->devi_ops->devo_bus_ops->bus_get_eventcookie);
2091		return (DEVI(pdip)->devi_ops->devo_bus_ops->
2092		    bus_get_eventcookie(pdip, rdip, eventname, cookiep));
2093	}
2094
2095	cardbus_err(dip, 8,
2096	    "cardbus_get_eventcookie calling ndi_event_retrieve_cookie\n");
2097
2098	rc = ndi_event_retrieve_cookie(cbp->cb_ndi_event_hdl, rdip, eventname,
2099	    cookiep, NDI_EVENT_NOPASS);
2100
2101	cardbus_err(dip, 7,
2102	    "cardbus_get_eventcookie rc %d cookie %p\n", rc, (void *)*cookiep);
2103	return (rc);
2104}
2105
2106static int
2107cardbus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
2108		ddi_eventcookie_t cookie, void (*callback)(dev_info_t *dip,
2109		ddi_eventcookie_t cookie, void *arg, void *bus_impldata),
2110		void *arg, ddi_callback_id_t *cb_id)
2111{
2112	cbus_t *cbp;
2113	int	cb_instance;
2114	int	rc;
2115
2116	/*
2117	 * get the soft state structure for the bus instance.
2118	 */
2119	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2120	    DDI_PROP_DONTPASS, "cbus-instance", -1);
2121	ASSERT(cb_instance >= 0);
2122	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
2123
2124	cardbus_err(dip, 6, "cardbus_add_eventcall\n");
2125
2126	ASSERT(number_of_cardbus_cards != 0);
2127
2128	if (cbp->cb_ndi_event_hdl == NULL) {
2129		/*
2130		 * We can't handle up (probably called at the attachment
2131		 * point) so pass it on up
2132		 */
2133		dev_info_t *pdip = ddi_get_parent(dip);
2134		cardbus_err(dip, 8,
2135		    "cardbus_add_eventcall calling %s - 0x%p\n",
2136		    ddi_driver_name(pdip),
2137		    (void *)
2138		    DEVI(pdip)->devi_ops->devo_bus_ops->bus_add_eventcall);
2139		return (DEVI(pdip)->devi_ops->devo_bus_ops->
2140		    bus_add_eventcall(pdip, rdip, cookie, callback,
2141		    arg, cb_id));
2142	}
2143
2144	cardbus_err(dip, 8,
2145	    "cardbus_add_eventcall calling ndi_event_add_callback\n");
2146
2147	rc = ndi_event_add_callback(cbp->cb_ndi_event_hdl, rdip, cookie,
2148	    callback, arg, NDI_EVENT_NOPASS, cb_id);
2149	cardbus_err(dip, 7,
2150	    "cardbus_add_eventcall rc %d cookie %p\n", rc, (void *)cookie);
2151	return (rc);
2152}
2153
2154static int
2155cardbus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
2156{
2157	cbus_t *cbp;
2158	int	cb_instance;
2159
2160	/*
2161	 * get the soft state structure for the bus instance.
2162	 */
2163	cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2164	    DDI_PROP_DONTPASS, "cbus-instance", -1);
2165	ASSERT(cb_instance >= 0);
2166	cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
2167
2168	cardbus_err(dip, 6, "cardbus_remove_eventcall\n");
2169
2170	ASSERT(number_of_cardbus_cards != 0);
2171
2172	if (cbp->cb_ndi_event_hdl == NULL) {
2173		/*
2174		 * We can't handle up (probably called at the attachment
2175		 * point) so pass it on up
2176		 */
2177		dev_info_t *pdip = ddi_get_parent(dip);
2178		cardbus_err(dip, 8,
2179		    "cardbus_remove_eventcall calling %s - 0x%p\n",
2180		    ddi_driver_name(pdip),
2181		    (void *)
2182		    DEVI(pdip)->devi_ops->devo_bus_ops->bus_remove_eventcall);
2183		return (DEVI(pdip)->devi_ops->devo_bus_ops->
2184		    bus_remove_eventcall(pdip, cb_id));
2185	}
2186
2187	return (ndi_event_remove_callback(cbp->cb_ndi_event_hdl, cb_id));
2188}
2189
2190static int
2191cardbus_post_event(dev_info_t *dip, dev_info_t *rdip,
2192		ddi_eventcookie_t cookie, void *bus_impldata)
2193{
2194	_NOTE(ARGUNUSED(rdip, cookie, bus_impldata))
2195	cardbus_err(dip, 1, "cardbus_post_event()\n");
2196	return (DDI_FAILURE);
2197}
2198
2199static int cardbus_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2200		ddi_intr_handle_impl_t *hdlp);
2201static int cardbus_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2202		ddi_intr_handle_impl_t *hdlp);
2203static int cardbus_enable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2204		ddi_intr_handle_impl_t *hdlp);
2205static int cardbus_disable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2206		ddi_intr_handle_impl_t *hdlp);
2207
2208static int
2209cardbus_get_pil(dev_info_t *dip)
2210{
2211	return ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2212	    "interrupt-priorities", 6);
2213}
2214
2215static int
2216cardbus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
2217	ddi_intr_handle_impl_t *hdlp, void *result)
2218{
2219	int ret = DDI_SUCCESS;
2220
2221#if defined(CARDBUS_DEBUG)
2222	cardbus_err(dip, 8, "cardbus_intr_ops() intr_op=%d\n", (int)intr_op);
2223#endif
2224
2225	switch (intr_op) {
2226	case DDI_INTROP_GETCAP:
2227		*(int *)result = DDI_INTR_FLAG_LEVEL;
2228		break;
2229	case DDI_INTROP_ALLOC:
2230		*(int *)result = hdlp->ih_scratch1;
2231		break;
2232	case DDI_INTROP_FREE:
2233		break;
2234	case DDI_INTROP_GETPRI:
2235		*(int *)result = hdlp->ih_pri ?
2236		    hdlp->ih_pri : cardbus_get_pil(dip);
2237		break;
2238	case DDI_INTROP_SETPRI:
2239		break;
2240	case DDI_INTROP_ADDISR:
2241	case DDI_INTROP_REMISR:
2242		if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) {
2243			cardbus_err(dip, 1, "Only fixed interrupts\n");
2244			return (DDI_FAILURE);
2245		}
2246		break;
2247	case DDI_INTROP_ENABLE:
2248		ret = cardbus_enable_intr_impl(dip, rdip, hdlp);
2249		break;
2250	case DDI_INTROP_DISABLE:
2251		ret = cardbus_disable_intr_impl(dip, rdip, hdlp);
2252		break;
2253	case DDI_INTROP_NINTRS:
2254	case DDI_INTROP_NAVAIL:
2255#ifdef sparc
2256		*(int *)result = i_ddi_get_intx_nintrs(rdip);
2257#else
2258		*(int *)result = 1;
2259#endif
2260		break;
2261	case DDI_INTROP_SUPPORTED_TYPES:
2262		*(int *)result = DDI_INTR_TYPE_FIXED;
2263		break;
2264	default:
2265		ret = DDI_ENOTSUP;
2266		break;
2267	}
2268
2269	return (ret);
2270}
2271
2272static int
2273cardbus_enable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2274		ddi_intr_handle_impl_t *hdlp)
2275{
2276	anp_t *anp = (anp_t *)ddi_get_driver_private(dip);
2277	set_irq_handler_t sih;
2278	uint_t socket = 0; /* We only support devices */
2279			    /* with one socket per function */
2280
2281	ASSERT(anp != NULL);
2282
2283	cardbus_err(dip, 9,
2284	    "cardbus_enable_intr_impl, intr=0x%p, arg1=0x%p, arg2=0x%p"
2285	    "rdip=0x%p(%s)\n",
2286	    (void *) hdlp->ih_cb_func,
2287	    hdlp->ih_cb_arg1, hdlp->ih_cb_arg2,
2288	    (void *) rdip, ddi_driver_name(rdip));
2289
2290	if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) {
2291		cardbus_err(dip, 1, "Only fixed interrupts\n");
2292		return (DDI_FAILURE);
2293	}
2294
2295	sih.socket = socket;
2296	sih.handler_id = (unsigned)(long)rdip;
2297	sih.handler = (f_tt *)hdlp->ih_cb_func;
2298	sih.arg1 = hdlp->ih_cb_arg1;
2299	sih.arg2 = hdlp->ih_cb_arg2;
2300	sih.irq = cardbus_get_pil(dip);
2301
2302	if ((*anp->an_if->pcif_set_interrupt)(dip, &sih) != SUCCESS)
2303		return (DDI_FAILURE);
2304
2305	return (DDI_SUCCESS);
2306}
2307
2308static int
2309cardbus_disable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2310		ddi_intr_handle_impl_t *hdlp)
2311{
2312	anp_t *anp = (anp_t *)ddi_get_driver_private(dip);
2313	clear_irq_handler_t cih;
2314	uint_t socket = 0; /* We only support devices with 1 socket per */
2315			    /* function. */
2316
2317	ASSERT(anp != NULL);
2318
2319	cardbus_err(dip, 9,
2320	    "cardbus_disable_intr_impl, intr=0x%p, arg1=0x%p, arg2=0x%p"
2321	    "rdip=0x%p(%s%d)\n",
2322	    (void *) hdlp->ih_cb_func,
2323	    hdlp->ih_cb_arg1, hdlp->ih_cb_arg2,
2324	    (void *) rdip, ddi_driver_name(rdip), ddi_get_instance(rdip));
2325
2326	if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) {
2327		cardbus_err(dip, 1, "Only fixed interrupts\n");
2328		return (DDI_FAILURE);
2329	}
2330
2331	cih.socket = socket;
2332	cih.handler_id = (unsigned)(long)rdip;
2333	cih.handler = (f_tt *)hdlp->ih_cb_func;
2334
2335	if ((*anp->an_if->pcif_clr_interrupt)(dip, &cih) != SUCCESS)
2336		return (DDI_FAILURE);
2337
2338	return (DDI_SUCCESS);
2339}
2340
2341#if defined(CARDBUS_DEBUG)
2342static int	cardbus_do_pprintf = 0;
2343#endif
2344
2345/*PRINTFLIKE3*/
2346void
2347cardbus_err(dev_info_t *dip, int level, const char *fmt, ...)
2348{
2349	if (cardbus_debug && (level <= cardbus_debug)) {
2350		va_list adx;
2351		int	instance;
2352		char	buf[256];
2353		const char	*name;
2354		char	*nl = "";
2355#if !defined(CARDBUS_DEBUG)
2356		int	ce;
2357		char	qmark = 0;
2358
2359		if (level <= 3)
2360			ce = CE_WARN;
2361		else
2362			ce = CE_CONT;
2363		if (level == 4)
2364			qmark = 1;
2365#endif
2366
2367		if (dip) {
2368			instance = ddi_get_instance(dip);
2369			/* name = ddi_binding_name(dip); */
2370			name = ddi_driver_name(dip);
2371		} else {
2372			instance = 0;
2373			name = "";
2374		}
2375
2376		va_start(adx, fmt);
2377		/* vcmn_err(ce, fmt, adx); */
2378		/* vprintf(fmt, adx); */
2379		/* prom_vprintf(fmt, adx); */
2380		(void) vsprintf(buf, fmt, adx);
2381		va_end(adx);
2382
2383		if (buf[strlen(buf) - 1] != '\n')
2384			nl = "\n";
2385
2386#if defined(CARDBUS_DEBUG)
2387		if (cardbus_do_pprintf) {
2388			if (dip) {
2389				if (instance >= 0)
2390					prom_printf("%s(%d),0x%p: %s%s",
2391					    name, instance, (void *)dip,
2392					    buf, nl);
2393				else
2394					prom_printf("%s,0x%p: %s%s", name,
2395					    (void *)dip, buf, nl);
2396			} else
2397				prom_printf("%s%s", buf, nl);
2398		} else {
2399			if (dip) {
2400				if (instance >= 0)
2401					cmn_err(CE_CONT, "%s(%d),0x%p: %s%s",
2402					    name, instance, (void *)dip,
2403					    buf, nl);
2404				else
2405					cmn_err(CE_CONT, "%s,0x%p: %s%s",
2406					    name, (void *)dip, buf, nl);
2407			} else
2408				cmn_err(CE_CONT, "%s%s", buf, nl);
2409		}
2410#else
2411		if (dip)
2412			cmn_err(ce, qmark ? "?%s%d: %s%s" : "%s%d: %s%s",
2413			    name, instance, buf, nl);
2414		else
2415			cmn_err(ce, qmark ? "?%s%s" : "%s%s", buf, nl);
2416#endif
2417	}
2418}
2419
2420static void cardbus_expand_busrange(dev_info_t *dip)
2421{
2422	dev_info_t *pdip;
2423	cardbus_bus_range_t *bus_range;
2424	int len;
2425
2426	pdip = ddi_get_parent(dip);
2427
2428	if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, "bus-range",
2429	    (caddr_t)&bus_range, &len) == DDI_PROP_SUCCESS) {
2430		ndi_ra_request_t req;
2431		uint64_t next_bus, blen;
2432		uint32_t ret;
2433		ddi_acc_handle_t handle;
2434
2435		if (bus_range->lo != bus_range->hi)
2436			cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2437			    "%u -> %u\n", bus_range->lo, bus_range->hi);
2438		else {
2439
2440			bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
2441			req.ra_addr = bus_range->lo + 1;
2442			req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
2443			req.ra_len = 12;
2444
2445			while ((req.ra_len > 0) &&
2446			    (ret = ndi_ra_alloc(ddi_get_parent(pdip), &req,
2447			    &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
2448			    NDI_RA_PASS)) != NDI_SUCCESS)
2449				req.ra_len--;
2450
2451			if (ret != NDI_SUCCESS) {
2452				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2453				    "fail to allocate bus number\n");
2454				goto exit;
2455			}
2456
2457			bus_range->hi = bus_range->lo + req.ra_len;
2458			if (ndi_prop_update_int_array(DDI_DEV_T_NONE, pdip,
2459			    "bus-range", (int *)bus_range, 2) != DDI_SUCCESS) {
2460				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2461				    "fail to update bus-range property\n");
2462				goto exit;
2463			}
2464
2465			if (pci_config_setup(pdip, &handle) != DDI_SUCCESS) {
2466				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2467				    "fail to pci_config_setup\n");
2468				goto exit;
2469			}
2470
2471			pci_config_put8(handle, PCI_BCNF_SECBUS, bus_range->lo);
2472			pci_config_put8(handle, PCI_BCNF_SUBBUS, bus_range->hi);
2473
2474			cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2475			    "parent dip %u -> %u\n",
2476			    pci_config_get8(handle, PCI_BCNF_SECBUS),
2477			    pci_config_get8(handle, PCI_BCNF_SUBBUS));
2478			pci_config_teardown(&handle);
2479
2480			if (ndi_ra_map_setup(pdip, NDI_RA_TYPE_PCI_BUSNUM)
2481			    != NDI_SUCCESS) {
2482				cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2483				    "fail to ndi_ra_map_setup of bus number\n");
2484				goto exit;
2485			}
2486
2487			(void) ndi_ra_free(pdip,
2488			    (uint64_t)bus_range->lo + 1, req.ra_len,
2489			    NDI_RA_TYPE_PCI_BUSNUM, 0);
2490		}
2491
2492		bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
2493		req.ra_len = 2;
2494
2495		while ((req.ra_len > 0) &&
2496		    (ret = ndi_ra_alloc(pdip, &req,
2497		    &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
2498		    0)) != NDI_SUCCESS)
2499			req.ra_len--;
2500
2501		cardbus_err(dip, 1, "cardbus_expand_busrange: "
2502		    "cardbus dip base %u length %d\n",
2503		    (int)next_bus, (int)req.ra_len);
2504
2505		if (ret != NDI_SUCCESS) {
2506			cardbus_err(dip, 1, "cardbus_expand_busrange: "
2507			    "fail to allocate bus number of length %d "
2508			    "from parent\n",
2509			    (int)req.ra_len);
2510			goto exit;
2511		}
2512
2513		if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_BUSNUM)
2514		    != NDI_SUCCESS) {
2515			cardbus_err(dip, 1, "cardbus_expand_busrange: "
2516			    "fail to ndi_ra_map_setup of bus numbers\n");
2517			goto exit;
2518		}
2519
2520		(void) ndi_ra_free(dip,
2521		    (uint64_t)next_bus, req.ra_len,
2522		    NDI_RA_TYPE_PCI_BUSNUM, 0);
2523exit:
2524		kmem_free(bus_range, len);
2525
2526	} else
2527		cardbus_err(pdip, 1, "cardbus_expand_busrange: "
2528		    "parent dip doesn't have busrange prop\n");
2529}
2530