1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #if defined(DEBUG) 30*0Sstevel@tonic-gate #define BUSRA_DEBUG 31*0Sstevel@tonic-gate #endif 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate /* 34*0Sstevel@tonic-gate * This module provides a set of resource management interfaces 35*0Sstevel@tonic-gate * to manage bus resources globally in the system. 36*0Sstevel@tonic-gate * 37*0Sstevel@tonic-gate * The bus nexus drivers are typically responsible to setup resource 38*0Sstevel@tonic-gate * maps for the bus resources available for a bus instance. However 39*0Sstevel@tonic-gate * this module also provides resource setup functions for PCI bus 40*0Sstevel@tonic-gate * (used by both SPARC and X86 platforms) and ISA bus instances (used 41*0Sstevel@tonic-gate * only for X86 platforms). 42*0Sstevel@tonic-gate */ 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate #include <sys/types.h> 45*0Sstevel@tonic-gate #include <sys/systm.h> 46*0Sstevel@tonic-gate #include <sys/ddi.h> 47*0Sstevel@tonic-gate #include <sys/sunddi.h> 48*0Sstevel@tonic-gate #include <sys/sunndi.h> 49*0Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 50*0Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 51*0Sstevel@tonic-gate #include <sys/kmem.h> 52*0Sstevel@tonic-gate #include <sys/pctypes.h> 53*0Sstevel@tonic-gate #include <sys/modctl.h> 54*0Sstevel@tonic-gate #include <sys/debug.h> 55*0Sstevel@tonic-gate #include <sys/spl.h> 56*0Sstevel@tonic-gate #include <sys/pci.h> 57*0Sstevel@tonic-gate #include <sys/autoconf.h> 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #if defined(BUSRA_DEBUG) 60*0Sstevel@tonic-gate int busra_debug = 0; 61*0Sstevel@tonic-gate #define DEBUGPRT \ 62*0Sstevel@tonic-gate if (busra_debug) cmn_err 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate #else 65*0Sstevel@tonic-gate #define DEBUGPRT \ 66*0Sstevel@tonic-gate if (0) cmn_err 67*0Sstevel@tonic-gate #endif 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate /* 71*0Sstevel@tonic-gate * global mutex that protects the global list of resource maps. 72*0Sstevel@tonic-gate */ 73*0Sstevel@tonic-gate kmutex_t ra_lock; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate /* 76*0Sstevel@tonic-gate * basic resource element 77*0Sstevel@tonic-gate */ 78*0Sstevel@tonic-gate struct ra_resource { 79*0Sstevel@tonic-gate struct ra_resource *ra_next; 80*0Sstevel@tonic-gate uint64_t ra_base; 81*0Sstevel@tonic-gate uint64_t ra_len; 82*0Sstevel@tonic-gate }; 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate /* 85*0Sstevel@tonic-gate * link list element for the list of dips (and their resource ranges) 86*0Sstevel@tonic-gate * for a particular resource type. 87*0Sstevel@tonic-gate * ra_rangeset points to the list of resources available 88*0Sstevel@tonic-gate * for this type and this dip. 89*0Sstevel@tonic-gate */ 90*0Sstevel@tonic-gate struct ra_dip_type { 91*0Sstevel@tonic-gate struct ra_dip_type *ra_next; 92*0Sstevel@tonic-gate struct ra_resource *ra_rangeset; 93*0Sstevel@tonic-gate dev_info_t *ra_dip; 94*0Sstevel@tonic-gate }; 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* 98*0Sstevel@tonic-gate * link list element for list of types resources. Each element 99*0Sstevel@tonic-gate * has all resources for a particular type. 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate struct ra_type_map { 102*0Sstevel@tonic-gate struct ra_type_map *ra_next; 103*0Sstevel@tonic-gate struct ra_dip_type *ra_dip_list; 104*0Sstevel@tonic-gate char *type; 105*0Sstevel@tonic-gate }; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /* 109*0Sstevel@tonic-gate * place holder to keep the head of the whole global list. 110*0Sstevel@tonic-gate * the address of the first typemap would be stored in it. 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate static struct ra_type_map *ra_map_list_head = NULL; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate /* 116*0Sstevel@tonic-gate * This is the loadable module wrapper. 117*0Sstevel@tonic-gate * It is essentially boilerplate so isn't documented 118*0Sstevel@tonic-gate */ 119*0Sstevel@tonic-gate extern struct mod_ops mod_miscops; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate #ifdef BUSRA_DEBUG 122*0Sstevel@tonic-gate void ra_dump_all(); 123*0Sstevel@tonic-gate #endif 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* internal function prototypes */ 126*0Sstevel@tonic-gate static struct ra_dip_type *find_dip_map_resources(dev_info_t *dip, char *type, 127*0Sstevel@tonic-gate struct ra_dip_type ***backdip, struct ra_type_map ***backtype, 128*0Sstevel@tonic-gate uint32_t flag); 129*0Sstevel@tonic-gate static int isnot_pow2(uint64_t value); 130*0Sstevel@tonic-gate static int claim_pci_busnum(dev_info_t *dip, void *arg); 131*0Sstevel@tonic-gate static int ra_map_exist(dev_info_t *dip, char *type); 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate #define RA_INSERT(prev, el) \ 135*0Sstevel@tonic-gate el->ra_next = *prev; \ 136*0Sstevel@tonic-gate *prev = el; 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate #define RA_REMOVE(prev, el) \ 139*0Sstevel@tonic-gate *prev = el->ra_next; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate static struct modlmisc modlmisc = { 143*0Sstevel@tonic-gate &mod_miscops, /* Type of module. This one is a module */ 144*0Sstevel@tonic-gate "Bus Resource Allocator (BUSRA) %I%", /* Name of the module. */ 145*0Sstevel@tonic-gate }; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 148*0Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 149*0Sstevel@tonic-gate }; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate int 152*0Sstevel@tonic-gate _init() 153*0Sstevel@tonic-gate { 154*0Sstevel@tonic-gate int ret; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate mutex_init(&ra_lock, NULL, MUTEX_DRIVER, 157*0Sstevel@tonic-gate (void *)(intptr_t)__ipltospl(SPL7 - 1)); 158*0Sstevel@tonic-gate if ((ret = mod_install(&modlinkage)) != 0) { 159*0Sstevel@tonic-gate mutex_destroy(&ra_lock); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate return (ret); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate int 165*0Sstevel@tonic-gate _fini() 166*0Sstevel@tonic-gate { 167*0Sstevel@tonic-gate int ret; 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate mutex_enter(&ra_lock); 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate if (ra_map_list_head != NULL) { 172*0Sstevel@tonic-gate mutex_exit(&ra_lock); 173*0Sstevel@tonic-gate return (EBUSY); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate ret = mod_remove(&modlinkage); 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate mutex_exit(&ra_lock); 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate if (ret == 0) 181*0Sstevel@tonic-gate mutex_destroy(&ra_lock); 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate return (ret); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate int 187*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate { 190*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate /* 194*0Sstevel@tonic-gate * set up an empty resource map for a given type and dip 195*0Sstevel@tonic-gate */ 196*0Sstevel@tonic-gate int 197*0Sstevel@tonic-gate ndi_ra_map_setup(dev_info_t *dip, char *type) 198*0Sstevel@tonic-gate { 199*0Sstevel@tonic-gate struct ra_type_map *typemapp; 200*0Sstevel@tonic-gate struct ra_dip_type *dipmap; 201*0Sstevel@tonic-gate struct ra_dip_type **backdip; 202*0Sstevel@tonic-gate struct ra_type_map **backtype; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate mutex_enter(&ra_lock); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate dipmap = find_dip_map_resources(dip, type, &backdip, &backtype, 0); 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate if (dipmap == NULL) { 210*0Sstevel@tonic-gate if (backtype == NULL) { 211*0Sstevel@tonic-gate typemapp = (struct ra_type_map *) 212*0Sstevel@tonic-gate kmem_zalloc(sizeof (*typemapp), KM_SLEEP); 213*0Sstevel@tonic-gate typemapp->type = (char *)kmem_zalloc(strlen(type) + 1, 214*0Sstevel@tonic-gate KM_SLEEP); 215*0Sstevel@tonic-gate (void) strcpy(typemapp->type, type); 216*0Sstevel@tonic-gate RA_INSERT(&ra_map_list_head, typemapp); 217*0Sstevel@tonic-gate } else { 218*0Sstevel@tonic-gate typemapp = *backtype; 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate if (backdip == NULL) { 221*0Sstevel@tonic-gate /* allocate and insert in list of dips for this type */ 222*0Sstevel@tonic-gate dipmap = (struct ra_dip_type *) 223*0Sstevel@tonic-gate kmem_zalloc(sizeof (*dipmap), KM_SLEEP); 224*0Sstevel@tonic-gate dipmap->ra_dip = dip; 225*0Sstevel@tonic-gate RA_INSERT(&typemapp->ra_dip_list, dipmap); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate mutex_exit(&ra_lock); 230*0Sstevel@tonic-gate return (NDI_SUCCESS); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate /* 234*0Sstevel@tonic-gate * destroys a resource map for a given dip and type 235*0Sstevel@tonic-gate */ 236*0Sstevel@tonic-gate int 237*0Sstevel@tonic-gate ndi_ra_map_destroy(dev_info_t *dip, char *type) 238*0Sstevel@tonic-gate { 239*0Sstevel@tonic-gate struct ra_dip_type *dipmap; 240*0Sstevel@tonic-gate struct ra_dip_type **backdip; 241*0Sstevel@tonic-gate struct ra_type_map **backtype, *typemap; 242*0Sstevel@tonic-gate struct ra_resource *range; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate mutex_enter(&ra_lock); 245*0Sstevel@tonic-gate dipmap = find_dip_map_resources(dip, type, &backdip, &backtype, 0); 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate if (dipmap == NULL) { 248*0Sstevel@tonic-gate mutex_exit(&ra_lock); 249*0Sstevel@tonic-gate return (NDI_FAILURE); 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate /* 253*0Sstevel@tonic-gate * destroy all resources for this dip 254*0Sstevel@tonic-gate * remove dip from type list 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate ASSERT((backdip != NULL) && (backtype != NULL)); 257*0Sstevel@tonic-gate while (dipmap->ra_rangeset != NULL) { 258*0Sstevel@tonic-gate range = dipmap->ra_rangeset; 259*0Sstevel@tonic-gate RA_REMOVE(&dipmap->ra_rangeset, range); 260*0Sstevel@tonic-gate kmem_free((caddr_t)range, sizeof (*range)); 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate /* remove from dip list */ 263*0Sstevel@tonic-gate RA_REMOVE(backdip, dipmap); 264*0Sstevel@tonic-gate kmem_free((caddr_t)dipmap, sizeof (*dipmap)); 265*0Sstevel@tonic-gate if ((*backtype)->ra_dip_list == NULL) { 266*0Sstevel@tonic-gate /* 267*0Sstevel@tonic-gate * This was the last dip with this resource type. 268*0Sstevel@tonic-gate * Remove the type from the global list. 269*0Sstevel@tonic-gate */ 270*0Sstevel@tonic-gate typemap = *backtype; 271*0Sstevel@tonic-gate RA_REMOVE(backtype, (*backtype)); 272*0Sstevel@tonic-gate kmem_free((caddr_t)typemap->type, strlen(typemap->type) + 1); 273*0Sstevel@tonic-gate kmem_free((caddr_t)typemap, sizeof (*typemap)); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate mutex_exit(&ra_lock); 277*0Sstevel@tonic-gate return (NDI_SUCCESS); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate static int 281*0Sstevel@tonic-gate ra_map_exist(dev_info_t *dip, char *type) 282*0Sstevel@tonic-gate { 283*0Sstevel@tonic-gate struct ra_dip_type **backdip; 284*0Sstevel@tonic-gate struct ra_type_map **backtype; 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate mutex_enter(&ra_lock); 287*0Sstevel@tonic-gate if (find_dip_map_resources(dip, type, &backdip, &backtype, 0) == NULL) { 288*0Sstevel@tonic-gate mutex_exit(&ra_lock); 289*0Sstevel@tonic-gate return (NDI_FAILURE); 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate mutex_exit(&ra_lock); 293*0Sstevel@tonic-gate return (NDI_SUCCESS); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate /* 296*0Sstevel@tonic-gate * Find a dip map for the specified type, if NDI_RA_PASS will go up on dev tree 297*0Sstevel@tonic-gate * if found, backdip and backtype will be updated to point to the previous 298*0Sstevel@tonic-gate * dip in the list and previous type for this dip in the list. 299*0Sstevel@tonic-gate * If no such type at all in the resource list both backdip and backtype 300*0Sstevel@tonic-gate * will be null. If the type found but no dip, back dip will be null. 301*0Sstevel@tonic-gate */ 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate static struct ra_dip_type * 304*0Sstevel@tonic-gate find_dip_map_resources(dev_info_t *dip, char *type, 305*0Sstevel@tonic-gate struct ra_dip_type ***backdip, struct ra_type_map ***backtype, 306*0Sstevel@tonic-gate uint32_t flag) 307*0Sstevel@tonic-gate { 308*0Sstevel@tonic-gate struct ra_type_map **prevmap; 309*0Sstevel@tonic-gate struct ra_dip_type *dipmap, **prevdip; 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate ASSERT(mutex_owned(&ra_lock)); 312*0Sstevel@tonic-gate prevdip = NULL; 313*0Sstevel@tonic-gate dipmap = NULL; 314*0Sstevel@tonic-gate prevmap = &ra_map_list_head; 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate while (*prevmap) { 317*0Sstevel@tonic-gate if (strcmp((*prevmap)->type, type) == 0) 318*0Sstevel@tonic-gate break; 319*0Sstevel@tonic-gate prevmap = &(*prevmap)->ra_next; 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate if (*prevmap) { 323*0Sstevel@tonic-gate for (; dip != NULL; dip = ddi_get_parent(dip)) { 324*0Sstevel@tonic-gate prevdip = &(*prevmap)->ra_dip_list; 325*0Sstevel@tonic-gate dipmap = *prevdip; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate while (dipmap) { 328*0Sstevel@tonic-gate if (dipmap->ra_dip == dip) 329*0Sstevel@tonic-gate break; 330*0Sstevel@tonic-gate prevdip = &dipmap->ra_next; 331*0Sstevel@tonic-gate dipmap = dipmap->ra_next; 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate if (dipmap != NULL) { 335*0Sstevel@tonic-gate /* found it */ 336*0Sstevel@tonic-gate break; 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate if (!(flag & NDI_RA_PASS)) { 340*0Sstevel@tonic-gate break; 341*0Sstevel@tonic-gate } 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate *backtype = (*prevmap == NULL) ? NULL: prevmap; 346*0Sstevel@tonic-gate *backdip = (dipmap == NULL) ? NULL: prevdip; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate return (dipmap); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate int 352*0Sstevel@tonic-gate ndi_ra_free(dev_info_t *dip, uint64_t base, uint64_t len, char *type, 353*0Sstevel@tonic-gate uint32_t flag) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate struct ra_dip_type *dipmap; 356*0Sstevel@tonic-gate struct ra_resource *newmap, *overlapmap, *oldmap = NULL; 357*0Sstevel@tonic-gate struct ra_resource *mapp, **backp; 358*0Sstevel@tonic-gate uint64_t newend, mapend; 359*0Sstevel@tonic-gate struct ra_dip_type **backdip; 360*0Sstevel@tonic-gate struct ra_type_map **backtype; 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate if (len == 0) { 363*0Sstevel@tonic-gate return (NDI_SUCCESS); 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate mutex_enter(&ra_lock); 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if ((dipmap = find_dip_map_resources(dip, type, &backdip, &backtype, 369*0Sstevel@tonic-gate flag)) == NULL) { 370*0Sstevel@tonic-gate mutex_exit(&ra_lock); 371*0Sstevel@tonic-gate return (NDI_FAILURE); 372*0Sstevel@tonic-gate } 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate mapp = dipmap->ra_rangeset; 375*0Sstevel@tonic-gate backp = &dipmap->ra_rangeset; 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate /* now find where range lies and fix things up */ 378*0Sstevel@tonic-gate newend = base + len; 379*0Sstevel@tonic-gate for (; mapp != NULL; backp = &(mapp->ra_next), mapp = mapp->ra_next) { 380*0Sstevel@tonic-gate mapend = mapp->ra_base + mapp->ra_len; 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate /* check for overlap first */ 383*0Sstevel@tonic-gate if ((base <= mapp->ra_base && newend > mapp->ra_base) || 384*0Sstevel@tonic-gate (base > mapp->ra_base && base < mapend)) { 385*0Sstevel@tonic-gate /* overlap with mapp */ 386*0Sstevel@tonic-gate overlapmap = mapp; 387*0Sstevel@tonic-gate goto overlap; 388*0Sstevel@tonic-gate } else if ((base == mapend && mapp->ra_next) && 389*0Sstevel@tonic-gate (newend > mapp->ra_next->ra_base)) { 390*0Sstevel@tonic-gate /* overlap with mapp->ra_next */ 391*0Sstevel@tonic-gate overlapmap = mapp->ra_next; 392*0Sstevel@tonic-gate goto overlap; 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate if (newend == mapp->ra_base) { 396*0Sstevel@tonic-gate /* simple - on front */ 397*0Sstevel@tonic-gate mapp->ra_base = base; 398*0Sstevel@tonic-gate mapp->ra_len += len; 399*0Sstevel@tonic-gate /* 400*0Sstevel@tonic-gate * don't need to check if it merges with 401*0Sstevel@tonic-gate * previous since that would match on on end 402*0Sstevel@tonic-gate */ 403*0Sstevel@tonic-gate break; 404*0Sstevel@tonic-gate } else if (base == mapend) { 405*0Sstevel@tonic-gate /* simple - on end */ 406*0Sstevel@tonic-gate mapp->ra_len += len; 407*0Sstevel@tonic-gate if (mapp->ra_next && 408*0Sstevel@tonic-gate (newend == mapp->ra_next->ra_base)) { 409*0Sstevel@tonic-gate /* merge with next node */ 410*0Sstevel@tonic-gate oldmap = mapp->ra_next; 411*0Sstevel@tonic-gate mapp->ra_len += oldmap->ra_len; 412*0Sstevel@tonic-gate RA_REMOVE(&mapp->ra_next, oldmap); 413*0Sstevel@tonic-gate kmem_free((caddr_t)oldmap, sizeof (*oldmap)); 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate break; 416*0Sstevel@tonic-gate } else if (base < mapp->ra_base) { 417*0Sstevel@tonic-gate /* somewhere in between so just an insert */ 418*0Sstevel@tonic-gate newmap = (struct ra_resource *) 419*0Sstevel@tonic-gate kmem_zalloc(sizeof (*newmap), KM_SLEEP); 420*0Sstevel@tonic-gate newmap->ra_base = base; 421*0Sstevel@tonic-gate newmap->ra_len = len; 422*0Sstevel@tonic-gate RA_INSERT(backp, newmap); 423*0Sstevel@tonic-gate break; 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate if (mapp == NULL) { 427*0Sstevel@tonic-gate /* stick on end */ 428*0Sstevel@tonic-gate newmap = (struct ra_resource *) 429*0Sstevel@tonic-gate kmem_zalloc(sizeof (*newmap), KM_SLEEP); 430*0Sstevel@tonic-gate newmap->ra_base = base; 431*0Sstevel@tonic-gate newmap->ra_len = len; 432*0Sstevel@tonic-gate RA_INSERT(backp, newmap); 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate mutex_exit(&ra_lock); 436*0Sstevel@tonic-gate return (NDI_SUCCESS); 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate overlap: 439*0Sstevel@tonic-gate /* 440*0Sstevel@tonic-gate * Bad free may happen on some x86 platforms with BIOS exporting 441*0Sstevel@tonic-gate * incorrect resource maps. The system is otherwise functioning 442*0Sstevel@tonic-gate * normally. We send such messages to syslog only. 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate cmn_err(CE_NOTE, "!ndi_ra_free: bad free, dip %p, resource type %s \n", 445*0Sstevel@tonic-gate (void *)dip, type); 446*0Sstevel@tonic-gate cmn_err(CE_NOTE, "!ndi_ra_free: freeing base 0x%" PRIx64 ", len 0x%" 447*0Sstevel@tonic-gate PRIX64 " overlaps with existing resource base 0x%" PRIx64 448*0Sstevel@tonic-gate ", len 0x%" PRIx64 "\n", base, len, overlapmap->ra_base, 449*0Sstevel@tonic-gate overlapmap->ra_len); 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate mutex_exit(&ra_lock); 452*0Sstevel@tonic-gate return (NDI_FAILURE); 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate /* check to see if value is power of 2 or not. */ 456*0Sstevel@tonic-gate static int 457*0Sstevel@tonic-gate isnot_pow2(uint64_t value) 458*0Sstevel@tonic-gate { 459*0Sstevel@tonic-gate uint32_t low; 460*0Sstevel@tonic-gate uint32_t hi; 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate low = value & 0xffffffff; 463*0Sstevel@tonic-gate hi = value >> 32; 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * ddi_ffs and ddi_fls gets long values, so in 32bit environment 467*0Sstevel@tonic-gate * won't work correctly for 64bit values 468*0Sstevel@tonic-gate */ 469*0Sstevel@tonic-gate if ((ddi_ffs(low) == ddi_fls(low)) && 470*0Sstevel@tonic-gate (ddi_ffs(hi) == ddi_fls(hi))) 471*0Sstevel@tonic-gate return (0); 472*0Sstevel@tonic-gate return (1); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate static void 476*0Sstevel@tonic-gate adjust_link(struct ra_resource **backp, struct ra_resource *mapp, 477*0Sstevel@tonic-gate uint64_t base, uint64_t len) 478*0Sstevel@tonic-gate { 479*0Sstevel@tonic-gate struct ra_resource *newmap; 480*0Sstevel@tonic-gate uint64_t newlen; 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate if (base != mapp->ra_base) { 483*0Sstevel@tonic-gate /* in the middle or end */ 484*0Sstevel@tonic-gate newlen = base - mapp->ra_base; 485*0Sstevel@tonic-gate if ((mapp->ra_len - newlen) == len) { 486*0Sstevel@tonic-gate /* on the end */ 487*0Sstevel@tonic-gate mapp->ra_len = newlen; 488*0Sstevel@tonic-gate } else { 489*0Sstevel@tonic-gate /* in the middle */ 490*0Sstevel@tonic-gate newmap = (struct ra_resource *) 491*0Sstevel@tonic-gate kmem_zalloc(sizeof (*newmap), KM_SLEEP); 492*0Sstevel@tonic-gate newmap->ra_base = base + len; 493*0Sstevel@tonic-gate newmap->ra_len = mapp->ra_len - 494*0Sstevel@tonic-gate (len + newlen); 495*0Sstevel@tonic-gate mapp->ra_len = newlen; 496*0Sstevel@tonic-gate RA_INSERT(&(mapp->ra_next), newmap); 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate } else { 499*0Sstevel@tonic-gate /* at the beginning */ 500*0Sstevel@tonic-gate mapp->ra_base += len; 501*0Sstevel@tonic-gate mapp->ra_len -= len; 502*0Sstevel@tonic-gate if (mapp->ra_len == 0) { 503*0Sstevel@tonic-gate /* remove the whole node */ 504*0Sstevel@tonic-gate RA_REMOVE(backp, mapp); 505*0Sstevel@tonic-gate kmem_free((caddr_t)mapp, sizeof (*mapp)); 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate } 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate int 511*0Sstevel@tonic-gate ndi_ra_alloc(dev_info_t *dip, ndi_ra_request_t *req, uint64_t *retbasep, 512*0Sstevel@tonic-gate uint64_t *retlenp, char *type, uint32_t flag) 513*0Sstevel@tonic-gate { 514*0Sstevel@tonic-gate struct ra_dip_type *dipmap; 515*0Sstevel@tonic-gate struct ra_resource *mapp, **backp, **backlargestp; 516*0Sstevel@tonic-gate uint64_t mask = 0; 517*0Sstevel@tonic-gate uint64_t len, remlen, largestbase, largestlen; 518*0Sstevel@tonic-gate uint64_t base, oldbase, lower, upper; 519*0Sstevel@tonic-gate struct ra_dip_type **backdip; 520*0Sstevel@tonic-gate struct ra_type_map **backtype; 521*0Sstevel@tonic-gate int rval = NDI_FAILURE; 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate len = req->ra_len; 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate if (req->ra_flags & NDI_RA_ALIGN_SIZE) { 527*0Sstevel@tonic-gate if (isnot_pow2(req->ra_len)) { 528*0Sstevel@tonic-gate DEBUGPRT(CE_WARN, "ndi_ra_alloc: bad length(pow2) 0x%" 529*0Sstevel@tonic-gate PRIx64, req->ra_len); 530*0Sstevel@tonic-gate *retbasep = 0; 531*0Sstevel@tonic-gate *retlenp = 0; 532*0Sstevel@tonic-gate return (NDI_FAILURE); 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate mask = (req->ra_flags & NDI_RA_ALIGN_SIZE) ? (len - 1) : 537*0Sstevel@tonic-gate req->ra_align_mask; 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate mutex_enter(&ra_lock); 541*0Sstevel@tonic-gate dipmap = find_dip_map_resources(dip, type, &backdip, &backtype, flag); 542*0Sstevel@tonic-gate if ((dipmap == NULL) || ((mapp = dipmap->ra_rangeset) == NULL)) { 543*0Sstevel@tonic-gate mutex_exit(&ra_lock); 544*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "ndi_ra_alloc no map found for this type\n"); 545*0Sstevel@tonic-gate return (NDI_FAILURE); 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "ndi_ra_alloc: mapp = %p len=%" PRIx64 ", mask=%" 549*0Sstevel@tonic-gate PRIx64 "\n", (void *)mapp, len, mask); 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate backp = &(dipmap->ra_rangeset); 552*0Sstevel@tonic-gate backlargestp = NULL; 553*0Sstevel@tonic-gate largestbase = 0; 554*0Sstevel@tonic-gate largestlen = 0; 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate lower = 0; 557*0Sstevel@tonic-gate upper = ~(uint64_t)0; 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate if (req->ra_flags & NDI_RA_ALLOC_BOUNDED) { 560*0Sstevel@tonic-gate /* bounded so skip to first possible */ 561*0Sstevel@tonic-gate lower = req->ra_boundbase; 562*0Sstevel@tonic-gate upper = req->ra_boundlen + lower; 563*0Sstevel@tonic-gate if ((upper == 0) || (upper < req->ra_boundlen)) 564*0Sstevel@tonic-gate upper = ~(uint64_t)0; 565*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "ndi_ra_alloc: ra_len = %" PRIx64 ", len = %" 566*0Sstevel@tonic-gate PRIx64 " ra_base=%" PRIx64 ", mask=%" PRIx64 567*0Sstevel@tonic-gate "\n", mapp->ra_len, len, mapp->ra_base, mask); 568*0Sstevel@tonic-gate for (; mapp != NULL && 569*0Sstevel@tonic-gate (mapp->ra_base + mapp->ra_len) < lower; 570*0Sstevel@tonic-gate backp = &(mapp->ra_next), mapp = mapp->ra_next) { 571*0Sstevel@tonic-gate if (((mapp->ra_len + mapp->ra_base) == 0) || 572*0Sstevel@tonic-gate ((mapp->ra_len + mapp->ra_base) < mapp->ra_len)) 573*0Sstevel@tonic-gate /* 574*0Sstevel@tonic-gate * This elements end goes beyond max uint64_t. 575*0Sstevel@tonic-gate * potential candidate, check end against lower 576*0Sstevel@tonic-gate * would not be precise. 577*0Sstevel@tonic-gate */ 578*0Sstevel@tonic-gate break; 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, " ra_len = %" PRIx64 ", ra_base=%" 581*0Sstevel@tonic-gate PRIx64 "\n", mapp->ra_len, mapp->ra_base); 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate if (!(req->ra_flags & NDI_RA_ALLOC_SPECIFIED)) { 587*0Sstevel@tonic-gate /* first fit - not user specified */ 588*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "ndi_ra_alloc(unspecified request)" 589*0Sstevel@tonic-gate "lower=%" PRIx64 ", upper=%" PRIx64 "\n", lower, upper); 590*0Sstevel@tonic-gate for (; mapp != NULL && mapp->ra_base <= upper; 591*0Sstevel@tonic-gate backp = &(mapp->ra_next), mapp = mapp->ra_next) { 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "ndi_ra_alloc: ra_len = %" PRIx64 594*0Sstevel@tonic-gate ", len = %" PRIx64 "", mapp->ra_len, len); 595*0Sstevel@tonic-gate base = mapp->ra_base; 596*0Sstevel@tonic-gate if (base < lower) { 597*0Sstevel@tonic-gate base = lower; 598*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "\tbase=%" PRIx64 599*0Sstevel@tonic-gate ", ra_base=%" PRIx64 ", mask=%" PRIx64, 600*0Sstevel@tonic-gate base, mapp->ra_base, mask); 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate if ((base & mask) != 0) { 604*0Sstevel@tonic-gate oldbase = base; 605*0Sstevel@tonic-gate /* 606*0Sstevel@tonic-gate * failed a critical constraint 607*0Sstevel@tonic-gate * adjust and see if it still fits 608*0Sstevel@tonic-gate */ 609*0Sstevel@tonic-gate base = base & ~mask; 610*0Sstevel@tonic-gate base += (mask + 1); 611*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "\tnew base=%" PRIx64 "\n", 612*0Sstevel@tonic-gate base); 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate /* 615*0Sstevel@tonic-gate * Check to see if the new base is past 616*0Sstevel@tonic-gate * the end of the resource. 617*0Sstevel@tonic-gate */ 618*0Sstevel@tonic-gate if (base >= (oldbase + mapp->ra_len + 1)) { 619*0Sstevel@tonic-gate continue; 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate if (req->ra_flags & NDI_RA_ALLOC_PARTIAL_OK) { 624*0Sstevel@tonic-gate if ((upper - mapp->ra_base) < mapp->ra_len) 625*0Sstevel@tonic-gate remlen = upper - base; 626*0Sstevel@tonic-gate else 627*0Sstevel@tonic-gate remlen = mapp->ra_len - 628*0Sstevel@tonic-gate (base - mapp->ra_base); 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate if ((backlargestp == NULL) || 631*0Sstevel@tonic-gate (largestlen < remlen)) { 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate backlargestp = backp; 634*0Sstevel@tonic-gate largestbase = base; 635*0Sstevel@tonic-gate largestlen = remlen; 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate if (mapp->ra_len >= len) { 640*0Sstevel@tonic-gate /* a candidate -- apply constraints */ 641*0Sstevel@tonic-gate if ((len > (mapp->ra_len - 642*0Sstevel@tonic-gate (base - mapp->ra_base))) || 643*0Sstevel@tonic-gate ((len - 1 + base) > upper)) { 644*0Sstevel@tonic-gate continue; 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate /* we have a fit */ 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "\thave a fit\n"); 650*0Sstevel@tonic-gate 651*0Sstevel@tonic-gate adjust_link(backp, mapp, base, len); 652*0Sstevel@tonic-gate rval = NDI_SUCCESS; 653*0Sstevel@tonic-gate break; 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate } else { 658*0Sstevel@tonic-gate /* want an exact value/fit */ 659*0Sstevel@tonic-gate base = req->ra_addr; 660*0Sstevel@tonic-gate len = req->ra_len; 661*0Sstevel@tonic-gate for (; mapp != NULL && mapp->ra_base <= upper; 662*0Sstevel@tonic-gate backp = &(mapp->ra_next), mapp = mapp->ra_next) { 663*0Sstevel@tonic-gate if (base >= mapp->ra_base && 664*0Sstevel@tonic-gate ((base - mapp->ra_base) < mapp->ra_len)) { 665*0Sstevel@tonic-gate /* 666*0Sstevel@tonic-gate * This is the node with he requested base in 667*0Sstevel@tonic-gate * its range 668*0Sstevel@tonic-gate */ 669*0Sstevel@tonic-gate if ((len > mapp->ra_len) || 670*0Sstevel@tonic-gate (base - mapp->ra_base > 671*0Sstevel@tonic-gate mapp->ra_len - len)) { 672*0Sstevel@tonic-gate /* length requirement not satisfied */ 673*0Sstevel@tonic-gate if (req->ra_flags & 674*0Sstevel@tonic-gate NDI_RA_ALLOC_PARTIAL_OK) { 675*0Sstevel@tonic-gate if ((upper - mapp->ra_base) 676*0Sstevel@tonic-gate < mapp->ra_len) 677*0Sstevel@tonic-gate remlen = upper - base; 678*0Sstevel@tonic-gate else 679*0Sstevel@tonic-gate remlen = 680*0Sstevel@tonic-gate mapp->ra_len - 681*0Sstevel@tonic-gate (base - 682*0Sstevel@tonic-gate mapp->ra_base); 683*0Sstevel@tonic-gate } 684*0Sstevel@tonic-gate backlargestp = backp; 685*0Sstevel@tonic-gate largestbase = base; 686*0Sstevel@tonic-gate largestlen = remlen; 687*0Sstevel@tonic-gate base = 0; 688*0Sstevel@tonic-gate } else { 689*0Sstevel@tonic-gate /* We have a match */ 690*0Sstevel@tonic-gate adjust_link(backp, mapp, base, len); 691*0Sstevel@tonic-gate rval = NDI_SUCCESS; 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate break; 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate } 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate if ((rval != NDI_SUCCESS) && 699*0Sstevel@tonic-gate (req->ra_flags & NDI_RA_ALLOC_PARTIAL_OK) && 700*0Sstevel@tonic-gate (backlargestp != NULL)) { 701*0Sstevel@tonic-gate adjust_link(backlargestp, *backlargestp, largestbase, 702*0Sstevel@tonic-gate largestlen); 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate base = largestbase; 705*0Sstevel@tonic-gate len = largestlen; 706*0Sstevel@tonic-gate rval = NDI_RA_PARTIAL_REQ; 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate mutex_exit(&ra_lock); 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate if (rval == NDI_FAILURE) { 712*0Sstevel@tonic-gate *retbasep = 0; 713*0Sstevel@tonic-gate *retlenp = 0; 714*0Sstevel@tonic-gate } else { 715*0Sstevel@tonic-gate *retbasep = base; 716*0Sstevel@tonic-gate *retlenp = len; 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate return (rval); 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate /* 722*0Sstevel@tonic-gate * isa_resource_setup 723*0Sstevel@tonic-gate * check for /used-resources and initialize 724*0Sstevel@tonic-gate * based on info there. If no /used-resources, 725*0Sstevel@tonic-gate * fail. 726*0Sstevel@tonic-gate */ 727*0Sstevel@tonic-gate int 728*0Sstevel@tonic-gate isa_resource_setup() 729*0Sstevel@tonic-gate { 730*0Sstevel@tonic-gate dev_info_t *used, *usedpdip; 731*0Sstevel@tonic-gate /* 732*0Sstevel@tonic-gate * note that at this time bootconf creates 32 bit properties for 733*0Sstevel@tonic-gate * io-space and device-memory 734*0Sstevel@tonic-gate */ 735*0Sstevel@tonic-gate struct iorange { 736*0Sstevel@tonic-gate uint32_t base; 737*0Sstevel@tonic-gate uint32_t len; 738*0Sstevel@tonic-gate } *iorange; 739*0Sstevel@tonic-gate struct memrange { 740*0Sstevel@tonic-gate uint32_t base; 741*0Sstevel@tonic-gate uint32_t len; 742*0Sstevel@tonic-gate } *memrange; 743*0Sstevel@tonic-gate uint32_t *irq; 744*0Sstevel@tonic-gate int proplen; 745*0Sstevel@tonic-gate int i, len; 746*0Sstevel@tonic-gate int maxrange; 747*0Sstevel@tonic-gate ndi_ra_request_t req; 748*0Sstevel@tonic-gate uint64_t retbase; 749*0Sstevel@tonic-gate uint64_t retlen; 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate used = ddi_find_devinfo("used-resources", -1, 0); 752*0Sstevel@tonic-gate if (used == NULL) { 753*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, 754*0Sstevel@tonic-gate "isa_resource_setup: used-resources not found"); 755*0Sstevel@tonic-gate return (NDI_FAILURE); 756*0Sstevel@tonic-gate } 757*0Sstevel@tonic-gate 758*0Sstevel@tonic-gate /* 759*0Sstevel@tonic-gate * initialize to all resources being present 760*0Sstevel@tonic-gate * and then remove the ones in use. 761*0Sstevel@tonic-gate */ 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate usedpdip = ddi_root_node(); 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate DEBUGPRT(CE_CONT, "isa_resource_setup: used = %p usedpdip = %p\n", 766*0Sstevel@tonic-gate (void *)used, (void *)usedpdip); 767*0Sstevel@tonic-gate 768*0Sstevel@tonic-gate if (ndi_ra_map_setup(usedpdip, NDI_RA_TYPE_IO) == NDI_FAILURE) { 769*0Sstevel@tonic-gate return (NDI_FAILURE); 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate /* initialize io space, highest end base is 0xffff */ 773*0Sstevel@tonic-gate /* note that length is highest addr + 1 since starts from 0 */ 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate (void) ndi_ra_free(usedpdip, 0, 0xffff + 1, NDI_RA_TYPE_IO, 0); 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, used, DDI_PROP_DONTPASS, 778*0Sstevel@tonic-gate "io-space", (caddr_t)&iorange, &proplen) == DDI_SUCCESS) { 779*0Sstevel@tonic-gate maxrange = proplen / sizeof (struct iorange); 780*0Sstevel@tonic-gate /* remove the "used" I/O resources */ 781*0Sstevel@tonic-gate for (i = 0; i < maxrange; i++) { 782*0Sstevel@tonic-gate bzero((caddr_t)&req, sizeof (req)); 783*0Sstevel@tonic-gate req.ra_addr = (uint64_t)iorange[i].base; 784*0Sstevel@tonic-gate req.ra_len = (uint64_t)iorange[i].len; 785*0Sstevel@tonic-gate req.ra_flags = NDI_RA_ALLOC_SPECIFIED; 786*0Sstevel@tonic-gate (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, 787*0Sstevel@tonic-gate NDI_RA_TYPE_IO, 0); 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate kmem_free((caddr_t)iorange, proplen); 791*0Sstevel@tonic-gate } 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate if (ndi_ra_map_setup(usedpdip, NDI_RA_TYPE_MEM) == NDI_FAILURE) { 794*0Sstevel@tonic-gate return (NDI_FAILURE); 795*0Sstevel@tonic-gate } 796*0Sstevel@tonic-gate /* initialize memory space where highest end base is 0xffffffff */ 797*0Sstevel@tonic-gate /* note that length is highest addr + 1 since starts from 0 */ 798*0Sstevel@tonic-gate (void) ndi_ra_free(usedpdip, 0, ((uint64_t)((uint32_t)~0)) + 1, 799*0Sstevel@tonic-gate NDI_RA_TYPE_MEM, 0); 800*0Sstevel@tonic-gate 801*0Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, used, DDI_PROP_DONTPASS, 802*0Sstevel@tonic-gate "device-memory", (caddr_t)&memrange, &proplen) == DDI_SUCCESS) { 803*0Sstevel@tonic-gate maxrange = proplen / sizeof (struct memrange); 804*0Sstevel@tonic-gate /* remove the "used" memory resources */ 805*0Sstevel@tonic-gate for (i = 0; i < maxrange; i++) { 806*0Sstevel@tonic-gate bzero((caddr_t)&req, sizeof (req)); 807*0Sstevel@tonic-gate req.ra_addr = (uint64_t)memrange[i].base; 808*0Sstevel@tonic-gate req.ra_len = (uint64_t)memrange[i].len; 809*0Sstevel@tonic-gate req.ra_flags = NDI_RA_ALLOC_SPECIFIED; 810*0Sstevel@tonic-gate (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, 811*0Sstevel@tonic-gate NDI_RA_TYPE_MEM, 0); 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate kmem_free((caddr_t)memrange, proplen); 815*0Sstevel@tonic-gate } 816*0Sstevel@tonic-gate 817*0Sstevel@tonic-gate if (ndi_ra_map_setup(usedpdip, NDI_RA_TYPE_INTR) == NDI_FAILURE) { 818*0Sstevel@tonic-gate return (NDI_FAILURE); 819*0Sstevel@tonic-gate } 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate /* initialize the interrupt space */ 822*0Sstevel@tonic-gate (void) ndi_ra_free(usedpdip, 0, 16, NDI_RA_TYPE_INTR, 0); 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 825*0Sstevel@tonic-gate bzero(&req, sizeof (req)); 826*0Sstevel@tonic-gate req.ra_addr = 2; /* 2 == 9 so never allow */ 827*0Sstevel@tonic-gate req.ra_len = 1; 828*0Sstevel@tonic-gate req.ra_flags = NDI_RA_ALLOC_SPECIFIED; 829*0Sstevel@tonic-gate (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, 830*0Sstevel@tonic-gate NDI_RA_TYPE_INTR, 0); 831*0Sstevel@tonic-gate #endif 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, used, DDI_PROP_DONTPASS, 834*0Sstevel@tonic-gate "interrupts", (caddr_t)&irq, &proplen) == DDI_SUCCESS) { 835*0Sstevel@tonic-gate /* Initialize available interrupts by negating the used */ 836*0Sstevel@tonic-gate len = (proplen / sizeof (uint32_t)); 837*0Sstevel@tonic-gate for (i = 0; i < len; i++) { 838*0Sstevel@tonic-gate bzero((caddr_t)&req, sizeof (req)); 839*0Sstevel@tonic-gate req.ra_addr = (uint64_t)irq[i]; 840*0Sstevel@tonic-gate req.ra_len = 1; 841*0Sstevel@tonic-gate req.ra_flags = NDI_RA_ALLOC_SPECIFIED; 842*0Sstevel@tonic-gate (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, 843*0Sstevel@tonic-gate NDI_RA_TYPE_INTR, 0); 844*0Sstevel@tonic-gate } 845*0Sstevel@tonic-gate kmem_free((caddr_t)irq, proplen); 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate #ifdef BUSRA_DEBUG 849*0Sstevel@tonic-gate if (busra_debug) { 850*0Sstevel@tonic-gate (void) ra_dump_all(NULL, usedpdip); 851*0Sstevel@tonic-gate } 852*0Sstevel@tonic-gate #endif 853*0Sstevel@tonic-gate return (NDI_SUCCESS); 854*0Sstevel@tonic-gate 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate #ifdef BUSRA_DEBUG 858*0Sstevel@tonic-gate void 859*0Sstevel@tonic-gate ra_dump_all(char *type, dev_info_t *dip) 860*0Sstevel@tonic-gate { 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate struct ra_type_map *typemap; 863*0Sstevel@tonic-gate struct ra_dip_type *dipmap; 864*0Sstevel@tonic-gate struct ra_resource *res; 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate typemap = (struct ra_type_map *)ra_map_list_head; 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate for (; typemap != NULL; typemap = typemap->ra_next) { 869*0Sstevel@tonic-gate if (type != NULL) { 870*0Sstevel@tonic-gate if (strcmp(typemap->type, type) != 0) 871*0Sstevel@tonic-gate continue; 872*0Sstevel@tonic-gate } 873*0Sstevel@tonic-gate cmn_err(CE_CONT, "type is %s\n", typemap->type); 874*0Sstevel@tonic-gate for (dipmap = typemap->ra_dip_list; dipmap != NULL; 875*0Sstevel@tonic-gate dipmap = dipmap->ra_next) { 876*0Sstevel@tonic-gate if (dip != NULL) { 877*0Sstevel@tonic-gate if ((dipmap->ra_dip) != dip) 878*0Sstevel@tonic-gate continue; 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate cmn_err(CE_CONT, " dip is %p\n", 881*0Sstevel@tonic-gate (void *)dipmap->ra_dip); 882*0Sstevel@tonic-gate for (res = dipmap->ra_rangeset; res != NULL; 883*0Sstevel@tonic-gate res = res->ra_next) { 884*0Sstevel@tonic-gate cmn_err(CE_CONT, "\t range is %" PRIx64 885*0Sstevel@tonic-gate " %" PRIx64 "\n", res->ra_base, 886*0Sstevel@tonic-gate res->ra_len); 887*0Sstevel@tonic-gate } 888*0Sstevel@tonic-gate if (dip != NULL) 889*0Sstevel@tonic-gate break; 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate if (type != NULL) 892*0Sstevel@tonic-gate break; 893*0Sstevel@tonic-gate } 894*0Sstevel@tonic-gate } 895*0Sstevel@tonic-gate #endif 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gate struct bus_range { /* 1275 "bus-range" property definition */ 898*0Sstevel@tonic-gate uint32_t lo; 899*0Sstevel@tonic-gate uint32_t hi; 900*0Sstevel@tonic-gate } pci_bus_range; 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate struct busnum_ctrl { 903*0Sstevel@tonic-gate int rv; 904*0Sstevel@tonic-gate dev_info_t *dip; 905*0Sstevel@tonic-gate struct bus_range *range; 906*0Sstevel@tonic-gate }; 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gate /* 910*0Sstevel@tonic-gate * Setup resource map for the pci bus node based on the "available" 911*0Sstevel@tonic-gate * property and "bus-range" property. 912*0Sstevel@tonic-gate */ 913*0Sstevel@tonic-gate int 914*0Sstevel@tonic-gate pci_resource_setup(dev_info_t *dip) 915*0Sstevel@tonic-gate { 916*0Sstevel@tonic-gate pci_regspec_t *regs; 917*0Sstevel@tonic-gate int rlen, rcount, i; 918*0Sstevel@tonic-gate char bus_type[16] = "(unknown)"; 919*0Sstevel@tonic-gate int len; 920*0Sstevel@tonic-gate struct busnum_ctrl ctrl; 921*0Sstevel@tonic-gate int circular_count; 922*0Sstevel@tonic-gate int rval = NDI_SUCCESS; 923*0Sstevel@tonic-gate 924*0Sstevel@tonic-gate /* 925*0Sstevel@tonic-gate * If this is a pci bus node then look for "available" property 926*0Sstevel@tonic-gate * to find the available resources on this bus. 927*0Sstevel@tonic-gate */ 928*0Sstevel@tonic-gate len = sizeof (bus_type); 929*0Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 930*0Sstevel@tonic-gate DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "device_type", 931*0Sstevel@tonic-gate (caddr_t)&bus_type, &len) != DDI_SUCCESS) 932*0Sstevel@tonic-gate return (NDI_FAILURE); 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate if (strcmp(bus_type, "pci") != 0) /* it is not a pci bus type */ 935*0Sstevel@tonic-gate return (NDI_FAILURE); 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate /* read the "available" property if it is available */ 938*0Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 939*0Sstevel@tonic-gate "available", (caddr_t)®s, &rlen) != DDI_SUCCESS) 940*0Sstevel@tonic-gate return (NDI_FAILURE); 941*0Sstevel@tonic-gate 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate /* 944*0Sstevel@tonic-gate * The pci-hotplug project addresses adding the call 945*0Sstevel@tonic-gate * to pci_resource_setup from pci nexus driver. 946*0Sstevel@tonic-gate * However that project would initially be only for x86, 947*0Sstevel@tonic-gate * so for sparc pcmcia-pci support we still need to call 948*0Sstevel@tonic-gate * pci_resource_setup in pcic driver. Once all pci nexus drivers 949*0Sstevel@tonic-gate * are updated to call pci_resource_setup this portion of the 950*0Sstevel@tonic-gate * code would really become an assert to make sure this 951*0Sstevel@tonic-gate * function is not called for the same dip twice. 952*0Sstevel@tonic-gate */ 953*0Sstevel@tonic-gate { 954*0Sstevel@tonic-gate if (ra_map_exist(dip, NDI_RA_TYPE_MEM) == NDI_SUCCESS) { 955*0Sstevel@tonic-gate return (NDI_FAILURE); 956*0Sstevel@tonic-gate } 957*0Sstevel@tonic-gate } 958*0Sstevel@tonic-gate 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate if (ndi_ra_map_setup(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) { 961*0Sstevel@tonic-gate return (NDI_FAILURE); 962*0Sstevel@tonic-gate } 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate if (ndi_ra_map_setup(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) { 965*0Sstevel@tonic-gate return (NDI_FAILURE); 966*0Sstevel@tonic-gate } 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gate if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_BUSNUM) == NDI_FAILURE) { 969*0Sstevel@tonic-gate return (NDI_FAILURE); 970*0Sstevel@tonic-gate } 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_PREFETCH_MEM) == 973*0Sstevel@tonic-gate NDI_FAILURE) { 974*0Sstevel@tonic-gate return (NDI_FAILURE); 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate /* create the available resource list for both memory and io space */ 979*0Sstevel@tonic-gate rcount = rlen / sizeof (pci_regspec_t); 980*0Sstevel@tonic-gate for (i = 0; i < rcount; i++) { 981*0Sstevel@tonic-gate switch (PCI_REG_ADDR_G(regs[i].pci_phys_hi)) { 982*0Sstevel@tonic-gate case PCI_REG_ADDR_G(PCI_ADDR_MEM32): 983*0Sstevel@tonic-gate (void) ndi_ra_free(dip, 984*0Sstevel@tonic-gate (uint64_t)regs[i].pci_phys_low, 985*0Sstevel@tonic-gate (uint64_t)regs[i].pci_size_low, 986*0Sstevel@tonic-gate (regs[i].pci_phys_hi & PCI_REG_PF_M) ? 987*0Sstevel@tonic-gate NDI_RA_TYPE_PCI_PREFETCH_MEM : NDI_RA_TYPE_MEM, 988*0Sstevel@tonic-gate 0); 989*0Sstevel@tonic-gate break; 990*0Sstevel@tonic-gate case PCI_REG_ADDR_G(PCI_ADDR_MEM64): 991*0Sstevel@tonic-gate (void) ndi_ra_free(dip, 992*0Sstevel@tonic-gate ((uint64_t)(regs[i].pci_phys_mid) << 32) | 993*0Sstevel@tonic-gate ((uint64_t)(regs[i].pci_phys_low)), 994*0Sstevel@tonic-gate ((uint64_t)(regs[i].pci_size_hi) << 32) | 995*0Sstevel@tonic-gate ((uint64_t)(regs[i].pci_size_low)), 996*0Sstevel@tonic-gate (regs[i].pci_phys_hi & PCI_REG_PF_M) ? 997*0Sstevel@tonic-gate NDI_RA_TYPE_PCI_PREFETCH_MEM : NDI_RA_TYPE_MEM, 998*0Sstevel@tonic-gate 0); 999*0Sstevel@tonic-gate break; 1000*0Sstevel@tonic-gate case PCI_REG_ADDR_G(PCI_ADDR_IO): 1001*0Sstevel@tonic-gate (void) ndi_ra_free(dip, 1002*0Sstevel@tonic-gate (uint64_t)regs[i].pci_phys_low, 1003*0Sstevel@tonic-gate (uint64_t)regs[i].pci_size_low, 1004*0Sstevel@tonic-gate NDI_RA_TYPE_IO, 1005*0Sstevel@tonic-gate 0); 1006*0Sstevel@tonic-gate break; 1007*0Sstevel@tonic-gate case PCI_REG_ADDR_G(PCI_ADDR_CONFIG): 1008*0Sstevel@tonic-gate break; 1009*0Sstevel@tonic-gate default: 1010*0Sstevel@tonic-gate cmn_err(CE_WARN, 1011*0Sstevel@tonic-gate "pci_resource_setup: bad addr type: %x\n", 1012*0Sstevel@tonic-gate PCI_REG_ADDR_G(regs[i].pci_phys_hi)); 1013*0Sstevel@tonic-gate break; 1014*0Sstevel@tonic-gate } 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate kmem_free((caddr_t)regs, rlen); 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate /* 1020*0Sstevel@tonic-gate * Create resource map for available bus numbers if the node 1021*0Sstevel@tonic-gate * has available-bus-range or bus-range property. 1022*0Sstevel@tonic-gate */ 1023*0Sstevel@tonic-gate len = sizeof (struct bus_range); 1024*0Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 1025*0Sstevel@tonic-gate "available-bus-range", (caddr_t)&pci_bus_range, &len) == 1026*0Sstevel@tonic-gate DDI_SUCCESS) { 1027*0Sstevel@tonic-gate /* 1028*0Sstevel@tonic-gate * Add bus numbers in the range to the free list. 1029*0Sstevel@tonic-gate */ 1030*0Sstevel@tonic-gate (void) ndi_ra_free(dip, (uint64_t)pci_bus_range.lo, 1031*0Sstevel@tonic-gate (uint64_t)pci_bus_range.hi - (uint64_t)pci_bus_range.lo + 1032*0Sstevel@tonic-gate 1, NDI_RA_TYPE_PCI_BUSNUM, 0); 1033*0Sstevel@tonic-gate } else { 1034*0Sstevel@tonic-gate /* 1035*0Sstevel@tonic-gate * We don't have an available-bus-range property. If, instead, 1036*0Sstevel@tonic-gate * we have a bus-range property we add all the bus numbers 1037*0Sstevel@tonic-gate * in that range to the free list but we must then scan 1038*0Sstevel@tonic-gate * for pci-pci bridges on this bus to find out the if there 1039*0Sstevel@tonic-gate * are any of those bus numbers already in use. If so, we can 1040*0Sstevel@tonic-gate * reclaim them. 1041*0Sstevel@tonic-gate */ 1042*0Sstevel@tonic-gate len = sizeof (struct bus_range); 1043*0Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_NONE, dip, 1044*0Sstevel@tonic-gate DDI_PROP_DONTPASS, "bus-range", (caddr_t)&pci_bus_range, 1045*0Sstevel@tonic-gate &len) == DDI_SUCCESS) { 1046*0Sstevel@tonic-gate if (pci_bus_range.lo != pci_bus_range.hi) { 1047*0Sstevel@tonic-gate /* 1048*0Sstevel@tonic-gate * Add bus numbers other than the secondary 1049*0Sstevel@tonic-gate * bus number to the free list. 1050*0Sstevel@tonic-gate */ 1051*0Sstevel@tonic-gate (void) ndi_ra_free(dip, 1052*0Sstevel@tonic-gate (uint64_t)pci_bus_range.lo + 1, 1053*0Sstevel@tonic-gate (uint64_t)pci_bus_range.hi - 1054*0Sstevel@tonic-gate (uint64_t)pci_bus_range.lo, 1055*0Sstevel@tonic-gate NDI_RA_TYPE_PCI_BUSNUM, 0); 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate /* scan for pci-pci bridges */ 1058*0Sstevel@tonic-gate ctrl.rv = DDI_SUCCESS; 1059*0Sstevel@tonic-gate ctrl.dip = dip; 1060*0Sstevel@tonic-gate ctrl.range = &pci_bus_range; 1061*0Sstevel@tonic-gate ndi_devi_enter(dip, &circular_count); 1062*0Sstevel@tonic-gate ddi_walk_devs(ddi_get_child(dip), 1063*0Sstevel@tonic-gate claim_pci_busnum, (void *)&ctrl); 1064*0Sstevel@tonic-gate ndi_devi_exit(dip, circular_count); 1065*0Sstevel@tonic-gate if (ctrl.rv != DDI_SUCCESS) { 1066*0Sstevel@tonic-gate /* failed to create the map */ 1067*0Sstevel@tonic-gate (void) ndi_ra_map_destroy(dip, 1068*0Sstevel@tonic-gate NDI_RA_TYPE_PCI_BUSNUM); 1069*0Sstevel@tonic-gate rval = NDI_FAILURE; 1070*0Sstevel@tonic-gate } 1071*0Sstevel@tonic-gate } 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate } 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate #ifdef BUSRA_DEBUG 1076*0Sstevel@tonic-gate if (busra_debug) { 1077*0Sstevel@tonic-gate (void) ra_dump_all(NULL, dip); 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate #endif 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate return (rval); 1082*0Sstevel@tonic-gate } 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate /* 1085*0Sstevel@tonic-gate * If the device is a PCI bus device (i.e bus-range property exists) then 1086*0Sstevel@tonic-gate * claim the bus numbers used by the device from the specified bus 1087*0Sstevel@tonic-gate * resource map. 1088*0Sstevel@tonic-gate */ 1089*0Sstevel@tonic-gate static int 1090*0Sstevel@tonic-gate claim_pci_busnum(dev_info_t *dip, void *arg) 1091*0Sstevel@tonic-gate { 1092*0Sstevel@tonic-gate struct bus_range pci_bus_range; 1093*0Sstevel@tonic-gate struct busnum_ctrl *ctrl; 1094*0Sstevel@tonic-gate ndi_ra_request_t req; 1095*0Sstevel@tonic-gate char bus_type[16] = "(unknown)"; 1096*0Sstevel@tonic-gate int len; 1097*0Sstevel@tonic-gate uint64_t base; 1098*0Sstevel@tonic-gate uint64_t retlen; 1099*0Sstevel@tonic-gate 1100*0Sstevel@tonic-gate ctrl = (struct busnum_ctrl *)arg; 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate /* check if this is a PCI bus node */ 1103*0Sstevel@tonic-gate len = sizeof (bus_type); 1104*0Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 1105*0Sstevel@tonic-gate DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "device_type", 1106*0Sstevel@tonic-gate (caddr_t)&bus_type, &len) != DDI_SUCCESS) 1107*0Sstevel@tonic-gate return (DDI_WALK_PRUNECHILD); 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate if (strcmp(bus_type, "pci") != 0) /* it is not a pci bus type */ 1110*0Sstevel@tonic-gate return (DDI_WALK_PRUNECHILD); 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate /* look for the bus-range property */ 1113*0Sstevel@tonic-gate len = sizeof (struct bus_range); 1114*0Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 1115*0Sstevel@tonic-gate "bus-range", (caddr_t)&pci_bus_range, &len) == DDI_SUCCESS) { 1116*0Sstevel@tonic-gate if ((pci_bus_range.lo >= ctrl->range->lo) && 1117*0Sstevel@tonic-gate (pci_bus_range.hi <= ctrl->range->hi)) { 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate /* claim the bus range from the bus resource map */ 1120*0Sstevel@tonic-gate bzero((caddr_t)&req, sizeof (req)); 1121*0Sstevel@tonic-gate req.ra_addr = (uint64_t)pci_bus_range.lo; 1122*0Sstevel@tonic-gate req.ra_flags |= NDI_RA_ALLOC_SPECIFIED; 1123*0Sstevel@tonic-gate req.ra_len = (uint64_t)pci_bus_range.hi - 1124*0Sstevel@tonic-gate (uint64_t)pci_bus_range.lo + 1; 1125*0Sstevel@tonic-gate if (ndi_ra_alloc(ctrl->dip, &req, &base, &retlen, 1126*0Sstevel@tonic-gate NDI_RA_TYPE_PCI_BUSNUM, 0) == NDI_SUCCESS) 1127*0Sstevel@tonic-gate return (DDI_WALK_PRUNECHILD); 1128*0Sstevel@tonic-gate } 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate /* 1132*0Sstevel@tonic-gate * Error return. 1133*0Sstevel@tonic-gate */ 1134*0Sstevel@tonic-gate ctrl->rv = DDI_FAILURE; 1135*0Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 1136*0Sstevel@tonic-gate } 1137*0Sstevel@tonic-gate 1138*0Sstevel@tonic-gate void 1139*0Sstevel@tonic-gate pci_resource_destroy(dev_info_t *dip) 1140*0Sstevel@tonic-gate { 1141*0Sstevel@tonic-gate (void) ndi_ra_map_destroy(dip, NDI_RA_TYPE_IO); 1142*0Sstevel@tonic-gate 1143*0Sstevel@tonic-gate (void) ndi_ra_map_destroy(dip, NDI_RA_TYPE_MEM); 1144*0Sstevel@tonic-gate 1145*0Sstevel@tonic-gate (void) ndi_ra_map_destroy(dip, NDI_RA_TYPE_PCI_BUSNUM); 1146*0Sstevel@tonic-gate 1147*0Sstevel@tonic-gate (void) ndi_ra_map_destroy(dip, NDI_RA_TYPE_PCI_PREFETCH_MEM); 1148*0Sstevel@tonic-gate } 1149*0Sstevel@tonic-gate 1150*0Sstevel@tonic-gate 1151*0Sstevel@tonic-gate int 1152*0Sstevel@tonic-gate pci_resource_setup_avail(dev_info_t *dip, pci_regspec_t *avail_p, int entries) 1153*0Sstevel@tonic-gate { 1154*0Sstevel@tonic-gate int i; 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate if (ndi_ra_map_setup(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) 1157*0Sstevel@tonic-gate return (NDI_FAILURE); 1158*0Sstevel@tonic-gate if (ndi_ra_map_setup(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) 1159*0Sstevel@tonic-gate return (NDI_FAILURE); 1160*0Sstevel@tonic-gate if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_PREFETCH_MEM) == NDI_FAILURE) 1161*0Sstevel@tonic-gate return (NDI_FAILURE); 1162*0Sstevel@tonic-gate 1163*0Sstevel@tonic-gate /* for each entry in the PCI "available" property */ 1164*0Sstevel@tonic-gate for (i = 0; i < entries; i++, avail_p++) { 1165*0Sstevel@tonic-gate if (avail_p->pci_phys_hi == -1u) 1166*0Sstevel@tonic-gate goto err; 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate switch (PCI_REG_ADDR_G(avail_p->pci_phys_hi)) { 1169*0Sstevel@tonic-gate case PCI_REG_ADDR_G(PCI_ADDR_MEM32): { 1170*0Sstevel@tonic-gate (void) ndi_ra_free(dip, 1171*0Sstevel@tonic-gate (uint64_t)avail_p->pci_phys_low, 1172*0Sstevel@tonic-gate (uint64_t)avail_p->pci_size_low, 1173*0Sstevel@tonic-gate (avail_p->pci_phys_hi & 1174*0Sstevel@tonic-gate PCI_REG_PF_M) ? 1175*0Sstevel@tonic-gate NDI_RA_TYPE_PCI_PREFETCH_MEM : 1176*0Sstevel@tonic-gate NDI_RA_TYPE_MEM, 1177*0Sstevel@tonic-gate 0); 1178*0Sstevel@tonic-gate } 1179*0Sstevel@tonic-gate break; 1180*0Sstevel@tonic-gate case PCI_REG_ADDR_G(PCI_ADDR_IO): 1181*0Sstevel@tonic-gate (void) ndi_ra_free(dip, 1182*0Sstevel@tonic-gate (uint64_t)avail_p->pci_phys_low, 1183*0Sstevel@tonic-gate (uint64_t)avail_p->pci_size_low, 1184*0Sstevel@tonic-gate NDI_RA_TYPE_IO, 1185*0Sstevel@tonic-gate 0); 1186*0Sstevel@tonic-gate break; 1187*0Sstevel@tonic-gate default: 1188*0Sstevel@tonic-gate goto err; 1189*0Sstevel@tonic-gate } 1190*0Sstevel@tonic-gate } 1191*0Sstevel@tonic-gate #ifdef BUSRA_DEBUG 1192*0Sstevel@tonic-gate if (busra_debug) { 1193*0Sstevel@tonic-gate (void) ra_dump_all(NULL, dip); 1194*0Sstevel@tonic-gate } 1195*0Sstevel@tonic-gate #endif 1196*0Sstevel@tonic-gate return (NDI_SUCCESS); 1197*0Sstevel@tonic-gate 1198*0Sstevel@tonic-gate err: 1199*0Sstevel@tonic-gate cmn_err(CE_WARN, "pci_resource_setup_avail: bad entry[%d]=%x\n", 1200*0Sstevel@tonic-gate i, avail_p->pci_phys_hi); 1201*0Sstevel@tonic-gate return (NDI_FAILURE); 1202*0Sstevel@tonic-gate } 1203