1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright (c) * Copyright (c) 2001 Tadpole Technology plc
28 * All rights reserved.
29 * From "@(#)pcicfg.c 1.31 99/06/18 SMI"
30 */
31
32 /*
33 * Copyright 2023 Oxide Computer Company
34 */
35
36 /*
37 * Cardbus module
38 */
39
40 #include <sys/conf.h>
41 #include <sys/modctl.h>
42
43 #include <sys/pci.h>
44
45 #include <sys/ddi.h>
46 #include <sys/sunndi.h>
47 #include <sys/ddi_impldefs.h>
48
49 #include <sys/hotplug/hpcsvc.h>
50
51 #include <sys/pctypes.h>
52 #include <sys/pcmcia.h>
53 #include <sys/sservice.h>
54 #include <sys/note.h>
55
56 #include <sys/pci/pci_types.h>
57 #include <sys/pci/pci_sc.h>
58
59 #include <sys/pcic_reg.h>
60 #include <sys/pcic_var.h>
61 #include <sys/pcmcia.h>
62
63 #ifdef sparc
64 #include <sys/ddi_subrdefs.h>
65 #elif defined(__x86)
66 #include <sys/pci_intr_lib.h>
67 #include <sys/mach_intr.h>
68 #endif
69
70 #include "cardbus.h"
71 #include "cardbus_parse.h"
72 #include "cardbus_hp.h"
73 #include "cardbus_cfg.h"
74
75 static int cardbus_command_default = PCI_COMM_SERR_ENABLE |
76 PCI_COMM_WAIT_CYC_ENAB |
77 PCI_COMM_PARITY_DETECT |
78 PCI_COMM_ME | PCI_COMM_MAE |
79 PCI_COMM_IO;
80
81 static int cardbus_next_instance = 0;
82 static int cardbus_count = 0;
83 int number_of_cardbus_cards = 0;
84
85 static int cardbus_bus_map(dev_info_t *dip, dev_info_t *rdip,
86 ddi_map_req_t *mp, off_t offset, off_t len, caddr_t *vaddrp);
87 static void pcirp2rp(const pci_regspec_t *pci_rp, struct regspec *rp);
88
89 static int cardbus_ctlops(dev_info_t *, dev_info_t *,
90 ddi_ctl_enum_t, void *arg, void *);
91 static void cardbus_init_child_regs(dev_info_t *child);
92 static int cardbus_initchild(dev_info_t *, dev_info_t *,
93 dev_info_t *, void *);
94 static int cardbus_name_child(dev_info_t *, char *, int);
95 static void cardbus_removechild(dev_info_t *dip);
96
97 static int cardbus_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
98 ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg,
99 ddi_dma_handle_t *handlep);
100 static int cardbus_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
101 ddi_dma_handle_t handle);
102 static int cardbus_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
103 ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
104 ddi_dma_cookie_t *cp, uint_t *ccountp);
105 static int cardbus_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
106 ddi_dma_handle_t handle);
107 static int cardbus_dma_flush(dev_info_t *dip, dev_info_t *rdip,
108 ddi_dma_handle_t handle, off_t off, size_t len,
109 uint_t cache_flags);
110 static int cardbus_dma_win(dev_info_t *dip, dev_info_t *rdip,
111 ddi_dma_handle_t handle, uint_t win, off_t *offp,
112 size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp);
113 static int cardbus_dma_map(dev_info_t *dip, dev_info_t *rdip,
114 struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep);
115
116 static int cardbus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
117 ddi_prop_op_t prop_op, int mod_flags,
118 char *name, caddr_t valuep, int *lengthp);
119
120 static int cardbus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
121 char *eventname, ddi_eventcookie_t *cookiep);
122 static int cardbus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
123 ddi_eventcookie_t cookie, void (*callback)(dev_info_t *dip,
124 ddi_eventcookie_t cookie, void *arg, void *bus_impldata),
125 void *arg, ddi_callback_id_t *cb_id);
126 static int cardbus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id);
127 static int cardbus_post_event(dev_info_t *dip, dev_info_t *rdip,
128 ddi_eventcookie_t cookie, void *bus_impldata);
129
130 static int cardbus_intr_ops(dev_info_t *dip, dev_info_t *rdip,
131 ddi_intr_op_t intr_op,
132 ddi_intr_handle_impl_t *hdlp, void *result);
133
134 static int check_token(char *token, int *len);
135 static char *find_token(char **cp, int *l, char *endc);
136 static int parse_token(char *token);
137 static int token_to_hex(char *token, unsigned *val, int len);
138 static int token_to_dec(char *token, unsigned *val, int len);
139 static void cardbus_add_prop(struct cb_deviceset_props *cdsp, int type,
140 char *name, caddr_t vp, int len);
141 static void cardbus_add_stringprop(struct cb_deviceset_props *cdsp,
142 char *name, char *vp, int len);
143 static void cardbus_prop_free(ddi_prop_t *propp);
144 static void cardbus_devprops_free(struct cb_deviceset_props *cbdp);
145 static int cardbus_parse_devprop(cbus_t *cbp, char *cp);
146 static void cardbus_device_props(cbus_t *cbp);
147
148 static void cardbus_expand_busrange(dev_info_t *dip);
149
150 static int cardbus_convert_properties(dev_info_t *dip);
151 static void cardbus_revert_properties(dev_info_t *dip);
152
153 /*
154 * driver global data
155 */
156 kmutex_t cardbus_list_mutex; /* Protects the probe handle list */
157 void *cardbus_state;
158 int cardbus_latency_timer = 0x40;
159 int cardbus_debug = 0;
160
161 /*
162 * Module linkage information for the kernel.
163 */
164 extern struct mod_ops mod_miscops;
165 static struct modlmisc modlmisc = {
166 &mod_miscops,
167 "Cardbus Configurator support",
168 };
169
170 static struct modlinkage modlinkage = {
171 MODREV_1,
172 &modlmisc,
173 NULL
174 };
175
176 int
_init(void)177 _init(void)
178 {
179 int error;
180
181 error = ddi_soft_state_init(&cardbus_state, sizeof (cbus_t), 0);
182 if (error != 0)
183 return (error);
184
185 mutex_init(&cardbus_list_mutex, NULL, MUTEX_DRIVER, NULL);
186 if ((error = mod_install(&modlinkage)) != 0) {
187 mutex_destroy(&cardbus_list_mutex);
188 }
189
190 return (error);
191 }
192
193 int
_fini(void)194 _fini(void)
195 {
196 int error;
197 if ((error = mod_remove(&modlinkage)) == 0) {
198 mutex_destroy(&cardbus_list_mutex);
199 ddi_soft_state_fini(&cardbus_state);
200 }
201 return (error);
202 }
203
204 int
_info(struct modinfo * modinfop)205 _info(struct modinfo *modinfop)
206 {
207 return (mod_info(&modlinkage, modinfop));
208 }
209
210 static
211 struct bus_ops cardbusbus_ops = {
212 BUSO_REV,
213 cardbus_bus_map,
214 NULL,
215 NULL,
216 NULL,
217 i_ddi_map_fault,
218 cardbus_dma_map,
219 cardbus_dma_allochdl,
220 cardbus_dma_freehdl,
221 cardbus_dma_bindhdl,
222 cardbus_dma_unbindhdl,
223 cardbus_dma_flush,
224 cardbus_dma_win,
225 ddi_dma_mctl,
226 cardbus_ctlops, /* (*bus_ctl)(); */
227 cardbus_prop_op,
228 cardbus_get_eventcookie, /* (*bus_get_eventcookie)(); */
229 cardbus_add_eventcall, /* (*bus_add_eventcall)(); */
230 cardbus_remove_eventcall, /* (*bus_remove_eventcall)(); */
231 cardbus_post_event, /* (*bus_post_event)(); */
232 NULL, /* (*bus_intr_ctl)(); */
233 NULL, /* (*bus_config)(); */
234 NULL, /* (*bus_unconfig)(); */
235 NULL, /* (*bus_fm_init)(); */
236 NULL, /* (*bus_fm_fini)(); */
237 NULL, /* (*bus_enter)(); */
238 NULL, /* (*bus_exit)(); */
239 NULL, /* (*bus_power)(); */
240 cardbus_intr_ops /* (*bus_intr_op)(); */
241 };
242
243 #define CB_EVENT_TAG_INSERT 0
244 #define CB_EVENT_TAG_REMOVE 1
245
246 static ndi_event_definition_t cb_ndi_event_defs[] = {
247 { CB_EVENT_TAG_INSERT, DDI_DEVI_INSERT_EVENT, EPL_INTERRUPT, 0 },
248 { CB_EVENT_TAG_REMOVE, DDI_DEVI_REMOVE_EVENT, EPL_INTERRUPT, 0 }
249 };
250
251 #define CB_N_NDI_EVENTS \
252 (sizeof (cb_ndi_event_defs) / sizeof (cb_ndi_event_defs[0]))
253
254 #ifdef sparc
255 struct busnum_ctrl {
256 int rv;
257 dev_info_t *dip;
258 cardbus_bus_range_t *range;
259 };
260
261 static int
cardbus_claim_pci_busnum(dev_info_t * dip,void * arg)262 cardbus_claim_pci_busnum(dev_info_t *dip, void *arg)
263 {
264 cardbus_bus_range_t pci_bus_range;
265 struct busnum_ctrl *ctrl;
266 ndi_ra_request_t req;
267 char bus_type[16] = "(unknown)";
268 int len;
269 uint64_t base;
270 uint64_t retlen;
271
272 ctrl = (struct busnum_ctrl *)arg;
273
274 /* check if this is a PCI bus node */
275 len = sizeof (bus_type);
276 if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF,
277 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
278 "device_type",
279 (caddr_t)&bus_type, &len) != DDI_SUCCESS)
280 return (0); /* (DDI_WALK_PRUNECHILD); */
281
282 if ((strcmp(bus_type, "pci") != 0) &&
283 (strcmp(bus_type, "pciex") != 0)) /* it is not a pci bus type */
284 return (0); /* (DDI_WALK_PRUNECHILD); */
285
286 /* look for the bus-range property */
287 len = sizeof (struct cardbus_bus_range);
288 if (ddi_getlongprop_buf(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
289 "bus-range", (caddr_t)&pci_bus_range, &len) == DDI_SUCCESS) {
290 cardbus_err(dip, 1, "cardbus_claim_pci_busnum: %u -> %u \n",
291 pci_bus_range.lo, pci_bus_range.hi);
292 if ((pci_bus_range.lo >= ctrl->range->lo) &&
293 (pci_bus_range.hi <= ctrl->range->hi)) {
294 cardbus_err(dip, 1,
295 "cardbus_claim_pci_busnum: claim %u -> %u \n",
296 pci_bus_range.lo, pci_bus_range.hi);
297
298 /* claim the bus range from the bus resource map */
299 bzero((caddr_t)&req, sizeof (req));
300 req.ra_addr = (uint64_t)pci_bus_range.lo;
301 req.ra_flags |= NDI_RA_ALLOC_SPECIFIED;
302 req.ra_len = (uint64_t)pci_bus_range.hi -
303 (uint64_t)pci_bus_range.lo + 1;
304
305 if (ndi_ra_alloc(ctrl->dip, &req, &base, &retlen,
306 NDI_RA_TYPE_PCI_BUSNUM, 0) == NDI_SUCCESS)
307 return (0); /* (DDI_WALK_PRUNECHILD); */
308 }
309 }
310
311 /*
312 * never Error return.
313 */
314 ctrl->rv = DDI_SUCCESS;
315 return (DDI_WALK_TERMINATE);
316 }
317
318 static void
cardbus_walk_node_child(dev_info_t * parent,int (* f)(dev_info_t *,void *),void * arg)319 cardbus_walk_node_child(dev_info_t *parent,
320 int (*f)(dev_info_t *, void *), void *arg)
321 {
322 dev_info_t *dip;
323 int ret;
324
325 for (dip = ddi_get_child(parent); dip;
326 dip = ddi_get_next_sibling(dip)) {
327
328 ret = (*f) (dip, arg);
329 if (ret)
330 return;
331 }
332 }
333
cardbus_fix_hostbridge_busrange(dev_info_t * dip)334 static void cardbus_fix_hostbridge_busrange(dev_info_t *dip)
335 {
336 cardbus_bus_range_t bus_range;
337 struct busnum_ctrl ctrl;
338
339 uint64_t next_bus;
340 uint64_t blen;
341 ndi_ra_request_t req;
342 int len;
343
344 cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange\n");
345
346 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
347 req.ra_len = 1;
348 if (ndi_ra_alloc(dip, &req,
349 &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
350 0) != NDI_SUCCESS) {
351 (void) ndi_ra_map_destroy(dip, NDI_RA_TYPE_PCI_BUSNUM);
352
353 if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_BUSNUM)
354 == NDI_FAILURE) {
355 cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange "
356 "NDI_RA_TYPE_PCI_BUSNUM setup fail\n");
357 return;
358 }
359
360 bus_range.lo = 0;
361 (void) ddi_getlongprop_buf(DDI_DEV_T_NONE, dip,
362 DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus_range, &len);
363 bus_range.hi = 255;
364
365 (void) ndi_ra_free(dip,
366 (uint64_t)bus_range.lo + 1,
367 (uint64_t)bus_range.hi - (uint64_t)bus_range.lo,
368 NDI_RA_TYPE_PCI_BUSNUM, 0);
369
370 ctrl.rv = DDI_SUCCESS;
371 ctrl.dip = dip;
372 ctrl.range = &bus_range;
373
374 cardbus_walk_node_child(dip, cardbus_claim_pci_busnum,
375 (void*)&ctrl);
376
377 if (ctrl.rv != DDI_SUCCESS)
378 cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange "
379 "cardbus_walk_node_child fails\n");
380
381 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
382 "bus-range", (int *)&bus_range, 2);
383
384 } else {
385 cardbus_err(dip, 1, "cardbus_fix_hostbridge_busrange "
386 "already set up %x\n", (int)next_bus);
387 (void) ndi_ra_free(dip, next_bus, (uint64_t)1,
388 NDI_RA_TYPE_PCI_BUSNUM, 0);
389 }
390 }
391
392 static dev_info_t *
cardbus_find_hsbridge_dip(dev_info_t * dip)393 cardbus_find_hsbridge_dip(dev_info_t *dip)
394 {
395 dev_info_t *pdip;
396
397 pdip = ddi_get_parent(dip);
398 while (pdip) {
399 if (ddi_get_parent(pdip) == ddi_root_node())
400 break;
401 pdip = ddi_get_parent(pdip);
402 }
403
404 return (pdip);
405 }
406 #endif /* sparc */
407
408 /*
409 * Attach a device to the cardbus infrastructure.
410 */
411 int
cardbus_attach(dev_info_t * dip,cb_nexus_cb_t * nex_ops)412 cardbus_attach(dev_info_t *dip, cb_nexus_cb_t *nex_ops)
413 {
414 cbus_t *cbp;
415 int cb_instance;
416 anp_t *anp = (anp_t *)ddi_get_driver_private(dip);
417 struct dev_info *devi = DEVI(dip);
418
419 mutex_enter(&cardbus_list_mutex);
420
421 /*
422 * Make sure that it is not already initialized.
423 */
424 if (ddi_prop_exists(DDI_DEV_T_ANY, dip,
425 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
426 "cbus-instance") == 1) {
427 cmn_err(CE_WARN,
428 "%s%d: cardbus instance already initialized!\n",
429 ddi_driver_name(dip), ddi_get_instance(dip));
430 mutex_exit(&cardbus_list_mutex);
431 return (DDI_FAILURE);
432 }
433
434 /*
435 * initialize soft state structure for the bus instance.
436 */
437 cb_instance = cardbus_next_instance++;
438
439 if (ddi_soft_state_zalloc(cardbus_state, cb_instance) != DDI_SUCCESS) {
440 cmn_err(CE_WARN, "%s%d: can't allocate cardbus soft state\n",
441 ddi_driver_name(dip), ddi_get_instance(dip));
442 mutex_exit(&cardbus_list_mutex);
443 return (DDI_FAILURE);
444 }
445
446 cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
447 cbp->cb_instance = cb_instance;
448 cbp->cb_dip = dip;
449 mutex_init(&cbp->cb_mutex, NULL, MUTEX_DRIVER, NULL);
450
451 /*
452 * Save the instance number of the soft state structure for
453 * this bus as a devinfo property.
454 */
455 if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
456 "cbus-instance", (caddr_t)&cb_instance,
457 sizeof (cb_instance)) != DDI_SUCCESS) {
458 cmn_err(CE_WARN,
459 "%s%d: failed to add the property 'cbus-instance'",
460 ddi_driver_name(dip), ddi_get_instance(dip));
461 ddi_soft_state_free(cardbus_state, cb_instance);
462 mutex_exit(&cardbus_list_mutex);
463 return (DDI_FAILURE);
464 }
465
466 cbp->cb_nex_ops = nex_ops;
467 /*
468 * TODO - Should probably be some sort of locking on the devinfo here.
469 */
470 cbp->orig_dopsp = devi->devi_ops;
471 cbp->orig_bopsp = devi->devi_ops->devo_bus_ops;
472 cbp->cb_dops = *devi->devi_ops;
473 devi->devi_ops = &cbp->cb_dops;
474
475 if (ndi_event_alloc_hdl(dip, *anp->an_iblock, &cbp->cb_ndi_event_hdl,
476 NDI_SLEEP) == NDI_SUCCESS) {
477 cbp->cb_ndi_events.ndi_n_events = CB_N_NDI_EVENTS;
478 cbp->cb_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
479 cbp->cb_ndi_events.ndi_event_defs = cb_ndi_event_defs;
480 if (ndi_event_bind_set(cbp->cb_ndi_event_hdl,
481 &cbp->cb_ndi_events,
482 NDI_SLEEP) != NDI_SUCCESS) {
483 cardbus_err(dip, 1,
484 "cardbus_attach: ndi_event_bind_set failed\n");
485 }
486 }
487
488 /*
489 * Check for device initialization property.
490 */
491 cardbus_device_props(cbp);
492
493 if (cardbus_init_hotplug(cbp) != DDI_SUCCESS) {
494 ddi_soft_state_free(cardbus_state, cb_instance);
495 mutex_exit(&cardbus_list_mutex);
496 return (DDI_FAILURE);
497 }
498
499 #ifdef sparc
500 /* a hack to fix the bus-range problem on pci root nodes */
501 {
502 dev_info_t *hs_dip;
503
504 hs_dip = cardbus_find_hsbridge_dip(dip);
505 cardbus_fix_hostbridge_busrange(hs_dip);
506 }
507 #endif
508
509 cardbus_expand_busrange(dip);
510 cardbus_count++;
511 mutex_exit(&cardbus_list_mutex);
512 return (DDI_SUCCESS);
513 }
514
515 #ifdef TODO
516 static int
cardbus_detach(dev_info_t * dip)517 cardbus_detach(dev_info_t *dip)
518 {
519 int cb_instance;
520 cbus_t *cbp;
521
522 mutex_enter(&cardbus_list_mutex);
523 /* get the instance number for the cardbus soft state data */
524 cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
525 DDI_PROP_DONTPASS, "cbus-instance", -1);
526 if (cb_instance < 0) {
527 mutex_exit(&cardbus_list_mutex);
528 return (DDI_FAILURE); /* no instance is setup for this bus */
529 }
530
531 cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
532
533 if (cbp->cb_dsp) {
534 struct cb_deviceset_props *cbdp, *ncbdp;
535
536 cbdp = cbp->cb_dsp;
537 while (cbdp) {
538 ncbdp = cbdp->next;
539 cardbus_devprops_free(cbdp);
540 cbdp = ncbdp;
541 }
542 }
543 /*
544 * Unregister the bus with the HPS.
545 *
546 * (Note: It is assumed that the HPS framework uninstalls
547 * event handlers for all the hot plug slots on this bus.)
548 */
549 (void) hpc_nexus_unregister_bus(dip);
550
551 if (cbp->cb_ndi_event_hdl != NULL) {
552 (void) ndi_event_unbind_set(cbp->cb_ndi_event_hdl,
553 &cbp->cb_ndi_events, NDI_SLEEP);
554 ndi_event_free_hdl(cbp->cb_ndi_event_hdl);
555 }
556
557 mutex_destroy(&cbp->cb_mutex);
558 if (cbp->nexus_path)
559 kmem_free(cbp->nexus_path, strlen(cbp->nexus_path) + 1);
560 if (cbp->name)
561 kmem_free(cbp->name, strlen(cbp->name) + 1);
562
563 ddi_soft_state_free(cardbus_state, cb_instance);
564
565 /* remove the 'cbus-instance' property from the devinfo node */
566 (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, "cbus-instance");
567
568 ASSERT(cardbus_count != 0);
569 --cardbus_count;
570
571 mutex_exit(&cardbus_list_mutex);
572 return (DDI_SUCCESS);
573 }
574 #endif
575
576 boolean_t
cardbus_load_cardbus(dev_info_t * dip,uint_t socket,uint32_t pc_base)577 cardbus_load_cardbus(dev_info_t *dip, uint_t socket, uint32_t pc_base)
578 {
579 #ifndef HOTPLUG
580 struct cardbus_config_ctrl ctrl;
581 #endif
582 int cb_instance;
583 cbus_t *cbp;
584 struct dev_info *devi = DEVI(dip);
585
586 _NOTE(ARGUNUSED(socket, pc_base))
587
588 #if defined(CARDBUS_DEBUG)
589 cardbus_err(dip, 6, "cardbus_load_cardbus\n");
590 #endif
591
592 cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
593 DDI_PROP_DONTPASS, "cbus-instance", -1);
594 ASSERT(cb_instance >= 0);
595 cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
596
597 if (cbp->fatal_problem)
598 return (B_FALSE);
599
600 if (cardbus_convert_properties(dip) == DDI_FAILURE)
601 return (B_FALSE);
602
603 number_of_cardbus_cards++;
604 devi->devi_ops->devo_bus_ops = &cardbusbus_ops;
605
606 #ifdef HOTPLUG
607 mutex_enter(&cbp->cb_mutex);
608 cbp->card_present = B_TRUE;
609
610 (void) hpc_slot_event_notify(cbp->slot_handle,
611 HPC_EVENT_SLOT_INSERTION, 0);
612 (void) hpc_slot_event_notify(cbp->slot_handle,
613 HPC_EVENT_SLOT_POWER_ON, 0);
614 (void) hpc_slot_event_notify(cbp->slot_handle,
615 HPC_EVENT_SLOT_CONFIGURE, 0);
616
617 mutex_exit(&cbp->cb_mutex);
618 #else
619 if (cardbus_configure(cbp) != PCICFG_SUCCESS) {
620 #if defined(CARDBUS_DEBUG)
621 cardbus_err(dip, 6, "cardbus_configure failed\n");
622 #endif
623 return (B_FALSE);
624 }
625
626 ctrl.rv = NDI_SUCCESS;
627 ctrl.busno = cardbus_primary_busno(dip);
628 ctrl.op = PCICFG_OP_ONLINE;
629 ctrl.dip = NULL;
630 ctrl.flags = PCICFG_FLAGS_CONTINUE;
631
632 /*
633 * The child of the dip is the cardbus dip. The child of the
634 * cardbus dip is the device itself
635 */
636 #if defined(CARDBUS_DEBUG)
637 cardbus_err(dip, 8, "cardbus_load_cardbus: calling cbus_configure\n");
638 #endif
639 ndi_devi_enter(dip);
640 ddi_walk_devs(ddi_get_child(dip), cbus_configure, (void *)&ctrl);
641 ndi_devi_exit(dip);
642
643 if (ctrl.rv != NDI_SUCCESS) {
644 cardbus_err(dip, 1,
645 "cardbus_load_cardbus (%s%d): failed to attach (%d)\n",
646 ctrl.dip ? ddi_driver_name(ctrl.dip) : "Unknown",
647 ctrl.dip ? ddi_get_instance(ctrl.dip) : 0,
648 ctrl.rv);
649
650 /*
651 * Returning error here will cause the pcic_load_cardbus() call
652 * to fail. This will invoke pcic_unload_cardbus() which calls
653 * cardbus_unload_cardbus() below.
654 */
655 return (B_FALSE);
656 }
657 #endif
658
659 #if defined(CARDBUS_DEBUG)
660 cardbus_err(dip, 7, "cardbus_load_cardbus: returning TRUE\n");
661 #endif
662
663 return (B_TRUE);
664 }
665
666 /*
667 * Unload the cardbus module
668 */
669 void
cardbus_unload_cardbus(dev_info_t * dip)670 cardbus_unload_cardbus(dev_info_t *dip)
671 {
672 int cb_instance;
673 #ifndef HOTPLUG
674 int prim_bus = cardbus_primary_busno(dip);
675 int rval;
676 #endif
677 cbus_t *cbp;
678
679 cardbus_err(dip, 6, "cardbus_unload_cardbus\n");
680
681 cb_instance = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
682 DDI_PROP_DONTPASS, "cbus-instance", -1);
683 ASSERT(cb_instance >= 0);
684 cbp = (cbus_t *)ddi_get_soft_state(cardbus_state, cb_instance);
685
686 if (number_of_cardbus_cards == 0)
687 return;
688
689 #ifdef HOTPLUG
690 mutex_enter(&cbp->cb_mutex);
691 cbp->card_present = B_FALSE;
692
693 (void) hpc_slot_event_notify(cbp->slot_handle,
694 HPC_EVENT_SLOT_POWER_OFF, 0);
695 (void) hpc_slot_event_notify(cbp->slot_handle,
696 HPC_EVENT_SLOT_UNCONFIGURE, 0);
697 (void) hpc_slot_event_notify(cbp->slot_handle,
698 HPC_EVENT_SLOT_REMOVAL, 0);
699
700 mutex_exit(&cbp->cb_mutex);
701 #else
702
703 cardbus_err(dip, 8,
704 "cardbus_unload_cardbus: calling cardbus_unconfigure_node\n");
705
706 rval = cardbus_unconfigure_node(dip, prim_bus, B_TRUE);
707
708 if (rval != NDI_SUCCESS) {
709 cardbus_err(dip, 4,
710 "cardbus_unload_cardbus: "
711 "cardbus_unconfigure_node failed\n");
712 number_of_cardbus_cards--;
713 cbp->fatal_problem = B_TRUE;
714 cmn_err(CE_WARN,
715 "cardbus(%s%d): Failed to remove device tree: "
716 "Slot disabled",
717 ddi_get_name(dip), ddi_get_instance(dip));
718 return;
719 }
720
721 (void) cardbus_unconfigure(cbp);
722 #endif
723
724 /*
725 * Inform the lower drivers that the card has been removed
726 */
727 if (cbp->cb_ndi_event_hdl != NULL) {
728 ddi_eventcookie_t cookie;
729 if (ndi_event_retrieve_cookie(cbp->cb_ndi_event_hdl, dip,
730 DDI_DEVI_REMOVE_EVENT, &cookie, 0) == NDI_SUCCESS) {
731 (void) ndi_event_run_callbacks(cbp->cb_ndi_event_hdl,
732 dip, cookie, NULL);
733 }
734 }
735
736 cardbus_revert_properties(dip);
737 }
738
739 static boolean_t
is_32bit_pccard(dev_info_t * dip)740 is_32bit_pccard(dev_info_t *dip)
741 {
742 int len;
743 char bus_type[16];
744
745 len = sizeof (bus_type);
746 if (ddi_prop_op(DDI_DEV_T_ANY, ddi_get_parent(dip),
747 PROP_LEN_AND_VAL_BUF, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
748 "device_type", (caddr_t)&bus_type, &len) != DDI_SUCCESS)
749 return (B_FALSE);
750
751 if ((strcmp(bus_type, "pci") != 0) &&
752 (strcmp(bus_type, "pciex") != 0) &&
753 (strcmp(bus_type, "cardbus") != 0)) /* not of pci type */
754 return (B_FALSE);
755
756 return (B_TRUE);
757 }
758
759 void
cardbus_save_children(dev_info_t * dip)760 cardbus_save_children(dev_info_t *dip)
761 {
762 for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
763 cardbus_save_children(ddi_get_child(dip));
764
765 if (strcmp("pcs", ddi_node_name(dip)) == 0)
766 continue;
767 if (!is_32bit_pccard(dip))
768 continue;
769 cardbus_err(dip, 1, "Saving device\n");
770 (void) pci_save_config_regs(dip);
771 }
772
773 }
774
775 void
cardbus_restore_children(dev_info_t * dip)776 cardbus_restore_children(dev_info_t *dip)
777 {
778 for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
779 cardbus_restore_children(ddi_get_child(dip));
780
781 if (strcmp("pcs", ddi_node_name(dip)) == 0)
782 continue;
783 if (!is_32bit_pccard(dip))
784 continue;
785 cardbus_err(dip, 1, "restoring device\n");
786 (void) pci_restore_config_regs(dip);
787 }
788
789 }
790
791 static int
cardbus_convert_properties(dev_info_t * dip)792 cardbus_convert_properties(dev_info_t *dip)
793 {
794 struct pcm_regs *pcic_avail_p, *old_avail_p;
795 pci_regspec_t *cb_avail_p, *new_avail_p;
796 pcic_ranges_t *pcic_range_p, *old_range_p;
797 cardbus_range_t *cb_range_p, *new_range_p;
798 int range_len, range_entries, i;
799 int avail_len, avail_entries;
800
801 #if defined(CARDBUS_DEBUG)
802 cardbus_err(dip, 6, "cardbus_convert_properties\n");
803 #endif
804
805 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
806 "#address-cells", 3) != DDI_SUCCESS) {
807 cardbus_err(dip, 1, "cardbus_convert_properties: "
808 "failed to update #address-cells property\n");
809 return (DDI_FAILURE);
810 }
811 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
812 "#size-cells", 2) != DDI_SUCCESS) {
813 cardbus_err(dip, 1, "cardbus_convert_properties: "
814 "failed to update #size-cells property\n");
815 return (DDI_FAILURE);
816 }
817
818 if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "available",
819 (caddr_t)&pcic_avail_p, &avail_len) != DDI_PROP_SUCCESS) {
820 cardbus_err(dip, 1, "cardbus_convert_properties: "
821 "no available property for pcmcia\n");
822 } else {
823 avail_entries = avail_len / sizeof (struct pcm_regs);
824 cb_avail_p = kmem_alloc(sizeof (pci_regspec_t) * avail_entries,
825 KM_SLEEP);
826
827 old_avail_p = pcic_avail_p;
828 new_avail_p = cb_avail_p;
829 for (i = 0; i < avail_entries;
830 i++, old_avail_p++, new_avail_p++) {
831 new_avail_p->pci_phys_hi = old_avail_p->phys_hi;
832 new_avail_p->pci_phys_mid = 0;
833 new_avail_p->pci_phys_low = old_avail_p->phys_lo;
834 new_avail_p->pci_size_hi = 0;
835 new_avail_p->pci_size_low = old_avail_p->phys_len;
836 }
837
838 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
839 "available",
840 (int *)cb_avail_p,
841 (sizeof (pci_regspec_t) * avail_entries)/sizeof (int));
842
843 kmem_free(pcic_avail_p, avail_len);
844 kmem_free(cb_avail_p, sizeof (pci_regspec_t) * avail_entries);
845 }
846
847 if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "ranges",
848 (caddr_t)&pcic_range_p, &range_len) != DDI_PROP_SUCCESS) {
849 cardbus_err(dip, 1, "cardbus_convert_properties: "
850 "no ranges property for pcmcia\n");
851 } else {
852 range_entries = range_len / sizeof (pcic_ranges_t);
853 cb_range_p = kmem_alloc(
854 sizeof (cardbus_range_t) * range_entries, KM_SLEEP);
855
856 old_range_p = pcic_range_p;
857 new_range_p = cb_range_p;
858 for (i = 0; i < range_entries;
859 i++, old_range_p++, new_range_p++) {
860 new_range_p->child_hi =
861 old_range_p->pcic_range_caddrhi;
862 new_range_p->child_mid = 0;
863 new_range_p->child_lo =
864 old_range_p->pcic_range_caddrlo;
865 new_range_p->parent_hi =
866 old_range_p->pcic_range_paddrhi;
867 new_range_p->parent_mid =
868 old_range_p->pcic_range_paddrmid;
869 new_range_p->parent_lo =
870 old_range_p->pcic_range_paddrlo;
871 new_range_p->size_hi = 0;
872 new_range_p->size_lo = old_range_p->pcic_range_size;
873 }
874
875 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
876 (int *)cb_range_p,
877 (sizeof (cardbus_range_t) * range_entries)/sizeof (int));
878
879 kmem_free(pcic_range_p, range_len);
880 kmem_free(cb_range_p, sizeof (cardbus_range_t) * range_entries);
881 }
882
883 return (DDI_SUCCESS);
884 }
885
886 static void
cardbus_revert_properties(dev_info_t * dip)887 cardbus_revert_properties(dev_info_t *dip)
888 {
889 #if defined(CARDBUS_DEBUG)
890 cardbus_err(dip, 6, "cardbus_revert_properties\n");
891 #endif
892
893 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "#address-cells");
894
895 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "#size-cells");
896
897 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "available");
898 }
899
900 static int
cardbus_prop_op(dev_t dev,dev_info_t * dip,dev_info_t * ch_dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp)901 cardbus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
902 ddi_prop_op_t prop_op, int mod_flags,
903 char *name, caddr_t valuep, int *lengthp)
904 {
905 #if defined(CARDBUS_DEBUG)
906 if ((ch_dip != dip) || (cardbus_debug >= 9))
907 cardbus_err(dip, 6,
908 "cardbus_prop_op(%s) (dip=0x%p, op=%d, name=%s)\n",
909 ddi_driver_name(ch_dip), (void *) dip, prop_op, name);
910 #endif
911 return (impl_ddi_bus_prop_op(dev, dip, ch_dip, prop_op,
912 mod_flags, name, valuep, lengthp));
913 }
914
915 static int
cardbus_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)916 cardbus_ctlops(dev_info_t *dip, dev_info_t *rdip,
917 ddi_ctl_enum_t ctlop, void *arg, void *result)
918 {
919 pci_regspec_t *regs;
920 int totreg, reglen;
921 const char *dname = ddi_driver_name(dip);
922
923 ASSERT(number_of_cardbus_cards != 0);
924
925 cardbus_err(dip, 6,
926 "cardbus_ctlops(%p, %p, %d, %p, %p)\n",
927 (void *)dip, (void *)rdip, ctlop, (void *)arg, (void *)result);
928
929 switch (ctlop) {
930 case DDI_CTLOPS_UNINITCHILD:
931 cardbus_removechild((dev_info_t *)arg);
932 return (DDI_SUCCESS);
933 case DDI_CTLOPS_POWER:
934 return (DDI_SUCCESS);
935
936 default:
937 /*
938 * Do Nothing
939 */
940 cardbus_err(dip, 8,
941 "cardbus_ctlops: Unsupported DDI_CTLOP %d\n", ctlop);
942 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
943
944 case DDI_CTLOPS_SIDDEV: /* see ddi_dev_is_sid(9F) */
945 return (DDI_SUCCESS);
946
947 case DDI_CTLOPS_SLAVEONLY: /* see ddi_slaveonly(9F) */
948 return (DDI_FAILURE); /* cardbus */
949
950 case DDI_CTLOPS_REGSIZE:
951 case DDI_CTLOPS_NREGS:
952 if (rdip == (dev_info_t *)NULL) {
953 *(int *)result = 0;
954 return (DDI_FAILURE);
955 }
956 break;
957
958 case DDI_CTLOPS_IOMIN:
959 /*
960 * If we are using the streaming cache, align at
961 * least on a cache line boundary. Otherwise use
962 * whatever alignment is passed in.
963 */
964
965 if (arg) {
966 int val = *((int *)result);
967
968 #ifdef PCI_SBUF_LINE_SIZE
969 val = maxbit(val, PCI_SBUF_LINE_SIZE);
970 #else
971 val = maxbit(val, 64);
972 #endif
973 *((int *)result) = val;
974 }
975 return (DDI_SUCCESS);
976
977 case DDI_CTLOPS_INITCHILD:
978 return (cardbus_initchild(rdip, dip, (dev_info_t *)arg,
979 result));
980
981 case DDI_CTLOPS_REPORTDEV:
982 if (rdip == (dev_info_t *)0)
983 return (DDI_FAILURE);
984
985 if (strcmp("pcs", ddi_node_name(rdip)) == 0)
986 cardbus_err(dip, 1,
987 "cardbus_ctlops: PCCard socket %d at %s@%s\n",
988 ddi_get_instance(rdip),
989 dname, ddi_get_name_addr(dip));
990 else {
991 pci_regspec_t *pci_rp;
992 dev_info_t *next;
993 int length;
994
995 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
996 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
997 (uint_t *)&length) != DDI_PROP_SUCCESS)
998 return (DDI_FAILURE);
999
1000 if (pci_rp->pci_phys_hi == 0)
1001 cardbus_err(dip, 1, "%s%d at %s@%s\n",
1002 ddi_driver_name(rdip),
1003 ddi_get_instance(rdip),
1004 dname, ddi_get_name_addr(dip));
1005 else {
1006 uint8_t bus, device, function;
1007 int32_t val32;
1008 char *ptr, buf[128];
1009
1010 bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1011 device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1012 function = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1013
1014 ptr = buf;
1015 (void) sprintf(ptr, " "
1016 "Bus %3d Device %2d Function %2d",
1017 bus, device, function);
1018 ptr = &ptr[strlen(ptr)];
1019
1020 val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
1021 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1022 "vendor-id", -1);
1023 if (val32 != -1) {
1024 (void) sprintf(ptr, " Vendor 0x%04x",
1025 val32);
1026 ptr = &ptr[strlen(ptr)];
1027 }
1028 val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
1029 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1030 "device-id", -1);
1031 if (val32 != -1) {
1032 (void) sprintf(ptr, " Device 0x%04x",
1033 val32);
1034 ptr = &ptr[strlen(ptr)];
1035 }
1036 val32 = ddi_getprop(DDI_DEV_T_ANY, rdip,
1037 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1038 "class-code", -1);
1039 if (val32 != -1) {
1040 const char *name;
1041
1042 if ((name = ddi_get_name(rdip)) !=
1043 NULL)
1044 (void) sprintf(ptr, " Name %s",
1045 name);
1046 else
1047 (void) sprintf(ptr,
1048 " Class 0x%x", val32 >> 8);
1049 ptr = &ptr[strlen(ptr)];
1050 }
1051
1052 *ptr++ = '\n';
1053 ASSERT(((caddr_t)ptr - (caddr_t)buf) <
1054 sizeof (buf));
1055 *ptr = '\0';
1056
1057 cardbus_err(dip, 1, buf);
1058 }
1059 ddi_prop_free(pci_rp);
1060
1061 for (next = ddi_get_child(rdip); next;
1062 next = ddi_get_next_sibling(next))
1063 (void) cardbus_ctlops(next, next,
1064 DDI_CTLOPS_REPORTDEV, arg, result);
1065 }
1066 return (DDI_SUCCESS);
1067 }
1068 *(int *)result = 0;
1069
1070 if (ddi_getlongprop(DDI_DEV_T_NONE, rdip,
1071 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
1072 (caddr_t)®s, ®len) != DDI_SUCCESS)
1073 return (DDI_FAILURE);
1074
1075 totreg = reglen / sizeof (pci_regspec_t);
1076 if (ctlop == DDI_CTLOPS_NREGS) {
1077 cardbus_err(dip, 6,
1078 "cardbus_ctlops, returning NREGS = %d\n", totreg);
1079 *(int *)result = totreg;
1080 } else if (ctlop == DDI_CTLOPS_REGSIZE) {
1081 const int rn = *(int *)arg;
1082 if (rn > totreg)
1083 return (DDI_FAILURE);
1084 cardbus_err(dip, 6,
1085 "cardbus_ctlops, returning REGSIZE(%d) = %d\n",
1086 rn, regs[rn].pci_size_low);
1087 *(off_t *)result = regs[rn].pci_size_low;
1088 }
1089 kmem_free(regs, reglen);
1090 return (DDI_SUCCESS);
1091 }
1092
1093 static void
cardbus_init_child_regs(dev_info_t * child)1094 cardbus_init_child_regs(dev_info_t *child)
1095 {
1096 ddi_acc_handle_t config_handle;
1097 uint16_t command_preserve, command;
1098 #if !defined(__x86)
1099 uint8_t bcr;
1100 #endif
1101 uint8_t header_type;
1102 uint8_t min_gnt, latency_timer;
1103 uint_t n;
1104
1105 /*
1106 * Map the child configuration space to for initialization.
1107 *
1108 * Set the latency-timer register to values appropriate
1109 * for the devices on the bus (based on other devices
1110 * MIN_GNT and MAX_LAT registers.
1111 *
1112 * Set the fast back-to-back enable bit in the command
1113 * register if it's supported and all devices on the bus
1114 * have the capability.
1115 *
1116 */
1117 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
1118 return;
1119
1120 cardbus_err(child, 6, "cardbus_init_child_regs()\n");
1121
1122 /*
1123 * Determine the configuration header type.
1124 */
1125 header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
1126
1127 /*
1128 * Support for "command-preserve" property. Note that we
1129 * add PCI_COMM_BACK2BACK_ENAB to the bits to be preserved
1130 * since the obp will set this if the device supports and
1131 * all targets on the same bus support it. Since psycho
1132 * doesn't support PCI_COMM_BACK2BACK_ENAB, it will never
1133 * be set. This is just here in case future revs do support
1134 * PCI_COMM_BACK2BACK_ENAB.
1135 */
1136 command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1137 DDI_PROP_DONTPASS,
1138 "command-preserve", 0);
1139 command = pci_config_get16(config_handle, PCI_CONF_COMM);
1140 command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
1141 command |= (cardbus_command_default & ~command_preserve);
1142 pci_config_put16(config_handle, PCI_CONF_COMM, command);
1143 command = pci_config_get16(config_handle, PCI_CONF_COMM);
1144
1145 #if !defined(__x86)
1146 /*
1147 * If the device has a bus control register then program it
1148 * based on the settings in the command register.
1149 */
1150 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
1151 bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
1152 if (cardbus_command_default & PCI_COMM_PARITY_DETECT)
1153 bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
1154 if (cardbus_command_default & PCI_COMM_SERR_ENABLE)
1155 bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
1156 bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
1157 pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
1158 }
1159 #endif
1160
1161 /*
1162 * Initialize cache-line-size configuration register if needed.
1163 */
1164 if (ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1165 "cache-line-size", 0) == 0) {
1166
1167 pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
1168 PCI_CACHE_LINE_SIZE);
1169 n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
1170 if (n != 0)
1171 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
1172 "cache-line-size", n);
1173 }
1174
1175 /*
1176 * Initialize latency timer registers if needed.
1177 */
1178 if (ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1179 "latency-timer", 0) == 0) {
1180
1181 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
1182 latency_timer = cardbus_latency_timer;
1183 pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
1184 latency_timer);
1185 } else {
1186 min_gnt = pci_config_get8(config_handle,
1187 PCI_CONF_MIN_G);
1188
1189 /*
1190 * Cardbus os only 33Mhz
1191 */
1192 if (min_gnt != 0) {
1193 latency_timer = min_gnt * 8;
1194 }
1195 }
1196 pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
1197 latency_timer);
1198 n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
1199 if (n != 0)
1200 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
1201 "latency-timer", n);
1202 }
1203
1204 pci_config_teardown(&config_handle);
1205 }
1206
1207 static int
cardbus_initchild(dev_info_t * rdip,dev_info_t * dip,dev_info_t * child,void * result)1208 cardbus_initchild(dev_info_t *rdip, dev_info_t *dip, dev_info_t *child,
1209 void *result)
1210 {
1211 char name[MAXNAMELEN];
1212 const char *dname = ddi_driver_name(dip);
1213 const struct cb_ops *cop;
1214
1215 _NOTE(ARGUNUSED(rdip, result))
1216
1217 cardbus_err(child, 6, "cardbus_initchild\n");
1218
1219 /*
1220 * Name the child
1221 */
1222 if (cardbus_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
1223 return (DDI_FAILURE);
1224
1225 ddi_set_name_addr(child, name);
1226 ddi_set_parent_data(child, NULL);
1227
1228 if (ndi_dev_is_persistent_node(child) == 0) {
1229 /*
1230 * Try to merge the properties from this prototype
1231 * node into real h/w nodes.
1232 */
1233 if (ndi_merge_node(child, cardbus_name_child) == DDI_SUCCESS) {
1234 /*
1235 * Merged ok - return failure to remove the node.
1236 */
1237 cardbus_removechild(child);
1238 return (DDI_FAILURE);
1239 }
1240 /*
1241 * The child was not merged into a h/w node,
1242 * but there's not much we can do with it other
1243 * than return failure to cause the node to be removed.
1244 */
1245 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
1246 ddi_driver_name(child), ddi_get_name_addr(child),
1247 ddi_driver_name(child));
1248 cardbus_removechild(child);
1249 return (DDI_NOT_WELL_FORMED);
1250 }
1251 cop = DEVI(dip)->devi_ops->devo_cb_ops;
1252
1253 if ((cop == NULL) || (!(cop->cb_flag & D_HOTPLUG))) {
1254 cmn_err(CE_WARN, "%s: driver doesn't support HOTPLUG\n", dname);
1255 return (DDI_FAILURE);
1256 }
1257
1258 cardbus_init_child_regs(child);
1259
1260 /*
1261 * Create ppd if needed.
1262 */
1263 if (ddi_get_parent_data(child) == NULL) {
1264 struct cardbus_parent_private_data *ppd;
1265
1266 #ifdef sparc
1267 ppd = (struct cardbus_parent_private_data *)
1268 kmem_zalloc(sizeof (struct cardbus_parent_private_data),
1269 KM_SLEEP);
1270
1271 #elif defined(__x86)
1272 ppd = (struct cardbus_parent_private_data *)
1273 kmem_zalloc(sizeof (struct cardbus_parent_private_data)
1274 + sizeof (struct intrspec), KM_SLEEP);
1275
1276 ppd->ppd.par_intr = (struct intrspec *)(ppd + 1);
1277 (ppd->ppd.par_intr)->intrspec_pri = 0;
1278 (ppd->ppd.par_intr)->intrspec_vec = 0;
1279 (ppd->ppd.par_intr)->intrspec_func = (uint_t (*)()) 0;
1280 #endif
1281
1282 if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
1283 "interrupts", -1) != -1)
1284 ppd->ppd.par_nintr = 1;
1285
1286 ppd->code = CB_PPD_CODE;
1287
1288 cardbus_err(child, 5,
1289 "cardbus_initchild: Creating empty ppd\n");
1290 ppd->ppd.par_nreg = 0;
1291 ppd->ppd.par_reg = NULL;
1292
1293 ddi_set_parent_data(child, (caddr_t)ppd);
1294 }
1295
1296 return (DDI_SUCCESS);
1297 }
1298
1299 static int
cardbus_name_child(dev_info_t * child,char * name,int namelen)1300 cardbus_name_child(dev_info_t *child, char *name, int namelen)
1301 {
1302 pci_regspec_t *pci_rp;
1303 char **unit_addr;
1304 uint_t n;
1305 int bus, device, func;
1306
1307 /*
1308 * Pseudo nodes indicate a prototype node with per-instance
1309 * properties to be merged into the real h/w device node.
1310 * The interpretation of the unit-address is DD[,F]
1311 * where DD is the device id and F is the function.
1312 */
1313 if (ndi_dev_is_persistent_node(child) == 0) {
1314 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
1315 DDI_PROP_DONTPASS,
1316 "unit-address", &unit_addr, &n) != DDI_PROP_SUCCESS) {
1317 cmn_err(CE_WARN, "cannot name node from %s.conf",
1318 ddi_driver_name(child));
1319 return (DDI_FAILURE);
1320 }
1321 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
1322 cmn_err(CE_WARN, "unit-address property in %s.conf"
1323 " not well-formed", ddi_driver_name(child));
1324 ddi_prop_free(unit_addr);
1325 return (DDI_FAILURE);
1326 }
1327 (void) snprintf(name, namelen, "%s", *unit_addr);
1328 ddi_prop_free(unit_addr);
1329 return (DDI_SUCCESS);
1330 }
1331
1332 /*
1333 * Get the address portion of the node name based on
1334 * the function and device number.
1335 */
1336 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1337 "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) {
1338 return (DDI_FAILURE);
1339 }
1340
1341 bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
1342 device = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1343 func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1344 ddi_prop_free(pci_rp);
1345
1346 if (func != 0)
1347 (void) snprintf(name, namelen, "%x,%x", device, func);
1348 else
1349 (void) snprintf(name, namelen, "%x", device);
1350
1351 cardbus_err(child, 8,
1352 "cardbus_name_child: system init done [%x][%x][%x]"
1353 " for %s [%s] nodeid: %x @%s\n",
1354 bus, device, func,
1355 ddi_get_name(child), ddi_get_name_addr(child),
1356 DEVI(child)->devi_nodeid, name);
1357
1358 return (DDI_SUCCESS);
1359 }
1360
1361 static void
cardbus_removechild(dev_info_t * dip)1362 cardbus_removechild(dev_info_t *dip)
1363 {
1364 struct cardbus_parent_private_data *ppd;
1365
1366 ddi_set_name_addr(dip, NULL);
1367 impl_rem_dev_props(dip);
1368 ppd = (struct cardbus_parent_private_data *)ddi_get_parent_data(dip);
1369 if (ppd && (ppd->code == CB_PPD_CODE)) {
1370 if (ppd->ppd.par_reg && (ppd->ppd.par_nreg > 0))
1371 kmem_free((caddr_t)ppd->ppd.par_reg,
1372 ppd->ppd.par_nreg * sizeof (struct regspec));
1373 #ifdef sparc
1374 kmem_free(ppd, sizeof (struct cardbus_parent_private_data));
1375 #elif defined(__x86)
1376 kmem_free(ppd, sizeof (struct cardbus_parent_private_data) +
1377 sizeof (struct intrspec));
1378 #endif
1379 cardbus_err(dip, 5,
1380 "cardbus_removechild: ddi_set_parent_data(NULL)\n");
1381 ddi_set_parent_data(dip, NULL);
1382 }
1383 }
1384
1385
1386 static char cb_bnamestr[] = "binding_name";
1387 static char cb_venidstr[] = "VendorID";
1388 static char cb_devidstr[] = "DeviceID";
1389 static char cb_nnamestr[] = "nodename";
1390
1391 static cb_props_parse_tree_t cb_props_parse_tree[] = {
1392 { cb_bnamestr, PT_STATE_STRING_VAR },
1393 { cb_venidstr, PT_STATE_HEX_VAR },
1394 { cb_devidstr, PT_STATE_HEX_VAR } };
1395
1396 static int
check_token(char * token,int * len)1397 check_token(char *token, int *len)
1398 {
1399 int state = PT_STATE_DEC_VAR;
1400 int sl = strlen(token), il = 1;
1401 char c;
1402
1403 if (token[0] == '0' && token[2] && (token[1] == 'x' || token[1] ==
1404 'X')) {
1405 state = PT_STATE_HEX_VAR;
1406 token += 2;
1407 }
1408
1409 while (c = *token++) {
1410 if (isdigit(c))
1411 continue;
1412 if (c == PARSE_COMMA) {
1413 il++;
1414 if (token[0] == '0' && token[2] && isx(token[1])) {
1415 state = PT_STATE_HEX_VAR;
1416 token += 2;
1417 }
1418 continue;
1419 }
1420 if (!isxdigit(c)) {
1421 *len = sl;
1422 return (PT_STATE_STRING_VAR);
1423 }
1424 state = PT_STATE_HEX_VAR;
1425 }
1426 *len = il;
1427 return (state);
1428 }
1429
1430
1431 static char *
find_token(char ** cp,int * l,char * endc)1432 find_token(char **cp, int *l, char *endc)
1433 {
1434 char *cpp = *cp;
1435
1436 while ((**cp && (isalpha(**cp) || isxdigit(**cp) ||
1437 (**cp == PARSE_UNDERSCORE) ||
1438 (**cp == PARSE_COMMA) ||
1439 (**cp == PARSE_DASH)))) {
1440 (*cp)++;
1441 (*l)++;
1442 }
1443
1444 *endc = **cp;
1445 **cp = '\0';
1446
1447 return (cpp);
1448 }
1449
1450 static int
parse_token(char * token)1451 parse_token(char *token)
1452 {
1453 cb_props_parse_tree_t *pt = cb_props_parse_tree;
1454 int k = sizeof (cb_props_parse_tree) /
1455 sizeof (cb_props_parse_tree_t);
1456
1457 while (k--) {
1458 if (strcmp((char *)token, pt->token) == 0)
1459 return (pt->state);
1460 pt++;
1461 }
1462
1463 return (PT_STATE_UNKNOWN);
1464 }
1465
1466 static int
token_to_hex(char * token,unsigned * val,int len)1467 token_to_hex(char *token, unsigned *val, int len)
1468 {
1469 uchar_t c;
1470
1471 *val = 0;
1472 if (token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) {
1473 token += 2;
1474 }
1475
1476 while (*token) {
1477 if (!isxdigit(*token)) {
1478 if (*token == PARSE_COMMA) {
1479 if (!(--len))
1480 return (1);
1481 val++;
1482 *val = 0;
1483 token++;
1484 if (token[0] == '0' && (token[1] == 'x' ||
1485 token[1] == 'X')) {
1486 token += 2;
1487 }
1488 continue;
1489 }
1490 return (0);
1491 }
1492 c = toupper(*token);
1493 if (c >= 'A')
1494 c = c - 'A' + 10 + '0';
1495 *val = ((*val * 16) + (c - '0'));
1496 token++;
1497 }
1498
1499 return (1);
1500 }
1501
1502 static int
token_to_dec(char * token,unsigned * val,int len)1503 token_to_dec(char *token, unsigned *val, int len)
1504 {
1505 *val = 0;
1506
1507 while (*token) {
1508 if (!isdigit(*token)) {
1509 if (*token == PARSE_COMMA) {
1510 if (!(--len))
1511 return (1);
1512 val++;
1513 *val = 0;
1514 token++;
1515 continue;
1516 }
1517 return (0);
1518 }
1519 *val = ((*val * 10) + (*token - '0'));
1520 token++;
1521 }
1522
1523 return (1);
1524 }
1525
1526 static void
cardbus_add_prop(struct cb_deviceset_props * cdsp,int type,char * name,caddr_t vp,int len)1527 cardbus_add_prop(struct cb_deviceset_props *cdsp, int type, char *name,
1528 caddr_t vp, int len)
1529 {
1530 ddi_prop_t *propp;
1531 int pnlen = strlen(name) + 1;
1532
1533 propp = (ddi_prop_t *)kmem_zalloc(sizeof (ddi_prop_t), KM_SLEEP);
1534 propp->prop_name = (char *)kmem_alloc(pnlen, KM_SLEEP);
1535 propp->prop_val = vp;
1536 bcopy(name, propp->prop_name, pnlen);
1537 propp->prop_len = len;
1538 propp->prop_flags = type;
1539 propp->prop_next = cdsp->prop_list;
1540 cdsp->prop_list = propp;
1541 }
1542
1543 static void
cardbus_add_stringprop(struct cb_deviceset_props * cdsp,char * name,char * vp,int len)1544 cardbus_add_stringprop(struct cb_deviceset_props *cdsp, char *name,
1545 char *vp, int len)
1546 {
1547 char *nstr = kmem_zalloc(len + 1, KM_SLEEP);
1548
1549 bcopy(vp, nstr, len);
1550 cardbus_add_prop(cdsp, DDI_PROP_TYPE_STRING, name, (caddr_t)nstr,
1551 len + 1);
1552 }
1553
1554 static void
cardbus_prop_free(ddi_prop_t * propp)1555 cardbus_prop_free(ddi_prop_t *propp)
1556 {
1557 if (propp->prop_len) {
1558 switch (propp->prop_flags) {
1559 case DDI_PROP_TYPE_STRING:
1560 kmem_free(propp->prop_val, propp->prop_len);
1561 break;
1562 case DDI_PROP_TYPE_INT:
1563 kmem_free(propp->prop_val,
1564 propp->prop_len * sizeof (int));
1565 break;
1566 }
1567 }
1568 kmem_free(propp->prop_name, strlen(propp->prop_name) + 1);
1569 kmem_free(propp, sizeof (ddi_prop_t *));
1570 }
1571
1572 static void
cardbus_devprops_free(struct cb_deviceset_props * cbdp)1573 cardbus_devprops_free(struct cb_deviceset_props *cbdp)
1574 {
1575 ddi_prop_t *propp, *npropp;
1576
1577 propp = cbdp->prop_list;
1578 while (propp) {
1579 npropp = propp->prop_next;
1580 cardbus_prop_free(propp);
1581 propp = npropp;
1582 }
1583 if (cbdp->nodename)
1584 kmem_free(cbdp->nodename, strlen(cbdp->nodename) + 1);
1585 if (cbdp->binding_name)
1586 kmem_free(cbdp->binding_name, strlen(cbdp->binding_name) +
1587 1);
1588 kmem_free(cbdp, sizeof (*cbdp));
1589 }
1590
1591 /*
1592 * Format of "cb-device-init-props" property:
1593 * Anything before the semi-colon is an identifying equate, anything
1594 * after the semi-colon is a setting equate.
1595 *
1596 * "binding_name=xXxXxX VendorID=NNNN DeviceID=NNNN; nodename=NewName
1597 * Prop=PropVal"
1598 *
1599 */
1600 static int
cardbus_parse_devprop(cbus_t * cbp,char * cp)1601 cardbus_parse_devprop(cbus_t *cbp, char *cp)
1602 {
1603 int state = PT_STATE_TOKEN, qm = 0, em = 0, smc = 0, l = 0;
1604 int length;
1605 char *token = "beginning of line";
1606 char *ptoken = NULL, *quote;
1607 char eq = '\0';
1608 struct cb_deviceset_props *cdsp;
1609
1610 cdsp = kmem_zalloc(sizeof (*cdsp), KM_SLEEP);
1611 length = strlen(cp);
1612
1613 while ((*cp) && (l < length)) {
1614 /*
1615 * Check for escaped characters
1616 */
1617 if (*cp == PARSE_ESCAPE) {
1618 char *cpp = cp, *cppp = cp + 1;
1619
1620 em = 1;
1621
1622 if (!qm) {
1623 cmn_err(CE_CONT, "cardbus_parse_devprop: "
1624 "escape not allowed outside "
1625 "of quotes at [%s]\n", token);
1626 cardbus_devprops_free(cdsp);
1627 return (DDI_FAILURE);
1628
1629 } /* if (!qm) */
1630
1631 while (*cppp)
1632 *cpp++ = *cppp++;
1633
1634 l++;
1635
1636 *cpp = '\0';
1637 } /* PARSE_ESCAPE */
1638
1639 /*
1640 * Check for quoted strings
1641 */
1642 if (!em && (*cp == PARSE_QUOTE)) {
1643 qm ^= 1;
1644 if (qm) {
1645 quote = cp + 1;
1646 } else {
1647 *cp = '\0';
1648 if (state == PT_STATE_CHECK) {
1649 if (strcmp(token, cb_nnamestr) == 0) {
1650 cdsp->nodename = kmem_alloc(
1651 strlen(quote) + 1,
1652 KM_SLEEP);
1653 (void) strcpy(cdsp->nodename,
1654 quote);
1655 } else
1656 cardbus_add_stringprop(cdsp,
1657 token, quote,
1658 strlen(quote));
1659 } else if (state != PT_STATE_STRING_VAR) {
1660 cmn_err(CE_CONT,
1661 "cardbus_parse_devprop: "
1662 "unexpected string [%s] after "
1663 "[%s]\n", quote, token);
1664 cardbus_devprops_free(cdsp);
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 *)(uintptr_t)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 *)(uintptr_t)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