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 * sun4 root nexus driver 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/ddi_subrdefs.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/async.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/intr.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/ndifm.h> 41*7c478bd9Sstevel@tonic-gate #include <vm/seg_dev.h> 42*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/ontrap.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* Useful debugging Stuff */ 46*7c478bd9Sstevel@tonic-gate #include <sys/nexusdebug.h> 47*7c478bd9Sstevel@tonic-gate #define ROOTNEX_MAP_DEBUG 0x1 48*7c478bd9Sstevel@tonic-gate #define ROOTNEX_INTR_DEBUG 0x2 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* 51*7c478bd9Sstevel@tonic-gate * config information 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate static int 55*7c478bd9Sstevel@tonic-gate rootnex_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 56*7c478bd9Sstevel@tonic-gate off_t offset, off_t len, caddr_t *vaddrp); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate static int 59*7c478bd9Sstevel@tonic-gate rootnex_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t, 60*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *, void *); 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate static int 63*7c478bd9Sstevel@tonic-gate rootnex_map_fault(dev_info_t *dip, dev_info_t *rdip, 64*7c478bd9Sstevel@tonic-gate struct hat *hat, struct seg *seg, caddr_t addr, 65*7c478bd9Sstevel@tonic-gate struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock); 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate static int 68*7c478bd9Sstevel@tonic-gate rootnex_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *); 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate static int 71*7c478bd9Sstevel@tonic-gate rootnex_busop_fminit(dev_info_t *dip, dev_info_t *tdip, int tcap, 72*7c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *ibc); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate static void 75*7c478bd9Sstevel@tonic-gate rootnex_fm_init(dev_info_t *); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate static int 78*7c478bd9Sstevel@tonic-gate rootnex_ctlops_peekpoke(ddi_ctl_enum_t, peekpoke_ctlops_t *, void *result); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * Defined in $KARCH/io/mach_rootnex.c 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate int rootnex_add_intr_impl(dev_info_t *dip, dev_info_t *rdip, 84*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp); 85*7c478bd9Sstevel@tonic-gate #pragma weak rootnex_add_intr_impl 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate int rootnex_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip, 88*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp); 89*7c478bd9Sstevel@tonic-gate #pragma weak rootnex_remove_intr_impl 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate void rootnex_get_intr_pri(dev_info_t *dip, dev_info_t *rdip, 92*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp); 93*7c478bd9Sstevel@tonic-gate #pragma weak rootnex_get_intr_pri 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate int rootnex_name_child_impl(dev_info_t *child, char *name, int namelen); 96*7c478bd9Sstevel@tonic-gate #pragma weak rootnex_name_child_impl 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate int rootnex_ctl_initchild_impl(dev_info_t *dip); 99*7c478bd9Sstevel@tonic-gate #pragma weak rootnex_initchild_impl 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate void rootnex_ctl_uninitchild_impl(dev_info_t *dip); 102*7c478bd9Sstevel@tonic-gate #pragma weak rootnex_uninitchild_impl 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate int rootnex_ctl_reportdev_impl(dev_info_t *dev); 105*7c478bd9Sstevel@tonic-gate #pragma weak rootnex_reportdev_impl 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate static struct cb_ops rootnex_cb_ops = { 108*7c478bd9Sstevel@tonic-gate nodev, /* open */ 109*7c478bd9Sstevel@tonic-gate nodev, /* close */ 110*7c478bd9Sstevel@tonic-gate nodev, /* strategy */ 111*7c478bd9Sstevel@tonic-gate nodev, /* print */ 112*7c478bd9Sstevel@tonic-gate nodev, /* dump */ 113*7c478bd9Sstevel@tonic-gate nodev, /* read */ 114*7c478bd9Sstevel@tonic-gate nodev, /* write */ 115*7c478bd9Sstevel@tonic-gate nodev, /* ioctl */ 116*7c478bd9Sstevel@tonic-gate nodev, /* devmap */ 117*7c478bd9Sstevel@tonic-gate nodev, /* mmap */ 118*7c478bd9Sstevel@tonic-gate nodev, /* segmap */ 119*7c478bd9Sstevel@tonic-gate nochpoll, /* chpoll */ 120*7c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 121*7c478bd9Sstevel@tonic-gate NULL, /* struct streamtab */ 122*7c478bd9Sstevel@tonic-gate D_NEW | D_MP | D_HOTPLUG, /* compatibility flags */ 123*7c478bd9Sstevel@tonic-gate CB_REV, /* Rev */ 124*7c478bd9Sstevel@tonic-gate nodev, /* cb_aread */ 125*7c478bd9Sstevel@tonic-gate nodev /* cb_awrite */ 126*7c478bd9Sstevel@tonic-gate }; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate static struct bus_ops rootnex_bus_ops = { 129*7c478bd9Sstevel@tonic-gate BUSO_REV, 130*7c478bd9Sstevel@tonic-gate rootnex_map, 131*7c478bd9Sstevel@tonic-gate NULL, 132*7c478bd9Sstevel@tonic-gate NULL, 133*7c478bd9Sstevel@tonic-gate NULL, 134*7c478bd9Sstevel@tonic-gate rootnex_map_fault, 135*7c478bd9Sstevel@tonic-gate ddi_no_dma_map, /* no rootnex_dma_map- now in sysio nexus */ 136*7c478bd9Sstevel@tonic-gate ddi_no_dma_allochdl, 137*7c478bd9Sstevel@tonic-gate ddi_no_dma_freehdl, 138*7c478bd9Sstevel@tonic-gate ddi_no_dma_bindhdl, 139*7c478bd9Sstevel@tonic-gate ddi_no_dma_unbindhdl, 140*7c478bd9Sstevel@tonic-gate ddi_no_dma_flush, 141*7c478bd9Sstevel@tonic-gate ddi_no_dma_win, 142*7c478bd9Sstevel@tonic-gate ddi_no_dma_mctl, /* no rootnex_dma_mctl- now in sysio nexus */ 143*7c478bd9Sstevel@tonic-gate rootnex_ctlops, 144*7c478bd9Sstevel@tonic-gate ddi_bus_prop_op, 145*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_get_eventcookie, 146*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_add_eventcall, 147*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_remove_eventcall, 148*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_post_event, 149*7c478bd9Sstevel@tonic-gate NULL, /* bus_intr_ctl */ 150*7c478bd9Sstevel@tonic-gate NULL, /* bus_config */ 151*7c478bd9Sstevel@tonic-gate NULL, /* bus_unconfig */ 152*7c478bd9Sstevel@tonic-gate rootnex_busop_fminit, /* bus_fm_init */ 153*7c478bd9Sstevel@tonic-gate NULL, /* bus_fm_fini */ 154*7c478bd9Sstevel@tonic-gate NULL, /* bus_fm_access_enter */ 155*7c478bd9Sstevel@tonic-gate NULL, /* bus_fm_access_fini */ 156*7c478bd9Sstevel@tonic-gate NULL, /* bus_power */ 157*7c478bd9Sstevel@tonic-gate rootnex_intr_ops /* bus_intr_op */ 158*7c478bd9Sstevel@tonic-gate }; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate static int rootnex_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 161*7c478bd9Sstevel@tonic-gate static int rootnex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate static struct dev_ops rootnex_ops = { 164*7c478bd9Sstevel@tonic-gate DEVO_REV, 165*7c478bd9Sstevel@tonic-gate 0, /* refcnt */ 166*7c478bd9Sstevel@tonic-gate ddi_no_info, /* info */ 167*7c478bd9Sstevel@tonic-gate nulldev, 168*7c478bd9Sstevel@tonic-gate nulldev, /* probe */ 169*7c478bd9Sstevel@tonic-gate rootnex_attach, 170*7c478bd9Sstevel@tonic-gate rootnex_detach, 171*7c478bd9Sstevel@tonic-gate nodev, /* reset */ 172*7c478bd9Sstevel@tonic-gate &rootnex_cb_ops, 173*7c478bd9Sstevel@tonic-gate &rootnex_bus_ops 174*7c478bd9Sstevel@tonic-gate }; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate extern uint_t root_phys_addr_lo_mask; 178*7c478bd9Sstevel@tonic-gate extern uint_t root_phys_addr_hi_mask; 179*7c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops; 180*7c478bd9Sstevel@tonic-gate extern struct dev_ops rootnex_ops; 181*7c478bd9Sstevel@tonic-gate extern struct cpu cpu0; 182*7c478bd9Sstevel@tonic-gate extern ddi_iblock_cookie_t rootnex_err_ibc; 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * Add statically defined root properties to this list... 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate static const int pagesize = PAGESIZE; 189*7c478bd9Sstevel@tonic-gate static const int mmu_pagesize = MMU_PAGESIZE; 190*7c478bd9Sstevel@tonic-gate static const int mmu_pageoffset = MMU_PAGEOFFSET; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate struct prop_def { 193*7c478bd9Sstevel@tonic-gate char *prop_name; 194*7c478bd9Sstevel@tonic-gate caddr_t prop_value; 195*7c478bd9Sstevel@tonic-gate }; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate static struct prop_def root_props[] = { 198*7c478bd9Sstevel@tonic-gate { "PAGESIZE", (caddr_t)&pagesize }, 199*7c478bd9Sstevel@tonic-gate { "MMU_PAGESIZE", (caddr_t)&mmu_pagesize}, 200*7c478bd9Sstevel@tonic-gate { "MMU_PAGEOFFSET", (caddr_t)&mmu_pageoffset}, 201*7c478bd9Sstevel@tonic-gate }; 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate static vmem_t *rootnex_regspec_arena; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate #define NROOT_PROPS (sizeof (root_props) / sizeof (struct prop_def)) 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate /* 210*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 214*7c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a nexus driver */ 215*7c478bd9Sstevel@tonic-gate "sun4 root nexus %I%", 216*7c478bd9Sstevel@tonic-gate &rootnex_ops, /* Driver ops */ 217*7c478bd9Sstevel@tonic-gate }; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 220*7c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 221*7c478bd9Sstevel@tonic-gate }; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate int 224*7c478bd9Sstevel@tonic-gate _init(void) 225*7c478bd9Sstevel@tonic-gate { 226*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate int 230*7c478bd9Sstevel@tonic-gate _fini(void) 231*7c478bd9Sstevel@tonic-gate { 232*7c478bd9Sstevel@tonic-gate return (EBUSY); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate int 236*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 237*7c478bd9Sstevel@tonic-gate { 238*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* 242*7c478bd9Sstevel@tonic-gate * rootnex_attach: 243*7c478bd9Sstevel@tonic-gate * 244*7c478bd9Sstevel@tonic-gate * attach the root nexus. 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate static void add_root_props(dev_info_t *); 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 249*7c478bd9Sstevel@tonic-gate static int 250*7c478bd9Sstevel@tonic-gate rootnex_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 251*7c478bd9Sstevel@tonic-gate { 252*7c478bd9Sstevel@tonic-gate int length; 253*7c478bd9Sstevel@tonic-gate char *valuep = NULL; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* 256*7c478bd9Sstevel@tonic-gate * Only do these functions when the driver is acting as the 257*7c478bd9Sstevel@tonic-gate * root nexus, not when it is driving a memory controller. 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate if (ddi_root_node() == devi) { 260*7c478bd9Sstevel@tonic-gate rootnex_fm_init(devi); 261*7c478bd9Sstevel@tonic-gate add_root_props(devi); 262*7c478bd9Sstevel@tonic-gate i_ddi_rootnex_init_events(devi); 263*7c478bd9Sstevel@tonic-gate rootnex_regspec_arena = vmem_create("regspec", 264*7c478bd9Sstevel@tonic-gate (void *)PIOMAPBASE, PIOMAPSIZE, MMU_PAGESIZE, NULL, NULL, 265*7c478bd9Sstevel@tonic-gate NULL, 0, VM_SLEEP); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, devi, PROP_LEN_AND_VAL_ALLOC, 269*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "banner-name", (caddr_t)&valuep, 270*7c478bd9Sstevel@tonic-gate &length) == DDI_PROP_SUCCESS) { 271*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root nexus = %s\n", valuep); 272*7c478bd9Sstevel@tonic-gate kmem_free(valuep, length); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * Add a no-suspend-resume property so that NDI 276*7c478bd9Sstevel@tonic-gate * does not attempt to suspend/resume the rootnex 277*7c478bd9Sstevel@tonic-gate * (or any of its aliases) node. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi, 280*7c478bd9Sstevel@tonic-gate "pm-hardware-state", "no-suspend-resume"); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 286*7c478bd9Sstevel@tonic-gate static int 287*7c478bd9Sstevel@tonic-gate rootnex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 288*7c478bd9Sstevel@tonic-gate { 289*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate static void 293*7c478bd9Sstevel@tonic-gate add_root_props(dev_info_t *devi) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate int i; 296*7c478bd9Sstevel@tonic-gate struct prop_def *rpp; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * Note that this for loop works because all of the 300*7c478bd9Sstevel@tonic-gate * properties in root_prop are integers 301*7c478bd9Sstevel@tonic-gate */ 302*7c478bd9Sstevel@tonic-gate for (i = 0, rpp = root_props; i < NROOT_PROPS; ++i, ++rpp) { 303*7c478bd9Sstevel@tonic-gate (void) e_ddi_prop_update_int(DDI_DEV_T_NONE, devi, 304*7c478bd9Sstevel@tonic-gate rpp->prop_name, *((int *)rpp->prop_value)); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* 308*7c478bd9Sstevel@tonic-gate * Create the root node "boolean" property 309*7c478bd9Sstevel@tonic-gate * corresponding to addressing type supported in the root node: 310*7c478bd9Sstevel@tonic-gate * 311*7c478bd9Sstevel@tonic-gate * Choices are: 312*7c478bd9Sstevel@tonic-gate * "relative-addressing" (OBP PROMS) 313*7c478bd9Sstevel@tonic-gate * "generic-addressing" (SunMon -- pseudo OBP/DDI) 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate (void) e_ddi_prop_update_int(DDI_DEV_T_NONE, devi, 317*7c478bd9Sstevel@tonic-gate DDI_RELATIVE_ADDRESSING, 1); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* 320*7c478bd9Sstevel@tonic-gate * Create fault management capability property 321*7c478bd9Sstevel@tonic-gate */ 322*7c478bd9Sstevel@tonic-gate (void) e_ddi_prop_update_int(DDI_DEV_T_NONE, devi, "fm-capable", 323*7c478bd9Sstevel@tonic-gate ddi_fm_capable(devi)); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate static int 327*7c478bd9Sstevel@tonic-gate rootnex_map_regspec(ddi_map_req_t *mp, caddr_t *vaddrp, uint_t mapping_attr) 328*7c478bd9Sstevel@tonic-gate { 329*7c478bd9Sstevel@tonic-gate ulong_t base; 330*7c478bd9Sstevel@tonic-gate caddr_t kaddr; 331*7c478bd9Sstevel@tonic-gate pgcnt_t npages; 332*7c478bd9Sstevel@tonic-gate pfn_t pfn; 333*7c478bd9Sstevel@tonic-gate uint_t pgoffset; 334*7c478bd9Sstevel@tonic-gate struct regspec *rp = mp->map_obj.rp; 335*7c478bd9Sstevel@tonic-gate ddi_acc_hdl_t *hp; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate base = (ulong_t)rp->regspec_addr & (~MMU_PAGEOFFSET); /* base addr */ 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* 340*7c478bd9Sstevel@tonic-gate * Take the bustype and the physical page base within the 341*7c478bd9Sstevel@tonic-gate * bus space and turn it into a 28 bit page frame number. 342*7c478bd9Sstevel@tonic-gate */ 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate pfn = BUSTYPE_TO_PFN(((rp->regspec_bustype) & root_phys_addr_hi_mask), 345*7c478bd9Sstevel@tonic-gate mmu_btop(base)); 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * Do a quick sanity check to make sure we are in I/O space. 350*7c478bd9Sstevel@tonic-gate */ 351*7c478bd9Sstevel@tonic-gate if (pf_is_memory(pfn)) 352*7c478bd9Sstevel@tonic-gate return (DDI_ME_INVAL); 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate if (rp->regspec_size == 0) { 355*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_map_regspec: zero " 356*7c478bd9Sstevel@tonic-gate "regspec_size\n")); 357*7c478bd9Sstevel@tonic-gate return (DDI_ME_INVAL); 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate if (mp->map_flags & DDI_MF_DEVICE_MAPPING) 361*7c478bd9Sstevel@tonic-gate *vaddrp = (caddr_t)pfn; 362*7c478bd9Sstevel@tonic-gate else { 363*7c478bd9Sstevel@tonic-gate pgoffset = (ulong_t)rp->regspec_addr & MMU_PAGEOFFSET; 364*7c478bd9Sstevel@tonic-gate npages = mmu_btopr(rp->regspec_size + pgoffset); 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_map_regspec: Mapping " 367*7c478bd9Sstevel@tonic-gate "%lu pages physical %x.%lx ", npages, rp->regspec_bustype, 368*7c478bd9Sstevel@tonic-gate base)); 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate if ((kaddr = vmem_alloc(rootnex_regspec_arena, 371*7c478bd9Sstevel@tonic-gate ptob(npages), VM_NOSLEEP)) == NULL) 372*7c478bd9Sstevel@tonic-gate return (DDI_ME_NORESOURCES); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate /* 375*7c478bd9Sstevel@tonic-gate * Now map in the pages we've allocated... 376*7c478bd9Sstevel@tonic-gate */ 377*7c478bd9Sstevel@tonic-gate hat_devload(kas.a_hat, kaddr, ptob(npages), pfn, 378*7c478bd9Sstevel@tonic-gate mp->map_prot | mapping_attr, HAT_LOAD_LOCK); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate *vaddrp = kaddr + pgoffset; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate hp = mp->map_handlep; 383*7c478bd9Sstevel@tonic-gate if (hp) { 384*7c478bd9Sstevel@tonic-gate hp->ah_pfn = pfn; 385*7c478bd9Sstevel@tonic-gate hp->ah_pnum = npages; 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("at virtual 0x%x\n", *vaddrp)); 390*7c478bd9Sstevel@tonic-gate return (0); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate static int 394*7c478bd9Sstevel@tonic-gate rootnex_unmap_regspec(ddi_map_req_t *mp, caddr_t *vaddrp) 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate caddr_t addr = *vaddrp; 397*7c478bd9Sstevel@tonic-gate pgcnt_t npages; 398*7c478bd9Sstevel@tonic-gate uint_t pgoffset; 399*7c478bd9Sstevel@tonic-gate caddr_t base; 400*7c478bd9Sstevel@tonic-gate struct regspec *rp; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate if (mp->map_flags & DDI_MF_DEVICE_MAPPING) 403*7c478bd9Sstevel@tonic-gate return (0); 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate rp = mp->map_obj.rp; 406*7c478bd9Sstevel@tonic-gate pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate if (rp->regspec_size == 0) { 409*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_unmap_regspec: " 410*7c478bd9Sstevel@tonic-gate "zero regspec_size\n")); 411*7c478bd9Sstevel@tonic-gate return (DDI_ME_INVAL); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate base = addr - pgoffset; 415*7c478bd9Sstevel@tonic-gate npages = mmu_btopr(rp->regspec_size + pgoffset); 416*7c478bd9Sstevel@tonic-gate hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK); 417*7c478bd9Sstevel@tonic-gate vmem_free(rootnex_regspec_arena, base, ptob(npages)); 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * Destroy the pointer - the mapping has logically gone 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate *vaddrp = (caddr_t)0; 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate return (0); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate static int 428*7c478bd9Sstevel@tonic-gate rootnex_map_handle(ddi_map_req_t *mp) 429*7c478bd9Sstevel@tonic-gate { 430*7c478bd9Sstevel@tonic-gate ddi_acc_hdl_t *hp; 431*7c478bd9Sstevel@tonic-gate uint_t hat_flags; 432*7c478bd9Sstevel@tonic-gate register struct regspec *rp; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * Set up the hat_flags for the mapping. 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate hp = mp->map_handlep; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate switch (hp->ah_acc.devacc_attr_endian_flags) { 440*7c478bd9Sstevel@tonic-gate case DDI_NEVERSWAP_ACC: 441*7c478bd9Sstevel@tonic-gate hat_flags = HAT_NEVERSWAP | HAT_STRICTORDER; 442*7c478bd9Sstevel@tonic-gate break; 443*7c478bd9Sstevel@tonic-gate case DDI_STRUCTURE_BE_ACC: 444*7c478bd9Sstevel@tonic-gate hat_flags = HAT_STRUCTURE_BE; 445*7c478bd9Sstevel@tonic-gate break; 446*7c478bd9Sstevel@tonic-gate case DDI_STRUCTURE_LE_ACC: 447*7c478bd9Sstevel@tonic-gate hat_flags = HAT_STRUCTURE_LE; 448*7c478bd9Sstevel@tonic-gate break; 449*7c478bd9Sstevel@tonic-gate default: 450*7c478bd9Sstevel@tonic-gate return (DDI_REGS_ACC_CONFLICT); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate switch (hp->ah_acc.devacc_attr_dataorder) { 454*7c478bd9Sstevel@tonic-gate case DDI_STRICTORDER_ACC: 455*7c478bd9Sstevel@tonic-gate break; 456*7c478bd9Sstevel@tonic-gate case DDI_UNORDERED_OK_ACC: 457*7c478bd9Sstevel@tonic-gate hat_flags |= HAT_UNORDERED_OK; 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate case DDI_MERGING_OK_ACC: 460*7c478bd9Sstevel@tonic-gate hat_flags |= HAT_MERGING_OK; 461*7c478bd9Sstevel@tonic-gate break; 462*7c478bd9Sstevel@tonic-gate case DDI_LOADCACHING_OK_ACC: 463*7c478bd9Sstevel@tonic-gate hat_flags |= HAT_LOADCACHING_OK; 464*7c478bd9Sstevel@tonic-gate break; 465*7c478bd9Sstevel@tonic-gate case DDI_STORECACHING_OK_ACC: 466*7c478bd9Sstevel@tonic-gate hat_flags |= HAT_STORECACHING_OK; 467*7c478bd9Sstevel@tonic-gate break; 468*7c478bd9Sstevel@tonic-gate default: 469*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate rp = mp->map_obj.rp; 473*7c478bd9Sstevel@tonic-gate if (rp->regspec_size == 0) 474*7c478bd9Sstevel@tonic-gate return (DDI_ME_INVAL); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate hp->ah_hat_flags = hat_flags; 477*7c478bd9Sstevel@tonic-gate hp->ah_pfn = mmu_btop((ulong_t)rp->regspec_addr & (~MMU_PAGEOFFSET)); 478*7c478bd9Sstevel@tonic-gate hp->ah_pnum = mmu_btopr(rp->regspec_size + 479*7c478bd9Sstevel@tonic-gate (ulong_t)rp->regspec_addr & MMU_PAGEOFFSET); 480*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate static int 484*7c478bd9Sstevel@tonic-gate rootnex_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 485*7c478bd9Sstevel@tonic-gate off_t offset, off_t len, caddr_t *vaddrp) 486*7c478bd9Sstevel@tonic-gate { 487*7c478bd9Sstevel@tonic-gate struct regspec *rp, tmp_reg; 488*7c478bd9Sstevel@tonic-gate ddi_map_req_t mr = *mp; /* Get private copy of request */ 489*7c478bd9Sstevel@tonic-gate int error; 490*7c478bd9Sstevel@tonic-gate uint_t mapping_attr; 491*7c478bd9Sstevel@tonic-gate ddi_acc_hdl_t *hp = NULL; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate mp = &mr; 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate switch (mp->map_op) { 496*7c478bd9Sstevel@tonic-gate case DDI_MO_MAP_LOCKED: 497*7c478bd9Sstevel@tonic-gate case DDI_MO_UNMAP: 498*7c478bd9Sstevel@tonic-gate case DDI_MO_MAP_HANDLE: 499*7c478bd9Sstevel@tonic-gate break; 500*7c478bd9Sstevel@tonic-gate default: 501*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_map: unimplemented map " 502*7c478bd9Sstevel@tonic-gate "op %d.", mp->map_op)); 503*7c478bd9Sstevel@tonic-gate return (DDI_ME_UNIMPLEMENTED); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if (mp->map_flags & DDI_MF_USER_MAPPING) { 507*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_map: unimplemented map " 508*7c478bd9Sstevel@tonic-gate "type: user.")); 509*7c478bd9Sstevel@tonic-gate return (DDI_ME_UNIMPLEMENTED); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* 513*7c478bd9Sstevel@tonic-gate * First, if given an rnumber, convert it to a regspec... 514*7c478bd9Sstevel@tonic-gate * (Presumably, this is on behalf of a child of the root node?) 515*7c478bd9Sstevel@tonic-gate */ 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate if (mp->map_type == DDI_MT_RNUMBER) { 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate int rnumber = mp->map_obj.rnumber; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate rp = i_ddi_rnumber_to_regspec(rdip, rnumber); 522*7c478bd9Sstevel@tonic-gate if (rp == (struct regspec *)0) { 523*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_map: Out of " 524*7c478bd9Sstevel@tonic-gate "range rnumber <%d>, device <%s>", rnumber, 525*7c478bd9Sstevel@tonic-gate ddi_get_name(rdip))); 526*7c478bd9Sstevel@tonic-gate return (DDI_ME_RNUMBER_RANGE); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* 530*7c478bd9Sstevel@tonic-gate * Convert the given ddi_map_req_t from rnumber to regspec... 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate mp->map_type = DDI_MT_REGSPEC; 534*7c478bd9Sstevel@tonic-gate mp->map_obj.rp = rp; 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate /* 538*7c478bd9Sstevel@tonic-gate * Adjust offset and length corresponding to called values... 539*7c478bd9Sstevel@tonic-gate * XXX: A non-zero length means override the one in the regspec 540*7c478bd9Sstevel@tonic-gate * XXX: regardless of what's in the parent's range?. 541*7c478bd9Sstevel@tonic-gate */ 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate tmp_reg = *(mp->map_obj.rp); /* Preserve underlying data */ 544*7c478bd9Sstevel@tonic-gate rp = mp->map_obj.rp = &tmp_reg; /* Use tmp_reg in request */ 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate rp->regspec_addr += (uint_t)offset; 547*7c478bd9Sstevel@tonic-gate if (len != 0) 548*7c478bd9Sstevel@tonic-gate rp->regspec_size = (uint_t)len; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* 551*7c478bd9Sstevel@tonic-gate * Apply any parent ranges at this level, if applicable. 552*7c478bd9Sstevel@tonic-gate * (This is where nexus specific regspec translation takes place. 553*7c478bd9Sstevel@tonic-gate * Use of this function is implicit agreement that translation is 554*7c478bd9Sstevel@tonic-gate * provided via ddi_apply_range.) 555*7c478bd9Sstevel@tonic-gate */ 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_map: applying range of parent " 558*7c478bd9Sstevel@tonic-gate "<%s> to child <%s>...\n", ddi_get_name(dip), ddi_get_name(rdip))); 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate if ((error = i_ddi_apply_range(dip, rdip, mp->map_obj.rp)) != 0) 561*7c478bd9Sstevel@tonic-gate return (error); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate switch (mp->map_op) { 564*7c478bd9Sstevel@tonic-gate case DDI_MO_MAP_LOCKED: 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate /* 567*7c478bd9Sstevel@tonic-gate * Set up the locked down kernel mapping to the regspec... 568*7c478bd9Sstevel@tonic-gate */ 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate /* 571*7c478bd9Sstevel@tonic-gate * If we were passed an access handle we need to determine 572*7c478bd9Sstevel@tonic-gate * the "endian-ness" of the mapping and fill in the handle. 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate if (mp->map_handlep) { 575*7c478bd9Sstevel@tonic-gate hp = mp->map_handlep; 576*7c478bd9Sstevel@tonic-gate switch (hp->ah_acc.devacc_attr_endian_flags) { 577*7c478bd9Sstevel@tonic-gate case DDI_NEVERSWAP_ACC: 578*7c478bd9Sstevel@tonic-gate mapping_attr = HAT_NEVERSWAP | HAT_STRICTORDER; 579*7c478bd9Sstevel@tonic-gate break; 580*7c478bd9Sstevel@tonic-gate case DDI_STRUCTURE_BE_ACC: 581*7c478bd9Sstevel@tonic-gate mapping_attr = HAT_STRUCTURE_BE; 582*7c478bd9Sstevel@tonic-gate break; 583*7c478bd9Sstevel@tonic-gate case DDI_STRUCTURE_LE_ACC: 584*7c478bd9Sstevel@tonic-gate mapping_attr = HAT_STRUCTURE_LE; 585*7c478bd9Sstevel@tonic-gate break; 586*7c478bd9Sstevel@tonic-gate default: 587*7c478bd9Sstevel@tonic-gate return (DDI_REGS_ACC_CONFLICT); 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate switch (hp->ah_acc.devacc_attr_dataorder) { 591*7c478bd9Sstevel@tonic-gate case DDI_STRICTORDER_ACC: 592*7c478bd9Sstevel@tonic-gate break; 593*7c478bd9Sstevel@tonic-gate case DDI_UNORDERED_OK_ACC: 594*7c478bd9Sstevel@tonic-gate mapping_attr |= HAT_UNORDERED_OK; 595*7c478bd9Sstevel@tonic-gate break; 596*7c478bd9Sstevel@tonic-gate case DDI_MERGING_OK_ACC: 597*7c478bd9Sstevel@tonic-gate mapping_attr |= HAT_MERGING_OK; 598*7c478bd9Sstevel@tonic-gate break; 599*7c478bd9Sstevel@tonic-gate case DDI_LOADCACHING_OK_ACC: 600*7c478bd9Sstevel@tonic-gate mapping_attr |= HAT_LOADCACHING_OK; 601*7c478bd9Sstevel@tonic-gate break; 602*7c478bd9Sstevel@tonic-gate case DDI_STORECACHING_OK_ACC: 603*7c478bd9Sstevel@tonic-gate mapping_attr |= HAT_STORECACHING_OK; 604*7c478bd9Sstevel@tonic-gate break; 605*7c478bd9Sstevel@tonic-gate default: 606*7c478bd9Sstevel@tonic-gate return (DDI_REGS_ACC_CONFLICT); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate } else { 609*7c478bd9Sstevel@tonic-gate mapping_attr = HAT_NEVERSWAP | HAT_STRICTORDER; 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * Set up the mapping. 614*7c478bd9Sstevel@tonic-gate */ 615*7c478bd9Sstevel@tonic-gate error = rootnex_map_regspec(mp, vaddrp, mapping_attr); 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* 618*7c478bd9Sstevel@tonic-gate * Fill in the access handle if needed. 619*7c478bd9Sstevel@tonic-gate */ 620*7c478bd9Sstevel@tonic-gate if (hp) { 621*7c478bd9Sstevel@tonic-gate hp->ah_addr = *vaddrp; 622*7c478bd9Sstevel@tonic-gate hp->ah_hat_flags = mapping_attr; 623*7c478bd9Sstevel@tonic-gate if (error == 0) 624*7c478bd9Sstevel@tonic-gate impl_acc_hdl_init(hp); 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate return (error); 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate case DDI_MO_UNMAP: 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate /* 631*7c478bd9Sstevel@tonic-gate * Release mapping... 632*7c478bd9Sstevel@tonic-gate */ 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate return (rootnex_unmap_regspec(mp, vaddrp)); 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate case DDI_MO_MAP_HANDLE: 637*7c478bd9Sstevel@tonic-gate return (rootnex_map_handle(mp)); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate return (DDI_ME_UNIMPLEMENTED); 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate static int 645*7c478bd9Sstevel@tonic-gate rootnex_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 646*7c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result) 647*7c478bd9Sstevel@tonic-gate { 648*7c478bd9Sstevel@tonic-gate ddi_ispec_t *ip = (ddi_ispec_t *)hdlp->ih_private; 649*7c478bd9Sstevel@tonic-gate int ret = DDI_SUCCESS; 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_INTR_DEBUG, ("rootnex_intr_ops: rdip=%s%d " 652*7c478bd9Sstevel@tonic-gate "intr_op 0x%x hdlp 0x%p\n", ddi_driver_name(rdip), 653*7c478bd9Sstevel@tonic-gate ddi_get_instance(rdip), intr_op, hdlp)); 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate switch (intr_op) { 656*7c478bd9Sstevel@tonic-gate case DDI_INTROP_GETCAP: 657*7c478bd9Sstevel@tonic-gate *(int *)result = 0; 658*7c478bd9Sstevel@tonic-gate break; 659*7c478bd9Sstevel@tonic-gate case DDI_INTROP_SETCAP: 660*7c478bd9Sstevel@tonic-gate ret = DDI_ENOTSUP; 661*7c478bd9Sstevel@tonic-gate break; 662*7c478bd9Sstevel@tonic-gate case DDI_INTROP_ALLOC: 663*7c478bd9Sstevel@tonic-gate *(int *)result = hdlp->ih_scratch1; 664*7c478bd9Sstevel@tonic-gate break; 665*7c478bd9Sstevel@tonic-gate case DDI_INTROP_FREE: 666*7c478bd9Sstevel@tonic-gate break; 667*7c478bd9Sstevel@tonic-gate case DDI_INTROP_GETPRI: 668*7c478bd9Sstevel@tonic-gate rootnex_get_intr_pri(dip, rdip, hdlp); 669*7c478bd9Sstevel@tonic-gate *(int *)result = ip->is_pil; 670*7c478bd9Sstevel@tonic-gate break; 671*7c478bd9Sstevel@tonic-gate case DDI_INTROP_SETPRI: 672*7c478bd9Sstevel@tonic-gate ip->is_pil = (*(int *)result); 673*7c478bd9Sstevel@tonic-gate break; 674*7c478bd9Sstevel@tonic-gate case DDI_INTROP_ADDISR: 675*7c478bd9Sstevel@tonic-gate ret = rootnex_add_intr_impl(dip, rdip, hdlp); 676*7c478bd9Sstevel@tonic-gate break; 677*7c478bd9Sstevel@tonic-gate case DDI_INTROP_REMISR: 678*7c478bd9Sstevel@tonic-gate ret = rootnex_remove_intr_impl(dip, rdip, hdlp); 679*7c478bd9Sstevel@tonic-gate break; 680*7c478bd9Sstevel@tonic-gate case DDI_INTROP_ENABLE: 681*7c478bd9Sstevel@tonic-gate case DDI_INTROP_DISABLE: 682*7c478bd9Sstevel@tonic-gate break; 683*7c478bd9Sstevel@tonic-gate case DDI_INTROP_NINTRS: 684*7c478bd9Sstevel@tonic-gate case DDI_INTROP_NAVAIL: 685*7c478bd9Sstevel@tonic-gate *(int *)result = i_ddi_get_nintrs(rdip); 686*7c478bd9Sstevel@tonic-gate break; 687*7c478bd9Sstevel@tonic-gate case DDI_INTROP_SUPPORTED_TYPES: 688*7c478bd9Sstevel@tonic-gate /* Root nexus driver supports only fixed interrupts */ 689*7c478bd9Sstevel@tonic-gate *(int *)result = i_ddi_get_nintrs(rdip) ? 690*7c478bd9Sstevel@tonic-gate DDI_INTR_TYPE_FIXED : 0; 691*7c478bd9Sstevel@tonic-gate break; 692*7c478bd9Sstevel@tonic-gate default: 693*7c478bd9Sstevel@tonic-gate ret = DDI_ENOTSUP; 694*7c478bd9Sstevel@tonic-gate break; 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate return (ret); 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate /* 702*7c478bd9Sstevel@tonic-gate * Shorthand defines 703*7c478bd9Sstevel@tonic-gate */ 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate #define DMAOBJ_PP_PP dmao_obj.pp_obj.pp_pp 706*7c478bd9Sstevel@tonic-gate #define DMAOBJ_PP_OFF dmao_ogj.pp_obj.pp_offset 707*7c478bd9Sstevel@tonic-gate #define ALO dma_lim->dlim_addr_lo 708*7c478bd9Sstevel@tonic-gate #define AHI dma_lim->dlim_addr_hi 709*7c478bd9Sstevel@tonic-gate #define OBJSIZE dmareq->dmar_object.dmao_size 710*7c478bd9Sstevel@tonic-gate #define ORIGVADDR dmareq->dmar_object.dmao_obj.virt_obj.v_addr 711*7c478bd9Sstevel@tonic-gate #define RED ((mp->dmai_rflags & DDI_DMA_REDZONE)? 1 : 0) 712*7c478bd9Sstevel@tonic-gate #define DIRECTION (mp->dmai_rflags & DDI_DMA_RDWR) 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate /* 715*7c478bd9Sstevel@tonic-gate * rootnex_map_fault: 716*7c478bd9Sstevel@tonic-gate * 717*7c478bd9Sstevel@tonic-gate * fault in mappings for requestors 718*7c478bd9Sstevel@tonic-gate */ 719*7c478bd9Sstevel@tonic-gate 720*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 721*7c478bd9Sstevel@tonic-gate static int 722*7c478bd9Sstevel@tonic-gate rootnex_map_fault(dev_info_t *dip, dev_info_t *rdip, 723*7c478bd9Sstevel@tonic-gate struct hat *hat, struct seg *seg, caddr_t addr, 724*7c478bd9Sstevel@tonic-gate struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock) 725*7c478bd9Sstevel@tonic-gate { 726*7c478bd9Sstevel@tonic-gate extern struct seg_ops segdev_ops; 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, ("rootnex_map_fault: address <%x> " 729*7c478bd9Sstevel@tonic-gate "pfn <%x>", addr, pfn)); 730*7c478bd9Sstevel@tonic-gate DPRINTF(ROOTNEX_MAP_DEBUG, (" Seg <%s>\n", 731*7c478bd9Sstevel@tonic-gate seg->s_ops == &segdev_ops ? "segdev" : 732*7c478bd9Sstevel@tonic-gate seg == &kvseg ? "segkmem" : "NONE!")); 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate /* 735*7c478bd9Sstevel@tonic-gate * This is all terribly broken, but it is a start 736*7c478bd9Sstevel@tonic-gate * 737*7c478bd9Sstevel@tonic-gate * XXX Note that this test means that segdev_ops 738*7c478bd9Sstevel@tonic-gate * must be exported from seg_dev.c. 739*7c478bd9Sstevel@tonic-gate * XXX What about devices with their own segment drivers? 740*7c478bd9Sstevel@tonic-gate */ 741*7c478bd9Sstevel@tonic-gate if (seg->s_ops == &segdev_ops) { 742*7c478bd9Sstevel@tonic-gate register struct segdev_data *sdp = 743*7c478bd9Sstevel@tonic-gate (struct segdev_data *)seg->s_data; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate if (hat == NULL) { 746*7c478bd9Sstevel@tonic-gate /* 747*7c478bd9Sstevel@tonic-gate * This is one plausible interpretation of 748*7c478bd9Sstevel@tonic-gate * a null hat i.e. use the first hat on the 749*7c478bd9Sstevel@tonic-gate * address space hat list which by convention is 750*7c478bd9Sstevel@tonic-gate * the hat of the system MMU. At alternative 751*7c478bd9Sstevel@tonic-gate * would be to panic .. this might well be better .. 752*7c478bd9Sstevel@tonic-gate */ 753*7c478bd9Sstevel@tonic-gate ASSERT(AS_READ_HELD(seg->s_as, &seg->s_as->a_lock)); 754*7c478bd9Sstevel@tonic-gate hat = seg->s_as->a_hat; 755*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "rootnex_map_fault: nil hat"); 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate hat_devload(hat, addr, MMU_PAGESIZE, pfn, prot | sdp->hat_attr, 758*7c478bd9Sstevel@tonic-gate (lock ? HAT_LOAD_LOCK : HAT_LOAD)); 759*7c478bd9Sstevel@tonic-gate } else if (seg == &kvseg && dp == (struct devpage *)0) { 760*7c478bd9Sstevel@tonic-gate hat_devload(kas.a_hat, addr, MMU_PAGESIZE, pfn, prot, 761*7c478bd9Sstevel@tonic-gate HAT_LOAD_LOCK); 762*7c478bd9Sstevel@tonic-gate } else 763*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 764*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 765*7c478bd9Sstevel@tonic-gate } 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate /* 768*7c478bd9Sstevel@tonic-gate * Name a child of rootnex 769*7c478bd9Sstevel@tonic-gate * 770*7c478bd9Sstevel@tonic-gate * This may be called multiple times, independent of initchild calls. 771*7c478bd9Sstevel@tonic-gate */ 772*7c478bd9Sstevel@tonic-gate int 773*7c478bd9Sstevel@tonic-gate rootnex_name_child(dev_info_t *child, char *name, int namelen) 774*7c478bd9Sstevel@tonic-gate { 775*7c478bd9Sstevel@tonic-gate return (rootnex_name_child_impl(child, name, namelen)); 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate static int 780*7c478bd9Sstevel@tonic-gate rootnex_ctl_initchild(dev_info_t *dip) 781*7c478bd9Sstevel@tonic-gate { 782*7c478bd9Sstevel@tonic-gate return (rootnex_ctl_initchild_impl(dip)); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate int 787*7c478bd9Sstevel@tonic-gate rootnex_ctl_uninitchild(dev_info_t *dip) 788*7c478bd9Sstevel@tonic-gate { 789*7c478bd9Sstevel@tonic-gate extern void impl_free_ddi_ppd(dev_info_t *); 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate rootnex_ctl_uninitchild_impl(dip); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate /* 794*7c478bd9Sstevel@tonic-gate * strip properties and convert node to prototype form 795*7c478bd9Sstevel@tonic-gate */ 796*7c478bd9Sstevel@tonic-gate impl_free_ddi_ppd(dip); 797*7c478bd9Sstevel@tonic-gate ddi_set_name_addr(dip, NULL); 798*7c478bd9Sstevel@tonic-gate impl_rem_dev_props(dip); 799*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 800*7c478bd9Sstevel@tonic-gate } 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate static int 804*7c478bd9Sstevel@tonic-gate rootnex_ctl_reportdev(dev_info_t *dev) 805*7c478bd9Sstevel@tonic-gate { 806*7c478bd9Sstevel@tonic-gate return (rootnex_ctl_reportdev_impl(dev)); 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate static int 811*7c478bd9Sstevel@tonic-gate rootnex_ctlops_peekpoke(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args, 812*7c478bd9Sstevel@tonic-gate void *result) 813*7c478bd9Sstevel@tonic-gate { 814*7c478bd9Sstevel@tonic-gate int err = DDI_SUCCESS; 815*7c478bd9Sstevel@tonic-gate on_trap_data_t otd; 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate /* No safe access except for peek/poke is supported. */ 818*7c478bd9Sstevel@tonic-gate if (in_args->handle != NULL) 819*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* Set up protected environment. */ 822*7c478bd9Sstevel@tonic-gate if (!on_trap(&otd, OT_DATA_ACCESS)) { 823*7c478bd9Sstevel@tonic-gate uintptr_t tramp = otd.ot_trampoline; 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate if (cmd == DDI_CTLOPS_POKE) { 826*7c478bd9Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&poke_fault; 827*7c478bd9Sstevel@tonic-gate err = do_poke(in_args->size, (void *)in_args->dev_addr, 828*7c478bd9Sstevel@tonic-gate (void *)in_args->host_addr); 829*7c478bd9Sstevel@tonic-gate } else { 830*7c478bd9Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&peek_fault; 831*7c478bd9Sstevel@tonic-gate err = do_peek(in_args->size, (void *)in_args->dev_addr, 832*7c478bd9Sstevel@tonic-gate (void *)in_args->host_addr); 833*7c478bd9Sstevel@tonic-gate result = (void *)in_args->host_addr; 834*7c478bd9Sstevel@tonic-gate } 835*7c478bd9Sstevel@tonic-gate otd.ot_trampoline = tramp; 836*7c478bd9Sstevel@tonic-gate } else 837*7c478bd9Sstevel@tonic-gate err = DDI_FAILURE; 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate /* Take down protected environment. */ 840*7c478bd9Sstevel@tonic-gate no_trap(); 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate return (err); 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 846*7c478bd9Sstevel@tonic-gate static int 847*7c478bd9Sstevel@tonic-gate rootnex_ctlops(dev_info_t *dip, dev_info_t *rdip, 848*7c478bd9Sstevel@tonic-gate ddi_ctl_enum_t ctlop, void *arg, void *result) 849*7c478bd9Sstevel@tonic-gate { 850*7c478bd9Sstevel@tonic-gate register int n, *ptr; 851*7c478bd9Sstevel@tonic-gate register struct ddi_parent_private_data *pdp; 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate static boolean_t reserved_msg_printed = B_FALSE; 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate switch (ctlop) { 856*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_DMAPMAPC: 857*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_BTOP: 860*7c478bd9Sstevel@tonic-gate /* 861*7c478bd9Sstevel@tonic-gate * Convert byte count input to physical page units. 862*7c478bd9Sstevel@tonic-gate * (byte counts that are not a page-size multiple 863*7c478bd9Sstevel@tonic-gate * are rounded down) 864*7c478bd9Sstevel@tonic-gate */ 865*7c478bd9Sstevel@tonic-gate *(ulong_t *)result = btop(*(ulong_t *)arg); 866*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_PTOB: 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * Convert size in physical pages to bytes 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate *(ulong_t *)result = ptob(*(ulong_t *)arg); 873*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_BTOPR: 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * Convert byte count input to physical page units 878*7c478bd9Sstevel@tonic-gate * (byte counts that are not a page-size multiple 879*7c478bd9Sstevel@tonic-gate * are rounded up) 880*7c478bd9Sstevel@tonic-gate */ 881*7c478bd9Sstevel@tonic-gate *(ulong_t *)result = btopr(*(ulong_t *)arg); 882*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: 885*7c478bd9Sstevel@tonic-gate return (rootnex_ctl_initchild((dev_info_t *)arg)); 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: 888*7c478bd9Sstevel@tonic-gate return (rootnex_ctl_uninitchild((dev_info_t *)arg)); 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV: 891*7c478bd9Sstevel@tonic-gate return (rootnex_ctl_reportdev(rdip)); 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_IOMIN: 894*7c478bd9Sstevel@tonic-gate /* 895*7c478bd9Sstevel@tonic-gate * Nothing to do here but reflect back.. 896*7c478bd9Sstevel@tonic-gate */ 897*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE: 900*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NREGS: 901*7c478bd9Sstevel@tonic-gate break; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_SIDDEV: 904*7c478bd9Sstevel@tonic-gate if (ndi_dev_is_prom_node(rdip)) 905*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 906*7c478bd9Sstevel@tonic-gate if (ndi_dev_is_persistent_node(rdip)) 907*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 908*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_POWER: { 911*7c478bd9Sstevel@tonic-gate return ((*pm_platform_power)((power_req_t *)arg)); 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_RESERVED1: /* Was DDI_CTLOPS_POKE_INIT, obsolete */ 915*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_RESERVED2: /* Was DDI_CTLOPS_POKE_FLUSH, obsolete */ 916*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_RESERVED3: /* Was DDI_CTLOPS_POKE_FINI, obsolete */ 917*7c478bd9Sstevel@tonic-gate if (!reserved_msg_printed) { 918*7c478bd9Sstevel@tonic-gate reserved_msg_printed = B_TRUE; 919*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Failing ddi_ctlops call(s) for " 920*7c478bd9Sstevel@tonic-gate "1 or more reserved/obsolete operations."); 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_POKE: 925*7c478bd9Sstevel@tonic-gate case DDI_CTLOPS_PEEK: 926*7c478bd9Sstevel@tonic-gate return (rootnex_ctlops_peekpoke(ctlop, (peekpoke_ctlops_t *)arg, 927*7c478bd9Sstevel@tonic-gate result)); 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate default: 930*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate /* 934*7c478bd9Sstevel@tonic-gate * The rest are for "hardware" properties 935*7c478bd9Sstevel@tonic-gate */ 936*7c478bd9Sstevel@tonic-gate if ((pdp = ddi_get_parent_data(rdip)) == NULL) 937*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate if (ctlop == DDI_CTLOPS_NREGS) { 940*7c478bd9Sstevel@tonic-gate ptr = (int *)result; 941*7c478bd9Sstevel@tonic-gate *ptr = pdp->par_nreg; 942*7c478bd9Sstevel@tonic-gate } else if (ctlop == DDI_CTLOPS_NINTRS) { 943*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 944*7c478bd9Sstevel@tonic-gate } else { /* ctlop == DDI_CTLOPS_REGSIZE */ 945*7c478bd9Sstevel@tonic-gate off_t *size = (off_t *)result; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate ptr = (int *)arg; 948*7c478bd9Sstevel@tonic-gate n = *ptr; 949*7c478bd9Sstevel@tonic-gate if (n >= pdp->par_nreg) { 950*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate *size = (off_t)pdp->par_reg[n].regspec_size; 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 958*7c478bd9Sstevel@tonic-gate int 959*7c478bd9Sstevel@tonic-gate rootnex_busop_fminit(dev_info_t *dip, dev_info_t *tdip, int cap, 960*7c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *ibc) 961*7c478bd9Sstevel@tonic-gate { 962*7c478bd9Sstevel@tonic-gate *ibc = rootnex_err_ibc; 963*7c478bd9Sstevel@tonic-gate return (ddi_system_fmcap | DDI_FM_ACCCHK_CAPABLE | 964*7c478bd9Sstevel@tonic-gate DDI_FM_DMACHK_CAPABLE); 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate static void 968*7c478bd9Sstevel@tonic-gate rootnex_fm_init(dev_info_t *dip) 969*7c478bd9Sstevel@tonic-gate { 970*7c478bd9Sstevel@tonic-gate int fmcap; 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate /* Minimum fm capability level for sun4u platforms */ 973*7c478bd9Sstevel@tonic-gate ddi_system_fmcap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE; 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate fmcap = ddi_system_fmcap; 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate /* 978*7c478bd9Sstevel@tonic-gate * Initialize ECC error handling 979*7c478bd9Sstevel@tonic-gate */ 980*7c478bd9Sstevel@tonic-gate rootnex_err_ibc = (ddi_iblock_cookie_t)PIL_15; 981*7c478bd9Sstevel@tonic-gate ddi_fm_init(dip, &fmcap, &rootnex_err_ibc); 982*7c478bd9Sstevel@tonic-gate } 983