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