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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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