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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
  27  */
  28 
  29 /*
  30  *      Host to PCI local bus driver
  31  */
  32 
  33 #include <sys/conf.h>
  34 #include <sys/modctl.h>
  35 #include <sys/pci.h>
  36 #include <sys/pci_impl.h>
  37 #include <sys/sysmacros.h>
  38 #include <sys/sunndi.h>
  39 #include <sys/ddifm.h>
  40 #include <sys/ndifm.h>
  41 #include <sys/fm/protocol.h>
  42 #include <sys/hotplug/pci/pcihp.h>
  43 #include <io/pci/pci_common.h>
  44 #include <io/pci/pci_tools_ext.h>
  45 
  46 /* Save minimal state. */
  47 void *pci_statep;
  48 
  49 /*
  50  * Bus Operation functions
  51  */
  52 static int      pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
  53                     off_t, off_t, caddr_t *);
  54 static int      pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
  55                     void *, void *);
  56 static int      pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
  57                     ddi_intr_handle_impl_t *, void *);
  58 static int      pci_fm_init(dev_info_t *, dev_info_t *, int,
  59                     ddi_iblock_cookie_t *);
  60 static int      pci_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
  61 
  62 struct bus_ops pci_bus_ops = {
  63         BUSO_REV,
  64         pci_bus_map,
  65         NULL,
  66         NULL,
  67         NULL,
  68         i_ddi_map_fault,
  69         NULL,
  70         ddi_dma_allochdl,
  71         ddi_dma_freehdl,
  72         ddi_dma_bindhdl,
  73         ddi_dma_unbindhdl,
  74         ddi_dma_flush,
  75         ddi_dma_win,
  76         ddi_dma_mctl,
  77         pci_ctlops,
  78         ddi_bus_prop_op,
  79         0,              /* (*bus_get_eventcookie)();    */
  80         0,              /* (*bus_add_eventcall)();      */
  81         0,              /* (*bus_remove_eventcall)();   */
  82         0,              /* (*bus_post_event)();         */
  83         0,              /* (*bus_intr_ctl)(); */
  84         0,              /* (*bus_config)(); */
  85         0,              /* (*bus_unconfig)(); */
  86         pci_fm_init,    /* (*bus_fm_init)(); */
  87         NULL,           /* (*bus_fm_fini)(); */
  88         NULL,           /* (*bus_fm_access_enter)(); */
  89         NULL,           /* (*bus_fm_access_exit)(); */
  90         NULL,           /* (*bus_power)(); */
  91         pci_intr_ops    /* (*bus_intr_op)(); */
  92 };
  93 
  94 /*
  95  * One goal here is to leverage off of the pcihp.c source without making
  96  * changes to it.  Call into it's cb_ops directly if needed, piggybacking
  97  * anything else needed by the pci_tools.c module.  Only pci_tools and pcihp
  98  * will be opening PCI nexus driver file descriptors.
  99  */
 100 static int      pci_open(dev_t *, int, int, cred_t *);
 101 static int      pci_close(dev_t, int, int, cred_t *);
 102 static int      pci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 103 static int      pci_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
 104                     caddr_t, int *);
 105 static int      pci_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
 106 static void     pci_peekpoke_cb(dev_info_t *, ddi_fm_error_t *);
 107 
 108 struct cb_ops pci_cb_ops = {
 109         pci_open,                       /* open */
 110         pci_close,                      /* close */
 111         nodev,                          /* strategy */
 112         nodev,                          /* print */
 113         nodev,                          /* dump */
 114         nodev,                          /* read */
 115         nodev,                          /* write */
 116         pci_ioctl,                      /* ioctl */
 117         nodev,                          /* devmap */
 118         nodev,                          /* mmap */
 119         nodev,                          /* segmap */
 120         nochpoll,                       /* poll */
 121         pci_prop_op,                    /* cb_prop_op */
 122         NULL,                           /* streamtab */
 123         D_NEW | D_MP | D_HOTPLUG,       /* Driver compatibility flag */
 124         CB_REV,                         /* rev */
 125         nodev,                          /* int (*cb_aread)() */
 126         nodev                           /* int (*cb_awrite)() */
 127 };
 128 
 129 /*
 130  * Device Node Operation functions
 131  */
 132 static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
 133 static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 134 
 135 struct dev_ops pci_ops = {
 136         DEVO_REV,               /* devo_rev */
 137         0,                      /* refcnt  */
 138         pci_info,               /* info */
 139         nulldev,                /* identify */
 140         nulldev,                /* probe */
 141         pci_attach,             /* attach */
 142         pci_detach,             /* detach */
 143         nulldev,                /* reset */
 144         &pci_cb_ops,                /* driver operations */
 145         &pci_bus_ops,               /* bus operations */
 146         NULL,                   /* power */
 147         ddi_quiesce_not_needed          /* quiesce */
 148 };
 149 
 150 /*
 151  * This variable controls the default setting of the command register
 152  * for pci devices.  See pci_initchild() for details.
 153  */
 154 static ushort_t pci_command_default = PCI_COMM_ME |
 155                                         PCI_COMM_MAE |
 156                                         PCI_COMM_IO;
 157 
 158 /*
 159  * Internal routines in support of particular pci_ctlops.
 160  */
 161 static int pci_removechild(dev_info_t *child);
 162 static int pci_initchild(dev_info_t *child);
 163 
 164 /*
 165  * Module linkage information for the kernel.
 166  */
 167 
 168 static struct modldrv modldrv = {
 169         &mod_driverops,                     /* Type of module */
 170         "x86 Host to PCI nexus driver",         /* Name of module */
 171         &pci_ops,                           /* driver ops */
 172 };
 173 
 174 static struct modlinkage modlinkage = {
 175         MODREV_1,
 176         (void *)&modldrv,
 177         NULL
 178 };
 179 
 180 int
 181 _init(void)
 182 {
 183         int e;
 184 
 185         /*
 186          * Initialize per-pci bus soft state pointer.
 187          */
 188         e = ddi_soft_state_init(&pci_statep, sizeof (pci_state_t), 1);
 189         if (e != 0)
 190                 return (e);
 191 
 192         if ((e = mod_install(&modlinkage)) != 0)
 193                 ddi_soft_state_fini(&pci_statep);
 194 
 195         return (e);
 196 }
 197 
 198 int
 199 _fini(void)
 200 {
 201         int rc;
 202 
 203         rc = mod_remove(&modlinkage);
 204         if (rc != 0)
 205                 return (rc);
 206 
 207         ddi_soft_state_fini(&pci_statep);
 208 
 209         return (rc);
 210 }
 211 
 212 int
 213 _info(struct modinfo *modinfop)
 214 {
 215         return (mod_info(&modlinkage, modinfop));
 216 }
 217 
 218 /*ARGSUSED*/
 219 static int
 220 pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
 221 {
 222         /*
 223          * Use the minor number as constructed by pcihp, as the index value to
 224          * ddi_soft_state_zalloc.
 225          */
 226         int instance = ddi_get_instance(devi);
 227         pci_state_t *pcip = NULL;
 228         switch (cmd) {
 229         case DDI_ATTACH:
 230                 break;
 231 
 232         case DDI_RESUME:
 233                 return (DDI_SUCCESS);
 234 
 235         default:
 236                 return (DDI_FAILURE);
 237         }
 238 
 239         if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci")
 240             != DDI_PROP_SUCCESS) {
 241                 cmn_err(CE_WARN, "pci:  'device_type' prop create failed");
 242         }
 243 
 244         if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) {
 245                 pcip = ddi_get_soft_state(pci_statep, instance);
 246         }
 247 
 248         if (pcip == NULL) {
 249                 goto bad_soft_state;
 250         }
 251 
 252         pcip->pci_dip = devi;
 253         pcip->pci_soft_state = PCI_SOFT_STATE_CLOSED;
 254 
 255         /*
 256          * Initialize hotplug support on this bus. At minimum
 257          * (for non hotplug bus) this would create ":devctl" minor
 258          * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
 259          * to this bus.
 260          */
 261         if (pcihp_init(devi) != DDI_SUCCESS) {
 262                 cmn_err(CE_WARN, "pci: Failed to setup hotplug framework");
 263                 goto bad_pcihp_init;
 264         }
 265 
 266         /* Second arg: initialize for pci, not pci_express */
 267         if (pcitool_init(devi, B_FALSE) != DDI_SUCCESS) {
 268                 goto bad_pcitool_init;
 269         }
 270 
 271         pcip->pci_fmcap = DDI_FM_ERRCB_CAPABLE |
 272             DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
 273         ddi_fm_init(devi, &pcip->pci_fmcap, &pcip->pci_fm_ibc);
 274         mutex_init(&pcip->pci_mutex, NULL, MUTEX_DRIVER, NULL);
 275         mutex_init(&pcip->pci_err_mutex, NULL, MUTEX_DRIVER,
 276             (void *)pcip->pci_fm_ibc);
 277         mutex_init(&pcip->pci_peek_poke_mutex, NULL, MUTEX_DRIVER,
 278             (void *)pcip->pci_fm_ibc);
 279         if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
 280                 pci_ereport_setup(devi);
 281                 ddi_fm_handler_register(devi, pci_fm_callback, NULL);
 282         }
 283 
 284         ddi_report_dev(devi);
 285 
 286         return (DDI_SUCCESS);
 287 
 288 bad_pcitool_init:
 289         (void) pcihp_uninit(devi);
 290 bad_pcihp_init:
 291         ddi_soft_state_free(pci_statep, instance);
 292 bad_soft_state:
 293         return (DDI_FAILURE);
 294 }
 295 
 296 /*ARGSUSED*/
 297 static int
 298 pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
 299 {
 300         int instance = ddi_get_instance(devi);
 301         pci_state_t *pcip;
 302 
 303         pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(devi));
 304 
 305 
 306         switch (cmd) {
 307         case DDI_DETACH:
 308                 if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
 309                         ddi_fm_handler_unregister(devi);
 310                         pci_ereport_teardown(devi);
 311                 }
 312                 mutex_destroy(&pcip->pci_peek_poke_mutex);
 313                 mutex_destroy(&pcip->pci_err_mutex);
 314                 mutex_destroy(&pcip->pci_mutex);
 315                 ddi_fm_fini(devi);      /* Uninitialize pcitool support. */
 316                 pcitool_uninit(devi);
 317 
 318                 /* Uninitialize hotplug support on this bus. */
 319                 (void) pcihp_uninit(devi);
 320 
 321                 ddi_soft_state_free(pci_statep, instance);
 322 
 323                 return (DDI_SUCCESS);
 324         case DDI_SUSPEND:
 325                 return (DDI_SUCCESS);
 326         default:
 327                 return (DDI_FAILURE);
 328         }
 329 }
 330 
 331 static int
 332 pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
 333         off_t offset, off_t len, caddr_t *vaddrp)
 334 {
 335         struct regspec reg;
 336         ddi_map_req_t mr;
 337         ddi_acc_hdl_t *hp;
 338         ddi_acc_impl_t *hdlp;
 339         pci_regspec_t pci_reg;
 340         pci_regspec_t *pci_rp;
 341         int     rnumber;
 342         int     length;
 343         pci_acc_cfblk_t *cfp;
 344         int     space;
 345         pci_state_t *pcip;
 346 
 347         mr = *mp; /* Get private copy of request */
 348         mp = &mr;
 349 
 350         if (mp->map_handlep != NULL) {
 351                 pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
 352                 hdlp = (ddi_acc_impl_t *)(mp->map_handlep)->ah_platform_private;
 353                 hdlp->ahi_err_mutexp = &pcip->pci_err_mutex;
 354                 hdlp->ahi_peekpoke_mutexp = &pcip->pci_peek_poke_mutex;
 355                 hdlp->ahi_scan_dip = dip;
 356                 hdlp->ahi_scan = pci_peekpoke_cb;
 357         }
 358 
 359         /*
 360          * check for register number
 361          */
 362         switch (mp->map_type) {
 363         case DDI_MT_REGSPEC:
 364                 pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
 365                 pci_rp = &pci_reg;
 366                 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
 367                         return (DDI_FAILURE);
 368                 break;
 369         case DDI_MT_RNUMBER:
 370                 rnumber = mp->map_obj.rnumber;
 371                 /*
 372                  * get ALL "reg" properties for dip, select the one of
 373                  * of interest. In x86, "assigned-addresses" property
 374                  * is identical to the "reg" property, so there is no
 375                  * need to cross check the two to determine the physical
 376                  * address of the registers.
 377                  * This routine still performs some validity checks to
 378                  * make sure that everything is okay.
 379                  */
 380                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
 381                     DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
 382                     (uint_t *)&length) != DDI_PROP_SUCCESS)
 383                         return (DDI_FAILURE);
 384 
 385                 /*
 386                  * validate the register number.
 387                  */
 388                 length /= (sizeof (pci_regspec_t) / sizeof (int));
 389                 if (rnumber >= length) {
 390                         ddi_prop_free(pci_rp);
 391                         return (DDI_FAILURE);
 392                 }
 393 
 394                 /*
 395                  * copy the required entry.
 396                  */
 397                 pci_reg = pci_rp[rnumber];
 398 
 399                 /*
 400                  * free the memory allocated by ddi_prop_lookup_int_array
 401                  */
 402                 ddi_prop_free(pci_rp);
 403 
 404                 pci_rp = &pci_reg;
 405                 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
 406                         return (DDI_FAILURE);
 407                 mp->map_type = DDI_MT_REGSPEC;
 408                 break;
 409         default:
 410                 return (DDI_ME_INVAL);
 411         }
 412 
 413         space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;
 414 
 415         /*
 416          * check for unmap and unlock of address space
 417          */
 418         if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) {
 419                 /*
 420                  * Adjust offset and length
 421                  * A non-zero length means override the one in the regspec.
 422                  */
 423                 pci_rp->pci_phys_low += (uint_t)offset;
 424                 if (len != 0)
 425                         pci_rp->pci_size_low = len;
 426 
 427                 switch (space) {
 428                 case PCI_ADDR_CONFIG:
 429                         /* No work required on unmap of Config space */
 430                         return (DDI_SUCCESS);
 431 
 432                 case PCI_ADDR_IO:
 433                         reg.regspec_bustype = 1;
 434                         break;
 435 
 436                 case PCI_ADDR_MEM64:
 437                         /*
 438                          * MEM64 requires special treatment on map, to check
 439                          * that the device is below 4G.  On unmap, however,
 440                          * we can assume that everything is OK... the map
 441                          * must have succeeded.
 442                          */
 443                         /* FALLTHROUGH */
 444                 case PCI_ADDR_MEM32:
 445                         reg.regspec_bustype = 0;
 446                         break;
 447 
 448                 default:
 449                         return (DDI_FAILURE);
 450                 }
 451                 reg.regspec_addr = pci_rp->pci_phys_low;
 452                 reg.regspec_size = pci_rp->pci_size_low;
 453 
 454                 mp->map_obj.rp = &reg;
 455                 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
 456 
 457         }
 458 
 459         /* check for user mapping request - not legal for Config */
 460         if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) {
 461                 return (DDI_FAILURE);
 462         }
 463 
 464         /*
 465          * check for config space
 466          * On x86, CONFIG is not mapped via MMU and there is
 467          * no endian-ness issues. Set the attr field in the handle to
 468          * indicate that the common routines to call the nexus driver.
 469          */
 470         if (space == PCI_ADDR_CONFIG) {
 471                 /* Can't map config space without a handle */
 472                 hp = (ddi_acc_hdl_t *)mp->map_handlep;
 473                 if (hp == NULL)
 474                         return (DDI_FAILURE);
 475 
 476                 /* record the device address for future reference */
 477                 cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private;
 478                 cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
 479                 cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
 480                 cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
 481 
 482                 *vaddrp = (caddr_t)offset;
 483                 return (pci_fm_acc_setup(hp, offset, len));
 484         }
 485 
 486         /*
 487          * range check
 488          */
 489         if ((offset >= pci_rp->pci_size_low) ||
 490             (len > pci_rp->pci_size_low) ||
 491             (offset + len > pci_rp->pci_size_low)) {
 492                 return (DDI_FAILURE);
 493         }
 494 
 495         /*
 496          * Adjust offset and length
 497          * A non-zero length means override the one in the regspec.
 498          */
 499         pci_rp->pci_phys_low += (uint_t)offset;
 500         if (len != 0)
 501                 pci_rp->pci_size_low = len;
 502 
 503         /*
 504          * convert the pci regsec into the generic regspec used by the
 505          * parent root nexus driver.
 506          */
 507         switch (space) {
 508         case PCI_ADDR_IO:
 509                 reg.regspec_bustype = 1;
 510                 break;
 511         case PCI_ADDR_MEM64:
 512                 /*
 513                  * We can't handle 64-bit devices that are mapped above
 514                  * 4G or that are larger than 4G.
 515                  */
 516                 if (pci_rp->pci_phys_mid != 0 ||
 517                     pci_rp->pci_size_hi != 0)
 518                         return (DDI_FAILURE);
 519                 /*
 520                  * Other than that, we can treat them as 32-bit mappings
 521                  */
 522                 /* FALLTHROUGH */
 523         case PCI_ADDR_MEM32:
 524                 reg.regspec_bustype = 0;
 525                 break;
 526         default:
 527                 return (DDI_FAILURE);
 528         }
 529         reg.regspec_addr = pci_rp->pci_phys_low;
 530         reg.regspec_size = pci_rp->pci_size_low;
 531 
 532         mp->map_obj.rp = &reg;
 533         return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
 534 }
 535 
 536 
 537 /*ARGSUSED*/
 538 static int
 539 pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
 540         ddi_ctl_enum_t ctlop, void *arg, void *result)
 541 {
 542         pci_regspec_t *drv_regp;
 543         uint_t  reglen;
 544         int     rn;
 545         int     totreg;
 546         pci_state_t *pcip;
 547         struct  attachspec *asp;
 548         struct  detachspec *dsp;
 549 
 550         switch (ctlop) {
 551         case DDI_CTLOPS_REPORTDEV:
 552                 if (rdip == (dev_info_t *)0)
 553                         return (DDI_FAILURE);
 554                 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
 555                     ddi_node_name(rdip), ddi_get_name_addr(rdip),
 556                     ddi_driver_name(rdip),
 557                     ddi_get_instance(rdip));
 558                 return (DDI_SUCCESS);
 559 
 560         case DDI_CTLOPS_INITCHILD:
 561                 return (pci_initchild((dev_info_t *)arg));
 562 
 563         case DDI_CTLOPS_UNINITCHILD:
 564                 return (pci_removechild((dev_info_t *)arg));
 565 
 566         case DDI_CTLOPS_SIDDEV:
 567                 return (DDI_SUCCESS);
 568 
 569         case DDI_CTLOPS_REGSIZE:
 570         case DDI_CTLOPS_NREGS:
 571                 if (rdip == (dev_info_t *)0)
 572                         return (DDI_FAILURE);
 573 
 574                 *(int *)result = 0;
 575                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
 576                     DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
 577                     &reglen) != DDI_PROP_SUCCESS) {
 578                         return (DDI_FAILURE);
 579                 }
 580 
 581                 totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
 582                 if (ctlop == DDI_CTLOPS_NREGS)
 583                         *(int *)result = totreg;
 584                 else if (ctlop == DDI_CTLOPS_REGSIZE) {
 585                         rn = *(int *)arg;
 586                         if (rn >= totreg) {
 587                                 ddi_prop_free(drv_regp);
 588                                 return (DDI_FAILURE);
 589                         }
 590                         *(off_t *)result = drv_regp[rn].pci_size_low;
 591                 }
 592                 ddi_prop_free(drv_regp);
 593 
 594                 return (DDI_SUCCESS);
 595 
 596         case DDI_CTLOPS_POWER: {
 597                 power_req_t     *reqp = (power_req_t *)arg;
 598                 /*
 599                  * We currently understand reporting of PCI_PM_IDLESPEED
 600                  * capability. Everything else is passed up.
 601                  */
 602                 if ((reqp->request_type == PMR_REPORT_PMCAP) &&
 603                     (reqp->req.report_pmcap_req.cap ==  PCI_PM_IDLESPEED)) {
 604 
 605                         return (DDI_SUCCESS);
 606                 }
 607                 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
 608         }
 609 
 610         case DDI_CTLOPS_PEEK:
 611         case DDI_CTLOPS_POKE:
 612                 pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
 613                 return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
 614                     pci_common_peekpoke, &pcip->pci_err_mutex,
 615                     &pcip->pci_peek_poke_mutex, pci_peekpoke_cb));
 616 
 617         /* for now only X86 systems support PME wakeup from suspended state */
 618         case DDI_CTLOPS_ATTACH:
 619                 asp = (struct attachspec *)arg;
 620                 if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
 621                         if (pci_pre_resume(rdip) != DDI_SUCCESS)
 622                                 return (DDI_FAILURE);
 623                 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
 624 
 625         case DDI_CTLOPS_DETACH:
 626                 dsp = (struct detachspec *)arg;
 627                 if (dsp->cmd == DDI_SUSPEND && dsp->when == DDI_POST)
 628                         if (pci_post_suspend(rdip) != DDI_SUCCESS)
 629                                 return (DDI_FAILURE);
 630                 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
 631 
 632         default:
 633                 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
 634         }
 635 
 636         /* NOTREACHED */
 637 
 638 }
 639 
 640 /*
 641  * pci_intr_ops
 642  */
 643 static int
 644 pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
 645     ddi_intr_handle_impl_t *hdlp, void *result)
 646 {
 647         return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));
 648 }
 649 
 650 
 651 static int
 652 pci_initchild(dev_info_t *child)
 653 {
 654         char name[80];
 655         ddi_acc_handle_t config_handle;
 656         ushort_t command_preserve, command;
 657 
 658         if (pci_common_name_child(child, name, 80) != DDI_SUCCESS) {
 659                 return (DDI_FAILURE);
 660         }
 661         ddi_set_name_addr(child, name);
 662 
 663         /*
 664          * Pseudo nodes indicate a prototype node with per-instance
 665          * properties to be merged into the real h/w device node.
 666          * The interpretation of the unit-address is DD[,F]
 667          * where DD is the device id and F is the function.
 668          */
 669         if (ndi_dev_is_persistent_node(child) == 0) {
 670                 extern int pci_allow_pseudo_children;
 671 
 672                 ddi_set_parent_data(child, NULL);
 673 
 674                 /*
 675                  * Try to merge the properties from this prototype
 676                  * node into real h/w nodes.
 677                  */
 678                 if (ndi_merge_node(child, pci_common_name_child) ==
 679                     DDI_SUCCESS) {
 680                         /*
 681                          * Merged ok - return failure to remove the node.
 682                          */
 683                         ddi_set_name_addr(child, NULL);
 684                         return (DDI_FAILURE);
 685                 }
 686 
 687                 /* workaround for ddivs to run under PCI */
 688                 if (pci_allow_pseudo_children) {
 689                         /*
 690                          * If the "interrupts" property doesn't exist,
 691                          * this must be the ddivs no-intr case, and it returns
 692                          * DDI_SUCCESS instead of DDI_FAILURE.
 693                          */
 694                         if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
 695                             DDI_PROP_DONTPASS, "interrupts", -1) == -1)
 696                                 return (DDI_SUCCESS);
 697                         /*
 698                          * Create the ddi_parent_private_data for a pseudo
 699                          * child.
 700                          */
 701                         pci_common_set_parent_private_data(child);
 702                         return (DDI_SUCCESS);
 703                 }
 704 
 705                 /*
 706                  * The child was not merged into a h/w node,
 707                  * but there's not much we can do with it other
 708                  * than return failure to cause the node to be removed.
 709                  */
 710                 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
 711                     ddi_get_name(child), ddi_get_name_addr(child),
 712                     ddi_get_name(child));
 713                 ddi_set_name_addr(child, NULL);
 714                 return (DDI_NOT_WELL_FORMED);
 715         }
 716 
 717         if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
 718             "interrupts", -1) != -1)
 719                 pci_common_set_parent_private_data(child);
 720         else
 721                 ddi_set_parent_data(child, NULL);
 722 
 723         /*
 724          * initialize command register
 725          */
 726         if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
 727                 return (DDI_FAILURE);
 728 
 729         /*
 730          * Support for the "command-preserve" property.
 731          */
 732         command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
 733             DDI_PROP_DONTPASS, "command-preserve", 0);
 734         command = pci_config_get16(config_handle, PCI_CONF_COMM);
 735         command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
 736         command |= (pci_command_default & ~command_preserve);
 737         pci_config_put16(config_handle, PCI_CONF_COMM, command);
 738 
 739         pci_config_teardown(&config_handle);
 740         return (DDI_SUCCESS);
 741 }
 742 
 743 static int
 744 pci_removechild(dev_info_t *dip)
 745 {
 746         struct ddi_parent_private_data *pdptr;
 747 
 748         if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
 749                 kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
 750                 ddi_set_parent_data(dip, NULL);
 751         }
 752         ddi_set_name_addr(dip, NULL);
 753 
 754         /*
 755          * Strip the node to properly convert it back to prototype form
 756          */
 757         ddi_remove_minor_node(dip, NULL);
 758 
 759         impl_rem_dev_props(dip);
 760 
 761         return (DDI_SUCCESS);
 762 }
 763 
 764 
 765 /*
 766  * When retrofitting this module for pci_tools, functions such as open, close,
 767  * and ioctl are now pulled into this module.  Before this, the functions in
 768  * the pcihp module were referenced directly.  Now they are called or
 769  * referenced through the pcihp cb_ops structure from functions in this module.
 770  */
 771 
 772 static int
 773 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
 774 {
 775         return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
 776 }
 777 
 778 static int
 779 pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
 780 {
 781         return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
 782 }
 783 
 784 static int
 785 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
 786 {
 787         minor_t         minor = getminor(dev);
 788         int             instance = PCI_MINOR_NUM_TO_INSTANCE(minor);
 789         pci_state_t     *pci_p = ddi_get_soft_state(pci_statep, instance);
 790         int             ret = ENOTTY;
 791 
 792         if (pci_p == NULL)
 793                 return (ENXIO);
 794 
 795         switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
 796         case PCI_TOOL_REG_MINOR_NUM:
 797         case PCI_TOOL_INTR_MINOR_NUM:
 798                 /* To handle pcitool related ioctls */
 799                 ret =  pci_common_ioctl(pci_p->pci_dip, dev, cmd, arg, mode,
 800                     credp, rvalp);
 801                 break;
 802         default:
 803                 /* To handle devctl and hotplug related ioctls */
 804                 ret = (pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode,
 805                     credp, rvalp);
 806                 break;
 807         }
 808 
 809         return (ret);
 810 }
 811 
 812 
 813 static int
 814 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
 815         int flags, char *name, caddr_t valuep, int *lengthp)
 816 {
 817         return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
 818             name, valuep, lengthp));
 819 }
 820 
 821 static int
 822 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
 823 {
 824         return (pcihp_info(dip, cmd, arg, result));
 825 }
 826 
 827 void pci_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
 828         (void) pci_ereport_post(dip, derr, NULL);
 829 }
 830 
 831 /*ARGSUSED*/
 832 static int
 833 pci_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
 834     ddi_iblock_cookie_t *ibc)
 835 {
 836         pci_state_t  *pcip = ddi_get_soft_state(pci_statep,
 837             ddi_get_instance(dip));
 838 
 839         ASSERT(ibc != NULL);
 840         *ibc = pcip->pci_fm_ibc;
 841 
 842         return (pcip->pci_fmcap);
 843 }
 844 
 845 /*ARGSUSED*/
 846 static int
 847 pci_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used)
 848 {
 849         pci_state_t  *pcip = ddi_get_soft_state(pci_statep,
 850             ddi_get_instance(dip));
 851 
 852         mutex_enter(&pcip->pci_err_mutex);
 853         pci_ereport_post(dip, derr, NULL);
 854         mutex_exit(&pcip->pci_err_mutex);
 855         return (derr->fme_status);
 856 }