1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*
  26  *     PCI configurator (pcicfg)
  27  */
  28 
  29 #include <sys/sysmacros.h>
  30 #include <sys/conf.h>
  31 #include <sys/kmem.h>
  32 #include <sys/debug.h>
  33 #include <sys/modctl.h>
  34 #include <sys/autoconf.h>
  35 #include <sys/hwconf.h>
  36 #include <sys/pcie.h>
  37 #include <sys/pcie_impl.h>
  38 #include <sys/pci_cap.h>
  39 #include <sys/ddi.h>
  40 #include <sys/sunndi.h>
  41 #include <sys/hotplug/pci/pcicfg.h>
  42 #include <sys/ndi_impldefs.h>
  43 #include <sys/pci_cfgacc.h>
  44 #include <sys/pcie_impl.h>
  45 
  46 /*
  47  * ************************************************************************
  48  * *** Implementation specific local data structures/definitions.       ***
  49  * ************************************************************************
  50  */
  51 
  52 static  int     pcicfg_start_devno = 0; /* for Debug only */
  53 
  54 #define PCICFG_MAX_ARI_FUNCTION 256
  55 
  56 #define PCICFG_NODEVICE 42
  57 #define PCICFG_NOMEMORY 43
  58 #define PCICFG_NOMULTI  44
  59 #define PCICFG_NORESRC  45
  60 
  61 #define PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & \
  62         0xFFFFFFFF00000000ULL)>> 32))
  63 #define PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
  64 #define PCICFG_LADDR(lo, hi)    (((uint64_t)(hi) << 32) | (uint32_t)(lo))
  65 
  66 #define PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
  67 #define PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
  68 #define PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
  69 #define PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
  70 
  71 #define PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
  72 #define PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
  73 
  74 #define PCICFG_MEMGRAN 0x100000
  75 #define PCICFG_IOGRAN 0x1000
  76 #define PCICFG_4GIG_LIMIT 0xFFFFFFFFUL
  77 
  78 #define PCICFG_MEM_MULT 4
  79 #define PCICFG_IO_MULT 4
  80 #define PCICFG_RANGE_LEN 3 /* Number of range entries */
  81 
  82 static int pcicfg_slot_busnums = 8;
  83 static int pcicfg_slot_memsize = 32 * PCICFG_MEMGRAN; /* 32MB per slot */
  84 static int pcicfg_slot_pf_memsize = 32 * PCICFG_MEMGRAN; /* 32MB per slot */
  85 static int pcicfg_slot_iosize = 64 * PCICFG_IOGRAN; /* 64K per slot */
  86 static int pcicfg_sec_reset_delay = 3000000;
  87 static int pcicfg_do_legacy_props = 1;  /* create legacy compatible prop */
  88 
  89 typedef struct hole hole_t;
  90 
  91 struct hole {
  92         uint64_t        start;
  93         uint64_t        len;
  94         hole_t          *next;
  95 };
  96 
  97 typedef struct pcicfg_phdl pcicfg_phdl_t;
  98 
  99 struct pcicfg_phdl {
 100 
 101         dev_info_t      *dip;           /* Associated with the bridge */
 102         dev_info_t      *top_dip;       /* top node of the attach point */
 103         pcicfg_phdl_t   *next;
 104 
 105         /* non-prefetchable memory space */
 106         uint64_t        memory_base;    /* Memory base for this attach point */
 107         uint64_t        memory_last;
 108         uint64_t        memory_len;
 109 
 110         /* prefetchable memory space */
 111         uint64_t        pf_memory_base; /* PF Memory base for this Connection */
 112         uint64_t        pf_memory_last;
 113         uint64_t        pf_memory_len;
 114 
 115         /* io space */
 116         uint32_t        io_base;        /* I/O base for this attach point */
 117         uint32_t        io_last;
 118         uint32_t        io_len;
 119 
 120         int             error;
 121         uint_t          highest_bus;    /* Highest bus seen on the probe */
 122 
 123         hole_t          mem_hole;       /* Memory hole linked list. */
 124         hole_t          pf_mem_hole;    /* PF Memory hole linked list. */
 125         hole_t          io_hole;        /* IO hole linked list */
 126 
 127         ndi_ra_request_t mem_req;       /* allocator request for memory */
 128         ndi_ra_request_t pf_mem_req;    /* allocator request for PF memory */
 129         ndi_ra_request_t io_req;        /* allocator request for I/O */
 130 };
 131 
 132 struct pcicfg_standard_prop_entry {
 133     uchar_t *name;
 134     uint_t  config_offset;
 135     uint_t  size;
 136 };
 137 
 138 
 139 struct pcicfg_name_entry {
 140     uint32_t class_code;
 141     char  *name;
 142 };
 143 
 144 struct pcicfg_find_ctrl {
 145         uint_t          device;
 146         uint_t          function;
 147         dev_info_t      *dip;
 148 };
 149 
 150 /*
 151  * List of Indirect Config Map Devices. At least the intent of the
 152  * design is to look for a device in this list during the configure
 153  * operation, and if the device is listed here, then it is a nontransparent
 154  * bridge, hence load the driver and avail the config map services from
 155  * the driver. Class and Subclass should be as defined in the PCI specs
 156  * ie. class is 0x6, and subclass is 0x9.
 157  */
 158 static struct {
 159         uint8_t         mem_range_bar_offset;
 160         uint8_t         io_range_bar_offset;
 161         uint8_t         prefetch_mem_range_bar_offset;
 162 } pcicfg_indirect_map_devs[] = {
 163         { PCI_CONF_BASE3, PCI_CONF_BASE2, PCI_CONF_BASE3 },
 164         { 0,    0,      0 },
 165 };
 166 
 167 #define PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\
 168         (\
 169         ((ulong_t)(busnum & 0xff) << 16)    |\
 170         ((ulong_t)(devnum & 0x1f) << 11)    |\
 171         ((ulong_t)(funcnum & 0x7) <<  8)    |\
 172         ((ulong_t)(register & 0x3f)))
 173 
 174 /*
 175  * debug macros:
 176  */
 177 #if     defined(DEBUG)
 178 extern void prom_printf(const char *, ...);
 179 
 180 /*
 181  * Following values are defined for this debug flag.
 182  *
 183  * 1 = dump configuration header only.
 184  * 2 = dump generic debug data only (no config header dumped)
 185  * 3 = dump everything (both 1 and 2)
 186  */
 187 int pcicfg_debug = 0;
 188 
 189 static void debug(char *, uintptr_t, uintptr_t,
 190         uintptr_t, uintptr_t, uintptr_t);
 191 
 192 #define DEBUG0(fmt)\
 193         debug(fmt, 0, 0, 0, 0, 0);
 194 #define DEBUG1(fmt, a1)\
 195         debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
 196 #define DEBUG2(fmt, a1, a2)\
 197         debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
 198 #define DEBUG3(fmt, a1, a2, a3)\
 199         debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
 200                 (uintptr_t)(a3), 0, 0);
 201 #define DEBUG4(fmt, a1, a2, a3, a4)\
 202         debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
 203                 (uintptr_t)(a3), (uintptr_t)(a4), 0);
 204 #define DEBUG5(fmt, a1, a2, a3, a4, a5)\
 205         debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
 206                 (uintptr_t)(a3), (uintptr_t)(a4), (uintptr_t)(a5));
 207 #else
 208 #define DEBUG0(fmt)
 209 #define DEBUG1(fmt, a1)
 210 #define DEBUG2(fmt, a1, a2)
 211 #define DEBUG3(fmt, a1, a2, a3)
 212 #define DEBUG4(fmt, a1, a2, a3, a4)
 213 #define DEBUG5(fmt, a1, a2, a3, a4, a5)
 214 #endif
 215 
 216 /*
 217  * forward declarations for routines defined in this module (called here)
 218  */
 219 
 220 static int pcicfg_add_config_reg(dev_info_t *,
 221     uint_t, uint_t, uint_t);
 222 static int pcicfg_probe_children(dev_info_t *, uint_t, uint_t, uint_t,
 223     uint_t *, pcicfg_flags_t, boolean_t);
 224 static int pcicfg_match_dev(dev_info_t *, void *);
 225 static dev_info_t *pcicfg_devi_find(dev_info_t *, uint_t, uint_t);
 226 static pcicfg_phdl_t *pcicfg_find_phdl(dev_info_t *);
 227 static pcicfg_phdl_t *pcicfg_create_phdl(dev_info_t *);
 228 static int pcicfg_destroy_phdl(dev_info_t *);
 229 static int pcicfg_sum_resources(dev_info_t *, void *);
 230 static int pcicfg_device_assign(dev_info_t *);
 231 static int pcicfg_bridge_assign(dev_info_t *, void *);
 232 static int pcicfg_device_assign_readonly(dev_info_t *);
 233 static int pcicfg_free_resources(dev_info_t *, pcicfg_flags_t);
 234 static void pcicfg_setup_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
 235 static void pcicfg_update_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
 236 static int pcicfg_update_assigned_prop(dev_info_t *, pci_regspec_t *);
 237 static void pcicfg_device_on(ddi_acc_handle_t);
 238 static void pcicfg_device_off(ddi_acc_handle_t);
 239 static int pcicfg_set_busnode_props(dev_info_t *, uint8_t);
 240 static int pcicfg_free_bridge_resources(dev_info_t *);
 241 static int pcicfg_free_device_resources(dev_info_t *);
 242 static int pcicfg_teardown_device(dev_info_t *, pcicfg_flags_t, boolean_t);
 243 static void pcicfg_reparent_node(dev_info_t *, dev_info_t *);
 244 static int pcicfg_config_setup(dev_info_t *, ddi_acc_handle_t *);
 245 static void pcicfg_config_teardown(ddi_acc_handle_t *);
 246 static void pcicfg_get_mem(pcicfg_phdl_t *, uint32_t, uint64_t *);
 247 static void pcicfg_get_pf_mem(pcicfg_phdl_t *, uint32_t, uint64_t *);
 248 static void pcicfg_get_io(pcicfg_phdl_t *, uint32_t, uint32_t *);
 249 static int pcicfg_update_ranges_prop(dev_info_t *, ppb_ranges_t *);
 250 static int pcicfg_configure_ntbridge(dev_info_t *, uint_t, uint_t);
 251 static uint_t pcicfg_ntbridge_child(dev_info_t *);
 252 static uint_t pcicfg_get_ntbridge_child_range(dev_info_t *, uint64_t *,
 253     uint64_t *, uint_t);
 254 static int pcicfg_is_ntbridge(dev_info_t *);
 255 static int pcicfg_ntbridge_allocate_resources(dev_info_t *);
 256 static int pcicfg_ntbridge_configure_done(dev_info_t *);
 257 static int pcicfg_ntbridge_program_child(dev_info_t *);
 258 static uint_t pcicfg_ntbridge_unconfigure(dev_info_t *);
 259 static int pcicfg_ntbridge_unconfigure_child(dev_info_t *, uint_t);
 260 static void pcicfg_free_hole(hole_t *);
 261 static uint64_t pcicfg_alloc_hole(hole_t *, uint64_t *, uint32_t);
 262 static int pcicfg_device_type(dev_info_t *, ddi_acc_handle_t *);
 263 static void pcicfg_update_phdl(dev_info_t *, uint8_t, uint8_t);
 264 static int pcicfg_get_cap(ddi_acc_handle_t, uint8_t);
 265 static uint8_t pcicfg_get_nslots(dev_info_t *, ddi_acc_handle_t);
 266 static int pcicfg_pcie_dev(dev_info_t *, ddi_acc_handle_t);
 267 static int pcicfg_pcie_device_type(dev_info_t *, ddi_acc_handle_t);
 268 static int pcicfg_pcie_port_type(dev_info_t *, ddi_acc_handle_t);
 269 static int pcicfg_probe_bridge(dev_info_t *, ddi_acc_handle_t, uint_t,
 270         uint_t *, boolean_t);
 271 static int pcicfg_find_resource_end(dev_info_t *, void *);
 272 static boolean_t is_pcie_fabric(dev_info_t *);
 273 
 274 static int pcicfg_populate_reg_props(dev_info_t *, ddi_acc_handle_t);
 275 static int pcicfg_populate_props_from_bar(dev_info_t *, ddi_acc_handle_t);
 276 static int pcicfg_update_assigned_prop_value(dev_info_t *, uint32_t,
 277     uint32_t, uint32_t, uint_t);
 278 static int pcicfg_ari_configure(dev_info_t *);
 279 
 280 #ifdef DEBUG
 281 static void pcicfg_dump_common_config(ddi_acc_handle_t config_handle);
 282 static void pcicfg_dump_device_config(ddi_acc_handle_t);
 283 static void pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle);
 284 static uint64_t pcicfg_unused_space(hole_t *, uint32_t *);
 285 
 286 #define PCICFG_DUMP_COMMON_CONFIG(hdl) (void)pcicfg_dump_common_config(hdl)
 287 #define PCICFG_DUMP_DEVICE_CONFIG(hdl) (void)pcicfg_dump_device_config(hdl)
 288 #define PCICFG_DUMP_BRIDGE_CONFIG(hdl) (void)pcicfg_dump_bridge_config(hdl)
 289 #else
 290 #define PCICFG_DUMP_COMMON_CONFIG(handle)
 291 #define PCICFG_DUMP_DEVICE_CONFIG(handle)
 292 #define PCICFG_DUMP_BRIDGE_CONFIG(handle)
 293 #endif
 294 
 295 static kmutex_t pcicfg_list_mutex; /* Protects the probe handle list */
 296 static pcicfg_phdl_t *pcicfg_phdl_list = NULL;
 297 
 298 #ifndef _DONT_USE_1275_GENERIC_NAMES
 299 /*
 300  * Class code table
 301  */
 302 static struct pcicfg_name_entry pcicfg_class_lookup [] = {
 303 
 304         { 0x001, "display" },
 305         { 0x100, "scsi" },
 306         { 0x101, "ide" },
 307         { 0x102, "fdc" },
 308         { 0x103, "ipi" },
 309         { 0x104, "raid" },
 310         { 0x105, "ata" },
 311         { 0x106, "sata" },
 312         { 0x200, "ethernet" },
 313         { 0x201, "token-ring" },
 314         { 0x202, "fddi" },
 315         { 0x203, "atm" },
 316         { 0x204, "isdn" },
 317         { 0x206, "mcd" },
 318         { 0x300, "display" },
 319         { 0x400, "video" },
 320         { 0x401, "sound" },
 321         { 0x500, "memory" },
 322         { 0x501, "flash" },
 323         { 0x600, "host" },
 324         { 0x601, "isa" },
 325         { 0x602, "eisa" },
 326         { 0x603, "mca" },
 327         { 0x604, "pci" },
 328         { 0x605, "pcmcia" },
 329         { 0x606, "nubus" },
 330         { 0x607, "cardbus" },
 331         { 0x609, "pci" },
 332         { 0x60a, "ib-pci" },
 333         { 0x700, "serial" },
 334         { 0x701, "parallel" },
 335         { 0x800, "interrupt-controller" },
 336         { 0x801, "dma-controller" },
 337         { 0x802, "timer" },
 338         { 0x803, "rtc" },
 339         { 0x900, "keyboard" },
 340         { 0x901, "pen" },
 341         { 0x902, "mouse" },
 342         { 0xa00, "dock" },
 343         { 0xb00, "cpu" },
 344         { 0xb01, "cpu" },
 345         { 0xb02, "cpu" },
 346         { 0xb10, "cpu" },
 347         { 0xb20, "cpu" },
 348         { 0xb30, "cpu" },
 349         { 0xb40, "coproc" },
 350         { 0xc00, "firewire" },
 351         { 0xc01, "access-bus" },
 352         { 0xc02, "ssa" },
 353         { 0xc03, "usb" },
 354         { 0xc04, "fibre-channel" },
 355         { 0xc05, "smbus" },
 356         { 0xc06, "ib" },
 357         { 0xd00, "irda" },
 358         { 0xd01, "ir" },
 359         { 0xd10, "rf" },
 360         { 0xd11, "btooth" },
 361         { 0xd12, "brdband" },
 362         { 0xd20, "802.11a" },
 363         { 0xd21, "802.11b" },
 364         { 0xe00, "i2o" },
 365         { 0xf01, "tv" },
 366         { 0xf02, "audio" },
 367         { 0xf03, "voice" },
 368         { 0xf04, "data" },
 369         { 0, 0 }
 370 };
 371 #endif /* _DONT_USE_1275_GENERIC_NAMES */
 372 
 373 /*
 374  * Module control operations
 375  */
 376 
 377 extern struct mod_ops mod_miscops;
 378 
 379 static struct modlmisc modlmisc = {
 380         &mod_miscops, /* Type of module */
 381         "PCI configurator"
 382 };
 383 
 384 static struct modlinkage modlinkage = {
 385         MODREV_1, { (void *)&modlmisc, NULL }
 386 };
 387 
 388 
 389 #ifdef DEBUG
 390 
 391 static void
 392 pcicfg_dump_common_config(ddi_acc_handle_t config_handle)
 393 {
 394         if ((pcicfg_debug & 1) == 0)
 395                 return;
 396         prom_printf(" Vendor ID   = [0x%x]\n",
 397             pci_config_get16(config_handle, PCI_CONF_VENID));
 398         prom_printf(" Device ID   = [0x%x]\n",
 399             pci_config_get16(config_handle, PCI_CONF_DEVID));
 400         prom_printf(" Command REG = [0x%x]\n",
 401             pci_config_get16(config_handle, PCI_CONF_COMM));
 402         prom_printf(" Status  REG = [0x%x]\n",
 403             pci_config_get16(config_handle, PCI_CONF_STAT));
 404         prom_printf(" Revision ID = [0x%x]\n",
 405             pci_config_get8(config_handle, PCI_CONF_REVID));
 406         prom_printf(" Prog Class  = [0x%x]\n",
 407             pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
 408         prom_printf(" Dev Class   = [0x%x]\n",
 409             pci_config_get8(config_handle, PCI_CONF_SUBCLASS));
 410         prom_printf(" Base Class  = [0x%x]\n",
 411             pci_config_get8(config_handle, PCI_CONF_BASCLASS));
 412         prom_printf(" Device ID   = [0x%x]\n",
 413             pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ));
 414         prom_printf(" Header Type = [0x%x]\n",
 415             pci_config_get8(config_handle, PCI_CONF_HEADER));
 416         prom_printf(" BIST        = [0x%x]\n",
 417             pci_config_get8(config_handle, PCI_CONF_BIST));
 418         prom_printf(" BASE 0      = [0x%x]\n",
 419             pci_config_get32(config_handle, PCI_CONF_BASE0));
 420         prom_printf(" BASE 1      = [0x%x]\n",
 421             pci_config_get32(config_handle, PCI_CONF_BASE1));
 422 
 423 }
 424 
 425 static void
 426 pcicfg_dump_device_config(ddi_acc_handle_t config_handle)
 427 {
 428         if ((pcicfg_debug & 1) == 0)
 429                 return;
 430         pcicfg_dump_common_config(config_handle);
 431 
 432         prom_printf(" BASE 2      = [0x%x]\n",
 433             pci_config_get32(config_handle, PCI_CONF_BASE2));
 434         prom_printf(" BASE 3      = [0x%x]\n",
 435             pci_config_get32(config_handle, PCI_CONF_BASE3));
 436         prom_printf(" BASE 4      = [0x%x]\n",
 437             pci_config_get32(config_handle, PCI_CONF_BASE4));
 438         prom_printf(" BASE 5      = [0x%x]\n",
 439             pci_config_get32(config_handle, PCI_CONF_BASE5));
 440         prom_printf(" Cardbus CIS = [0x%x]\n",
 441             pci_config_get32(config_handle, PCI_CONF_CIS));
 442         prom_printf(" Sub VID     = [0x%x]\n",
 443             pci_config_get16(config_handle, PCI_CONF_SUBVENID));
 444         prom_printf(" Sub SID     = [0x%x]\n",
 445             pci_config_get16(config_handle, PCI_CONF_SUBSYSID));
 446         prom_printf(" ROM         = [0x%x]\n",
 447             pci_config_get32(config_handle, PCI_CONF_ROM));
 448         prom_printf(" I Line      = [0x%x]\n",
 449             pci_config_get8(config_handle, PCI_CONF_ILINE));
 450         prom_printf(" I Pin       = [0x%x]\n",
 451             pci_config_get8(config_handle, PCI_CONF_IPIN));
 452         prom_printf(" Max Grant   = [0x%x]\n",
 453             pci_config_get8(config_handle, PCI_CONF_MIN_G));
 454         prom_printf(" Max Latent  = [0x%x]\n",
 455             pci_config_get8(config_handle, PCI_CONF_MAX_L));
 456 }
 457 
 458 static void
 459 pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle)
 460 {
 461         if ((pcicfg_debug & 1) == 0)
 462                 return;
 463         pcicfg_dump_common_config(config_handle);
 464 
 465         prom_printf("........................................\n");
 466 
 467         prom_printf(" Pri Bus     = [0x%x]\n",
 468             pci_config_get8(config_handle, PCI_BCNF_PRIBUS));
 469         prom_printf(" Sec Bus     = [0x%x]\n",
 470             pci_config_get8(config_handle, PCI_BCNF_SECBUS));
 471         prom_printf(" Sub Bus     = [0x%x]\n",
 472             pci_config_get8(config_handle, PCI_BCNF_SUBBUS));
 473         prom_printf(" Latency     = [0x%x]\n",
 474             pci_config_get8(config_handle, PCI_BCNF_LATENCY_TIMER));
 475         prom_printf(" I/O Base LO = [0x%x]\n",
 476             pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW));
 477         prom_printf(" I/O Lim LO  = [0x%x]\n",
 478             pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW));
 479         prom_printf(" Sec. Status = [0x%x]\n",
 480             pci_config_get16(config_handle, PCI_BCNF_SEC_STATUS));
 481         prom_printf(" Mem Base    = [0x%x]\n",
 482             pci_config_get16(config_handle, PCI_BCNF_MEM_BASE));
 483         prom_printf(" Mem Limit   = [0x%x]\n",
 484             pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT));
 485         prom_printf(" PF Mem Base = [0x%x]\n",
 486             pci_config_get16(config_handle, PCI_BCNF_PF_BASE_LOW));
 487         prom_printf(" PF Mem Lim  = [0x%x]\n",
 488             pci_config_get16(config_handle, PCI_BCNF_PF_LIMIT_LOW));
 489         prom_printf(" PF Base HI  = [0x%x]\n",
 490             pci_config_get32(config_handle, PCI_BCNF_PF_BASE_HIGH));
 491         prom_printf(" PF Lim  HI  = [0x%x]\n",
 492             pci_config_get32(config_handle, PCI_BCNF_PF_LIMIT_HIGH));
 493         prom_printf(" I/O Base HI = [0x%x]\n",
 494             pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI));
 495         prom_printf(" I/O Lim HI  = [0x%x]\n",
 496             pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI));
 497         prom_printf(" ROM addr    = [0x%x]\n",
 498             pci_config_get32(config_handle, PCI_BCNF_ROM));
 499         prom_printf(" Intr Line   = [0x%x]\n",
 500             pci_config_get8(config_handle, PCI_BCNF_ILINE));
 501         prom_printf(" Intr Pin    = [0x%x]\n",
 502             pci_config_get8(config_handle, PCI_BCNF_IPIN));
 503         prom_printf(" Bridge Ctrl = [0x%x]\n",
 504             pci_config_get16(config_handle, PCI_BCNF_BCNTRL));
 505 }
 506 #endif
 507 
 508 int
 509 _init()
 510 {
 511         DEBUG0(" PCI configurator installed\n");
 512         mutex_init(&pcicfg_list_mutex, NULL, MUTEX_DRIVER, NULL);
 513         return (mod_install(&modlinkage));
 514 }
 515 
 516 int
 517 _fini(void)
 518 {
 519         int error;
 520 
 521         error = mod_remove(&modlinkage);
 522         if (error != 0) {
 523                 return (error);
 524         }
 525         mutex_destroy(&pcicfg_list_mutex);
 526         return (0);
 527 }
 528 
 529 int
 530 _info(struct modinfo *modinfop)
 531 {
 532         return (mod_info(&modlinkage, modinfop));
 533 }
 534 
 535 /*
 536  * In the following functions ndi_devi_enter() without holding the
 537  * parent dip is sufficient. This is because  pci dr is driven through
 538  * opens on the nexus which is in the device tree path above the node
 539  * being operated on, and implicitly held due to the open.
 540  */
 541 
 542 /*
 543  * This entry point is called to configure a device (and
 544  * all its children) on the given bus. It is called when
 545  * a new device is added to the PCI domain.  This routine
 546  * will create the device tree and program the devices
 547  * registers.
 548  */
 549 int
 550 pcicfg_configure(dev_info_t *devi, uint_t device, uint_t function,
 551     pcicfg_flags_t flags)
 552 {
 553         uint_t bus;
 554         int len;
 555         int func;
 556         dev_info_t *attach_point;
 557         pci_bus_range_t pci_bus_range;
 558         int rv;
 559         int circ;
 560         uint_t highest_bus;
 561         int ari_mode = B_FALSE;
 562         int max_function = PCI_MAX_FUNCTIONS;
 563         int trans_device;
 564         dev_info_t *new_device;
 565         boolean_t is_pcie;
 566 
 567         if (flags == PCICFG_FLAG_ENABLE_ARI)
 568                 return (pcicfg_ari_configure(devi));
 569 
 570         /*
 571          * Start probing at the device specified in "device" on the
 572          * "bus" specified.
 573          */
 574         len = sizeof (pci_bus_range_t);
 575         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, devi, 0, "bus-range",
 576             (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
 577                 DEBUG0("no bus-range property\n");
 578                 return (PCICFG_FAILURE);
 579         }
 580 
 581         bus = pci_bus_range.lo; /* primary bus number of this bus node */
 582 
 583         attach_point = devi;
 584 
 585         is_pcie = is_pcie_fabric(devi);
 586 
 587         ndi_devi_enter(devi, &circ);
 588         for (func = 0; func < max_function; ) {
 589 
 590                 if ((function != PCICFG_ALL_FUNC) && (function != func))
 591                         goto next;
 592 
 593                 if (ari_mode)
 594                         trans_device = func >> 3;
 595                 else
 596                         trans_device = device;
 597 
 598                 switch (rv = pcicfg_probe_children(attach_point,
 599                     bus, trans_device, func & 7, &highest_bus,
 600                     flags, is_pcie)) {
 601                         case PCICFG_NORESRC:
 602                         case PCICFG_FAILURE:
 603                                 DEBUG2("configure failed: bus [0x%x] device "
 604                                     "[0x%x]\n", bus, trans_device);
 605                                 goto cleanup;
 606                         case PCICFG_NODEVICE:
 607                                 DEBUG3("no device : bus "
 608                                     "[0x%x] slot [0x%x] func [0x%x]\n",
 609                                     bus, trans_device, func &7);
 610 
 611                                 /*
 612                                  * When walking the list of ARI functions
 613                                  * we don't expect to see a non-present
 614                                  * function, so we will stop walking
 615                                  * the function list.
 616                                  */
 617                                 if (ari_mode == B_TRUE)
 618                                         break;
 619 
 620                                 if (func)
 621                                         goto next;
 622                                 break;
 623                         default:
 624                                 DEBUG3("configure: bus => [%d] "
 625                                     "slot => [%d] func => [%d]\n",
 626                                     bus, trans_device, func & 7);
 627                         break;
 628                 }
 629 
 630                 if (rv != PCICFG_SUCCESS)
 631                         break;
 632 
 633                 if ((new_device = pcicfg_devi_find(attach_point,
 634                     trans_device, func & 7)) == NULL) {
 635                         DEBUG0("Did'nt find device node just created\n");
 636                         goto cleanup;
 637                 }
 638 
 639                 /*
 640                  * Up until now, we have detected a non transparent bridge
 641                  * (ntbridge) as a part of the generic probe code and
 642                  * configured only one configuration
 643                  * header which is the side facing the host bus.
 644                  * Now, configure the other side and create children.
 645                  *
 646                  * In order to make the process simpler, lets load the device
 647                  * driver for the non transparent bridge as this is a
 648                  * Solaris bundled driver, and use its configuration map
 649                  * services rather than programming it here.
 650                  * If the driver is not bundled into Solaris, it must be
 651                  * first loaded and configured before performing any
 652                  * hotplug operations.
 653                  *
 654                  * This not only makes the code here simpler but also more
 655                  * generic.
 656                  *
 657                  * So here we go.
 658                  */
 659 
 660                 /*
 661                  * check if this is a bridge in nontransparent mode
 662                  */
 663                 if (pcicfg_is_ntbridge(new_device) != DDI_FAILURE) {
 664                         DEBUG0("pcicfg: Found nontransparent bridge.\n");
 665 
 666                         rv = pcicfg_configure_ntbridge(new_device, bus,
 667                             trans_device);
 668                         if (rv != PCICFG_SUCCESS)
 669                                 goto cleanup;
 670                 }
 671 
 672 next:
 673                 /*
 674                  * Determine if ARI Forwarding should be enabled.
 675                  */
 676                 if (func == 0) {
 677                         if ((pcie_ari_supported(devi)
 678                             == PCIE_ARI_FORW_SUPPORTED) &&
 679                             (pcie_ari_device(new_device) == PCIE_ARI_DEVICE)) {
 680                                 if (pcie_ari_enable(devi) == DDI_SUCCESS) {
 681                                         (void) ddi_prop_create(DDI_DEV_T_NONE,
 682                                             devi,  DDI_PROP_CANSLEEP,
 683                                             "ari-enabled", NULL, 0);
 684 
 685                                         ari_mode = B_TRUE;
 686                                         max_function = PCICFG_MAX_ARI_FUNCTION;
 687                                 }
 688                         }
 689                 }
 690                 if (ari_mode == B_TRUE) {
 691                         int next_function;
 692 
 693                         DEBUG0("Next Function - ARI Device\n");
 694                         if (pcie_ari_get_next_function(new_device,
 695                             &next_function) != DDI_SUCCESS)
 696                                 goto cleanup;
 697 
 698                         /*
 699                          * Check if there are more fucntions to probe.
 700                          */
 701                         if (next_function == 0) {
 702                                 DEBUG0("Next Function - "
 703                                     "No more ARI Functions\n");
 704                                 break;
 705                         }
 706                         func = next_function;
 707                 } else {
 708                         func++;
 709                 }
 710                 DEBUG1("Next Function - %x\n", func);
 711         }
 712 
 713         ndi_devi_exit(devi, circ);
 714 
 715         if (func == 0)
 716                 return (PCICFG_FAILURE);        /* probe failed */
 717         else
 718                 return (PCICFG_SUCCESS);
 719 
 720 cleanup:
 721         /*
 722          * Clean up a partially created "probe state" tree.
 723          * There are no resources allocated to the in the
 724          * probe state.
 725          */
 726 
 727         for (func = 0; func < PCI_MAX_FUNCTIONS; func++) {
 728                 if ((function != PCICFG_ALL_FUNC) && (function != func))
 729                         continue;
 730 
 731                 if ((new_device = pcicfg_devi_find(devi, device, func))
 732                     == NULL) {
 733                         continue;
 734                 }
 735 
 736                 DEBUG2("Cleaning up device [0x%x] function [0x%x]\n",
 737                     device, func);
 738                 /*
 739                  * If this was a bridge device it will have a
 740                  * probe handle - if not, no harm in calling this.
 741                  */
 742                 (void) pcicfg_destroy_phdl(new_device);
 743                 if (is_pcie) {
 744                         /*
 745                          * free pcie_bus_t for the sub-tree
 746                          */
 747                         if (ddi_get_child(new_device) != NULL)
 748                                 pcie_fab_fini_bus(new_device, PCIE_BUS_ALL);
 749 
 750                         pcie_fini_bus(new_device, PCIE_BUS_ALL);
 751                 }
 752                 /*
 753                  * This will free up the node
 754                  */
 755                 (void) ndi_devi_offline(new_device, NDI_DEVI_REMOVE);
 756         }
 757         ndi_devi_exit(devi, circ);
 758 
 759         /*
 760          * Use private return codes to help identify issues without debugging
 761          * enabled.  Resource limitations and mis-configurations are
 762          * probably the most likely caue of configuration failures on x86.
 763          * Convert return code back to values expected by the external
 764          * consumer before returning so we will warn only once on the first
 765          * encountered failure.
 766          */
 767         if (rv == PCICFG_NORESRC) {
 768                 char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 769 
 770                 (void) ddi_pathname(devi, path);
 771                 cmn_err(CE_CONT, "?Not enough PCI resources to "
 772                     "configure: %s\n", path);
 773 
 774                 kmem_free(path, MAXPATHLEN);
 775                 rv = PCICFG_FAILURE;
 776         }
 777 
 778         return (rv);
 779 }
 780 
 781 /*
 782  * configure the child nodes of ntbridge. new_device points to ntbridge itself
 783  */
 784 /*ARGSUSED*/
 785 static int
 786 pcicfg_configure_ntbridge(dev_info_t *new_device, uint_t bus, uint_t device)
 787 {
 788         int bus_range[2], rc = PCICFG_FAILURE, rc1, max_devs = 0;
 789         int                     devno;
 790         dev_info_t              *new_ntbridgechild;
 791         ddi_acc_handle_t        config_handle;
 792         uint16_t                vid;
 793         uint64_t                next_bus;
 794         uint64_t                blen;
 795         ndi_ra_request_t        req;
 796         uint8_t                 pcie_device_type = 0;
 797 
 798         /*
 799          * If we need to do indirect config, lets create a property here
 800          * to let the child conf map routine know that it has to
 801          * go through the DDI calls, and not assume the devices are
 802          * mapped directly under the host.
 803          */
 804         if ((rc = ndi_prop_update_int(DDI_DEV_T_NONE, new_device,
 805             PCI_DEV_CONF_MAP_PROP, (int)DDI_SUCCESS)) != DDI_SUCCESS) {
 806                 DEBUG0("Cannot create indirect conf map property.\n");
 807                 return ((int)PCICFG_FAILURE);
 808         }
 809 
 810         if (pci_config_setup(new_device, &config_handle) != DDI_SUCCESS)
 811                 return (PCICFG_FAILURE);
 812         /* check if we are PCIe device */
 813         if (pcicfg_pcie_device_type(new_device, config_handle) == DDI_SUCCESS) {
 814                 DEBUG0("PCIe device detected\n");
 815                 pcie_device_type = 1;
 816         }
 817         pci_config_teardown(&config_handle);
 818         /* create Bus node properties for ntbridge. */
 819         if (pcicfg_set_busnode_props(new_device, pcie_device_type)
 820             != PCICFG_SUCCESS) {
 821                 DEBUG0("Failed to set busnode props\n");
 822                 return (rc);
 823         }
 824 
 825         /* For now: Lets only support one layer of child */
 826         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
 827         req.ra_len = 1;
 828         if (ndi_ra_alloc(ddi_get_parent(new_device), &req, &next_bus, &blen,
 829             NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
 830                 DEBUG0("ntbridge: Failed to get a bus number\n");
 831                 return (PCICFG_NORESRC);
 832         }
 833 
 834         DEBUG1("ntbridge bus range start  ->[%d]\n", next_bus);
 835 
 836         /*
 837          * Following will change, as we detect more bridges
 838          * on the way.
 839          */
 840         bus_range[0] = (int)next_bus;
 841         bus_range[1] = (int)next_bus;
 842 
 843         if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_device, "bus-range",
 844             bus_range, 2) != DDI_SUCCESS) {
 845                 DEBUG0("Cannot set ntbridge bus-range property");
 846                 return (rc);
 847         }
 848 
 849         /*
 850          * The other interface (away from the host) will be
 851          * initialized by the nexus driver when it loads.
 852          * We just have to set the registers and the nexus driver
 853          * figures out the rest.
 854          */
 855 
 856         /*
 857          * finally, lets load and attach the driver
 858          * before configuring children of ntbridge.
 859          */
 860         rc = ndi_devi_online(new_device, NDI_ONLINE_ATTACH|NDI_CONFIG);
 861         if (rc != NDI_SUCCESS) {
 862                 cmn_err(CE_WARN,
 863                 "pcicfg: Fail:cant load nontransparent bridgd driver..\n");
 864                 rc = PCICFG_FAILURE;
 865                 return (rc);
 866         }
 867         DEBUG0("pcicfg: Success loading nontransparent bridge nexus driver..");
 868 
 869         /* Now set aside pci resource allocation requests for our children */
 870         if (pcicfg_ntbridge_allocate_resources(new_device) != PCICFG_SUCCESS) {
 871                 max_devs = 0;
 872                 rc = PCICFG_FAILURE;
 873         } else
 874                 max_devs = PCI_MAX_DEVICES;
 875 
 876         /* Probe devices on 2nd bus */
 877         rc = PCICFG_SUCCESS;
 878         for (devno = pcicfg_start_devno; devno < max_devs; devno++) {
 879 
 880                 ndi_devi_alloc_sleep(new_device, DEVI_PSEUDO_NEXNAME,
 881                     (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild);
 882 
 883                 if (pcicfg_add_config_reg(new_ntbridgechild, next_bus, devno, 0)
 884                     != DDI_PROP_SUCCESS) {
 885                         cmn_err(CE_WARN,
 886                             "Failed to add conf reg for ntbridge child.\n");
 887                         (void) ndi_devi_free(new_ntbridgechild);
 888                         rc = PCICFG_FAILURE;
 889                         break;
 890                 }
 891 
 892                 if (pci_config_setup(new_ntbridgechild, &config_handle)
 893                     != DDI_SUCCESS) {
 894                         cmn_err(CE_WARN,
 895                             "Cannot map ntbridge child %x\n", devno);
 896                         (void) ndi_devi_free(new_ntbridgechild);
 897                         rc = PCICFG_FAILURE;
 898                         break;
 899                 }
 900 
 901                 /*
 902                  * See if there is any PCI HW at this location
 903                  * by reading the Vendor ID.  If it returns with 0xffff
 904                  * then there is no hardware at this location.
 905                  */
 906                 vid = pci_config_get16(config_handle, PCI_CONF_VENID);
 907 
 908                 pci_config_teardown(&config_handle);
 909                 (void) ndi_devi_free(new_ntbridgechild);
 910                 if (vid == 0xffff)
 911                         continue;
 912 
 913                 /* Lets fake attachments points for each child, */
 914                 rc = pcicfg_configure(new_device, devno, PCICFG_ALL_FUNC, 0);
 915                 if (rc != PCICFG_SUCCESS) {
 916                         int old_dev = pcicfg_start_devno;
 917 
 918                         cmn_err(CE_WARN,
 919                             "Error configuring ntbridge child dev=%d\n", devno);
 920 
 921                         while (old_dev != devno) {
 922                                 if (pcicfg_ntbridge_unconfigure_child(
 923                                     new_device, old_dev) == PCICFG_FAILURE)
 924                                         cmn_err(CE_WARN, "Unconfig Error "
 925                                             "ntbridge child dev=%d\n", old_dev);
 926                                 old_dev++;
 927                         }
 928                         break;
 929                 }
 930         } /* devno loop */
 931         DEBUG1("ntbridge: finish probing 2nd bus, rc=%d\n", rc);
 932 
 933         if (rc == PCICFG_SUCCESS)
 934                 rc = pcicfg_ntbridge_configure_done(new_device);
 935         else {
 936                 pcicfg_phdl_t *entry = pcicfg_find_phdl(new_device);
 937                 uint_t                  *bus;
 938                 int                     k;
 939 
 940                 if (ddi_getlongprop(DDI_DEV_T_ANY, new_device,
 941                     DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus, &k)
 942                     != DDI_PROP_SUCCESS) {
 943                         DEBUG0("Failed to read bus-range property\n");
 944                         rc = PCICFG_FAILURE;
 945                         return (rc);
 946                 }
 947 
 948                 DEBUG2("Need to free bus [%d] range [%d]\n",
 949                     bus[0], bus[1] - bus[0] + 1);
 950 
 951                 if (ndi_ra_free(ddi_get_parent(new_device), (uint64_t)bus[0],
 952                     (uint64_t)(bus[1] - bus[0] + 1), NDI_RA_TYPE_PCI_BUSNUM,
 953                     NDI_RA_PASS) != NDI_SUCCESS) {
 954                         DEBUG0("Failed to free a bus number\n");
 955                         rc = PCICFG_FAILURE;
 956                         kmem_free(bus, k);
 957                         return (rc);
 958                 }
 959 
 960                 /*
 961                  * Since no memory allocations are done for non transparent
 962                  * bridges (but instead we just set the handle with the
 963                  * already allocated memory, we just need to reset the
 964                  * following values before calling the destroy_phdl()
 965                  * function next, otherwise the it will try to free
 966                  * memory allocated as in case of a transparent bridge.
 967                  */
 968                 entry->memory_len = 0;
 969                 entry->pf_memory_len = 0;
 970                 entry->io_len = 0;
 971                 kmem_free(bus, k);
 972                 /* the following will free hole data. */
 973                 (void) pcicfg_destroy_phdl(new_device);
 974         }
 975 
 976         /*
 977          * Unload driver just in case child configure failed!
 978          */
 979         rc1 = ndi_devi_offline(new_device, 0);
 980         DEBUG1("pcicfg: now unloading the ntbridge driver. rc1=%d\n", rc1);
 981         if (rc1 != NDI_SUCCESS) {
 982                 cmn_err(CE_WARN,
 983                 "pcicfg: cant unload ntbridge driver..children.\n");
 984                 rc = PCICFG_FAILURE;
 985         }
 986 
 987         return (rc);
 988 }
 989 
 990 static int
 991 pcicfg_ntbridge_allocate_resources(dev_info_t *dip)
 992 {
 993         pcicfg_phdl_t           *phdl;
 994         ndi_ra_request_t        *mem_request;
 995         ndi_ra_request_t        *pf_mem_request;
 996         ndi_ra_request_t        *io_request;
 997         uint64_t                boundbase, boundlen;
 998 
 999         phdl = pcicfg_find_phdl(dip);
1000         ASSERT(phdl);
1001 
1002         mem_request = &phdl->mem_req;
1003         pf_mem_request = &phdl->pf_mem_req;
1004         io_request  = &phdl->io_req;
1005 
1006         phdl->error = PCICFG_SUCCESS;
1007 
1008         /* Set Memory space handle for ntbridge */
1009         if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1010             PCI_BASE_SPACE_MEM) != DDI_SUCCESS) {
1011                 cmn_err(CE_WARN,
1012                     "ntbridge: Mem resource information failure\n");
1013                 phdl->memory_len  = 0;
1014                 return (PCICFG_FAILURE);
1015         }
1016         mem_request->ra_boundbase = boundbase;
1017         mem_request->ra_boundlen = boundbase + boundlen;
1018         mem_request->ra_len = boundlen;
1019         mem_request->ra_align_mask =
1020             PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
1021         mem_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1022 
1023         /*
1024          * mem_request->ra_len =
1025          * PCICFG_ROUND_UP(mem_request->ra_len, PCICFG_MEMGRAN);
1026          */
1027 
1028         phdl->memory_base = phdl->memory_last = boundbase;
1029         phdl->memory_len  = boundlen;
1030         phdl->mem_hole.start = phdl->memory_base;
1031         phdl->mem_hole.len = mem_request->ra_len;
1032         phdl->mem_hole.next = (hole_t *)NULL;
1033 
1034         DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of memory\n",
1035             boundlen, mem_request->ra_len);
1036 
1037         /* Set IO space handle for ntbridge */
1038         if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1039             PCI_BASE_SPACE_IO) != DDI_SUCCESS) {
1040                 cmn_err(CE_WARN, "ntbridge: IO resource information failure\n");
1041                 phdl->io_len  = 0;
1042                 return (PCICFG_FAILURE);
1043         }
1044         io_request->ra_len = boundlen;
1045         io_request->ra_align_mask =
1046             PCICFG_IOGRAN - 1;   /* 4K alignment on I/O space */
1047         io_request->ra_boundbase = boundbase;
1048         io_request->ra_boundlen = boundbase + boundlen;
1049         io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1050 
1051         /*
1052          * io_request->ra_len =
1053          * PCICFG_ROUND_UP(io_request->ra_len, PCICFG_IOGRAN);
1054          */
1055 
1056         phdl->io_base = phdl->io_last = (uint32_t)boundbase;
1057         phdl->io_len  = (uint32_t)boundlen;
1058         phdl->io_hole.start = phdl->io_base;
1059         phdl->io_hole.len = io_request->ra_len;
1060         phdl->io_hole.next = (hole_t *)NULL;
1061 
1062         DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of IO\n",
1063             boundlen, io_request->ra_len);
1064 
1065         /* Set Prefetchable Memory space handle for ntbridge */
1066         if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1067             PCI_BASE_SPACE_MEM | PCI_BASE_PREF_M) != DDI_SUCCESS) {
1068                 cmn_err(CE_WARN,
1069                     "ntbridge: PF Mem resource information failure\n");
1070                 phdl->pf_memory_len  = 0;
1071                 return (PCICFG_FAILURE);
1072         }
1073         pf_mem_request->ra_boundbase = boundbase;
1074         pf_mem_request->ra_boundlen = boundbase + boundlen;
1075         pf_mem_request->ra_len = boundlen;
1076         pf_mem_request->ra_align_mask =
1077             PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
1078         pf_mem_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1079 
1080         /*
1081          * pf_mem_request->ra_len =
1082          * PCICFG_ROUND_UP(pf_mem_request->ra_len, PCICFG_MEMGRAN);
1083          */
1084 
1085         phdl->pf_memory_base = phdl->pf_memory_last = boundbase;
1086         phdl->pf_memory_len  = boundlen;
1087         phdl->pf_mem_hole.start = phdl->pf_memory_base;
1088         phdl->pf_mem_hole.len = pf_mem_request->ra_len;
1089         phdl->pf_mem_hole.next = (hole_t *)NULL;
1090 
1091         DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of PF "
1092             "memory\n", boundlen, pf_mem_request->ra_len);
1093 
1094         DEBUG2("MEMORY BASE = [0x%lx] length [0x%lx]\n",
1095             phdl->memory_base, phdl->memory_len);
1096         DEBUG2("IO     BASE = [0x%x] length [0x%x]\n",
1097             phdl->io_base, phdl->io_len);
1098         DEBUG2("PF MEMORY BASE = [0x%lx] length [0x%lx]\n",
1099             phdl->pf_memory_base, phdl->pf_memory_len);
1100 
1101         return (PCICFG_SUCCESS);
1102 }
1103 
1104 static int
1105 pcicfg_ntbridge_configure_done(dev_info_t *dip)
1106 {
1107         ppb_ranges_t range[PCICFG_RANGE_LEN];
1108         pcicfg_phdl_t           *entry;
1109         uint_t                  len;
1110         pci_bus_range_t         bus_range;
1111         int                     new_bus_range[2];
1112 
1113         DEBUG1("Configuring children for %p\n", dip);
1114 
1115         entry = pcicfg_find_phdl(dip);
1116         ASSERT(entry);
1117 
1118         bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
1119         range[1].child_high = range[1].parent_high |=
1120             (PCI_REG_REL_M | PCI_ADDR_MEM32);
1121         range[1].child_low = range[1].parent_low = (uint32_t)entry->memory_base;
1122 
1123         range[0].child_high = range[0].parent_high |=
1124             (PCI_REG_REL_M | PCI_ADDR_IO);
1125         range[0].child_low = range[0].parent_low = (uint32_t)entry->io_base;
1126 
1127         range[2].child_high = range[2].parent_high |=
1128             (PCI_REG_REL_M | PCI_ADDR_MEM32 | PCI_REG_PF_M);
1129         range[2].child_low = range[2].parent_low =
1130             (uint32_t)entry->pf_memory_base;
1131 
1132         len = sizeof (pci_bus_range_t);
1133         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1134             "bus-range", (caddr_t)&bus_range, (int *)&len) != DDI_SUCCESS) {
1135                 DEBUG0("no bus-range property\n");
1136                 return (PCICFG_FAILURE);
1137         }
1138 
1139         new_bus_range[0] = bus_range.lo;        /* primary bus number */
1140         if (entry->highest_bus) {    /* secondary bus number */
1141                 if (entry->highest_bus < bus_range.lo) {
1142                         cmn_err(CE_WARN,
1143                             "ntbridge bus range invalid !(%d,%d)\n",
1144                             bus_range.lo, entry->highest_bus);
1145                         new_bus_range[1] = bus_range.lo + entry->highest_bus;
1146                 }
1147                 else
1148                         new_bus_range[1] = entry->highest_bus;
1149         }
1150         else
1151                 new_bus_range[1] = bus_range.hi;
1152 
1153         DEBUG2("ntbridge: bus range lo=%x, hi=%x\n", new_bus_range[0],
1154             new_bus_range[1]);
1155 
1156         if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "bus-range",
1157             new_bus_range, 2) != DDI_SUCCESS) {
1158                 DEBUG0("Failed to set bus-range property");
1159                 entry->error = PCICFG_FAILURE;
1160                 return (PCICFG_FAILURE);
1161         }
1162 
1163 #ifdef DEBUG
1164         {
1165                 uint64_t        unused;
1166                 unused = pcicfg_unused_space(&entry->io_hole, &len);
1167                 DEBUG2("ntbridge: Unused IO space %llx bytes over %d holes\n",
1168                     unused, len);
1169         }
1170 #endif
1171 
1172         range[0].size_low = entry->io_len;
1173         if (pcicfg_update_ranges_prop(dip, &range[0])) {
1174                 DEBUG0("Failed to update ranges (i/o)\n");
1175                 entry->error = PCICFG_FAILURE;
1176                 return (PCICFG_FAILURE);
1177         }
1178 
1179 #ifdef DEBUG
1180         {
1181                 uint64_t        unused;
1182                 unused = pcicfg_unused_space(&entry->mem_hole, &len);
1183                 DEBUG2("ntbridge: Unused Mem space %llx bytes over %d holes\n",
1184                     unused, len);
1185         }
1186 #endif
1187 
1188         range[1].size_low = entry->memory_len;
1189         if (pcicfg_update_ranges_prop(dip, &range[1])) {
1190                 DEBUG0("Failed to update ranges (memory)\n");
1191                 entry->error = PCICFG_FAILURE;
1192                 return (PCICFG_FAILURE);
1193         }
1194 
1195 #ifdef DEBUG
1196         {
1197                 uint64_t        unused;
1198                 unused = pcicfg_unused_space(&entry->pf_mem_hole, &len);
1199                 DEBUG2("ntbridge: Unused PF Mem space %llx bytes over"
1200                     " %d holes\n", unused, len);
1201         }
1202 #endif
1203 
1204         range[2].size_low = entry->pf_memory_len;
1205         if (pcicfg_update_ranges_prop(dip, &range[2])) {
1206                 DEBUG0("Failed to update ranges (PF memory)\n");
1207                 entry->error = PCICFG_FAILURE;
1208                 return (PCICFG_FAILURE);
1209         }
1210 
1211         return (PCICFG_SUCCESS);
1212 }
1213 
1214 static int
1215 pcicfg_ntbridge_program_child(dev_info_t *dip)
1216 {
1217         pcicfg_phdl_t   *entry;
1218         int             rc = PCICFG_SUCCESS;
1219         dev_info_t      *anode = dip;
1220 
1221         /* Find the Hotplug Connection (CN) node */
1222         while ((anode != NULL) &&
1223             (strcmp(ddi_binding_name(anode), "hp_attachment") != 0)) {
1224                 anode = ddi_get_parent(anode);
1225         }
1226 
1227         if (anode == NULL) {
1228                 DEBUG0("ntbridge child tree not in PROBE state\n");
1229                 return (PCICFG_FAILURE);
1230         }
1231         entry = pcicfg_find_phdl(ddi_get_parent(anode));
1232         ASSERT(entry);
1233 
1234         if (pcicfg_bridge_assign(dip, entry) == DDI_WALK_TERMINATE) {
1235                 cmn_err(CE_WARN,
1236                     "ntbridge: Error assigning range for child %s\n",
1237                     ddi_get_name(dip));
1238                 rc = PCICFG_FAILURE;
1239         }
1240         return (rc);
1241 }
1242 
1243 static int
1244 pcicfg_ntbridge_unconfigure_child(dev_info_t *new_device, uint_t devno)
1245 {
1246 
1247         dev_info_t      *new_ntbridgechild;
1248         int             len, bus;
1249         uint16_t        vid;
1250         ddi_acc_handle_t        config_handle;
1251         pci_bus_range_t pci_bus_range;
1252 
1253         len = sizeof (pci_bus_range_t);
1254         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, new_device, DDI_PROP_DONTPASS,
1255             "bus-range", (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
1256                 DEBUG0("no bus-range property\n");
1257                 return (PCICFG_FAILURE);
1258         }
1259 
1260         bus = pci_bus_range.lo; /* primary bus number of this bus node */
1261 
1262         ndi_devi_alloc_sleep(new_device, DEVI_PSEUDO_NEXNAME,
1263             (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild);
1264 
1265         if (pcicfg_add_config_reg(new_ntbridgechild, bus, devno, 0)
1266             != DDI_PROP_SUCCESS) {
1267                 cmn_err(CE_WARN, "Unconfigure: Failed to add conf reg prop for "
1268                     "ntbridge child.\n");
1269                 (void) ndi_devi_free(new_ntbridgechild);
1270                 return (PCICFG_FAILURE);
1271         }
1272 
1273         if (pci_config_setup(new_ntbridgechild, &config_handle)
1274             != DDI_SUCCESS) {
1275                 cmn_err(CE_WARN, "pcicfg: Cannot map ntbridge child %x\n",
1276                     devno);
1277                 (void) ndi_devi_free(new_ntbridgechild);
1278                 return (PCICFG_FAILURE);
1279         }
1280 
1281         /*
1282          * See if there is any PCI HW at this location
1283          * by reading the Vendor ID.  If it returns with 0xffff
1284          * then there is no hardware at this location.
1285          */
1286         vid = pci_config_get16(config_handle, PCI_CONF_VENID);
1287 
1288         pci_config_teardown(&config_handle);
1289         (void) ndi_devi_free(new_ntbridgechild);
1290         if (vid == 0xffff)
1291                 return (PCICFG_NODEVICE);
1292 
1293         return (pcicfg_unconfigure(new_device, devno, PCICFG_ALL_FUNC, 0));
1294 }
1295 
1296 static uint_t
1297 pcicfg_ntbridge_unconfigure(dev_info_t *dip)
1298 {
1299         pcicfg_phdl_t *entry = pcicfg_find_phdl(dip);
1300         uint_t                  *bus;
1301         int                     k, rc = DDI_FAILURE;
1302 
1303         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "bus-range",
1304             (caddr_t)&bus, &k) != DDI_PROP_SUCCESS) {
1305                 DEBUG0("ntbridge: Failed to read bus-range property\n");
1306                 return (rc);
1307         }
1308 
1309         DEBUG2("ntbridge: Need to free bus [%d] range [%d]\n",
1310             bus[0], bus[1] - bus[0] + 1);
1311 
1312         if (ndi_ra_free(ddi_get_parent(dip), (uint64_t)bus[0],
1313             (uint64_t)(bus[1] - bus[0] + 1),
1314             NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
1315                 DEBUG0("ntbridge: Failed to free a bus number\n");
1316                 kmem_free(bus, k);
1317                 return (rc);
1318         }
1319 
1320         /*
1321          * Since our resources will be freed at the parent level,
1322          * just reset these values.
1323          */
1324         entry->memory_len = 0;
1325         entry->io_len = 0;
1326         entry->pf_memory_len = 0;
1327 
1328         kmem_free(bus, k);
1329 
1330         /* the following will also free hole data. */
1331         return (pcicfg_destroy_phdl(dip));
1332 
1333 }
1334 
1335 static int
1336 pcicfg_is_ntbridge(dev_info_t *dip)
1337 {
1338         ddi_acc_handle_t        config_handle;
1339         uint8_t         class, subclass;
1340         int             rc = DDI_SUCCESS;
1341 
1342         if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
1343                 cmn_err(CE_WARN,
1344                     "pcicfg: cannot map config space, to get map type\n");
1345                 return (DDI_FAILURE);
1346         }
1347         class = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
1348         subclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
1349 
1350         /* check for class=6, subclass=9, for non transparent bridges.  */
1351         if ((class != PCI_CLASS_BRIDGE) || (subclass != PCI_BRIDGE_STBRIDGE))
1352                 rc = DDI_FAILURE;
1353 
1354         DEBUG3("pcicfg: checking device %x,%x for indirect map. rc=%d\n",
1355             pci_config_get16(config_handle, PCI_CONF_VENID),
1356             pci_config_get16(config_handle, PCI_CONF_DEVID),
1357             rc);
1358         pci_config_teardown(&config_handle);
1359         return (rc);
1360 }
1361 
1362 static uint_t
1363 pcicfg_ntbridge_child(dev_info_t *dip)
1364 {
1365         int             len, val, rc = DDI_FAILURE;
1366         dev_info_t      *anode = dip;
1367 
1368         /*
1369          * Find the Hotplug Connection (CN) node
1370          */
1371         while ((anode != NULL) && (strcmp(ddi_binding_name(anode),
1372             "hp_attachment") != 0)) {
1373                 anode = ddi_get_parent(anode);
1374         }
1375 
1376         if (anode == NULL) {
1377                 DEBUG0("ntbridge child tree not in PROBE state\n");
1378                 return (rc);
1379         }
1380         len = sizeof (int);
1381         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(anode),
1382             DDI_PROP_DONTPASS, PCI_DEV_CONF_MAP_PROP, (caddr_t)&val, &len)
1383             != DDI_SUCCESS) {
1384 
1385                 DEBUG1("ntbridge child: no \"%s\" property\n",
1386                     PCI_DEV_CONF_MAP_PROP);
1387                 return (rc);
1388         }
1389         DEBUG0("ntbridge child: success\n");
1390         return (DDI_SUCCESS);
1391 }
1392 
1393 static uint_t
1394 pcicfg_get_ntbridge_child_range(dev_info_t *dip, uint64_t *boundbase,
1395                                 uint64_t *boundlen, uint_t space_type)
1396 {
1397         int             length, found = DDI_FAILURE, acount, i, ibridge;
1398         pci_regspec_t   *assigned;
1399 
1400         if ((ibridge = pcicfg_is_ntbridge(dip)) == DDI_FAILURE)
1401                 return (found);
1402 
1403         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1404             "assigned-addresses", (caddr_t)&assigned, &length)
1405             != DDI_PROP_SUCCESS) {
1406                 DEBUG1("Failed to get assigned-addresses property %llx\n", dip);
1407                 return (found);
1408         }
1409         DEBUG1("pcicfg: ntbridge child range: dip = %s\n",
1410             ddi_driver_name(dip));
1411 
1412         acount = length / sizeof (pci_regspec_t);
1413 
1414         for (i = 0; i < acount; i++) {
1415                 if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1416                     pcicfg_indirect_map_devs[ibridge].mem_range_bar_offset) &&
1417                     (space_type == PCI_BASE_SPACE_MEM)) {
1418                         found = DDI_SUCCESS;
1419                         break;
1420                 } else if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1421                     pcicfg_indirect_map_devs[ibridge].io_range_bar_offset) &&
1422                     (space_type == PCI_BASE_SPACE_IO)) {
1423                         found = DDI_SUCCESS;
1424                         break;
1425                 } else if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1426                     pcicfg_indirect_map_devs[ibridge].
1427                     prefetch_mem_range_bar_offset) &&
1428                     (space_type == (PCI_BASE_SPACE_MEM |
1429                     PCI_BASE_PREF_M))) {
1430                         found = DDI_SUCCESS;
1431                         break;
1432                 }
1433         }
1434         DEBUG3("pcicfg: ntbridge child range: space=%x, base=%lx, len=%lx\n",
1435             space_type, assigned[i].pci_phys_low, assigned[i].pci_size_low);
1436 
1437         if (found == DDI_SUCCESS)  {
1438                 *boundbase = assigned[i].pci_phys_low;
1439                 *boundlen = assigned[i].pci_size_low;
1440         }
1441 
1442         kmem_free(assigned, length);
1443         return (found);
1444 }
1445 
1446 /*
1447  * This will turn  resources allocated by pcicfg_configure()
1448  * and remove the device tree from the Hotplug Connection (CN)
1449  * and below.  The routine assumes the devices have their
1450  * drivers detached.
1451  */
1452 int
1453 pcicfg_unconfigure(dev_info_t *devi, uint_t device, uint_t function,
1454     pcicfg_flags_t flags)
1455 {
1456         dev_info_t *child_dip;
1457         int func;
1458         int i;
1459         int max_function, trans_device;
1460         int circ;
1461         boolean_t is_pcie;
1462 
1463         if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED)
1464                 max_function = PCICFG_MAX_ARI_FUNCTION;
1465         else
1466                 max_function = PCI_MAX_FUNCTIONS;
1467 
1468         /*
1469          * Cycle through devices to make sure none are busy.
1470          * If a single device is busy fail the whole unconfigure.
1471          */
1472         is_pcie = is_pcie_fabric(devi);
1473 
1474         ndi_devi_enter(devi, &circ);
1475         for (func = 0; func < max_function; func++) {
1476                 if ((function != PCICFG_ALL_FUNC) && (function != func))
1477                         continue;
1478 
1479                 if (max_function == PCICFG_MAX_ARI_FUNCTION)
1480                         trans_device = func >> 3; /* ARI Device */
1481                 else
1482                         trans_device = device;
1483 
1484                 if ((child_dip = pcicfg_devi_find(devi, trans_device,
1485                     func & 7)) == NULL)
1486                         continue;
1487 
1488                 if (ndi_devi_offline(child_dip, NDI_UNCONFIG) == NDI_SUCCESS)
1489                         continue;
1490 
1491                 /*
1492                  * Device function is busy. Before returning we have to
1493                  * put all functions back online which were taken
1494                  * offline during the process.
1495                  */
1496                 DEBUG2("Device [0x%x] function [0x%x] is busy\n",
1497                     trans_device, func & 7);
1498                 /*
1499                  * If we are only asked to offline one specific function,
1500                  * and that fails, we just simply return.
1501                  */
1502                 if (function != PCICFG_ALL_FUNC)
1503                         return (PCICFG_FAILURE);
1504 
1505                 for (i = 0; i < func; i++) {
1506                         if (max_function == PCICFG_MAX_ARI_FUNCTION)
1507                                 trans_device = i >> 3;
1508 
1509                         if ((child_dip = pcicfg_devi_find(devi, trans_device,
1510                             i & 7)) == NULL) {
1511                                 DEBUG0("No more devices to put back "
1512                                     "on line!!\n");
1513                                 /*
1514                                  * Made it through all functions
1515                                  */
1516                                 continue;
1517                         }
1518                         if (ndi_devi_online(child_dip, NDI_CONFIG)
1519                             != NDI_SUCCESS) {
1520                                 DEBUG0("Failed to put back devices state\n");
1521                                 goto fail;
1522                         }
1523                 }
1524                 goto fail;
1525         }
1526 
1527         /*
1528          * Now, tear down all devinfo nodes for this Connector.
1529          */
1530         for (func = 0; func < max_function; func++) {
1531                 if ((function != PCICFG_ALL_FUNC) && (function != func))
1532                         continue;
1533 
1534                 if (max_function == PCICFG_MAX_ARI_FUNCTION)
1535                         trans_device = func >> 3; /* ARI Device */
1536                 else
1537                         trans_device = device;
1538 
1539                 if ((child_dip = pcicfg_devi_find(devi, trans_device, func & 7))
1540                     == NULL) {
1541                         DEBUG2("No device at %x,%x\n", trans_device, func & 7);
1542                         continue;
1543                 }
1544 
1545                 DEBUG2("Tearing down device [0x%x] function [0x%x]\n",
1546                     trans_device, func & 7);
1547 
1548                 if (pcicfg_is_ntbridge(child_dip) != DDI_FAILURE)
1549                         if (pcicfg_ntbridge_unconfigure(child_dip) !=
1550                             PCICFG_SUCCESS) {
1551                                 cmn_err(CE_WARN,
1552                                     "ntbridge: unconfigure failed\n");
1553                                 goto fail;
1554                         }
1555 
1556                 if (pcicfg_teardown_device(child_dip, flags, is_pcie)
1557                     != PCICFG_SUCCESS) {
1558                         DEBUG2("Failed to tear down device [0x%x]"
1559                             "function [0x%x]\n", trans_device, func & 7);
1560                         goto fail;
1561                 }
1562         }
1563 
1564         if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED) {
1565                 (void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "ari-enabled");
1566                 (void) pcie_ari_disable(devi);
1567         }
1568 
1569         ndi_devi_exit(devi, circ);
1570         return (PCICFG_SUCCESS);
1571 
1572 fail:
1573         ndi_devi_exit(devi, circ);
1574         return (PCICFG_FAILURE);
1575 }
1576 
1577 static int
1578 pcicfg_teardown_device(dev_info_t *dip, pcicfg_flags_t flags, boolean_t is_pcie)
1579 {
1580         ddi_acc_handle_t        handle;
1581 
1582         /*
1583          * Free up resources associated with 'dip'
1584          */
1585         if (pcicfg_free_resources(dip, flags) != PCICFG_SUCCESS) {
1586                 DEBUG0("Failed to free resources\n");
1587                 return (PCICFG_FAILURE);
1588         }
1589 
1590         /*
1591          * disable the device
1592          */
1593         if (pcicfg_config_setup(dip, &handle) != PCICFG_SUCCESS)
1594                 return (PCICFG_FAILURE);
1595         pcicfg_device_off(handle);
1596         pcicfg_config_teardown(&handle);
1597 
1598         if (is_pcie) {
1599                 /*
1600                  * free pcie_bus_t for the sub-tree
1601                  */
1602                 if (ddi_get_child(dip) != NULL)
1603                         pcie_fab_fini_bus(dip, PCIE_BUS_ALL);
1604 
1605                 pcie_fini_bus(dip, PCIE_BUS_ALL);
1606         }
1607 
1608         /*
1609          * The framework provides this routine which can
1610          * tear down a sub-tree.
1611          */
1612         if (ndi_devi_offline(dip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
1613                 DEBUG0("Failed to offline and remove node\n");
1614                 return (PCICFG_FAILURE);
1615         }
1616 
1617         return (PCICFG_SUCCESS);
1618 }
1619 
1620 /*
1621  * BEGIN GENERIC SUPPORT ROUTINES
1622  */
1623 static pcicfg_phdl_t *
1624 pcicfg_find_phdl(dev_info_t *dip)
1625 {
1626         pcicfg_phdl_t *entry;
1627         mutex_enter(&pcicfg_list_mutex);
1628         for (entry = pcicfg_phdl_list; entry != NULL; entry = entry->next) {
1629                 if (entry->dip == dip) {
1630                         mutex_exit(&pcicfg_list_mutex);
1631                         return (entry);
1632                 }
1633         }
1634         mutex_exit(&pcicfg_list_mutex);
1635 
1636         /*
1637          * Did'nt find entry - create one
1638          */
1639         return (pcicfg_create_phdl(dip));
1640 }
1641 
1642 static pcicfg_phdl_t *
1643 pcicfg_create_phdl(dev_info_t *dip)
1644 {
1645         pcicfg_phdl_t *new;
1646 
1647         new = (pcicfg_phdl_t *)kmem_zalloc(sizeof (pcicfg_phdl_t), KM_SLEEP);
1648 
1649         new->dip = dip;
1650         mutex_enter(&pcicfg_list_mutex);
1651         new->next = pcicfg_phdl_list;
1652         pcicfg_phdl_list = new;
1653         mutex_exit(&pcicfg_list_mutex);
1654 
1655         return (new);
1656 }
1657 
1658 static int
1659 pcicfg_destroy_phdl(dev_info_t *dip)
1660 {
1661         pcicfg_phdl_t *entry;
1662         pcicfg_phdl_t *follow = NULL;
1663 
1664         mutex_enter(&pcicfg_list_mutex);
1665         for (entry = pcicfg_phdl_list; entry != NULL; follow = entry,
1666             entry = entry->next) {
1667                 if (entry->dip == dip) {
1668                         if (entry == pcicfg_phdl_list) {
1669                                 pcicfg_phdl_list = entry->next;
1670                         } else {
1671                                 follow->next = entry->next;
1672                         }
1673                         /*
1674                          * If this entry has any allocated memory
1675                          * or IO space associated with it, that
1676                          * must be freed up.
1677                          */
1678                         if (entry->memory_len > 0) {
1679                                 (void) ndi_ra_free(ddi_get_parent(dip),
1680                                     entry->memory_base, entry->memory_len,
1681                                     NDI_RA_TYPE_MEM, NDI_RA_PASS);
1682                         }
1683                         pcicfg_free_hole(&entry->mem_hole);
1684 
1685                         if (entry->io_len > 0) {
1686                                 (void) ndi_ra_free(ddi_get_parent(dip),
1687                                     entry->io_base, entry->io_len,
1688                                     NDI_RA_TYPE_IO, NDI_RA_PASS);
1689                         }
1690                         pcicfg_free_hole(&entry->io_hole);
1691 
1692                         if (entry->pf_memory_len > 0) {
1693                                 (void) ndi_ra_free(ddi_get_parent(dip),
1694                                     entry->pf_memory_base, entry->pf_memory_len,
1695                                     NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
1696                         }
1697                         pcicfg_free_hole(&entry->pf_mem_hole);
1698 
1699                         /*
1700                          * Destroy this entry
1701                          */
1702                         kmem_free((caddr_t)entry, sizeof (pcicfg_phdl_t));
1703                         mutex_exit(&pcicfg_list_mutex);
1704                         return (PCICFG_SUCCESS);
1705                 }
1706         }
1707         mutex_exit(&pcicfg_list_mutex);
1708         /*
1709          * Did'nt find the entry
1710          */
1711         return (PCICFG_FAILURE);
1712 }
1713 
1714 static int
1715 pcicfg_bridge_assign(dev_info_t *dip, void *hdl)
1716 {
1717         ddi_acc_handle_t handle;
1718         pci_regspec_t *reg;
1719         int length;
1720         int rcount;
1721         int i;
1722         int offset;
1723         uint64_t mem_answer;
1724         uint32_t io_answer;
1725         int count;
1726         uint8_t header_type;
1727         ppb_ranges_t range[PCICFG_RANGE_LEN];
1728         int bus_range[2];
1729         uint64_t mem_residual;
1730         uint64_t pf_mem_residual;
1731         uint64_t io_residual;
1732 
1733         pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
1734 
1735         DEBUG1("bridge assign: assigning addresses to %s\n", ddi_get_name(dip));
1736 
1737         entry->error = PCICFG_SUCCESS;
1738 
1739         if (entry == NULL) {
1740                 DEBUG0("Failed to get entry\n");
1741                 entry->error = PCICFG_FAILURE;
1742                 return (DDI_WALK_TERMINATE);
1743         }
1744 
1745         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
1746                 DEBUG0("Failed to map config space!\n");
1747                 entry->error = PCICFG_FAILURE;
1748                 return (DDI_WALK_TERMINATE);
1749         }
1750 
1751         header_type = pci_config_get8(handle, PCI_CONF_HEADER);
1752 
1753         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
1754 
1755                 bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
1756 
1757                 (void) pcicfg_setup_bridge(entry, handle);
1758 
1759                 range[0].child_high = range[0].parent_high |=
1760                     (PCI_REG_REL_M | PCI_ADDR_IO);
1761                 range[0].child_low = range[0].parent_low = entry->io_last;
1762                 range[1].child_high = range[1].parent_high |=
1763                     (PCI_REG_REL_M | PCI_ADDR_MEM32);
1764                 range[1].child_low = range[1].parent_low =
1765                     entry->memory_last;
1766                 range[2].child_high = range[2].parent_high |=
1767                     (PCI_REG_REL_M | PCI_ADDR_MEM32 | PCI_REG_PF_M);
1768                 range[2].child_low = range[2].parent_low =
1769                     entry->pf_memory_last;
1770 
1771                 ndi_devi_enter(dip, &count);
1772                 ddi_walk_devs(ddi_get_child(dip),
1773                     pcicfg_bridge_assign, (void *)entry);
1774                 ndi_devi_exit(dip, count);
1775 
1776                 (void) pcicfg_update_bridge(entry, handle);
1777 
1778                 bus_range[0] = pci_config_get8(handle, PCI_BCNF_SECBUS);
1779                 bus_range[1] = pci_config_get8(handle, PCI_BCNF_SUBBUS);
1780 
1781                 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1782                     "bus-range", bus_range, 2) != DDI_SUCCESS) {
1783                         DEBUG0("Failed to set bus-range property");
1784                         entry->error = PCICFG_FAILURE;
1785                         (void) pcicfg_config_teardown(&handle);
1786                         return (DDI_WALK_TERMINATE);
1787                 }
1788 
1789                 /*
1790                  * Put back memory and I/O space not allocated
1791                  * under the bridge.
1792                  */
1793                 mem_residual = entry->memory_len -
1794                     (entry->memory_last - entry->memory_base);
1795                 if (mem_residual > 0) {
1796                         (void) ndi_ra_free(ddi_get_parent(dip),
1797                             entry->memory_last, mem_residual,
1798                             NDI_RA_TYPE_MEM, NDI_RA_PASS);
1799                 }
1800 
1801                 io_residual = entry->io_len - (entry->io_last - entry->io_base);
1802                 if (io_residual > 0) {
1803                         (void) ndi_ra_free(ddi_get_parent(dip), entry->io_last,
1804                             io_residual, NDI_RA_TYPE_IO, NDI_RA_PASS);
1805                 }
1806 
1807                 pf_mem_residual = entry->pf_memory_len -
1808                     (entry->pf_memory_last - entry->pf_memory_base);
1809                 if (pf_mem_residual > 0) {
1810                         (void) ndi_ra_free(ddi_get_parent(dip),
1811                             entry->pf_memory_last, pf_mem_residual,
1812                             NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
1813                 }
1814 
1815                 if (entry->io_len > 0) {
1816                         range[0].size_low = entry->io_last - entry->io_base;
1817                         if (pcicfg_update_ranges_prop(dip, &range[0])) {
1818                                 DEBUG0("Failed to update ranges (i/o)\n");
1819                                 entry->error = PCICFG_FAILURE;
1820                                 (void) pcicfg_config_teardown(&handle);
1821                                 return (DDI_WALK_TERMINATE);
1822                         }
1823                 }
1824                 if (entry->memory_len > 0) {
1825                         range[1].size_low =
1826                             entry->memory_last - entry->memory_base;
1827                         if (pcicfg_update_ranges_prop(dip, &range[1])) {
1828                                 DEBUG0("Failed to update ranges (memory)\n");
1829                                 entry->error = PCICFG_FAILURE;
1830                                 (void) pcicfg_config_teardown(&handle);
1831                                 return (DDI_WALK_TERMINATE);
1832                         }
1833                 }
1834                 if (entry->pf_memory_len > 0) {
1835                         range[2].size_low =
1836                             entry->pf_memory_last - entry->pf_memory_base;
1837                         if (pcicfg_update_ranges_prop(dip, &range[2])) {
1838                                 DEBUG0("Failed to update ranges (PF memory)\n");
1839                                 entry->error = PCICFG_FAILURE;
1840                                 (void) pcicfg_config_teardown(&handle);
1841                                 return (DDI_WALK_TERMINATE);
1842                         }
1843                 }
1844 
1845                 (void) pcicfg_device_on(handle);
1846 
1847                 PCICFG_DUMP_BRIDGE_CONFIG(handle);
1848 
1849                 (void) pcicfg_config_teardown(&handle);
1850 
1851                 return (DDI_WALK_PRUNECHILD);
1852         }
1853 
1854         /*
1855          * If there is an interrupt pin set program
1856          * interrupt line with default values.
1857          */
1858         if (pci_config_get8(handle, PCI_CONF_IPIN)) {
1859                 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
1860         }
1861 
1862         /*
1863          * A single device (under a bridge).
1864          * For each "reg" property with a length, allocate memory
1865          * and program the base registers.
1866          */
1867         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
1868             (caddr_t)&reg, &length) != DDI_PROP_SUCCESS) {
1869                 DEBUG0("Failed to read reg property\n");
1870                 entry->error = PCICFG_FAILURE;
1871                 (void) pcicfg_config_teardown(&handle);
1872                 return (DDI_WALK_TERMINATE);
1873         }
1874 
1875         rcount = length / sizeof (pci_regspec_t);
1876         offset = PCI_CONF_BASE0;
1877         for (i = 0; i < rcount; i++) {
1878                 if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) {
1879 
1880                         offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
1881 
1882                         switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
1883                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
1884 
1885                                 if (reg[i].pci_phys_hi & PCI_REG_PF_M) {
1886                                         /* allocate prefetchable memory */
1887                                         pcicfg_get_pf_mem(entry,
1888                                             reg[i].pci_size_low, &mem_answer);
1889                                 } else { /* get non prefetchable memory */
1890                                         pcicfg_get_mem(entry,
1891                                             reg[i].pci_size_low, &mem_answer);
1892                                 }
1893                                 pci_config_put64(handle, offset, mem_answer);
1894                                 DEBUG2("REGISTER off %x (64)LO ----> [0x%x]\n",
1895                                     offset, pci_config_get32(handle, offset));
1896                                 DEBUG2("REGISTER off %x (64)HI ----> [0x%x]\n",
1897                                     offset + 4,
1898                                     pci_config_get32(handle, offset + 4));
1899 
1900                                 reg[i].pci_phys_hi |= PCI_REG_REL_M;
1901                                 reg[i].pci_phys_low = PCICFG_LOADDR(mem_answer);
1902                                 reg[i].pci_phys_mid = PCICFG_HIADDR(mem_answer);
1903                                 break;
1904 
1905                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
1906                                 if (reg[i].pci_phys_hi & PCI_REG_PF_M) {
1907                                         /* allocate prefetchable memory */
1908                                         pcicfg_get_pf_mem(entry,
1909                                             reg[i].pci_size_low, &mem_answer);
1910                                 } else {
1911                                         /* get non prefetchable memory */
1912                                         pcicfg_get_mem(entry,
1913                                             reg[i].pci_size_low, &mem_answer);
1914                                 }
1915 
1916                                 pci_config_put32(handle, offset,
1917                                     (uint32_t)mem_answer);
1918 
1919                                 DEBUG2("REGISTER off %x(32)LO ----> [0x%x]\n",
1920                                     offset, pci_config_get32(handle, offset));
1921 
1922                                 reg[i].pci_phys_hi |= PCI_REG_REL_M;
1923                                 reg[i].pci_phys_low = (uint32_t)mem_answer;
1924 
1925                                 break;
1926                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
1927                                 /* allocate I/O space from the allocator */
1928 
1929                                 (void) pcicfg_get_io(entry, reg[i].pci_size_low,
1930                                     &io_answer);
1931                                 pci_config_put32(handle, offset, io_answer);
1932 
1933                                 DEBUG2("REGISTER off %x (I/O)LO ----> [0x%x]\n",
1934                                     offset, pci_config_get32(handle, offset));
1935 
1936                                 reg[i].pci_phys_hi |= PCI_REG_REL_M;
1937                                 reg[i].pci_phys_low = io_answer;
1938 
1939                                 break;
1940                         default:
1941                                 DEBUG0("Unknown register type\n");
1942                                 kmem_free(reg, length);
1943                                 (void) pcicfg_config_teardown(&handle);
1944                                 entry->error = PCICFG_FAILURE;
1945                                 return (DDI_WALK_TERMINATE);
1946                         } /* switch */
1947 
1948                         /*
1949                          * Now that memory locations are assigned,
1950                          * update the assigned address property.
1951                          */
1952                         if (pcicfg_update_assigned_prop(dip, &reg[i])
1953                             != PCICFG_SUCCESS) {
1954                                 kmem_free(reg, length);
1955                                 (void) pcicfg_config_teardown(&handle);
1956                                 entry->error = PCICFG_FAILURE;
1957                                 return (DDI_WALK_TERMINATE);
1958                         }
1959                 }
1960         }
1961         (void) pcicfg_device_on(handle);
1962 
1963         PCICFG_DUMP_DEVICE_CONFIG(handle);
1964 
1965         (void) pcicfg_config_teardown(&handle);
1966         kmem_free((caddr_t)reg, length);
1967         return (DDI_WALK_CONTINUE);
1968 }
1969 
1970 static int
1971 pcicfg_device_assign(dev_info_t *dip)
1972 {
1973         ddi_acc_handle_t        handle;
1974         pci_regspec_t           *reg;
1975         int                     length;
1976         int                     rcount;
1977         int                     i;
1978         int                     offset;
1979         ndi_ra_request_t        request;
1980         uint64_t                answer;
1981         uint64_t                alen;
1982 
1983         DEBUG1("%llx now under configuration\n", dip);
1984 
1985         /* request.ra_len = PCICFG_ROUND_UP(request.ra_len, PCICFG_IOGRAN); */
1986         if (pcicfg_ntbridge_child(dip) == DDI_SUCCESS) {
1987 
1988                 return (pcicfg_ntbridge_program_child(dip));
1989         }
1990         /*
1991          * XXX Failure here should be noted
1992          */
1993         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
1994             (caddr_t)&reg, &length) != DDI_PROP_SUCCESS) {
1995                 DEBUG0("Failed to read reg property\n");
1996                 return (PCICFG_FAILURE);
1997         }
1998 
1999         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2000                 DEBUG0("Failed to map config space!\n");
2001                 kmem_free(reg, length);
2002                 return (PCICFG_FAILURE);
2003         }
2004 
2005         /*
2006          * A single device
2007          *
2008          * For each "reg" property with a length, allocate memory
2009          * and program the base registers.
2010          */
2011 
2012         /*
2013          * If there is an interrupt pin set program
2014          * interrupt line with default values.
2015          */
2016         if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2017                 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2018         }
2019 
2020         bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2021 
2022         /*
2023          * Note: Both non-prefetchable and prefetchable memory space
2024          * allocations are made within 32bit space. Currently, BIOSs
2025          * allocate device memory for PCI devices within the 32bit space
2026          * so this will not be a problem.
2027          */
2028         request.ra_flags |= NDI_RA_ALIGN_SIZE | NDI_RA_ALLOC_BOUNDED;
2029         request.ra_boundbase = 0;
2030         request.ra_boundlen = PCICFG_4GIG_LIMIT;
2031 
2032         rcount = length / sizeof (pci_regspec_t);
2033         offset = PCI_CONF_BASE0;
2034         for (i = 0; i < rcount; i++) {
2035                 char    *mem_type;
2036 
2037                 if ((reg[i].pci_size_low != 0)|| (reg[i].pci_size_hi != 0)) {
2038 
2039                         offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
2040                         request.ra_len = reg[i].pci_size_low;
2041 
2042                         switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
2043                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2044                                 if (reg[i].pci_phys_hi & PCI_REG_PF_M) {
2045                                         mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2046                                 } else {
2047                                         mem_type = NDI_RA_TYPE_MEM;
2048                                 }
2049                                 /* allocate memory space from the allocator */
2050                                 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2051                                     &answer, &alen, mem_type, NDI_RA_PASS)
2052                                     != NDI_SUCCESS) {
2053                                         DEBUG0("Failed to allocate 64b mem\n");
2054                                         kmem_free(reg, length);
2055                                         (void) pcicfg_config_teardown(&handle);
2056                                         return (PCICFG_NORESRC);
2057                                 }
2058                                 DEBUG3("64 addr = [0x%x.0x%x] len [0x%x]\n",
2059                                     PCICFG_HIADDR(answer),
2060                                     PCICFG_LOADDR(answer), alen);
2061                                 /* program the low word */
2062                                 pci_config_put32(handle, offset,
2063                                     PCICFG_LOADDR(answer));
2064                                 /* program the high word */
2065                                 pci_config_put32(handle, offset + 4,
2066                                     PCICFG_HIADDR(answer));
2067 
2068                                 reg[i].pci_phys_hi |= PCI_REG_REL_M;
2069                                 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2070                                 reg[i].pci_phys_mid = PCICFG_HIADDR(answer);
2071                                 /*
2072                                  * currently support 32b address space
2073                                  * assignments only.
2074                                  */
2075                                 reg[i].pci_phys_hi ^=
2076                                     PCI_ADDR_MEM64 ^ PCI_ADDR_MEM32;
2077 
2078                                 offset += 8;
2079                                 break;
2080 
2081                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2082                                 if (reg[i].pci_phys_hi & PCI_REG_PF_M)
2083                                         mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2084                                 else
2085                                         mem_type = NDI_RA_TYPE_MEM;
2086                                 /* allocate memory space from the allocator */
2087                                 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2088                                     &answer, &alen, mem_type, NDI_RA_PASS)
2089                                     != NDI_SUCCESS) {
2090                                         DEBUG0("Failed to allocate 32b mem\n");
2091                                         kmem_free(reg, length);
2092                                         (void) pcicfg_config_teardown(&handle);
2093                                         return (PCICFG_NORESRC);
2094                                 }
2095                                 DEBUG3("32 addr = [0x%x.0x%x] len [0x%x]\n",
2096                                     PCICFG_HIADDR(answer),
2097                                     PCICFG_LOADDR(answer),
2098                                     alen);
2099                                 /* program the low word */
2100                                 pci_config_put32(handle, offset,
2101                                     PCICFG_LOADDR(answer));
2102 
2103                                 reg[i].pci_phys_hi |= PCI_REG_REL_M;
2104                                 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2105                                 reg[i].pci_phys_mid = 0;
2106 
2107                                 offset += 4;
2108                                 break;
2109                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2110                                 /*
2111                                  * Try to allocate I/O space. If it fails,
2112                                  * continue here instead of returning failure
2113                                  * so that the hotplug for drivers that don't
2114                                  * use I/O space can succeed, For drivers
2115                                  * that need to use I/O space, the hotplug
2116                                  * will still fail later during driver attach.
2117                                  */
2118                                 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2119                                     &answer, &alen, NDI_RA_TYPE_IO, NDI_RA_PASS)
2120                                     != NDI_SUCCESS) {
2121                                         DEBUG0("Failed to allocate I/O\n");
2122                                         continue;
2123                                 }
2124                                 DEBUG3("I/O addr = [0x%x.0x%x] len [0x%x]\n",
2125                                     PCICFG_HIADDR(answer),
2126                                     PCICFG_LOADDR(answer), alen);
2127                                 pci_config_put32(handle, offset,
2128                                     PCICFG_LOADDR(answer));
2129 
2130                                 reg[i].pci_phys_hi |= PCI_REG_REL_M;
2131                                 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2132 
2133                                 offset += 4;
2134                                 break;
2135                         default:
2136                                 DEBUG0("Unknown register type\n");
2137                                 kmem_free(reg, length);
2138                                 (void) pcicfg_config_teardown(&handle);
2139                                 return (PCICFG_FAILURE);
2140                         } /* switch */
2141 
2142                         /*
2143                          * Now that memory locations are assigned,
2144                          * update the assigned address property.
2145                          */
2146 
2147                         if (pcicfg_update_assigned_prop(dip, &reg[i])
2148                             != PCICFG_SUCCESS) {
2149                                 kmem_free(reg, length);
2150                                 (void) pcicfg_config_teardown(&handle);
2151                                 return (PCICFG_FAILURE);
2152                         }
2153                 }
2154         }
2155 
2156         (void) pcicfg_device_on(handle);
2157         kmem_free(reg, length);
2158 
2159         PCICFG_DUMP_DEVICE_CONFIG(handle);
2160 
2161         (void) pcicfg_config_teardown(&handle);
2162         return (PCICFG_SUCCESS);
2163 }
2164 
2165 static int
2166 pcicfg_device_assign_readonly(dev_info_t *dip)
2167 {
2168         ddi_acc_handle_t        handle;
2169         pci_regspec_t           *assigned;
2170         int                     length;
2171         int                     acount;
2172         int                     i;
2173         ndi_ra_request_t        request;
2174         uint64_t                answer;
2175         uint64_t                alen;
2176 
2177         DEBUG1("%llx now under configuration\n", dip);
2178 
2179         /*
2180          * we don't support ntbridges for readonly probe.
2181          */
2182         if (pcicfg_ntbridge_child(dip) == DDI_SUCCESS) {
2183                 return (PCICFG_FAILURE);
2184         }
2185 
2186         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2187             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
2188             &length) != DDI_PROP_SUCCESS) {
2189                 DEBUG0("Failed to read assigned-addresses property\n");
2190                 return (PCICFG_FAILURE);
2191         }
2192 
2193         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2194                 DEBUG0("Failed to map config space!\n");
2195                 kmem_free(assigned, length);
2196                 return (PCICFG_FAILURE);
2197         }
2198 
2199         /*
2200          * If there is an interrupt pin set program
2201          * interrupt line with default values.
2202          */
2203         if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2204                 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2205         }
2206         /*
2207          * Note: Both non-prefetchable and prefetchable memory space
2208          * allocations are made within 32bit space. Currently, BIOSs
2209          * allocate device memory for PCI devices within the 32bit space
2210          * so this will not be a problem.
2211          */
2212         bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2213 
2214         request.ra_flags = NDI_RA_ALLOC_SPECIFIED;  /* specified addr */
2215         request.ra_boundbase = 0;
2216         request.ra_boundlen = PCICFG_4GIG_LIMIT;
2217 
2218         acount = length / sizeof (pci_regspec_t);
2219         for (i = 0; i < acount; i++) {
2220                 char    *mem_type;
2221 
2222                 if ((assigned[i].pci_size_low != 0)||
2223                     (assigned[i].pci_size_hi != 0)) {
2224 
2225                         request.ra_len = assigned[i].pci_size_low;
2226 
2227                         switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
2228                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2229                                 request.ra_addr = (uint64_t)PCICFG_LADDR(
2230                                     assigned[i].pci_phys_low,
2231                                     assigned[i].pci_phys_mid);
2232 
2233                                 if (assigned[i].pci_phys_hi & PCI_REG_PF_M) {
2234                                         mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2235                                 } else {
2236                                         mem_type = NDI_RA_TYPE_MEM;
2237                                 }
2238                                 /* allocate memory space from the allocator */
2239                                 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2240                                     &answer, &alen, mem_type, NDI_RA_PASS)
2241                                     != NDI_SUCCESS) {
2242                                         DEBUG0("Failed to allocate 64b mem\n");
2243                                         kmem_free(assigned, length);
2244                                         return (PCICFG_NORESRC);
2245                                 }
2246 
2247                                 break;
2248                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2249                                 request.ra_addr = (uint64_t)
2250                                     assigned[i].pci_phys_low;
2251 
2252                                 if (assigned[i].pci_phys_hi & PCI_REG_PF_M)
2253                                         mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2254                                 else
2255                                         mem_type = NDI_RA_TYPE_MEM;
2256                                 /* allocate memory space from the allocator */
2257                                 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2258                                     &answer, &alen, mem_type, NDI_RA_PASS)
2259                                     != NDI_SUCCESS) {
2260                                         DEBUG0("Failed to allocate 32b mem\n");
2261                                         kmem_free(assigned, length);
2262                                         return (PCICFG_NORESRC);
2263                                 }
2264 
2265                                 break;
2266                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2267                                 request.ra_addr = (uint64_t)
2268                                     assigned[i].pci_phys_low;
2269 
2270                                 /* allocate I/O space from the allocator */
2271                                 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2272                                     &answer, &alen, NDI_RA_TYPE_IO, NDI_RA_PASS)
2273                                     != NDI_SUCCESS) {
2274                                         DEBUG0("Failed to allocate I/O\n");
2275                                         kmem_free(assigned, length);
2276                                         return (PCICFG_NORESRC);
2277                                 }
2278 
2279                                 break;
2280                         default:
2281                                 DEBUG0("Unknown register type\n");
2282                                 kmem_free(assigned, length);
2283                                 return (PCICFG_FAILURE);
2284                         } /* switch */
2285                 }
2286         }
2287 
2288         (void) pcicfg_device_on(handle);
2289         kmem_free(assigned, length);
2290 
2291         PCICFG_DUMP_DEVICE_CONFIG(handle);
2292 
2293         (void) pcicfg_config_teardown(&handle);
2294         return (PCICFG_SUCCESS);
2295 }
2296 
2297 #ifdef  DEBUG
2298 /*
2299  * This function is useful in debug mode, where we can measure how
2300  * much memory was wasted/unallocated in bridge device's domain.
2301  */
2302 static uint64_t
2303 pcicfg_unused_space(hole_t *hole, uint32_t *hole_count)
2304 {
2305         uint64_t len = 0;
2306         uint32_t count = 0;
2307 
2308         do {
2309                 len += hole->len;
2310                 hole = hole->next;
2311                 count++;
2312         } while (hole);
2313         *hole_count = count;
2314         return (len);
2315 }
2316 #endif
2317 
2318 /*
2319  * This function frees data structures that hold the hole information
2320  * which are allocated in pcicfg_alloc_hole(). This is not freeing
2321  * any memory allocated through NDI calls.
2322  */
2323 static void
2324 pcicfg_free_hole(hole_t *addr_hole)
2325 {
2326         hole_t *nhole, *hole = addr_hole->next;
2327 
2328         while (hole) {
2329                 nhole = hole->next;
2330                 kmem_free(hole, sizeof (hole_t));
2331                 hole = nhole;
2332         }
2333 }
2334 
2335 static uint64_t
2336 pcicfg_alloc_hole(hole_t *addr_hole, uint64_t *alast, uint32_t length)
2337 {
2338         uint64_t actual_hole_start, ostart, olen;
2339         hole_t  *hole = addr_hole, *thole, *nhole;
2340 
2341         do {
2342                 actual_hole_start = PCICFG_ROUND_UP(hole->start, length);
2343                 if (((actual_hole_start - hole->start) + length) <= hole->len) {
2344                         DEBUG3("hole found. start %llx, len %llx, req=0x%x\n",
2345                             hole->start, hole->len, length);
2346                         ostart = hole->start;
2347                         olen = hole->len;
2348                         /* current hole parameters adjust */
2349                         if ((actual_hole_start - hole->start) == 0) {
2350                                 hole->start += length;
2351                                 hole->len -= length;
2352                                 if (hole->start > *alast)
2353                                         *alast = hole->start;
2354                         } else {
2355                                 hole->len = actual_hole_start - hole->start;
2356                                 nhole = (hole_t *)kmem_zalloc(sizeof (hole_t),
2357                                     KM_SLEEP);
2358                                 nhole->start = actual_hole_start + length;
2359                                 nhole->len = (ostart + olen) - nhole->start;
2360                                 nhole->next = NULL;
2361                                 thole = hole->next;
2362                                 hole->next = nhole;
2363                                 nhole->next = thole;
2364                                 if (nhole->start > *alast)
2365                                         *alast = nhole->start;
2366                                 DEBUG2("put new hole to %llx, %llx\n",
2367                                     nhole->start, nhole->len);
2368                         }
2369                         DEBUG2("adjust current hole to %llx, %llx\n",
2370                             hole->start, hole->len);
2371                         break;
2372                 }
2373                 actual_hole_start = 0;
2374                 hole = hole->next;
2375         } while (hole);
2376 
2377         DEBUG1("return hole at %llx\n", actual_hole_start);
2378         return (actual_hole_start);
2379 }
2380 
2381 static void
2382 pcicfg_get_mem(pcicfg_phdl_t *entry, uint32_t length, uint64_t *ans)
2383 {
2384         uint64_t new_mem;
2385 
2386         /* See if there is a hole, that can hold this request. */
2387         new_mem = pcicfg_alloc_hole(&entry->mem_hole, &entry->memory_last,
2388             length);
2389         if (new_mem) {  /* if non-zero, found a hole. */
2390                 if (ans != NULL)
2391                         *ans = new_mem;
2392         } else
2393                 cmn_err(CE_WARN, "No %u bytes memory window for %s\n",
2394                     length, ddi_get_name(entry->dip));
2395 }
2396 
2397 static void
2398 pcicfg_get_io(pcicfg_phdl_t *entry,
2399         uint32_t length, uint32_t *ans)
2400 {
2401         uint32_t new_io;
2402         uint64_t io_last;
2403 
2404         /*
2405          * See if there is a hole, that can hold this request.
2406          * Pass 64 bit parameters and then truncate to 32 bit.
2407          */
2408         io_last = entry->io_last;
2409         new_io = (uint32_t)pcicfg_alloc_hole(&entry->io_hole, &io_last, length);
2410         if (new_io) {   /* if non-zero, found a hole. */
2411                 entry->io_last = (uint32_t)io_last;
2412                 if (ans != NULL)
2413                         *ans = new_io;
2414         } else
2415                 cmn_err(CE_WARN, "No %u bytes IO space window for %s\n",
2416                     length, ddi_get_name(entry->dip));
2417 }
2418 
2419 static void
2420 pcicfg_get_pf_mem(pcicfg_phdl_t *entry, uint32_t length, uint64_t *ans)
2421 {
2422         uint64_t new_mem;
2423 
2424         /* See if there is a hole, that can hold this request. */
2425         new_mem = pcicfg_alloc_hole(&entry->pf_mem_hole, &entry->pf_memory_last,
2426             length);
2427         if (new_mem) {  /* if non-zero, found a hole. */
2428                 if (ans != NULL)
2429                         *ans = new_mem;
2430         } else
2431                 cmn_err(CE_WARN, "No %u bytes PF memory window for %s\n",
2432                     length, ddi_get_name(entry->dip));
2433 }
2434 
2435 static int
2436 pcicfg_sum_resources(dev_info_t *dip, void *hdl)
2437 {
2438         pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
2439         pci_regspec_t *pci_rp;
2440         int length;
2441         int rcount;
2442         int i;
2443         ndi_ra_request_t *pf_mem_request;
2444         ndi_ra_request_t *mem_request;
2445         ndi_ra_request_t *io_request;
2446         uint8_t header_type;
2447         ddi_acc_handle_t handle;
2448 
2449         entry->error = PCICFG_SUCCESS;
2450 
2451         pf_mem_request = &entry->pf_mem_req;
2452         mem_request = &entry->mem_req;
2453         io_request =  &entry->io_req;
2454 
2455         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2456                 DEBUG0("Failed to map config space!\n");
2457                 entry->error = PCICFG_FAILURE;
2458                 return (DDI_WALK_TERMINATE);
2459         }
2460 
2461         header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2462 
2463         /*
2464          * If its a bridge - just record the highest bus seen
2465          */
2466         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2467 
2468                 if (entry->highest_bus < pci_config_get8(handle,
2469                     PCI_BCNF_SECBUS)) {
2470                         entry->highest_bus =
2471                             pci_config_get8(handle, PCI_BCNF_SECBUS);
2472                 }
2473                 (void) pcicfg_config_teardown(&handle);
2474                 entry->error = PCICFG_FAILURE;
2475                 return (DDI_WALK_CONTINUE);
2476         } else {
2477                 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2478                     "reg", (caddr_t)&pci_rp, &length) != DDI_PROP_SUCCESS) {
2479                         /*
2480                          * If one node in (the subtree of nodes)
2481                          * doesn't have a "reg" property fail the
2482                          * allocation.
2483                          */
2484                         entry->memory_len = 0;
2485                         entry->io_len = 0;
2486                         entry->pf_memory_len = 0;
2487                         entry->error = PCICFG_FAILURE;
2488                         (void) pcicfg_config_teardown(&handle);
2489                         return (DDI_WALK_TERMINATE);
2490                 }
2491                 /*
2492                  * For each "reg" property with a length, add that to the
2493                  * total memory (or I/O) to allocate.
2494                  */
2495                 rcount = length / sizeof (pci_regspec_t);
2496 
2497                 for (i = 0; i < rcount; i++) {
2498 
2499                         switch (PCI_REG_ADDR_G(pci_rp[i].pci_phys_hi)) {
2500 
2501                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2502                                 if (pci_rp[i].pci_phys_hi & PCI_REG_PF_M) {
2503                                         pf_mem_request->ra_len =
2504                                             pci_rp[i].pci_size_low +
2505                                             PCICFG_ROUND_UP(
2506                                             pf_mem_request->ra_len,
2507                                             pci_rp[i].pci_size_low);
2508                                         DEBUG1("ADDING 32 --->0x%x\n",
2509                                             pci_rp[i].pci_size_low);
2510                                 } else {
2511                                         mem_request->ra_len =
2512                                             pci_rp[i].pci_size_low +
2513                                             PCICFG_ROUND_UP(mem_request->ra_len,
2514                                             pci_rp[i].pci_size_low);
2515                                         DEBUG1("ADDING 32 --->0x%x\n",
2516                                             pci_rp[i].pci_size_low);
2517                                 }
2518 
2519                                 break;
2520                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2521                                 if (pci_rp[i].pci_phys_hi & PCI_REG_PF_M) {
2522                                         pf_mem_request->ra_len =
2523                                             pci_rp[i].pci_size_low +
2524                                             PCICFG_ROUND_UP(
2525                                             pf_mem_request->ra_len,
2526                                             pci_rp[i].pci_size_low);
2527                                         DEBUG1("ADDING 64 --->0x%x\n",
2528                                             pci_rp[i].pci_size_low);
2529                                 } else {
2530                                         mem_request->ra_len =
2531                                             pci_rp[i].pci_size_low +
2532                                             PCICFG_ROUND_UP(mem_request->ra_len,
2533                                             pci_rp[i].pci_size_low);
2534                                         DEBUG1("ADDING 64 --->0x%x\n",
2535                                             pci_rp[i].pci_size_low);
2536                                 }
2537 
2538                                 break;
2539                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2540                                 io_request->ra_len =
2541                                     pci_rp[i].pci_size_low +
2542                                     PCICFG_ROUND_UP(io_request->ra_len,
2543                                     pci_rp[i].pci_size_low);
2544                                 DEBUG1("ADDING I/O --->0x%x\n",
2545                                     pci_rp[i].pci_size_low);
2546                                 break;
2547                         default:
2548                                 /* Config space register - not included */
2549                                 break;
2550                         }
2551                 }
2552 
2553                 /*
2554                  * free the memory allocated by ddi_getlongprop
2555                  */
2556                 kmem_free(pci_rp, length);
2557 
2558                 /*
2559                  * continue the walk to the next sibling to sum memory
2560                  */
2561 
2562                 (void) pcicfg_config_teardown(&handle);
2563 
2564                 return (DDI_WALK_CONTINUE);
2565         }
2566 }
2567 
2568 static int
2569 pcicfg_free_bridge_resources(dev_info_t *dip)
2570 {
2571         ppb_ranges_t            *ranges;
2572         uint_t                  *bus;
2573         int                     k;
2574         int                     length = 0;
2575         int                     i;
2576 
2577 
2578         if ((i = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2579             "ranges", (caddr_t)&ranges, &length)) != DDI_PROP_SUCCESS) {
2580                 DEBUG0("Failed to read ranges property\n");
2581                 if (ddi_get_child(dip)) {
2582                         cmn_err(CE_WARN, "No ranges property found for %s",
2583                             ddi_get_name(dip));
2584                         /*
2585                          * strictly speaking, we can check for children with
2586                          * assigned-addresses but for now it is better to
2587                          * be conservative and assume that if there are child
2588                          * nodes, then they do consume PCI memory or IO
2589                          * resources, Hence return failure.
2590                          */
2591                         return (PCICFG_FAILURE);
2592                 }
2593                 length = 0;
2594         }
2595 
2596         for (i = 0; i < length / sizeof (ppb_ranges_t); i++) {
2597                 char *mem_type;
2598 
2599                 if (ranges[i].size_low != 0 || ranges[i].size_high != 0) {
2600                         switch (ranges[i].parent_high & PCI_REG_ADDR_M) {
2601                         case PCI_ADDR_IO:
2602                                 DEBUG2("Free I/O    base/length = "
2603                                     "[0x%x]/[0x%x]\n", ranges[i].child_low,
2604                                     ranges[i].size_low);
2605                                 if (ndi_ra_free(ddi_get_parent(dip),
2606                                     (uint64_t)ranges[i].child_low,
2607                                     (uint64_t)ranges[i].size_low,
2608                                     NDI_RA_TYPE_IO, NDI_RA_PASS)
2609                                     != NDI_SUCCESS) {
2610                                         DEBUG0("Trouble freeing "
2611                                             "PCI i/o space\n");
2612                                         kmem_free(ranges, length);
2613                                         return (PCICFG_FAILURE);
2614                                 }
2615                                 break;
2616                         case PCI_ADDR_MEM32:
2617                         case PCI_ADDR_MEM64:
2618                                 if (ranges[i].parent_high & PCI_REG_PF_M) {
2619                                         DEBUG3("Free PF Memory base/length = "
2620                                             "[0x%x.0x%x]/[0x%x]\n",
2621                                             ranges[i].child_mid,
2622                                             ranges[i].child_low,
2623                                             ranges[i].size_low);
2624                                         mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2625                                 } else {
2626                                         DEBUG3("Free Memory base/length"
2627                                             " = [0x%x.0x%x]/[0x%x]\n",
2628                                             ranges[i].child_mid,
2629                                             ranges[i].child_low,
2630                                             ranges[i].size_low)
2631                                         mem_type = NDI_RA_TYPE_MEM;
2632                                 }
2633                                 if (ndi_ra_free(ddi_get_parent(dip),
2634                                     PCICFG_LADDR(ranges[i].child_low,
2635                                     ranges[i].child_mid),
2636                                     (uint64_t)ranges[i].size_low,
2637                                     mem_type, NDI_RA_PASS) != NDI_SUCCESS) {
2638                                         DEBUG0("Trouble freeing "
2639                                             "PCI memory space\n");
2640                                         kmem_free(ranges, length);
2641                                         return (PCICFG_FAILURE);
2642                                 }
2643                                 break;
2644                         default:
2645                                 DEBUG0("Unknown memory space\n");
2646                                 break;
2647                         }
2648                 }
2649         }
2650 
2651         if (length)
2652                 kmem_free(ranges, length);
2653 
2654         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2655             "bus-range", (caddr_t)&bus, &k) != DDI_PROP_SUCCESS) {
2656                 DEBUG0("Failed to read bus-range property\n");
2657                 return (PCICFG_FAILURE);
2658         }
2659 
2660         DEBUG2("Need to free bus [%d] range [%d]\n",
2661             bus[0], bus[1] - bus[0] + 1);
2662 
2663         if (ndi_ra_free(ddi_get_parent(dip), (uint64_t)bus[0],
2664             (uint64_t)(bus[1] - bus[0] + 1), NDI_RA_TYPE_PCI_BUSNUM,
2665             NDI_RA_PASS) != NDI_SUCCESS) {
2666                 DEBUG0("Failed to free a bus number\n");
2667                 kmem_free(bus, k);
2668                 return (PCICFG_FAILURE);
2669         }
2670 
2671         kmem_free(bus, k);
2672         return (PCICFG_SUCCESS);
2673 }
2674 
2675 static int
2676 pcicfg_free_device_resources(dev_info_t *dip)
2677 {
2678         pci_regspec_t *assigned;
2679 
2680         int length;
2681         int acount;
2682         int i;
2683 
2684         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2685             "assigned-addresses", (caddr_t)&assigned, &length)
2686             != DDI_PROP_SUCCESS) {
2687                 DEBUG0("Failed to read assigned-addresses property\n");
2688                 return (PCICFG_FAILURE);
2689         }
2690 
2691         /*
2692          * For each "assigned-addresses" property entry with a length,
2693          * call the memory allocation routines to return the
2694          * resource.
2695          */
2696         acount = length / sizeof (pci_regspec_t);
2697         for (i = 0; i < acount; i++) {
2698                 char *mem_type;
2699 
2700                 /*
2701                  * Free the resource if the size of it is not zero.
2702                  */
2703                 if ((assigned[i].pci_size_low != 0)||
2704                     (assigned[i].pci_size_hi != 0)) {
2705                         switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
2706                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2707                                 /*
2708                                  * Check the assigned address for zero.
2709                                  * (Workaround for Devconf (x86) bug to
2710                                  * skip bogus entry for ROM base address
2711                                  * register. If the assigned address is
2712                                  * zero then ignore the entry
2713                                  * (see bugid 4281306)).
2714                                  */
2715                                 if (assigned[i].pci_phys_low == 0)
2716                                         break; /* ignore the entry */
2717 
2718                                 if (assigned[i].pci_phys_hi & PCI_REG_PF_M)
2719                                         mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2720                                 else
2721                                         mem_type = NDI_RA_TYPE_MEM;
2722 
2723                                 if (ndi_ra_free(ddi_get_parent(dip),
2724                                     (uint64_t)assigned[i].pci_phys_low,
2725                                     (uint64_t)assigned[i].pci_size_low,
2726                                     mem_type, NDI_RA_PASS) != NDI_SUCCESS) {
2727                                         DEBUG0("Trouble freeing "
2728                                             "PCI memory space\n");
2729                                         kmem_free(assigned, length);
2730                                         return (PCICFG_FAILURE);
2731                                 }
2732 
2733                                 DEBUG4("Returned 0x%x of 32 bit %s space"
2734                                     " @ 0x%x from register 0x%x\n",
2735                                     assigned[i].pci_size_low, mem_type,
2736                                     assigned[i].pci_phys_low,
2737                                     PCI_REG_REG_G(assigned[i].pci_phys_hi));
2738 
2739                         break;
2740                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2741                                 if (assigned[i].pci_phys_hi & PCI_REG_PF_M)
2742                                         mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2743                                 else
2744                                         mem_type = NDI_RA_TYPE_MEM;
2745 
2746                                 if (ndi_ra_free(ddi_get_parent(dip),
2747                                     PCICFG_LADDR(assigned[i].pci_phys_low,
2748                                     assigned[i].pci_phys_mid),
2749                                     (uint64_t)assigned[i].pci_size_low,
2750                                     mem_type, NDI_RA_PASS) != NDI_SUCCESS) {
2751                                         DEBUG0("Trouble freeing "
2752                                             "PCI memory space\n");
2753                                         kmem_free(assigned, length);
2754                                         return (PCICFG_FAILURE);
2755                                 }
2756 
2757                                 DEBUG5("Returned 0x%x of 64 bit %s space"
2758                                     " @ 0x%x.0x%x from register 0x%x\n",
2759                                     assigned[i].pci_size_low,
2760                                     mem_type, assigned[i].pci_phys_mid,
2761                                     assigned[i].pci_phys_low,
2762                                     PCI_REG_REG_G(assigned[i].pci_phys_hi));
2763 
2764                         break;
2765                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2766                                 if (ndi_ra_free(ddi_get_parent(dip),
2767                                     (uint64_t)assigned[i].pci_phys_low,
2768                                     (uint64_t)assigned[i].pci_size_low,
2769                                     NDI_RA_TYPE_IO, NDI_RA_PASS) !=
2770                                     NDI_SUCCESS) {
2771                                         DEBUG0("Trouble freeing "
2772                                             "PCI IO space\n");
2773                                         kmem_free(assigned, length);
2774                                         return (PCICFG_FAILURE);
2775                                 }
2776                                 DEBUG3("Returned 0x%x of IO space @ 0x%x from "
2777                                     "register 0x%x\n", assigned[i].pci_size_low,
2778                                     assigned[i].pci_phys_low,
2779                                     PCI_REG_REG_G(assigned[i].pci_phys_hi));
2780                         break;
2781                         default:
2782                                 DEBUG0("Unknown register type\n");
2783                                 kmem_free(assigned, length);
2784                                 return (PCICFG_FAILURE);
2785                         } /* switch */
2786                 }
2787         }
2788         kmem_free(assigned, length);
2789         return (PCICFG_SUCCESS);
2790 }
2791 
2792 static int
2793 pcicfg_free_resources(dev_info_t *dip, pcicfg_flags_t flags)
2794 {
2795         ddi_acc_handle_t handle;
2796         uint8_t header_type;
2797 
2798         if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
2799                 DEBUG0("Failed to map config space!\n");
2800                 return (PCICFG_FAILURE);
2801         }
2802 
2803         header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2804 
2805         (void) pci_config_teardown(&handle);
2806 
2807         /*
2808          * A different algorithm is used for bridges and leaf devices.
2809          */
2810         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2811                 /*
2812                  * We only support readonly probing for leaf devices.
2813                  */
2814                 if (flags & PCICFG_FLAG_READ_ONLY)
2815                         return (PCICFG_FAILURE);
2816 
2817                 if (pcicfg_free_bridge_resources(dip) != PCICFG_SUCCESS) {
2818                         DEBUG0("Failed freeing up bridge resources\n");
2819                         return (PCICFG_FAILURE);
2820                 }
2821         } else {
2822                 if (pcicfg_free_device_resources(dip) != PCICFG_SUCCESS) {
2823                         DEBUG0("Failed freeing up device resources\n");
2824                         return (PCICFG_FAILURE);
2825                 }
2826         }
2827 
2828         return (PCICFG_SUCCESS);
2829 }
2830 
2831 #ifndef _DONT_USE_1275_GENERIC_NAMES
2832 static char *
2833 pcicfg_get_class_name(uint32_t classcode)
2834 {
2835         struct pcicfg_name_entry *ptr;
2836 
2837         for (ptr = &pcicfg_class_lookup[0]; ptr->name != NULL; ptr++) {
2838                 if (ptr->class_code == classcode) {
2839                         return (ptr->name);
2840                 }
2841         }
2842         return (NULL);
2843 }
2844 #endif /* _DONT_USE_1275_GENERIC_NAMES */
2845 
2846 static dev_info_t *
2847 pcicfg_devi_find(dev_info_t *dip, uint_t device, uint_t function)
2848 {
2849         struct pcicfg_find_ctrl ctrl;
2850         int count;
2851 
2852         ctrl.device = device;
2853         ctrl.function = function;
2854         ctrl.dip = NULL;
2855 
2856         ndi_devi_enter(dip, &count);
2857         ddi_walk_devs(ddi_get_child(dip), pcicfg_match_dev, (void *)&ctrl);
2858         ndi_devi_exit(dip, count);
2859 
2860         return (ctrl.dip);
2861 }
2862 
2863 static int
2864 pcicfg_match_dev(dev_info_t *dip, void *hdl)
2865 {
2866         struct pcicfg_find_ctrl *ctrl = (struct pcicfg_find_ctrl *)hdl;
2867         pci_regspec_t *pci_rp;
2868         int length;
2869         int pci_dev;
2870         int pci_func;
2871 
2872         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2873             "reg", (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) {
2874                 ctrl->dip = NULL;
2875                 return (DDI_WALK_TERMINATE);
2876         }
2877 
2878         /* get the PCI device address info */
2879         pci_dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
2880         pci_func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
2881 
2882         /*
2883          * free the memory allocated by ddi_prop_lookup_int_array
2884          */
2885         ddi_prop_free(pci_rp);
2886 
2887 
2888         if ((pci_dev == ctrl->device) && (pci_func == ctrl->function)) {
2889                 /* found the match for the specified device address */
2890                 ctrl->dip = dip;
2891                 return (DDI_WALK_TERMINATE);
2892         }
2893 
2894         /*
2895          * continue the walk to the next sibling to look for a match.
2896          */
2897         return (DDI_WALK_PRUNECHILD);
2898 }
2899 
2900 static int
2901 pcicfg_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone)
2902 {
2903         int             alen;
2904         pci_regspec_t   *assigned;
2905         caddr_t         newreg;
2906         uint_t          status;
2907 
2908         status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2909             "assigned-addresses", (caddr_t)&assigned, &alen);
2910         switch (status) {
2911                 case DDI_PROP_SUCCESS:
2912                 break;
2913                 case DDI_PROP_NO_MEMORY:
2914                         DEBUG0("no memory for assigned-addresses property\n");
2915                         return (PCICFG_FAILURE);
2916                 default:
2917                         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
2918                             "assigned-addresses", (int *)newone,
2919                             sizeof (*newone)/sizeof (int));
2920                         return (PCICFG_SUCCESS);
2921         }
2922 
2923         /*
2924          * Allocate memory for the existing
2925          * assigned-addresses(s) plus one and then
2926          * build it.
2927          */
2928 
2929         newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
2930 
2931         bcopy(assigned, newreg, alen);
2932         bcopy(newone, newreg + alen, sizeof (*newone));
2933 
2934         /*
2935          * Write out the new "assigned-addresses" spec
2936          */
2937         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
2938             "assigned-addresses", (int *)newreg,
2939             (alen + sizeof (*newone))/sizeof (int));
2940 
2941         kmem_free((caddr_t)newreg, alen+sizeof (*newone));
2942         kmem_free(assigned, alen);
2943 
2944         return (PCICFG_SUCCESS);
2945 }
2946 
2947 static int
2948 pcicfg_update_ranges_prop(dev_info_t *dip, ppb_ranges_t *addition)
2949 {
2950         int             rlen;
2951         ppb_ranges_t    *ranges;
2952         caddr_t         newreg;
2953         uint_t          status;
2954 
2955         status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2956             "ranges", (caddr_t)&ranges, &rlen);
2957 
2958 
2959         switch (status) {
2960                 case DDI_PROP_SUCCESS:
2961                         break;
2962                 case DDI_PROP_NO_MEMORY:
2963                         DEBUG0("ranges present, but unable to get memory\n");
2964                         return (PCICFG_FAILURE);
2965                 default:
2966                         DEBUG0("no ranges property - creating one\n");
2967                         if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
2968                             dip, "ranges", (int *)addition,
2969                             sizeof (ppb_ranges_t)/sizeof (int))
2970                             != DDI_SUCCESS) {
2971                                 DEBUG0("Did'nt create ranges property\n");
2972                                 return (PCICFG_FAILURE);
2973                         }
2974                         return (PCICFG_SUCCESS);
2975         }
2976 
2977         /*
2978          * Allocate memory for the existing ranges plus one and then
2979          * build it.
2980          */
2981         newreg = kmem_zalloc(rlen+sizeof (ppb_ranges_t), KM_SLEEP);
2982 
2983         bcopy(ranges, newreg, rlen);
2984         bcopy(addition, newreg + rlen, sizeof (ppb_ranges_t));
2985 
2986         /*
2987          * Write out the new "ranges" property
2988          */
2989         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
2990             (int *)newreg, (rlen + sizeof (ppb_ranges_t))/sizeof (int));
2991 
2992         DEBUG1("Updating ranges property for %d entries",
2993             rlen / sizeof (ppb_ranges_t) + 1);
2994 
2995         kmem_free((caddr_t)newreg, rlen+sizeof (ppb_ranges_t));
2996 
2997         kmem_free((caddr_t)ranges, rlen);
2998 
2999         return (PCICFG_SUCCESS);
3000 }
3001 
3002 static int
3003 pcicfg_update_reg_prop(dev_info_t *dip, uint32_t regvalue, uint_t reg_offset)
3004 {
3005         int             rlen;
3006         pci_regspec_t   *reg;
3007         caddr_t         newreg;
3008         uint32_t        hiword;
3009         pci_regspec_t   addition;
3010         uint32_t        size;
3011         uint_t          status;
3012 
3013         status = ddi_getlongprop(DDI_DEV_T_ANY,
3014             dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
3015 
3016         switch (status) {
3017                 case DDI_PROP_SUCCESS:
3018                 break;
3019                 case DDI_PROP_NO_MEMORY:
3020                         DEBUG0("reg present, but unable to get memory\n");
3021                         return (PCICFG_FAILURE);
3022                 default:
3023                         DEBUG0("no reg property\n");
3024                         return (PCICFG_FAILURE);
3025         }
3026 
3027         /*
3028          * Allocate memory for the existing reg(s) plus one and then
3029          * build it.
3030          */
3031         newreg = kmem_zalloc(rlen+sizeof (pci_regspec_t), KM_SLEEP);
3032 
3033         /*
3034          * Build the regspec, then add it to the existing one(s)
3035          */
3036 
3037         hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3038             PCI_REG_DEV_G(reg->pci_phys_hi),
3039             PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3040 
3041         if (reg_offset == PCI_CONF_ROM) {
3042                 size = (~(PCI_BASE_ROM_ADDR_M & regvalue))+1;
3043                 hiword |= PCI_ADDR_MEM32;
3044         } else {
3045                 size = (~(PCI_BASE_M_ADDR_M & regvalue))+1;
3046 
3047                 if ((PCI_BASE_SPACE_M & regvalue) == PCI_BASE_SPACE_MEM) {
3048                         if ((PCI_BASE_TYPE_M & regvalue) == PCI_BASE_TYPE_MEM) {
3049                                 hiword |= PCI_ADDR_MEM32;
3050                         } else if ((PCI_BASE_TYPE_M & regvalue)
3051                             == PCI_BASE_TYPE_ALL) {
3052                                 hiword |= PCI_ADDR_MEM64;
3053                         }
3054                         if (regvalue & PCI_BASE_PREF_M)
3055                                 hiword |= PCI_REG_PF_M;
3056                 } else {
3057                         hiword |= PCI_ADDR_IO;
3058                 }
3059         }
3060 
3061         addition.pci_phys_hi = hiword;
3062         addition.pci_phys_mid = 0;
3063         addition.pci_phys_low = 0;
3064         addition.pci_size_hi = 0;
3065         addition.pci_size_low = size;
3066 
3067         bcopy(reg, newreg, rlen);
3068         bcopy(&addition, newreg + rlen, sizeof (pci_regspec_t));
3069 
3070         DEBUG3("updating BAR@off %x with %x,%x\n", reg_offset, hiword, size);
3071         /*
3072          * Write out the new "reg" property
3073          */
3074         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "reg",
3075             (int *)newreg, (rlen + sizeof (pci_regspec_t))/sizeof (int));
3076 
3077         kmem_free((caddr_t)newreg, rlen+sizeof (pci_regspec_t));
3078         kmem_free((caddr_t)reg, rlen);
3079 
3080         return (PCICFG_SUCCESS);
3081 }
3082 
3083 static int
3084 pcicfg_update_assigned_prop_value(dev_info_t *dip, uint32_t size,
3085     uint32_t base, uint32_t base_hi, uint_t reg_offset)
3086 {
3087         int             rlen;
3088         pci_regspec_t   *reg;
3089         uint32_t        hiword;
3090         pci_regspec_t   addition;
3091         uint_t          status;
3092 
3093         status = ddi_getlongprop(DDI_DEV_T_ANY,
3094             dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
3095 
3096         switch (status) {
3097                 case DDI_PROP_SUCCESS:
3098                 break;
3099                 case DDI_PROP_NO_MEMORY:
3100                         DEBUG0("reg present, but unable to get memory\n");
3101                         return (PCICFG_FAILURE);
3102                 default:
3103                         /*
3104                          * Since the config space "reg" entry should have been
3105                          * created, we expect a "reg" property already
3106                          * present here.
3107                          */
3108                         DEBUG0("no reg property\n");
3109                         return (PCICFG_FAILURE);
3110         }
3111 
3112         /*
3113          * Build the regspec, then add it to the existing one(s)
3114          */
3115 
3116         hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3117             PCI_REG_DEV_G(reg->pci_phys_hi),
3118             PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3119 
3120         hiword |= PCI_REG_REL_M;
3121 
3122         if (reg_offset == PCI_CONF_ROM) {
3123                 hiword |= PCI_ADDR_MEM32;
3124 
3125                 base = PCI_BASE_ROM_ADDR_M & base;
3126         } else {
3127                 if ((PCI_BASE_SPACE_M & base) == PCI_BASE_SPACE_MEM) {
3128                         if ((PCI_BASE_TYPE_M & base) == PCI_BASE_TYPE_MEM) {
3129                                 hiword |= PCI_ADDR_MEM32;
3130                         } else if ((PCI_BASE_TYPE_M & base)
3131                             == PCI_BASE_TYPE_ALL) {
3132                                 hiword |= PCI_ADDR_MEM64;
3133                         }
3134                         if (base & PCI_BASE_PREF_M)
3135                                 hiword |= PCI_REG_PF_M;
3136 
3137                         base = PCI_BASE_M_ADDR_M & base;
3138                 } else {
3139                         hiword |= PCI_ADDR_IO;
3140 
3141                         base = PCI_BASE_IO_ADDR_M & base;
3142                         base_hi = 0;
3143                 }
3144         }
3145 
3146         addition.pci_phys_hi = hiword;
3147         addition.pci_phys_mid = base_hi;
3148         addition.pci_phys_low = base;
3149         addition.pci_size_hi = 0;
3150         addition.pci_size_low = size;
3151 
3152         DEBUG3("updating BAR@off %x with %x,%x\n", reg_offset, hiword, size);
3153 
3154         kmem_free((caddr_t)reg, rlen);
3155 
3156         return (pcicfg_update_assigned_prop(dip, &addition));
3157 }
3158 
3159 static void
3160 pcicfg_device_on(ddi_acc_handle_t config_handle)
3161 {
3162         /*
3163          * Enable memory, IO, and bus mastership
3164          * XXX should we enable parity, SERR#,
3165          * fast back-to-back, and addr. stepping?
3166          */
3167         pci_config_put16(config_handle, PCI_CONF_COMM,
3168             pci_config_get16(config_handle, PCI_CONF_COMM) | 0x7);
3169 }
3170 
3171 static void
3172 pcicfg_device_off(ddi_acc_handle_t config_handle)
3173 {
3174         /*
3175          * Disable I/O and memory traffic through the bridge
3176          */
3177         pci_config_put16(config_handle, PCI_CONF_COMM, 0x0);
3178 }
3179 
3180 /*
3181  * Setup the basic 1275 properties based on information found in the config
3182  * header of the PCI device
3183  */
3184 static int
3185 pcicfg_set_standard_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3186         uint8_t pcie_dev)
3187 {
3188         int ret;
3189         uint16_t cap_id_loc, val;
3190         uint32_t wordval;
3191         uint8_t byteval;
3192 
3193         /* These two exists only for non-bridges */
3194         if (((pci_config_get8(config_handle, PCI_CONF_HEADER) &
3195             PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) && !pcie_dev) {
3196                 byteval = pci_config_get8(config_handle, PCI_CONF_MIN_G);
3197                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3198                     "min-grant", byteval)) != DDI_SUCCESS) {
3199                         return (ret);
3200                 }
3201 
3202                 byteval = pci_config_get8(config_handle, PCI_CONF_MAX_L);
3203                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3204                     "max-latency", byteval)) != DDI_SUCCESS) {
3205                         return (ret);
3206                 }
3207         }
3208 
3209         /*
3210          * These should always exist and have the value of the
3211          * corresponding register value
3212          */
3213         val = pci_config_get16(config_handle, PCI_CONF_VENID);
3214 
3215         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vendor-id", val))
3216             != DDI_SUCCESS) {
3217                 return (ret);
3218         }
3219         val = pci_config_get16(config_handle, PCI_CONF_DEVID);
3220         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "device-id", val))
3221             != DDI_SUCCESS) {
3222                 return (ret);
3223         }
3224         byteval = pci_config_get8(config_handle, PCI_CONF_REVID);
3225         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3226             "revision-id", byteval)) != DDI_SUCCESS) {
3227                 return (ret);
3228         }
3229 
3230         wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
3231             (pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
3232 
3233         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3234             "class-code", wordval)) != DDI_SUCCESS) {
3235                 return (ret);
3236         }
3237         val = (pci_config_get16(config_handle, PCI_CONF_STAT) &
3238             PCI_STAT_DEVSELT);
3239         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3240             "devsel-speed", val)) != DDI_SUCCESS) {
3241                 return (ret);
3242         }
3243 
3244         /*
3245          * The next three are bits set in the status register.  The property is
3246          * present (but with no value other than its own existence) if the bit
3247          * is set, non-existent otherwise
3248          */
3249         if ((!pcie_dev) &&
3250             (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_FBBC)) {
3251                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3252                     "fast-back-to-back", 0)) != DDI_SUCCESS) {
3253                         return (ret);
3254                 }
3255         }
3256         if ((!pcie_dev) &&
3257             (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_66MHZ)) {
3258                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3259                     "66mhz-capable", 0)) != DDI_SUCCESS) {
3260                         return (ret);
3261                 }
3262         }
3263         if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_UDF) {
3264                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3265                     "udf-supported", 0)) != DDI_SUCCESS) {
3266                         return (ret);
3267                 }
3268         }
3269 
3270         /*
3271          * These next three are optional and are not present
3272          * if the corresponding register is zero.  If the value
3273          * is non-zero then the property exists with the value
3274          * of the register.
3275          */
3276         if ((val = pci_config_get16(config_handle, PCI_CONF_SUBVENID)) != 0) {
3277                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3278                     "subsystem-vendor-id", val)) != DDI_SUCCESS) {
3279                         return (ret);
3280                 }
3281         }
3282         if ((val = pci_config_get16(config_handle, PCI_CONF_SUBSYSID)) != 0) {
3283                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3284                     "subsystem-id", val)) != DDI_SUCCESS) {
3285                         return (ret);
3286                 }
3287         }
3288         if ((val = pci_config_get16(config_handle, PCI_CONF_CACHE_LINESZ))
3289             != 0) {
3290                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3291                     "cache-line-size", val)) != DDI_SUCCESS) {
3292                         return (ret);
3293                 }
3294         }
3295 
3296         /*
3297          * If the Interrupt Pin register is non-zero then the
3298          * interrupts property exists
3299          */
3300         if ((byteval = pci_config_get8(config_handle, PCI_CONF_IPIN)) != 0) {
3301                 /*
3302                  * If interrupt pin is non-zero,
3303                  * record the interrupt line used
3304                  */
3305                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3306                     "interrupts", byteval)) != DDI_SUCCESS) {
3307                         return (ret);
3308                 }
3309         }
3310         (void) PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_E, &cap_id_loc);
3311         if (pcie_dev && cap_id_loc != PCI_CAP_NEXT_PTR_NULL) {
3312                 val = pci_config_get16(config_handle, cap_id_loc + PCIE_PCIECAP)
3313                     & PCIE_PCIECAP_SLOT_IMPL;
3314                 /* if slot implemented, get physical slot number */
3315                 if (val) {
3316                         wordval = pci_config_get32(config_handle, cap_id_loc +
3317                             PCIE_SLOTCAP);
3318                         /* create the property only if slotnum set correctly? */
3319                         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3320                             "physical-slot#", PCIE_SLOTCAP_PHY_SLOT_NUM(
3321                             wordval))) != DDI_SUCCESS) {
3322                                 return (ret);
3323                         }
3324                 }
3325         }
3326 
3327         return (PCICFG_SUCCESS);
3328 }
3329 
3330 static int
3331 pcicfg_set_busnode_props(dev_info_t *dip, uint8_t pcie_device_type)
3332 {
3333         int ret;
3334         char device_type[8];
3335 
3336         if (pcie_device_type)
3337                 (void) strcpy(device_type, "pciex");
3338         else
3339                 (void) strcpy(device_type, "pci");
3340 
3341         if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3342             "device_type", device_type)) != DDI_SUCCESS) {
3343                 return (ret);
3344         }
3345         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3346             "#address-cells", 3)) != DDI_SUCCESS) {
3347                 return (ret);
3348         }
3349         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "#size-cells", 2))
3350             != DDI_SUCCESS) {
3351                 return (ret);
3352         }
3353         return (PCICFG_SUCCESS);
3354 }
3355 
3356 static int
3357 pcicfg_set_childnode_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3358                 uint8_t pcie_dev)
3359 {
3360 
3361         int             ret;
3362         char            *name;
3363         char            buffer[64], pprefix[8], nprefix[8];
3364         uint16_t        classcode;
3365         uint8_t         revid, pif, pclass, psubclass;
3366         char            *compat[24];
3367         int             i;
3368         int             n;
3369         uint16_t                sub_vid, sub_sid, vid, did;
3370         /* set the property prefix based on the device type */
3371         if (pcie_dev) {
3372                 (void) sprintf(pprefix, "pciex");
3373         } else
3374                 (void) sprintf(pprefix, "pci");
3375 
3376         /* set the prefix right for name property */
3377         /* x86 platforms need to go with pci for upgrade purposes */
3378         (void) sprintf(nprefix, "pci");
3379 
3380         /*
3381          * NOTE: These are for both a child and PCI-PCI bridge node
3382          */
3383         sub_vid = pci_config_get16(config_handle, PCI_CONF_SUBVENID);
3384         sub_sid = pci_config_get16(config_handle, PCI_CONF_SUBSYSID);
3385         vid = pci_config_get16(config_handle, PCI_CONF_VENID);
3386         did = pci_config_get16(config_handle, PCI_CONF_DEVID);
3387         revid = pci_config_get8(config_handle, PCI_CONF_REVID);
3388         pif = pci_config_get8(config_handle, PCI_CONF_PROGCLASS);
3389         classcode = pci_config_get16(config_handle, PCI_CONF_SUBCLASS);
3390         pclass = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
3391         psubclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
3392 
3393         if (!sub_vid)
3394                 (void) sprintf(buffer, "%s%x,%x", nprefix, vid, did);
3395         else
3396                 (void) sprintf(buffer, "%s%x,%x", nprefix, sub_vid, sub_sid);
3397 
3398         /*
3399          * In some environments, trying to use "generic" 1275 names is
3400          * not the convention.  In those cases use the name as created
3401          * above.  In all the rest of the cases, check to see if there
3402          * is a generic name first.
3403          */
3404 #ifdef _DONT_USE_1275_GENERIC_NAMES
3405         name = buffer;
3406 #else
3407         if ((name = pcicfg_get_class_name(classcode)) == NULL) {
3408                 /*
3409                  * Set name to the above fabricated name
3410                  */
3411                 name = buffer;
3412         }
3413 #endif
3414 
3415         /*
3416          * The node name field needs to be filled in with the name
3417          */
3418         if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
3419                 DEBUG0("Failed to set nodename for node\n");
3420                 return (PCICFG_FAILURE);
3421         }
3422 
3423         /*
3424          * Create the compatible property as an array of pointers
3425          * to strings.  Start with the buffer created above.
3426          */
3427         n = 0;
3428 
3429         /*
3430          * Setup 'compatible' as per the PCI2.1 bindings document.
3431          *      pci[ex]VVVV,DDDD.SSSS.ssss.RR
3432          *      pci[ex]VVVV,DDDD.SSSS.ssss
3433          *      pciSSSS.ssss  -> not created for PCIe as per PCIe bindings
3434          *      pci[ex]VVVV,DDDD.RR
3435          *      pci[ex]VVVV,DDDD
3436          *      pci[ex]class,CCSSPP
3437          *      pci[ex]class,CCSS
3438          * Add legacy entries for compatibility with legacy devices and OS
3439          * for x86.
3440          *      pciVVVV,DDDD.SSSS.ssss.RR
3441          *      pciVVVV,DDDD.SSSS.ssss
3442          *      pciSSSS.ssss
3443          *      pciVVVV,DDDD.RR
3444          *      pciVVVV,DDDD
3445          *      pciclass,CCSSPP
3446          *      pciclass,CCSS
3447          */
3448 
3449         do {
3450                 if (sub_vid) {
3451                         /* pci[ex]VVVV,DDDD.SSSS.ssss.RR */
3452                         (void) sprintf(buffer, "%s%x,%x.%x.%x.%x", pprefix, vid,
3453                             did, sub_vid, sub_sid, revid);
3454                         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3455                         (void) strcpy(compat[n++], buffer);
3456 
3457                         /* pci[ex]VVVV,DDDD.SSSS.ssss */
3458                         (void) sprintf(buffer, "%s%x,%x.%x.%x", pprefix,  vid,
3459                             did, sub_vid, sub_sid);
3460                         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3461                         (void) strcpy(compat[n++], buffer);
3462 
3463                         /* pciSSSS.ssss  -> not created for PCIe as per PCIe */
3464                         /* binding to IEEE 1275 spec.                    */
3465                         if (!pcie_dev && pcicfg_do_legacy_props) {
3466                                 (void) sprintf(buffer, "pci%x,%x", sub_vid,
3467                                     sub_sid);
3468                                 compat[n] = kmem_alloc(strlen(buffer) + 1,
3469                                     KM_SLEEP);
3470                                 (void) strcpy(compat[n++], buffer);
3471                         }
3472                 }
3473 
3474                 /* pci[ex]VVVV,DDDD.RR */
3475                 (void) sprintf(buffer, "%s%x,%x.%x", pprefix,  vid, did, revid);
3476                 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3477                 (void) strcpy(compat[n++], buffer);
3478 
3479                 /* pci[ex]VVVV,DDDD */
3480                 (void) sprintf(buffer, "%s%x,%x", pprefix, vid, did);
3481                 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3482                 (void) strcpy(compat[n++], buffer);
3483 
3484                 /* pci[ex]class,CCSSPP */
3485                 (void) sprintf(buffer, "%sclass,%02x%02x%02x", pprefix, pclass,
3486                     psubclass, pif);
3487                 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3488                 (void) strcpy(compat[n++], buffer);
3489 
3490                 /* pci[ex]class,CCSS */
3491                 (void) sprintf(buffer, "%sclass,%04x", pprefix, classcode);
3492                 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3493                 (void) strcpy(compat[n++], buffer);
3494 
3495                 if (!pcie_dev)
3496                         break;
3497 
3498                 /* also add compatible names using "pci" prefix */
3499                 (void) sprintf(pprefix, "pci");
3500                 pcie_dev = 0;
3501 
3502         } while (pcicfg_do_legacy_props);
3503 
3504         ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, "compatible",
3505             (char **)compat, n);
3506 
3507         for (i = 0; i < n; i++) {
3508                 kmem_free(compat[i], strlen(compat[i]) + 1);
3509         }
3510 
3511         return (ret);
3512 }
3513 
3514 /*
3515  * Program the bus numbers into the bridge
3516  */
3517 static void
3518 pcicfg_set_bus_numbers(ddi_acc_handle_t config_handle,
3519 uint_t primary, uint_t secondary, uint_t subordinate)
3520 {
3521         DEBUG3("Setting bridge bus-range %d,%d,%d\n", primary, secondary,
3522             subordinate);
3523         /*
3524          * Primary bus#
3525          */
3526         pci_config_put8(config_handle, PCI_BCNF_PRIBUS, primary);
3527 
3528         /*
3529          * Secondary bus#
3530          */
3531         pci_config_put8(config_handle, PCI_BCNF_SECBUS, secondary);
3532 
3533         /*
3534          * Set the subordinate bus number to ff in order to pass through any
3535          * type 1 cycle with a bus number higher than the secondary bus#
3536          */
3537         pci_config_put8(config_handle, PCI_BCNF_SUBBUS, subordinate);
3538 }
3539 
3540 /*
3541  * Put bridge registers into initial state
3542  */
3543 static void
3544 pcicfg_setup_bridge(pcicfg_phdl_t *entry,
3545         ddi_acc_handle_t handle)
3546 {
3547         /*
3548          * The highest bus seen during probing is the max-subordinate bus
3549          */
3550         pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus);
3551 
3552         /*
3553          * Reset the secondary bus
3554          */
3555         pci_config_put16(handle, PCI_BCNF_BCNTRL,
3556             pci_config_get16(handle, PCI_BCNF_BCNTRL) | 0x40);
3557         drv_usecwait(1000);
3558         pci_config_put16(handle, PCI_BCNF_BCNTRL,
3559             pci_config_get16(handle, PCI_BCNF_BCNTRL) & ~0x40);
3560         drv_usecwait(1000);
3561 
3562         /*
3563          * Program the memory base register with the
3564          * start of the memory range
3565          */
3566         pci_config_put16(handle, PCI_BCNF_MEM_BASE,
3567             PCICFG_HIWORD(PCICFG_LOADDR(entry->memory_last)));
3568 
3569         /*
3570          * Program the I/O base register with the start of the I/O range
3571          */
3572         pci_config_put8(handle, PCI_BCNF_IO_BASE_LOW,
3573             PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(entry->io_last))));
3574         pci_config_put16(handle, PCI_BCNF_IO_BASE_HI,
3575             PCICFG_HIWORD(PCICFG_LOADDR(entry->io_last)));
3576 
3577         /*
3578          * Program the PF memory base register with the start of
3579          * PF memory range
3580          */
3581         pci_config_put16(handle, PCI_BCNF_PF_BASE_LOW,
3582             PCICFG_HIWORD(PCICFG_LOADDR(entry->pf_memory_last)));
3583         pci_config_put32(handle, PCI_BCNF_PF_BASE_HIGH,
3584             PCICFG_HIADDR(entry->pf_memory_last));
3585 
3586         /*
3587          * Clear status bits
3588          */
3589         pci_config_put16(handle, PCI_BCNF_SEC_STATUS, 0xffff);
3590 
3591         /*
3592          * Needs to be set to this value
3593          */
3594         pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
3595 
3596         /*
3597          * XXX - may be delay should be used since noone configures
3598          * devices in the interrupt context
3599          */
3600         drv_usecwait(pcicfg_sec_reset_delay);   /* 1 sec wait */
3601 }
3602 
3603 static void
3604 pcicfg_update_bridge(pcicfg_phdl_t *entry,
3605         ddi_acc_handle_t handle)
3606 {
3607         uint_t length;
3608 
3609         /*
3610          * Program the memory limit register with the end of the memory range
3611          */
3612 
3613         DEBUG1("DOWN ROUNDED ===>[0x%x]\n",
3614             PCICFG_ROUND_DOWN(entry->memory_last, PCICFG_MEMGRAN));
3615 
3616         pci_config_put16(handle, PCI_BCNF_MEM_LIMIT,
3617             PCICFG_HIWORD(PCICFG_LOADDR(
3618             PCICFG_ROUND_DOWN(entry->memory_last, PCICFG_MEMGRAN))));
3619         /*
3620          * Since this is a bridge, the rest of this range will
3621          * be responded to by the bridge.  We have to round up
3622          * so no other device claims it.
3623          */
3624         if ((length = (PCICFG_ROUND_UP(entry->memory_last, PCICFG_MEMGRAN)
3625             - entry->memory_last)) > 0) {
3626                 (void) pcicfg_get_mem(entry, length, NULL);
3627                 DEBUG1("Added [0x%x]at the top of the bridge (mem)\n", length);
3628         }
3629 
3630         /*
3631          * Program the PF memory limit register with the end of the memory range
3632          */
3633 
3634         DEBUG1("DOWN ROUNDED ===>[0x%x]\n",
3635             PCICFG_ROUND_DOWN(entry->pf_memory_last, PCICFG_MEMGRAN));
3636 
3637         pci_config_put16(handle, PCI_BCNF_PF_LIMIT_LOW,
3638             PCICFG_HIWORD(PCICFG_LOADDR(PCICFG_ROUND_DOWN(
3639             entry->pf_memory_last, PCICFG_MEMGRAN))));
3640         pci_config_put32(handle, PCI_BCNF_PF_LIMIT_HIGH, PCICFG_HIADDR(
3641             PCICFG_ROUND_DOWN(entry->pf_memory_last, PCICFG_MEMGRAN)));
3642         if ((length = (PCICFG_ROUND_UP(entry->pf_memory_last, PCICFG_MEMGRAN)
3643             - entry->pf_memory_last)) > 0) {
3644                 (void) pcicfg_get_pf_mem(entry, length, NULL);
3645                 DEBUG1("Added [0x%x]at the top of the bridge (PF mem)\n",
3646                     length);
3647         }
3648 
3649         /*
3650          * Program the I/O limit register with the end of the I/O range
3651          */
3652         pci_config_put8(handle, PCI_BCNF_IO_LIMIT_LOW,
3653             PCICFG_HIBYTE(PCICFG_LOWORD(
3654             PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last, PCICFG_IOGRAN)))));
3655 
3656         pci_config_put16(handle, PCI_BCNF_IO_LIMIT_HI, PCICFG_HIWORD(
3657             PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last, PCICFG_IOGRAN))));
3658 
3659         /*
3660          * Same as above for I/O space. Since this is a
3661          * bridge, the rest of this range will be responded
3662          * to by the bridge.  We have to round up so no
3663          * other device claims it.
3664          */
3665         if ((length = (PCICFG_ROUND_UP(entry->io_last, PCICFG_IOGRAN)
3666             - entry->io_last)) > 0) {
3667                 (void) pcicfg_get_io(entry, length, NULL);
3668                 DEBUG1("Added [0x%x]at the top of the bridge (I/O)\n", length);
3669         }
3670 }
3671 
3672 static int
3673 pcicfg_probe_children(dev_info_t *parent, uint_t bus, uint_t device,
3674     uint_t func, uint_t *highest_bus, pcicfg_flags_t flags, boolean_t is_pcie)
3675 {
3676         dev_info_t              *new_child;
3677         ddi_acc_handle_t        config_handle;
3678         uint8_t                 header_type, pcie_dev = 0;
3679         int                     ret = PCICFG_FAILURE;
3680 
3681         /*
3682          * This node will be put immediately below
3683          * "parent". Allocate a blank device node.  It will either
3684          * be filled in or freed up based on further probing.
3685          */
3686 
3687         ndi_devi_alloc_sleep(parent, DEVI_PSEUDO_NEXNAME,
3688             (pnode_t)DEVI_SID_NODEID, &new_child);
3689 
3690         if (pcicfg_add_config_reg(new_child, bus, device, func)
3691             != DDI_SUCCESS) {
3692                 DEBUG0("pcicfg_probe_children():Failed to add candidate REG\n");
3693                 goto failedconfig;
3694         }
3695 
3696         if ((ret = pcicfg_config_setup(new_child, &config_handle))
3697             != PCICFG_SUCCESS) {
3698                 if (ret == PCICFG_NODEVICE) {
3699                         (void) ndi_devi_free(new_child);
3700                         return (ret);
3701                 }
3702                 DEBUG0("pcicfg_probe_children():"
3703                 "Failed to setup config space\n");
3704                 goto failedconfig;
3705         }
3706 
3707         if (is_pcie)
3708                 (void) pcie_init_bus(new_child, PCI_GETBDF(bus, device, func),
3709                     PCIE_BUS_INITIAL);
3710 
3711         /*
3712          * As soon as we have access to config space,
3713          * turn off device. It will get turned on
3714          * later (after memory is assigned).
3715          */
3716         (void) pcicfg_device_off(config_handle);
3717 
3718         /* check if we are PCIe device */
3719         if (pcicfg_pcie_dev(new_child, config_handle) == DDI_SUCCESS) {
3720                 DEBUG0("PCIe device detected\n");
3721                 pcie_dev = 1;
3722         }
3723 
3724         /*
3725          * Set 1275 properties common to all devices
3726          */
3727         if (pcicfg_set_standard_props(new_child, config_handle, pcie_dev)
3728             != PCICFG_SUCCESS) {
3729                 DEBUG0("Failed to set standard properties\n");
3730                 goto failedchild;
3731         }
3732 
3733         /*
3734          * Child node properties  NOTE: Both for PCI-PCI bridge and child node
3735          */
3736         if (pcicfg_set_childnode_props(new_child, config_handle, pcie_dev)
3737             != PCICFG_SUCCESS) {
3738                 goto failedchild;
3739         }
3740 
3741         header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
3742 
3743         /*
3744          * If this is not a multi-function card only probe function zero.
3745          */
3746         if ((!(header_type & PCI_HEADER_MULTI)) && (func != 0)) {
3747 
3748                 ret = PCICFG_NODEVICE;
3749                 goto failedchild;
3750         }
3751 
3752         /*
3753          * Attach the child to its parent
3754          */
3755         (void) i_ndi_config_node(new_child, DS_LINKED, 0);
3756 
3757         DEVI_SET_PCI(new_child);
3758 
3759         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
3760 
3761                 DEBUG3("--Bridge found bus [0x%x] device[0x%x] func [0x%x]\n",
3762                     bus, device, func);
3763 
3764                 /* Only support read-only probe for leaf device */
3765                 if (flags & PCICFG_FLAG_READ_ONLY)
3766                         goto failedchild;
3767 
3768                 ret = pcicfg_probe_bridge(new_child, config_handle, bus,
3769                     highest_bus, is_pcie);
3770                 if (ret != PCICFG_SUCCESS) {
3771                         (void) pcicfg_free_bridge_resources(new_child);
3772                         goto failedchild;
3773                 }
3774 
3775         } else {
3776 
3777                 DEBUG3("--Leaf device found bus [0x%x] device"
3778                     "[0x%x] func [0x%x]\n", bus, device, func);
3779 
3780                 if (flags & PCICFG_FLAG_READ_ONLY) {
3781                         /*
3782                          * with read-only probe, don't do any resource
3783                          * allocation, just read the BARs and update props.
3784                          */
3785                         ret = pcicfg_populate_props_from_bar(new_child,
3786                             config_handle);
3787                         if (ret != PCICFG_SUCCESS)
3788                                 goto failedchild;
3789 
3790                         /*
3791                          * now allocate the resources, just remove the
3792                          * resources from the parent busra pool.
3793                          */
3794                         ret = pcicfg_device_assign_readonly(new_child);
3795                         if (ret != PCICFG_SUCCESS) {
3796                                 (void) pcicfg_free_device_resources(new_child);
3797                                 goto failedchild;
3798                         }
3799 
3800                 } else {
3801                         /*
3802                          * update "reg" property by sizing the BARs.
3803                          */
3804                         ret = pcicfg_populate_reg_props(new_child,
3805                             config_handle);
3806                         if (ret != PCICFG_SUCCESS)
3807                                 goto failedchild;
3808 
3809                         /* now allocate & program the resources */
3810                         ret = pcicfg_device_assign(new_child);
3811                         if (ret != PCICFG_SUCCESS) {
3812                                 (void) pcicfg_free_device_resources(new_child);
3813                                 goto failedchild;
3814                         }
3815                 }
3816 
3817                 (void) ndi_devi_bind_driver(new_child, 0);
3818         }
3819 
3820         (void) pcicfg_config_teardown(&config_handle);
3821 
3822         /*
3823          * Properties have been setted up, so initialize the remaining
3824          * bus_t fields
3825          */
3826         if (is_pcie)
3827                 (void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
3828 
3829         return (PCICFG_SUCCESS);
3830 
3831 failedchild:
3832         /*
3833          * XXX check if it should be taken offline (if online)
3834          */
3835         (void) pcicfg_config_teardown(&config_handle);
3836 
3837         if (is_pcie)
3838                 pcie_fini_bus(new_child, PCIE_BUS_FINAL);
3839 
3840 failedconfig:
3841 
3842         (void) ndi_devi_free(new_child);
3843         return (ret);
3844 }
3845 
3846 /*
3847  * Sizing the BARs and update "reg" property
3848  */
3849 static int
3850 pcicfg_populate_reg_props(dev_info_t *new_child,
3851     ddi_acc_handle_t config_handle)
3852 {
3853         int             i;
3854         uint32_t        request;
3855 
3856         i = PCI_CONF_BASE0;
3857 
3858         while (i <= PCI_CONF_BASE5) {
3859 
3860                 pci_config_put32(config_handle, i, 0xffffffff);
3861 
3862                 request = pci_config_get32(config_handle, i);
3863                 /*
3864                  * If its a zero length, don't do
3865                  * any programming.
3866                  */
3867                 if (request != 0) {
3868                         /*
3869                          * Add to the "reg" property
3870                          */
3871                         if (pcicfg_update_reg_prop(new_child,
3872                             request, i) != PCICFG_SUCCESS) {
3873                                 goto failedchild;
3874                         }
3875                 } else {
3876                         DEBUG1("BASE register [0x%x] asks for "
3877                             "[0x0]=[0x0](32)\n", i);
3878                         i += 4;
3879                         continue;
3880                 }
3881 
3882                 /*
3883                  * Increment by eight if it is 64 bit address space
3884                  */
3885                 if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
3886                         DEBUG3("BASE register [0x%x] asks for "
3887                             "[0x%x]=[0x%x] (64)\n",
3888                             i, request, (~(PCI_BASE_M_ADDR_M & request))+1);
3889                         i += 8;
3890                 } else {
3891                         DEBUG3("BASE register [0x%x] asks for "
3892                             "[0x%x]=[0x%x](32)\n",
3893                             i, request, (~(PCI_BASE_M_ADDR_M & request))+1);
3894                         i += 4;
3895                 }
3896         }
3897 
3898         /*
3899          * Get the ROM size and create register for it
3900          */
3901         pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
3902 
3903         request = pci_config_get32(config_handle, PCI_CONF_ROM);
3904         /*
3905          * If its a zero length, don't do
3906          * any programming.
3907          */
3908 
3909         if (request != 0) {
3910                 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
3911                     PCI_CONF_ROM, request,
3912                     (~(PCI_BASE_ROM_ADDR_M & request)) + 1);
3913                 /*
3914                  * Add to the "reg" property
3915                  */
3916                 if (pcicfg_update_reg_prop(new_child, request, PCI_CONF_ROM)
3917                     != PCICFG_SUCCESS) {
3918                         goto failedchild;
3919                 }
3920         }
3921 
3922         return (PCICFG_SUCCESS);
3923 
3924 failedchild:
3925         return (PCICFG_FAILURE);
3926 }
3927 
3928 /*
3929  * Read the BARs and update properties. Used in virtual hotplug.
3930  */
3931 static int
3932 pcicfg_populate_props_from_bar(dev_info_t *new_child,
3933     ddi_acc_handle_t config_handle)
3934 {
3935         uint32_t request, base, base_hi, size;
3936         int i;
3937 
3938         i = PCI_CONF_BASE0;
3939 
3940         while (i <= PCI_CONF_BASE5) {
3941                 /*
3942                  * determine the size of the address space
3943                  */
3944                 base = pci_config_get32(config_handle, i);
3945                 pci_config_put32(config_handle, i, 0xffffffff);
3946                 request = pci_config_get32(config_handle, i);
3947                 pci_config_put32(config_handle, i, base);
3948 
3949                 /*
3950                  * If its a zero length, don't do any programming.
3951                  */
3952                 if (request != 0) {
3953                         /*
3954                          * Add to the "reg" property
3955                          */
3956                         if (pcicfg_update_reg_prop(new_child,
3957                             request, i) != PCICFG_SUCCESS) {
3958                                 goto failedchild;
3959                         }
3960 
3961                         if ((PCI_BASE_SPACE_IO & request) == 0 &&
3962                             (PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
3963                                 base_hi = pci_config_get32(config_handle, i+4);
3964                         } else {
3965                                 base_hi = 0;
3966                         }
3967                         /*
3968                          * Add to "assigned-addresses" property
3969                          */
3970                         size = (~(PCI_BASE_M_ADDR_M & request))+1;
3971                         if (pcicfg_update_assigned_prop_value(new_child,
3972                             size, base, base_hi, i) != PCICFG_SUCCESS) {
3973                                 goto failedchild;
3974                         }
3975                 } else {
3976                         DEBUG1("BASE register [0x%x] asks for [0x0]=[0x0]"
3977                             "(32)\n", i);
3978                         i += 4;
3979                         continue;
3980                 }
3981 
3982                 /*
3983                  * Increment by eight if it is 64 bit address space
3984                  */
3985                 if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
3986                         DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]"
3987                             "(64)\n", i, request,
3988                             (~(PCI_BASE_M_ADDR_M & request)) + 1);
3989                         i += 8;
3990                 } else {
3991                         DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]"
3992                             "(32)\n", i, request,
3993                             (~(PCI_BASE_M_ADDR_M & request)) + 1);
3994                         i += 4;
3995                 }
3996         }
3997 
3998         /*
3999          * Get the ROM size and create register for it
4000          */
4001         base = pci_config_get32(config_handle, PCI_CONF_ROM);
4002         pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
4003         request = pci_config_get32(config_handle, PCI_CONF_ROM);
4004         pci_config_put32(config_handle, PCI_CONF_ROM, base);
4005 
4006         /*
4007          * If its a zero length, don't do
4008          * any programming.
4009          */
4010         if (request != 0) {
4011                 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4012                     PCI_CONF_ROM, request,
4013                     (~(PCI_BASE_ROM_ADDR_M & request)) + 1);
4014                 /*
4015                  * Add to the "reg" property
4016                  */
4017                 if (pcicfg_update_reg_prop(new_child, request, PCI_CONF_ROM)
4018                     != PCICFG_SUCCESS) {
4019                         goto failedchild;
4020                 }
4021                 /*
4022                  * Add to "assigned-addresses" property
4023                  */
4024                 size = (~(PCI_BASE_ROM_ADDR_M & request))+1;
4025                 if (pcicfg_update_assigned_prop_value(new_child, size,
4026                     base, 0, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4027                         goto failedchild;
4028                 }
4029         }
4030 
4031         return (PCICFG_SUCCESS);
4032 
4033 failedchild:
4034         return (PCICFG_FAILURE);
4035 }
4036 
4037 static int
4038 pcicfg_probe_bridge(dev_info_t *new_child, ddi_acc_handle_t h, uint_t bus,
4039     uint_t *highest_bus, boolean_t is_pcie)
4040 {
4041         uint64_t next_bus;
4042         uint_t new_bus, num_slots;
4043         ndi_ra_request_t req;
4044         int rval, i, j;
4045         uint64_t mem_answer, io_answer, mem_base, io_base, mem_alen, io_alen;
4046         uint64_t pf_mem_answer, pf_mem_base, pf_mem_alen;
4047         uint64_t mem_size, io_size, pf_mem_size;
4048         uint64_t mem_end, pf_mem_end, io_end;
4049         uint64_t round_answer, round_len;
4050         ppb_ranges_t range[PCICFG_RANGE_LEN];
4051         int bus_range[2];
4052         pcicfg_phdl_t phdl;
4053         int count;
4054         uint64_t pcibus_base, pcibus_alen;
4055         uint64_t max_bus;
4056         uint8_t pcie_device_type = 0;
4057         uint_t pf_mem_supported = 0;
4058         dev_info_t *new_device;
4059         int trans_device;
4060         int ari_mode = B_FALSE;
4061         int max_function = PCI_MAX_FUNCTIONS;
4062 
4063         io_answer = io_base = io_alen = io_size = 0;
4064         pf_mem_answer = pf_mem_base = pf_mem_size = pf_mem_alen = 0;
4065 
4066         /*
4067          * Set "device_type" to "pci", the actual type will be set later
4068          * by pcicfg_set_busnode_props() below. This is needed as the
4069          * pcicfg_ra_free() below would update "available" property based
4070          * on "device_type".
4071          *
4072          * This code can be removed later after PCI configurator is changed
4073          * to use PCIRM, which automatically update properties upon allocation
4074          * and free, at that time we'll be able to remove the code inside
4075          * ndi_ra_alloc/free() which currently updates "available" property
4076          * for pci/pcie devices in pcie fabric.
4077          */
4078         if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
4079             "device_type", "pci") != DDI_SUCCESS) {
4080                 DEBUG0("Failed to set \"device_type\" props\n");
4081                 return (PCICFG_FAILURE);
4082         }
4083 
4084         /*
4085          * setup resource maps for the bridge node
4086          */
4087         if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_PCI_BUSNUM)
4088             == NDI_FAILURE) {
4089                 DEBUG0("Can not setup resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
4090                 rval = PCICFG_FAILURE;
4091                 goto cleanup;
4092         }
4093         if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
4094                 DEBUG0("Can not setup resource map - NDI_RA_TYPE_MEM\n");
4095                 rval = PCICFG_FAILURE;
4096                 goto cleanup;
4097         }
4098         if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_IO) == NDI_FAILURE) {
4099                 DEBUG0("Can not setup resource map - NDI_RA_TYPE_IO\n");
4100                 rval = PCICFG_FAILURE;
4101                 goto cleanup;
4102         }
4103         if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_PCI_PREFETCH_MEM) ==
4104             NDI_FAILURE) {
4105                 DEBUG0("Can not setup resource map -"
4106                     " NDI_RA_TYPE_PCI_PREFETCH_MEM\n");
4107                 rval = PCICFG_FAILURE;
4108                 goto cleanup;
4109         }
4110 
4111         /*
4112          * Allocate bus range pool for the bridge.
4113          */
4114         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4115         req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4116         req.ra_boundbase = 0;
4117         req.ra_boundlen = req.ra_len = (PCI_MAX_BUS_NUM -1);
4118         req.ra_align_mask = 0;  /* no alignment needed */
4119 
4120         rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4121             &pcibus_base, &pcibus_alen, NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4122 
4123         if (rval != NDI_SUCCESS) {
4124                 if (rval == NDI_RA_PARTIAL_REQ) {
4125                         /*EMPTY*/
4126                         DEBUG0("NDI_RA_PARTIAL_REQ returned for bus range\n");
4127                 } else {
4128                         DEBUG0(
4129                             "Failed to allocate bus range for bridge\n");
4130                         rval = PCICFG_NORESRC;
4131                         goto cleanup;
4132                 }
4133         }
4134 
4135         DEBUG2("Bus Range Allocated [base=%d] [len=%d]\n",
4136             pcibus_base, pcibus_alen);
4137 
4138         /*
4139          * Put available bus range into the pool.
4140          * Take the first one for this bridge to use and don't give
4141          * to child.
4142          */
4143         (void) ndi_ra_free(new_child, pcibus_base+1, pcibus_alen-1,
4144             NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4145 
4146         next_bus = pcibus_base;
4147         max_bus = pcibus_base + pcibus_alen - 1;
4148 
4149         new_bus = next_bus;
4150 
4151         DEBUG1("NEW bus found  ->[%d]\n", new_bus);
4152 
4153         /* Keep track of highest bus for subordinate bus programming */
4154         *highest_bus = new_bus;
4155 
4156         /*
4157          * Allocate (non-prefetchable) Memory Space for Bridge
4158          */
4159         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4160         req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4161         req.ra_boundbase = 0;
4162         /*
4163          * limit the boundlen,len to a 32b quantity. It should be Ok to
4164          * lose alignment-based-size of resource due to this.
4165          */
4166         req.ra_boundlen = PCICFG_4GIG_LIMIT;
4167         req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
4168         req.ra_align_mask =
4169             PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
4170 
4171         rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4172             &mem_answer, &mem_alen,  NDI_RA_TYPE_MEM, NDI_RA_PASS);
4173 
4174         if (rval != NDI_SUCCESS) {
4175                 if (rval == NDI_RA_PARTIAL_REQ) {
4176                         /*EMPTY*/
4177                         DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
4178                 } else {
4179                         DEBUG0(
4180                             "Failed to allocate memory for bridge\n");
4181                         rval = PCICFG_NORESRC;
4182                         goto cleanup;
4183                 }
4184         }
4185 
4186         DEBUG3("Bridge Memory Allocated [0x%x.%x] len [0x%x]\n",
4187             PCICFG_HIADDR(mem_answer),
4188             PCICFG_LOADDR(mem_answer),
4189             mem_alen);
4190 
4191         /*
4192          * Put available memory into the pool.
4193          */
4194         (void) ndi_ra_free(new_child, mem_answer, mem_alen, NDI_RA_TYPE_MEM,
4195             NDI_RA_PASS);
4196 
4197         mem_base = mem_answer;
4198 
4199         /*
4200          * Allocate I/O Space for Bridge
4201          */
4202         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4203         req.ra_align_mask = PCICFG_IOGRAN - 1; /* 4k alignment */
4204         req.ra_boundbase = 0;
4205         req.ra_boundlen = PCICFG_4GIG_LIMIT;
4206         req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4207         req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
4208 
4209         rval = ndi_ra_alloc(ddi_get_parent(new_child), &req, &io_answer,
4210             &io_alen, NDI_RA_TYPE_IO, NDI_RA_PASS);
4211 
4212         if (rval != NDI_SUCCESS) {
4213                 if (rval == NDI_RA_PARTIAL_REQ) {
4214                         /*EMPTY*/
4215                         DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
4216                 } else {
4217                         DEBUG0("Failed to allocate io space for bridge\n");
4218                         /* i/o space is an optional requirement so continue */
4219                 }
4220         }
4221 
4222         DEBUG3("Bridge IO Space Allocated [0x%x.%x] len [0x%x]\n",
4223             PCICFG_HIADDR(io_answer), PCICFG_LOADDR(io_answer), io_alen);
4224 
4225         /*
4226          * Put available I/O into the pool.
4227          */
4228         (void) ndi_ra_free(new_child, io_answer, io_alen, NDI_RA_TYPE_IO,
4229             NDI_RA_PASS);
4230 
4231         io_base = io_answer;
4232 
4233         /*
4234          * Check if the bridge supports Prefetchable memory range.
4235          * If it does, then we setup PF memory range for the bridge.
4236          * Otherwise, we skip the step of setting up PF memory
4237          * range for it. This could cause config operation to
4238          * fail if any devices under the bridge need PF memory.
4239          */
4240         /* write a non zero value to the PF BASE register */
4241         pci_config_put16(h, PCI_BCNF_PF_BASE_LOW, 0xfff0);
4242         /* if the read returns zero then PF range is not supported */
4243         if (pci_config_get16(h, PCI_BCNF_PF_BASE_LOW) == 0) {
4244                 /* bridge doesn't support PF memory range */
4245                 goto pf_setup_end;
4246         } else {
4247                 pf_mem_supported = 1;
4248                 /* reset the PF BASE register */
4249                 pci_config_put16(h, PCI_BCNF_PF_BASE_LOW, 0);
4250         }
4251 
4252         /*
4253          * Bridge supports PF mem range; Allocate PF Memory Space for it.
4254          *
4255          * Note: Both non-prefetchable and prefetchable memory space
4256          * allocations are made within 32bit space. Currently, BIOSs
4257          * allocate device memory for PCI devices within the 32bit space
4258          * so this will not be a problem.
4259          */
4260         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4261         req.ra_flags = NDI_RA_ALLOC_PARTIAL_OK | NDI_RA_ALLOC_BOUNDED;
4262         req.ra_boundbase = 0;
4263         req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
4264         req.ra_align_mask =
4265             PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
4266 
4267         rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4268             &pf_mem_answer, &pf_mem_alen,  NDI_RA_TYPE_PCI_PREFETCH_MEM,
4269             NDI_RA_PASS);
4270 
4271         if (rval != NDI_SUCCESS) {
4272                 if (rval == NDI_RA_PARTIAL_REQ) {
4273                         /*EMPTY*/
4274                         DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
4275                 } else {
4276                         DEBUG0(
4277                             "Failed to allocate PF memory for bridge\n");
4278                         /* PF mem is an optional requirement so continue */
4279                 }
4280         }
4281 
4282         DEBUG3("Bridge PF Memory Allocated [0x%x.%x] len [0x%x]\n",
4283             PCICFG_HIADDR(pf_mem_answer),
4284             PCICFG_LOADDR(pf_mem_answer),
4285             pf_mem_alen);
4286 
4287         /*
4288          * Put available PF memory into the pool.
4289          */
4290         (void) ndi_ra_free(new_child, pf_mem_answer, pf_mem_alen,
4291             NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
4292 
4293         pf_mem_base = pf_mem_answer;
4294 
4295         /*
4296          * Program the PF memory base register with the
4297          * start of the memory range
4298          */
4299         pci_config_put16(h, PCI_BCNF_PF_BASE_LOW,
4300             PCICFG_HIWORD(PCICFG_LOADDR(pf_mem_answer)));
4301         pci_config_put32(h, PCI_BCNF_PF_BASE_HIGH,
4302             PCICFG_HIADDR(pf_mem_answer));
4303 
4304         /*
4305          * Program the PF memory limit register with the
4306          * end of the memory range.
4307          */
4308         pci_config_put16(h, PCI_BCNF_PF_LIMIT_LOW,
4309             PCICFG_HIWORD(PCICFG_LOADDR(
4310             PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4311             PCICFG_MEMGRAN) - 1)));
4312         pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH,
4313             PCICFG_HIADDR(PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4314             PCICFG_MEMGRAN) - 1));
4315 
4316         /*
4317          * Allocate the chunk of PF memory (if any) not programmed into the
4318          * bridge because of the round down.
4319          */
4320         if (PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen), PCICFG_MEMGRAN)
4321             != (pf_mem_answer + pf_mem_alen)) {
4322                 DEBUG0("Need to allocate Memory round off chunk\n");
4323                 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4324                 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
4325                 req.ra_addr = PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4326                     PCICFG_MEMGRAN);
4327                 req.ra_len =  (pf_mem_answer + pf_mem_alen) -
4328                     (PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4329                     PCICFG_MEMGRAN));
4330 
4331                 (void) ndi_ra_alloc(new_child, &req,
4332                     &round_answer, &round_len,  NDI_RA_TYPE_PCI_PREFETCH_MEM,
4333                     NDI_RA_PASS);
4334         }
4335 
4336 pf_setup_end:
4337 
4338         /*
4339          * Program the memory base register with the
4340          * start of the memory range
4341          */
4342         pci_config_put16(h, PCI_BCNF_MEM_BASE,
4343             PCICFG_HIWORD(PCICFG_LOADDR(mem_answer)));
4344 
4345         /*
4346          * Program the memory limit register with the
4347          * end of the memory range.
4348          */
4349 
4350         pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
4351             PCICFG_HIWORD(PCICFG_LOADDR(
4352             PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN) - 1)));
4353 
4354         /*
4355          * Allocate the chunk of memory (if any) not programmed into the
4356          * bridge because of the round down.
4357          */
4358         if (PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN)
4359             != (mem_answer + mem_alen)) {
4360                 DEBUG0("Need to allocate Memory round off chunk\n");
4361                 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4362                 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
4363                 req.ra_addr = PCICFG_ROUND_DOWN((mem_answer + mem_alen),
4364                     PCICFG_MEMGRAN);
4365                 req.ra_len =  (mem_answer + mem_alen) -
4366                     (PCICFG_ROUND_DOWN((mem_answer + mem_alen),
4367                     PCICFG_MEMGRAN));
4368 
4369                 (void) ndi_ra_alloc(new_child, &req,
4370                     &round_answer, &round_len,  NDI_RA_TYPE_MEM, NDI_RA_PASS);
4371         }
4372 
4373         /*
4374          * Program the I/O Space Base
4375          */
4376         pci_config_put8(h, PCI_BCNF_IO_BASE_LOW,
4377             PCICFG_HIBYTE(PCICFG_LOWORD(
4378             PCICFG_LOADDR(io_answer))));
4379 
4380         pci_config_put16(h, PCI_BCNF_IO_BASE_HI,
4381             PCICFG_HIWORD(PCICFG_LOADDR(io_answer)));
4382 
4383         /*
4384          * Program the I/O Space Limit
4385          */
4386         pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
4387             PCICFG_HIBYTE(PCICFG_LOWORD(
4388             PCICFG_LOADDR(PCICFG_ROUND_DOWN(io_answer + io_alen,
4389             PCICFG_IOGRAN)))) - 1);
4390 
4391         pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
4392             PCICFG_HIWORD(PCICFG_LOADDR(
4393             PCICFG_ROUND_DOWN(io_answer + io_alen, PCICFG_IOGRAN)))
4394             - 1);
4395 
4396         /*
4397          * Allocate the chunk of I/O (if any) not programmed into the
4398          * bridge because of the round down.
4399          */
4400         if (PCICFG_ROUND_DOWN((io_answer + io_alen), PCICFG_IOGRAN)
4401             != (io_answer + io_alen)) {
4402                 DEBUG0("Need to allocate I/O round off chunk\n");
4403                 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4404                 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
4405                 req.ra_addr = PCICFG_ROUND_DOWN((io_answer + io_alen),
4406                     PCICFG_IOGRAN);
4407                 req.ra_len =  (io_answer + io_alen) -
4408                     (PCICFG_ROUND_DOWN((io_answer + io_alen),
4409                     PCICFG_IOGRAN));
4410 
4411                 (void) ndi_ra_alloc(new_child, &req,
4412                     &round_answer, &round_len,  NDI_RA_TYPE_IO, NDI_RA_PASS);
4413         }
4414 
4415         (void) pcicfg_set_bus_numbers(h, bus, new_bus, max_bus);
4416 
4417         /*
4418          * Setup "ranges" and "bus-range" properties before onlining
4419          * the bridge.
4420          */
4421         bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
4422 
4423         range[0].child_high = range[0].parent_high |= (PCI_REG_REL_M |
4424             PCI_ADDR_IO);
4425         range[0].child_low = range[0].parent_low = io_base;
4426         range[1].child_high = range[1].parent_high |=
4427             (PCI_REG_REL_M | PCI_ADDR_MEM32);
4428         range[1].child_low = range[1].parent_low = mem_base;
4429         range[2].child_high = range[2].parent_high |=
4430             (PCI_REG_REL_M | PCI_ADDR_MEM64 | PCI_REG_PF_M);
4431         range[2].child_low = range[2].parent_low = pf_mem_base;
4432 
4433         range[0].size_low = io_alen;
4434         (void) pcicfg_update_ranges_prop(new_child, &range[0]);
4435         range[1].size_low = mem_alen;
4436         (void) pcicfg_update_ranges_prop(new_child, &range[1]);
4437         range[2].size_low = pf_mem_alen;
4438         (void) pcicfg_update_ranges_prop(new_child, &range[2]);
4439 
4440         bus_range[0] = new_bus;
4441         bus_range[1] = max_bus;
4442         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
4443             "bus-range", bus_range, 2);
4444 
4445         /*
4446          * Reset the secondary bus
4447          */
4448         pci_config_put16(h, PCI_BCNF_BCNTRL,
4449             pci_config_get16(h, PCI_BCNF_BCNTRL) | 0x40);
4450 
4451         drv_usecwait(100);
4452 
4453         pci_config_put16(h, PCI_BCNF_BCNTRL,
4454             pci_config_get16(h, PCI_BCNF_BCNTRL) & ~0x40);
4455 
4456         /*
4457          * Clear status bits
4458          */
4459         pci_config_put16(h, PCI_BCNF_SEC_STATUS, 0xffff);
4460 
4461         /*
4462          * Needs to be set to this value
4463          */
4464         pci_config_put8(h, PCI_CONF_ILINE, 0xf);
4465 
4466         /* check our device_type as defined by Open Firmware */
4467         if (pcicfg_pcie_device_type(new_child, h) == DDI_SUCCESS)
4468                 pcie_device_type = 1;
4469 
4470         /*
4471          * Set bus properties
4472          */
4473         if (pcicfg_set_busnode_props(new_child, pcie_device_type)
4474             != PCICFG_SUCCESS) {
4475                 DEBUG0("Failed to set busnode props\n");
4476                 rval = PCICFG_FAILURE;
4477                 goto cleanup;
4478         }
4479 
4480         (void) pcicfg_device_on(h);
4481 
4482         if (is_pcie)
4483                 (void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
4484         if (ndi_devi_online(new_child, NDI_NO_EVENT|NDI_CONFIG)
4485             != NDI_SUCCESS) {
4486                 DEBUG0("Unable to online bridge\n");
4487                 rval = PCICFG_FAILURE;
4488                 goto cleanup;
4489         }
4490 
4491         DEBUG0("Bridge is ONLINE\n");
4492 
4493         /*
4494          * After a Reset, we need to wait 2^25 clock cycles before the
4495          * first Configuration access.  The worst case is 33MHz, which
4496          * is a 1 second wait.
4497          */
4498         drv_usecwait(pcicfg_sec_reset_delay);
4499 
4500         /*
4501          * Probe all children devices
4502          */
4503         DEBUG0("Bridge Programming Complete - probe children\n");
4504         ndi_devi_enter(new_child, &count);
4505         for (i = 0; ((i < PCI_MAX_DEVICES) && (ari_mode == B_FALSE));
4506             i++) {
4507                 for (j = 0; j < max_function; ) {
4508                         if (ari_mode)
4509                                 trans_device = j >> 3;
4510                         else
4511                                 trans_device = i;
4512 
4513                         if ((rval = pcicfg_probe_children(new_child,
4514                             new_bus, trans_device, j & 7, highest_bus,
4515                             0, is_pcie)) != PCICFG_SUCCESS) {
4516                                 if (rval == PCICFG_NODEVICE) {
4517                                         DEBUG3("No Device at bus [0x%x]"
4518                                             "device [0x%x] "
4519                                             "func [0x%x]\n", new_bus,
4520                                             trans_device, j & 7);
4521 
4522                                         if (j)
4523                                                 goto next;
4524                                 } else
4525                                         /*EMPTY*/
4526                                         DEBUG3("Failed to configure bus "
4527                                             "[0x%x] device [0x%x] "
4528                                             "func [0x%x]\n", new_bus,
4529                                             trans_device, j & 7);
4530                                 break;
4531                         }
4532 next:
4533                         new_device = pcicfg_devi_find(new_child, trans_device,
4534                             (j & 7));
4535 
4536                         /*
4537                          * Determine if ARI Forwarding should be enabled.
4538                          */
4539                         if (j == 0) {
4540                                 if (new_device == NULL)
4541                                         break;
4542 
4543                                 if ((pcie_ari_supported(new_child) ==
4544                                     PCIE_ARI_FORW_SUPPORTED) &&
4545                                     (pcie_ari_device(new_device) ==
4546                                     PCIE_ARI_DEVICE)) {
4547                                         if (pcie_ari_enable(new_child) ==
4548                                             DDI_SUCCESS) {
4549                                                 (void) ddi_prop_create(
4550                                                     DDI_DEV_T_NONE,
4551                                                     new_child,
4552                                                     DDI_PROP_CANSLEEP,
4553                                                     "ari-enabled", NULL, 0);
4554                                                 ari_mode = B_TRUE;
4555                                                 max_function =
4556                                                     PCICFG_MAX_ARI_FUNCTION;
4557                                         }
4558                                 }
4559                         }
4560                         if (ari_mode == B_TRUE) {
4561                                 int next_function;
4562 
4563                                 if (new_device == NULL)
4564                                         break;
4565 
4566                                 if (pcie_ari_get_next_function(new_device,
4567                                     &next_function) != DDI_SUCCESS)
4568                                         break;
4569 
4570                                 j = next_function;
4571 
4572                                 if (next_function == 0)
4573                                         break;
4574                         } else
4575                                 j++;
4576 
4577                 }
4578                 /* if any function fails to be configured, no need to proceed */
4579                 if (rval != PCICFG_NODEVICE)
4580                         break;
4581         }
4582         ndi_devi_exit(new_child, count);
4583 
4584         /*
4585          * Offline the bridge to allow reprogramming of resources.
4586          *
4587          * This should always succeed since nobody else has started to
4588          * use it yet, failing to detach the driver would indicate a bug.
4589          * Also in that case it's better just panic than allowing the
4590          * configurator to proceed with BAR reprogramming without bridge
4591          * driver detached.
4592          */
4593         VERIFY(ndi_devi_offline(new_child, NDI_NO_EVENT|NDI_UNCONFIG)
4594             == NDI_SUCCESS);
4595         if (is_pcie)
4596                 pcie_fini_bus(new_child, PCIE_BUS_INITIAL);
4597 
4598         phdl.dip = new_child;
4599         phdl.memory_base = mem_answer;
4600         phdl.io_base = io_answer;
4601         phdl.pf_memory_base = pf_mem_answer;
4602         phdl.error = PCICFG_SUCCESS;    /* in case of empty child tree */
4603 
4604         ndi_devi_enter(ddi_get_parent(new_child), &count);
4605         ddi_walk_devs(new_child, pcicfg_find_resource_end, (void *)&phdl);
4606         ndi_devi_exit(ddi_get_parent(new_child), count);
4607 
4608         num_slots = pcicfg_get_nslots(new_child, h);
4609         mem_end = PCICFG_ROUND_UP(phdl.memory_base, PCICFG_MEMGRAN);
4610         io_end = PCICFG_ROUND_UP(phdl.io_base, PCICFG_IOGRAN);
4611         pf_mem_end = PCICFG_ROUND_UP(phdl.pf_memory_base, PCICFG_MEMGRAN);
4612 
4613         DEBUG4("Start of Unallocated Bridge(%d slots) Resources Mem=0x%lx "
4614             "I/O=0x%lx PF_mem=%x%lx\n", num_slots, mem_end, io_end, pf_mem_end);
4615 
4616         /*
4617          * Before probing the children we've allocated maximum MEM/IO
4618          * resources from parent, and updated "available" property
4619          * accordingly. Later we'll be giving up unused resources to
4620          * the parent, thus we need to destroy "available" property
4621          * here otherwise it will be out-of-sync with the actual free
4622          * resources this bridge has. This property will be rebuilt below
4623          * with the actual free resources reserved for hotplug slots
4624          * (if any).
4625          */
4626         (void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "available");
4627         /*
4628          * if the bridge a slots, then preallocate. If not, assume static
4629          * configuration. Also check for preallocation limits and spit
4630          * warning messages appropriately (perhaps some can be in debug mode).
4631          */
4632         if (num_slots) {
4633                 uint64_t mem_reqd = mem_answer +
4634                     (num_slots * pcicfg_slot_memsize);
4635                 uint64_t io_reqd = io_answer +
4636                     (num_slots * pcicfg_slot_iosize);
4637                 uint64_t pf_mem_reqd = pf_mem_answer +
4638                     (num_slots * pcicfg_slot_pf_memsize);
4639                 uint8_t highest_bus_reqd = new_bus +
4640                     (num_slots * pcicfg_slot_busnums);
4641 #ifdef DEBUG
4642                 if (mem_end > mem_reqd)
4643                         DEBUG3("Memory space consumed by bridge more "
4644                             "than planned for %d slot(s)(%" PRIx64 ",%"
4645                             PRIx64 ")", num_slots, mem_answer, mem_end);
4646                 if (io_end > io_reqd)
4647                         DEBUG3("IO space consumed by bridge more than"
4648                             " planned for %d slot(s)(%" PRIx64 ",%" PRIx64 ")",
4649                             num_slots, io_answer, io_end);
4650                 if (pf_mem_end > pf_mem_reqd)
4651                         DEBUG3("PF Memory space consumed by bridge"
4652                             " more than planned for %d slot(s)(%" PRIx64 ",%"
4653                             PRIx64 ")", num_slots, pf_mem_answer, pf_mem_end);
4654                 if (*highest_bus > highest_bus_reqd)
4655                         DEBUG3("Buses consumed by bridge more "
4656                             "than planned for %d slot(s)(%x, %x)",
4657                             num_slots, new_bus, *highest_bus);
4658 
4659                 if (mem_reqd > (mem_answer + mem_alen))
4660                         DEBUG3("Memory space required by bridge more "
4661                             "than available for %d slot(s)(%" PRIx64 ",%"
4662                             PRIx64 ")", num_slots, mem_answer, mem_end);
4663                 if (io_reqd > (io_answer + io_alen))
4664                         DEBUG3("IO space required by bridge more than"
4665                             "available for %d slot(s)(%" PRIx64 ",%" PRIx64 ")",
4666                             num_slots, io_answer, io_end);
4667                 if (pf_mem_reqd > (pf_mem_answer + pf_mem_alen))
4668                         DEBUG3("PF Memory space required by bridge"
4669                             " more than available for %d slot(s)(%" PRIx64 ",%"
4670                             PRIx64 ")", num_slots, pf_mem_answer, pf_mem_end);
4671                 if (highest_bus_reqd > max_bus)
4672                         DEBUG3("Bus numbers required by bridge more "
4673                             "than available for %d slot(s)(%x, %x)",
4674                             num_slots, new_bus, *highest_bus);
4675 #endif
4676                 mem_end = MAX((MIN(mem_reqd, (mem_answer + mem_alen))),
4677                     mem_end);
4678                 io_end = MAX((MIN(io_reqd, (io_answer + io_alen))), io_end);
4679                 pf_mem_end = MAX((MIN(pf_mem_reqd, (pf_mem_answer +
4680                     pf_mem_alen))), pf_mem_end);
4681                 *highest_bus = MAX((MIN(highest_bus_reqd, max_bus)),
4682                     *highest_bus);
4683                 DEBUG4("mem_end %lx, io_end %lx, pf_mem_end %lx"
4684                     " highest_bus %x\n", mem_end, io_end, pf_mem_end,
4685                     *highest_bus);
4686         }
4687 
4688         /*
4689          * Give back unused memory space to parent.
4690          */
4691         (void) ndi_ra_free(ddi_get_parent(new_child), mem_end,
4692             (mem_answer + mem_alen) - mem_end, NDI_RA_TYPE_MEM, NDI_RA_PASS);
4693 
4694         if (mem_end == mem_answer) {
4695                 DEBUG0("No memory resources used\n");
4696                 /*
4697                  * To prevent the bridge from forwarding any Memory
4698                  * transactions, the Memory Limit will be programmed
4699                  * with a smaller value than the Memory Base.
4700                  */
4701                 pci_config_put16(h, PCI_BCNF_MEM_BASE, 0xffff);
4702                 pci_config_put16(h, PCI_BCNF_MEM_LIMIT, 0);
4703 
4704                 mem_size = 0;
4705         } else {
4706                 /*
4707                  * Reprogram the end of the memory.
4708                  */
4709                 pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
4710                     PCICFG_HIWORD(mem_end) - 1);
4711                 mem_size = mem_end - mem_base;
4712         }
4713 
4714         /*
4715          * Give back unused io space to parent.
4716          */
4717         (void) ndi_ra_free(ddi_get_parent(new_child),
4718             io_end, (io_answer + io_alen) - io_end,
4719             NDI_RA_TYPE_IO, NDI_RA_PASS);
4720 
4721         if (io_end == io_answer) {
4722                 DEBUG0("No IO Space resources used\n");
4723 
4724                 /*
4725                  * To prevent the bridge from forwarding any I/O
4726                  * transactions, the I/O Limit will be programmed
4727                  * with a smaller value than the I/O Base.
4728                  */
4729                 pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW, 0);
4730                 pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI, 0);
4731                 pci_config_put8(h, PCI_BCNF_IO_BASE_LOW, 0xff);
4732                 pci_config_put16(h, PCI_BCNF_IO_BASE_HI, 0);
4733 
4734                 io_size = 0;
4735         } else {
4736                 /*
4737                  * Reprogram the end of the io space.
4738                  */
4739                 pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
4740                     PCICFG_HIBYTE(PCICFG_LOWORD(
4741                     PCICFG_LOADDR(io_end) - 1)));
4742 
4743                 pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
4744                     PCICFG_HIWORD(PCICFG_LOADDR(io_end - 1)));
4745 
4746                 io_size = io_end - io_base;
4747         }
4748 
4749         /*
4750          * Give back unused PF memory space to parent.
4751          */
4752         if (pf_mem_supported) {
4753                 (void) ndi_ra_free(ddi_get_parent(new_child),
4754                     pf_mem_end, (pf_mem_answer + pf_mem_alen) - pf_mem_end,
4755                     NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
4756 
4757                 if (pf_mem_end == pf_mem_answer) {
4758                         DEBUG0("No PF memory resources used\n");
4759                         /*
4760                          * To prevent the bridge from forwarding any PF Memory
4761                          * transactions, the PF Memory Limit will be programmed
4762                          * with a smaller value than the Memory Base.
4763                          */
4764                         pci_config_put16(h, PCI_BCNF_PF_BASE_LOW, 0xfff0);
4765                         pci_config_put32(h, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
4766                         pci_config_put16(h, PCI_BCNF_PF_LIMIT_LOW, 0);
4767                         pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH, 0);
4768 
4769                         pf_mem_size = 0;
4770                 } else {
4771                         /*
4772                          * Reprogram the end of the PF memory range.
4773                          */
4774                         pci_config_put16(h, PCI_BCNF_PF_LIMIT_LOW,
4775                             PCICFG_HIWORD(PCICFG_LOADDR(pf_mem_end - 1)));
4776                         pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH,
4777                             PCICFG_HIADDR(pf_mem_end - 1));
4778                         pf_mem_size = pf_mem_end - pf_mem_base;
4779                 }
4780         }
4781 
4782         if ((max_bus - *highest_bus) > 0) {
4783                 /*
4784                  * Give back unused bus numbers
4785                  */
4786                 (void) ndi_ra_free(ddi_get_parent(new_child),
4787                     *highest_bus+1, max_bus - *highest_bus,
4788                     NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4789         }
4790 
4791         /*
4792          * Set bus numbers to ranges encountered during scan
4793          */
4794         (void) pcicfg_set_bus_numbers(h, bus, new_bus, *highest_bus);
4795 
4796         /*
4797          * Remove the ranges property if it exists since we will create
4798          * a new one.
4799          */
4800         (void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "ranges");
4801 
4802         DEBUG2("Creating Ranges property - Mem Address %lx Mem Size %x\n",
4803             mem_base, mem_size);
4804         DEBUG2("                         - I/O Address %lx I/O Size %x\n",
4805             io_base, io_size);
4806         DEBUG2("                         - PF Mem address %lx PF Mem Size %x\n",
4807             pf_mem_base, pf_mem_size);
4808 
4809         bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
4810 
4811         range[0].child_high = range[0].parent_high |= (PCI_REG_REL_M |
4812             PCI_ADDR_IO);
4813         range[0].child_low = range[0].parent_low = io_base;
4814         range[1].child_high = range[1].parent_high |=
4815             (PCI_REG_REL_M | PCI_ADDR_MEM32);
4816         range[1].child_low = range[1].parent_low = mem_base;
4817         range[2].child_high = range[2].parent_high |=
4818             (PCI_REG_REL_M | PCI_ADDR_MEM64 | PCI_REG_PF_M);
4819         range[2].child_low = range[2].parent_low = pf_mem_base;
4820 
4821         if (io_size > 0) {
4822                 range[0].size_low = io_size;
4823                 (void) pcicfg_update_ranges_prop(new_child, &range[0]);
4824         }
4825         if (mem_size > 0) {
4826                 range[1].size_low = mem_size;
4827                 (void) pcicfg_update_ranges_prop(new_child, &range[1]);
4828         }
4829         if (pf_mem_size > 0) {
4830                 range[2].size_low = pf_mem_size;
4831                 (void) pcicfg_update_ranges_prop(new_child, &range[2]);
4832         }
4833 
4834         bus_range[0] = pci_config_get8(h, PCI_BCNF_SECBUS);
4835         bus_range[1] = pci_config_get8(h, PCI_BCNF_SUBBUS);
4836         DEBUG1("End of bridge probe: bus_range[0] =  %d\n", bus_range[0]);
4837         DEBUG1("End of bridge probe: bus_range[1] =  %d\n", bus_range[1]);
4838 
4839         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
4840             "bus-range", bus_range, 2);
4841 
4842         rval = PCICFG_SUCCESS;
4843 
4844         PCICFG_DUMP_BRIDGE_CONFIG(h);
4845 
4846 cleanup:
4847         /* free up resources (for error return case only) */
4848         if (rval != PCICFG_SUCCESS) {
4849                 if (mem_alen)
4850                         (void) ndi_ra_free(ddi_get_parent(new_child), mem_base,
4851                             mem_alen, NDI_RA_TYPE_MEM, NDI_RA_PASS);
4852                 if (io_alen)
4853                         (void) ndi_ra_free(ddi_get_parent(new_child), io_base,
4854                             io_alen, NDI_RA_TYPE_IO, NDI_RA_PASS);
4855                 if (pf_mem_alen)
4856                         (void) ndi_ra_free(ddi_get_parent(new_child),
4857                             pf_mem_base, pf_mem_alen,
4858                             NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
4859                 if (pcibus_alen)
4860                         (void) ndi_ra_free(ddi_get_parent(new_child),
4861                             pcibus_base, pcibus_alen, NDI_RA_TYPE_PCI_BUSNUM,
4862                             NDI_RA_PASS);
4863         }
4864 
4865         /* free up any resource maps setup for the bridge node */
4866         (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_PCI_BUSNUM);
4867         (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_IO);
4868         (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_MEM);
4869         (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_PCI_PREFETCH_MEM);
4870 
4871         return (rval);
4872 }
4873 
4874 static int
4875 pcicfg_find_resource_end(dev_info_t *dip, void *hdl)
4876 {
4877         pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
4878         pci_regspec_t *pci_ap;
4879         int length;
4880         int rcount;
4881         int i;
4882 
4883         entry->error = PCICFG_SUCCESS;
4884 
4885         if (dip == entry->dip) {
4886                 DEBUG0("Don't include parent bridge node\n");
4887                 return (DDI_WALK_CONTINUE);
4888         } else {
4889                 if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
4890                     DDI_PROP_DONTPASS, "assigned-addresses",
4891                     (caddr_t)&pci_ap,  &length) != DDI_PROP_SUCCESS) {
4892                         DEBUG0("Node doesn't have assigned-addresses\n");
4893                         return (DDI_WALK_CONTINUE);
4894                 }
4895 
4896                 rcount = length / sizeof (pci_regspec_t);
4897 
4898                 for (i = 0; i < rcount; i++) {
4899 
4900                         switch (PCI_REG_ADDR_G(pci_ap[i].pci_phys_hi)) {
4901 
4902                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
4903                                 if (pci_ap[i].pci_phys_hi & PCI_REG_PF_M) {
4904                                         if ((pci_ap[i].pci_phys_low +
4905                                             pci_ap[i].pci_size_low) >
4906                                             entry->pf_memory_base) {
4907                                                 entry->pf_memory_base =
4908                                                     pci_ap[i].pci_phys_low +
4909                                                     pci_ap[i].pci_size_low;
4910                                         }
4911                                 } else {
4912                                         if ((pci_ap[i].pci_phys_low +
4913                                             pci_ap[i].pci_size_low) >
4914                                             entry->memory_base) {
4915                                                 entry->memory_base =
4916                                                     pci_ap[i].pci_phys_low +
4917                                                     pci_ap[i].pci_size_low;
4918                                         }
4919                                 }
4920                                 break;
4921                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
4922                                 if (pci_ap[i].pci_phys_hi & PCI_REG_PF_M) {
4923                                         if ((PCICFG_LADDR(
4924                                             pci_ap[i].pci_phys_low,
4925                                             pci_ap[i].pci_phys_mid) +
4926                                             pci_ap[i].pci_size_low) >
4927                                             entry->pf_memory_base) {
4928                                                 entry->pf_memory_base =
4929                                                     PCICFG_LADDR(
4930                                                     pci_ap[i].pci_phys_low,
4931                                                     pci_ap[i].pci_phys_mid) +
4932                                                     pci_ap[i].pci_size_low;
4933                                         }
4934                                 } else {
4935                                         if ((PCICFG_LADDR(
4936                                             pci_ap[i].pci_phys_low,
4937                                             pci_ap[i].pci_phys_mid) +
4938                                             pci_ap[i].pci_size_low) >
4939                                             entry->memory_base) {
4940                                                 entry->memory_base =
4941                                                     PCICFG_LADDR(
4942                                                     pci_ap[i].pci_phys_low,
4943                                                     pci_ap[i].pci_phys_mid) +
4944                                                     pci_ap[i].pci_size_low;
4945                                         }
4946                                 }
4947                                 break;
4948                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
4949                                 if ((pci_ap[i].pci_phys_low +
4950                                     pci_ap[i].pci_size_low) >
4951                                     entry->io_base) {
4952                                         entry->io_base =
4953                                             pci_ap[i].pci_phys_low +
4954                                             pci_ap[i].pci_size_low;
4955                                 }
4956                                 break;
4957                         }
4958                 }
4959 
4960                 /*
4961                  * free the memory allocated by ddi_getlongprop
4962                  */
4963                 kmem_free(pci_ap, length);
4964 
4965                 /*
4966                  * continue the walk to the next sibling to sum memory
4967                  */
4968                 return (DDI_WALK_CONTINUE);
4969         }
4970 }
4971 
4972 /*
4973  * Make "parent" be the parent of the "child" dip
4974  */
4975 static void
4976 pcicfg_reparent_node(dev_info_t *child, dev_info_t *parent)
4977 {
4978         int circ;
4979         dev_info_t *opdip;
4980 
4981         ASSERT(i_ddi_node_state(child) <= DS_LINKED);
4982         /*
4983          * Unlink node from tree before reparenting
4984          */
4985         opdip = ddi_get_parent(child);
4986         ndi_devi_enter(opdip, &circ);
4987         (void) i_ndi_unconfig_node(child, DS_PROTO, 0);
4988         ndi_devi_exit(opdip, circ);
4989 
4990         DEVI(child)->devi_parent = DEVI(parent);
4991         DEVI(child)->devi_bus_ctl = DEVI(parent);
4992         (void) ndi_devi_bind_driver(child, 0);
4993 }
4994 
4995 /*
4996  * Return PCICFG_SUCCESS if device exists at the specified address.
4997  * Return PCICFG_NODEVICE is no device exists at the specified address.
4998  */
4999 int
5000 pcicfg_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle)
5001 {
5002         caddr_t cfgaddr;
5003         ddi_device_acc_attr_t attr;
5004         dev_info_t *anode;
5005         int status;
5006         int             rlen;
5007         pci_regspec_t   *reg;
5008         int             ret = DDI_SUCCESS;
5009         int16_t         tmp;
5010 
5011         /*
5012          * Get the pci register spec from the node
5013          */
5014         status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
5015             (caddr_t)&reg, &rlen);
5016 
5017         switch (status) {
5018                 case DDI_PROP_SUCCESS:
5019                         break;
5020                 case DDI_PROP_NO_MEMORY:
5021                         DEBUG0("reg present, but unable to get memory\n");
5022                         return (PCICFG_FAILURE);
5023                 default:
5024                         DEBUG0("no reg property\n");
5025                         return (PCICFG_FAILURE);
5026         }
5027 
5028         anode = dip;
5029         DEBUG2("conf_map: dip=%p, anode=%p\n", dip, anode);
5030 
5031         attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
5032         attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
5033         attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
5034 
5035         if (ddi_regs_map_setup(anode, 0, &cfgaddr, 0, 0, &attr, handle)
5036             != DDI_SUCCESS) {
5037                 DEBUG0("Failed to setup registers\n");
5038                 kmem_free((caddr_t)reg, rlen);
5039                 return (PCICFG_FAILURE);
5040         }
5041 
5042         /*
5043          * need to use DDI interfaces as the conf space is
5044          * cannot be directly accessed by the host.
5045          */
5046         tmp = (int16_t)ddi_get16(*handle, (uint16_t *)cfgaddr);
5047         if ((tmp == (int16_t)0xffff) || (tmp == -1)) {
5048                 DEBUG1("NO DEVICEFOUND, read %x\n", tmp);
5049                 ret = PCICFG_NODEVICE;
5050         } else {
5051                 if (tmp == 0) {
5052                         DEBUG0("Device Not Ready yet ?");
5053                         ret = PCICFG_NODEVICE;
5054                 } else {
5055                         DEBUG1("DEVICEFOUND, read %x\n", tmp);
5056                         ret = PCICFG_SUCCESS;
5057                 }
5058         }
5059 
5060         if (ret == PCICFG_NODEVICE)
5061                 ddi_regs_map_free(handle);
5062         kmem_free((caddr_t)reg, rlen);
5063 
5064         return (ret);
5065 
5066 }
5067 
5068 static void
5069 pcicfg_config_teardown(ddi_acc_handle_t *handle)
5070 {
5071         (void) ddi_regs_map_free(handle);
5072 }
5073 
5074 static int
5075 pcicfg_add_config_reg(dev_info_t *dip,
5076         uint_t bus, uint_t device, uint_t func)
5077 {
5078         int reg[10] = { PCI_ADDR_CONFIG, 0, 0, 0, 0};
5079 
5080         reg[0] = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
5081 
5082         return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "reg", reg, 5));
5083 }
5084 
5085 static int
5086 pcicfg_ari_configure(dev_info_t *dip)
5087 {
5088         if (pcie_ari_supported(dip) == PCIE_ARI_FORW_NOT_SUPPORTED)
5089                 return (DDI_FAILURE);
5090 
5091         /*
5092          * Until we have resource balancing, dynamically configure
5093          * ARI functions without firmware assistamce.
5094          */
5095         return (DDI_FAILURE);
5096 }
5097 
5098 
5099 #ifdef DEBUG
5100 static void
5101 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
5102         uintptr_t a4, uintptr_t a5)
5103 {
5104         if (pcicfg_debug > 1) {
5105                 prom_printf("pcicfg: ");
5106                 prom_printf(fmt, a1, a2, a3, a4, a5);
5107         }
5108 }
5109 #endif
5110 
5111 /*ARGSUSED*/
5112 static uint8_t
5113 pcicfg_get_nslots(dev_info_t *dip, ddi_acc_handle_t handle)
5114 {
5115         uint16_t cap_id_loc, slot_id_loc;
5116         uint8_t num_slots = 0;
5117 
5118         /* just depend on the pcie_cap for now. */
5119         (void) PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_id_loc);
5120         (void) PCI_CAP_LOCATE(handle, PCI_CAP_ID_SLOT_ID, &slot_id_loc);
5121         if (cap_id_loc != PCI_CAP_NEXT_PTR_NULL) {
5122                 if (pci_config_get8(handle, cap_id_loc + PCI_CAP_ID_REGS_OFF) &
5123                     PCIE_PCIECAP_SLOT_IMPL)
5124                         num_slots = 1;
5125         } else /* not a PCIe switch/bridge. Must be a PCI-PCI[-X] bridge */
5126         if (slot_id_loc != PCI_CAP_NEXT_PTR_NULL) {
5127                 uint8_t esr_reg = pci_config_get8(handle, slot_id_loc + 2);
5128                 num_slots = PCI_CAPSLOT_NSLOTS(esr_reg);
5129         }
5130         /* XXX - need to cover PCI-PCIe bridge with n slots */
5131         return (num_slots);
5132 }
5133 
5134 /*ARGSUSED*/
5135 static int
5136 pcicfg_pcie_dev(dev_info_t *dip, ddi_acc_handle_t handle)
5137 {
5138         /* get parent device's device_type property */
5139         char *device_type;
5140         int val;
5141         dev_info_t *pdip = ddi_get_parent(dip);
5142 
5143         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
5144             "device_type", &device_type) != DDI_PROP_SUCCESS) {
5145                 DEBUG2("device_type property missing for %s#%d",
5146                     ddi_get_name(pdip), ddi_get_instance(pdip));
5147                 return (DDI_FAILURE);
5148         }
5149         DEBUG1("device_type=<%s>\n", device_type);
5150 
5151         val = DDI_FAILURE;
5152         if (strcmp(device_type, "pciex") == 0)
5153                 val = DDI_SUCCESS;
5154         ddi_prop_free(device_type);
5155         return (val);
5156 }
5157 
5158 static int
5159 pcicfg_pcie_device_type(dev_info_t *dip, ddi_acc_handle_t handle)
5160 {
5161         int port_type = pcicfg_pcie_port_type(dip, handle);
5162 
5163         DEBUG1("device port_type = %x\n", port_type);
5164         /* No PCIe CAP regs, we are not PCIe device_type */
5165         if (port_type < 0)
5166                 return (DDI_FAILURE);
5167 
5168         /* check for all PCIe device_types */
5169         if ((port_type == PCIE_PCIECAP_DEV_TYPE_UP) ||
5170             (port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
5171             (port_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
5172             (port_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE))
5173                 return (DDI_SUCCESS);
5174 
5175         return (DDI_FAILURE);
5176 
5177 }
5178 
5179 /*ARGSUSED*/
5180 static int
5181 pcicfg_pcie_port_type(dev_info_t *dip, ddi_acc_handle_t handle)
5182 {
5183         int port_type = -1;
5184         uint16_t cap_loc;
5185 
5186         /* Note: need to look at the port type information here */
5187         (void) PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_loc);
5188         if (cap_loc != PCI_CAP_NEXT_PTR_NULL)
5189                 port_type = pci_config_get16(handle,
5190                     cap_loc + PCIE_PCIECAP) & PCIE_PCIECAP_DEV_TYPE_MASK;
5191 
5192         return (port_type);
5193 }
5194 
5195 /*
5196  * Return true if the devinfo node is in a PCI Express hierarchy.
5197  */
5198 static boolean_t
5199 is_pcie_fabric(dev_info_t *dip)
5200 {
5201         dev_info_t *root = ddi_root_node();
5202         dev_info_t *pdip;
5203         boolean_t found = B_FALSE;
5204         char *bus;
5205 
5206         /*
5207          * Does this device reside in a pcie fabric ?
5208          */
5209         for (pdip = dip; pdip && (pdip != root) && !found;
5210             pdip = ddi_get_parent(pdip)) {
5211                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
5212                     DDI_PROP_DONTPASS, "device_type", &bus) !=
5213                     DDI_PROP_SUCCESS)
5214                         break;
5215 
5216                 if (strcmp(bus, "pciex") == 0)
5217                         found = B_TRUE;
5218 
5219                 ddi_prop_free(bus);
5220         }
5221 
5222         return (found);
5223 }