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