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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 /*
  25  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
  26  */
  27 
  28 /*
  29  * Common x86 and SPARC PCI-E to PCI bus bridge nexus driver
  30  */
  31 
  32 #include <sys/sysmacros.h>
  33 #include <sys/conf.h>
  34 #include <sys/kmem.h>
  35 #include <sys/debug.h>
  36 #include <sys/modctl.h>
  37 #include <sys/autoconf.h>
  38 #include <sys/ddi_impldefs.h>
  39 #include <sys/pci.h>
  40 #include <sys/ddi.h>
  41 #include <sys/sunddi.h>
  42 #include <sys/sunndi.h>
  43 #include <sys/fm/util.h>
  44 #include <sys/pci_cap.h>
  45 #include <sys/pci_impl.h>
  46 #include <sys/pcie_impl.h>
  47 #include <sys/open.h>
  48 #include <sys/stat.h>
  49 #include <sys/file.h>
  50 #include <sys/promif.h>           /* prom_printf */
  51 #include <sys/disp.h>
  52 #include <sys/pcie_pwr.h>
  53 #include <sys/hotplug/pci/pcie_hp.h>
  54 #include "pcieb.h"
  55 #ifdef PX_PLX
  56 #include <io/pciex/pcieb_plx.h>
  57 #endif /* PX_PLX */
  58 
  59 /*LINTLIBRARY*/
  60 
  61 /* panic flag */
  62 int pcieb_die = PF_ERR_FATAL_FLAGS;
  63 int pcieb_disable_41210_wkarnd = 0;
  64 
  65 /* flag to turn on MSI support */
  66 int pcieb_enable_msi = 1;
  67 
  68 #if defined(DEBUG)
  69 uint_t pcieb_dbg_print = 0;
  70 
  71 static char *pcieb_debug_sym [] = {     /* same sequence as pcieb_debug_bit */
  72         /*  0 */ "attach",
  73         /*  1 */ "pwr",
  74         /*  2 */ "intr"
  75 };
  76 #endif /* DEBUG */
  77 
  78 static int pcieb_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *, off_t,
  79         off_t, caddr_t *);
  80 static int pcieb_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
  81         void *);
  82 static int pcieb_fm_init(pcieb_devstate_t *pcieb_p);
  83 static void pcieb_fm_fini(pcieb_devstate_t *pcieb_p);
  84 static int pcieb_fm_init_child(dev_info_t *dip, dev_info_t *cdip, int cap,
  85     ddi_iblock_cookie_t *ibc_p);
  86 static int pcieb_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
  87         ddi_dma_attr_t *attr_p, int (*waitfp)(caddr_t), caddr_t arg,
  88         ddi_dma_handle_t *handlep);
  89 static int pcieb_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
  90         ddi_dma_handle_t handle, enum ddi_dma_ctlops cmd, off_t *offp,
  91         size_t *lenp, caddr_t *objp, uint_t cache_flags);
  92 static int pcieb_intr_ops(dev_info_t *dip, dev_info_t *rdip,
  93         ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result);
  94 
  95 static struct bus_ops pcieb_bus_ops = {
  96         BUSO_REV,
  97         pcieb_bus_map,
  98         0,
  99         0,
 100         0,
 101         i_ddi_map_fault,
 102         0,
 103         pcieb_dma_allochdl,
 104         ddi_dma_freehdl,
 105         ddi_dma_bindhdl,
 106         ddi_dma_unbindhdl,
 107         ddi_dma_flush,
 108         ddi_dma_win,
 109         pcieb_dma_mctl,
 110         pcieb_ctlops,
 111         ddi_bus_prop_op,
 112         ndi_busop_get_eventcookie,      /* (*bus_get_eventcookie)();    */
 113         ndi_busop_add_eventcall,        /* (*bus_add_eventcall)();      */
 114         ndi_busop_remove_eventcall,     /* (*bus_remove_eventcall)();   */
 115         ndi_post_event,                 /* (*bus_post_event)();         */
 116         NULL,                           /* (*bus_intr_ctl)();           */
 117         NULL,                           /* (*bus_config)();             */
 118         NULL,                           /* (*bus_unconfig)();           */
 119         pcieb_fm_init_child,            /* (*bus_fm_init)();            */
 120         NULL,                           /* (*bus_fm_fini)();            */
 121         i_ndi_busop_access_enter,       /* (*bus_fm_access_enter)();    */
 122         i_ndi_busop_access_exit,        /* (*bus_fm_access_exit)();     */
 123         pcie_bus_power,                 /* (*bus_power)();      */
 124         pcieb_intr_ops,                 /* (*bus_intr_op)();            */
 125         pcie_hp_common_ops              /* (*bus_hp_op)();              */
 126 };
 127 
 128 static int      pcieb_open(dev_t *, int, int, cred_t *);
 129 static int      pcieb_close(dev_t, int, int, cred_t *);
 130 static int      pcieb_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 131 static int      pcieb_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
 132 static uint_t   pcieb_intr_handler(caddr_t arg1, caddr_t arg2);
 133 
 134 /* PM related functions */
 135 static int      pcieb_pwr_setup(dev_info_t *dip);
 136 static int      pcieb_pwr_init_and_raise(dev_info_t *dip, pcie_pwr_t *pwr_p);
 137 static void     pcieb_pwr_teardown(dev_info_t *dip);
 138 static int      pcieb_pwr_disable(dev_info_t *dip);
 139 
 140 /* Hotplug related functions */
 141 static void pcieb_id_props(pcieb_devstate_t *pcieb);
 142 
 143 /*
 144  * soft state pointer
 145  */
 146 void *pcieb_state;
 147 
 148 static struct cb_ops pcieb_cb_ops = {
 149         pcieb_open,                     /* open */
 150         pcieb_close,                    /* close */
 151         nodev,                          /* strategy */
 152         nodev,                          /* print */
 153         nodev,                          /* dump */
 154         nodev,                          /* read */
 155         nodev,                          /* write */
 156         pcieb_ioctl,                    /* ioctl */
 157         nodev,                          /* devmap */
 158         nodev,                          /* mmap */
 159         nodev,                          /* segmap */
 160         nochpoll,                       /* poll */
 161         pcie_prop_op,                   /* cb_prop_op */
 162         NULL,                           /* streamtab */
 163         D_NEW | D_MP | D_HOTPLUG,       /* Driver compatibility flag */
 164         CB_REV,                         /* rev */
 165         nodev,                          /* int (*cb_aread)() */
 166         nodev                           /* int (*cb_awrite)() */
 167 };
 168 
 169 static int      pcieb_probe(dev_info_t *);
 170 static int      pcieb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
 171 static int      pcieb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 172 
 173 static struct dev_ops pcieb_ops = {
 174         DEVO_REV,               /* devo_rev */
 175         0,                      /* refcnt  */
 176         pcieb_info,             /* info */
 177         nulldev,                /* identify */
 178         pcieb_probe,            /* probe */
 179         pcieb_attach,           /* attach */
 180         pcieb_detach,           /* detach */
 181         nulldev,                /* reset */
 182         &pcieb_cb_ops,              /* driver operations */
 183         &pcieb_bus_ops,             /* bus operations */
 184         pcie_power,             /* power */
 185         ddi_quiesce_not_needed,         /* quiesce */
 186 };
 187 
 188 /*
 189  * Module linkage information for the kernel.
 190  */
 191 
 192 static struct modldrv modldrv = {
 193         &mod_driverops, /* Type of module */
 194         "PCIe bridge/switch driver",
 195         &pcieb_ops, /* driver ops */
 196 };
 197 
 198 static struct modlinkage modlinkage = {
 199         MODREV_1,
 200         { (void *)&modldrv, NULL }
 201 };
 202 
 203 /*
 204  * forward function declarations:
 205  */
 206 static void     pcieb_uninitchild(dev_info_t *);
 207 static int      pcieb_initchild(dev_info_t *child);
 208 static void     pcieb_create_ranges_prop(dev_info_t *, ddi_acc_handle_t);
 209 static boolean_t pcieb_is_pcie_device_type(dev_info_t *dip);
 210 
 211 /* interrupt related declarations */
 212 static int      pcieb_msi_supported(dev_info_t *);
 213 static int      pcieb_intr_attach(pcieb_devstate_t *pcieb);
 214 static int      pcieb_intr_init(pcieb_devstate_t *pcieb_p, int intr_type);
 215 static void     pcieb_intr_fini(pcieb_devstate_t *pcieb_p);
 216 
 217 int
 218 _init(void)
 219 {
 220         int e;
 221 
 222         if ((e = ddi_soft_state_init(&pcieb_state, sizeof (pcieb_devstate_t),
 223             1)) == 0 && (e = mod_install(&modlinkage)) != 0)
 224                 ddi_soft_state_fini(&pcieb_state);
 225         return (e);
 226 }
 227 
 228 int
 229 _fini(void)
 230 {
 231         int e;
 232 
 233         if ((e = mod_remove(&modlinkage)) == 0) {
 234                 ddi_soft_state_fini(&pcieb_state);
 235         }
 236         return (e);
 237 }
 238 
 239 int
 240 _info(struct modinfo *modinfop)
 241 {
 242         return (mod_info(&modlinkage, modinfop));
 243 }
 244 
 245 /* ARGSUSED */
 246 static int
 247 pcieb_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 248 {
 249         minor_t         minor = getminor((dev_t)arg);
 250         int             instance = PCI_MINOR_NUM_TO_INSTANCE(minor);
 251         pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state, instance);
 252         int             ret = DDI_SUCCESS;
 253 
 254         switch (infocmd) {
 255         case DDI_INFO_DEVT2INSTANCE:
 256                 *result = (void *)(intptr_t)instance;
 257                 break;
 258         case DDI_INFO_DEVT2DEVINFO:
 259                 if (pcieb == NULL) {
 260                         ret = DDI_FAILURE;
 261                         break;
 262                 }
 263 
 264                 *result = (void *)pcieb->pcieb_dip;
 265                 break;
 266         default:
 267                 ret = DDI_FAILURE;
 268                 break;
 269         }
 270 
 271         return (ret);
 272 }
 273 
 274 
 275 /*ARGSUSED*/
 276 static int
 277 pcieb_probe(dev_info_t *devi)
 278 {
 279         return (DDI_PROBE_SUCCESS);
 280 }
 281 
 282 /*
 283  * This is a workaround for an undocumented HW erratum with the
 284  * multi-function, F0 and F2, Intel 41210 PCIe-to-PCI bridge. When
 285  * Fn (cdip) attaches, this workaround is called to initialize Fn's
 286  * sibling (sdip) with MPS/MRRS if it isn't already configured.
 287  * Doing so prevents a malformed TLP panic.
 288  */
 289 static void
 290 pcieb_41210_mps_wkrnd(dev_info_t *cdip)
 291 {
 292         dev_info_t *sdip;
 293         ddi_acc_handle_t cfg_hdl;
 294         uint16_t cdip_dev_ctrl, cdip_mrrs_mps;
 295         pcie_bus_t *cdip_bus_p = PCIE_DIP2BUS(cdip);
 296 
 297         /* Get cdip's MPS/MRRS already setup by pcie_initchild_mps() */
 298         ASSERT(cdip_bus_p);
 299         cdip_dev_ctrl  = PCIE_CAP_GET(16, cdip_bus_p, PCIE_DEVCTL);
 300         cdip_mrrs_mps  = cdip_dev_ctrl &
 301             (PCIE_DEVCTL_MAX_READ_REQ_MASK | PCIE_DEVCTL_MAX_PAYLOAD_MASK);
 302 
 303         /* Locate sdip and set its MPS/MRRS when applicable */
 304         for (sdip = ddi_get_child(ddi_get_parent(cdip)); sdip;
 305             sdip = ddi_get_next_sibling(sdip)) {
 306                 uint16_t sdip_dev_ctrl, sdip_mrrs_mps, cap_ptr;
 307                 uint32_t bus_dev_ven_id;
 308 
 309                 if (sdip == cdip || pci_config_setup(sdip, &cfg_hdl)
 310                     != DDI_SUCCESS)
 311                         continue;
 312 
 313                 /* must be an Intel 41210 bridge */
 314                 bus_dev_ven_id = pci_config_get32(cfg_hdl, PCI_CONF_VENID);
 315                 if (!PCIEB_IS_41210_BRIDGE(bus_dev_ven_id)) {
 316                         pci_config_teardown(&cfg_hdl);
 317                         continue;
 318                 }
 319 
 320                 if (PCI_CAP_LOCATE(cfg_hdl, PCI_CAP_ID_PCI_E, &cap_ptr)
 321                     != DDI_SUCCESS) {
 322                         pci_config_teardown(&cfg_hdl);
 323                         continue;
 324                 }
 325 
 326                 /* get sdip's MPS/MRRS to compare to cdip's */
 327                 sdip_dev_ctrl = PCI_CAP_GET16(cfg_hdl, NULL, cap_ptr,
 328                     PCIE_DEVCTL);
 329                 sdip_mrrs_mps = sdip_dev_ctrl &
 330                     (PCIE_DEVCTL_MAX_READ_REQ_MASK |
 331                     PCIE_DEVCTL_MAX_PAYLOAD_MASK);
 332 
 333                 /* if sdip already attached then its MPS/MRRS is configured */
 334                 if (i_ddi_devi_attached(sdip)) {
 335                         ASSERT(sdip_mrrs_mps == cdip_mrrs_mps);
 336                         pci_config_teardown(&cfg_hdl);
 337                         continue;
 338                 }
 339 
 340                 /* otherwise, update sdip's MPS/MRRS if different from cdip's */
 341                 if (sdip_mrrs_mps != cdip_mrrs_mps) {
 342                         sdip_dev_ctrl = (sdip_dev_ctrl &
 343                             ~(PCIE_DEVCTL_MAX_READ_REQ_MASK |
 344                             PCIE_DEVCTL_MAX_PAYLOAD_MASK)) | cdip_mrrs_mps;
 345 
 346                         PCI_CAP_PUT16(cfg_hdl, NULL, cap_ptr, PCIE_DEVCTL,
 347                             sdip_dev_ctrl);
 348                 }
 349 
 350                 /*
 351                  * note: sdip's bus_mps will be updated by
 352                  * pcie_initchild_mps()
 353                  */
 354 
 355                 pci_config_teardown(&cfg_hdl);
 356 
 357                 break;
 358         }
 359 }
 360 
 361 static int
 362 pcieb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
 363 {
 364         int                     instance;
 365         char                    device_type[8];
 366         pcieb_devstate_t        *pcieb;
 367         pcie_bus_t              *bus_p = PCIE_DIP2UPBUS(devi);
 368         ddi_acc_handle_t        config_handle = bus_p->bus_cfg_hdl;
 369 
 370         switch (cmd) {
 371         case DDI_RESUME:
 372                 (void) pcie_pwr_resume(devi);
 373                 return (DDI_SUCCESS);
 374 
 375         default:
 376                 return (DDI_FAILURE);
 377 
 378         case DDI_ATTACH:
 379                 break;
 380         }
 381 
 382         if (!(PCIE_IS_BDG(bus_p))) {
 383                 PCIEB_DEBUG(DBG_ATTACH, devi, "This is not a switch or"
 384                 " bridge\n");
 385                 return (DDI_FAILURE);
 386         }
 387 
 388         /*
 389          * If PCIE_LINKCTL_LINK_DISABLE bit in the PCIe Config
 390          * Space (PCIe Capability Link Control Register) is set,
 391          * then do not bind the driver.
 392          */
 393         if (PCIE_CAP_GET(16, bus_p, PCIE_LINKCTL) & PCIE_LINKCTL_LINK_DISABLE)
 394                 return (DDI_FAILURE);
 395 
 396         /*
 397          * Allocate and get soft state structure.
 398          */
 399         instance = ddi_get_instance(devi);
 400         if (ddi_soft_state_zalloc(pcieb_state, instance) != DDI_SUCCESS)
 401                 return (DDI_FAILURE);
 402         pcieb = ddi_get_soft_state(pcieb_state, instance);
 403         pcieb->pcieb_dip = devi;
 404 
 405         if ((pcieb_fm_init(pcieb)) != DDI_SUCCESS) {
 406                 PCIEB_DEBUG(DBG_ATTACH, devi, "Failed in pcieb_fm_init\n");
 407                 goto fail;
 408         }
 409         pcieb->pcieb_init_flags |= PCIEB_INIT_FM;
 410 
 411         mutex_init(&pcieb->pcieb_mutex, NULL, MUTEX_DRIVER, NULL);
 412         mutex_init(&pcieb->pcieb_err_mutex, NULL, MUTEX_DRIVER,
 413             (void *)pcieb->pcieb_fm_ibc);
 414         mutex_init(&pcieb->pcieb_peek_poke_mutex, NULL, MUTEX_DRIVER,
 415             (void *)pcieb->pcieb_fm_ibc);
 416 
 417         /* create special properties for device identification */
 418         pcieb_id_props(pcieb);
 419 
 420         /*
 421          * Power management setup. This also makes sure that switch/bridge
 422          * is at D0 during attach.
 423          */
 424         if (pwr_common_setup(devi) != DDI_SUCCESS) {
 425                 PCIEB_DEBUG(DBG_PWR, devi, "pwr_common_setup failed\n");
 426                 goto fail;
 427         }
 428 
 429         if (pcieb_pwr_setup(devi) != DDI_SUCCESS) {
 430                 PCIEB_DEBUG(DBG_PWR, devi, "pxb_pwr_setup failed \n");
 431                 goto fail;
 432         }
 433 
 434         /*
 435          * Make sure the "device_type" property exists.
 436          */
 437         if (pcieb_is_pcie_device_type(devi))
 438                 (void) strcpy(device_type, "pciex");
 439         else
 440                 (void) strcpy(device_type, "pci");
 441 
 442         (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
 443             "device_type", device_type);
 444 
 445         /*
 446          * Check whether the "ranges" property is present.
 447          * Otherwise create the ranges property by reading
 448          * the configuration registers
 449          */
 450         if (ddi_prop_exists(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
 451             "ranges") == 0) {
 452                 pcieb_create_ranges_prop(devi, config_handle);
 453         }
 454 
 455         if (PCIE_IS_PCI_BDG(bus_p))
 456                 pcieb_set_pci_perf_parameters(devi, config_handle);
 457 
 458 #ifdef PX_PLX
 459         pcieb_attach_plx_workarounds(pcieb);
 460 #endif /* PX_PLX */
 461 
 462         if (pcie_init(devi, NULL) != DDI_SUCCESS)
 463                 goto fail;
 464 
 465         /* Intel PCIe-to-PCI 41210 bridge workaround -- if applicable */
 466         if (pcieb_disable_41210_wkarnd == 0 &&
 467             PCIEB_IS_41210_BRIDGE(bus_p->bus_dev_ven_id))
 468                 pcieb_41210_mps_wkrnd(devi);
 469 
 470         /*
 471          * Initialize interrupt handlers. Ignore return value.
 472          */
 473         (void) pcieb_intr_attach(pcieb);
 474 
 475         (void) pcie_hpintr_enable(devi);
 476 
 477         /* Do any platform specific workarounds needed at this time */
 478         pcieb_plat_attach_workaround(devi);
 479 
 480         /*
 481          * If this is a root port, determine and set the max payload size.
 482          * Since this will involve scanning the fabric, all error enabling
 483          * and sw workarounds should be in place before doing this.
 484          */
 485         if (PCIE_IS_RP(bus_p))
 486                 pcie_init_root_port_mps(devi);
 487 
 488         ddi_report_dev(devi);
 489         return (DDI_SUCCESS);
 490 
 491 fail:
 492         (void) pcieb_detach(devi, DDI_DETACH);
 493         return (DDI_FAILURE);
 494 }
 495 
 496 static int
 497 pcieb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
 498 {
 499         pcieb_devstate_t *pcieb;
 500         int error = DDI_SUCCESS;
 501 
 502         switch (cmd) {
 503         case DDI_SUSPEND:
 504                 error = pcie_pwr_suspend(devi);
 505                 return (error);
 506 
 507         case DDI_DETACH:
 508                 break;
 509 
 510         default:
 511                 return (DDI_FAILURE);
 512         }
 513 
 514         pcieb = ddi_get_soft_state(pcieb_state, ddi_get_instance(devi));
 515 
 516         /* disable hotplug interrupt */
 517         (void) pcie_hpintr_disable(devi);
 518 
 519         /* remove interrupt handlers */
 520         pcieb_intr_fini(pcieb);
 521 
 522         /* uninitialize inband PCI-E HPC if present */
 523         (void) pcie_uninit(devi);
 524 
 525         (void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");
 526 
 527         (void) ndi_prop_remove(DDI_DEV_T_NONE, pcieb->pcieb_dip,
 528             "pcie_ce_mask");
 529 
 530         if (pcieb->pcieb_init_flags & PCIEB_INIT_FM)
 531                 pcieb_fm_fini(pcieb);
 532 
 533         pcieb_pwr_teardown(devi);
 534         pwr_common_teardown(devi);
 535 
 536         mutex_destroy(&pcieb->pcieb_peek_poke_mutex);
 537         mutex_destroy(&pcieb->pcieb_err_mutex);
 538         mutex_destroy(&pcieb->pcieb_mutex);
 539 
 540         /*
 541          * And finally free the per-pci soft state.
 542          */
 543         ddi_soft_state_free(pcieb_state, ddi_get_instance(devi));
 544 
 545         return (DDI_SUCCESS);
 546 }
 547 
 548 static int
 549 pcieb_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
 550     off_t offset, off_t len, caddr_t *vaddrp)
 551 {
 552         dev_info_t *pdip;
 553 
 554         if (PCIE_IS_RP(PCIE_DIP2BUS(dip)) && mp->map_handlep != NULL) {
 555                 ddi_acc_impl_t *hdlp =
 556                     (ddi_acc_impl_t *)(mp->map_handlep)->ah_platform_private;
 557 
 558                 pcieb_set_prot_scan(dip, hdlp);
 559         }
 560         pdip = (dev_info_t *)DEVI(dip)->devi_parent;
 561         return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip, rdip, mp,
 562             offset, len, vaddrp));
 563 }
 564 
 565 static int
 566 pcieb_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
 567     void *arg, void *result)
 568 {
 569         pci_regspec_t *drv_regp;
 570         int     reglen;
 571         int     rn;
 572         int     totreg;
 573         pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state,
 574             ddi_get_instance(dip));
 575         struct detachspec *ds;
 576         struct attachspec *as;
 577 
 578         switch (ctlop) {
 579         case DDI_CTLOPS_REPORTDEV:
 580                 if (rdip == (dev_info_t *)0)
 581                         return (DDI_FAILURE);
 582 
 583                 if (ddi_get_parent(rdip) == dip) {
 584                         cmn_err(CE_CONT, "?PCIE-device: %s@%s, %s%d\n",
 585                             ddi_node_name(rdip), ddi_get_name_addr(rdip),
 586                             ddi_driver_name(rdip), ddi_get_instance(rdip));
 587                 }
 588 
 589                 /* Pass it up for fabric sync */
 590                 (void) ddi_ctlops(dip, rdip, ctlop, arg, result);
 591                 return (DDI_SUCCESS);
 592 
 593         case DDI_CTLOPS_INITCHILD:
 594                 return (pcieb_initchild((dev_info_t *)arg));
 595 
 596         case DDI_CTLOPS_UNINITCHILD:
 597                 pcieb_uninitchild((dev_info_t *)arg);
 598                 return (DDI_SUCCESS);
 599 
 600         case DDI_CTLOPS_SIDDEV:
 601                 return (DDI_SUCCESS);
 602 
 603         case DDI_CTLOPS_REGSIZE:
 604         case DDI_CTLOPS_NREGS:
 605                 if (rdip == (dev_info_t *)0)
 606                         return (DDI_FAILURE);
 607                 break;
 608 
 609         case DDI_CTLOPS_PEEK:
 610         case DDI_CTLOPS_POKE:
 611                 return (pcieb_plat_peekpoke(dip, rdip, ctlop, arg, result));
 612         case DDI_CTLOPS_ATTACH:
 613                 if (!pcie_is_child(dip, rdip))
 614                         return (DDI_SUCCESS);
 615 
 616                 as = (struct attachspec *)arg;
 617                 switch (as->when) {
 618                 case DDI_PRE:
 619                         if (as->cmd == DDI_RESUME) {
 620                                 pcie_clear_errors(rdip);
 621                                 if (pcieb_plat_ctlops(rdip, ctlop, arg) !=
 622                                     DDI_SUCCESS)
 623                                         return (DDI_FAILURE);
 624                         }
 625 
 626                         if (as->cmd == DDI_ATTACH)
 627                                 return (pcie_pm_hold(dip));
 628 
 629                         return (DDI_SUCCESS);
 630 
 631                 case DDI_POST:
 632                         if (as->cmd == DDI_ATTACH &&
 633                             as->result != DDI_SUCCESS) {
 634                                 /*
 635                                  * Attach failed for the child device. The child
 636                                  * driver may have made PM calls before the
 637                                  * attach failed. pcie_pm_remove_child() should
 638                                  * cleanup PM state and holds (if any)
 639                                  * associated with the child device.
 640                                  */
 641                                 return (pcie_pm_remove_child(dip, rdip));
 642                         }
 643 
 644                         if (as->result == DDI_SUCCESS) {
 645                                 pf_init(rdip, (void *)pcieb->pcieb_fm_ibc,
 646                                     as->cmd);
 647 
 648                                 (void) pcieb_plat_ctlops(rdip, ctlop, arg);
 649                         }
 650 
 651                         /*
 652                          * For empty hotplug-capable slots, we should explicitly
 653                          * disable the errors, so that we won't panic upon
 654                          * unsupported hotplug messages.
 655                          */
 656                         if ((!ddi_prop_exists(DDI_DEV_T_ANY, rdip,
 657                             DDI_PROP_DONTPASS, "hotplug-capable")) ||
 658                             ddi_get_child(rdip)) {
 659                                 (void) pcie_postattach_child(rdip);
 660                                 return (DDI_SUCCESS);
 661                         }
 662 
 663                         pcie_disable_errors(rdip);
 664 
 665                         return (DDI_SUCCESS);
 666                 default:
 667                         break;
 668                 }
 669                 return (DDI_SUCCESS);
 670 
 671         case DDI_CTLOPS_DETACH:
 672                 if (!pcie_is_child(dip, rdip))
 673                         return (DDI_SUCCESS);
 674 
 675                 ds = (struct detachspec *)arg;
 676                 switch (ds->when) {
 677                 case DDI_PRE:
 678                         pf_fini(rdip, ds->cmd);
 679                         return (DDI_SUCCESS);
 680 
 681                 case DDI_POST:
 682                         if (pcieb_plat_ctlops(rdip, ctlop, arg) != DDI_SUCCESS)
 683                                 return (DDI_FAILURE);
 684                         if (ds->cmd == DDI_DETACH &&
 685                             ds->result == DDI_SUCCESS) {
 686                                 return (pcie_pm_remove_child(dip, rdip));
 687                         }
 688                         return (DDI_SUCCESS);
 689                 default:
 690                         break;
 691                 }
 692                 return (DDI_SUCCESS);
 693         default:
 694                 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
 695         }
 696 
 697         *(int *)result = 0;
 698         if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
 699             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg", (caddr_t)&drv_regp,
 700             &reglen) != DDI_SUCCESS)
 701                 return (DDI_FAILURE);
 702 
 703         totreg = reglen / sizeof (pci_regspec_t);
 704         if (ctlop == DDI_CTLOPS_NREGS)
 705                 *(int *)result = totreg;
 706         else if (ctlop == DDI_CTLOPS_REGSIZE) {
 707                 rn = *(int *)arg;
 708                 if (rn >= totreg) {
 709                         kmem_free(drv_regp, reglen);
 710                         return (DDI_FAILURE);
 711                 }
 712 
 713                 *(off_t *)result = drv_regp[rn].pci_size_low |
 714                     ((uint64_t)drv_regp[rn].pci_size_hi << 32);
 715         }
 716 
 717         kmem_free(drv_regp, reglen);
 718         return (DDI_SUCCESS);
 719 }
 720 
 721 /*
 722  * name_child
 723  *
 724  * This function is called from init_child to name a node. It is
 725  * also passed as a callback for node merging functions.
 726  *
 727  * return value: DDI_SUCCESS, DDI_FAILURE
 728  */
 729 static int
 730 pcieb_name_child(dev_info_t *child, char *name, int namelen)
 731 {
 732         pci_regspec_t *pci_rp;
 733         uint_t device, func;
 734         char **unit_addr;
 735         uint_t n;
 736 
 737         /*
 738          * For .conf nodes, use unit-address property as name
 739          */
 740         if (ndi_dev_is_persistent_node(child) == 0) {
 741                 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
 742                     DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
 743                     DDI_PROP_SUCCESS) {
 744                         cmn_err(CE_WARN,
 745                             "cannot find unit-address in %s.conf",
 746                             ddi_driver_name(child));
 747                         return (DDI_FAILURE);
 748                 }
 749                 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
 750                         cmn_err(CE_WARN, "unit-address property in %s.conf"
 751                             " not well-formed", ddi_driver_name(child));
 752                         ddi_prop_free(unit_addr);
 753                         return (DDI_FAILURE);
 754                 }
 755                 (void) snprintf(name, namelen, "%s", *unit_addr);
 756                 ddi_prop_free(unit_addr);
 757                 return (DDI_SUCCESS);
 758         }
 759 
 760         /*
 761          * Get the address portion of the node name based on
 762          * the function and device number.
 763          */
 764         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
 765             DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) {
 766                 return (DDI_FAILURE);
 767         }
 768 
 769         /* copy the device identifications */
 770         device = PCI_REG_DEV_G(pci_rp[0].pci_phys_hi);
 771         func = PCI_REG_FUNC_G(pci_rp[0].pci_phys_hi);
 772 
 773         if (pcie_ari_is_enabled(ddi_get_parent(child))
 774             == PCIE_ARI_FORW_ENABLED) {
 775                 func = (device << 3) | func;
 776                 device = 0;
 777         }
 778 
 779         if (func != 0)
 780                 (void) snprintf(name, namelen, "%x,%x", device, func);
 781         else
 782                 (void) snprintf(name, namelen, "%x", device);
 783 
 784         ddi_prop_free(pci_rp);
 785         return (DDI_SUCCESS);
 786 }
 787 
 788 static int
 789 pcieb_initchild(dev_info_t *child)
 790 {
 791         char name[MAXNAMELEN];
 792         int result = DDI_FAILURE;
 793         pcieb_devstate_t *pcieb =
 794             (pcieb_devstate_t *)ddi_get_soft_state(pcieb_state,
 795             ddi_get_instance(ddi_get_parent(child)));
 796 
 797         /*
 798          * Name the child
 799          */
 800         if (pcieb_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS) {
 801                 result = DDI_FAILURE;
 802                 goto done;
 803         }
 804         ddi_set_name_addr(child, name);
 805 
 806         /*
 807          * Pseudo nodes indicate a prototype node with per-instance
 808          * properties to be merged into the real h/w device node.
 809          * The interpretation of the unit-address is DD[,F]
 810          * where DD is the device id and F is the function.
 811          */
 812         if (ndi_dev_is_persistent_node(child) == 0) {
 813                 extern int pci_allow_pseudo_children;
 814 
 815                 /*
 816                  * Try to merge the properties from this prototype
 817                  * node into real h/w nodes.
 818                  */
 819                 if (ndi_merge_node(child, pcieb_name_child) == DDI_SUCCESS) {
 820                         /*
 821                          * Merged ok - return failure to remove the node.
 822                          */
 823                         ddi_set_name_addr(child, NULL);
 824                         result = DDI_FAILURE;
 825                         goto done;
 826                 }
 827 
 828                 /* workaround for ddivs to run under PCI-E */
 829                 if (pci_allow_pseudo_children) {
 830                         result = DDI_SUCCESS;
 831                         goto done;
 832                 }
 833 
 834                 /*
 835                  * The child was not merged into a h/w node,
 836                  * but there's not much we can do with it other
 837                  * than return failure to cause the node to be removed.
 838                  */
 839                 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
 840                     ddi_driver_name(child), ddi_get_name_addr(child),
 841                     ddi_driver_name(child));
 842                 ddi_set_name_addr(child, NULL);
 843                 result = DDI_NOT_WELL_FORMED;
 844                 goto done;
 845         }
 846 
 847         /* platform specific initchild */
 848         pcieb_plat_initchild(child);
 849 
 850         if (pcie_pm_hold(pcieb->pcieb_dip) != DDI_SUCCESS) {
 851                 PCIEB_DEBUG(DBG_PWR, pcieb->pcieb_dip,
 852                     "INITCHILD: px_pm_hold failed\n");
 853                 result = DDI_FAILURE;
 854                 goto done;
 855         }
 856         /* Any return from here must call pcie_pm_release */
 857 
 858         /*
 859          * If configuration registers were previously saved by
 860          * child (before it entered D3), then let the child do the
 861          * restore to set up the config regs as it'll first need to
 862          * power the device out of D3.
 863          */
 864         if (ddi_prop_exists(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
 865             "config-regs-saved-by-child") == 1) {
 866                 PCIEB_DEBUG(DBG_PWR, ddi_get_parent(child),
 867                     "INITCHILD: config regs to be restored by child"
 868                     " for %s@%s\n", ddi_node_name(child),
 869                     ddi_get_name_addr(child));
 870 
 871                 result = DDI_SUCCESS;
 872                 goto cleanup;
 873         }
 874 
 875         PCIEB_DEBUG(DBG_PWR, ddi_get_parent(child),
 876             "INITCHILD: config regs setup for %s@%s\n",
 877             ddi_node_name(child), ddi_get_name_addr(child));
 878 
 879         pcie_init_dom(child);
 880 
 881         if (pcie_initchild(child) != DDI_SUCCESS) {
 882                 result = DDI_FAILURE;
 883                 pcie_fini_dom(child);
 884                 goto cleanup;
 885         }
 886 
 887 #ifdef PX_PLX
 888         if (pcieb_init_plx_workarounds(pcieb, child) == DDI_FAILURE) {
 889                 result = DDI_FAILURE;
 890                 pcie_fini_dom(child);
 891                 goto cleanup;
 892         }
 893 #endif /* PX_PLX */
 894 
 895         result = DDI_SUCCESS;
 896 cleanup:
 897         pcie_pm_release(pcieb->pcieb_dip);
 898 done:
 899         return (result);
 900 }
 901 
 902 static void
 903 pcieb_uninitchild(dev_info_t *dip)
 904 {
 905 
 906         pcie_uninitchild(dip);
 907 
 908         pcieb_plat_uninitchild(dip);
 909 
 910         ddi_set_name_addr(dip, NULL);
 911 
 912         /*
 913          * Strip the node to properly convert it back to prototype form
 914          */
 915         ddi_remove_minor_node(dip, NULL);
 916 
 917         ddi_prop_remove_all(dip);
 918 }
 919 
 920 static boolean_t
 921 pcieb_is_pcie_device_type(dev_info_t *dip)
 922 {
 923         pcie_bus_t      *bus_p = PCIE_DIP2BUS(dip);
 924 
 925         if (PCIE_IS_SW(bus_p) || PCIE_IS_RP(bus_p) || PCIE_IS_PCI2PCIE(bus_p))
 926                 return (B_TRUE);
 927 
 928         return (B_FALSE);
 929 }
 930 
 931 static int
 932 pcieb_intr_attach(pcieb_devstate_t *pcieb)
 933 {
 934         int                     intr_types;
 935         dev_info_t              *dip = pcieb->pcieb_dip;
 936 
 937         /* Allow platform specific code to do any initialization first */
 938         pcieb_plat_intr_attach(pcieb);
 939 
 940         /*
 941          * Initialize interrupt handlers.
 942          * If both MSI and FIXED are supported, try to attach MSI first.
 943          * If MSI fails for any reason, then try FIXED, but only allow one
 944          * type to be attached.
 945          */
 946         if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
 947                 PCIEB_DEBUG(DBG_ATTACH, dip, "ddi_intr_get_supported_types"
 948                     " failed\n");
 949                 goto FAIL;
 950         }
 951 
 952         if ((intr_types & DDI_INTR_TYPE_MSI) &&
 953             (pcieb_msi_supported(dip) == DDI_SUCCESS)) {
 954                 if (pcieb_intr_init(pcieb, DDI_INTR_TYPE_MSI) == DDI_SUCCESS)
 955                         intr_types = DDI_INTR_TYPE_MSI;
 956                 else {
 957                         PCIEB_DEBUG(DBG_ATTACH, dip, "Unable to attach MSI"
 958                             " handler\n");
 959                 }
 960         }
 961 
 962         if (intr_types != DDI_INTR_TYPE_MSI) {
 963                 /*
 964                  * MSIs are not supported or MSI initialization failed. For Root
 965                  * Ports mark this so error handling might try to fallback to
 966                  * some other mechanism if available (machinecheck etc.).
 967                  */
 968                 if (PCIE_IS_RP(PCIE_DIP2UPBUS(dip)))
 969                         pcieb->pcieb_no_aer_msi = B_TRUE;
 970         }
 971 
 972         if (intr_types & DDI_INTR_TYPE_FIXED) {
 973                 if (pcieb_intr_init(pcieb, DDI_INTR_TYPE_FIXED) !=
 974                     DDI_SUCCESS) {
 975                         PCIEB_DEBUG(DBG_ATTACH, dip,
 976                             "Unable to attach INTx handler\n");
 977                         goto FAIL;
 978                 }
 979         }
 980         return (DDI_SUCCESS);
 981 
 982 FAIL:
 983         return (DDI_FAILURE);
 984 }
 985 
 986 /*
 987  * This function initializes internally generated interrupts only.
 988  * It does not affect any interrupts generated by downstream devices
 989  * or the forwarding of them.
 990  *
 991  * Enable Device Specific Interrupts or Hotplug features here.
 992  * Enabling features may change how many interrupts are requested
 993  * by the device.  If features are not enabled first, the
 994  * device might not ask for any interrupts.
 995  */
 996 
 997 static int
 998 pcieb_intr_init(pcieb_devstate_t *pcieb, int intr_type)
 999 {
1000         dev_info_t      *dip = pcieb->pcieb_dip;
1001         int             nintrs, request, count, x;
1002         int             intr_cap = 0;
1003         int             inum = 0;
1004         int             ret, hp_msi_off;
1005         pcie_bus_t      *bus_p = PCIE_DIP2UPBUS(dip);
1006         uint16_t        vendorid = bus_p->bus_dev_ven_id & 0xFFFF;
1007         boolean_t       is_hp = B_FALSE;
1008         boolean_t       is_pme = B_FALSE;
1009 
1010         PCIEB_DEBUG(DBG_ATTACH, dip, "pcieb_intr_init: Attaching %s handler\n",
1011             (intr_type == DDI_INTR_TYPE_MSI) ? "MSI" : "INTx");
1012 
1013         request = 0;
1014         if (PCIE_IS_HOTPLUG_ENABLED(dip)) {
1015                 request++;
1016                 is_hp = B_TRUE;
1017         }
1018 
1019         /*
1020          * Hotplug and PME share the same MSI vector. If hotplug is not
1021          * supported check if MSI is needed for PME.
1022          */
1023         if ((intr_type == DDI_INTR_TYPE_MSI) && PCIE_IS_RP(bus_p) &&
1024             (vendorid == NVIDIA_VENDOR_ID)) {
1025                 is_pme = B_TRUE;
1026                 if (!is_hp)
1027                         request++;
1028         }
1029 
1030         /*
1031          * Setup MSI if this device is a Rootport and has AER. Currently no
1032          * SPARC Root Port supports fabric errors being reported through it.
1033          */
1034         if (intr_type == DDI_INTR_TYPE_MSI) {
1035                 if (PCIE_IS_RP(bus_p) && PCIE_HAS_AER(bus_p))
1036                         request++;
1037         }
1038 
1039         if (request == 0)
1040                 return (DDI_SUCCESS);
1041 
1042         /*
1043          * Get number of supported interrupts.
1044          *
1045          * Several Bridges/Switches will not have this property set, resulting
1046          * in a FAILURE, if the device is not configured in a way that
1047          * interrupts are needed. (eg. hotplugging)
1048          */
1049         ret = ddi_intr_get_nintrs(dip, intr_type, &nintrs);
1050         if ((ret != DDI_SUCCESS) || (nintrs == 0)) {
1051                 PCIEB_DEBUG(DBG_ATTACH, dip, "ddi_intr_get_nintrs ret:%d"
1052                     " req:%d\n", ret, nintrs);
1053                 return (DDI_FAILURE);
1054         }
1055 
1056         PCIEB_DEBUG(DBG_ATTACH, dip, "bdf 0x%x: ddi_intr_get_nintrs: nintrs %d",
1057             " request %d\n", bus_p->bus_bdf, nintrs, request);
1058 
1059         if (request > nintrs)
1060                 request = nintrs;
1061 
1062         /* Allocate an array of interrupt handlers */
1063         pcieb->pcieb_htable_size = sizeof (ddi_intr_handle_t) * request;
1064         pcieb->pcieb_htable = kmem_zalloc(pcieb->pcieb_htable_size,
1065             KM_SLEEP);
1066         pcieb->pcieb_init_flags |= PCIEB_INIT_HTABLE;
1067 
1068         ret = ddi_intr_alloc(dip, pcieb->pcieb_htable, intr_type, inum,
1069             request, &count, DDI_INTR_ALLOC_NORMAL);
1070         if ((ret != DDI_SUCCESS) || (count == 0)) {
1071                 PCIEB_DEBUG(DBG_ATTACH, dip, "ddi_intr_alloc() ret: %d ask: %d"
1072                     " actual: %d\n", ret, request, count);
1073                 goto FAIL;
1074         }
1075         pcieb->pcieb_init_flags |= PCIEB_INIT_ALLOC;
1076 
1077         /* Save the actual number of interrupts allocated */
1078         pcieb->pcieb_intr_count = count;
1079         if (count < request) {
1080                 PCIEB_DEBUG(DBG_ATTACH, dip, "bdf 0%x: Requested Intr: %d"
1081                     " Received: %d\n", bus_p->bus_bdf, request, count);
1082         }
1083 
1084         /*
1085          * NVidia (MCP55 and other) chipsets have a errata that if the number
1086          * of requested MSI intrs is not allocated we have to fall back to INTx.
1087          */
1088         if (intr_type == DDI_INTR_TYPE_MSI) {
1089                 if (PCIE_IS_RP(bus_p) && (vendorid == NVIDIA_VENDOR_ID)) {
1090                         if (request != count)
1091                                 goto FAIL;
1092                 }
1093         }
1094 
1095         /* Get interrupt priority */
1096         ret = ddi_intr_get_pri(pcieb->pcieb_htable[0],
1097             &pcieb->pcieb_intr_priority);
1098         if (ret != DDI_SUCCESS) {
1099                 PCIEB_DEBUG(DBG_ATTACH, dip, "ddi_intr_get_pri() ret: %d\n",
1100                     ret);
1101                 goto FAIL;
1102         }
1103 
1104         if (pcieb->pcieb_intr_priority >= LOCK_LEVEL) {
1105                 pcieb->pcieb_intr_priority = LOCK_LEVEL - 1;
1106                 ret = ddi_intr_set_pri(pcieb->pcieb_htable[0],
1107                     pcieb->pcieb_intr_priority);
1108                 if (ret != DDI_SUCCESS) {
1109                         PCIEB_DEBUG(DBG_ATTACH, dip, "ddi_intr_set_pri() ret:"
1110                         " %d\n", ret);
1111 
1112                         goto FAIL;
1113                 }
1114         }
1115 
1116         mutex_init(&pcieb->pcieb_intr_mutex, NULL, MUTEX_DRIVER, NULL);
1117 
1118         pcieb->pcieb_init_flags |= PCIEB_INIT_MUTEX;
1119 
1120         for (count = 0; count < pcieb->pcieb_intr_count; count++) {
1121                 ret = ddi_intr_add_handler(pcieb->pcieb_htable[count],
1122                     pcieb_intr_handler, (caddr_t)pcieb,
1123                     (caddr_t)(uintptr_t)(inum + count));
1124 
1125                 if (ret != DDI_SUCCESS) {
1126                         PCIEB_DEBUG(DBG_ATTACH, dip, "Cannot add "
1127                             "interrupt(%d)\n", ret);
1128                         break;
1129                 }
1130         }
1131 
1132         /* If unsucessful, remove the added handlers */
1133         if (ret != DDI_SUCCESS) {
1134                 for (x = 0; x < count; x++) {
1135                         (void) ddi_intr_remove_handler(pcieb->pcieb_htable[x]);
1136                 }
1137                 goto FAIL;
1138         }
1139 
1140         pcieb->pcieb_init_flags |= PCIEB_INIT_HANDLER;
1141 
1142         (void) ddi_intr_get_cap(pcieb->pcieb_htable[0], &intr_cap);
1143 
1144         /*
1145          * Get this intr lock because we are not quite ready to handle
1146          * interrupts immediately after enabling it. The MSI multi register
1147          * gets programmed in ddi_intr_enable after which we need to get the
1148          * MSI offsets for Hotplug/AER.
1149          */
1150         mutex_enter(&pcieb->pcieb_intr_mutex);
1151 
1152         if (intr_cap & DDI_INTR_FLAG_BLOCK) {
1153                 (void) ddi_intr_block_enable(pcieb->pcieb_htable,
1154                     pcieb->pcieb_intr_count);
1155                 pcieb->pcieb_init_flags |= PCIEB_INIT_BLOCK;
1156         } else {
1157                 for (count = 0; count < pcieb->pcieb_intr_count; count++) {
1158                         (void) ddi_intr_enable(pcieb->pcieb_htable[count]);
1159                 }
1160         }
1161         pcieb->pcieb_init_flags |= PCIEB_INIT_ENABLE;
1162 
1163         /* Save the interrupt type */
1164         pcieb->pcieb_intr_type = intr_type;
1165 
1166         /* Get the MSI offset for hotplug/PME from the PCIe cap reg */
1167         if (intr_type == DDI_INTR_TYPE_MSI) {
1168                 hp_msi_off = PCI_CAP_GET16(bus_p->bus_cfg_hdl, NULL,
1169                     bus_p->bus_pcie_off, PCIE_PCIECAP) &
1170                     PCIE_PCIECAP_INT_MSG_NUM;
1171 
1172                 if (hp_msi_off >= count) {
1173                         PCIEB_DEBUG(DBG_ATTACH, dip, "MSI number %d in PCIe "
1174                             "cap > max allocated %d\n", hp_msi_off, count);
1175                         mutex_exit(&pcieb->pcieb_intr_mutex);
1176                         goto FAIL;
1177                 }
1178 
1179                 if (is_hp)
1180                         pcieb->pcieb_isr_tab[hp_msi_off] |= PCIEB_INTR_SRC_HP;
1181 
1182                 if (is_pme)
1183                         pcieb->pcieb_isr_tab[hp_msi_off] |= PCIEB_INTR_SRC_PME;
1184         } else {
1185                 /* INTx handles only Hotplug interrupts */
1186                 if (is_hp)
1187                         pcieb->pcieb_isr_tab[0] |= PCIEB_INTR_SRC_HP;
1188         }
1189 
1190 
1191         /*
1192          * Get the MSI offset for errors from the AER Root Error status
1193          * register.
1194          */
1195         if ((intr_type == DDI_INTR_TYPE_MSI) && PCIE_IS_RP(bus_p)) {
1196                 if (PCIE_HAS_AER(bus_p)) {
1197                         int aer_msi_off;
1198                         aer_msi_off = (PCI_XCAP_GET32(bus_p->bus_cfg_hdl, NULL,
1199                             bus_p->bus_aer_off, PCIE_AER_RE_STS) >>
1200                             PCIE_AER_RE_STS_MSG_NUM_SHIFT) &
1201                             PCIE_AER_RE_STS_MSG_NUM_MASK;
1202 
1203                         if (aer_msi_off >= count) {
1204                                 PCIEB_DEBUG(DBG_ATTACH, dip, "MSI number %d in"
1205                                     " AER cap > max allocated %d\n",
1206                                     aer_msi_off, count);
1207                                 mutex_exit(&pcieb->pcieb_intr_mutex);
1208                                 goto FAIL;
1209                         }
1210                         pcieb->pcieb_isr_tab[aer_msi_off] |= PCIEB_INTR_SRC_AER;
1211                 } else {
1212                         /*
1213                          * This RP does not have AER. Fallback to the
1214                          * SERR+Machinecheck approach if available.
1215                          */
1216                         pcieb->pcieb_no_aer_msi = B_TRUE;
1217                 }
1218         }
1219 
1220         mutex_exit(&pcieb->pcieb_intr_mutex);
1221         return (DDI_SUCCESS);
1222 
1223 FAIL:
1224         pcieb_intr_fini(pcieb);
1225         return (DDI_FAILURE);
1226 }
1227 
1228 static void
1229 pcieb_intr_fini(pcieb_devstate_t *pcieb)
1230 {
1231         int x;
1232         int count = pcieb->pcieb_intr_count;
1233         int flags = pcieb->pcieb_init_flags;
1234 
1235         if ((flags & PCIEB_INIT_ENABLE) &&
1236             (flags & PCIEB_INIT_BLOCK)) {
1237                 (void) ddi_intr_block_disable(pcieb->pcieb_htable, count);
1238                 flags &= ~(PCIEB_INIT_ENABLE |
1239                     PCIEB_INIT_BLOCK);
1240         }
1241 
1242         if (flags & PCIEB_INIT_MUTEX)
1243                 mutex_destroy(&pcieb->pcieb_intr_mutex);
1244 
1245         for (x = 0; x < count; x++) {
1246                 if (flags & PCIEB_INIT_ENABLE)
1247                         (void) ddi_intr_disable(pcieb->pcieb_htable[x]);
1248 
1249                 if (flags & PCIEB_INIT_HANDLER)
1250                         (void) ddi_intr_remove_handler(pcieb->pcieb_htable[x]);
1251 
1252                 if (flags & PCIEB_INIT_ALLOC)
1253                         (void) ddi_intr_free(pcieb->pcieb_htable[x]);
1254         }
1255 
1256         flags &= ~(PCIEB_INIT_ENABLE | PCIEB_INIT_HANDLER | PCIEB_INIT_ALLOC |
1257             PCIEB_INIT_MUTEX);
1258 
1259         if (flags & PCIEB_INIT_HTABLE)
1260                 kmem_free(pcieb->pcieb_htable, pcieb->pcieb_htable_size);
1261 
1262         flags &= ~PCIEB_INIT_HTABLE;
1263 
1264         pcieb->pcieb_init_flags &= flags;
1265 }
1266 
1267 /*
1268  * Checks if this device needs MSIs enabled or not.
1269  */
1270 /*ARGSUSED*/
1271 static int
1272 pcieb_msi_supported(dev_info_t *dip)
1273 {
1274         return ((pcieb_enable_msi && pcieb_plat_msi_supported(dip)) ?
1275             DDI_SUCCESS: DDI_FAILURE);
1276 }
1277 
1278 /*ARGSUSED*/
1279 static int
1280 pcieb_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
1281     ddi_iblock_cookie_t *ibc)
1282 {
1283         pcieb_devstate_t  *pcieb = ddi_get_soft_state(pcieb_state,
1284             ddi_get_instance(dip));
1285 
1286         ASSERT(ibc != NULL);
1287         *ibc = pcieb->pcieb_fm_ibc;
1288 
1289         return (DEVI(dip)->devi_fmhdl->fh_cap | DDI_FM_ACCCHK_CAPABLE |
1290             DDI_FM_DMACHK_CAPABLE);
1291 }
1292 
1293 static int
1294 pcieb_fm_init(pcieb_devstate_t *pcieb_p)
1295 {
1296         dev_info_t      *dip = pcieb_p->pcieb_dip;
1297         int             fm_cap = DDI_FM_EREPORT_CAPABLE;
1298 
1299         /*
1300          * Request our capability level and get our parents capability
1301          * and ibc.
1302          */
1303         ddi_fm_init(dip, &fm_cap, &pcieb_p->pcieb_fm_ibc);
1304 
1305         return (DDI_SUCCESS);
1306 }
1307 
1308 /*
1309  * Breakdown our FMA resources
1310  */
1311 static void
1312 pcieb_fm_fini(pcieb_devstate_t *pcieb_p)
1313 {
1314         /*
1315          * Clean up allocated fm structures
1316          */
1317         ddi_fm_fini(pcieb_p->pcieb_dip);
1318 }
1319 
1320 static int
1321 pcieb_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1322 {
1323         int             inst = PCI_MINOR_NUM_TO_INSTANCE(getminor(*devp));
1324         pcieb_devstate_t        *pcieb = ddi_get_soft_state(pcieb_state, inst);
1325         int     rv;
1326 
1327         if (pcieb == NULL)
1328                 return (ENXIO);
1329 
1330         mutex_enter(&pcieb->pcieb_mutex);
1331         rv = pcie_open(pcieb->pcieb_dip, devp, flags, otyp, credp);
1332         mutex_exit(&pcieb->pcieb_mutex);
1333 
1334         return (rv);
1335 }
1336 
1337 static int
1338 pcieb_close(dev_t dev, int flags, int otyp, cred_t *credp)
1339 {
1340         int             inst = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
1341         pcieb_devstate_t        *pcieb = ddi_get_soft_state(pcieb_state, inst);
1342         int     rv;
1343 
1344         if (pcieb == NULL)
1345                 return (ENXIO);
1346 
1347         mutex_enter(&pcieb->pcieb_mutex);
1348         rv = pcie_close(pcieb->pcieb_dip, dev, flags, otyp, credp);
1349         mutex_exit(&pcieb->pcieb_mutex);
1350 
1351         return (rv);
1352 }
1353 
1354 static int
1355 pcieb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1356         int *rvalp)
1357 {
1358         int             inst = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
1359         pcieb_devstate_t        *pcieb = ddi_get_soft_state(pcieb_state, inst);
1360         int             rv;
1361 
1362         if (pcieb == NULL)
1363                 return (ENXIO);
1364 
1365         /* To handle devctl and hotplug related ioctls */
1366         rv = pcie_ioctl(pcieb->pcieb_dip, dev, cmd, arg, mode, credp, rvalp);
1367 
1368         return (rv);
1369 }
1370 
1371 /*
1372  * Common interrupt handler for hotplug, PME and errors.
1373  */
1374 static uint_t
1375 pcieb_intr_handler(caddr_t arg1, caddr_t arg2)
1376 {
1377         pcieb_devstate_t *pcieb_p = (pcieb_devstate_t *)arg1;
1378         dev_info_t      *dip = pcieb_p->pcieb_dip;
1379         ddi_fm_error_t  derr;
1380         int             sts = 0;
1381         int             ret = DDI_INTR_UNCLAIMED;
1382         int             isrc;
1383 
1384         if (!(pcieb_p->pcieb_init_flags & PCIEB_INIT_ENABLE))
1385                 goto FAIL;
1386 
1387         mutex_enter(&pcieb_p->pcieb_intr_mutex);
1388         isrc = pcieb_p->pcieb_isr_tab[(int)(uintptr_t)arg2];
1389         mutex_exit(&pcieb_p->pcieb_intr_mutex);
1390 
1391         PCIEB_DEBUG(DBG_INTR, dip, "Received intr number %d\n",
1392             (int)(uintptr_t)arg2);
1393 
1394         if (isrc == PCIEB_INTR_SRC_UNKNOWN)
1395                 goto FAIL;
1396 
1397         if (isrc & PCIEB_INTR_SRC_HP)
1398                 ret = pcie_intr(dip);
1399 
1400         if (isrc & PCIEB_INTR_SRC_PME)
1401                 ret = DDI_INTR_CLAIMED;
1402 
1403         /* AER Error */
1404         if (isrc & PCIEB_INTR_SRC_AER) {
1405                 /*
1406                  *  If MSI is shared with PME/hotplug then check Root Error
1407                  *  Status Reg before claiming it. For now it's ok since
1408                  *  we know we get 2 MSIs.
1409                  */
1410                 ret = DDI_INTR_CLAIMED;
1411                 bzero(&derr, sizeof (ddi_fm_error_t));
1412                 derr.fme_version = DDI_FME_VERSION;
1413                 mutex_enter(&pcieb_p->pcieb_peek_poke_mutex);
1414                 mutex_enter(&pcieb_p->pcieb_err_mutex);
1415 
1416                 pf_eh_enter(PCIE_DIP2BUS(dip));
1417                 PCIE_ROOT_EH_SRC(PCIE_DIP2PFD(dip))->intr_type =
1418                     PF_INTR_TYPE_AER;
1419 
1420                 if ((DEVI(dip)->devi_fmhdl->fh_cap) & DDI_FM_EREPORT_CAPABLE)
1421                         sts = pf_scan_fabric(dip, &derr, NULL);
1422                 pf_eh_exit(PCIE_DIP2BUS(dip));
1423 
1424                 mutex_exit(&pcieb_p->pcieb_err_mutex);
1425                 mutex_exit(&pcieb_p->pcieb_peek_poke_mutex);
1426                 if (pcieb_die & sts)
1427                         fm_panic("%s-%d: PCI(-X) Express Fatal Error. (0x%x)",
1428                             ddi_driver_name(dip), ddi_get_instance(dip), sts);
1429         }
1430 FAIL:
1431         return (ret);
1432 }
1433 
1434 /*
1435  * Some PCI-X to PCI-E bridges do not support full 64-bit addressing on the
1436  * PCI-X side of the bridge.  We build a special version of this driver for
1437  * those bridges, which uses PCIEB_ADDR_LIMIT_LO and/or PCIEB_ADDR_LIMIT_HI
1438  * to define the range of values which the chip can handle.  The code below
1439  * then clamps the DMA address range supplied by the driver, preventing the
1440  * PCI-E nexus driver from allocating any memory the bridge can't deal
1441  * with.
1442  */
1443 static int
1444 pcieb_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
1445         ddi_dma_attr_t *attr_p, int (*waitfp)(caddr_t), caddr_t arg,
1446         ddi_dma_handle_t *handlep)
1447 {
1448         int             ret;
1449 #ifdef  PCIEB_BCM
1450         uint64_t        lim;
1451 
1452         /*
1453          * If the leaf device's limits are outside than what the Broadcom
1454          * bridge can handle, we need to clip the values passed up the chain.
1455          */
1456         lim = attr_p->dma_attr_addr_lo;
1457         attr_p->dma_attr_addr_lo = MAX(lim, PCIEB_ADDR_LIMIT_LO);
1458 
1459         lim = attr_p->dma_attr_addr_hi;
1460         attr_p->dma_attr_addr_hi = MIN(lim, PCIEB_ADDR_LIMIT_HI);
1461 
1462 #endif  /* PCIEB_BCM */
1463 
1464         /*
1465          * This is a software workaround to fix the Broadcom 5714/5715 PCIe-PCI
1466          * bridge prefetch bug. Intercept the DMA alloc handle request and set
1467          * PX_DMAI_FLAGS_MAP_BUFZONE flag in the handle. If this flag is set,
1468          * the px nexus driver will allocate an extra page & make it valid one,
1469          * for any DVMA request that comes from any of the Broadcom bridge child
1470          * devices.
1471          */
1472         if ((ret = ddi_dma_allochdl(dip, rdip, attr_p, waitfp, arg,
1473             handlep)) == DDI_SUCCESS) {
1474                 ddi_dma_impl_t  *mp = (ddi_dma_impl_t *)*handlep;
1475 #ifdef  PCIEB_BCM
1476                 mp->dmai_inuse |= PX_DMAI_FLAGS_MAP_BUFZONE;
1477 #endif  /* PCIEB_BCM */
1478                 /*
1479                  * For a given rdip, update mp->dmai_bdf with the bdf value
1480                  * of pcieb's immediate child or secondary bus-id of the
1481                  * PCIe2PCI bridge.
1482                  */
1483                 mp->dmai_minxfer = pcie_get_bdf_for_dma_xfer(dip, rdip);
1484         }
1485 
1486         return (ret);
1487 }
1488 
1489 /*
1490  * FDVMA feature is not supported for any child device of Broadcom 5714/5715
1491  * PCIe-PCI bridge due to prefetch bug. Return failure immediately, so that
1492  * these drivers will switch to regular DVMA path.
1493  */
1494 /*ARGSUSED*/
1495 static int
1496 pcieb_dma_mctl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
1497         enum ddi_dma_ctlops cmd, off_t *offp, size_t *lenp, caddr_t *objp,
1498         uint_t cache_flags)
1499 {
1500         int     ret;
1501 
1502 #ifdef  PCIEB_BCM
1503         if (cmd == DDI_DMA_RESERVE)
1504                 return (DDI_FAILURE);
1505 #endif  /* PCIEB_BCM */
1506 
1507         if (((ret = ddi_dma_mctl(dip, rdip, handle, cmd, offp, lenp, objp,
1508             cache_flags)) == DDI_SUCCESS) && (cmd == DDI_DMA_RESERVE)) {
1509                 ddi_dma_impl_t  *mp = (ddi_dma_impl_t *)*objp;
1510 
1511                 /*
1512                  * For a given rdip, update mp->dmai_bdf with the bdf value
1513                  * of pcieb's immediate child or secondary bus-id of the
1514                  * PCIe2PCI bridge.
1515                  */
1516                 mp->dmai_minxfer = pcie_get_bdf_for_dma_xfer(dip, rdip);
1517         }
1518 
1519         return (ret);
1520 }
1521 
1522 static int
1523 pcieb_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
1524     ddi_intr_handle_impl_t *hdlp, void *result)
1525 {
1526         return (pcieb_plat_intr_ops(dip, rdip, intr_op, hdlp, result));
1527 
1528 }
1529 
1530 /*
1531  * Power management related initialization specific to pcieb.
1532  * Called by pcieb_attach()
1533  */
1534 static int
1535 pcieb_pwr_setup(dev_info_t *dip)
1536 {
1537         char *comp_array[5];
1538         int i;
1539         ddi_acc_handle_t conf_hdl;
1540         uint16_t pmcap, cap_ptr;
1541         pcie_pwr_t *pwr_p;
1542 
1543         /* Some platforms/devices may choose to disable PM */
1544         if (pcieb_plat_pwr_disable(dip)) {
1545                 (void) pcieb_pwr_disable(dip);
1546                 return (DDI_SUCCESS);
1547         }
1548 
1549         ASSERT(PCIE_PMINFO(dip));
1550         pwr_p = PCIE_NEXUS_PMINFO(dip);
1551         ASSERT(pwr_p);
1552 
1553         /* Code taken from pci_pci driver */
1554         if (pci_config_setup(dip, &pwr_p->pwr_conf_hdl) != DDI_SUCCESS) {
1555                 PCIEB_DEBUG(DBG_PWR, dip, "pcieb_pwr_setup: pci_config_setup "
1556                     "failed\n");
1557                 return (DDI_FAILURE);
1558         }
1559         conf_hdl = pwr_p->pwr_conf_hdl;
1560 
1561         /*
1562          * Walk the capabilities searching for a PM entry.
1563          */
1564         if ((PCI_CAP_LOCATE(conf_hdl, PCI_CAP_ID_PM, &cap_ptr)) ==
1565             DDI_FAILURE) {
1566                 PCIEB_DEBUG(DBG_PWR, dip, "switch/bridge does not support PM. "
1567                     " PCI PM data structure not found in config header\n");
1568                 pci_config_teardown(&conf_hdl);
1569                 return (DDI_SUCCESS);
1570         }
1571         /*
1572          * Save offset to pmcsr for future references.
1573          */
1574         pwr_p->pwr_pmcsr_offset = cap_ptr + PCI_PMCSR;
1575         pmcap = PCI_CAP_GET16(conf_hdl, NULL, cap_ptr, PCI_PMCAP);
1576         if (pmcap & PCI_PMCAP_D1) {
1577                 PCIEB_DEBUG(DBG_PWR, dip, "D1 state supported\n");
1578                 pwr_p->pwr_pmcaps |= PCIE_SUPPORTS_D1;
1579         }
1580         if (pmcap & PCI_PMCAP_D2) {
1581                 PCIEB_DEBUG(DBG_PWR, dip, "D2 state supported\n");
1582                 pwr_p->pwr_pmcaps |= PCIE_SUPPORTS_D2;
1583         }
1584 
1585         i = 0;
1586         comp_array[i++] = "NAME=PCIe switch/bridge PM";
1587         comp_array[i++] = "0=Power Off (D3)";
1588         if (pwr_p->pwr_pmcaps & PCIE_SUPPORTS_D2)
1589                 comp_array[i++] = "1=D2";
1590         if (pwr_p->pwr_pmcaps & PCIE_SUPPORTS_D1)
1591                 comp_array[i++] = "2=D1";
1592         comp_array[i++] = "3=Full Power D0";
1593 
1594         /*
1595          * Create pm-components property, if it does not exist already.
1596          */
1597         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
1598             "pm-components", comp_array, i) != DDI_PROP_SUCCESS) {
1599                 PCIEB_DEBUG(DBG_PWR, dip, "could not create pm-components "
1600                     " prop\n");
1601                 pci_config_teardown(&conf_hdl);
1602                 return (DDI_FAILURE);
1603         }
1604         return (pcieb_pwr_init_and_raise(dip, pwr_p));
1605 }
1606 
1607 /*
1608  * undo whatever is done in pcieb_pwr_setup. called by pcieb_detach()
1609  */
1610 static void
1611 pcieb_pwr_teardown(dev_info_t *dip)
1612 {
1613         pcie_pwr_t      *pwr_p;
1614 
1615         if (!PCIE_PMINFO(dip) || !(pwr_p = PCIE_NEXUS_PMINFO(dip)))
1616                 return;
1617 
1618         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components");
1619         if (pwr_p->pwr_conf_hdl)
1620                 pci_config_teardown(&pwr_p->pwr_conf_hdl);
1621 }
1622 
1623 /*
1624  * Initializes the power level and raise the power to D0, if it is
1625  * not at D0.
1626  */
1627 static int
1628 pcieb_pwr_init_and_raise(dev_info_t *dip, pcie_pwr_t *pwr_p)
1629 {
1630         uint16_t pmcsr;
1631         int ret = DDI_SUCCESS;
1632 
1633         /*
1634          * Intialize our power level from PMCSR. The common code initializes
1635          * this to UNKNOWN. There is no guarantee that we will be at full
1636          * power at attach. If we are not at D0, raise the power.
1637          */
1638         pmcsr = pci_config_get16(pwr_p->pwr_conf_hdl, pwr_p->pwr_pmcsr_offset);
1639         pmcsr &= PCI_PMCSR_STATE_MASK;
1640         switch (pmcsr) {
1641         case PCI_PMCSR_D0:
1642                 pwr_p->pwr_func_lvl = PM_LEVEL_D0;
1643                 break;
1644 
1645         case PCI_PMCSR_D1:
1646                 pwr_p->pwr_func_lvl = PM_LEVEL_D1;
1647                 break;
1648 
1649         case PCI_PMCSR_D2:
1650                 pwr_p->pwr_func_lvl = PM_LEVEL_D2;
1651                 break;
1652 
1653         case PCI_PMCSR_D3HOT:
1654                 pwr_p->pwr_func_lvl = PM_LEVEL_D3;
1655                 break;
1656 
1657         default:
1658                 break;
1659         }
1660 
1661         /* Raise the power to D0. */
1662         if (pwr_p->pwr_func_lvl != PM_LEVEL_D0 &&
1663             ((ret = pm_raise_power(dip, 0, PM_LEVEL_D0)) != DDI_SUCCESS)) {
1664                 /*
1665                  * Read PMCSR again. If it is at D0, ignore the return
1666                  * value from pm_raise_power.
1667                  */
1668                 pmcsr = pci_config_get16(pwr_p->pwr_conf_hdl,
1669                     pwr_p->pwr_pmcsr_offset);
1670                 if ((pmcsr & PCI_PMCSR_STATE_MASK) == PCI_PMCSR_D0)
1671                         ret = DDI_SUCCESS;
1672                 else {
1673                         PCIEB_DEBUG(DBG_PWR, dip, "pcieb_pwr_setup: could not "
1674                             "raise power to D0 \n");
1675                 }
1676         }
1677         if (ret == DDI_SUCCESS)
1678                 pwr_p->pwr_func_lvl = PM_LEVEL_D0;
1679         return (ret);
1680 }
1681 
1682 /*
1683  * Disable PM for x86 and PLX 8532 switch.
1684  * For PLX Transitioning one port on this switch to low power causes links
1685  * on other ports on the same station to die. Due to PLX erratum #34, we
1686  * can't allow the downstream device go to non-D0 state.
1687  */
1688 static int
1689 pcieb_pwr_disable(dev_info_t *dip)
1690 {
1691         pcie_pwr_t *pwr_p;
1692 
1693         ASSERT(PCIE_PMINFO(dip));
1694         pwr_p = PCIE_NEXUS_PMINFO(dip);
1695         ASSERT(pwr_p);
1696         PCIEB_DEBUG(DBG_PWR, dip, "pcieb_pwr_disable: disabling PM\n");
1697         pwr_p->pwr_func_lvl = PM_LEVEL_D0;
1698         pwr_p->pwr_flags = PCIE_NO_CHILD_PM;
1699         return (DDI_SUCCESS);
1700 }
1701 
1702 #ifdef DEBUG
1703 int pcieb_dbg_intr_print = 0;
1704 void
1705 pcieb_dbg(uint_t bit, dev_info_t *dip, char *fmt, ...)
1706 {
1707         va_list ap;
1708 
1709         if (!pcieb_dbg_print)
1710                 return;
1711 
1712         if (dip)
1713                 prom_printf("%s(%d): %s", ddi_driver_name(dip),
1714                     ddi_get_instance(dip), pcieb_debug_sym[bit]);
1715 
1716         va_start(ap, fmt);
1717         if (servicing_interrupt()) {
1718                 if (pcieb_dbg_intr_print)
1719                         prom_vprintf(fmt, ap);
1720         } else {
1721                 prom_vprintf(fmt, ap);
1722         }
1723 
1724         va_end(ap);
1725 }
1726 #endif
1727 
1728 static void
1729 pcieb_id_props(pcieb_devstate_t *pcieb)
1730 {
1731         uint64_t serialid = 0;  /* 40b field of EUI-64 serial no. register */
1732         uint16_t cap_ptr;
1733         uint8_t fic = 0;        /* 1 = first in chassis device */
1734         pcie_bus_t *bus_p = PCIE_DIP2BUS(pcieb->pcieb_dip);
1735         ddi_acc_handle_t config_handle = bus_p->bus_cfg_hdl;
1736 
1737         /*
1738          * Identify first in chassis.  In the special case of a Sun branded
1739          * PLX device, it obviously is first in chassis.  Otherwise, in the
1740          * general case, look for an Expansion Slot Register and check its
1741          * first-in-chassis bit.
1742          */
1743 #ifdef  PX_PLX
1744         uint16_t vendor_id = bus_p->bus_dev_ven_id & 0xFFFF;
1745         uint16_t device_id = bus_p->bus_dev_ven_id >> 16;
1746         if ((vendor_id == PXB_VENDOR_SUN) &&
1747             ((device_id == PXB_DEVICE_PLX_PCIX) ||
1748             (device_id == PXB_DEVICE_PLX_PCIE))) {
1749                 fic = 1;
1750         }
1751 #endif  /* PX_PLX */
1752         if ((fic == 0) && ((PCI_CAP_LOCATE(config_handle,
1753             PCI_CAP_ID_SLOT_ID, &cap_ptr)) != DDI_FAILURE)) {
1754                 uint8_t esr = PCI_CAP_GET8(config_handle, NULL,
1755                     cap_ptr, PCI_CAP_ID_REGS_OFF);
1756                 if (PCI_CAPSLOT_FIC(esr))
1757                         fic = 1;
1758         }
1759 
1760         if ((PCI_CAP_LOCATE(config_handle,
1761             PCI_CAP_XCFG_SPC(PCIE_EXT_CAP_ID_SER), &cap_ptr)) != DDI_FAILURE) {
1762                 /* Serialid can be 0 thru a full 40b number */
1763                 serialid = PCI_XCAP_GET32(config_handle, NULL,
1764                     cap_ptr, PCIE_SER_SID_UPPER_DW);
1765                 serialid <<= 32;
1766                 serialid |= PCI_XCAP_GET32(config_handle, NULL,
1767                     cap_ptr, PCIE_SER_SID_LOWER_DW);
1768         }
1769 
1770         if (fic)
1771                 (void) ndi_prop_create_boolean(DDI_DEV_T_NONE, pcieb->pcieb_dip,
1772                     "first-in-chassis");
1773         if (serialid)
1774                 (void) ddi_prop_update_int64(DDI_DEV_T_NONE, pcieb->pcieb_dip,
1775                     "serialid#", serialid);
1776 }
1777 
1778 static void
1779 pcieb_create_ranges_prop(dev_info_t *dip,
1780         ddi_acc_handle_t config_handle)
1781 {
1782         uint32_t base, limit;
1783         ppb_ranges_t    ranges[PCIEB_RANGE_LEN];
1784         uint8_t io_base_lo, io_limit_lo;
1785         uint16_t io_base_hi, io_limit_hi, mem_base, mem_limit;
1786         int i = 0, rangelen = sizeof (ppb_ranges_t)/sizeof (int);
1787 
1788         io_base_lo = pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW);
1789         io_limit_lo = pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW);
1790         io_base_hi = pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI);
1791         io_limit_hi = pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI);
1792         mem_base = pci_config_get16(config_handle, PCI_BCNF_MEM_BASE);
1793         mem_limit = pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT);
1794 
1795         /*
1796          * Create ranges for IO space
1797          */
1798         ranges[i].size_low = ranges[i].size_high = 0;
1799         ranges[i].parent_mid = ranges[i].child_mid = ranges[i].parent_high = 0;
1800         ranges[i].child_high = ranges[i].parent_high |=
1801             (PCI_REG_REL_M | PCI_ADDR_IO);
1802         base = PCIEB_16bit_IOADDR(io_base_lo);
1803         limit = PCIEB_16bit_IOADDR(io_limit_lo);
1804 
1805         if ((io_base_lo & 0xf) == PCIEB_32BIT_IO) {
1806                 base = PCIEB_LADDR(base, io_base_hi);
1807         }
1808         if ((io_limit_lo & 0xf) == PCIEB_32BIT_IO) {
1809                 limit = PCIEB_LADDR(limit, io_limit_hi);
1810         }
1811 
1812         if ((io_base_lo & PCIEB_32BIT_IO) && (io_limit_hi > 0)) {
1813                 base = PCIEB_LADDR(base, io_base_hi);
1814                 limit = PCIEB_LADDR(limit, io_limit_hi);
1815         }
1816 
1817         /*
1818          * Create ranges for 32bit memory space
1819          */
1820         base = PCIEB_32bit_MEMADDR(mem_base);
1821         limit = PCIEB_32bit_MEMADDR(mem_limit);
1822         ranges[i].size_low = ranges[i].size_high = 0;
1823         ranges[i].parent_mid = ranges[i].child_mid = ranges[i].parent_high = 0;
1824         ranges[i].child_high = ranges[i].parent_high |=
1825             (PCI_REG_REL_M | PCI_ADDR_MEM32);
1826         ranges[i].child_low = ranges[i].parent_low = base;
1827         if (limit >= base) {
1828                 ranges[i].size_low = limit - base + PCIEB_MEMGRAIN;
1829                 i++;
1830         }
1831 
1832         if (i) {
1833                 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
1834                     (int *)ranges, i * rangelen);
1835         }
1836 }
1837 
1838 /*
1839  * For PCI and PCI-X devices including PCIe2PCI bridge, initialize
1840  * cache-line-size and latency timer configuration registers.
1841  */
1842 void
1843 pcieb_set_pci_perf_parameters(dev_info_t *dip, ddi_acc_handle_t cfg_hdl)
1844 {
1845         uint_t  n;
1846 
1847         /* Initialize cache-line-size configuration register if needed */
1848         if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1849             "cache-line-size", 0) == 0) {
1850                 pci_config_put8(cfg_hdl, PCI_CONF_CACHE_LINESZ,
1851                     PCIEB_CACHE_LINE_SIZE);
1852                 n = pci_config_get8(cfg_hdl, PCI_CONF_CACHE_LINESZ);
1853                 if (n != 0) {
1854                         (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip,
1855                             "cache-line-size", n);
1856                 }
1857         }
1858 
1859         /* Initialize latency timer configuration registers if needed */
1860         if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1861             "latency-timer", 0) == 0) {
1862                 uchar_t min_gnt, latency_timer;
1863                 uchar_t header_type;
1864 
1865                 /* Determine the configuration header type */
1866                 header_type = pci_config_get8(cfg_hdl, PCI_CONF_HEADER);
1867 
1868                 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
1869                         latency_timer = PCIEB_LATENCY_TIMER;
1870                         pci_config_put8(cfg_hdl, PCI_BCNF_LATENCY_TIMER,
1871                             latency_timer);
1872                 } else {
1873                         min_gnt = pci_config_get8(cfg_hdl, PCI_CONF_MIN_G);
1874                         latency_timer = min_gnt * 8;
1875                 }
1876 
1877                 pci_config_put8(cfg_hdl, PCI_CONF_LATENCY_TIMER,
1878                     latency_timer);
1879                 n = pci_config_get8(cfg_hdl, PCI_CONF_LATENCY_TIMER);
1880                 if (n != 0) {
1881                         (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip,
1882                             "latency-timer", n);
1883                 }
1884         }
1885 }