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 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/conf.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/ddi_impldefs.h> 34 #include <sys/ddi_subrdefs.h> 35 #include <sys/pci.h> 36 #include <sys/pci/pci_nexus.h> 37 #include <sys/autoconf.h> 38 #include <sys/cmn_err.h> 39 #include <sys/errno.h> 40 #include <sys/kmem.h> 41 #include <sys/debug.h> 42 #include <sys/sysmacros.h> 43 #include <sys/acebus.h> 44 45 #ifdef DEBUG 46 static uint_t acebus_debug_flags = 0; 47 #endif 48 49 /* 50 * The values of the following variables are used to initialize 51 * the cache line size and latency timer registers in the ebus 52 * configuration header. Variables are used instead of constants 53 * to allow tuning from the /etc/system file. 54 */ 55 static uint8_t acebus_cache_line_size = 0x10; /* 64 bytes */ 56 static uint8_t acebus_latency_timer = 0x40; /* 64 PCI cycles */ 57 58 /* 59 * function prototypes for bus ops routines: 60 */ 61 static int 62 acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 63 off_t offset, off_t len, caddr_t *addrp); 64 static int 65 acebus_ctlops(dev_info_t *dip, dev_info_t *rdip, 66 ddi_ctl_enum_t op, void *arg, void *result); 67 static int 68 acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 69 ddi_intr_handle_impl_t *hdlp, void *result); 70 71 /* 72 * function prototypes for dev ops routines: 73 */ 74 static int acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 75 static int acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 76 77 /* 78 * general function prototypes: 79 */ 80 static int acebus_config(ebus_devstate_t *ebus_p); 81 static int acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip, 82 ebus_regspec_t *ebus_rp, pci_regspec_t *rp); 83 static int acebus_get_ranges_prop(ebus_devstate_t *ebus_p); 84 #ifdef ACEBUS_HOTPLUG 85 static int acebus_update_props(ebus_devstate_t *ebus_p); 86 static int acebus_set_imap(dev_info_t *dip); 87 #endif 88 89 #define getprop(dip, name, addr, intp) \ 90 ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \ 91 (name), (caddr_t)(addr), (intp)) 92 93 /* 94 * bus ops and dev ops structures: 95 */ 96 static struct bus_ops acebus_bus_ops = { 97 BUSO_REV, 98 acebus_map, 99 NULL, 100 NULL, 101 NULL, 102 i_ddi_map_fault, 103 ddi_dma_map, 104 ddi_dma_allochdl, 105 ddi_dma_freehdl, 106 ddi_dma_bindhdl, 107 ddi_dma_unbindhdl, 108 ddi_dma_flush, 109 ddi_dma_win, 110 ddi_dma_mctl, 111 acebus_ctlops, 112 ddi_bus_prop_op, 113 0, /* (*bus_get_eventcookie)(); */ 114 0, /* (*bus_add_eventcall)(); */ 115 0, /* (*bus_remove_eventcall)(); */ 116 0, /* (*bus_post_event)(); */ 117 0, /* (*bus_intr_ctl)(); */ 118 NULL, /* (*bus_config)(); */ 119 NULL, /* (*bus_unconfig)(); */ 120 NULL, /* (*bus_fm_init)(); */ 121 NULL, /* (*bus_fm_fini)(); */ 122 NULL, /* (*bus_fm_access_enter)(); */ 123 NULL, /* (*bus_fm_access_fini)(); */ 124 NULL, /* (*bus_power)(); */ 125 acebus_intr_ops /* (*bus_intr_op)(); */ 126 }; 127 128 static struct dev_ops acebus_ops = { 129 DEVO_REV, 130 0, 131 ddi_no_info, 132 nulldev, 133 nulldev, 134 acebus_attach, 135 acebus_detach, 136 nodev, 137 (struct cb_ops *)0, 138 &acebus_bus_ops 139 }; 140 141 /* 142 * module definitions: 143 */ 144 #include <sys/modctl.h> 145 extern struct mod_ops mod_driverops; 146 147 static struct modldrv modldrv = { 148 &mod_driverops, /* Type of module. This one is a driver */ 149 "Alarm Card ebus nexus v%I%", /* Name of module. */ 150 &acebus_ops, /* driver ops */ 151 }; 152 153 static struct modlinkage modlinkage = { 154 MODREV_1, (void *)&modldrv, NULL 155 }; 156 157 /* 158 * driver global data: 159 */ 160 static void *per_acebus_state; /* per-ebus soft state pointer */ 161 162 163 int 164 _init(void) 165 { 166 int e; 167 168 /* 169 * Initialize per-ebus soft state pointer. 170 */ 171 e = ddi_soft_state_init(&per_acebus_state, sizeof (ebus_devstate_t), 1); 172 if (e != 0) 173 return (e); 174 175 /* 176 * Install the module. 177 */ 178 e = mod_install(&modlinkage); 179 if (e != 0) 180 ddi_soft_state_fini(&per_acebus_state); 181 return (e); 182 } 183 184 int 185 _fini(void) 186 { 187 int e; 188 189 /* 190 * Remove the module. 191 */ 192 e = mod_remove(&modlinkage); 193 if (e != 0) 194 return (e); 195 196 /* 197 * Free the soft state info. 198 */ 199 ddi_soft_state_fini(&per_acebus_state); 200 return (e); 201 } 202 203 int 204 _info(struct modinfo *modinfop) 205 { 206 return (mod_info(&modlinkage, modinfop)); 207 } 208 209 /* device driver entry points */ 210 211 /* 212 * attach entry point: 213 * 214 * normal attach: 215 * 216 * create soft state structure (dip, reg, nreg and state fields) 217 * map in configuration header 218 * make sure device is properly configured 219 * report device 220 */ 221 static int 222 acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 223 { 224 ebus_devstate_t *ebus_p; /* per ebus state pointer */ 225 int instance; 226 227 DBG1(D_ATTACH, NULL, "dip=%x\n", dip); 228 switch (cmd) { 229 case DDI_ATTACH: 230 231 /* 232 * Allocate soft state for this instance. 233 */ 234 instance = ddi_get_instance(dip); 235 if (ddi_soft_state_zalloc(per_acebus_state, instance) 236 != DDI_SUCCESS) { 237 DBG(D_ATTACH, NULL, "failed to alloc soft state\n"); 238 return (DDI_FAILURE); 239 } 240 ebus_p = get_acebus_soft_state(instance); 241 ebus_p->dip = dip; 242 243 /* 244 * Make sure the master enable and memory access enable 245 * bits are set in the config command register. 246 */ 247 if (!acebus_config(ebus_p)) { 248 free_acebus_soft_state(instance); 249 return (DDI_FAILURE); 250 } 251 252 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, 253 DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0); 254 /* Get our ranges property for mapping child registers. */ 255 if (acebus_get_ranges_prop(ebus_p) != DDI_SUCCESS) { 256 free_acebus_soft_state(instance); 257 return (DDI_FAILURE); 258 } 259 260 /* 261 * Make the state as attached and report the device. 262 */ 263 ebus_p->state = ATTACHED; 264 ddi_report_dev(dip); 265 DBG(D_ATTACH, ebus_p, "returning\n"); 266 return (DDI_SUCCESS); 267 268 case DDI_RESUME: 269 270 instance = ddi_get_instance(dip); 271 ebus_p = get_acebus_soft_state(instance); 272 273 /* 274 * Make sure the master enable and memory access enable 275 * bits are set in the config command register. 276 */ 277 if (!acebus_config(ebus_p)) { 278 free_acebus_soft_state(instance); 279 return (DDI_FAILURE); 280 } 281 282 ebus_p->state = RESUMED; 283 return (DDI_SUCCESS); 284 } 285 return (DDI_FAILURE); 286 } 287 288 /* 289 * detach entry point: 290 */ 291 static int 292 acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 293 { 294 int instance = ddi_get_instance(dip); 295 ebus_devstate_t *ebus_p = get_acebus_soft_state(instance); 296 297 switch (cmd) { 298 case DDI_DETACH: 299 DBG1(D_DETACH, ebus_p, "DDI_DETACH dip=%p\n", dip); 300 ddi_prop_remove_all(dip); 301 kmem_free(ebus_p->rangep, ebus_p->range_cnt * 302 sizeof (struct ebus_pci_rangespec)); 303 free_acebus_soft_state(instance); 304 return (DDI_SUCCESS); 305 306 case DDI_SUSPEND: 307 DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip); 308 ebus_p->state = SUSPENDED; 309 return (DDI_SUCCESS); 310 } 311 return (DDI_FAILURE); 312 } 313 314 315 static int 316 acebus_get_ranges_prop(ebus_devstate_t *ebus_p) 317 { 318 struct ebus_pci_rangespec *rangep; 319 int nrange, range_len; 320 321 if (ddi_getlongprop(DDI_DEV_T_ANY, ebus_p->dip, DDI_PROP_DONTPASS, 322 "ranges", (caddr_t)&rangep, &range_len) != DDI_SUCCESS) { 323 324 cmn_err(CE_WARN, "%s%d: can't get ranges property", 325 ddi_get_name(ebus_p->dip), ddi_get_instance(ebus_p->dip)); 326 return (DDI_ME_REGSPEC_RANGE); 327 } 328 329 nrange = range_len / sizeof (struct ebus_pci_rangespec); 330 331 if (nrange == 0) { 332 kmem_free(rangep, range_len); 333 return (DDI_FAILURE); 334 } 335 336 #ifdef DEBUG 337 /* */ { 338 int i; 339 340 for (i = 0; i < nrange; i++) { 341 DBG5(D_MAP, ebus_p, "ebus range addr 0x%x.0x%x PCI range " 342 "addr 0x%x.0x%x.0x%x ", rangep[i].ebus_phys_hi, 343 rangep[i].ebus_phys_low, rangep[i].pci_phys_hi, 344 rangep[i].pci_phys_mid, rangep[i].pci_phys_low); 345 DBG1(D_MAP, ebus_p, "Size 0x%x\n", rangep[i].rng_size); 346 } 347 } 348 #endif /* DEBUG */ 349 350 ebus_p->rangep = rangep; 351 ebus_p->range_cnt = nrange; 352 353 return (DDI_SUCCESS); 354 } 355 356 357 /* bus driver entry points */ 358 359 /* 360 * bus map entry point: 361 * 362 * if map request is for an rnumber 363 * get the corresponding regspec from device node 364 * build a new regspec in our parent's format 365 * build a new map_req with the new regspec 366 * call up the tree to complete the mapping 367 */ 368 static int 369 acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 370 off_t off, off_t len, caddr_t *addrp) 371 { 372 ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip)); 373 ebus_regspec_t *ebus_rp, *ebus_regs; 374 pci_regspec_t pci_reg; 375 ddi_map_req_t p_map_request; 376 int rnumber, i, n; 377 int rval = DDI_SUCCESS; 378 379 /* 380 * Handle the mapping according to its type. 381 */ 382 DBG4(D_MAP, ebus_p, "rdip=%s%d: off=%x len=%x\n", 383 ddi_get_name(rdip), ddi_get_instance(rdip), off, len); 384 switch (mp->map_type) { 385 case DDI_MT_REGSPEC: 386 387 /* 388 * We assume the register specification is in ebus format. 389 * We must convert it into a PCI format regspec and pass 390 * the request to our parent. 391 */ 392 DBG3(D_MAP, ebus_p, "rdip=%s%d: REGSPEC - handlep=%x\n", 393 ddi_get_name(rdip), ddi_get_instance(rdip), 394 mp->map_handlep); 395 ebus_rp = (ebus_regspec_t *)mp->map_obj.rp; 396 break; 397 398 case DDI_MT_RNUMBER: 399 400 /* 401 * Get the "reg" property from the device node and convert 402 * it to our parent's format. 403 */ 404 rnumber = mp->map_obj.rnumber; 405 DBG4(D_MAP, ebus_p, "rdip=%s%d: rnumber=%x handlep=%x\n", 406 ddi_get_name(rdip), ddi_get_instance(rdip), 407 rnumber, mp->map_handlep); 408 409 if (getprop(rdip, "reg", &ebus_regs, &i) != DDI_SUCCESS) { 410 DBG(D_MAP, ebus_p, "can't get reg property\n"); 411 return (DDI_ME_RNUMBER_RANGE); 412 } 413 n = i / sizeof (ebus_regspec_t); 414 415 if (rnumber < 0 || rnumber >= n) { 416 DBG(D_MAP, ebus_p, "rnumber out of range\n"); 417 return (DDI_ME_RNUMBER_RANGE); 418 } 419 ebus_rp = &ebus_regs[rnumber]; 420 break; 421 422 default: 423 return (DDI_ME_INVAL); 424 425 } 426 427 /* Adjust our reg property with offset and length */ 428 ebus_rp->addr_low += off; 429 if (len) 430 ebus_rp->size = len; 431 432 /* 433 * Now we have a copy the "reg" entry we're attempting to map. 434 * Translate this into our parents PCI address using the ranges 435 * property. 436 */ 437 rval = acebus_apply_range(ebus_p, rdip, ebus_rp, &pci_reg); 438 439 if (mp->map_type == DDI_MT_RNUMBER) 440 kmem_free((caddr_t)ebus_regs, i); 441 442 if (rval != DDI_SUCCESS) 443 return (rval); 444 445 #ifdef ACEBUS_HOTPLUG 446 /* 447 * The map operation provides a translated (not a re-assigned, or 448 * relocated) ebus address for the child in its address space(range). 449 * Ebus address space is relocatible but its child address space 450 * is not. As specified by their 'reg' properties, they reside 451 * at a fixed offset in their parent's (ebus's) space. 452 * 453 * By setting this bit, we will not run into HostPCI nexus 454 * trying to relocate a translated ebus address (which is already 455 * relocated) and failing the operation. 456 * The reason for doing this here is that the PCI hotplug configurator 457 * always marks the ebus space as relocatible (unlike OBP) and that 458 * information is implied for the child too, which is wrong. 459 */ 460 pci_reg.pci_phys_hi |= PCI_RELOCAT_B; 461 #endif 462 #ifdef DEBUG 463 DBG5(D_MAP, ebus_p, "(%x,%x,%x)(%x,%x)\n", 464 pci_reg.pci_phys_hi, 465 pci_reg.pci_phys_mid, 466 pci_reg.pci_phys_low, 467 pci_reg.pci_size_hi, 468 pci_reg.pci_size_low); 469 #endif 470 471 p_map_request = *mp; 472 p_map_request.map_type = DDI_MT_REGSPEC; 473 p_map_request.map_obj.rp = (struct regspec *)&pci_reg; 474 rval = ddi_map(dip, &p_map_request, 0, 0, addrp); 475 DBG1(D_MAP, ebus_p, "parent returned %x\n", rval); 476 return (rval); 477 } 478 479 480 static int 481 acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip, 482 ebus_regspec_t *ebus_rp, pci_regspec_t *rp) 483 { 484 int b; 485 int rval = DDI_SUCCESS; 486 struct ebus_pci_rangespec *rangep = ebus_p->rangep; 487 int nrange = ebus_p->range_cnt; 488 static const char out_of_range[] = 489 "Out of range register specification from device node <%s>"; 490 491 DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n", 492 ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size); 493 494 for (b = 0; b < nrange; ++b, ++rangep) { 495 496 /* Check for the correct space */ 497 if (ebus_rp->addr_hi == rangep->ebus_phys_hi) 498 /* See if we fit in this range */ 499 if ((ebus_rp->addr_low >= 500 rangep->ebus_phys_low) && 501 ((ebus_rp->addr_low + ebus_rp->size - 1) 502 <= (rangep->ebus_phys_low + 503 rangep->rng_size - 1))) { 504 uint_t addr_offset = ebus_rp->addr_low - 505 rangep->ebus_phys_low; 506 /* 507 * Use the range entry to translate 508 * the EBUS physical address into the 509 * parents PCI space. 510 */ 511 rp->pci_phys_hi = 512 rangep->pci_phys_hi; 513 rp->pci_phys_mid = rangep->pci_phys_mid; 514 rp->pci_phys_low = 515 rangep->pci_phys_low + addr_offset; 516 rp->pci_size_hi = 0; 517 rp->pci_size_low = 518 min(ebus_rp->size, (rangep->rng_size - 519 addr_offset)); 520 521 DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ", 522 rangep->ebus_phys_hi, 523 rangep->ebus_phys_low); 524 DBG4(D_MAP, ebus_p, "Parent hi0x%x " 525 "mid0x%x lo0x%x size 0x%x\n", 526 rangep->pci_phys_hi, 527 rangep->pci_phys_mid, 528 rangep->pci_phys_low, 529 rangep->rng_size); 530 531 break; 532 } 533 } 534 535 if (b == nrange) { 536 cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip)); 537 return (DDI_ME_REGSPEC_RANGE); 538 } 539 540 return (rval); 541 } 542 543 544 /* 545 * control ops entry point: 546 * 547 * Requests handled completely: 548 * DDI_CTLOPS_INITCHILD 549 * DDI_CTLOPS_UNINITCHILD 550 * DDI_CTLOPS_REPORTDEV 551 * DDI_CTLOPS_REGSIZE 552 * DDI_CTLOPS_NREGS 553 * 554 * All others passed to parent. 555 */ 556 static int 557 acebus_ctlops(dev_info_t *dip, dev_info_t *rdip, 558 ddi_ctl_enum_t op, void *arg, void *result) 559 { 560 #ifdef DEBUG 561 ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip)); 562 #endif 563 ebus_regspec_t *ebus_rp; 564 int32_t reglen; 565 int i, n; 566 char name[10]; 567 568 switch (op) { 569 case DDI_CTLOPS_INITCHILD: { 570 dev_info_t *child = (dev_info_t *)arg; 571 /* 572 * Set the address portion of the node name based on the 573 * address/offset. 574 */ 575 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n", 576 ddi_get_name(child), ddi_get_instance(child)); 577 578 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 579 "reg", (caddr_t)&ebus_rp, ®len) != DDI_SUCCESS) { 580 581 DBG(D_CTLOPS, ebus_p, "can't get reg property\n"); 582 return (DDI_FAILURE); 583 584 } 585 586 (void) sprintf(name, "%x,%x", ebus_rp->addr_hi, 587 ebus_rp->addr_low); 588 ddi_set_name_addr(child, name); 589 kmem_free((caddr_t)ebus_rp, reglen); 590 591 ddi_set_parent_data(child, NULL); 592 593 return (DDI_SUCCESS); 594 595 } 596 597 case DDI_CTLOPS_UNINITCHILD: 598 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n", 599 ddi_get_name((dev_info_t *)arg), 600 ddi_get_instance((dev_info_t *)arg)); 601 ddi_set_name_addr((dev_info_t *)arg, NULL); 602 ddi_remove_minor_node((dev_info_t *)arg, NULL); 603 impl_rem_dev_props((dev_info_t *)arg); 604 return (DDI_SUCCESS); 605 606 case DDI_CTLOPS_REPORTDEV: 607 608 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n", 609 ddi_get_name(rdip), ddi_get_instance(rdip)); 610 cmn_err(CE_CONT, "?%s%d at %s%d: offset %s\n", 611 ddi_driver_name(rdip), ddi_get_instance(rdip), 612 ddi_driver_name(dip), ddi_get_instance(dip), 613 ddi_get_name_addr(rdip)); 614 return (DDI_SUCCESS); 615 616 case DDI_CTLOPS_REGSIZE: 617 618 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n", 619 ddi_get_name(rdip), ddi_get_instance(rdip)); 620 if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) { 621 DBG(D_CTLOPS, ebus_p, "can't get reg property\n"); 622 return (DDI_FAILURE); 623 } 624 n = i / sizeof (ebus_regspec_t); 625 if (*(int *)arg < 0 || *(int *)arg >= n) { 626 DBG(D_MAP, ebus_p, "rnumber out of range\n"); 627 kmem_free((caddr_t)ebus_rp, i); 628 return (DDI_FAILURE); 629 } 630 *((off_t *)result) = ebus_rp[*(int *)arg].size; 631 kmem_free((caddr_t)ebus_rp, i); 632 return (DDI_SUCCESS); 633 634 case DDI_CTLOPS_NREGS: 635 636 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_NREGS: rdip=%s%d\n", 637 ddi_get_name(rdip), ddi_get_instance(rdip)); 638 if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) { 639 DBG(D_CTLOPS, ebus_p, "can't get reg property\n"); 640 return (DDI_FAILURE); 641 } 642 *((uint_t *)result) = i / sizeof (ebus_regspec_t); 643 kmem_free((caddr_t)ebus_rp, i); 644 return (DDI_SUCCESS); 645 } 646 647 /* 648 * Now pass the request up to our parent. 649 */ 650 DBG2(D_CTLOPS, ebus_p, "passing request to parent: rdip=%s%d\n", 651 ddi_get_name(rdip), ddi_get_instance(rdip)); 652 return (ddi_ctlops(dip, rdip, op, arg, result)); 653 } 654 655 struct ebus_string_to_pil { 656 int8_t *string; 657 uint32_t pil; 658 }; 659 660 static struct ebus_string_to_pil acebus_name_to_pil[] = {{"SUNW,CS4231", 9}, 661 {"fdthree", 8}, 662 {"ecpp", 3}, 663 {"su", 12}, 664 {"se", 12}, 665 {"power", 14}}; 666 667 static struct ebus_string_to_pil acebus_device_type_to_pil[] = {{"serial", 12}, 668 {"block", 8}}; 669 670 static int 671 acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 672 ddi_intr_handle_impl_t *hdlp, void *result) 673 { 674 #ifdef DEBUG 675 ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip)); 676 #endif 677 int8_t *name, *device_type; 678 int32_t i, max_children, max_device_types, len; 679 680 /* 681 * NOTE: These ops below will never be supported in this nexus 682 * driver, hence they always return immediately. 683 */ 684 switch (intr_op) { 685 case DDI_INTROP_GETCAP: 686 *(int *)result = DDI_INTR_FLAG_LEVEL; 687 return (DDI_SUCCESS); 688 case DDI_INTROP_SETCAP: 689 case DDI_INTROP_SETMASK: 690 case DDI_INTROP_CLRMASK: 691 case DDI_INTROP_GETPENDING: 692 return (DDI_ENOTSUP); 693 default: 694 break; 695 } 696 697 if ((intr_op == DDI_INTROP_SUPPORTED_TYPES) || hdlp->ih_pri) 698 goto done; 699 700 /* 701 * This is a hack to set the PIL for the devices under ebus. 702 * We first look up a device by it's specific name, if we can't 703 * match the name, we try and match it's device_type property. 704 * Lastly we default a PIL level of 1. 705 */ 706 DBG1(D_INTR, ebus_p, "ebus_p %p\n", ebus_p); 707 708 name = ddi_get_name(rdip); 709 max_children = sizeof (acebus_name_to_pil) / 710 sizeof (struct ebus_string_to_pil); 711 712 for (i = 0; i < max_children; i++) { 713 if (strcmp(acebus_name_to_pil[i].string, name) == 0) { 714 DBG2(D_INTR, ebus_p, "child name %s; match PIL %d\n", 715 acebus_name_to_pil[i].string, 716 acebus_name_to_pil[i].pil); 717 718 hdlp->ih_pri = acebus_name_to_pil[i].pil; 719 goto done; 720 } 721 } 722 723 if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, 724 "device_type", (caddr_t)&device_type, &len) == DDI_SUCCESS) { 725 726 max_device_types = sizeof (acebus_device_type_to_pil) / 727 sizeof (struct ebus_string_to_pil); 728 729 for (i = 0; i < max_device_types; i++) { 730 if (strcmp(acebus_device_type_to_pil[i].string, 731 device_type) == 0) { 732 DBG2(D_INTR, ebus_p, 733 "Device type %s; match PIL %d\n", 734 acebus_device_type_to_pil[i].string, 735 acebus_device_type_to_pil[i].pil); 736 737 hdlp->ih_pri = acebus_device_type_to_pil[i].pil; 738 break; 739 } 740 } 741 742 kmem_free(device_type, len); 743 } 744 745 /* 746 * If we get here, we need to set a default value 747 * for the PIL. 748 */ 749 if (hdlp->ih_pri == 0) { 750 hdlp->ih_pri = 1; 751 cmn_err(CE_WARN, "%s%d assigning default interrupt level %d " 752 "for device %s%d", ddi_driver_name(dip), 753 ddi_get_instance(dip), hdlp->ih_pri, ddi_driver_name(rdip), 754 ddi_get_instance(rdip)); 755 } 756 757 done: 758 /* Pass up the request to our parent. */ 759 return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result)); 760 } 761 762 763 static int 764 acebus_config(ebus_devstate_t *ebus_p) 765 { 766 ddi_acc_handle_t conf_handle; 767 uint16_t comm; 768 #ifdef ACEBUS_HOTPLUG 769 int tcr_reg; 770 caddr_t csr_io; 771 ddi_device_acc_attr_t csr_attr = { /* CSR map attributes */ 772 DDI_DEVICE_ATTR_V0, 773 DDI_STRUCTURE_LE_ACC, 774 DDI_STRICTORDER_ACC 775 }; 776 ddi_acc_handle_t csr_handle; 777 #endif 778 779 /* 780 * Make sure the master enable and memory access enable 781 * bits are set in the config command register. 782 */ 783 if (pci_config_setup(ebus_p->dip, &conf_handle) != DDI_SUCCESS) 784 return (0); 785 786 comm = pci_config_get16(conf_handle, PCI_CONF_COMM), 787 #ifdef DEBUG 788 DBG1(D_ATTACH, ebus_p, "command register was 0x%x\n", comm); 789 #endif 790 comm |= (PCI_COMM_ME|PCI_COMM_MAE|PCI_COMM_SERR_ENABLE| 791 PCI_COMM_PARITY_DETECT); 792 pci_config_put16(conf_handle, PCI_CONF_COMM, comm), 793 #ifdef DEBUG 794 DBG1(D_MAP, ebus_p, "command register is now 0x%x\n", 795 pci_config_get16(conf_handle, PCI_CONF_COMM)); 796 #endif 797 pci_config_put8(conf_handle, PCI_CONF_CACHE_LINESZ, 798 (uchar_t)acebus_cache_line_size); 799 pci_config_put8(conf_handle, PCI_CONF_LATENCY_TIMER, 800 (uchar_t)acebus_latency_timer); 801 pci_config_teardown(&conf_handle); 802 803 #ifdef ACEBUS_HOTPLUG 804 if (acebus_update_props(ebus_p) != DDI_SUCCESS) { 805 cmn_err(CE_WARN, "%s%d: Could not update special properties.", 806 ddi_driver_name(ebus_p->dip), 807 ddi_get_instance(ebus_p->dip)); 808 return (0); 809 } 810 811 if (ddi_regs_map_setup(ebus_p->dip, CSR_IO_RINDEX, 812 (caddr_t *)&csr_io, 0, CSR_SIZE, &csr_attr, 813 &csr_handle) != DDI_SUCCESS) { 814 cmn_err(CE_WARN, "%s%d: Could not map Ebus CSR.", 815 ddi_driver_name(ebus_p->dip), 816 ddi_get_instance(ebus_p->dip)); 817 } 818 #ifdef DEBUG 819 if (acebus_debug_flags) { 820 DBG3(D_ATTACH, ebus_p, "tcr[123] = %x,%x,%x\n", 821 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 822 TCR1_OFF)), 823 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 824 TCR2_OFF)), 825 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 826 TCR3_OFF))); 827 DBG2(D_ATTACH, ebus_p, "pmd-aux=%x, freq-aux=%x\n", 828 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 829 PMD_AUX_OFF)), 830 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 831 FREQ_AUX_OFF))); 832 #ifdef ACEBUS_DEBUG 833 for (comm = 0; comm < 4; comm++) 834 prom_printf("dcsr%d=%x, dacr%d=%x, dbcr%d=%x\n", comm, 835 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 836 0x700000+(0x2000*comm))), comm, 837 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 838 0x700000+(0x2000*comm)+4)), comm, 839 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 840 0x700000+(0x2000*comm)+8))); 841 #endif 842 } /* acebus_debug_flags */ 843 #endif 844 /* If TCR registers are not initialized, initialize them here */ 845 tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 846 TCR1_OFF)); 847 if ((tcr_reg == 0) || (tcr_reg == -1)) 848 ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF), 849 TCR1_REGVAL); 850 tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 851 TCR2_OFF)); 852 if ((tcr_reg == 0) || (tcr_reg == -1)) 853 ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF), 854 TCR2_REGVAL); 855 tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 856 TCR3_OFF)); 857 if ((tcr_reg == 0) || (tcr_reg == -1)) 858 ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF), 859 TCR3_REGVAL); 860 #ifdef DEBUG 861 if (acebus_debug_flags) { 862 DBG3(D_ATTACH, ebus_p, "wrote tcr[123] = %x,%x,%x\n", 863 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 864 TCR1_OFF)), 865 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 866 TCR2_OFF)), 867 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 868 TCR3_OFF))); 869 } 870 #endif 871 872 ddi_regs_map_free(&csr_handle); 873 #endif /* ACEBUS_HOTPLUG */ 874 return (1); /* return success */ 875 } 876 877 #ifdef DEBUG 878 extern void prom_printf(const char *, ...); 879 880 static void 881 acebus_debug(uint_t flag, ebus_devstate_t *ebus_p, char *fmt, 882 uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5) 883 { 884 char *s; 885 886 if (acebus_debug_flags & flag) { 887 switch (flag) { 888 case D_ATTACH: 889 s = "attach"; break; 890 case D_DETACH: 891 s = "detach"; break; 892 case D_MAP: 893 s = "map"; break; 894 case D_CTLOPS: 895 s = "ctlops"; break; 896 case D_INTR: 897 s = "intr"; break; 898 } 899 if (ebus_p) 900 cmn_err(CE_CONT, "%s%d: %s: ", 901 ddi_get_name(ebus_p->dip), 902 ddi_get_instance(ebus_p->dip), s); 903 else 904 cmn_err(CE_CONT, "ebus: "); 905 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5); 906 } 907 } 908 #endif 909 910 #ifdef ACEBUS_HOTPLUG 911 #define EBUS_CHILD_PHYS_LOW_RANGE 0x10 912 #define EBUS_CHILD_PHYS_HI_RANGE 0x14 913 914 static int 915 acebus_update_props(ebus_devstate_t *ebus_p) 916 { 917 dev_info_t *dip = ebus_p->dip; 918 struct ebus_pci_rangespec er[2], *erp; 919 pci_regspec_t *pci_rp, *prp; 920 int length, rnums, imask[3], i, found = 0; 921 922 /* 923 * If "ranges" property is found, then the device is initialized 924 * by OBP, hence simply return. 925 * Otherwise we create all the properties here. 926 */ 927 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 928 "ranges", (int **)&erp, (uint_t *)&length) == DDI_PROP_SUCCESS) { 929 ddi_prop_free(erp); 930 return (DDI_SUCCESS); 931 } 932 933 /* 934 * interrupt-map is the only property that comes from a .conf file. 935 * Since it doesn't have the nodeid field set, it must be done here. 936 * Other properties can come from OBP or created here. 937 */ 938 if (acebus_set_imap(dip) != DDI_SUCCESS) { 939 return (DDI_FAILURE); 940 } 941 942 /* 943 * Create the "ranges" property. 944 * Ebus has BAR0 and BAR1 allocated (both in memory space). 945 * Other BARs are 0. 946 * Hence there are 2 memory ranges it operates in. (one for each BAR). 947 * ie. there are 2 entries in its ranges property. 948 */ 949 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 950 DDI_PROP_DONTPASS, "assigned-addresses", 951 (int **)&pci_rp, (uint_t *)&length) 952 != DDI_PROP_SUCCESS) { 953 cmn_err(CE_WARN, "%s%d: Could not get assigned-addresses", 954 ddi_driver_name(dip), ddi_get_instance(dip)); 955 return (DDI_FAILURE); 956 } 957 /* 958 * Create the 1st mem range in which it operates corresponding 959 * to BAR0 960 */ 961 er[0].ebus_phys_hi = EBUS_CHILD_PHYS_LOW_RANGE; 962 rnums = (length * sizeof (int))/sizeof (pci_regspec_t); 963 for (i = 0; i < rnums; i++) { 964 prp = pci_rp + i; 965 if (PCI_REG_REG_G(prp->pci_phys_hi) == er[0].ebus_phys_hi) { 966 found = 1; 967 break; 968 } 969 } 970 if (!found) { 971 cmn_err(CE_WARN, "No assigned space for memory range 0."); 972 ddi_prop_free(pci_rp); 973 return (DDI_FAILURE); 974 } 975 found = 0; 976 er[0].ebus_phys_low = 0; 977 er[0].pci_phys_hi = prp->pci_phys_hi; 978 er[0].pci_phys_mid = prp->pci_phys_mid; 979 er[0].pci_phys_low = prp->pci_phys_low; 980 er[0].rng_size = prp->pci_size_low; 981 982 /* 983 * Create the 2nd mem range in which it operates corresponding 984 * to BAR1 985 */ 986 er[1].ebus_phys_hi = EBUS_CHILD_PHYS_HI_RANGE; 987 for (i = 0; i < rnums; i++) { 988 prp = pci_rp + i; 989 if (PCI_REG_REG_G(prp->pci_phys_hi) == er[1].ebus_phys_hi) { 990 found = 1; 991 break; 992 } 993 } 994 if (!found) { 995 cmn_err(CE_WARN, "No assigned space for memory range 1."); 996 ddi_prop_free(pci_rp); 997 return (DDI_FAILURE); 998 } 999 er[1].ebus_phys_low = 0; 1000 er[1].pci_phys_hi = prp->pci_phys_hi; 1001 er[1].pci_phys_mid = prp->pci_phys_mid; 1002 er[1].pci_phys_low = prp->pci_phys_low; 1003 er[1].rng_size = prp->pci_size_low; 1004 1005 ddi_prop_free(pci_rp); 1006 length = sizeof (er) / sizeof (int); 1007 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 1008 "ranges", (int *)er, length) != DDI_PROP_SUCCESS) { 1009 cmn_err(CE_WARN, "%s%d: Could not create ranges property", 1010 ddi_driver_name(dip), ddi_get_instance(dip)); 1011 return (DDI_FAILURE); 1012 } 1013 /* The following properties are as defined by PCI 1275 bindings. */ 1014 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, 1015 "#address-cells", 2) != DDI_PROP_SUCCESS) 1016 return (DDI_FAILURE); 1017 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, 1018 "#size-cells", 1) != DDI_PROP_SUCCESS) 1019 return (DDI_FAILURE); 1020 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, 1021 "#interrupt-cells", 1) != DDI_PROP_SUCCESS) 1022 return (DDI_FAILURE); 1023 1024 imask[0] = 0x1f; 1025 imask[1] = 0x00ffffff; 1026 imask[2] = 0x00000003; 1027 length = sizeof (imask) / sizeof (int); 1028 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 1029 "interrupt-map-mask", (int *)imask, length) != DDI_PROP_SUCCESS) { 1030 cmn_err(CE_WARN, "%s%d: Could not update imap mask property", 1031 ddi_driver_name(dip), ddi_get_instance(dip)); 1032 return (DDI_FAILURE); 1033 } 1034 1035 return (DDI_SUCCESS); 1036 } 1037 1038 /* 1039 * This function takes in the ac-interrupt-map property from the .conf file, 1040 * fills in the 'nodeid' information and then creates the 'interrupt-map' 1041 * property. 1042 */ 1043 static int 1044 acebus_set_imap(dev_info_t *dip) 1045 { 1046 int *imapp, *timapp, length, num, i, default_ival = 0; 1047 dev_info_t *tdip = dip; 1048 int *port_id, imap_ok = 1; 1049 int ilength; 1050 int acebus_default_se_imap[5]; 1051 1052 /* 1053 * interrupt-map is specified via .conf file in hotplug mode, 1054 * since the child configuration is static. 1055 * It could even be hardcoded in the driver. 1056 */ 1057 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1058 "ac-interrupt-map", (int **)&imapp, (uint_t *)&ilength) != 1059 DDI_PROP_SUCCESS) { 1060 /* assume default implementation */ 1061 acebus_default_se_imap[0] = 0x14; 1062 acebus_default_se_imap[1] = 0x400000; 1063 acebus_default_se_imap[2] = 1; 1064 acebus_default_se_imap[3] = 0; 1065 acebus_default_se_imap[4] = 2; 1066 imapp = acebus_default_se_imap; 1067 ilength = 5; 1068 default_ival = 1; 1069 } 1070 num = ilength / 5; /* there are 5 integer cells in our property */ 1071 timapp = imapp; 1072 for (i = 0; i < num; i++) { 1073 if (*(timapp+i*5+3) == 0) 1074 imap_ok = 0; 1075 } 1076 if (imap_ok) { 1077 if (!default_ival) 1078 ddi_prop_free(imapp); 1079 return (DDI_SUCCESS); 1080 } 1081 1082 while (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, tdip, 1083 DDI_PROP_DONTPASS, "upa-portid", (int **)&port_id, 1084 (uint_t *)&length) != DDI_PROP_SUCCESS) { 1085 tdip = ddi_get_parent(tdip); 1086 if (tdip == NULL) { 1087 cmn_err(CE_WARN, "%s%d: Could not get imap parent", 1088 ddi_driver_name(dip), ddi_get_instance(dip)); 1089 if (!default_ival) 1090 ddi_prop_free(imapp); 1091 return (DDI_FAILURE); 1092 } 1093 } 1094 timapp = imapp; 1095 for (i = 0; i < num; i++) { 1096 *(timapp+i*5+3) = ddi_get_nodeid(tdip); 1097 } 1098 1099 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 1100 "interrupt-map", imapp, ilength) != DDI_PROP_SUCCESS) { 1101 cmn_err(CE_WARN, "%s%d: Could not update AC imap property", 1102 ddi_driver_name(dip), ddi_get_instance(dip)); 1103 if (!default_ival) 1104 ddi_prop_free(imapp); 1105 return (DDI_FAILURE); 1106 } 1107 if (!default_ival) 1108 ddi_prop_free(imapp); 1109 return (DDI_SUCCESS); 1110 } 1111 #endif /* ACEBUS_HOTPLUG */ 1112