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