1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * PCI nexus driver interface 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/conf.h> /* nulldev */ 35*0Sstevel@tonic-gate #include <sys/stat.h> /* devctl */ 36*0Sstevel@tonic-gate #include <sys/kmem.h> 37*0Sstevel@tonic-gate #include <sys/async.h> /* ecc_flt for pci_ecc.h */ 38*0Sstevel@tonic-gate #include <sys/sunddi.h> 39*0Sstevel@tonic-gate #include <sys/sunndi.h> 40*0Sstevel@tonic-gate #include <sys/ndifm.h> 41*0Sstevel@tonic-gate #include <sys/ontrap.h> 42*0Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 43*0Sstevel@tonic-gate #include <sys/ddi_subrdefs.h> 44*0Sstevel@tonic-gate #include <sys/epm.h> 45*0Sstevel@tonic-gate #include <sys/hotplug/pci/pcihp.h> 46*0Sstevel@tonic-gate #include <sys/spl.h> 47*0Sstevel@tonic-gate #include <sys/pci/pci_obj.h> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /*LINTLIBRARY*/ 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate /* 52*0Sstevel@tonic-gate * function prototype for hotplug routine: 53*0Sstevel@tonic-gate */ 54*0Sstevel@tonic-gate static void 55*0Sstevel@tonic-gate pci_init_hotplug(struct pci *); 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate /* 58*0Sstevel@tonic-gate * function prototypes for dev ops routines: 59*0Sstevel@tonic-gate */ 60*0Sstevel@tonic-gate static int pci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 61*0Sstevel@tonic-gate static int pci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 62*0Sstevel@tonic-gate static int pci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 63*0Sstevel@tonic-gate void *arg, void **result); 64*0Sstevel@tonic-gate static int pci_ctlops_poke(pci_t *pci_p, peekpoke_ctlops_t *in_args); 65*0Sstevel@tonic-gate static int pci_ctlops_peek(pci_t *pci_p, peekpoke_ctlops_t *in_args, 66*0Sstevel@tonic-gate void *result); 67*0Sstevel@tonic-gate static off_t get_reg_set_size(dev_info_t *child, int rnumber); 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* 70*0Sstevel@tonic-gate * bus ops and dev ops structures: 71*0Sstevel@tonic-gate */ 72*0Sstevel@tonic-gate static struct bus_ops pci_bus_ops = { 73*0Sstevel@tonic-gate BUSO_REV, 74*0Sstevel@tonic-gate pci_map, 75*0Sstevel@tonic-gate 0, 76*0Sstevel@tonic-gate 0, 77*0Sstevel@tonic-gate 0, 78*0Sstevel@tonic-gate i_ddi_map_fault, 79*0Sstevel@tonic-gate pci_dma_setup, 80*0Sstevel@tonic-gate pci_dma_allochdl, 81*0Sstevel@tonic-gate pci_dma_freehdl, 82*0Sstevel@tonic-gate pci_dma_bindhdl, 83*0Sstevel@tonic-gate pci_dma_unbindhdl, 84*0Sstevel@tonic-gate pci_dma_sync, 85*0Sstevel@tonic-gate pci_dma_win, 86*0Sstevel@tonic-gate pci_dma_ctlops, 87*0Sstevel@tonic-gate pci_ctlops, 88*0Sstevel@tonic-gate ddi_bus_prop_op, 89*0Sstevel@tonic-gate ndi_busop_get_eventcookie, /* (*bus_get_eventcookie)(); */ 90*0Sstevel@tonic-gate ndi_busop_add_eventcall, /* (*bus_add_eventcall)(); */ 91*0Sstevel@tonic-gate ndi_busop_remove_eventcall, /* (*bus_remove_eventcall)(); */ 92*0Sstevel@tonic-gate ndi_post_event, /* (*bus_post_event)(); */ 93*0Sstevel@tonic-gate NULL, /* (*bus_intr_ctl)(); */ 94*0Sstevel@tonic-gate NULL, /* (*bus_config)(); */ 95*0Sstevel@tonic-gate NULL, /* (*bus_unconfig)(); */ 96*0Sstevel@tonic-gate pci_fm_init_child, /* (*bus_fm_init)(); */ 97*0Sstevel@tonic-gate NULL, /* (*bus_fm_fini)(); */ 98*0Sstevel@tonic-gate pci_bus_enter, /* (*bus_fm_access_enter)(); */ 99*0Sstevel@tonic-gate pci_bus_exit, /* (*bus_fm_access_fini)(); */ 100*0Sstevel@tonic-gate NULL, /* (*bus_power)(); */ 101*0Sstevel@tonic-gate pci_intr_ops /* (*bus_intr_op)(); */ 102*0Sstevel@tonic-gate }; 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate extern struct cb_ops pci_cb_ops; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate static struct dev_ops pci_ops = { 107*0Sstevel@tonic-gate DEVO_REV, 108*0Sstevel@tonic-gate 0, 109*0Sstevel@tonic-gate pci_info, 110*0Sstevel@tonic-gate nulldev, 111*0Sstevel@tonic-gate 0, 112*0Sstevel@tonic-gate pci_attach, 113*0Sstevel@tonic-gate pci_detach, 114*0Sstevel@tonic-gate nodev, 115*0Sstevel@tonic-gate &pci_cb_ops, 116*0Sstevel@tonic-gate &pci_bus_ops, 117*0Sstevel@tonic-gate 0 118*0Sstevel@tonic-gate }; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* 121*0Sstevel@tonic-gate * module definitions: 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate #include <sys/modctl.h> 124*0Sstevel@tonic-gate extern struct mod_ops mod_driverops; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate static struct modldrv modldrv = { 127*0Sstevel@tonic-gate &mod_driverops, /* Type of module - driver */ 128*0Sstevel@tonic-gate "PCI Bus nexus driver %I%", /* Name of module. */ 129*0Sstevel@tonic-gate &pci_ops, /* driver ops */ 130*0Sstevel@tonic-gate }; 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 133*0Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 134*0Sstevel@tonic-gate }; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate /* 137*0Sstevel@tonic-gate * driver global data: 138*0Sstevel@tonic-gate */ 139*0Sstevel@tonic-gate void *per_pci_state; /* per-pbm soft state pointer */ 140*0Sstevel@tonic-gate void *per_pci_common_state; /* per-psycho soft state pointer */ 141*0Sstevel@tonic-gate kmutex_t pci_global_mutex; /* attach/detach common struct lock */ 142*0Sstevel@tonic-gate errorq_t *pci_ecc_queue = NULL; /* per-system ecc handling queue */ 143*0Sstevel@tonic-gate errorq_t *pci_target_queue = NULL; /* per-system target handling queue */ 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate extern void pci_child_cfg_save(dev_info_t *dip); 146*0Sstevel@tonic-gate extern void pci_child_cfg_restore(dev_info_t *dip); 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate int 149*0Sstevel@tonic-gate _init(void) 150*0Sstevel@tonic-gate { 151*0Sstevel@tonic-gate int e; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * Initialize per-pci bus soft state pointer. 155*0Sstevel@tonic-gate */ 156*0Sstevel@tonic-gate e = ddi_soft_state_init(&per_pci_state, sizeof (pci_t), 1); 157*0Sstevel@tonic-gate if (e != 0) 158*0Sstevel@tonic-gate return (e); 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * Initialize per-psycho soft state pointer. 162*0Sstevel@tonic-gate */ 163*0Sstevel@tonic-gate e = ddi_soft_state_init(&per_pci_common_state, 164*0Sstevel@tonic-gate sizeof (pci_common_t), 1); 165*0Sstevel@tonic-gate if (e != 0) { 166*0Sstevel@tonic-gate ddi_soft_state_fini(&per_pci_state); 167*0Sstevel@tonic-gate return (e); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* 171*0Sstevel@tonic-gate * Initialize global mutexes. 172*0Sstevel@tonic-gate */ 173*0Sstevel@tonic-gate mutex_init(&pci_global_mutex, NULL, MUTEX_DRIVER, NULL); 174*0Sstevel@tonic-gate pci_reloc_init(); 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate /* 177*0Sstevel@tonic-gate * Create the performance kstats. 178*0Sstevel@tonic-gate */ 179*0Sstevel@tonic-gate pci_kstat_init(); 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate /* 182*0Sstevel@tonic-gate * Install the module. 183*0Sstevel@tonic-gate */ 184*0Sstevel@tonic-gate e = mod_install(&modlinkage); 185*0Sstevel@tonic-gate if (e != 0) { 186*0Sstevel@tonic-gate ddi_soft_state_fini(&per_pci_state); 187*0Sstevel@tonic-gate ddi_soft_state_fini(&per_pci_common_state); 188*0Sstevel@tonic-gate mutex_destroy(&pci_global_mutex); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate return (e); 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate int 194*0Sstevel@tonic-gate _fini(void) 195*0Sstevel@tonic-gate { 196*0Sstevel@tonic-gate int e; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate /* 199*0Sstevel@tonic-gate * Remove the module. 200*0Sstevel@tonic-gate */ 201*0Sstevel@tonic-gate e = mod_remove(&modlinkage); 202*0Sstevel@tonic-gate if (e != 0) 203*0Sstevel@tonic-gate return (e); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate /* 206*0Sstevel@tonic-gate * Destroy pci_ecc_queue, and set it to NULL. 207*0Sstevel@tonic-gate */ 208*0Sstevel@tonic-gate if (pci_ecc_queue) 209*0Sstevel@tonic-gate errorq_destroy(pci_ecc_queue); 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate pci_ecc_queue = NULL; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * Destroy pci_target_queue, and set it to NULL. 215*0Sstevel@tonic-gate */ 216*0Sstevel@tonic-gate if (pci_target_queue) 217*0Sstevel@tonic-gate errorq_destroy(pci_target_queue); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate pci_target_queue = NULL; 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate /* 222*0Sstevel@tonic-gate * Destroy the performance kstats. 223*0Sstevel@tonic-gate */ 224*0Sstevel@tonic-gate pci_kstat_fini(); 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* 227*0Sstevel@tonic-gate * Free the per-pci and per-psycho soft state info and destroy 228*0Sstevel@tonic-gate * mutex for per-psycho soft state. 229*0Sstevel@tonic-gate */ 230*0Sstevel@tonic-gate ddi_soft_state_fini(&per_pci_state); 231*0Sstevel@tonic-gate ddi_soft_state_fini(&per_pci_common_state); 232*0Sstevel@tonic-gate mutex_destroy(&pci_global_mutex); 233*0Sstevel@tonic-gate pci_reloc_fini(); 234*0Sstevel@tonic-gate return (e); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate int 238*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 239*0Sstevel@tonic-gate { 240*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /*ARGSUSED*/ 244*0Sstevel@tonic-gate static int 245*0Sstevel@tonic-gate pci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 246*0Sstevel@tonic-gate { 247*0Sstevel@tonic-gate int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(getminor((dev_t)arg)); 248*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(instance); 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate /* allow hotplug to deal with ones it manages */ 251*0Sstevel@tonic-gate if (pci_p && (pci_p->hotplug_capable == B_TRUE)) 252*0Sstevel@tonic-gate return (pcihp_info(dip, infocmd, arg, result)); 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate /* non-hotplug or not attached */ 255*0Sstevel@tonic-gate switch (infocmd) { 256*0Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 257*0Sstevel@tonic-gate *result = (void *)instance; 258*0Sstevel@tonic-gate return (DDI_SUCCESS); 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 261*0Sstevel@tonic-gate if (pci_p == NULL) 262*0Sstevel@tonic-gate return (DDI_FAILURE); 263*0Sstevel@tonic-gate *result = (void *)pci_p->pci_dip; 264*0Sstevel@tonic-gate return (DDI_SUCCESS); 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate default: 267*0Sstevel@tonic-gate return (DDI_FAILURE); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate /* device driver entry points */ 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * attach entry point: 275*0Sstevel@tonic-gate */ 276*0Sstevel@tonic-gate static int 277*0Sstevel@tonic-gate pci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 278*0Sstevel@tonic-gate { 279*0Sstevel@tonic-gate pci_t *pci_p; /* per bus state pointer */ 280*0Sstevel@tonic-gate int instance = ddi_get_instance(dip); 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate switch (cmd) { 283*0Sstevel@tonic-gate case DDI_ATTACH: 284*0Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "DDI_ATTACH\n"); 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate /* 287*0Sstevel@tonic-gate * Allocate and get the per-pci soft state structure. 288*0Sstevel@tonic-gate */ 289*0Sstevel@tonic-gate if (alloc_pci_soft_state(instance) != DDI_SUCCESS) { 290*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: can't allocate pci state", 291*0Sstevel@tonic-gate ddi_driver_name(dip), instance); 292*0Sstevel@tonic-gate goto err_bad_pci_softstate; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate pci_p = get_pci_soft_state(instance); 295*0Sstevel@tonic-gate pci_p->pci_dip = dip; 296*0Sstevel@tonic-gate mutex_init(&pci_p->pci_mutex, NULL, MUTEX_DRIVER, NULL); 297*0Sstevel@tonic-gate pci_p->pci_soft_state = PCI_SOFT_STATE_CLOSED; 298*0Sstevel@tonic-gate pci_p->pci_open_count = 0; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate /* 301*0Sstevel@tonic-gate * Get key properties of the pci bridge node and 302*0Sstevel@tonic-gate * determine it's type (psycho, schizo, etc ...). 303*0Sstevel@tonic-gate */ 304*0Sstevel@tonic-gate if (get_pci_properties(pci_p, dip) == DDI_FAILURE) 305*0Sstevel@tonic-gate goto err_bad_pci_prop; 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * Map in the registers. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate if (map_pci_registers(pci_p, dip) == DDI_FAILURE) 311*0Sstevel@tonic-gate goto err_bad_reg_prop; 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate if (pci_obj_setup(pci_p) != DDI_SUCCESS) 314*0Sstevel@tonic-gate goto err_bad_objs; 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate /* 317*0Sstevel@tonic-gate * If this PCI leaf has hotplug and this platform 318*0Sstevel@tonic-gate * loads hotplug modules then initialize the 319*0Sstevel@tonic-gate * hotplug framework. 320*0Sstevel@tonic-gate */ 321*0Sstevel@tonic-gate pci_init_hotplug(pci_p); 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate /* 324*0Sstevel@tonic-gate * Create the "devctl" node for hotplug support. 325*0Sstevel@tonic-gate * For non-hotplug bus, we still need ":devctl" to 326*0Sstevel@tonic-gate * support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls. 327*0Sstevel@tonic-gate */ 328*0Sstevel@tonic-gate if (pci_p->hotplug_capable == B_FALSE) { 329*0Sstevel@tonic-gate if (ddi_create_minor_node(dip, "devctl", S_IFCHR, 330*0Sstevel@tonic-gate PCIHP_AP_MINOR_NUM(instance, PCIHP_DEVCTL_MINOR), 331*0Sstevel@tonic-gate DDI_NT_NEXUS, 0) != DDI_SUCCESS) 332*0Sstevel@tonic-gate goto err_bad_devctl_node; 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * Due to unresolved hardware issues, disable PCIPM until 337*0Sstevel@tonic-gate * the problem is fully understood. 338*0Sstevel@tonic-gate * 339*0Sstevel@tonic-gate * pci_pwr_setup(pci_p, dip); 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate ddi_report_dev(dip); 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate pci_p->pci_state = PCI_ATTACHED; 345*0Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "attach success\n"); 346*0Sstevel@tonic-gate break; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate err_bad_objs: 349*0Sstevel@tonic-gate ddi_remove_minor_node(dip, "devctl"); 350*0Sstevel@tonic-gate err_bad_devctl_node: 351*0Sstevel@tonic-gate unmap_pci_registers(pci_p); 352*0Sstevel@tonic-gate err_bad_reg_prop: 353*0Sstevel@tonic-gate free_pci_properties(pci_p); 354*0Sstevel@tonic-gate err_bad_pci_prop: 355*0Sstevel@tonic-gate mutex_destroy(&pci_p->pci_mutex); 356*0Sstevel@tonic-gate free_pci_soft_state(instance); 357*0Sstevel@tonic-gate err_bad_pci_softstate: 358*0Sstevel@tonic-gate return (DDI_FAILURE); 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate case DDI_RESUME: 361*0Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "DDI_RESUME\n"); 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate /* 364*0Sstevel@tonic-gate * Make sure the Psycho control registers and IOMMU 365*0Sstevel@tonic-gate * are configured properly. 366*0Sstevel@tonic-gate */ 367*0Sstevel@tonic-gate pci_p = get_pci_soft_state(instance); 368*0Sstevel@tonic-gate mutex_enter(&pci_p->pci_mutex); 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate /* 371*0Sstevel@tonic-gate * Make sure this instance has been suspended. 372*0Sstevel@tonic-gate */ 373*0Sstevel@tonic-gate if (pci_p->pci_state != PCI_SUSPENDED) { 374*0Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "instance NOT suspended\n"); 375*0Sstevel@tonic-gate mutex_exit(&pci_p->pci_mutex); 376*0Sstevel@tonic-gate return (DDI_FAILURE); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate pci_obj_resume(pci_p); 379*0Sstevel@tonic-gate pci_p->pci_state = PCI_ATTACHED; 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate pci_child_cfg_restore(dip); 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate mutex_exit(&pci_p->pci_mutex); 384*0Sstevel@tonic-gate break; 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate default: 387*0Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "unsupported attach op\n"); 388*0Sstevel@tonic-gate return (DDI_FAILURE); 389*0Sstevel@tonic-gate } 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate return (DDI_SUCCESS); 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* 395*0Sstevel@tonic-gate * detach entry point: 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate static int 398*0Sstevel@tonic-gate pci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 399*0Sstevel@tonic-gate { 400*0Sstevel@tonic-gate int instance = ddi_get_instance(dip); 401*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(instance); 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate /* 404*0Sstevel@tonic-gate * Make sure we are currently attached 405*0Sstevel@tonic-gate */ 406*0Sstevel@tonic-gate if (pci_p->pci_state != PCI_ATTACHED) { 407*0Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "failed - instance not attached\n"); 408*0Sstevel@tonic-gate return (DDI_FAILURE); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate mutex_enter(&pci_p->pci_mutex); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate switch (cmd) { 414*0Sstevel@tonic-gate case DDI_DETACH: 415*0Sstevel@tonic-gate DEBUG0(DBG_DETACH, dip, "DDI_DETACH\n"); 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate if (pci_p->hotplug_capable == B_TRUE) 418*0Sstevel@tonic-gate if (pcihp_uninit(dip) == DDI_FAILURE) { 419*0Sstevel@tonic-gate mutex_exit(&pci_p->pci_mutex); 420*0Sstevel@tonic-gate return (DDI_FAILURE); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate pci_obj_destroy(pci_p); 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * Free the pci soft state structure and the rest of the 427*0Sstevel@tonic-gate * resources it's using. 428*0Sstevel@tonic-gate */ 429*0Sstevel@tonic-gate free_pci_properties(pci_p); 430*0Sstevel@tonic-gate unmap_pci_registers(pci_p); 431*0Sstevel@tonic-gate mutex_exit(&pci_p->pci_mutex); 432*0Sstevel@tonic-gate mutex_destroy(&pci_p->pci_mutex); 433*0Sstevel@tonic-gate free_pci_soft_state(instance); 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate /* Free the interrupt-priorities prop if we created it. */ { 436*0Sstevel@tonic-gate int len; 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate if (ddi_getproplen(DDI_DEV_T_ANY, dip, 439*0Sstevel@tonic-gate DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 440*0Sstevel@tonic-gate "interrupt-priorities", &len) == DDI_PROP_SUCCESS) 441*0Sstevel@tonic-gate (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, 442*0Sstevel@tonic-gate "interrupt-priorities"); 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate return (DDI_SUCCESS); 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate case DDI_SUSPEND: 447*0Sstevel@tonic-gate pci_child_cfg_save(dip); 448*0Sstevel@tonic-gate pci_obj_suspend(pci_p); 449*0Sstevel@tonic-gate pci_p->pci_state = PCI_SUSPENDED; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate mutex_exit(&pci_p->pci_mutex); 452*0Sstevel@tonic-gate return (DDI_SUCCESS); 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate default: 455*0Sstevel@tonic-gate DEBUG0(DBG_DETACH, dip, "unsupported detach op\n"); 456*0Sstevel@tonic-gate mutex_exit(&pci_p->pci_mutex); 457*0Sstevel@tonic-gate return (DDI_FAILURE); 458*0Sstevel@tonic-gate } 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate /* bus driver entry points */ 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate /* 465*0Sstevel@tonic-gate * bus map entry point: 466*0Sstevel@tonic-gate * 467*0Sstevel@tonic-gate * if map request is for an rnumber 468*0Sstevel@tonic-gate * get the corresponding regspec from device node 469*0Sstevel@tonic-gate * build a new regspec in our parent's format 470*0Sstevel@tonic-gate * build a new map_req with the new regspec 471*0Sstevel@tonic-gate * call up the tree to complete the mapping 472*0Sstevel@tonic-gate */ 473*0Sstevel@tonic-gate int 474*0Sstevel@tonic-gate pci_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 475*0Sstevel@tonic-gate off_t off, off_t len, caddr_t *addrp) 476*0Sstevel@tonic-gate { 477*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 478*0Sstevel@tonic-gate struct regspec p_regspec; 479*0Sstevel@tonic-gate ddi_map_req_t p_mapreq; 480*0Sstevel@tonic-gate int reglen, rval, r_no; 481*0Sstevel@tonic-gate pci_regspec_t reloc_reg, *rp = &reloc_reg; 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate DEBUG2(DBG_MAP, dip, "rdip=%s%d:", 484*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip)); 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate if (mp->map_flags & DDI_MF_USER_MAPPING) 487*0Sstevel@tonic-gate return (DDI_ME_UNIMPLEMENTED); 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate switch (mp->map_type) { 490*0Sstevel@tonic-gate case DDI_MT_REGSPEC: 491*0Sstevel@tonic-gate reloc_reg = *(pci_regspec_t *)mp->map_obj.rp; /* dup whole */ 492*0Sstevel@tonic-gate break; 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate case DDI_MT_RNUMBER: 495*0Sstevel@tonic-gate r_no = mp->map_obj.rnumber; 496*0Sstevel@tonic-gate DEBUG1(DBG_MAP | DBG_CONT, dip, " r#=%x", r_no); 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, rdip, DDI_PROP_DONTPASS, 499*0Sstevel@tonic-gate "reg", (caddr_t)&rp, ®len) != DDI_SUCCESS) 500*0Sstevel@tonic-gate return (DDI_ME_RNUMBER_RANGE); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate if (r_no < 0 || r_no >= reglen / sizeof (pci_regspec_t)) { 503*0Sstevel@tonic-gate kmem_free(rp, reglen); 504*0Sstevel@tonic-gate return (DDI_ME_RNUMBER_RANGE); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate rp += r_no; 507*0Sstevel@tonic-gate break; 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate default: 510*0Sstevel@tonic-gate return (DDI_ME_INVAL); 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate DEBUG0(DBG_MAP | DBG_CONT, dip, "\n"); 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate /* use "assigned-addresses" to relocate regspec within pci space */ 515*0Sstevel@tonic-gate if (rval = pci_reloc_reg(dip, rdip, pci_p, rp)) 516*0Sstevel@tonic-gate goto done; 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate if (len) /* adjust regspec according to mapping request */ 519*0Sstevel@tonic-gate rp->pci_size_low = len; 520*0Sstevel@tonic-gate rp->pci_phys_low += off; 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate /* use "ranges" to translate relocated pci regspec into parent space */ 523*0Sstevel@tonic-gate if (rval = pci_xlate_reg(pci_p, rp, &p_regspec)) 524*0Sstevel@tonic-gate goto done; 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate p_mapreq = *mp; /* dup the whole structure */ 527*0Sstevel@tonic-gate p_mapreq.map_type = DDI_MT_REGSPEC; 528*0Sstevel@tonic-gate p_mapreq.map_obj.rp = &p_regspec; 529*0Sstevel@tonic-gate rval = ddi_map(dip, &p_mapreq, 0, 0, addrp); 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate if (rval == DDI_SUCCESS) { 532*0Sstevel@tonic-gate /* 533*0Sstevel@tonic-gate * Set-up access functions for FM access error capable drivers. 534*0Sstevel@tonic-gate * The axq workaround prevents fault management support 535*0Sstevel@tonic-gate */ 536*0Sstevel@tonic-gate if (DDI_FM_ACC_ERR_CAP(pci_p->pci_fm_cap) && 537*0Sstevel@tonic-gate DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)) && 538*0Sstevel@tonic-gate mp->map_handlep->ah_acc.devacc_attr_access != 539*0Sstevel@tonic-gate DDI_DEFAULT_ACC) 540*0Sstevel@tonic-gate pci_fm_acc_setup(mp, rdip); 541*0Sstevel@tonic-gate pci_axq_setup(mp, pci_p->pci_pbm_p); 542*0Sstevel@tonic-gate } 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate done: 545*0Sstevel@tonic-gate if (mp->map_type == DDI_MT_RNUMBER) 546*0Sstevel@tonic-gate kmem_free(rp - r_no, reglen); 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate return (rval); 549*0Sstevel@tonic-gate } 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate /* 552*0Sstevel@tonic-gate * bus dma map entry point 553*0Sstevel@tonic-gate * return value: 554*0Sstevel@tonic-gate * DDI_DMA_PARTIAL_MAP 1 555*0Sstevel@tonic-gate * DDI_DMA_MAPOK 0 556*0Sstevel@tonic-gate * DDI_DMA_MAPPED 0 557*0Sstevel@tonic-gate * DDI_DMA_NORESOURCES -1 558*0Sstevel@tonic-gate * DDI_DMA_NOMAPPING -2 559*0Sstevel@tonic-gate * DDI_DMA_TOOBIG -3 560*0Sstevel@tonic-gate */ 561*0Sstevel@tonic-gate int 562*0Sstevel@tonic-gate pci_dma_setup(dev_info_t *dip, dev_info_t *rdip, ddi_dma_req_t *dmareq, 563*0Sstevel@tonic-gate ddi_dma_handle_t *handlep) 564*0Sstevel@tonic-gate { 565*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 566*0Sstevel@tonic-gate iommu_t *iommu_p = pci_p->pci_iommu_p; 567*0Sstevel@tonic-gate ddi_dma_impl_t *mp; 568*0Sstevel@tonic-gate int ret; 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate DEBUG3(DBG_DMA_MAP, dip, "mapping - rdip=%s%d type=%s\n", 571*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), 572*0Sstevel@tonic-gate handlep ? "alloc" : "advisory"); 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate if (!(mp = pci_dma_lmts2hdl(dip, rdip, iommu_p, dmareq))) 575*0Sstevel@tonic-gate return (DDI_DMA_NORESOURCES); 576*0Sstevel@tonic-gate if (mp == (ddi_dma_impl_t *)DDI_DMA_NOMAPPING) 577*0Sstevel@tonic-gate return (DDI_DMA_NOMAPPING); 578*0Sstevel@tonic-gate if (ret = pci_dma_type(pci_p, dmareq, mp)) 579*0Sstevel@tonic-gate goto freehandle; 580*0Sstevel@tonic-gate if (ret = pci_dma_pfn(pci_p, dmareq, mp)) 581*0Sstevel@tonic-gate goto freehandle; 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate switch (PCI_DMA_TYPE(mp)) { 584*0Sstevel@tonic-gate case DMAI_FLAGS_DVMA: /* LINTED E_EQUALITY_NOT_ASSIGNMENT */ 585*0Sstevel@tonic-gate if ((ret = pci_dvma_win(pci_p, dmareq, mp)) || !handlep) 586*0Sstevel@tonic-gate goto freehandle; 587*0Sstevel@tonic-gate if (!PCI_DMA_CANCACHE(mp)) { /* try fast track */ 588*0Sstevel@tonic-gate if (PCI_DMA_CANFAST(mp)) { 589*0Sstevel@tonic-gate if (!pci_dvma_map_fast(iommu_p, mp)) 590*0Sstevel@tonic-gate break; 591*0Sstevel@tonic-gate /* LINTED E_NOP_ELSE_STMT */ 592*0Sstevel@tonic-gate } else { 593*0Sstevel@tonic-gate PCI_DVMA_FASTTRAK_PROF(mp); 594*0Sstevel@tonic-gate } 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate if (ret = pci_dvma_map(mp, dmareq, iommu_p)) 597*0Sstevel@tonic-gate goto freehandle; 598*0Sstevel@tonic-gate break; 599*0Sstevel@tonic-gate case DMAI_FLAGS_PEER_TO_PEER: /* LINTED E_EQUALITY_NOT_ASSIGNMENT */ 600*0Sstevel@tonic-gate if ((ret = pci_dma_physwin(pci_p, dmareq, mp)) || !handlep) 601*0Sstevel@tonic-gate goto freehandle; 602*0Sstevel@tonic-gate break; 603*0Sstevel@tonic-gate case DMAI_FLAGS_BYPASS: 604*0Sstevel@tonic-gate default: 605*0Sstevel@tonic-gate panic("%s%d: pci_dma_setup: bad dma type 0x%x", 606*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), 607*0Sstevel@tonic-gate PCI_DMA_TYPE(mp)); 608*0Sstevel@tonic-gate /*NOTREACHED*/ 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate *handlep = (ddi_dma_handle_t)mp; 611*0Sstevel@tonic-gate mp->dmai_flags |= (DMAI_FLAGS_INUSE | DMAI_FLAGS_MAPPED); 612*0Sstevel@tonic-gate dump_dma_handle(DBG_DMA_MAP, dip, mp); 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate return ((mp->dmai_nwin == 1) ? DDI_DMA_MAPPED : DDI_DMA_PARTIAL_MAP); 615*0Sstevel@tonic-gate freehandle: 616*0Sstevel@tonic-gate if (ret == DDI_DMA_NORESOURCES) 617*0Sstevel@tonic-gate pci_dma_freemp(mp); /* don't run_callback() */ 618*0Sstevel@tonic-gate else 619*0Sstevel@tonic-gate (void) pci_dma_freehdl(dip, rdip, (ddi_dma_handle_t)mp); 620*0Sstevel@tonic-gate return (ret); 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate /* 625*0Sstevel@tonic-gate * bus dma alloc handle entry point: 626*0Sstevel@tonic-gate */ 627*0Sstevel@tonic-gate int 628*0Sstevel@tonic-gate pci_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp, 629*0Sstevel@tonic-gate int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 630*0Sstevel@tonic-gate { 631*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 632*0Sstevel@tonic-gate ddi_dma_impl_t *mp; 633*0Sstevel@tonic-gate int rval; 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate DEBUG2(DBG_DMA_ALLOCH, dip, "rdip=%s%d\n", 636*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip)); 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate if (attrp->dma_attr_version != DMA_ATTR_V0) 639*0Sstevel@tonic-gate return (DDI_DMA_BADATTR); 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate if (!(mp = pci_dma_allocmp(dip, rdip, waitfp, arg))) 642*0Sstevel@tonic-gate return (DDI_DMA_NORESOURCES); 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate /* 645*0Sstevel@tonic-gate * Save requestor's information 646*0Sstevel@tonic-gate */ 647*0Sstevel@tonic-gate mp->dmai_attr = *attrp; /* whole object - augmented later */ 648*0Sstevel@tonic-gate *DEV_ATTR(mp) = *attrp; /* whole object - device orig attr */ 649*0Sstevel@tonic-gate DEBUG1(DBG_DMA_ALLOCH, dip, "mp=%p\n", mp); 650*0Sstevel@tonic-gate 651*0Sstevel@tonic-gate /* check and convert dma attributes to handle parameters */ 652*0Sstevel@tonic-gate if (rval = pci_dma_attr2hdl(pci_p, mp)) { 653*0Sstevel@tonic-gate pci_dma_freehdl(dip, rdip, (ddi_dma_handle_t)mp); 654*0Sstevel@tonic-gate *handlep = NULL; 655*0Sstevel@tonic-gate return (rval); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate *handlep = (ddi_dma_handle_t)mp; 658*0Sstevel@tonic-gate return (DDI_SUCCESS); 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate /* 663*0Sstevel@tonic-gate * bus dma free handle entry point: 664*0Sstevel@tonic-gate */ 665*0Sstevel@tonic-gate /*ARGSUSED*/ 666*0Sstevel@tonic-gate int 667*0Sstevel@tonic-gate pci_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) 668*0Sstevel@tonic-gate { 669*0Sstevel@tonic-gate DEBUG3(DBG_DMA_FREEH, dip, "rdip=%s%d mp=%p\n", 670*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), handle); 671*0Sstevel@tonic-gate pci_dma_freemp((ddi_dma_impl_t *)handle); 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate if (pci_kmem_clid) { 674*0Sstevel@tonic-gate DEBUG0(DBG_DMA_FREEH, dip, "run handle callback\n"); 675*0Sstevel@tonic-gate ddi_run_callback(&pci_kmem_clid); 676*0Sstevel@tonic-gate } 677*0Sstevel@tonic-gate return (DDI_SUCCESS); 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate /* 682*0Sstevel@tonic-gate * bus dma bind handle entry point: 683*0Sstevel@tonic-gate */ 684*0Sstevel@tonic-gate int 685*0Sstevel@tonic-gate pci_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 686*0Sstevel@tonic-gate ddi_dma_handle_t handle, ddi_dma_req_t *dmareq, 687*0Sstevel@tonic-gate ddi_dma_cookie_t *cookiep, uint_t *ccountp) 688*0Sstevel@tonic-gate { 689*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 690*0Sstevel@tonic-gate iommu_t *iommu_p = pci_p->pci_iommu_p; 691*0Sstevel@tonic-gate ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; 692*0Sstevel@tonic-gate int ret; 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate DEBUG4(DBG_DMA_BINDH, dip, "rdip=%s%d mp=%p dmareq=%p\n", 695*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), mp, dmareq); 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate if (mp->dmai_flags & DMAI_FLAGS_INUSE) 698*0Sstevel@tonic-gate return (DDI_DMA_INUSE); 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate ASSERT((mp->dmai_flags & ~DMAI_FLAGS_PRESERVE) == 0); 701*0Sstevel@tonic-gate mp->dmai_flags |= DMAI_FLAGS_INUSE; 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate if (ret = pci_dma_type(pci_p, dmareq, mp)) 704*0Sstevel@tonic-gate goto err; 705*0Sstevel@tonic-gate if (ret = pci_dma_pfn(pci_p, dmareq, mp)) 706*0Sstevel@tonic-gate goto err; 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate switch (PCI_DMA_TYPE(mp)) { 709*0Sstevel@tonic-gate case DMAI_FLAGS_DVMA: 710*0Sstevel@tonic-gate if (ret = pci_dvma_win(pci_p, dmareq, mp)) 711*0Sstevel@tonic-gate goto map_err; 712*0Sstevel@tonic-gate if (!PCI_DMA_CANCACHE(mp)) { /* try fast track */ 713*0Sstevel@tonic-gate if (PCI_DMA_CANFAST(mp)) { 714*0Sstevel@tonic-gate if (!pci_dvma_map_fast(iommu_p, mp)) 715*0Sstevel@tonic-gate goto mapped; /*LINTED E_NOP_ELSE_STMT*/ 716*0Sstevel@tonic-gate } else { 717*0Sstevel@tonic-gate PCI_DVMA_FASTTRAK_PROF(mp); 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate if (ret = pci_dvma_map(mp, dmareq, iommu_p)) 721*0Sstevel@tonic-gate goto map_err; 722*0Sstevel@tonic-gate mapped: 723*0Sstevel@tonic-gate *ccountp = 1; 724*0Sstevel@tonic-gate MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping, mp->dmai_size); 725*0Sstevel@tonic-gate break; 726*0Sstevel@tonic-gate case DMAI_FLAGS_BYPASS: 727*0Sstevel@tonic-gate case DMAI_FLAGS_PEER_TO_PEER: 728*0Sstevel@tonic-gate if (ret = pci_dma_physwin(pci_p, dmareq, mp)) 729*0Sstevel@tonic-gate goto map_err; 730*0Sstevel@tonic-gate *ccountp = WINLST(mp)->win_ncookies; 731*0Sstevel@tonic-gate *cookiep = *(ddi_dma_cookie_t *)(WINLST(mp) + 1); /* wholeobj */ 732*0Sstevel@tonic-gate break; 733*0Sstevel@tonic-gate default: 734*0Sstevel@tonic-gate panic("%s%d: pci_dma_bindhdl(%p): bad dma type", 735*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), mp); 736*0Sstevel@tonic-gate /*NOTREACHED*/ 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate DEBUG2(DBG_DMA_BINDH, dip, "cookie %x+%x\n", cookiep->dmac_address, 739*0Sstevel@tonic-gate cookiep->dmac_size); 740*0Sstevel@tonic-gate dump_dma_handle(DBG_DMA_MAP, dip, mp); 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate if (mp->dmai_attr.dma_attr_flags & DDI_DMA_FLAGERR) 743*0Sstevel@tonic-gate (void) ndi_fmc_insert(rdip, DMA_HANDLE, mp, NULL); 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate mp->dmai_flags |= DMAI_FLAGS_MAPPED; 746*0Sstevel@tonic-gate return (mp->dmai_nwin == 1 ? DDI_DMA_MAPPED : DDI_DMA_PARTIAL_MAP); 747*0Sstevel@tonic-gate map_err: 748*0Sstevel@tonic-gate pci_dvma_unregister_callbacks(pci_p, mp); 749*0Sstevel@tonic-gate pci_dma_freepfn(mp); 750*0Sstevel@tonic-gate err: 751*0Sstevel@tonic-gate mp->dmai_flags &= DMAI_FLAGS_PRESERVE; 752*0Sstevel@tonic-gate return (ret); 753*0Sstevel@tonic-gate } 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate /* 756*0Sstevel@tonic-gate * bus dma unbind handle entry point: 757*0Sstevel@tonic-gate */ 758*0Sstevel@tonic-gate /*ARGSUSED*/ 759*0Sstevel@tonic-gate int 760*0Sstevel@tonic-gate pci_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) 761*0Sstevel@tonic-gate { 762*0Sstevel@tonic-gate ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; 763*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 764*0Sstevel@tonic-gate iommu_t *iommu_p = pci_p->pci_iommu_p; 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate DEBUG3(DBG_DMA_UNBINDH, dip, "rdip=%s%d, mp=%p\n", 767*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), handle); 768*0Sstevel@tonic-gate if ((mp->dmai_flags & DMAI_FLAGS_INUSE) == 0) { 769*0Sstevel@tonic-gate DEBUG0(DBG_DMA_UNBINDH, dip, "handle not in use\n"); 770*0Sstevel@tonic-gate return (DDI_FAILURE); 771*0Sstevel@tonic-gate } 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate mp->dmai_flags &= ~DMAI_FLAGS_MAPPED; 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate switch (PCI_DMA_TYPE(mp)) { 776*0Sstevel@tonic-gate case DMAI_FLAGS_DVMA: 777*0Sstevel@tonic-gate pci_dvma_unregister_callbacks(pci_p, mp); 778*0Sstevel@tonic-gate pci_dma_sync_unmap(dip, rdip, mp); 779*0Sstevel@tonic-gate pci_dvma_unmap(iommu_p, mp); 780*0Sstevel@tonic-gate pci_dma_freepfn(mp); 781*0Sstevel@tonic-gate break; 782*0Sstevel@tonic-gate case DMAI_FLAGS_BYPASS: 783*0Sstevel@tonic-gate case DMAI_FLAGS_PEER_TO_PEER: 784*0Sstevel@tonic-gate pci_dma_freewin(mp); 785*0Sstevel@tonic-gate break; 786*0Sstevel@tonic-gate default: 787*0Sstevel@tonic-gate panic("%s%d: pci_dma_unbindhdl:bad dma type %p", 788*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), mp); 789*0Sstevel@tonic-gate /*NOTREACHED*/ 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate if (iommu_p->iommu_dvma_clid != 0) { 792*0Sstevel@tonic-gate DEBUG0(DBG_DMA_UNBINDH, dip, "run dvma callback\n"); 793*0Sstevel@tonic-gate ddi_run_callback(&iommu_p->iommu_dvma_clid); 794*0Sstevel@tonic-gate } 795*0Sstevel@tonic-gate if (pci_kmem_clid) { 796*0Sstevel@tonic-gate DEBUG0(DBG_DMA_UNBINDH, dip, "run handle callback\n"); 797*0Sstevel@tonic-gate ddi_run_callback(&pci_kmem_clid); 798*0Sstevel@tonic-gate } 799*0Sstevel@tonic-gate mp->dmai_flags &= DMAI_FLAGS_PRESERVE; 800*0Sstevel@tonic-gate SYNC_BUF_PA(mp) = 0; 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate if (mp->dmai_attr.dma_attr_flags & DDI_DMA_FLAGERR) { 803*0Sstevel@tonic-gate if (DEVI(rdip)->devi_fmhdl != NULL && 804*0Sstevel@tonic-gate DDI_FM_DMA_ERR_CAP(DEVI(rdip)->devi_fmhdl->fh_cap)) { 805*0Sstevel@tonic-gate (void) ndi_fmc_remove(rdip, DMA_HANDLE, mp); 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate } 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate return (DDI_SUCCESS); 810*0Sstevel@tonic-gate } 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate /* 814*0Sstevel@tonic-gate * bus dma win entry point: 815*0Sstevel@tonic-gate */ 816*0Sstevel@tonic-gate int 817*0Sstevel@tonic-gate pci_dma_win(dev_info_t *dip, dev_info_t *rdip, 818*0Sstevel@tonic-gate ddi_dma_handle_t handle, uint_t win, off_t *offp, 819*0Sstevel@tonic-gate size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 820*0Sstevel@tonic-gate { 821*0Sstevel@tonic-gate ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; 822*0Sstevel@tonic-gate DEBUG2(DBG_DMA_WIN, dip, "rdip=%s%d\n", 823*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip)); 824*0Sstevel@tonic-gate dump_dma_handle(DBG_DMA_WIN, dip, mp); 825*0Sstevel@tonic-gate if (win >= mp->dmai_nwin) { 826*0Sstevel@tonic-gate DEBUG1(DBG_DMA_WIN, dip, "%x out of range\n", win); 827*0Sstevel@tonic-gate return (DDI_FAILURE); 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate 830*0Sstevel@tonic-gate switch (PCI_DMA_TYPE(mp)) { 831*0Sstevel@tonic-gate case DMAI_FLAGS_DVMA: 832*0Sstevel@tonic-gate if (win != PCI_DMA_CURWIN(mp)) { 833*0Sstevel@tonic-gate pci_t *pci_p = 834*0Sstevel@tonic-gate get_pci_soft_state(ddi_get_instance(dip)); 835*0Sstevel@tonic-gate pci_dma_sync_unmap(dip, rdip, mp); 836*0Sstevel@tonic-gate /* map_window sets dmai_mapping/size/offset */ 837*0Sstevel@tonic-gate iommu_map_window(pci_p->pci_iommu_p, mp, win); 838*0Sstevel@tonic-gate } 839*0Sstevel@tonic-gate if (cookiep) 840*0Sstevel@tonic-gate MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping, 841*0Sstevel@tonic-gate mp->dmai_size); 842*0Sstevel@tonic-gate if (ccountp) 843*0Sstevel@tonic-gate *ccountp = 1; 844*0Sstevel@tonic-gate break; 845*0Sstevel@tonic-gate case DMAI_FLAGS_PEER_TO_PEER: 846*0Sstevel@tonic-gate case DMAI_FLAGS_BYPASS: { 847*0Sstevel@tonic-gate int i; 848*0Sstevel@tonic-gate ddi_dma_cookie_t *ck_p; 849*0Sstevel@tonic-gate pci_dma_win_t *win_p = mp->dmai_winlst; 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate for (i = 0; i < win; win_p = win_p->win_next, i++); 852*0Sstevel@tonic-gate ck_p = (ddi_dma_cookie_t *)(win_p + 1); 853*0Sstevel@tonic-gate *cookiep = *ck_p; 854*0Sstevel@tonic-gate mp->dmai_offset = win_p->win_offset; 855*0Sstevel@tonic-gate mp->dmai_size = win_p->win_size; 856*0Sstevel@tonic-gate mp->dmai_mapping = ck_p->dmac_laddress; 857*0Sstevel@tonic-gate mp->dmai_cookie = ck_p + 1; 858*0Sstevel@tonic-gate win_p->win_curseg = 0; 859*0Sstevel@tonic-gate if (ccountp) 860*0Sstevel@tonic-gate *ccountp = win_p->win_ncookies; 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate break; 863*0Sstevel@tonic-gate default: 864*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: pci_dma_win:bad dma type 0x%x", 865*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), 866*0Sstevel@tonic-gate PCI_DMA_TYPE(mp)); 867*0Sstevel@tonic-gate return (DDI_FAILURE); 868*0Sstevel@tonic-gate } 869*0Sstevel@tonic-gate if (cookiep) 870*0Sstevel@tonic-gate DEBUG2(DBG_DMA_WIN, dip, 871*0Sstevel@tonic-gate "cookie - dmac_address=%x dmac_size=%x\n", 872*0Sstevel@tonic-gate cookiep->dmac_address, cookiep->dmac_size); 873*0Sstevel@tonic-gate if (offp) 874*0Sstevel@tonic-gate *offp = (off_t)mp->dmai_offset; 875*0Sstevel@tonic-gate if (lenp) 876*0Sstevel@tonic-gate *lenp = mp->dmai_size; 877*0Sstevel@tonic-gate return (DDI_SUCCESS); 878*0Sstevel@tonic-gate } 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate #ifdef DEBUG 881*0Sstevel@tonic-gate static char *pci_dmactl_str[] = { 882*0Sstevel@tonic-gate "DDI_DMA_FREE", 883*0Sstevel@tonic-gate "DDI_DMA_SYNC", 884*0Sstevel@tonic-gate "DDI_DMA_HTOC", 885*0Sstevel@tonic-gate "DDI_DMA_KVADDR", 886*0Sstevel@tonic-gate "DDI_DMA_MOVWIN", 887*0Sstevel@tonic-gate "DDI_DMA_REPWIN", 888*0Sstevel@tonic-gate "DDI_DMA_GETERR", 889*0Sstevel@tonic-gate "DDI_DMA_COFF", 890*0Sstevel@tonic-gate "DDI_DMA_NEXTWIN", 891*0Sstevel@tonic-gate "DDI_DMA_NEXTSEG", 892*0Sstevel@tonic-gate "DDI_DMA_SEGTOC", 893*0Sstevel@tonic-gate "DDI_DMA_RESERVE", 894*0Sstevel@tonic-gate "DDI_DMA_RELEASE", 895*0Sstevel@tonic-gate "DDI_DMA_RESETH", 896*0Sstevel@tonic-gate "DDI_DMA_CKSYNC", 897*0Sstevel@tonic-gate "DDI_DMA_IOPB_ALLOC", 898*0Sstevel@tonic-gate "DDI_DMA_IOPB_FREE", 899*0Sstevel@tonic-gate "DDI_DMA_SMEM_ALLOC", 900*0Sstevel@tonic-gate "DDI_DMA_SMEM_FREE", 901*0Sstevel@tonic-gate "DDI_DMA_SET_SBUS64", 902*0Sstevel@tonic-gate "DDI_DMA_REMAP" 903*0Sstevel@tonic-gate }; 904*0Sstevel@tonic-gate #endif 905*0Sstevel@tonic-gate 906*0Sstevel@tonic-gate /* 907*0Sstevel@tonic-gate * bus dma control entry point: 908*0Sstevel@tonic-gate */ 909*0Sstevel@tonic-gate int 910*0Sstevel@tonic-gate pci_dma_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle, 911*0Sstevel@tonic-gate enum ddi_dma_ctlops cmd, off_t *offp, size_t *lenp, caddr_t *objp, 912*0Sstevel@tonic-gate uint_t cache_flags) 913*0Sstevel@tonic-gate { 914*0Sstevel@tonic-gate ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; 915*0Sstevel@tonic-gate DEBUG3(DBG_DMA_CTL, dip, "%s: rdip=%s%d\n", pci_dmactl_str[cmd], 916*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip)); 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate switch (cmd) { 919*0Sstevel@tonic-gate case DDI_DMA_FREE: 920*0Sstevel@tonic-gate (void) pci_dma_unbindhdl(dip, rdip, handle); 921*0Sstevel@tonic-gate (void) pci_dma_freehdl(dip, rdip, handle); 922*0Sstevel@tonic-gate return (DDI_SUCCESS); 923*0Sstevel@tonic-gate case DDI_DMA_RESERVE: { 924*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 925*0Sstevel@tonic-gate return (pci_fdvma_reserve(dip, rdip, pci_p, 926*0Sstevel@tonic-gate (ddi_dma_req_t *)offp, (ddi_dma_handle_t *)objp)); 927*0Sstevel@tonic-gate } 928*0Sstevel@tonic-gate case DDI_DMA_RELEASE: { 929*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 930*0Sstevel@tonic-gate return (pci_fdvma_release(dip, pci_p, mp)); 931*0Sstevel@tonic-gate } 932*0Sstevel@tonic-gate default: 933*0Sstevel@tonic-gate break; 934*0Sstevel@tonic-gate } 935*0Sstevel@tonic-gate 936*0Sstevel@tonic-gate switch (PCI_DMA_TYPE(mp)) { 937*0Sstevel@tonic-gate case DMAI_FLAGS_DVMA: 938*0Sstevel@tonic-gate return (pci_dvma_ctl(dip, rdip, mp, cmd, offp, lenp, objp, 939*0Sstevel@tonic-gate cache_flags)); 940*0Sstevel@tonic-gate case DMAI_FLAGS_PEER_TO_PEER: 941*0Sstevel@tonic-gate case DMAI_FLAGS_BYPASS: 942*0Sstevel@tonic-gate return (pci_dma_ctl(dip, rdip, mp, cmd, offp, lenp, objp, 943*0Sstevel@tonic-gate cache_flags)); 944*0Sstevel@tonic-gate default: 945*0Sstevel@tonic-gate panic("%s%d: pci_dma_ctlops(%x):bad dma type %x", 946*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip), cmd, 947*0Sstevel@tonic-gate mp->dmai_flags); 948*0Sstevel@tonic-gate /*NOTREACHED*/ 949*0Sstevel@tonic-gate } 950*0Sstevel@tonic-gate } 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate #ifdef DEBUG 953*0Sstevel@tonic-gate int pci_peekfault_cnt = 0; 954*0Sstevel@tonic-gate int pci_pokefault_cnt = 0; 955*0Sstevel@tonic-gate #endif /* DEBUG */ 956*0Sstevel@tonic-gate 957*0Sstevel@tonic-gate static int 958*0Sstevel@tonic-gate pci_do_poke(pci_t *pci_p, peekpoke_ctlops_t *in_args) 959*0Sstevel@tonic-gate { 960*0Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p; 961*0Sstevel@tonic-gate int err = DDI_SUCCESS; 962*0Sstevel@tonic-gate on_trap_data_t otd; 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate mutex_enter(&pbm_p->pbm_pokefault_mutex); 965*0Sstevel@tonic-gate pbm_p->pbm_ontrap_data = &otd; 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate /* Set up protected environment. */ 968*0Sstevel@tonic-gate if (!on_trap(&otd, OT_DATA_ACCESS)) { 969*0Sstevel@tonic-gate uintptr_t tramp = otd.ot_trampoline; 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&poke_fault; 972*0Sstevel@tonic-gate err = do_poke(in_args->size, (void *)in_args->dev_addr, 973*0Sstevel@tonic-gate (void *)in_args->host_addr); 974*0Sstevel@tonic-gate otd.ot_trampoline = tramp; 975*0Sstevel@tonic-gate } else 976*0Sstevel@tonic-gate err = DDI_FAILURE; 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate /* 979*0Sstevel@tonic-gate * Read the async fault register for the PBM to see it sees 980*0Sstevel@tonic-gate * a master-abort. 981*0Sstevel@tonic-gate */ 982*0Sstevel@tonic-gate pbm_clear_error(pbm_p); 983*0Sstevel@tonic-gate 984*0Sstevel@tonic-gate if (otd.ot_trap & OT_DATA_ACCESS) 985*0Sstevel@tonic-gate err = DDI_FAILURE; 986*0Sstevel@tonic-gate 987*0Sstevel@tonic-gate /* Take down protected environment. */ 988*0Sstevel@tonic-gate no_trap(); 989*0Sstevel@tonic-gate 990*0Sstevel@tonic-gate pbm_p->pbm_ontrap_data = NULL; 991*0Sstevel@tonic-gate mutex_exit(&pbm_p->pbm_pokefault_mutex); 992*0Sstevel@tonic-gate 993*0Sstevel@tonic-gate #ifdef DEBUG 994*0Sstevel@tonic-gate if (err == DDI_FAILURE) 995*0Sstevel@tonic-gate pci_pokefault_cnt++; 996*0Sstevel@tonic-gate #endif 997*0Sstevel@tonic-gate return (err); 998*0Sstevel@tonic-gate } 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate static int 1002*0Sstevel@tonic-gate pci_do_caut_put(pci_t *pci_p, peekpoke_ctlops_t *cautacc_ctlops_arg) 1003*0Sstevel@tonic-gate { 1004*0Sstevel@tonic-gate size_t size = cautacc_ctlops_arg->size; 1005*0Sstevel@tonic-gate uintptr_t dev_addr = cautacc_ctlops_arg->dev_addr; 1006*0Sstevel@tonic-gate uintptr_t host_addr = cautacc_ctlops_arg->host_addr; 1007*0Sstevel@tonic-gate ddi_acc_impl_t *hp = (ddi_acc_impl_t *)cautacc_ctlops_arg->handle; 1008*0Sstevel@tonic-gate size_t repcount = cautacc_ctlops_arg->repcount; 1009*0Sstevel@tonic-gate uint_t flags = cautacc_ctlops_arg->flags; 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p; 1012*0Sstevel@tonic-gate int err = DDI_SUCCESS; 1013*0Sstevel@tonic-gate 1014*0Sstevel@tonic-gate /* Use ontrap data in handle set up by FMA */ 1015*0Sstevel@tonic-gate pbm_p->pbm_ontrap_data = (on_trap_data_t *)hp->ahi_err->err_ontrap; 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED; 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate /* 1020*0Sstevel@tonic-gate * Note that i_ndi_busop_access_enter ends up grabbing the pokefault 1021*0Sstevel@tonic-gate * mutex. 1022*0Sstevel@tonic-gate */ 1023*0Sstevel@tonic-gate i_ndi_busop_access_enter(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 1024*0Sstevel@tonic-gate 1025*0Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) { 1026*0Sstevel@tonic-gate for (; repcount; repcount--) { 1027*0Sstevel@tonic-gate switch (size) { 1028*0Sstevel@tonic-gate 1029*0Sstevel@tonic-gate case sizeof (uint8_t): 1030*0Sstevel@tonic-gate i_ddi_put8(hp, (uint8_t *)dev_addr, 1031*0Sstevel@tonic-gate *(uint8_t *)host_addr); 1032*0Sstevel@tonic-gate break; 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate case sizeof (uint16_t): 1035*0Sstevel@tonic-gate i_ddi_put16(hp, (uint16_t *)dev_addr, 1036*0Sstevel@tonic-gate *(uint16_t *)host_addr); 1037*0Sstevel@tonic-gate break; 1038*0Sstevel@tonic-gate 1039*0Sstevel@tonic-gate case sizeof (uint32_t): 1040*0Sstevel@tonic-gate i_ddi_put32(hp, (uint32_t *)dev_addr, 1041*0Sstevel@tonic-gate *(uint32_t *)host_addr); 1042*0Sstevel@tonic-gate break; 1043*0Sstevel@tonic-gate 1044*0Sstevel@tonic-gate case sizeof (uint64_t): 1045*0Sstevel@tonic-gate i_ddi_put64(hp, (uint64_t *)dev_addr, 1046*0Sstevel@tonic-gate *(uint64_t *)host_addr); 1047*0Sstevel@tonic-gate break; 1048*0Sstevel@tonic-gate } 1049*0Sstevel@tonic-gate 1050*0Sstevel@tonic-gate host_addr += size; 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR) 1053*0Sstevel@tonic-gate dev_addr += size; 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate /* 1056*0Sstevel@tonic-gate * Read the async fault register for the PBM to see if 1057*0Sstevel@tonic-gate * it sees a master-abort. 1058*0Sstevel@tonic-gate */ 1059*0Sstevel@tonic-gate pbm_clear_error(pbm_p); 1060*0Sstevel@tonic-gate 1061*0Sstevel@tonic-gate if (pbm_p->pbm_ontrap_data->ot_trap & OT_DATA_ACCESS) { 1062*0Sstevel@tonic-gate err = DDI_FAILURE; 1063*0Sstevel@tonic-gate #ifdef DEBUG 1064*0Sstevel@tonic-gate pci_pokefault_cnt++; 1065*0Sstevel@tonic-gate #endif 1066*0Sstevel@tonic-gate break; 1067*0Sstevel@tonic-gate } 1068*0Sstevel@tonic-gate } 1069*0Sstevel@tonic-gate } 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate i_ddi_notrap((ddi_acc_handle_t)hp); 1072*0Sstevel@tonic-gate pbm_p->pbm_ontrap_data = NULL; 1073*0Sstevel@tonic-gate i_ndi_busop_access_exit(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 1074*0Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_UNEXPECTED; 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate return (err); 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate static int 1081*0Sstevel@tonic-gate pci_ctlops_poke(pci_t *pci_p, peekpoke_ctlops_t *in_args) 1082*0Sstevel@tonic-gate { 1083*0Sstevel@tonic-gate return (in_args->handle ? pci_do_caut_put(pci_p, in_args) : 1084*0Sstevel@tonic-gate pci_do_poke(pci_p, in_args)); 1085*0Sstevel@tonic-gate } 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate 1088*0Sstevel@tonic-gate static int 1089*0Sstevel@tonic-gate pci_do_peek(pci_t *pci_p, peekpoke_ctlops_t *in_args) 1090*0Sstevel@tonic-gate { 1091*0Sstevel@tonic-gate int err = DDI_SUCCESS; 1092*0Sstevel@tonic-gate on_trap_data_t otd; 1093*0Sstevel@tonic-gate 1094*0Sstevel@tonic-gate if (!on_trap(&otd, OT_DATA_ACCESS)) { 1095*0Sstevel@tonic-gate uintptr_t tramp = otd.ot_trampoline; 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&peek_fault; 1098*0Sstevel@tonic-gate err = do_peek(in_args->size, (void *)in_args->dev_addr, 1099*0Sstevel@tonic-gate (void *)in_args->host_addr); 1100*0Sstevel@tonic-gate otd.ot_trampoline = tramp; 1101*0Sstevel@tonic-gate } else 1102*0Sstevel@tonic-gate err = DDI_FAILURE; 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate no_trap(); 1105*0Sstevel@tonic-gate 1106*0Sstevel@tonic-gate #ifdef DEBUG 1107*0Sstevel@tonic-gate if (err == DDI_FAILURE) 1108*0Sstevel@tonic-gate pci_peekfault_cnt++; 1109*0Sstevel@tonic-gate #endif 1110*0Sstevel@tonic-gate return (err); 1111*0Sstevel@tonic-gate } 1112*0Sstevel@tonic-gate 1113*0Sstevel@tonic-gate static int 1114*0Sstevel@tonic-gate pci_do_caut_get(pci_t *pci_p, peekpoke_ctlops_t *cautacc_ctlops_arg) 1115*0Sstevel@tonic-gate { 1116*0Sstevel@tonic-gate size_t size = cautacc_ctlops_arg->size; 1117*0Sstevel@tonic-gate uintptr_t dev_addr = cautacc_ctlops_arg->dev_addr; 1118*0Sstevel@tonic-gate uintptr_t host_addr = cautacc_ctlops_arg->host_addr; 1119*0Sstevel@tonic-gate ddi_acc_impl_t *hp = (ddi_acc_impl_t *)cautacc_ctlops_arg->handle; 1120*0Sstevel@tonic-gate size_t repcount = cautacc_ctlops_arg->repcount; 1121*0Sstevel@tonic-gate uint_t flags = cautacc_ctlops_arg->flags; 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p; 1124*0Sstevel@tonic-gate int err = DDI_SUCCESS; 1125*0Sstevel@tonic-gate 1126*0Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED; 1127*0Sstevel@tonic-gate i_ndi_busop_access_enter(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate /* Can this code be optimized? */ 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate if (repcount == 1) { 1132*0Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) { 1133*0Sstevel@tonic-gate i_ddi_caut_get(size, (void *)dev_addr, 1134*0Sstevel@tonic-gate (void *)host_addr); 1135*0Sstevel@tonic-gate } else { 1136*0Sstevel@tonic-gate int i; 1137*0Sstevel@tonic-gate uint8_t *ff_addr = (uint8_t *)host_addr; 1138*0Sstevel@tonic-gate for (i = 0; i < size; i++) 1139*0Sstevel@tonic-gate *ff_addr++ = 0xff; 1140*0Sstevel@tonic-gate 1141*0Sstevel@tonic-gate err = DDI_FAILURE; 1142*0Sstevel@tonic-gate #ifdef DEBUG 1143*0Sstevel@tonic-gate pci_peekfault_cnt++; 1144*0Sstevel@tonic-gate #endif 1145*0Sstevel@tonic-gate } 1146*0Sstevel@tonic-gate } else { 1147*0Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) { 1148*0Sstevel@tonic-gate for (; repcount; repcount--) { 1149*0Sstevel@tonic-gate i_ddi_caut_get(size, (void *)dev_addr, 1150*0Sstevel@tonic-gate (void *)host_addr); 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate host_addr += size; 1153*0Sstevel@tonic-gate 1154*0Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR) 1155*0Sstevel@tonic-gate dev_addr += size; 1156*0Sstevel@tonic-gate } 1157*0Sstevel@tonic-gate } else { 1158*0Sstevel@tonic-gate err = DDI_FAILURE; 1159*0Sstevel@tonic-gate #ifdef DEBUG 1160*0Sstevel@tonic-gate pci_peekfault_cnt++; 1161*0Sstevel@tonic-gate #endif 1162*0Sstevel@tonic-gate } 1163*0Sstevel@tonic-gate } 1164*0Sstevel@tonic-gate 1165*0Sstevel@tonic-gate i_ddi_notrap((ddi_acc_handle_t)hp); 1166*0Sstevel@tonic-gate pbm_p->pbm_ontrap_data = NULL; 1167*0Sstevel@tonic-gate i_ndi_busop_access_exit(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 1168*0Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_UNEXPECTED; 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gate return (err); 1171*0Sstevel@tonic-gate } 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate 1174*0Sstevel@tonic-gate static int 1175*0Sstevel@tonic-gate pci_ctlops_peek(pci_t *pci_p, peekpoke_ctlops_t *in_args, void *result) 1176*0Sstevel@tonic-gate { 1177*0Sstevel@tonic-gate result = (void *)in_args->host_addr; 1178*0Sstevel@tonic-gate return (in_args->handle ? pci_do_caut_get(pci_p, in_args) : 1179*0Sstevel@tonic-gate pci_do_peek(pci_p, in_args)); 1180*0Sstevel@tonic-gate } 1181*0Sstevel@tonic-gate 1182*0Sstevel@tonic-gate /* 1183*0Sstevel@tonic-gate * get_reg_set_size 1184*0Sstevel@tonic-gate * 1185*0Sstevel@tonic-gate * Given a dev info pointer to a pci child and a register number, this 1186*0Sstevel@tonic-gate * routine returns the size element of that reg set property. 1187*0Sstevel@tonic-gate * return value: size of reg set on success, -1 on error 1188*0Sstevel@tonic-gate */ 1189*0Sstevel@tonic-gate static off_t 1190*0Sstevel@tonic-gate get_reg_set_size(dev_info_t *child, int rnumber) 1191*0Sstevel@tonic-gate { 1192*0Sstevel@tonic-gate pci_regspec_t *pci_rp; 1193*0Sstevel@tonic-gate off_t size; 1194*0Sstevel@tonic-gate int i; 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate if (rnumber < 0) 1197*0Sstevel@tonic-gate return (-1); 1198*0Sstevel@tonic-gate 1199*0Sstevel@tonic-gate /* 1200*0Sstevel@tonic-gate * Get the reg property for the device. 1201*0Sstevel@tonic-gate */ 1202*0Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg", 1203*0Sstevel@tonic-gate (caddr_t)&pci_rp, &i) != DDI_SUCCESS) 1204*0Sstevel@tonic-gate return (-1); 1205*0Sstevel@tonic-gate 1206*0Sstevel@tonic-gate if (rnumber >= (i / (int)sizeof (pci_regspec_t))) { 1207*0Sstevel@tonic-gate kmem_free(pci_rp, i); 1208*0Sstevel@tonic-gate return (-1); 1209*0Sstevel@tonic-gate } 1210*0Sstevel@tonic-gate 1211*0Sstevel@tonic-gate size = pci_rp[rnumber].pci_size_low | 1212*0Sstevel@tonic-gate ((uint64_t)pci_rp[rnumber].pci_size_hi << 32); 1213*0Sstevel@tonic-gate kmem_free(pci_rp, i); 1214*0Sstevel@tonic-gate return (size); 1215*0Sstevel@tonic-gate } 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate /* 1219*0Sstevel@tonic-gate * control ops entry point: 1220*0Sstevel@tonic-gate * 1221*0Sstevel@tonic-gate * Requests handled completely: 1222*0Sstevel@tonic-gate * DDI_CTLOPS_INITCHILD see init_child() for details 1223*0Sstevel@tonic-gate * DDI_CTLOPS_UNINITCHILD 1224*0Sstevel@tonic-gate * DDI_CTLOPS_REPORTDEV see report_dev() for details 1225*0Sstevel@tonic-gate * DDI_CTLOPS_XLATE_INTRS nothing to do 1226*0Sstevel@tonic-gate * DDI_CTLOPS_IOMIN cache line size if streaming otherwise 1 1227*0Sstevel@tonic-gate * DDI_CTLOPS_REGSIZE 1228*0Sstevel@tonic-gate * DDI_CTLOPS_NREGS 1229*0Sstevel@tonic-gate * DDI_CTLOPS_NINTRS 1230*0Sstevel@tonic-gate * DDI_CTLOPS_DVMAPAGESIZE 1231*0Sstevel@tonic-gate * DDI_CTLOPS_POKE 1232*0Sstevel@tonic-gate * DDI_CTLOPS_PEEK 1233*0Sstevel@tonic-gate * DDI_CTLOPS_QUIESCE 1234*0Sstevel@tonic-gate * DDI_CTLOPS_UNQUIESCE 1235*0Sstevel@tonic-gate * 1236*0Sstevel@tonic-gate * All others passed to parent. 1237*0Sstevel@tonic-gate */ 1238*0Sstevel@tonic-gate int 1239*0Sstevel@tonic-gate pci_ctlops(dev_info_t *dip, dev_info_t *rdip, 1240*0Sstevel@tonic-gate ddi_ctl_enum_t op, void *arg, void *result) 1241*0Sstevel@tonic-gate { 1242*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip)); 1243*0Sstevel@tonic-gate 1244*0Sstevel@tonic-gate switch (op) { 1245*0Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: 1246*0Sstevel@tonic-gate return (init_child(pci_p, (dev_info_t *)arg)); 1247*0Sstevel@tonic-gate 1248*0Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: 1249*0Sstevel@tonic-gate return (uninit_child(pci_p, (dev_info_t *)arg)); 1250*0Sstevel@tonic-gate 1251*0Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV: 1252*0Sstevel@tonic-gate return (report_dev(rdip)); 1253*0Sstevel@tonic-gate 1254*0Sstevel@tonic-gate case DDI_CTLOPS_IOMIN: 1255*0Sstevel@tonic-gate 1256*0Sstevel@tonic-gate /* 1257*0Sstevel@tonic-gate * If we are using the streaming cache, align at 1258*0Sstevel@tonic-gate * least on a cache line boundary. Otherwise use 1259*0Sstevel@tonic-gate * whatever alignment is passed in. 1260*0Sstevel@tonic-gate */ 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate if ((int)arg) { 1263*0Sstevel@tonic-gate int val = *((int *)result); 1264*0Sstevel@tonic-gate 1265*0Sstevel@tonic-gate val = maxbit(val, PCI_SBUF_LINE_SIZE); 1266*0Sstevel@tonic-gate *((int *)result) = val; 1267*0Sstevel@tonic-gate } 1268*0Sstevel@tonic-gate return (DDI_SUCCESS); 1269*0Sstevel@tonic-gate 1270*0Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE: 1271*0Sstevel@tonic-gate *((off_t *)result) = get_reg_set_size(rdip, *((int *)arg)); 1272*0Sstevel@tonic-gate return (*((off_t *)result) == -1 ? DDI_FAILURE : DDI_SUCCESS); 1273*0Sstevel@tonic-gate 1274*0Sstevel@tonic-gate case DDI_CTLOPS_NREGS: 1275*0Sstevel@tonic-gate *((uint_t *)result) = get_nreg_set(rdip); 1276*0Sstevel@tonic-gate return (DDI_SUCCESS); 1277*0Sstevel@tonic-gate 1278*0Sstevel@tonic-gate case DDI_CTLOPS_DVMAPAGESIZE: 1279*0Sstevel@tonic-gate *((ulong_t *)result) = IOMMU_PAGE_SIZE; 1280*0Sstevel@tonic-gate return (DDI_SUCCESS); 1281*0Sstevel@tonic-gate 1282*0Sstevel@tonic-gate case DDI_CTLOPS_POKE: 1283*0Sstevel@tonic-gate return (pci_ctlops_poke(pci_p, (peekpoke_ctlops_t *)arg)); 1284*0Sstevel@tonic-gate 1285*0Sstevel@tonic-gate case DDI_CTLOPS_PEEK: 1286*0Sstevel@tonic-gate return (pci_ctlops_peek(pci_p, (peekpoke_ctlops_t *)arg, 1287*0Sstevel@tonic-gate result)); 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate case DDI_CTLOPS_AFFINITY: 1290*0Sstevel@tonic-gate break; 1291*0Sstevel@tonic-gate 1292*0Sstevel@tonic-gate case DDI_CTLOPS_QUIESCE: 1293*0Sstevel@tonic-gate return (pci_bus_quiesce(pci_p, rdip, result)); 1294*0Sstevel@tonic-gate 1295*0Sstevel@tonic-gate case DDI_CTLOPS_UNQUIESCE: 1296*0Sstevel@tonic-gate return (pci_bus_unquiesce(pci_p, rdip, result)); 1297*0Sstevel@tonic-gate 1298*0Sstevel@tonic-gate default: 1299*0Sstevel@tonic-gate break; 1300*0Sstevel@tonic-gate } 1301*0Sstevel@tonic-gate 1302*0Sstevel@tonic-gate /* 1303*0Sstevel@tonic-gate * Now pass the request up to our parent. 1304*0Sstevel@tonic-gate */ 1305*0Sstevel@tonic-gate DEBUG2(DBG_CTLOPS, dip, "passing request to parent: rdip=%s%d\n", 1306*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip)); 1307*0Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, op, arg, result)); 1308*0Sstevel@tonic-gate } 1309*0Sstevel@tonic-gate 1310*0Sstevel@tonic-gate 1311*0Sstevel@tonic-gate /* ARGSUSED */ 1312*0Sstevel@tonic-gate int 1313*0Sstevel@tonic-gate pci_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 1314*0Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result) 1315*0Sstevel@tonic-gate { 1316*0Sstevel@tonic-gate pci_t *pci_p = get_pci_soft_state( 1317*0Sstevel@tonic-gate ddi_get_instance(dip)); 1318*0Sstevel@tonic-gate ddi_ispec_t *ip = (ddi_ispec_t *)hdlp->ih_private; 1319*0Sstevel@tonic-gate int ret = DDI_SUCCESS; 1320*0Sstevel@tonic-gate 1321*0Sstevel@tonic-gate switch (intr_op) { 1322*0Sstevel@tonic-gate case DDI_INTROP_GETCAP: 1323*0Sstevel@tonic-gate /* GetCap will always fail for all non PCI devices */ 1324*0Sstevel@tonic-gate (void) pci_intx_get_cap(rdip, (int *)result); 1325*0Sstevel@tonic-gate break; 1326*0Sstevel@tonic-gate case DDI_INTROP_SETCAP: 1327*0Sstevel@tonic-gate ret = DDI_ENOTSUP; 1328*0Sstevel@tonic-gate break; 1329*0Sstevel@tonic-gate case DDI_INTROP_ALLOC: 1330*0Sstevel@tonic-gate *(int *)result = hdlp->ih_scratch1; 1331*0Sstevel@tonic-gate break; 1332*0Sstevel@tonic-gate case DDI_INTROP_FREE: 1333*0Sstevel@tonic-gate break; 1334*0Sstevel@tonic-gate case DDI_INTROP_GETPRI: 1335*0Sstevel@tonic-gate *(int *)result = ip->is_pil ? 1336*0Sstevel@tonic-gate ip->is_pil : pci_class_to_pil(rdip); 1337*0Sstevel@tonic-gate break; 1338*0Sstevel@tonic-gate case DDI_INTROP_SETPRI: 1339*0Sstevel@tonic-gate ip->is_pil = (*(int *)result); 1340*0Sstevel@tonic-gate break; 1341*0Sstevel@tonic-gate case DDI_INTROP_ADDISR: 1342*0Sstevel@tonic-gate hdlp->ih_vector = *ip->is_intr; 1343*0Sstevel@tonic-gate 1344*0Sstevel@tonic-gate ret = pci_add_intr(dip, rdip, hdlp); 1345*0Sstevel@tonic-gate break; 1346*0Sstevel@tonic-gate case DDI_INTROP_REMISR: 1347*0Sstevel@tonic-gate hdlp->ih_vector = *ip->is_intr; 1348*0Sstevel@tonic-gate 1349*0Sstevel@tonic-gate ret = pci_remove_intr(dip, rdip, hdlp); 1350*0Sstevel@tonic-gate break; 1351*0Sstevel@tonic-gate case DDI_INTROP_ENABLE: 1352*0Sstevel@tonic-gate ret = ib_update_intr_state(pci_p, rdip, hdlp, 1353*0Sstevel@tonic-gate PCI_INTR_STATE_ENABLE); 1354*0Sstevel@tonic-gate break; 1355*0Sstevel@tonic-gate case DDI_INTROP_DISABLE: 1356*0Sstevel@tonic-gate ret = ib_update_intr_state(pci_p, rdip, hdlp, 1357*0Sstevel@tonic-gate PCI_INTR_STATE_DISABLE); 1358*0Sstevel@tonic-gate break; 1359*0Sstevel@tonic-gate case DDI_INTROP_SETMASK: 1360*0Sstevel@tonic-gate ret = pci_intx_set_mask(rdip); 1361*0Sstevel@tonic-gate break; 1362*0Sstevel@tonic-gate case DDI_INTROP_CLRMASK: 1363*0Sstevel@tonic-gate ret = pci_intx_clr_mask(rdip); 1364*0Sstevel@tonic-gate break; 1365*0Sstevel@tonic-gate case DDI_INTROP_GETPENDING: 1366*0Sstevel@tonic-gate ret = pci_intx_get_pending(rdip, (int *)result); 1367*0Sstevel@tonic-gate break; 1368*0Sstevel@tonic-gate case DDI_INTROP_NINTRS: 1369*0Sstevel@tonic-gate case DDI_INTROP_NAVAIL: 1370*0Sstevel@tonic-gate *(int *)result = i_ddi_get_nintrs(rdip); 1371*0Sstevel@tonic-gate break; 1372*0Sstevel@tonic-gate case DDI_INTROP_SUPPORTED_TYPES: 1373*0Sstevel@tonic-gate /* PCI nexus driver supports only fixed interrupts */ 1374*0Sstevel@tonic-gate *(int *)result = i_ddi_get_nintrs(rdip) ? 1375*0Sstevel@tonic-gate DDI_INTR_TYPE_FIXED : 0; 1376*0Sstevel@tonic-gate break; 1377*0Sstevel@tonic-gate default: 1378*0Sstevel@tonic-gate ret = DDI_ENOTSUP; 1379*0Sstevel@tonic-gate break; 1380*0Sstevel@tonic-gate } 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate return (ret); 1383*0Sstevel@tonic-gate } 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate static void 1386*0Sstevel@tonic-gate pci_init_hotplug(struct pci *pci_p) 1387*0Sstevel@tonic-gate { 1388*0Sstevel@tonic-gate pci_bus_range_t bus_range; 1389*0Sstevel@tonic-gate dev_info_t *dip; 1390*0Sstevel@tonic-gate struct cb_ops *ops; 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate /* 1393*0Sstevel@tonic-gate * Before initializing hotplug - open up 1394*0Sstevel@tonic-gate * bus range. The busra module will 1395*0Sstevel@tonic-gate * initialize its pool of bus numbers from 1396*0Sstevel@tonic-gate * this. "busra" will be the agent that keeps 1397*0Sstevel@tonic-gate * track of them during hotplug. Also, note, 1398*0Sstevel@tonic-gate * that busra will remove any bus numbers 1399*0Sstevel@tonic-gate * already in use from boot time. 1400*0Sstevel@tonic-gate */ 1401*0Sstevel@tonic-gate bus_range.lo = 0x0; 1402*0Sstevel@tonic-gate bus_range.hi = 0xff; 1403*0Sstevel@tonic-gate dip = pci_p->pci_dip; 1404*0Sstevel@tonic-gate pci_p->hotplug_capable = B_FALSE; 1405*0Sstevel@tonic-gate 1406*0Sstevel@tonic-gate /* 1407*0Sstevel@tonic-gate * If this property exists, this nexus has hot-plug 1408*0Sstevel@tonic-gate * slots. 1409*0Sstevel@tonic-gate */ 1410*0Sstevel@tonic-gate if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1411*0Sstevel@tonic-gate "hotplug-capable")) { 1412*0Sstevel@tonic-gate if (ndi_prop_update_int_array(DDI_DEV_T_NONE, 1413*0Sstevel@tonic-gate dip, "bus-range", 1414*0Sstevel@tonic-gate (int *)&bus_range, 1415*0Sstevel@tonic-gate 2) != DDI_PROP_SUCCESS) { 1416*0Sstevel@tonic-gate return; 1417*0Sstevel@tonic-gate } 1418*0Sstevel@tonic-gate 1419*0Sstevel@tonic-gate if (pcihp_init(dip) != DDI_SUCCESS) { 1420*0Sstevel@tonic-gate return; 1421*0Sstevel@tonic-gate } 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate if (ops = pcihp_get_cb_ops()) { 1424*0Sstevel@tonic-gate pci_ops.devo_cb_ops = ops; 1425*0Sstevel@tonic-gate DEBUG2(DBG_ATTACH, dip, "%s%d hotplug enabled", 1426*0Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip)); 1427*0Sstevel@tonic-gate } else { 1428*0Sstevel@tonic-gate return; 1429*0Sstevel@tonic-gate } 1430*0Sstevel@tonic-gate 1431*0Sstevel@tonic-gate pci_p->hotplug_capable = B_TRUE; 1432*0Sstevel@tonic-gate } 1433*0Sstevel@tonic-gate } 1434