xref: /titanic_41/usr/src/uts/common/io/cardbus/cardbus.c (revision 903a11ebdc8df157c4700150f41f1f262f4a8ae8)
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 
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 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",
166 };
167 
168 static struct modlinkage modlinkage = {
169 	MODREV_1,
170 	&modlmisc,
171 	NULL
172 };
173 
174 int
_init(void)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
_fini(void)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
_info(struct modinfo * modinfop)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
cardbus_claim_pci_busnum(dev_info_t * dip,void * arg)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
cardbus_walk_node_child(dev_info_t * parent,int (* f)(dev_info_t *,void *),void * arg)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 
cardbus_fix_hostbridge_busrange(dev_info_t * dip)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 *
cardbus_find_hsbridge_dip(dev_info_t * dip)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
cardbus_attach(dev_info_t * dip,cb_nexus_cb_t * nex_ops)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
cardbus_detach(dev_info_t * dip)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
cardbus_load_cardbus(dev_info_t * dip,uint_t socket,uint32_t pc_base)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
cardbus_unload_cardbus(dev_info_t * dip)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 
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 
738 static boolean_t
is_32bit_pccard(dev_info_t * dip)739 is_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 
760 void
cardbus_save_children(dev_info_t * dip)761 cardbus_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 
776 void
cardbus_restore_children(dev_info_t * dip)777 cardbus_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 
792 static int
cardbus_convert_properties(dev_info_t * dip)793 cardbus_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 
887 static void
cardbus_revert_properties(dev_info_t * dip)888 cardbus_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 
901 static int
cardbus_prop_op(dev_t dev,dev_info_t * dip,dev_info_t * ch_dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp)902 cardbus_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 
916 static int
cardbus_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)917 cardbus_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 
1094 static void
cardbus_init_child_regs(dev_info_t * child)1095 cardbus_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 
1208 static int
cardbus_initchild(dev_info_t * rdip,dev_info_t * dip,dev_info_t * child,void * result)1209 cardbus_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 
1300 static int
cardbus_name_child(dev_info_t * child,char * name,int namelen)1301 cardbus_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 
1362 static void
cardbus_removechild(dev_info_t * dip)1363 cardbus_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 
1387 static char	cb_bnamestr[] = "binding_name";
1388 static char	cb_venidstr[] = "VendorID";
1389 static char	cb_devidstr[] = "DeviceID";
1390 static char	cb_nnamestr[] = "nodename";
1391 
1392 static 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 
1397 static int
check_token(char * token,int * len)1398 check_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 
1432 static char *
find_token(char ** cp,int * l,char * endc)1433 find_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 
1451 static int
parse_token(char * token)1452 parse_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 
1467 static int
token_to_hex(char * token,unsigned * val,int len)1468 token_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 
1503 static int
token_to_dec(char * token,unsigned * val,int len)1504 token_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 
1527 static void
cardbus_add_prop(struct cb_deviceset_props * cdsp,int type,char * name,caddr_t vp,int len)1528 cardbus_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 
1544 static void
cardbus_add_stringprop(struct cb_deviceset_props * cdsp,char * name,char * vp,int len)1545 cardbus_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 
1555 static void
cardbus_prop_free(ddi_prop_t * propp)1556 cardbus_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 
1573 static void
cardbus_devprops_free(struct cb_deviceset_props * cbdp)1574 cardbus_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  */
1601 static int
cardbus_parse_devprop(cbus_t * cbp,char * cp)1602 cardbus_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 
1835 static void
cardbus_device_props(cbus_t * cbp)1836 cardbus_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 
1853 static int
cardbus_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)1854 cardbus_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 
1889 static void
pcirp2rp(const pci_regspec_t * pci_rp,struct regspec * rp)1890 pcirp2rp(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 
1905 static int
cardbus_dma_allochdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_attr_t * attr,int (* waitfp)(caddr_t),caddr_t arg,ddi_dma_handle_t * handlep)1906 cardbus_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 
1927 static int
cardbus_dma_freehdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)1928 cardbus_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 
1948 static int
cardbus_dma_bindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,struct ddi_dma_req * dmareq,ddi_dma_cookie_t * cp,uint_t * ccountp)1949 cardbus_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 
1971 static int
cardbus_dma_unbindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)1972 cardbus_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 
1993 static int
cardbus_dma_flush(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,off_t off,size_t len,uint_t cache_flags)1994 cardbus_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 
2016 static int
cardbus_dma_win(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,uint_t win,off_t * offp,size_t * lenp,ddi_dma_cookie_t * cookiep,uint_t * ccountp)2017 cardbus_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 
2038 static int
cardbus_dma_map(dev_info_t * dip,dev_info_t * rdip,struct ddi_dma_req * dmareqp,ddi_dma_handle_t * handlep)2039 cardbus_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 
2060 static int
cardbus_get_eventcookie(dev_info_t * dip,dev_info_t * rdip,char * eventname,ddi_eventcookie_t * cookiep)2061 cardbus_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 
2106 static int
cardbus_add_eventcall(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t cookie,void (* callback)(dev_info_t * dip,ddi_eventcookie_t cookie,void * arg,void * bus_impldata),void * arg,ddi_callback_id_t * cb_id)2107 cardbus_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 
2154 static int
cardbus_remove_eventcall(dev_info_t * dip,ddi_callback_id_t cb_id)2155 cardbus_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 
2190 static int
cardbus_post_event(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t cookie,void * bus_impldata)2191 cardbus_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 
2199 static int cardbus_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2200 		ddi_intr_handle_impl_t *hdlp);
2201 static int cardbus_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2202 		ddi_intr_handle_impl_t *hdlp);
2203 static int cardbus_enable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2204 		ddi_intr_handle_impl_t *hdlp);
2205 static int cardbus_disable_intr_impl(dev_info_t *dip, dev_info_t *rdip,
2206 		ddi_intr_handle_impl_t *hdlp);
2207 
2208 static int
cardbus_get_pil(dev_info_t * dip)2209 cardbus_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 
2215 static int
cardbus_intr_ops(dev_info_t * dip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)2216 cardbus_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 
2272 static int
cardbus_enable_intr_impl(dev_info_t * dip,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp)2273 cardbus_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 
2308 static int
cardbus_disable_intr_impl(dev_info_t * dip,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp)2309 cardbus_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)
2342 static int	cardbus_do_pprintf = 0;
2343 #endif
2344 
2345 /*PRINTFLIKE3*/
2346 void
cardbus_err(dev_info_t * dip,int level,const char * fmt,...)2347 cardbus_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 
cardbus_expand_busrange(dev_info_t * dip)2420 static 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);
2523 exit:
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