1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * The tvhci driver can be used to exercise the mpxio framework together 31*7c478bd9Sstevel@tonic-gate * with tphci/tclient. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/scsi/impl/scsi_reset_notify.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/mdi_impldefs.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/disp.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate /* cb_ops entry points */ 45*7c478bd9Sstevel@tonic-gate static int tvhci_open(dev_t *, int, int, cred_t *); 46*7c478bd9Sstevel@tonic-gate static int tvhci_close(dev_t, int, int, cred_t *); 47*7c478bd9Sstevel@tonic-gate static int tvhci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 48*7c478bd9Sstevel@tonic-gate static int tvhci_attach(dev_info_t *, ddi_attach_cmd_t); 49*7c478bd9Sstevel@tonic-gate static int tvhci_detach(dev_info_t *, ddi_detach_cmd_t); 50*7c478bd9Sstevel@tonic-gate static int tvhci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* bus_ops entry points */ 53*7c478bd9Sstevel@tonic-gate static int tvhci_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, 54*7c478bd9Sstevel@tonic-gate void *); 55*7c478bd9Sstevel@tonic-gate static int tvhci_initchild(dev_info_t *, dev_info_t *); 56*7c478bd9Sstevel@tonic-gate static int tvhci_uninitchild(dev_info_t *, dev_info_t *); 57*7c478bd9Sstevel@tonic-gate static int tvhci_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, void *, 58*7c478bd9Sstevel@tonic-gate dev_info_t **); 59*7c478bd9Sstevel@tonic-gate static int tvhci_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t, 60*7c478bd9Sstevel@tonic-gate void *); 61*7c478bd9Sstevel@tonic-gate static int tvhci_intr_op(dev_info_t *dip, dev_info_t *rdip, 62*7c478bd9Sstevel@tonic-gate ddi_intr_op_t op, ddi_intr_handle_impl_t *hdlp, void *result); 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* vhci ops */ 65*7c478bd9Sstevel@tonic-gate static int tvhci_pi_init(dev_info_t *, mdi_pathinfo_t *, int); 66*7c478bd9Sstevel@tonic-gate static int tvhci_pi_uninit(dev_info_t *, mdi_pathinfo_t *, int); 67*7c478bd9Sstevel@tonic-gate static int tvhci_pi_state_change(dev_info_t *, mdi_pathinfo_t *, 68*7c478bd9Sstevel@tonic-gate mdi_pathinfo_state_t, uint32_t, int); 69*7c478bd9Sstevel@tonic-gate static int tvhci_failover(dev_info_t *, dev_info_t *, int); 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate static void *tvhci_state; 72*7c478bd9Sstevel@tonic-gate struct tvhci_state { 73*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 74*7c478bd9Sstevel@tonic-gate }; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate static mdi_vhci_ops_t tvhci_opinfo = { 77*7c478bd9Sstevel@tonic-gate MDI_VHCI_OPS_REV, 78*7c478bd9Sstevel@tonic-gate tvhci_pi_init, 79*7c478bd9Sstevel@tonic-gate tvhci_pi_uninit, 80*7c478bd9Sstevel@tonic-gate tvhci_pi_state_change, 81*7c478bd9Sstevel@tonic-gate tvhci_failover 82*7c478bd9Sstevel@tonic-gate }; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate static struct cb_ops tvhci_cb_ops = { 85*7c478bd9Sstevel@tonic-gate tvhci_open, /* open */ 86*7c478bd9Sstevel@tonic-gate tvhci_close, /* close */ 87*7c478bd9Sstevel@tonic-gate nodev, /* strategy */ 88*7c478bd9Sstevel@tonic-gate nodev, /* print */ 89*7c478bd9Sstevel@tonic-gate nodev, /* dump */ 90*7c478bd9Sstevel@tonic-gate nodev, /* read */ 91*7c478bd9Sstevel@tonic-gate nodev, /* write */ 92*7c478bd9Sstevel@tonic-gate tvhci_ioctl, /* ioctl */ 93*7c478bd9Sstevel@tonic-gate nodev, /* devmap */ 94*7c478bd9Sstevel@tonic-gate nodev, /* mmap */ 95*7c478bd9Sstevel@tonic-gate nodev, /* segmap */ 96*7c478bd9Sstevel@tonic-gate nochpoll, /* chpoll */ 97*7c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 98*7c478bd9Sstevel@tonic-gate 0, /* streamtab */ 99*7c478bd9Sstevel@tonic-gate D_NEW | D_MP, /* cb_flag */ 100*7c478bd9Sstevel@tonic-gate CB_REV, /* rev */ 101*7c478bd9Sstevel@tonic-gate nodev, /* aread */ 102*7c478bd9Sstevel@tonic-gate nodev /* awrite */ 103*7c478bd9Sstevel@tonic-gate }; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate static struct bus_ops tvhci_bus_ops = { 106*7c478bd9Sstevel@tonic-gate BUSO_REV, /* busops_rev */ 107*7c478bd9Sstevel@tonic-gate nullbusmap, /* bus_map */ 108*7c478bd9Sstevel@tonic-gate NULL, /* bus_get_intrspec */ 109*7c478bd9Sstevel@tonic-gate NULL, /* bus_add_interspec */ 110*7c478bd9Sstevel@tonic-gate NULL, /* bus_remove_interspec */ 111*7c478bd9Sstevel@tonic-gate i_ddi_map_fault, /* bus_map_fault */ 112*7c478bd9Sstevel@tonic-gate ddi_no_dma_map, /* bus_dma_map */ 113*7c478bd9Sstevel@tonic-gate ddi_no_dma_allochdl, /* bus_dma_allochdl */ 114*7c478bd9Sstevel@tonic-gate NULL, /* bus_dma_freehdl */ 115*7c478bd9Sstevel@tonic-gate NULL, /* bus_dma_bindhdl */ 116*7c478bd9Sstevel@tonic-gate NULL, /* bus_dma_unbindhdl */ 117*7c478bd9Sstevel@tonic-gate NULL, /* bus_dma_flush */ 118*7c478bd9Sstevel@tonic-gate NULL, /* bus_dma_win */ 119*7c478bd9Sstevel@tonic-gate NULL, /* bus_dma_ctl */ 120*7c478bd9Sstevel@tonic-gate tvhci_ctl, /* bus_ctl */ 121*7c478bd9Sstevel@tonic-gate ddi_bus_prop_op, /* bus_prop_op */ 122*7c478bd9Sstevel@tonic-gate NULL, /* bus_get_eventcookie */ 123*7c478bd9Sstevel@tonic-gate NULL, /* bus_add_eventcall */ 124*7c478bd9Sstevel@tonic-gate NULL, /* bus_remove_event */ 125*7c478bd9Sstevel@tonic-gate NULL, /* bus_post_event */ 126*7c478bd9Sstevel@tonic-gate NULL, /* bus_intr_ctl */ 127*7c478bd9Sstevel@tonic-gate tvhci_bus_config, /* bus_config */ 128*7c478bd9Sstevel@tonic-gate tvhci_bus_unconfig, /* bus_unconfig */ 129*7c478bd9Sstevel@tonic-gate NULL, /* bus_fm_init */ 130*7c478bd9Sstevel@tonic-gate NULL, /* bus_fm_fini */ 131*7c478bd9Sstevel@tonic-gate NULL, /* bus_fm_access_enter */ 132*7c478bd9Sstevel@tonic-gate NULL, /* bus_fm_access_exit */ 133*7c478bd9Sstevel@tonic-gate NULL, /* bus_power */ 134*7c478bd9Sstevel@tonic-gate tvhci_intr_op /* bus_intr_op */ 135*7c478bd9Sstevel@tonic-gate }; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate static struct dev_ops tvhci_ops = { 138*7c478bd9Sstevel@tonic-gate DEVO_REV, 139*7c478bd9Sstevel@tonic-gate 0, 140*7c478bd9Sstevel@tonic-gate tvhci_getinfo, 141*7c478bd9Sstevel@tonic-gate nulldev, /* identify */ 142*7c478bd9Sstevel@tonic-gate nulldev, /* probe */ 143*7c478bd9Sstevel@tonic-gate tvhci_attach, /* attach and detach are mandatory */ 144*7c478bd9Sstevel@tonic-gate tvhci_detach, 145*7c478bd9Sstevel@tonic-gate nodev, /* reset */ 146*7c478bd9Sstevel@tonic-gate &tvhci_cb_ops, /* cb_ops */ 147*7c478bd9Sstevel@tonic-gate &tvhci_bus_ops, /* bus_ops */ 148*7c478bd9Sstevel@tonic-gate NULL, /* power */ 149*7c478bd9Sstevel@tonic-gate }; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 154*7c478bd9Sstevel@tonic-gate &mod_driverops, 155*7c478bd9Sstevel@tonic-gate "test vhci driver %I%", 156*7c478bd9Sstevel@tonic-gate &tvhci_ops 157*7c478bd9Sstevel@tonic-gate }; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 160*7c478bd9Sstevel@tonic-gate MODREV_1, 161*7c478bd9Sstevel@tonic-gate &modldrv, 162*7c478bd9Sstevel@tonic-gate NULL 163*7c478bd9Sstevel@tonic-gate }; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate int 166*7c478bd9Sstevel@tonic-gate _init(void) 167*7c478bd9Sstevel@tonic-gate { 168*7c478bd9Sstevel@tonic-gate int rval; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate if ((rval = ddi_soft_state_init(&tvhci_state, 171*7c478bd9Sstevel@tonic-gate sizeof (struct tvhci_state), 2)) != 0) { 172*7c478bd9Sstevel@tonic-gate return (rval); 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate if ((rval = mod_install(&modlinkage)) != 0) { 176*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&tvhci_state); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate return (rval); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate int 183*7c478bd9Sstevel@tonic-gate _fini(void) 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate int rval; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * don't start cleaning up until we know that the module remove 189*7c478bd9Sstevel@tonic-gate * has worked -- if this works, then we know that each instance 190*7c478bd9Sstevel@tonic-gate * has successfully been detached 191*7c478bd9Sstevel@tonic-gate */ 192*7c478bd9Sstevel@tonic-gate if ((rval = mod_remove(&modlinkage)) != 0) { 193*7c478bd9Sstevel@tonic-gate return (rval); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&tvhci_state); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate return (rval); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate int 202*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 208*7c478bd9Sstevel@tonic-gate static int 209*7c478bd9Sstevel@tonic-gate tvhci_open(dev_t *devp, int flag, int otype, cred_t *credp) 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate struct tvhci_state *vhci; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (otype != OTYP_CHR) { 214*7c478bd9Sstevel@tonic-gate return (EINVAL); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate vhci = ddi_get_soft_state(tvhci_state, getminor(*devp)); 218*7c478bd9Sstevel@tonic-gate if (vhci == NULL) { 219*7c478bd9Sstevel@tonic-gate return (ENXIO); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate return (0); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 227*7c478bd9Sstevel@tonic-gate static int 228*7c478bd9Sstevel@tonic-gate tvhci_close(dev_t dev, int flag, int otype, cred_t *credp) 229*7c478bd9Sstevel@tonic-gate { 230*7c478bd9Sstevel@tonic-gate struct tvhci_state *vhci; 231*7c478bd9Sstevel@tonic-gate if (otype != OTYP_CHR) { 232*7c478bd9Sstevel@tonic-gate return (EINVAL); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate vhci = ddi_get_soft_state(tvhci_state, getminor(dev)); 236*7c478bd9Sstevel@tonic-gate if (vhci == NULL) { 237*7c478bd9Sstevel@tonic-gate return (ENXIO); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate return (0); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 244*7c478bd9Sstevel@tonic-gate static int 245*7c478bd9Sstevel@tonic-gate tvhci_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 246*7c478bd9Sstevel@tonic-gate cred_t *credp, int *rval) 247*7c478bd9Sstevel@tonic-gate { 248*7c478bd9Sstevel@tonic-gate return (0); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * attach the module 253*7c478bd9Sstevel@tonic-gate */ 254*7c478bd9Sstevel@tonic-gate static int 255*7c478bd9Sstevel@tonic-gate tvhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 256*7c478bd9Sstevel@tonic-gate { 257*7c478bd9Sstevel@tonic-gate char *vclass; 258*7c478bd9Sstevel@tonic-gate int instance, vhci_regis = 0; 259*7c478bd9Sstevel@tonic-gate struct tvhci_state *vhci = NULL; 260*7c478bd9Sstevel@tonic-gate dev_info_t *pdip; 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate instance = ddi_get_instance(dip); 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate switch (cmd) { 265*7c478bd9Sstevel@tonic-gate case DDI_ATTACH: 266*7c478bd9Sstevel@tonic-gate break; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate case DDI_RESUME: 269*7c478bd9Sstevel@tonic-gate case DDI_PM_RESUME: 270*7c478bd9Sstevel@tonic-gate return (0); /* nothing to do */ 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate default: 273*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * Allocate vhci data structure. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(tvhci_state, instance) != DDI_SUCCESS) { 280*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate vhci = ddi_get_soft_state(tvhci_state, instance); 284*7c478bd9Sstevel@tonic-gate ASSERT(vhci != NULL); 285*7c478bd9Sstevel@tonic-gate vhci->dip = dip; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* parent must be /pshot */ 288*7c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(dip); 289*7c478bd9Sstevel@tonic-gate if (strcmp(ddi_driver_name(pdip), "pshot") != 0 || 290*7c478bd9Sstevel@tonic-gate ddi_get_parent(pdip) != ddi_root_node()) { 291*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "tvhci must be under /pshot/"); 292*7c478bd9Sstevel@tonic-gate goto attach_fail; 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * XXX add mpxio-disable property. need to remove the check 297*7c478bd9Sstevel@tonic-gate * from the framework 298*7c478bd9Sstevel@tonic-gate */ 299*7c478bd9Sstevel@tonic-gate (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, 300*7c478bd9Sstevel@tonic-gate "mpxio-disable", "no"); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate /* bus_addr is the <vhci_class> */ 303*7c478bd9Sstevel@tonic-gate vclass = ddi_get_name_addr(dip); 304*7c478bd9Sstevel@tonic-gate if (vclass == NULL || vclass[1] == '\0') { 305*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "tvhci invalid vhci class"); 306*7c478bd9Sstevel@tonic-gate goto attach_fail; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* 310*7c478bd9Sstevel@tonic-gate * Attach this instance with the mpxio framework 311*7c478bd9Sstevel@tonic-gate */ 312*7c478bd9Sstevel@tonic-gate if (mdi_vhci_register(vclass, dip, &tvhci_opinfo, 0) != MDI_SUCCESS) { 313*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s mdi_vhci_register failed", 314*7c478bd9Sstevel@tonic-gate ddi_node_name(dip)); 315*7c478bd9Sstevel@tonic-gate goto attach_fail; 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate vhci_regis++; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, "devctl", S_IFCHR, 320*7c478bd9Sstevel@tonic-gate instance, DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) { 321*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s ddi_create_minor_node failed", 322*7c478bd9Sstevel@tonic-gate ddi_node_name(dip)); 323*7c478bd9Sstevel@tonic-gate goto attach_fail; 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1); 327*7c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 328*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate attach_fail: 331*7c478bd9Sstevel@tonic-gate if (vhci_regis) 332*7c478bd9Sstevel@tonic-gate (void) mdi_vhci_unregister(dip, 0); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate ddi_soft_state_free(tvhci_state, instance); 335*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 340*7c478bd9Sstevel@tonic-gate static int 341*7c478bd9Sstevel@tonic-gate tvhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 342*7c478bd9Sstevel@tonic-gate { 343*7c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate switch (cmd) { 346*7c478bd9Sstevel@tonic-gate case DDI_DETACH: 347*7c478bd9Sstevel@tonic-gate break; 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 350*7c478bd9Sstevel@tonic-gate case DDI_PM_SUSPEND: 351*7c478bd9Sstevel@tonic-gate return (0); /* nothing to do */ 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate default: 354*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate if (mdi_vhci_unregister(dip, 0) != MDI_SUCCESS) 358*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 361*7c478bd9Sstevel@tonic-gate ddi_soft_state_free(tvhci_state, instance); 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * tvhci_getinfo() 368*7c478bd9Sstevel@tonic-gate * Given the device number, return the devinfo pointer or the 369*7c478bd9Sstevel@tonic-gate * instance number. 370*7c478bd9Sstevel@tonic-gate * Note: always succeed DDI_INFO_DEVT2INSTANCE, even before attach. 371*7c478bd9Sstevel@tonic-gate */ 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 374*7c478bd9Sstevel@tonic-gate static int 375*7c478bd9Sstevel@tonic-gate tvhci_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate struct tvhci_state *vhci; 378*7c478bd9Sstevel@tonic-gate int instance = getminor((dev_t)arg); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate switch (cmd) { 381*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 382*7c478bd9Sstevel@tonic-gate vhci = ddi_get_soft_state(tvhci_state, instance); 383*7c478bd9Sstevel@tonic-gate if (vhci != NULL) 384*7c478bd9Sstevel@tonic-gate *result = vhci->dip; 385*7c478bd9Sstevel@tonic-gate else { 386*7c478bd9Sstevel@tonic-gate *result = NULL; 387*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate break; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 392*7c478bd9Sstevel@tonic-gate *result = (void *)(uintptr_t)instance; 393*7c478bd9Sstevel@tonic-gate break; 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate default: 396*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 403*7c478bd9Sstevel@tonic-gate static int 404*7c478bd9Sstevel@tonic-gate tvhci_pi_init(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags) 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate return (MDI_SUCCESS); 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 410*7c478bd9Sstevel@tonic-gate static int 411*7c478bd9Sstevel@tonic-gate tvhci_pi_uninit(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags) 412*7c478bd9Sstevel@tonic-gate { 413*7c478bd9Sstevel@tonic-gate return (MDI_SUCCESS); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 417*7c478bd9Sstevel@tonic-gate static int 418*7c478bd9Sstevel@tonic-gate tvhci_pi_state_change(dev_info_t *vdip, mdi_pathinfo_t *pip, 419*7c478bd9Sstevel@tonic-gate mdi_pathinfo_state_t state, uint32_t ext_state, int flags) 420*7c478bd9Sstevel@tonic-gate { 421*7c478bd9Sstevel@tonic-gate return (MDI_SUCCESS); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 425*7c478bd9Sstevel@tonic-gate static int 426*7c478bd9Sstevel@tonic-gate tvhci_failover(dev_info_t *vdip, dev_info_t *cdip, int flags) 427*7c478bd9Sstevel@tonic-gate { 428*7c478bd9Sstevel@tonic-gate return (MDI_SUCCESS); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate /* 432*7c478bd9Sstevel@tonic-gate * Interrupt stuff. NO OP for pseudo drivers. 433*7c478bd9Sstevel@tonic-gate */ 434*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 435*7c478bd9Sstevel@tonic-gate static int 436*7c478bd9Sstevel@tonic-gate tvhci_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 437*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result) 438*7c478bd9Sstevel@tonic-gate { 439*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 443*7c478bd9Sstevel@tonic-gate static int 444*7c478bd9Sstevel@tonic-gate tvhci_ctl(dev_info_t *dip, dev_info_t *rdip, 445*7c478bd9Sstevel@tonic-gate ddi_ctl_enum_t ctlop, void *arg, void *result) 446*7c478bd9Sstevel@tonic-gate { 447*7c478bd9Sstevel@tonic-gate switch (ctlop) { 448*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV: 449*7c478bd9Sstevel@tonic-gate if (rdip == (dev_info_t *)0) 450*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 451*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?tvhci-device: %s%d\n", 452*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip)); 453*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: 456*7c478bd9Sstevel@tonic-gate { 457*7c478bd9Sstevel@tonic-gate dev_info_t *child = (dev_info_t *)arg; 458*7c478bd9Sstevel@tonic-gate return (tvhci_initchild(dip, child)); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: 462*7c478bd9Sstevel@tonic-gate { 463*7c478bd9Sstevel@tonic-gate dev_info_t *child = (dev_info_t *)arg; 464*7c478bd9Sstevel@tonic-gate return (tvhci_uninitchild(dip, child)); 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_DMAPMAPC: 468*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REPORTINT: 469*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE: 470*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NREGS: 471*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NINTRS: 472*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_SIDDEV: 473*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_SLAVEONLY: 474*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_AFFINITY: 475*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_INTR_HILEVEL: 476*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_XLATE_INTRS: 477*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_POKE: 478*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_PEEK: 479*7c478bd9Sstevel@tonic-gate /* 480*7c478bd9Sstevel@tonic-gate * These ops correspond to functions that "shouldn't" be called 481*7c478bd9Sstevel@tonic-gate * by a pseudo driver. So we whine when we're called. 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s%d: invalid op (%d) from %s%d\n", 484*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), ddi_get_instance(dip), 485*7c478bd9Sstevel@tonic-gate ctlop, ddi_get_name(rdip), ddi_get_instance(rdip)); 486*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_ATTACH: 489*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_BTOP: 490*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_BTOPR: 491*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_DETACH: 492*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_DVMAPAGESIZE: 493*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_IOMIN: 494*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_POWER: 495*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_PTOB: 496*7c478bd9Sstevel@tonic-gate default: 497*7c478bd9Sstevel@tonic-gate /* 498*7c478bd9Sstevel@tonic-gate * The ops that we pass up (default). We pass up memory 499*7c478bd9Sstevel@tonic-gate * allocation oriented ops that we receive - these may be 500*7c478bd9Sstevel@tonic-gate * associated with pseudo HBA drivers below us with target 501*7c478bd9Sstevel@tonic-gate * drivers below them that use ddi memory allocation 502*7c478bd9Sstevel@tonic-gate * interfaces like scsi_alloc_consistent_buf. 503*7c478bd9Sstevel@tonic-gate */ 504*7c478bd9Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* set devi_addr to "g<guid>" */ 509*7c478bd9Sstevel@tonic-gate static int 510*7c478bd9Sstevel@tonic-gate tvhci_initchild(dev_info_t *dip, dev_info_t *child) 511*7c478bd9Sstevel@tonic-gate { 512*7c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(dip)) 513*7c478bd9Sstevel@tonic-gate char *guid, *addr; 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 516*7c478bd9Sstevel@tonic-gate MDI_CLIENT_GUID_PROP, &guid) != DDI_SUCCESS) { 517*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "tvhci_initchild - no guid property"); 518*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate addr = kmem_alloc(MAXNAMELEN, KM_SLEEP); 522*7c478bd9Sstevel@tonic-gate (void) snprintf(addr, MAXNAMELEN, "g%s", guid); 523*7c478bd9Sstevel@tonic-gate ddi_set_name_addr(child, addr); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate kmem_free(addr, MAXNAMELEN); 526*7c478bd9Sstevel@tonic-gate ddi_prop_free(guid); 527*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 531*7c478bd9Sstevel@tonic-gate static int 532*7c478bd9Sstevel@tonic-gate tvhci_uninitchild(dev_info_t *dip, dev_info_t *child) 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate ddi_set_name_addr(child, NULL); 535*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* form paddr by cname@<phci_inst>,<guid> */ 539*7c478bd9Sstevel@tonic-gate static char * 540*7c478bd9Sstevel@tonic-gate tvh_get_phci_devname(char *cname, char *guid, 541*7c478bd9Sstevel@tonic-gate dev_info_t *pdip, char *pname, int len) 542*7c478bd9Sstevel@tonic-gate { 543*7c478bd9Sstevel@tonic-gate (void) snprintf(pname, len, "%s@%d,%s", 544*7c478bd9Sstevel@tonic-gate cname, ddi_get_instance(pdip), guid); 545*7c478bd9Sstevel@tonic-gate return (pname); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate static int 549*7c478bd9Sstevel@tonic-gate tvh_enum_by_phci(dev_info_t *vdip, char *devnm, int flags) 550*7c478bd9Sstevel@tonic-gate { 551*7c478bd9Sstevel@tonic-gate mdi_phci_t *ph; 552*7c478bd9Sstevel@tonic-gate mdi_vhci_t *vh = (mdi_vhci_t *)DEVI(vdip)->devi_mdi_xhci; 553*7c478bd9Sstevel@tonic-gate dev_info_t *pdip, *cdip; 554*7c478bd9Sstevel@tonic-gate char *cname, *caddr, *guid, *pname; 555*7c478bd9Sstevel@tonic-gate int rval = DDI_FAILURE; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate (void) i_ddi_parse_name(devnm, &cname, &caddr, NULL); 558*7c478bd9Sstevel@tonic-gate if (cname == NULL || caddr == NULL || caddr[0] != 'g') 559*7c478bd9Sstevel@tonic-gate return (rval); 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate guid = caddr + 1; 562*7c478bd9Sstevel@tonic-gate pname = kmem_alloc(MAXNAMELEN, KM_SLEEP); 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate /* mutex_enter(&mdi_mutex); XXX need lock access */ 565*7c478bd9Sstevel@tonic-gate ph = vh->vh_phci_head; 566*7c478bd9Sstevel@tonic-gate while (ph) { 567*7c478bd9Sstevel@tonic-gate pdip = ph->ph_dip; 568*7c478bd9Sstevel@tonic-gate /* mutex_exit(&mdi_mutex); */ 569*7c478bd9Sstevel@tonic-gate (void) tvh_get_phci_devname(cname, guid, pdip, pname, 570*7c478bd9Sstevel@tonic-gate MAXNAMELEN); 571*7c478bd9Sstevel@tonic-gate if (ndi_devi_config_one(pdip, pname, &cdip, flags) 572*7c478bd9Sstevel@tonic-gate == DDI_SUCCESS) { 573*7c478bd9Sstevel@tonic-gate ndi_rele_devi(cdip); 574*7c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate /* mutex_enter(&mdi_mutex); */ 577*7c478bd9Sstevel@tonic-gate ph = ph->ph_next; 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate /* mutex_exit(&mdi_mutex); */ 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate *(caddr - 1) = '@'; /* undo damage from i_ddi_parse_name() */ 582*7c478bd9Sstevel@tonic-gate kmem_free(pname, MAXNAMELEN); 583*7c478bd9Sstevel@tonic-gate return (rval); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate static int 587*7c478bd9Sstevel@tonic-gate tvh_remove_by_phci(dev_info_t *vdip, char *devnm, int flags) 588*7c478bd9Sstevel@tonic-gate { 589*7c478bd9Sstevel@tonic-gate int rval = DDI_SUCCESS; 590*7c478bd9Sstevel@tonic-gate mdi_phci_t *ph; 591*7c478bd9Sstevel@tonic-gate mdi_vhci_t *vh = (mdi_vhci_t *)DEVI(vdip)->devi_mdi_xhci; 592*7c478bd9Sstevel@tonic-gate dev_info_t *pdip; 593*7c478bd9Sstevel@tonic-gate char *cname, *caddr, *guid, *pname; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate (void) i_ddi_parse_name(devnm, &cname, &caddr, NULL); 596*7c478bd9Sstevel@tonic-gate if (cname == NULL || caddr == NULL || caddr[0] != 'g') 597*7c478bd9Sstevel@tonic-gate return (rval); /* devnm can't exist */ 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate guid = caddr + 1; 600*7c478bd9Sstevel@tonic-gate pname = kmem_alloc(MAXNAMELEN, KM_SLEEP); 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate /* mutex_enter(&mdi_mutex); XXX need lock access */ 603*7c478bd9Sstevel@tonic-gate ph = vh->vh_phci_head; 604*7c478bd9Sstevel@tonic-gate while (ph) { 605*7c478bd9Sstevel@tonic-gate pdip = ph->ph_dip; 606*7c478bd9Sstevel@tonic-gate /* mutex_exit(&mdi_mutex); */ 607*7c478bd9Sstevel@tonic-gate (void) tvh_get_phci_devname(cname, guid, pdip, pname, 608*7c478bd9Sstevel@tonic-gate MAXNAMELEN); 609*7c478bd9Sstevel@tonic-gate rval = ndi_devi_unconfig_one(pdip, pname, NULL, flags); 610*7c478bd9Sstevel@tonic-gate /* mutex_enter(&mdi_mutex); */ 611*7c478bd9Sstevel@tonic-gate if (rval != NDI_SUCCESS) 612*7c478bd9Sstevel@tonic-gate break; 613*7c478bd9Sstevel@tonic-gate ph = ph->ph_next; 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate /* mutex_exit(&mdi_mutex); */ 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate kmem_free(pname, MAXNAMELEN); 618*7c478bd9Sstevel@tonic-gate return (rval); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate static int 622*7c478bd9Sstevel@tonic-gate tvhci_bus_config(dev_info_t *parent, uint_t flags, 623*7c478bd9Sstevel@tonic-gate ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 624*7c478bd9Sstevel@tonic-gate { 625*7c478bd9Sstevel@tonic-gate char *devnm; 626*7c478bd9Sstevel@tonic-gate dev_info_t *cdip; 627*7c478bd9Sstevel@tonic-gate int circ; 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate switch (op) { 630*7c478bd9Sstevel@tonic-gate case BUS_CONFIG_ONE: 631*7c478bd9Sstevel@tonic-gate break; 632*7c478bd9Sstevel@tonic-gate case BUS_CONFIG_ALL: 633*7c478bd9Sstevel@tonic-gate /* XXX call into phci's here? */ 634*7c478bd9Sstevel@tonic-gate case BUS_CONFIG_DRIVER: 635*7c478bd9Sstevel@tonic-gate return (ndi_busop_bus_config(parent, flags, op, arg, childp, 636*7c478bd9Sstevel@tonic-gate 0)); 637*7c478bd9Sstevel@tonic-gate default: 638*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate devnm = (char *)arg; 642*7c478bd9Sstevel@tonic-gate ndi_devi_enter(parent, &circ); 643*7c478bd9Sstevel@tonic-gate cdip = ndi_devi_findchild(parent, devnm); 644*7c478bd9Sstevel@tonic-gate ndi_devi_exit(parent, circ); 645*7c478bd9Sstevel@tonic-gate if (cdip == NULL) { 646*7c478bd9Sstevel@tonic-gate /* call into registered phci's */ 647*7c478bd9Sstevel@tonic-gate (void) tvh_enum_by_phci(parent, devnm, flags); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate return (ndi_busop_bus_config(parent, flags, op, arg, childp, 0)); 651*7c478bd9Sstevel@tonic-gate } 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate static int 654*7c478bd9Sstevel@tonic-gate tvhci_bus_unconfig(dev_info_t *parent, uint_t flags, 655*7c478bd9Sstevel@tonic-gate ddi_bus_config_op_t op, void *arg) 656*7c478bd9Sstevel@tonic-gate { 657*7c478bd9Sstevel@tonic-gate char *devnm, *slashname; 658*7c478bd9Sstevel@tonic-gate int rval, circ; 659*7c478bd9Sstevel@tonic-gate dev_info_t *cdip, *ndip; 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate /* 662*7c478bd9Sstevel@tonic-gate * If we are not removing device nodes, pathinfo can be 663*7c478bd9Sstevel@tonic-gate * left as is. So no need to disturb the phci's. 664*7c478bd9Sstevel@tonic-gate */ 665*7c478bd9Sstevel@tonic-gate if ((flags & NDI_DEVI_REMOVE) == 0) { 666*7c478bd9Sstevel@tonic-gate return (ndi_busop_bus_unconfig(parent, flags, op, arg)); 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate switch (op) { 670*7c478bd9Sstevel@tonic-gate case BUS_UNCONFIG_ONE: 671*7c478bd9Sstevel@tonic-gate devnm = (char *)arg; 672*7c478bd9Sstevel@tonic-gate ndi_devi_enter(parent, &circ); 673*7c478bd9Sstevel@tonic-gate if (ndi_devi_findchild(parent, devnm) == NULL) { 674*7c478bd9Sstevel@tonic-gate ndi_devi_exit(parent, circ); 675*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate ndi_devi_exit(parent, circ); 678*7c478bd9Sstevel@tonic-gate return (tvh_remove_by_phci(parent, devnm, flags)); 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate case BUS_UNCONFIG_ALL: 681*7c478bd9Sstevel@tonic-gate /* this functionality is for developers only */ 682*7c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 683*7c478bd9Sstevel@tonic-gate slashname = kmem_alloc(MAXNAMELEN, KM_SLEEP); 684*7c478bd9Sstevel@tonic-gate devnm = slashname + 1; 685*7c478bd9Sstevel@tonic-gate ndi_devi_enter(parent, &circ); 686*7c478bd9Sstevel@tonic-gate cdip = ddi_get_child(parent); 687*7c478bd9Sstevel@tonic-gate while (cdip != NULL) { 688*7c478bd9Sstevel@tonic-gate ndip = ddi_get_next_sibling(cdip); 689*7c478bd9Sstevel@tonic-gate (void) ddi_deviname(cdip, slashname); 690*7c478bd9Sstevel@tonic-gate ndi_devi_exit(parent, circ); 691*7c478bd9Sstevel@tonic-gate rval = tvh_remove_by_phci(parent, devnm, flags); 692*7c478bd9Sstevel@tonic-gate if (rval != DDI_SUCCESS) { 693*7c478bd9Sstevel@tonic-gate break; 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate ndi_devi_enter(parent, &circ); 696*7c478bd9Sstevel@tonic-gate cdip = ndip; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate ndi_devi_exit(parent, circ); 699*7c478bd9Sstevel@tonic-gate return (rval); 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate case BUS_UNCONFIG_DRIVER: 702*7c478bd9Sstevel@tonic-gate /* unconfig driver never comes with NDI_DEVI_REMOVE */ 703*7c478bd9Sstevel@tonic-gate default: 704*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 707*7c478bd9Sstevel@tonic-gate } 708