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