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