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