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 #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/ddi_subrdefs.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/spl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/async.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/dvma.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/upa64s.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * driver global data: 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate static void *per_upa64s_state; /* soft state pointer */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* 53*7c478bd9Sstevel@tonic-gate * function prototypes for bus ops routines: 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate static int 56*7c478bd9Sstevel@tonic-gate upa64s_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 57*7c478bd9Sstevel@tonic-gate off_t offset, off_t len, caddr_t *addrp); 58*7c478bd9Sstevel@tonic-gate static int 59*7c478bd9Sstevel@tonic-gate upa64s_ctlops(dev_info_t *dip, dev_info_t *rdip, 60*7c478bd9Sstevel@tonic-gate ddi_ctl_enum_t op, void *arg, void *result); 61*7c478bd9Sstevel@tonic-gate static int 62*7c478bd9Sstevel@tonic-gate upa64_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 63*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result); 64*7c478bd9Sstevel@tonic-gate static int 65*7c478bd9Sstevel@tonic-gate upa64s_add_intr_impl(dev_info_t *dip, dev_info_t *rdip, 66*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp); 67*7c478bd9Sstevel@tonic-gate static int 68*7c478bd9Sstevel@tonic-gate upa64s_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip, 69*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp); 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * function prototypes for dev ops routines: 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate static int upa64s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 75*7c478bd9Sstevel@tonic-gate static int upa64s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 76*7c478bd9Sstevel@tonic-gate static int upa64s_power(dev_info_t *dip, int component, int level); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * bus ops and dev ops structures: 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate static struct bus_ops upa64s_bus_ops = { 82*7c478bd9Sstevel@tonic-gate BUSO_REV, 83*7c478bd9Sstevel@tonic-gate upa64s_map, 84*7c478bd9Sstevel@tonic-gate 0, 85*7c478bd9Sstevel@tonic-gate 0, 86*7c478bd9Sstevel@tonic-gate 0, 87*7c478bd9Sstevel@tonic-gate i_ddi_map_fault, 88*7c478bd9Sstevel@tonic-gate ddi_no_dma_map, 89*7c478bd9Sstevel@tonic-gate ddi_no_dma_allochdl, 90*7c478bd9Sstevel@tonic-gate ddi_no_dma_freehdl, 91*7c478bd9Sstevel@tonic-gate ddi_no_dma_bindhdl, 92*7c478bd9Sstevel@tonic-gate ddi_no_dma_unbindhdl, 93*7c478bd9Sstevel@tonic-gate ddi_no_dma_flush, 94*7c478bd9Sstevel@tonic-gate ddi_no_dma_win, 95*7c478bd9Sstevel@tonic-gate ddi_no_dma_mctl, 96*7c478bd9Sstevel@tonic-gate upa64s_ctlops, 97*7c478bd9Sstevel@tonic-gate ddi_bus_prop_op, 98*7c478bd9Sstevel@tonic-gate 0, 99*7c478bd9Sstevel@tonic-gate 0, 100*7c478bd9Sstevel@tonic-gate 0, 101*7c478bd9Sstevel@tonic-gate 0, 102*7c478bd9Sstevel@tonic-gate 0, 103*7c478bd9Sstevel@tonic-gate 0, 104*7c478bd9Sstevel@tonic-gate 0, 105*7c478bd9Sstevel@tonic-gate 0, 106*7c478bd9Sstevel@tonic-gate 0, 107*7c478bd9Sstevel@tonic-gate 0, 108*7c478bd9Sstevel@tonic-gate 0, 109*7c478bd9Sstevel@tonic-gate 0, 110*7c478bd9Sstevel@tonic-gate upa64_intr_ops 111*7c478bd9Sstevel@tonic-gate }; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate static struct dev_ops upa64s_ops = { 114*7c478bd9Sstevel@tonic-gate DEVO_REV, 115*7c478bd9Sstevel@tonic-gate 0, 116*7c478bd9Sstevel@tonic-gate ddi_no_info, 117*7c478bd9Sstevel@tonic-gate nulldev, 118*7c478bd9Sstevel@tonic-gate 0, 119*7c478bd9Sstevel@tonic-gate upa64s_attach, 120*7c478bd9Sstevel@tonic-gate upa64s_detach, 121*7c478bd9Sstevel@tonic-gate nodev, 122*7c478bd9Sstevel@tonic-gate (struct cb_ops *)0, 123*7c478bd9Sstevel@tonic-gate &upa64s_bus_ops, 124*7c478bd9Sstevel@tonic-gate upa64s_power 125*7c478bd9Sstevel@tonic-gate }; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * module definitions: 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 131*7c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 134*7c478bd9Sstevel@tonic-gate &mod_driverops, /* type of module */ 135*7c478bd9Sstevel@tonic-gate "UPA64S nexus driver %I%", /* name of module */ 136*7c478bd9Sstevel@tonic-gate &upa64s_ops, /* driver ops */ 137*7c478bd9Sstevel@tonic-gate }; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 140*7c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 141*7c478bd9Sstevel@tonic-gate }; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate int 144*7c478bd9Sstevel@tonic-gate _init(void) 145*7c478bd9Sstevel@tonic-gate { 146*7c478bd9Sstevel@tonic-gate int e; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * Initialize per instance bus soft state pointer. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate if (e = ddi_soft_state_init(&per_upa64s_state, 152*7c478bd9Sstevel@tonic-gate sizeof (upa64s_devstate_t), 2)) 153*7c478bd9Sstevel@tonic-gate return (e); 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate * Install the module. 156*7c478bd9Sstevel@tonic-gate */ 157*7c478bd9Sstevel@tonic-gate if (e = mod_install(&modlinkage)) 158*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&per_upa64s_state); 159*7c478bd9Sstevel@tonic-gate return (e); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate int 163*7c478bd9Sstevel@tonic-gate _fini(void) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate int e = mod_remove(&modlinkage); 166*7c478bd9Sstevel@tonic-gate if (e) 167*7c478bd9Sstevel@tonic-gate return (e); 168*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&per_upa64s_state); 169*7c478bd9Sstevel@tonic-gate return (e); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate int 173*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 174*7c478bd9Sstevel@tonic-gate { 175*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * forward declarations: 181*7c478bd9Sstevel@tonic-gate */ 182*7c478bd9Sstevel@tonic-gate static void upa64s_intrdist(void *arg); 183*7c478bd9Sstevel@tonic-gate static int init_child(dev_info_t *child); 184*7c478bd9Sstevel@tonic-gate static int report_dev(dev_info_t *dip); 185*7c478bd9Sstevel@tonic-gate static int get_properties(upa64s_devstate_t *upa64s_p, dev_info_t *dip); 186*7c478bd9Sstevel@tonic-gate static void save_state(upa64s_devstate_t *upa64s_p); 187*7c478bd9Sstevel@tonic-gate static void restore_state(upa64s_devstate_t *upa64s_p); 188*7c478bd9Sstevel@tonic-gate static int xlate_reg_prop(dev_info_t *dip, upa64s_regspec_t *upa64s_rp, 189*7c478bd9Sstevel@tonic-gate off_t off, off_t len, struct regspec *rp); 190*7c478bd9Sstevel@tonic-gate static int get_reg_set(dev_info_t *dip, dev_info_t *child, int rnumber, 191*7c478bd9Sstevel@tonic-gate off_t off, off_t len, struct regspec *rp); 192*7c478bd9Sstevel@tonic-gate static off_t get_reg_set_size(dev_info_t *child, int rnumber); 193*7c478bd9Sstevel@tonic-gate static uint_t get_nreg_set(dev_info_t *child); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* device driver entry points */ 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * attach entry point: 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate static int 202*7c478bd9Sstevel@tonic-gate upa64s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate upa64s_devstate_t *upa64s_p; /* per upa64s state pointer */ 205*7c478bd9Sstevel@tonic-gate ddi_device_acc_attr_t attr; 206*7c478bd9Sstevel@tonic-gate int instance; 207*7c478bd9Sstevel@tonic-gate char *pmc[] = { "NAME=Framebuffer Power", "0=Off", "1=On", NULL }; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate switch (cmd) { 210*7c478bd9Sstevel@tonic-gate case DDI_ATTACH: 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * Allocate and get the per instance soft state structure. 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate instance = ddi_get_instance(dip); 215*7c478bd9Sstevel@tonic-gate if (alloc_upa64s_soft_state(instance) != DDI_SUCCESS) { 216*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: can't allocate upa64s state", 217*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), instance); 218*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate upa64s_p = get_upa64s_soft_state(instance); 221*7c478bd9Sstevel@tonic-gate upa64s_p->dip = dip; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * Get key properties of the bridge node. 225*7c478bd9Sstevel@tonic-gate */ 226*7c478bd9Sstevel@tonic-gate if (get_properties(upa64s_p, dip) != DDI_SUCCESS) 227*7c478bd9Sstevel@tonic-gate goto fail; 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * Create "pm-components" property for the purpose of 231*7c478bd9Sstevel@tonic-gate * doing Power Management. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip, 234*7c478bd9Sstevel@tonic-gate "pm-components", pmc, ((sizeof (pmc)/sizeof (char *)) - 1)) 235*7c478bd9Sstevel@tonic-gate != DDI_PROP_SUCCESS) { 236*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: failed to create pm-components " 237*7c478bd9Sstevel@tonic-gate "property.", ddi_get_name(dip), instance); 238*7c478bd9Sstevel@tonic-gate goto fail; 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* Map in the UPA's registers */ 242*7c478bd9Sstevel@tonic-gate attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 243*7c478bd9Sstevel@tonic-gate attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 244*7c478bd9Sstevel@tonic-gate attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 245*7c478bd9Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 0, 246*7c478bd9Sstevel@tonic-gate (caddr_t *)&upa64s_p->config_base, 0, 0, &attr, 247*7c478bd9Sstevel@tonic-gate &upa64s_p->config_base_ah) != DDI_SUCCESS) { 248*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: failed to map reg1.", 249*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), instance); 250*7c478bd9Sstevel@tonic-gate goto fail; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate upa64s_p->upa0_config = (uint64_t *)(upa64s_p->config_base + 254*7c478bd9Sstevel@tonic-gate UPA64S_UPA0_CONFIG_OFFSET); 255*7c478bd9Sstevel@tonic-gate upa64s_p->upa1_config = (uint64_t *)(upa64s_p->config_base + 256*7c478bd9Sstevel@tonic-gate UPA64S_UPA1_CONFIG_OFFSET); 257*7c478bd9Sstevel@tonic-gate upa64s_p->if_config = (uint64_t *)(upa64s_p->config_base + 258*7c478bd9Sstevel@tonic-gate UPA64S_IF_CONFIG_OFFSET); 259*7c478bd9Sstevel@tonic-gate upa64s_p->estar = (uint64_t *)(upa64s_p->config_base + 260*7c478bd9Sstevel@tonic-gate UPA64S_ESTAR_OFFSET); 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 1, (caddr_t *)&upa64s_p->imr[0], 263*7c478bd9Sstevel@tonic-gate 0, 0, &attr, &upa64s_p->imr_ah[0]) != DDI_SUCCESS) { 264*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: failed to map reg2.", 265*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), instance); 266*7c478bd9Sstevel@tonic-gate goto fail1; 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 2, (caddr_t *)&upa64s_p->imr[1], 270*7c478bd9Sstevel@tonic-gate 0, 0, &attr, &upa64s_p->imr_ah[1]) != DDI_SUCCESS) { 271*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: failed to map reg3.", 272*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), instance); 273*7c478bd9Sstevel@tonic-gate goto fail2; 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * Power level of a component is unknown at attach time. 278*7c478bd9Sstevel@tonic-gate * Bring the power level to what is needed for normal operation. 279*7c478bd9Sstevel@tonic-gate */ 280*7c478bd9Sstevel@tonic-gate upa64s_p->power_level = UPA64S_PM_UNKNOWN; 281*7c478bd9Sstevel@tonic-gate if (pm_raise_power(dip, UPA64S_PM_COMP, UPA64S_PM_NORMOP) != 282*7c478bd9Sstevel@tonic-gate DDI_SUCCESS) { 283*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: failed to raise the power.", 284*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), instance); 285*7c478bd9Sstevel@tonic-gate goto fail3; 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate intr_dist_add(upa64s_intrdist, dip); 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 291*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate case DDI_RESUME: 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate upa64s_p = get_upa64s_soft_state(ddi_get_instance(dip)); 296*7c478bd9Sstevel@tonic-gate DBG(D_ATTACH, dip, "DDI_RESUME\n"); 297*7c478bd9Sstevel@tonic-gate restore_state(upa64s_p); 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate /* 300*7c478bd9Sstevel@tonic-gate * Power level of a component is unknown at resume time. 301*7c478bd9Sstevel@tonic-gate * Bring the power level to what it was before suspend. 302*7c478bd9Sstevel@tonic-gate */ 303*7c478bd9Sstevel@tonic-gate upa64s_p->power_level = UPA64S_PM_UNKNOWN; 304*7c478bd9Sstevel@tonic-gate if (pm_raise_power(dip, UPA64S_PM_COMP, 305*7c478bd9Sstevel@tonic-gate upa64s_p->saved_power_level) != DDI_SUCCESS) 306*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: failed to change power level " 307*7c478bd9Sstevel@tonic-gate "during resume!", ddi_get_name(dip), instance); 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate default: 312*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate fail3: 316*7c478bd9Sstevel@tonic-gate ddi_regs_map_free(&upa64s_p->imr_ah[1]); 317*7c478bd9Sstevel@tonic-gate fail2: 318*7c478bd9Sstevel@tonic-gate ddi_regs_map_free(&upa64s_p->imr_ah[0]); 319*7c478bd9Sstevel@tonic-gate fail1: 320*7c478bd9Sstevel@tonic-gate ddi_regs_map_free(&upa64s_p->config_base_ah); 321*7c478bd9Sstevel@tonic-gate fail: 322*7c478bd9Sstevel@tonic-gate free_upa64s_soft_state(instance); 323*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * detach entry point: 329*7c478bd9Sstevel@tonic-gate */ 330*7c478bd9Sstevel@tonic-gate static int 331*7c478bd9Sstevel@tonic-gate upa64s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 332*7c478bd9Sstevel@tonic-gate { 333*7c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 334*7c478bd9Sstevel@tonic-gate upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance); 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate switch (cmd) { 337*7c478bd9Sstevel@tonic-gate case DDI_DETACH: 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate DBG(D_DETACH, dip, "DDI_DETACH\n"); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* 342*7c478bd9Sstevel@tonic-gate * Power down the device. 343*7c478bd9Sstevel@tonic-gate */ 344*7c478bd9Sstevel@tonic-gate if (pm_lower_power(dip, UPA64S_PM_COMP, UPA64S_PM_RESET) != 345*7c478bd9Sstevel@tonic-gate DDI_SUCCESS) 346*7c478bd9Sstevel@tonic-gate DBG(D_DETACH, dip, "failed to power off!\n"); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate intr_dist_rem(upa64s_intrdist, dip); 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate ddi_regs_map_free(&upa64s_p->config_base_ah); 351*7c478bd9Sstevel@tonic-gate ddi_regs_map_free(&upa64s_p->imr_ah[0]); 352*7c478bd9Sstevel@tonic-gate ddi_regs_map_free(&upa64s_p->imr_ah[1]); 353*7c478bd9Sstevel@tonic-gate free_upa64s_soft_state(instance); 354*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate DBG(D_DETACH, dip, "DDI_SUSPEND\n"); 359*7c478bd9Sstevel@tonic-gate save_state(upa64s_p); 360*7c478bd9Sstevel@tonic-gate upa64s_p->saved_power_level = upa64s_p->power_level; 361*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * power entry point: 369*7c478bd9Sstevel@tonic-gate * 370*7c478bd9Sstevel@tonic-gate * This entry point is called by Power Management framework to 371*7c478bd9Sstevel@tonic-gate * reset upa bus and slow down/speed up the upa interface of 372*7c478bd9Sstevel@tonic-gate * Schizo chip. 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate static int 375*7c478bd9Sstevel@tonic-gate upa64s_power(dev_info_t *dip, int component, int level) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 378*7c478bd9Sstevel@tonic-gate upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance); 379*7c478bd9Sstevel@tonic-gate volatile uint64_t uint64_data; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate DBG2(D_POWER, dip, "component=%d, level=%d\n", component, level); 382*7c478bd9Sstevel@tonic-gate if (component != UPA64S_PM_COMP || 383*7c478bd9Sstevel@tonic-gate level < UPA64S_PM_RESET || level > UPA64S_PM_NORMOP) 384*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* 387*7c478bd9Sstevel@tonic-gate * We can't set the hardware to the state that it is 388*7c478bd9Sstevel@tonic-gate * already in. So if the power state is not known, inquire the 389*7c478bd9Sstevel@tonic-gate * state of the hardware. If it is already in that state, 390*7c478bd9Sstevel@tonic-gate * record and return, otherwise make the state change. 391*7c478bd9Sstevel@tonic-gate */ 392*7c478bd9Sstevel@tonic-gate if (upa64s_p->power_level == UPA64S_PM_UNKNOWN) { 393*7c478bd9Sstevel@tonic-gate uint64_data = ddi_get64(upa64s_p->config_base_ah, 394*7c478bd9Sstevel@tonic-gate upa64s_p->if_config); 395*7c478bd9Sstevel@tonic-gate if ((level == UPA64S_PM_RESET && 396*7c478bd9Sstevel@tonic-gate uint64_data == UPA64S_NOT_POK_RST_L) || 397*7c478bd9Sstevel@tonic-gate (level == UPA64S_PM_NORMOP && 398*7c478bd9Sstevel@tonic-gate uint64_data == UPA64S_POK_NOT_RST_L)) { 399*7c478bd9Sstevel@tonic-gate upa64s_p->power_level = level; 400*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate if (level == upa64s_p->power_level) { 405*7c478bd9Sstevel@tonic-gate DBG1(D_POWER, dip, "device is already at power level %d\n", 406*7c478bd9Sstevel@tonic-gate level); 407*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate if (level == UPA64S_PM_RESET) { 412*7c478bd9Sstevel@tonic-gate /* 413*7c478bd9Sstevel@tonic-gate * Assert UPA64S_RESET 414*7c478bd9Sstevel@tonic-gate */ 415*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config, 416*7c478bd9Sstevel@tonic-gate UPA64S_POK_RST_L); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate /* 419*7c478bd9Sstevel@tonic-gate * Deassert UPA64S_POK. Flush the store buffer. 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config, 422*7c478bd9Sstevel@tonic-gate UPA64S_NOT_POK_RST_L); 423*7c478bd9Sstevel@tonic-gate uint64_data = ddi_get64(upa64s_p->config_base_ah, 424*7c478bd9Sstevel@tonic-gate upa64s_p->if_config); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate /* 427*7c478bd9Sstevel@tonic-gate * Internal UPA clock to 1/2 speed 428*7c478bd9Sstevel@tonic-gate */ 429*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar, 430*7c478bd9Sstevel@tonic-gate UPA64S_1_2_SPEED); 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate /* 433*7c478bd9Sstevel@tonic-gate * Internal UPA clock to 1/64 speed. Flush the store buffer. 434*7c478bd9Sstevel@tonic-gate */ 435*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar, 436*7c478bd9Sstevel@tonic-gate UPA64S_1_64_SPEED); 437*7c478bd9Sstevel@tonic-gate uint64_data = ddi_get64(upa64s_p->config_base_ah, 438*7c478bd9Sstevel@tonic-gate upa64s_p->estar); 439*7c478bd9Sstevel@tonic-gate } else { 440*7c478bd9Sstevel@tonic-gate /* 441*7c478bd9Sstevel@tonic-gate * Internal UPA clock to 1/2 speed 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar, 444*7c478bd9Sstevel@tonic-gate UPA64S_1_2_SPEED); 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * Internal UPA clock to full speed. Flush the store buffer. 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar, 450*7c478bd9Sstevel@tonic-gate UPA64S_FULL_SPEED); 451*7c478bd9Sstevel@tonic-gate uint64_data = ddi_get64(upa64s_p->config_base_ah, 452*7c478bd9Sstevel@tonic-gate upa64s_p->estar); 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate /* 455*7c478bd9Sstevel@tonic-gate * Assert UPA64S_POK. Flush the store buffer before 456*7c478bd9Sstevel@tonic-gate * the wait delay. 457*7c478bd9Sstevel@tonic-gate */ 458*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config, 459*7c478bd9Sstevel@tonic-gate UPA64S_POK_RST_L); 460*7c478bd9Sstevel@tonic-gate uint64_data = ddi_get64(upa64s_p->config_base_ah, 461*7c478bd9Sstevel@tonic-gate upa64s_p->if_config); 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate /* 464*7c478bd9Sstevel@tonic-gate * Delay 20 milliseconds for the signals to settle down. 465*7c478bd9Sstevel@tonic-gate */ 466*7c478bd9Sstevel@tonic-gate delay(drv_usectohz(20*1000)); 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate /* 469*7c478bd9Sstevel@tonic-gate * Deassert UPA64S_RESET. Flush the store buffer. 470*7c478bd9Sstevel@tonic-gate */ 471*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config, 472*7c478bd9Sstevel@tonic-gate UPA64S_POK_NOT_RST_L); 473*7c478bd9Sstevel@tonic-gate uint64_data = ddi_get64(upa64s_p->config_base_ah, 474*7c478bd9Sstevel@tonic-gate upa64s_p->if_config); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate upa64s_p->power_level = level; 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate /* bus driver entry points */ 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate /* 484*7c478bd9Sstevel@tonic-gate * bus map entry point: 485*7c478bd9Sstevel@tonic-gate * 486*7c478bd9Sstevel@tonic-gate * if map request is for an rnumber 487*7c478bd9Sstevel@tonic-gate * get the corresponding regspec from device node 488*7c478bd9Sstevel@tonic-gate * build a new regspec in our parent's format 489*7c478bd9Sstevel@tonic-gate * build a new map_req with the new regspec 490*7c478bd9Sstevel@tonic-gate * call up the tree to complete the mapping 491*7c478bd9Sstevel@tonic-gate */ 492*7c478bd9Sstevel@tonic-gate static int 493*7c478bd9Sstevel@tonic-gate upa64s_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 494*7c478bd9Sstevel@tonic-gate off_t off, off_t len, caddr_t *addrp) 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate struct regspec regspec; 497*7c478bd9Sstevel@tonic-gate ddi_map_req_t p_map_request; 498*7c478bd9Sstevel@tonic-gate int rnumber, rval; 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate DBG4(D_MAP, dip, "upa64s_map() mp=%x.%x addrp=%x.%08x\n", 501*7c478bd9Sstevel@tonic-gate HI32(mp), LO32(mp), HI32(addrp), LO32(addrp)); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate /* 504*7c478bd9Sstevel@tonic-gate * User level mappings are not supported yet. 505*7c478bd9Sstevel@tonic-gate */ 506*7c478bd9Sstevel@tonic-gate if (mp->map_flags & DDI_MF_USER_MAPPING) { 507*7c478bd9Sstevel@tonic-gate DBG2(D_MAP, dip, "rdip=%s%d: no user level mappings yet!\n", 508*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip)); 509*7c478bd9Sstevel@tonic-gate return (DDI_ME_UNIMPLEMENTED); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* 513*7c478bd9Sstevel@tonic-gate * Now handle the mapping according to its type. 514*7c478bd9Sstevel@tonic-gate */ 515*7c478bd9Sstevel@tonic-gate switch (mp->map_type) { 516*7c478bd9Sstevel@tonic-gate case DDI_MT_REGSPEC: 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate /* 519*7c478bd9Sstevel@tonic-gate * We assume the register specification is in PCI format. 520*7c478bd9Sstevel@tonic-gate * We must convert it into a regspec of our parent's 521*7c478bd9Sstevel@tonic-gate * and pass the request to our parent. 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate DBG3(D_MAP, dip, "rdip=%s%d: REGSPEC - handlep=%x\n", 524*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip), 525*7c478bd9Sstevel@tonic-gate mp->map_handlep); 526*7c478bd9Sstevel@tonic-gate rval = xlate_reg_prop(dip, (upa64s_regspec_t *)mp->map_obj.rp, 527*7c478bd9Sstevel@tonic-gate off, len, ®spec); 528*7c478bd9Sstevel@tonic-gate break; 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate case DDI_MT_RNUMBER: 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate /* 533*7c478bd9Sstevel@tonic-gate * Get the "reg" property from the device node and convert 534*7c478bd9Sstevel@tonic-gate * it to our parent's format. 535*7c478bd9Sstevel@tonic-gate */ 536*7c478bd9Sstevel@tonic-gate DBG4(D_MAP, dip, "rdip=%s%d: rnumber=%x handlep=%x\n", 537*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip), 538*7c478bd9Sstevel@tonic-gate mp->map_obj.rnumber, mp->map_handlep); 539*7c478bd9Sstevel@tonic-gate rnumber = mp->map_obj.rnumber; 540*7c478bd9Sstevel@tonic-gate if (rnumber < 0) 541*7c478bd9Sstevel@tonic-gate return (DDI_ME_RNUMBER_RANGE); 542*7c478bd9Sstevel@tonic-gate rval = get_reg_set(dip, rdip, rnumber, off, len, ®spec); 543*7c478bd9Sstevel@tonic-gate break; 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate default: 546*7c478bd9Sstevel@tonic-gate return (DDI_ME_INVAL); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate if (rval != DDI_SUCCESS) { 550*7c478bd9Sstevel@tonic-gate DBG(D_MAP, dip, "failed on regspec\n\n"); 551*7c478bd9Sstevel@tonic-gate return (rval); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate /* 555*7c478bd9Sstevel@tonic-gate * Now we have a copy of the upa64s regspec converted to our parent's 556*7c478bd9Sstevel@tonic-gate * format. Build a new map request based on this regspec and pass 557*7c478bd9Sstevel@tonic-gate * it to our parent. 558*7c478bd9Sstevel@tonic-gate */ 559*7c478bd9Sstevel@tonic-gate p_map_request = *mp; 560*7c478bd9Sstevel@tonic-gate p_map_request.map_type = DDI_MT_REGSPEC; 561*7c478bd9Sstevel@tonic-gate p_map_request.map_obj.rp = ®spec; 562*7c478bd9Sstevel@tonic-gate rval = ddi_map(dip, &p_map_request, 0, 0, addrp); 563*7c478bd9Sstevel@tonic-gate DBG3(D_MAP, dip, "ddi_map returns: rval=%x addrp=%x.%08x\n\n", 564*7c478bd9Sstevel@tonic-gate rval, HI32(*addrp), LO32(*addrp)); 565*7c478bd9Sstevel@tonic-gate return (rval); 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate /* 569*7c478bd9Sstevel@tonic-gate * Translate the UPA devices interrupt property. This is the only case I 570*7c478bd9Sstevel@tonic-gate * know of where the interrupts property is meaningless. As a result, we 571*7c478bd9Sstevel@tonic-gate * just use UPA_BASE_INO as our interrupt value and add to it the upa port id. 572*7c478bd9Sstevel@tonic-gate * UPA portid is returned too. 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate #define UPA_BASE_INO 0x2a 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate static int 577*7c478bd9Sstevel@tonic-gate upa64s_xlate_intr(dev_info_t *rdip, int32_t safariport, ddi_ispec_t *ispecp) 578*7c478bd9Sstevel@tonic-gate { 579*7c478bd9Sstevel@tonic-gate uint32_t ino = UPA_BASE_INO; 580*7c478bd9Sstevel@tonic-gate int32_t portid; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate /* Clear the ffb's interrupts property, it's meaningless */ 583*7c478bd9Sstevel@tonic-gate *ispecp->is_intr = 0; 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate if ((portid = ddi_getprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, 586*7c478bd9Sstevel@tonic-gate "upa-portid", -1)) == -1) 587*7c478bd9Sstevel@tonic-gate return (-1); 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate ino += portid; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate *ispecp->is_intr = UPA64S_MAKE_MONDO(safariport, ino); 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate DBG5(D_A_ISPEC, rdip, "upa64s_xlate_intr: rdip=%s%d: upa portid %d " 594*7c478bd9Sstevel@tonic-gate "ino=%x mondo 0x%x\n", ddi_get_name(rdip), ddi_get_instance(rdip), 595*7c478bd9Sstevel@tonic-gate portid, ino, *ispecp->is_intr); 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate return (portid); 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate /* 601*7c478bd9Sstevel@tonic-gate * bus add intrspec entry point: 602*7c478bd9Sstevel@tonic-gate */ 603*7c478bd9Sstevel@tonic-gate static int 604*7c478bd9Sstevel@tonic-gate upa64s_add_intr_impl(dev_info_t *dip, dev_info_t *rdip, 605*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp) 606*7c478bd9Sstevel@tonic-gate { 607*7c478bd9Sstevel@tonic-gate int upaport, instance = ddi_get_instance(dip); 608*7c478bd9Sstevel@tonic-gate upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance); 609*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 610*7c478bd9Sstevel@tonic-gate uint_t (*int_handler)(caddr_t, caddr_t) = hdlp->ih_cb_func; 611*7c478bd9Sstevel@tonic-gate caddr_t int_handler_arg1 = hdlp->ih_cb_arg1; 612*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 613*7c478bd9Sstevel@tonic-gate ddi_ispec_t *ip = (ddi_ispec_t *)hdlp->ih_private; 614*7c478bd9Sstevel@tonic-gate uint_t cpu_id; 615*7c478bd9Sstevel@tonic-gate volatile uint64_t imr_data; 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate upaport = upa64s_xlate_intr(rdip, upa64s_p->safari_id, ip); 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate if (*ip->is_intr == 0) 620*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate DBG3(D_A_ISPEC, dip, 623*7c478bd9Sstevel@tonic-gate "rdip=%s%d - IDDI_INTR_TYPE_NORMAL, mondo=%x\n", 624*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip), *ip->is_intr); 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate /* 627*7c478bd9Sstevel@tonic-gate * Make sure an interrupt handler isn't already installed. 628*7c478bd9Sstevel@tonic-gate */ 629*7c478bd9Sstevel@tonic-gate if (upa64s_p->ino_state[upaport] != INO_FREE) { 630*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate /* 634*7c478bd9Sstevel@tonic-gate * Install the handler in the system table. 635*7c478bd9Sstevel@tonic-gate */ 636*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 637*7c478bd9Sstevel@tonic-gate DBG2(D_A_ISPEC, dip, "i_ddi_add_ivintr: hdlr=%p arg=%p\n", 638*7c478bd9Sstevel@tonic-gate int_handler, int_handler_arg1); 639*7c478bd9Sstevel@tonic-gate #endif 640*7c478bd9Sstevel@tonic-gate hdlp->ih_vector = *ip->is_intr; 641*7c478bd9Sstevel@tonic-gate if (i_ddi_add_ivintr(hdlp) != DDI_SUCCESS) 642*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate cpu_id = intr_dist_cpuid(); 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate /* 647*7c478bd9Sstevel@tonic-gate * Enable the interrupt through its interrupt mapping register. 648*7c478bd9Sstevel@tonic-gate */ 649*7c478bd9Sstevel@tonic-gate imr_data = UPA64S_CPUID_TO_IMR(cpu_id); 650*7c478bd9Sstevel@tonic-gate imr_data = UPA64S_GET_MAP_REG(hdlp->ih_vector, imr_data); 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate DBG4(D_A_ISPEC, dip, "IMR [upaport=%d mapping reg 0x%p] = %x.%x\n", 653*7c478bd9Sstevel@tonic-gate upaport, upa64s_p->imr[upaport], HI32(imr_data), LO32(imr_data)); 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport], imr_data); 656*7c478bd9Sstevel@tonic-gate /* Read the data back to flush store buffers. */ 657*7c478bd9Sstevel@tonic-gate imr_data = ddi_get64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport]); 658*7c478bd9Sstevel@tonic-gate upa64s_p->ino_state[upaport] = INO_INUSE; 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate DBG(D_A_ISPEC, dip, "add_intrspec success!\n"); 661*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate /* 666*7c478bd9Sstevel@tonic-gate * bus remove intrspec entry point 667*7c478bd9Sstevel@tonic-gate */ 668*7c478bd9Sstevel@tonic-gate static int 669*7c478bd9Sstevel@tonic-gate upa64s_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip, 670*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp) 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate upa64s_devstate_t *upa64s_p = 673*7c478bd9Sstevel@tonic-gate get_upa64s_soft_state(ddi_get_instance(dip)); 674*7c478bd9Sstevel@tonic-gate ddi_ispec_t *ip = (ddi_ispec_t *)hdlp->ih_private; 675*7c478bd9Sstevel@tonic-gate int upaport; 676*7c478bd9Sstevel@tonic-gate #ifndef lint 677*7c478bd9Sstevel@tonic-gate volatile uint64_t tmp; 678*7c478bd9Sstevel@tonic-gate #endif 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate /* 681*7c478bd9Sstevel@tonic-gate * Make sure the mondo is valid. 682*7c478bd9Sstevel@tonic-gate */ 683*7c478bd9Sstevel@tonic-gate upaport = upa64s_xlate_intr(rdip, upa64s_p->safari_id, ip); 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate if (*ip->is_intr == 0) 686*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate DBG3(D_R_ISPEC, dip, 689*7c478bd9Sstevel@tonic-gate "rdip=%s%d - IDDI_INTR_TYPE_NORMAL, mondo=%x\n", 690*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip), *ip->is_intr); 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate if (upa64s_p->ino_state[upaport] != INO_INUSE) { 693*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate /* Call up to our parent to handle the removal */ 697*7c478bd9Sstevel@tonic-gate hdlp->ih_vector = *ip->is_intr; 698*7c478bd9Sstevel@tonic-gate i_ddi_rem_ivintr(hdlp); 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport], 0); 701*7c478bd9Sstevel@tonic-gate #ifndef lint 702*7c478bd9Sstevel@tonic-gate /* Flush store buffers */ 703*7c478bd9Sstevel@tonic-gate tmp = ddi_get64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport]); 704*7c478bd9Sstevel@tonic-gate #endif 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate upa64s_p->ino_state[upaport] = INO_FREE; 707*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate /* new intr_ops structure */ 712*7c478bd9Sstevel@tonic-gate static int 713*7c478bd9Sstevel@tonic-gate upa64_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 714*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result) 715*7c478bd9Sstevel@tonic-gate { 716*7c478bd9Sstevel@tonic-gate ddi_ispec_t *ip = (ddi_ispec_t *)hdlp->ih_private; 717*7c478bd9Sstevel@tonic-gate int ret = DDI_SUCCESS; 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate switch (intr_op) { 720*7c478bd9Sstevel@tonic-gate case DDI_INTROP_GETCAP: 721*7c478bd9Sstevel@tonic-gate *(int *)result = 0; 722*7c478bd9Sstevel@tonic-gate break; 723*7c478bd9Sstevel@tonic-gate case DDI_INTROP_ALLOC: 724*7c478bd9Sstevel@tonic-gate *(int *)result = hdlp->ih_scratch1; 725*7c478bd9Sstevel@tonic-gate break; 726*7c478bd9Sstevel@tonic-gate case DDI_INTROP_FREE: 727*7c478bd9Sstevel@tonic-gate break; 728*7c478bd9Sstevel@tonic-gate case DDI_INTROP_GETPRI: 729*7c478bd9Sstevel@tonic-gate /* 730*7c478bd9Sstevel@tonic-gate * We only have slave UPA devices so force the PIL to 5. 731*7c478bd9Sstevel@tonic-gate * this is done since all slave UPA devices have historically 732*7c478bd9Sstevel@tonic-gate * had their PILs set to 5. Only do it if the PIL is not 733*7c478bd9Sstevel@tonic-gate * being preset. 734*7c478bd9Sstevel@tonic-gate */ 735*7c478bd9Sstevel@tonic-gate *(int *)result = ip->is_pil ? ip->is_pil : 5; 736*7c478bd9Sstevel@tonic-gate break; 737*7c478bd9Sstevel@tonic-gate case DDI_INTROP_SETPRI: 738*7c478bd9Sstevel@tonic-gate ip->is_pil = (*(int *)result); 739*7c478bd9Sstevel@tonic-gate break; 740*7c478bd9Sstevel@tonic-gate case DDI_INTROP_ADDISR: 741*7c478bd9Sstevel@tonic-gate hdlp->ih_vector = *ip->is_intr; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate ret = upa64s_add_intr_impl(dip, rdip, hdlp); 744*7c478bd9Sstevel@tonic-gate break; 745*7c478bd9Sstevel@tonic-gate case DDI_INTROP_REMISR: 746*7c478bd9Sstevel@tonic-gate hdlp->ih_vector = *ip->is_intr; 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate ret = upa64s_remove_intr_impl(dip, rdip, hdlp); 749*7c478bd9Sstevel@tonic-gate break; 750*7c478bd9Sstevel@tonic-gate case DDI_INTROP_ENABLE: 751*7c478bd9Sstevel@tonic-gate case DDI_INTROP_DISABLE: 752*7c478bd9Sstevel@tonic-gate break; 753*7c478bd9Sstevel@tonic-gate case DDI_INTROP_NINTRS: 754*7c478bd9Sstevel@tonic-gate case DDI_INTROP_NAVAIL: 755*7c478bd9Sstevel@tonic-gate *(int *)result = i_ddi_get_nintrs(rdip); 756*7c478bd9Sstevel@tonic-gate break; 757*7c478bd9Sstevel@tonic-gate case DDI_INTROP_SETCAP: 758*7c478bd9Sstevel@tonic-gate case DDI_INTROP_SETMASK: 759*7c478bd9Sstevel@tonic-gate case DDI_INTROP_CLRMASK: 760*7c478bd9Sstevel@tonic-gate case DDI_INTROP_GETPENDING: 761*7c478bd9Sstevel@tonic-gate ret = DDI_ENOTSUP; 762*7c478bd9Sstevel@tonic-gate break; 763*7c478bd9Sstevel@tonic-gate case DDI_INTROP_SUPPORTED_TYPES: 764*7c478bd9Sstevel@tonic-gate /* only support fixed interrupts */ 765*7c478bd9Sstevel@tonic-gate *(int *)result = i_ddi_get_nintrs(rdip) ? 766*7c478bd9Sstevel@tonic-gate DDI_INTR_TYPE_FIXED : 0; 767*7c478bd9Sstevel@tonic-gate break; 768*7c478bd9Sstevel@tonic-gate default: 769*7c478bd9Sstevel@tonic-gate ret = i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result); 770*7c478bd9Sstevel@tonic-gate break; 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate return (ret); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 777*7c478bd9Sstevel@tonic-gate uint_t upa64s_debug_flags = (uint_t)0; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate extern void prom_printf(const char *, ...); 780*7c478bd9Sstevel@tonic-gate #endif 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate /* 783*7c478bd9Sstevel@tonic-gate * control ops entry point: 784*7c478bd9Sstevel@tonic-gate * 785*7c478bd9Sstevel@tonic-gate * Requests handled completely: 786*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_INITCHILD see init_child() for details 787*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_UNINITCHILD 788*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_REPORTDEV see report_dev() for details 789*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_XLATE_INTRS nothing to do 790*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_REGSIZE 791*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_NREGS 792*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_NINTRS 793*7c478bd9Sstevel@tonic-gate * 794*7c478bd9Sstevel@tonic-gate * All others passed to parent. 795*7c478bd9Sstevel@tonic-gate */ 796*7c478bd9Sstevel@tonic-gate static int 797*7c478bd9Sstevel@tonic-gate upa64s_ctlops(dev_info_t *dip, dev_info_t *rdip, 798*7c478bd9Sstevel@tonic-gate ddi_ctl_enum_t op, void *arg, void *result) 799*7c478bd9Sstevel@tonic-gate { 800*7c478bd9Sstevel@tonic-gate DBG5(D_CTLOPS, dip, "dip=%x.%x rdip=%x.%x op=%x", 801*7c478bd9Sstevel@tonic-gate HI32(dip), LO32(dip), HI32(rdip), LO32(rdip), op); 802*7c478bd9Sstevel@tonic-gate DBG4(D_CTLOPS|D_CONT, dip, " arg=%x.%x result=%x.%x\n", 803*7c478bd9Sstevel@tonic-gate HI32(arg), LO32(arg), HI32(result), LO32(result)); 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate switch (op) { 806*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: 807*7c478bd9Sstevel@tonic-gate DBG2(D_CTLOPS, dip, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n", 808*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip)); 809*7c478bd9Sstevel@tonic-gate return (init_child((dev_info_t *)arg)); 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: 812*7c478bd9Sstevel@tonic-gate DBG2(D_CTLOPS, dip, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n", 813*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip)); 814*7c478bd9Sstevel@tonic-gate ddi_set_name_addr((dev_info_t *)arg, NULL); 815*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node((dev_info_t *)arg, NULL); 816*7c478bd9Sstevel@tonic-gate impl_rem_dev_props((dev_info_t *)arg); 817*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV: 820*7c478bd9Sstevel@tonic-gate DBG2(D_CTLOPS, dip, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n", 821*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip)); 822*7c478bd9Sstevel@tonic-gate return (report_dev(rdip)); 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_XLATE_INTRS: 825*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE: 828*7c478bd9Sstevel@tonic-gate DBG2(D_CTLOPS, dip, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n", 829*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip)); 830*7c478bd9Sstevel@tonic-gate *((off_t *)result) = get_reg_set_size(rdip, *((int *)arg)); 831*7c478bd9Sstevel@tonic-gate return (*((off_t *)result) == -1 ? DDI_FAILURE : DDI_SUCCESS); 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NREGS: 834*7c478bd9Sstevel@tonic-gate DBG2(D_CTLOPS, dip, "DDI_CTLOPS_NREGS: rdip=%s%d\n", 835*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip)); 836*7c478bd9Sstevel@tonic-gate *((uint_t *)result) = get_nreg_set(rdip); 837*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NINTRS: 840*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate /* 844*7c478bd9Sstevel@tonic-gate * Now pass the request up to our parent. 845*7c478bd9Sstevel@tonic-gate */ 846*7c478bd9Sstevel@tonic-gate DBG3(D_CTLOPS, dip, "passing request to parent: rdip=%s%d op=%x\n\n", 847*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip), ddi_get_instance(rdip), op); 848*7c478bd9Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, op, arg, result)); 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* support routines */ 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate /* 855*7c478bd9Sstevel@tonic-gate * get_properties 856*7c478bd9Sstevel@tonic-gate * 857*7c478bd9Sstevel@tonic-gate * This function is called from the attach routine to get the key 858*7c478bd9Sstevel@tonic-gate * properties of the upa64s node. 859*7c478bd9Sstevel@tonic-gate * 860*7c478bd9Sstevel@tonic-gate * used by: upa64s_attach() 861*7c478bd9Sstevel@tonic-gate * 862*7c478bd9Sstevel@tonic-gate * return value: none 863*7c478bd9Sstevel@tonic-gate */ 864*7c478bd9Sstevel@tonic-gate static int 865*7c478bd9Sstevel@tonic-gate get_properties(upa64s_devstate_t *upa64s_p, dev_info_t *dip) 866*7c478bd9Sstevel@tonic-gate { 867*7c478bd9Sstevel@tonic-gate int safari_id; 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * Get the device's safari id. 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate safari_id = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 873*7c478bd9Sstevel@tonic-gate "portid", -1); 874*7c478bd9Sstevel@tonic-gate if (safari_id == -1) { 875*7c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 876*7c478bd9Sstevel@tonic-gate panic("%s%d: no portid property", ddi_get_name(dip), instance); 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate upa64s_p->safari_id = safari_id; 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate /* 885*7c478bd9Sstevel@tonic-gate * save_state 886*7c478bd9Sstevel@tonic-gate * 887*7c478bd9Sstevel@tonic-gate * This routine saves a copy of the upa64s register state. 888*7c478bd9Sstevel@tonic-gate * 889*7c478bd9Sstevel@tonic-gate * used by: upa64s_detach() on a suspend operation 890*7c478bd9Sstevel@tonic-gate */ 891*7c478bd9Sstevel@tonic-gate static void 892*7c478bd9Sstevel@tonic-gate save_state(upa64s_devstate_t *upa64s_p) 893*7c478bd9Sstevel@tonic-gate { 894*7c478bd9Sstevel@tonic-gate upa64s_p->imr_data[0] = ddi_get64(upa64s_p->imr_ah[0], 895*7c478bd9Sstevel@tonic-gate upa64s_p->imr[0]); 896*7c478bd9Sstevel@tonic-gate upa64s_p->imr_data[1] = ddi_get64(upa64s_p->imr_ah[1], 897*7c478bd9Sstevel@tonic-gate upa64s_p->imr[1]); 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate /* 902*7c478bd9Sstevel@tonic-gate * restore_state 903*7c478bd9Sstevel@tonic-gate * 904*7c478bd9Sstevel@tonic-gate * This routine restores a copy of the upa64s register state. 905*7c478bd9Sstevel@tonic-gate * 906*7c478bd9Sstevel@tonic-gate * used by: upa64s_attach() on a resume operation 907*7c478bd9Sstevel@tonic-gate */ 908*7c478bd9Sstevel@tonic-gate static void 909*7c478bd9Sstevel@tonic-gate restore_state(upa64s_devstate_t *upa64s_p) 910*7c478bd9Sstevel@tonic-gate { 911*7c478bd9Sstevel@tonic-gate #ifndef lint 912*7c478bd9Sstevel@tonic-gate volatile uint64_t tmp; 913*7c478bd9Sstevel@tonic-gate #endif 914*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->imr_ah[0], upa64s_p->imr[0], 915*7c478bd9Sstevel@tonic-gate upa64s_p->imr_data[0]); 916*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->imr_ah[1], upa64s_p->imr[1], 917*7c478bd9Sstevel@tonic-gate upa64s_p->imr_data[1]); 918*7c478bd9Sstevel@tonic-gate #ifndef lint 919*7c478bd9Sstevel@tonic-gate /* Flush the store buffer */ 920*7c478bd9Sstevel@tonic-gate tmp = ddi_get64(upa64s_p->imr_ah[0], upa64s_p->imr[0]); 921*7c478bd9Sstevel@tonic-gate tmp = ddi_get64(upa64s_p->imr_ah[1], upa64s_p->imr[1]); 922*7c478bd9Sstevel@tonic-gate #endif 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate /* 927*7c478bd9Sstevel@tonic-gate * get_reg_set 928*7c478bd9Sstevel@tonic-gate * 929*7c478bd9Sstevel@tonic-gate * This routine will get a upa64s format regspec for a given 930*7c478bd9Sstevel@tonic-gate * device node and register number. 931*7c478bd9Sstevel@tonic-gate * 932*7c478bd9Sstevel@tonic-gate * used by: upa64s_map() 933*7c478bd9Sstevel@tonic-gate * 934*7c478bd9Sstevel@tonic-gate * return value: 935*7c478bd9Sstevel@tonic-gate * 936*7c478bd9Sstevel@tonic-gate * DDI_SUCCESS - on success 937*7c478bd9Sstevel@tonic-gate * DDI_ME_INVAL - regspec is invalid 938*7c478bd9Sstevel@tonic-gate * DDI_ME_RNUMBER_RANGE - rnumber out of range 939*7c478bd9Sstevel@tonic-gate */ 940*7c478bd9Sstevel@tonic-gate static int 941*7c478bd9Sstevel@tonic-gate get_reg_set(dev_info_t *dip, dev_info_t *child, int rnumber, 942*7c478bd9Sstevel@tonic-gate off_t off, off_t len, struct regspec *rp) 943*7c478bd9Sstevel@tonic-gate { 944*7c478bd9Sstevel@tonic-gate upa64s_regspec_t *upa64s_rp; 945*7c478bd9Sstevel@tonic-gate int i, n, rval; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate /* 948*7c478bd9Sstevel@tonic-gate * Get child device "reg" property 949*7c478bd9Sstevel@tonic-gate */ 950*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "reg", 951*7c478bd9Sstevel@tonic-gate (caddr_t)&upa64s_rp, &i) != DDI_SUCCESS) 952*7c478bd9Sstevel@tonic-gate return (DDI_ME_RNUMBER_RANGE); 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate n = i / (int)sizeof (upa64s_regspec_t); 955*7c478bd9Sstevel@tonic-gate if (rnumber >= n) { 956*7c478bd9Sstevel@tonic-gate kmem_free(upa64s_rp, i); 957*7c478bd9Sstevel@tonic-gate return (DDI_ME_RNUMBER_RANGE); 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate /* 961*7c478bd9Sstevel@tonic-gate * Convert each the upa64s format register specification to 962*7c478bd9Sstevel@tonic-gate * out parent format. 963*7c478bd9Sstevel@tonic-gate */ 964*7c478bd9Sstevel@tonic-gate rval = xlate_reg_prop(dip, &upa64s_rp[rnumber], off, len, rp); 965*7c478bd9Sstevel@tonic-gate kmem_free(upa64s_rp, i); 966*7c478bd9Sstevel@tonic-gate return (rval); 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * xlate_reg_prop 972*7c478bd9Sstevel@tonic-gate * 973*7c478bd9Sstevel@tonic-gate * This routine converts a upa64s format regspec to a standard 974*7c478bd9Sstevel@tonic-gate * regspec containing the corresponding system address. 975*7c478bd9Sstevel@tonic-gate * 976*7c478bd9Sstevel@tonic-gate * used by: upa64s_map() 977*7c478bd9Sstevel@tonic-gate * 978*7c478bd9Sstevel@tonic-gate * return value: 979*7c478bd9Sstevel@tonic-gate * 980*7c478bd9Sstevel@tonic-gate * DDI_SUCCESS 981*7c478bd9Sstevel@tonic-gate * DDI_FAILURE - off + len is beyond device address range 982*7c478bd9Sstevel@tonic-gate * DDI_ME_INVAL - regspec is invalid 983*7c478bd9Sstevel@tonic-gate */ 984*7c478bd9Sstevel@tonic-gate static int 985*7c478bd9Sstevel@tonic-gate xlate_reg_prop(dev_info_t *dip, upa64s_regspec_t *child_rp, off_t off, 986*7c478bd9Sstevel@tonic-gate off_t len, struct regspec *rp) 987*7c478bd9Sstevel@tonic-gate { 988*7c478bd9Sstevel@tonic-gate int n_ranges, ranges_len, i; 989*7c478bd9Sstevel@tonic-gate uint64_t child_beg, child_end; 990*7c478bd9Sstevel@tonic-gate upa64s_ranges_t *range_p, *rng_p; 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate DBG4(D_MAP, dip, "upa64s regspec - ((%x,%x) (%x,%x))\n", 993*7c478bd9Sstevel@tonic-gate HI32(child_rp->upa64s_phys), LO32(child_rp->upa64s_phys), 994*7c478bd9Sstevel@tonic-gate HI32(child_rp->upa64s_size), LO32(child_rp->upa64s_size)); 995*7c478bd9Sstevel@tonic-gate DBG2(D_MAP, dip, "upa64s xlate_reg_prp - off=%lx len=%lx\n", off, len); 996*7c478bd9Sstevel@tonic-gate #if 0 997*7c478bd9Sstevel@tonic-gate /* 998*7c478bd9Sstevel@tonic-gate * both FFB and AFB have broken "reg" properties, all mapping 999*7c478bd9Sstevel@tonic-gate * requests are done through reg-0 with very long offsets. 1000*7c478bd9Sstevel@tonic-gate * Hence this safety check is always violated. 1001*7c478bd9Sstevel@tonic-gate */ 1002*7c478bd9Sstevel@tonic-gate if (off + len > child_rp->upa64s_size) { 1003*7c478bd9Sstevel@tonic-gate DBG(D_MAP, dip, "upa64s xlate_reg_prp: bad off + len\n"); 1004*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1005*7c478bd9Sstevel@tonic-gate } 1006*7c478bd9Sstevel@tonic-gate #endif 1007*7c478bd9Sstevel@tonic-gate /* 1008*7c478bd9Sstevel@tonic-gate * current "struct regspec" only supports 32-bit sizes. 1009*7c478bd9Sstevel@tonic-gate */ 1010*7c478bd9Sstevel@tonic-gate if (child_rp->upa64s_size >= (1ull << 32)) 1011*7c478bd9Sstevel@tonic-gate panic("upa64s: reg size must be less than 4 Gb"); 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 1014*7c478bd9Sstevel@tonic-gate "ranges", (caddr_t)&range_p, &ranges_len) != DDI_SUCCESS) { 1015*7c478bd9Sstevel@tonic-gate ranges_len = 0; 1016*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: no ranges property", 1017*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), ddi_get_instance(dip)); 1018*7c478bd9Sstevel@tonic-gate } 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate n_ranges = ranges_len / sizeof (upa64s_regspec_t); 1021*7c478bd9Sstevel@tonic-gate child_beg = child_rp->upa64s_phys; 1022*7c478bd9Sstevel@tonic-gate #if 0 1023*7c478bd9Sstevel@tonic-gate /* 1024*7c478bd9Sstevel@tonic-gate * again, this safety checking can not be performed. 1025*7c478bd9Sstevel@tonic-gate * Hack by adding a pratical max child reg bank length. 1026*7c478bd9Sstevel@tonic-gate */ 1027*7c478bd9Sstevel@tonic-gate child_end = child_beg + child_rp->upa64s_size; 1028*7c478bd9Sstevel@tonic-gate #else 1029*7c478bd9Sstevel@tonic-gate #define UPA64S_MAX_CHILD_LEN 0xe000000 1030*7c478bd9Sstevel@tonic-gate child_end = child_beg + UPA64S_MAX_CHILD_LEN; 1031*7c478bd9Sstevel@tonic-gate #endif 1032*7c478bd9Sstevel@tonic-gate for (i = 0, rng_p = range_p; i < n_ranges; i++, rng_p++) { 1033*7c478bd9Sstevel@tonic-gate uint64_t rng_beg = rng_p->upa64s_child; 1034*7c478bd9Sstevel@tonic-gate uint64_t rng_end = rng_beg + rng_p->upa64s_size; 1035*7c478bd9Sstevel@tonic-gate if ((rng_beg <= child_beg) && (rng_end >= child_end)) { 1036*7c478bd9Sstevel@tonic-gate uint64_t addr = child_beg - rng_beg + off; 1037*7c478bd9Sstevel@tonic-gate addr += rng_p->upa64s_parent; 1038*7c478bd9Sstevel@tonic-gate rp->regspec_bustype = HI32(addr); 1039*7c478bd9Sstevel@tonic-gate rp->regspec_addr = LO32(addr); 1040*7c478bd9Sstevel@tonic-gate rp->regspec_size = len ? len : child_rp->upa64s_size; 1041*7c478bd9Sstevel@tonic-gate break; 1042*7c478bd9Sstevel@tonic-gate } 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate if (ranges_len) 1045*7c478bd9Sstevel@tonic-gate kmem_free(range_p, ranges_len); 1046*7c478bd9Sstevel@tonic-gate DBG4(D_MAP, dip, "regspec (%x,%x,%x) i=%x\n", 1047*7c478bd9Sstevel@tonic-gate rp->regspec_bustype, rp->regspec_addr, rp->regspec_size, i); 1048*7c478bd9Sstevel@tonic-gate return (i < n_ranges? DDI_SUCCESS : DDI_ME_INVAL); 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate /* 1053*7c478bd9Sstevel@tonic-gate * report_dev 1054*7c478bd9Sstevel@tonic-gate * 1055*7c478bd9Sstevel@tonic-gate * This function is called from our control ops routine on a 1056*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_REPORTDEV request. 1057*7c478bd9Sstevel@tonic-gate */ 1058*7c478bd9Sstevel@tonic-gate static int 1059*7c478bd9Sstevel@tonic-gate report_dev(dev_info_t *dip) 1060*7c478bd9Sstevel@tonic-gate { 1061*7c478bd9Sstevel@tonic-gate if (dip == (dev_info_t *)0) 1062*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1063*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?UPA64S-device: %s@%s, %s #%d\n", 1064*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_name_addr(dip), 1065*7c478bd9Sstevel@tonic-gate ddi_major_to_name(ddi_name_to_major(ddi_get_name(dip))), 1066*7c478bd9Sstevel@tonic-gate ddi_get_instance(dip)); 1067*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 1068*7c478bd9Sstevel@tonic-gate } 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate /* 1072*7c478bd9Sstevel@tonic-gate * init_child 1073*7c478bd9Sstevel@tonic-gate * 1074*7c478bd9Sstevel@tonic-gate * This function is called from our control ops routine on a 1075*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_INITCHILD request. It builds and sets the device's 1076*7c478bd9Sstevel@tonic-gate * parent private data area. 1077*7c478bd9Sstevel@tonic-gate * 1078*7c478bd9Sstevel@tonic-gate * used by: upa64s_ctlops() 1079*7c478bd9Sstevel@tonic-gate * 1080*7c478bd9Sstevel@tonic-gate * return value: none 1081*7c478bd9Sstevel@tonic-gate */ 1082*7c478bd9Sstevel@tonic-gate static int 1083*7c478bd9Sstevel@tonic-gate init_child(dev_info_t *child) 1084*7c478bd9Sstevel@tonic-gate { 1085*7c478bd9Sstevel@tonic-gate upa64s_regspec_t *child_rp; 1086*7c478bd9Sstevel@tonic-gate int i; 1087*7c478bd9Sstevel@tonic-gate char addr[256]; 1088*7c478bd9Sstevel@tonic-gate int32_t portid; 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate if ((portid = ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 1091*7c478bd9Sstevel@tonic-gate "upa-portid", -1)) == -1) 1092*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate /* 1095*7c478bd9Sstevel@tonic-gate * Set the address portion of the node name based on 1096*7c478bd9Sstevel@tonic-gate * the function and device number. 1097*7c478bd9Sstevel@tonic-gate */ 1098*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "reg", 1099*7c478bd9Sstevel@tonic-gate (caddr_t)&child_rp, &i) != DDI_SUCCESS) { 1100*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate 1103*7c478bd9Sstevel@tonic-gate (void) sprintf(addr, "%x,%x", portid, LO32(child_rp->upa64s_phys)); 1104*7c478bd9Sstevel@tonic-gate ddi_set_name_addr(child, addr); 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate ddi_set_parent_data(child, NULL); 1107*7c478bd9Sstevel@tonic-gate kmem_free(child_rp, i); 1108*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate /* 1113*7c478bd9Sstevel@tonic-gate * get_reg_set_size 1114*7c478bd9Sstevel@tonic-gate * 1115*7c478bd9Sstevel@tonic-gate * Given a dev info pointer to a child and a register number, this 1116*7c478bd9Sstevel@tonic-gate * routine returns the size element of that reg set property. 1117*7c478bd9Sstevel@tonic-gate * 1118*7c478bd9Sstevel@tonic-gate * used by: upa64s_ctlops() - DDI_CTLOPS_REGSIZE 1119*7c478bd9Sstevel@tonic-gate * 1120*7c478bd9Sstevel@tonic-gate * return value: size of reg set on success, -1 on error 1121*7c478bd9Sstevel@tonic-gate */ 1122*7c478bd9Sstevel@tonic-gate static off_t 1123*7c478bd9Sstevel@tonic-gate get_reg_set_size(dev_info_t *child, int rnumber) 1124*7c478bd9Sstevel@tonic-gate { 1125*7c478bd9Sstevel@tonic-gate upa64s_regspec_t *upa64s_rp; 1126*7c478bd9Sstevel@tonic-gate uint_t size; 1127*7c478bd9Sstevel@tonic-gate int i; 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate if (rnumber < 0) 1130*7c478bd9Sstevel@tonic-gate return (-1); 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate /* 1133*7c478bd9Sstevel@tonic-gate * Get the reg property for the device. 1134*7c478bd9Sstevel@tonic-gate */ 1135*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "reg", 1136*7c478bd9Sstevel@tonic-gate (caddr_t)&upa64s_rp, &i) != DDI_SUCCESS) 1137*7c478bd9Sstevel@tonic-gate return (-1); 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate if (rnumber >= (i / (int)sizeof (upa64s_regspec_t))) { 1140*7c478bd9Sstevel@tonic-gate kmem_free(upa64s_rp, i); 1141*7c478bd9Sstevel@tonic-gate return (-1); 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate 1144*7c478bd9Sstevel@tonic-gate /* >4G reg size not supported */ 1145*7c478bd9Sstevel@tonic-gate size = (uint32_t)upa64s_rp[rnumber].upa64s_size; 1146*7c478bd9Sstevel@tonic-gate kmem_free(upa64s_rp, i); 1147*7c478bd9Sstevel@tonic-gate return (size); 1148*7c478bd9Sstevel@tonic-gate } 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate /* 1152*7c478bd9Sstevel@tonic-gate * get_nreg_set 1153*7c478bd9Sstevel@tonic-gate * 1154*7c478bd9Sstevel@tonic-gate * Given a dev info pointer to a child, this routine returns the 1155*7c478bd9Sstevel@tonic-gate * number of sets in its "reg" property. 1156*7c478bd9Sstevel@tonic-gate * 1157*7c478bd9Sstevel@tonic-gate * used by: upa64s_ctlops() - DDI_CTLOPS_NREGS 1158*7c478bd9Sstevel@tonic-gate * 1159*7c478bd9Sstevel@tonic-gate * return value: # of reg sets on success, zero on error 1160*7c478bd9Sstevel@tonic-gate */ 1161*7c478bd9Sstevel@tonic-gate static uint_t 1162*7c478bd9Sstevel@tonic-gate get_nreg_set(dev_info_t *child) 1163*7c478bd9Sstevel@tonic-gate { 1164*7c478bd9Sstevel@tonic-gate upa64s_regspec_t *upa64s_rp; 1165*7c478bd9Sstevel@tonic-gate int i, n; 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate /* 1168*7c478bd9Sstevel@tonic-gate * Get the reg property for the device. 1169*7c478bd9Sstevel@tonic-gate */ 1170*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "reg", 1171*7c478bd9Sstevel@tonic-gate (caddr_t)&upa64s_rp, &i) != DDI_SUCCESS) 1172*7c478bd9Sstevel@tonic-gate return (0); 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate n = i / (int)sizeof (upa64s_regspec_t); 1175*7c478bd9Sstevel@tonic-gate kmem_free(upa64s_rp, i); 1176*7c478bd9Sstevel@tonic-gate return (n); 1177*7c478bd9Sstevel@tonic-gate } 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate /* 1181*7c478bd9Sstevel@tonic-gate * upa64s_intrdist 1182*7c478bd9Sstevel@tonic-gate * 1183*7c478bd9Sstevel@tonic-gate * The following routine is the callback function for this nexus driver 1184*7c478bd9Sstevel@tonic-gate * to support interrupt distribution on sun4u systems. When this 1185*7c478bd9Sstevel@tonic-gate * function is called by the interrupt distribution framework, it will 1186*7c478bd9Sstevel@tonic-gate * reprogram all the active the mondo registers. 1187*7c478bd9Sstevel@tonic-gate */ 1188*7c478bd9Sstevel@tonic-gate static void 1189*7c478bd9Sstevel@tonic-gate upa64s_intrdist(void *arg) 1190*7c478bd9Sstevel@tonic-gate { 1191*7c478bd9Sstevel@tonic-gate dev_info_t *dip = (dev_info_t *)arg; 1192*7c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 1193*7c478bd9Sstevel@tonic-gate upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance); 1194*7c478bd9Sstevel@tonic-gate uint_t upaport; 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate for (upaport = 0; upaport < UPA64S_PORTS; upaport++) { 1197*7c478bd9Sstevel@tonic-gate volatile uint64_t *imr; 1198*7c478bd9Sstevel@tonic-gate volatile uint64_t imr_dat; 1199*7c478bd9Sstevel@tonic-gate uint_t mondo; 1200*7c478bd9Sstevel@tonic-gate uint32_t cpuid; 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate if (upa64s_p->ino_state[upaport] != INO_INUSE) 1203*7c478bd9Sstevel@tonic-gate continue; 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate imr = upa64s_p->imr[upaport]; 1206*7c478bd9Sstevel@tonic-gate mondo = UPA64S_IMR_TO_MONDO(*imr); 1207*7c478bd9Sstevel@tonic-gate cpuid = intr_dist_cpuid(); 1208*7c478bd9Sstevel@tonic-gate imr_dat = UPA64S_CPUID_TO_IMR(cpuid); 1209*7c478bd9Sstevel@tonic-gate imr_dat = UPA64S_GET_MAP_REG(mondo, imr_dat); 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate /* Check and re-program cpu target if necessary */ 1212*7c478bd9Sstevel@tonic-gate DBG2(D_INTRDIST, dip, "mondo=%x cpuid=%x\n", mondo, cpuid); 1213*7c478bd9Sstevel@tonic-gate if (UPA64S_IMR_TO_CPUID(*imr) == cpuid) { 1214*7c478bd9Sstevel@tonic-gate DBG(D_INTRDIST, dip, "same cpuid\n"); 1215*7c478bd9Sstevel@tonic-gate continue; 1216*7c478bd9Sstevel@tonic-gate } 1217*7c478bd9Sstevel@tonic-gate ddi_put64(upa64s_p->imr_ah[upaport], (uint64_t *)imr, imr_dat); 1218*7c478bd9Sstevel@tonic-gate imr_dat = ddi_get64(upa64s_p->imr_ah[upaport], (uint64_t *)imr); 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate } 1221*7c478bd9Sstevel@tonic-gate 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1224*7c478bd9Sstevel@tonic-gate static void 1225*7c478bd9Sstevel@tonic-gate upa64s_debug(uint_t flag, dev_info_t *dip, char *fmt, 1226*7c478bd9Sstevel@tonic-gate uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5) 1227*7c478bd9Sstevel@tonic-gate { 1228*7c478bd9Sstevel@tonic-gate char *s = NULL; 1229*7c478bd9Sstevel@tonic-gate uint_t cont = 0; 1230*7c478bd9Sstevel@tonic-gate if (flag & D_CONT) { 1231*7c478bd9Sstevel@tonic-gate flag &= ~D_CONT; 1232*7c478bd9Sstevel@tonic-gate cont = 1; 1233*7c478bd9Sstevel@tonic-gate } 1234*7c478bd9Sstevel@tonic-gate if (!(upa64s_debug_flags & flag)) 1235*7c478bd9Sstevel@tonic-gate return; 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate switch (flag) { 1238*7c478bd9Sstevel@tonic-gate case D_ATTACH: s = "attach"; break; 1239*7c478bd9Sstevel@tonic-gate case D_DETACH: s = "detach"; break; 1240*7c478bd9Sstevel@tonic-gate case D_POWER: s = "power"; break; 1241*7c478bd9Sstevel@tonic-gate case D_MAP: s = "map"; break; 1242*7c478bd9Sstevel@tonic-gate case D_CTLOPS: s = "ctlops"; break; 1243*7c478bd9Sstevel@tonic-gate case D_G_ISPEC: s = "get_intrspec"; break; 1244*7c478bd9Sstevel@tonic-gate case D_A_ISPEC: s = "add_intrspec"; break; 1245*7c478bd9Sstevel@tonic-gate case D_R_ISPEC: s = "remove_intrspec"; break; 1246*7c478bd9Sstevel@tonic-gate case D_INIT_CLD: s = "init_child"; break; 1247*7c478bd9Sstevel@tonic-gate case D_INTRDIST: s = "intrdist"; break; 1248*7c478bd9Sstevel@tonic-gate } 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate if (s && cont == 0) { 1251*7c478bd9Sstevel@tonic-gate prom_printf("%s(%d): %s: ", ddi_get_name(dip), 1252*7c478bd9Sstevel@tonic-gate ddi_get_instance(dip), s); 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate prom_printf(fmt, a1, a2, a3, a4, a5); 1255*7c478bd9Sstevel@tonic-gate } 1256*7c478bd9Sstevel@tonic-gate #endif 1257