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