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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*
  26  *     PCI configurator (pcicfg)
  27  */
  28 
  29 #include <sys/isa_defs.h>
  30 
  31 #include <sys/conf.h>
  32 #include <sys/kmem.h>
  33 #include <sys/debug.h>
  34 #include <sys/modctl.h>
  35 #include <sys/autoconf.h>
  36 #include <sys/hwconf.h>
  37 #include <sys/ddi_impldefs.h>
  38 #include <sys/fcode.h>
  39 #include <sys/pci.h>
  40 #include <sys/pcie.h>
  41 #include <sys/pcie_impl.h>
  42 #include <sys/ddi.h>
  43 #include <sys/sunddi.h>
  44 #include <sys/sunndi.h>
  45 #include <sys/pci_cap.h>
  46 #include <sys/hotplug/pci/pcicfg.h>
  47 #include <sys/ndi_impldefs.h>
  48 #include <sys/pci_cfgacc.h>
  49 
  50 #define PCICFG_DEVICE_TYPE_PCI  1
  51 #define PCICFG_DEVICE_TYPE_PCIE 2
  52 
  53 #define EFCODE21554     /* changes for supporting 21554 */
  54 
  55 static int pcicfg_alloc_resource(dev_info_t *, pci_regspec_t);
  56 static int pcicfg_free_resource(dev_info_t *, pci_regspec_t, pcicfg_flags_t);
  57 static int pcicfg_remove_assigned_prop(dev_info_t *, pci_regspec_t *);
  58 
  59 #ifdef  PCICFG_INTERPRET_FCODE
  60 static int pcicfg_fcode_assign_bars(ddi_acc_handle_t, dev_info_t *,
  61     uint_t, uint_t, uint_t, int32_t, pci_regspec_t *);
  62 #endif  /* PCICFG_INTERPRET_FCODE */
  63 
  64 /*
  65  * ************************************************************************
  66  * *** Implementation specific local data structures/definitions.       ***
  67  * ************************************************************************
  68  */
  69 
  70 static  int     pcicfg_start_devno = 0; /* for Debug only */
  71 
  72 #define PCICFG_MAX_DEVICE 32
  73 #define PCICFG_MAX_FUNCTION 8
  74 #define PCICFG_MAX_ARI_FUNCTION 256
  75 #define PCICFG_MAX_REGISTER 64
  76 #define PCICFG_MAX_BUS_DEPTH 255
  77 
  78 #define PCICFG_NODEVICE 42
  79 #define PCICFG_NOMEMORY 43
  80 #define PCICFG_NOMULTI  44
  81 
  82 #define PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32))
  83 #define PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
  84 #define PCICFG_LADDR(lo, hi)    (((uint64_t)(hi) << 32) | (uint32_t)(lo))
  85 
  86 #define PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
  87 #define PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
  88 #define PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
  89 #define PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
  90 
  91 #define PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
  92 #define PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
  93 
  94 #define PCICFG_MEMGRAN 0x100000
  95 #define PCICFG_IOGRAN 0x1000
  96 #define PCICFG_4GIG_LIMIT 0xFFFFFFFFUL
  97 
  98 #define PCICFG_MEM_MULT 4
  99 #define PCICFG_IO_MULT 4
 100 #define PCICFG_RANGE_LEN 2 /* Number of range entries */
 101 
 102 static int pcicfg_slot_busnums = 8;
 103 static int pcicfg_slot_memsize = 32 * PCICFG_MEMGRAN; /* 32MB per slot */
 104 static int pcicfg_slot_iosize = 16 * PCICFG_IOGRAN; /* 64K per slot */
 105 static int pcicfg_chassis_per_tree = 1;
 106 static int pcicfg_sec_reset_delay = 1000000;
 107 
 108 /*
 109  * The following typedef is used to represent a
 110  * 1275 "bus-range" property of a PCI Bus node.
 111  * DAF - should be in generic include file...
 112  */
 113 
 114 typedef struct pcicfg_bus_range {
 115         uint32_t lo;
 116         uint32_t hi;
 117 } pcicfg_bus_range_t;
 118 
 119 typedef struct pcicfg_range {
 120 
 121         uint32_t child_hi;
 122         uint32_t child_mid;
 123         uint32_t child_lo;
 124         uint32_t parent_hi;
 125         uint32_t parent_mid;
 126         uint32_t parent_lo;
 127         uint32_t size_hi;
 128         uint32_t size_lo;
 129 
 130 } pcicfg_range_t;
 131 
 132 typedef struct hole hole_t;
 133 
 134 struct hole {
 135         uint64_t        start;
 136         uint64_t        len;
 137         hole_t          *next;
 138 };
 139 
 140 typedef struct pcicfg_phdl pcicfg_phdl_t;
 141 
 142 struct pcicfg_phdl {
 143 
 144         dev_info_t      *dip;           /* Associated with the attach point */
 145         pcicfg_phdl_t   *next;
 146 
 147         uint64_t        memory_base;    /* Memory base for this attach point */
 148         uint64_t        memory_last;
 149         uint64_t        memory_len;
 150         uint32_t        io_base;        /* I/O base for this attach point */
 151         uint32_t        io_last;
 152         uint32_t        io_len;
 153 
 154         int             error;
 155         uint_t          highest_bus;    /* Highest bus seen on the probe */
 156 
 157         hole_t          mem_hole;       /* Memory hole linked list. */
 158         hole_t          io_hole;        /* IO hole linked list */
 159 
 160         ndi_ra_request_t mem_req;       /* allocator request for memory */
 161         ndi_ra_request_t io_req;        /* allocator request for I/O */
 162 };
 163 
 164 struct pcicfg_standard_prop_entry {
 165     uchar_t *name;
 166     uint_t  config_offset;
 167     uint_t  size;
 168 };
 169 
 170 
 171 struct pcicfg_name_entry {
 172     uint32_t class_code;
 173     char  *name;
 174 };
 175 
 176 struct pcicfg_find_ctrl {
 177         uint_t          device;
 178         uint_t          function;
 179         dev_info_t      *dip;
 180 };
 181 
 182 typedef struct pcicfg_err_regs {
 183         uint16_t cmd;
 184         uint16_t bcntl;
 185         uint16_t pcie_dev;
 186         uint16_t devctl;
 187         uint16_t pcie_cap_off;
 188 } pcicfg_err_regs_t;
 189 
 190 /*
 191  * List of Indirect Config Map Devices. At least the intent of the
 192  * design is to look for a device in this list during the configure
 193  * operation, and if the device is listed here, then it is a nontransparent
 194  * bridge, hence load the driver and avail the config map services from
 195  * the driver. Class and Subclass should be as defined in the PCI specs
 196  * ie. class is 0x6, and subclass is 0x9.
 197  */
 198 static struct {
 199         uint8_t         mem_range_bar_offset;
 200         uint8_t         io_range_bar_offset;
 201         uint8_t         prefetch_mem_range_bar_offset;
 202 } pcicfg_indirect_map_devs[] = {
 203         PCI_CONF_BASE3, PCI_CONF_BASE2, PCI_CONF_BASE3,
 204         0,      0,      0,
 205 };
 206 
 207 #define PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\
 208         (\
 209         ((ulong_t)(busnum & 0xff) << 16)    |\
 210         ((ulong_t)(devnum & 0x1f) << 11)    |\
 211         ((ulong_t)(funcnum & 0x7) <<  8)    |\
 212         ((ulong_t)(register & 0x3f)))
 213 
 214 /*
 215  * debug macros:
 216  */
 217 #if     defined(DEBUG)
 218 extern void prom_printf(const char *, ...);
 219 
 220 /*
 221  * Following values are defined for this debug flag.
 222  *
 223  * 1 = dump configuration header only.
 224  * 2 = dump generic debug data only (no config header dumped)
 225  * 3 = dump everything (both 1 and 2)
 226  */
 227 int pcicfg_debug = 0;
 228 int pcicfg_dump_fcode = 0;
 229 
 230 static void debug(char *, uintptr_t, uintptr_t,
 231         uintptr_t, uintptr_t, uintptr_t);
 232 
 233 #define DEBUG0(fmt)\
 234         debug(fmt, 0, 0, 0, 0, 0);
 235 #define DEBUG1(fmt, a1)\
 236         debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
 237 #define DEBUG2(fmt, a1, a2)\
 238         debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
 239 #define DEBUG3(fmt, a1, a2, a3)\
 240         debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
 241                 (uintptr_t)(a3), 0, 0);
 242 #define DEBUG4(fmt, a1, a2, a3, a4)\
 243         debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
 244                 (uintptr_t)(a3), (uintptr_t)(a4), 0);
 245 #else
 246 #define DEBUG0(fmt)
 247 #define DEBUG1(fmt, a1)
 248 #define DEBUG2(fmt, a1, a2)
 249 #define DEBUG3(fmt, a1, a2, a3)
 250 #define DEBUG4(fmt, a1, a2, a3, a4)
 251 #endif
 252 
 253 #ifdef PCICFG_INTERPRET_FCODE
 254 int pcicfg_dont_interpret = 0;
 255 #else
 256 int pcicfg_dont_interpret = 1;
 257 #endif
 258 
 259 /*
 260  * forward declarations for routines defined in this module (called here)
 261  */
 262 
 263 static int pcicfg_add_config_reg(dev_info_t *,
 264     uint_t, uint_t, uint_t);
 265 static int pcicfg_probe_children(dev_info_t *, uint_t, uint_t, uint_t,
 266     uint_t *, pcicfg_flags_t, boolean_t);
 267 
 268 #ifdef PCICFG_INTERPRET_FCODE
 269 static int pcicfg_load_fcode(dev_info_t *, uint_t, uint_t, uint_t,
 270         uint16_t, uint16_t, uchar_t **, int *, int, int);
 271 #endif
 272 
 273 static int pcicfg_fcode_probe(dev_info_t *, uint_t, uint_t, uint_t,
 274     uint_t *, pcicfg_flags_t, boolean_t);
 275 static int pcicfg_probe_bridge(dev_info_t *, ddi_acc_handle_t, uint_t,
 276     uint_t *, boolean_t);
 277 static int pcicfg_free_all_resources(dev_info_t *);
 278 static int pcicfg_alloc_new_resources(dev_info_t *);
 279 static int pcicfg_match_dev(dev_info_t *, void *);
 280 static dev_info_t *pcicfg_devi_find(dev_info_t *, uint_t, uint_t);
 281 static pcicfg_phdl_t *pcicfg_find_phdl(dev_info_t *);
 282 static pcicfg_phdl_t *pcicfg_create_phdl(dev_info_t *);
 283 static int pcicfg_destroy_phdl(dev_info_t *);
 284 static int pcicfg_sum_resources(dev_info_t *, void *);
 285 static int pcicfg_find_resource_end(dev_info_t *, void *);
 286 static int pcicfg_allocate_chunk(dev_info_t *);
 287 static int pcicfg_program_ap(dev_info_t *);
 288 static int pcicfg_device_assign(dev_info_t *);
 289 static int pcicfg_bridge_assign(dev_info_t *, void *);
 290 static int pcicfg_device_assign_readonly(dev_info_t *);
 291 static int pcicfg_free_resources(dev_info_t *, pcicfg_flags_t);
 292 static void pcicfg_setup_bridge(pcicfg_phdl_t *, ddi_acc_handle_t,
 293     dev_info_t *);
 294 static void pcicfg_update_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
 295 static void pcicfg_enable_bridge_probe_err(dev_info_t *dip,
 296                                 ddi_acc_handle_t h, pcicfg_err_regs_t *regs);
 297 static void pcicfg_disable_bridge_probe_err(dev_info_t *dip,
 298                                 ddi_acc_handle_t h, pcicfg_err_regs_t *regs);
 299 static int pcicfg_update_assigned_prop(dev_info_t *, pci_regspec_t *);
 300 static void pcicfg_device_on(ddi_acc_handle_t);
 301 static void pcicfg_device_off(ddi_acc_handle_t);
 302 static int pcicfg_set_busnode_props(dev_info_t *, uint8_t, int, int);
 303 static int pcicfg_free_bridge_resources(dev_info_t *);
 304 static int pcicfg_free_device_resources(dev_info_t *, pcicfg_flags_t);
 305 static int pcicfg_teardown_device(dev_info_t *, pcicfg_flags_t, boolean_t);
 306 static int pcicfg_config_setup(dev_info_t *, ddi_acc_handle_t *);
 307 static void pcicfg_config_teardown(ddi_acc_handle_t *);
 308 static void pcicfg_get_mem(pcicfg_phdl_t *, uint32_t, uint64_t *);
 309 static void pcicfg_get_io(pcicfg_phdl_t *, uint32_t, uint32_t *);
 310 static int pcicfg_update_ranges_prop(dev_info_t *, pcicfg_range_t *);
 311 static int pcicfg_map_phys(dev_info_t *, pci_regspec_t *, caddr_t *,
 312     ddi_device_acc_attr_t *, ddi_acc_handle_t *);
 313 static void pcicfg_unmap_phys(ddi_acc_handle_t *, pci_regspec_t *);
 314 static int pcicfg_dump_assigned(dev_info_t *);
 315 static uint_t pcicfg_configure_ntbridge(dev_info_t *, uint_t, uint_t);
 316 static int pcicfg_indirect_map(dev_info_t *dip);
 317 static uint_t pcicfg_get_ntbridge_child_range(dev_info_t *, uint64_t *,
 318                                 uint64_t *, uint_t);
 319 static int pcicfg_is_ntbridge(dev_info_t *);
 320 static int pcicfg_ntbridge_allocate_resources(dev_info_t *);
 321 static int pcicfg_ntbridge_configure_done(dev_info_t *);
 322 static int pcicfg_ntbridge_unconfigure(dev_info_t *);
 323 static int pcicfg_ntbridge_unconfigure_child(dev_info_t *, uint_t);
 324 static void pcicfg_free_hole(hole_t *);
 325 static uint64_t pcicfg_alloc_hole(hole_t *, uint64_t *, uint32_t);
 326 static int pcicfg_update_available_prop(dev_info_t *, pci_regspec_t *);
 327 static int pcicfg_ari_configure(dev_info_t *);
 328 static int pcicfg_populate_reg_props(dev_info_t *, ddi_acc_handle_t);
 329 static int pcicfg_populate_props_from_bar(dev_info_t *, ddi_acc_handle_t);
 330 static int pcicfg_update_assigned_prop_value(dev_info_t *, uint32_t,
 331     uint32_t, uint32_t, uint_t);
 332 static boolean_t is_pcie_fabric(dev_info_t *dip);
 333 
 334 #ifdef DEBUG
 335 static void pcicfg_dump_common_config(ddi_acc_handle_t config_handle);
 336 static void pcicfg_dump_device_config(ddi_acc_handle_t);
 337 
 338 static void pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle);
 339 static uint64_t pcicfg_unused_space(hole_t *, uint32_t *);
 340 
 341 #define PCICFG_DUMP_COMMON_CONFIG(hdl) (void)pcicfg_dump_common_config(hdl)
 342 #define PCICFG_DUMP_DEVICE_CONFIG(hdl) (void)pcicfg_dump_device_config(hdl)
 343 #define PCICFG_DUMP_BRIDGE_CONFIG(hdl) (void)pcicfg_dump_bridge_config(hdl)
 344 #else
 345 #define PCICFG_DUMP_COMMON_CONFIG(handle)
 346 #define PCICFG_DUMP_DEVICE_CONFIG(handle)
 347 #define PCICFG_DUMP_BRIDGE_CONFIG(handle)
 348 #endif
 349 
 350 static kmutex_t pcicfg_list_mutex; /* Protects the probe handle list */
 351 static pcicfg_phdl_t *pcicfg_phdl_list = NULL;
 352 
 353 #ifndef _DONT_USE_1275_GENERIC_NAMES
 354 /*
 355  * Class code table
 356  */
 357 static struct pcicfg_name_entry pcicfg_class_lookup [] = {
 358 
 359         { 0x001, "display" },
 360         { 0x100, "scsi" },
 361         { 0x101, "ide" },
 362         { 0x102, "fdc" },
 363         { 0x103, "ipi" },
 364         { 0x104, "raid" },
 365         { 0x200, "ethernet" },
 366         { 0x201, "token-ring" },
 367         { 0x202, "fddi" },
 368         { 0x203, "atm" },
 369         { 0x300, "display" },
 370         { 0x400, "video" },
 371         { 0x401, "sound" },
 372         { 0x500, "memory" },
 373         { 0x501, "flash" },
 374         { 0x600, "host" },
 375         { 0x601, "isa" },
 376         { 0x602, "eisa" },
 377         { 0x603, "mca" },
 378         { 0x604, "pci" },
 379         { 0x605, "pcmcia" },
 380         { 0x606, "nubus" },
 381         { 0x607, "cardbus" },
 382         { 0x609, "pci" },
 383         { 0x700, "serial" },
 384         { 0x701, "parallel" },
 385         { 0x800, "interrupt-controller" },
 386         { 0x801, "dma-controller" },
 387         { 0x802, "timer" },
 388         { 0x803, "rtc" },
 389         { 0x900, "keyboard" },
 390         { 0x901, "pen" },
 391         { 0x902, "mouse" },
 392         { 0xa00, "dock" },
 393         { 0xb00, "cpu" },
 394         { 0xc00, "firewire" },
 395         { 0xc01, "access-bus" },
 396         { 0xc02, "ssa" },
 397         { 0xc03, "usb" },
 398         { 0xc04, "fibre-channel" },
 399         { 0, 0 }
 400 };
 401 #endif /* _DONT_USE_1275_GENERIC_NAMES */
 402 
 403 /*
 404  * Module control operations
 405  */
 406 
 407 extern struct mod_ops mod_miscops;
 408 
 409 static struct modlmisc modlmisc = {
 410         &mod_miscops, /* Type of module */
 411         "PCIe/PCI Config (EFCode Enabled)"
 412 };
 413 
 414 static struct modlinkage modlinkage = {
 415         MODREV_1, (void *)&modlmisc, NULL
 416 };
 417 
 418 #ifdef DEBUG
 419 
 420 static void
 421 pcicfg_dump_common_config(ddi_acc_handle_t config_handle)
 422 {
 423         if ((pcicfg_debug & 1) == 0)
 424                 return;
 425         cmn_err(CE_CONT, " Vendor ID   = [0x%x]\n",
 426             pci_config_get16(config_handle, PCI_CONF_VENID));
 427         cmn_err(CE_CONT, " Device ID   = [0x%x]\n",
 428             pci_config_get16(config_handle, PCI_CONF_DEVID));
 429         cmn_err(CE_CONT, " Command REG = [0x%x]\n",
 430             pci_config_get16(config_handle, PCI_CONF_COMM));
 431         cmn_err(CE_CONT, " Status  REG = [0x%x]\n",
 432             pci_config_get16(config_handle, PCI_CONF_STAT));
 433         cmn_err(CE_CONT, " Revision ID = [0x%x]\n",
 434             pci_config_get8(config_handle, PCI_CONF_REVID));
 435         cmn_err(CE_CONT, " Prog Class  = [0x%x]\n",
 436             pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
 437         cmn_err(CE_CONT, " Dev Class   = [0x%x]\n",
 438             pci_config_get8(config_handle, PCI_CONF_SUBCLASS));
 439         cmn_err(CE_CONT, " Base Class  = [0x%x]\n",
 440             pci_config_get8(config_handle, PCI_CONF_BASCLASS));
 441         cmn_err(CE_CONT, " Device ID   = [0x%x]\n",
 442             pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ));
 443         cmn_err(CE_CONT, " Header Type = [0x%x]\n",
 444             pci_config_get8(config_handle, PCI_CONF_HEADER));
 445         cmn_err(CE_CONT, " BIST        = [0x%x]\n",
 446             pci_config_get8(config_handle, PCI_CONF_BIST));
 447         cmn_err(CE_CONT, " BASE 0      = [0x%x]\n",
 448             pci_config_get32(config_handle, PCI_CONF_BASE0));
 449         cmn_err(CE_CONT, " BASE 1      = [0x%x]\n",
 450             pci_config_get32(config_handle, PCI_CONF_BASE1));
 451 
 452 }
 453 
 454 static void
 455 pcicfg_dump_device_config(ddi_acc_handle_t config_handle)
 456 {
 457         if ((pcicfg_debug & 1) == 0)
 458                 return;
 459         pcicfg_dump_common_config(config_handle);
 460 
 461         cmn_err(CE_CONT, " BASE 2      = [0x%x]\n",
 462             pci_config_get32(config_handle, PCI_CONF_BASE2));
 463         cmn_err(CE_CONT, " BASE 3      = [0x%x]\n",
 464             pci_config_get32(config_handle, PCI_CONF_BASE3));
 465         cmn_err(CE_CONT, " BASE 4      = [0x%x]\n",
 466             pci_config_get32(config_handle, PCI_CONF_BASE4));
 467         cmn_err(CE_CONT, " BASE 5      = [0x%x]\n",
 468             pci_config_get32(config_handle, PCI_CONF_BASE5));
 469         cmn_err(CE_CONT, " Cardbus CIS = [0x%x]\n",
 470             pci_config_get32(config_handle, PCI_CONF_CIS));
 471         cmn_err(CE_CONT, " Sub VID     = [0x%x]\n",
 472             pci_config_get16(config_handle, PCI_CONF_SUBVENID));
 473         cmn_err(CE_CONT, " Sub SID     = [0x%x]\n",
 474             pci_config_get16(config_handle, PCI_CONF_SUBSYSID));
 475         cmn_err(CE_CONT, " ROM         = [0x%x]\n",
 476             pci_config_get32(config_handle, PCI_CONF_ROM));
 477         cmn_err(CE_CONT, " I Line      = [0x%x]\n",
 478             pci_config_get8(config_handle, PCI_CONF_ILINE));
 479         cmn_err(CE_CONT, " I Pin       = [0x%x]\n",
 480             pci_config_get8(config_handle, PCI_CONF_IPIN));
 481         cmn_err(CE_CONT, " Max Grant   = [0x%x]\n",
 482             pci_config_get8(config_handle, PCI_CONF_MIN_G));
 483         cmn_err(CE_CONT, " Max Latent  = [0x%x]\n",
 484             pci_config_get8(config_handle, PCI_CONF_MAX_L));
 485 }
 486 
 487 static void
 488 pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle)
 489 {
 490         if ((pcicfg_debug & 1) == 0)
 491                 return;
 492 
 493         pcicfg_dump_common_config(config_handle);
 494 
 495         cmn_err(CE_CONT, "........................................\n");
 496 
 497         cmn_err(CE_CONT, " Pri Bus     = [0x%x]\n",
 498             pci_config_get8(config_handle, PCI_BCNF_PRIBUS));
 499         cmn_err(CE_CONT, " Sec Bus     = [0x%x]\n",
 500             pci_config_get8(config_handle, PCI_BCNF_SECBUS));
 501         cmn_err(CE_CONT, " Sub Bus     = [0x%x]\n",
 502             pci_config_get8(config_handle, PCI_BCNF_SUBBUS));
 503         cmn_err(CE_CONT, " Latency     = [0x%x]\n",
 504             pci_config_get8(config_handle, PCI_BCNF_LATENCY_TIMER));
 505         cmn_err(CE_CONT, " I/O Base LO = [0x%x]\n",
 506             pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW));
 507         cmn_err(CE_CONT, " I/O Lim LO  = [0x%x]\n",
 508             pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW));
 509         cmn_err(CE_CONT, " Sec. Status = [0x%x]\n",
 510             pci_config_get16(config_handle, PCI_BCNF_SEC_STATUS));
 511         cmn_err(CE_CONT, " Mem Base    = [0x%x]\n",
 512             pci_config_get16(config_handle, PCI_BCNF_MEM_BASE));
 513         cmn_err(CE_CONT, " Mem Limit   = [0x%x]\n",
 514             pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT));
 515         cmn_err(CE_CONT, " PF Mem Base = [0x%x]\n",
 516             pci_config_get16(config_handle, PCI_BCNF_PF_BASE_LOW));
 517         cmn_err(CE_CONT, " PF Mem Lim  = [0x%x]\n",
 518             pci_config_get16(config_handle, PCI_BCNF_PF_LIMIT_LOW));
 519         cmn_err(CE_CONT, " PF Base HI  = [0x%x]\n",
 520             pci_config_get32(config_handle, PCI_BCNF_PF_BASE_HIGH));
 521         cmn_err(CE_CONT, " PF Lim  HI  = [0x%x]\n",
 522             pci_config_get32(config_handle, PCI_BCNF_PF_LIMIT_HIGH));
 523         cmn_err(CE_CONT, " I/O Base HI = [0x%x]\n",
 524             pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI));
 525         cmn_err(CE_CONT, " I/O Lim HI  = [0x%x]\n",
 526             pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI));
 527         cmn_err(CE_CONT, " ROM addr    = [0x%x]\n",
 528             pci_config_get32(config_handle, PCI_BCNF_ROM));
 529         cmn_err(CE_CONT, " Intr Line   = [0x%x]\n",
 530             pci_config_get8(config_handle, PCI_BCNF_ILINE));
 531         cmn_err(CE_CONT, " Intr Pin    = [0x%x]\n",
 532             pci_config_get8(config_handle, PCI_BCNF_IPIN));
 533         cmn_err(CE_CONT, " Bridge Ctrl = [0x%x]\n",
 534             pci_config_get16(config_handle, PCI_BCNF_BCNTRL));
 535 }
 536 
 537 #endif
 538 
 539 
 540 int
 541 _init()
 542 {
 543         DEBUG0("PCI configurator installed - Fcode Interpretation/21554\n");
 544 
 545         mutex_init(&pcicfg_list_mutex, NULL, MUTEX_DRIVER, NULL);
 546         return (mod_install(&modlinkage));
 547 }
 548 
 549 int
 550 _fini(void)
 551 {
 552         int error;
 553 
 554         error = mod_remove(&modlinkage);
 555         if (error != 0) {
 556                 return (error);
 557         }
 558         mutex_destroy(&pcicfg_list_mutex);
 559         return (0);
 560 }
 561 
 562 int
 563 _info(modinfop)
 564 struct modinfo *modinfop;
 565 {
 566         return (mod_info(&modlinkage, modinfop));
 567 }
 568 
 569 /*ARGSUSED*/
 570 static uint8_t
 571 pcicfg_get_nslots(dev_info_t *dip, ddi_acc_handle_t handle)
 572 {
 573         uint8_t num_slots = 0;
 574         uint16_t cap_ptr;
 575 
 576         if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_HOTPLUG,
 577             &cap_ptr)) == DDI_SUCCESS) {
 578                 uint32_t config;
 579 
 580                 PCI_CAP_PUT8(handle, NULL, cap_ptr, PCI_HP_DWORD_SELECT_OFF,
 581                     PCI_HP_SLOT_CONFIGURATION_REG);
 582                 config = PCI_CAP_GET32(handle, NULL, cap_ptr,
 583                     PCI_HP_DWORD_DATA_OFF);
 584                 num_slots = config & 0x1F;
 585         } else if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_SLOT_ID, &cap_ptr))
 586             == DDI_SUCCESS) {
 587                 uint8_t esr_reg = PCI_CAP_GET8(handle, NULL,
 588                     cap_ptr, PCI_CAP_ID_REGS_OFF);
 589 
 590                 num_slots = PCI_CAPSLOT_NSLOTS(esr_reg);
 591         } else if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_ptr))
 592             == DDI_SUCCESS) {
 593                 int port_type = PCI_CAP_GET16(handle, NULL, cap_ptr,
 594                     PCIE_PCIECAP) & PCIE_PCIECAP_DEV_TYPE_MASK;
 595 
 596                 if ((port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) &&
 597                     (PCI_CAP_GET16(handle, NULL, cap_ptr, PCIE_PCIECAP)
 598                     & PCIE_PCIECAP_SLOT_IMPL))
 599                                 num_slots = 1;
 600         }
 601 
 602         DEBUG3("%s#%d has %d slots",
 603             ddi_get_name(dip), ddi_get_instance(dip), num_slots);
 604 
 605         return (num_slots);
 606 }
 607 
 608 /*ARGSUSED*/
 609 static uint8_t
 610 pcicfg_is_chassis(dev_info_t *dip, ddi_acc_handle_t handle)
 611 {
 612         uint16_t cap_ptr;
 613 
 614         if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_SLOT_ID, &cap_ptr)) !=
 615             DDI_FAILURE) {
 616 
 617                 uint8_t esr_reg = PCI_CAP_GET8(handle, NULL, cap_ptr, 2);
 618                 if (PCI_CAPSLOT_FIC(esr_reg))
 619                         return (B_TRUE);
 620         }
 621         return (B_FALSE);
 622 }
 623 
 624 /*ARGSUSED*/
 625 static int
 626 pcicfg_pcie_dev(dev_info_t *dip, int bus_type, pcicfg_err_regs_t *regs)
 627 {
 628         /* get parent device's device_type property */
 629         char *device_type;
 630         int rc = DDI_FAILURE;
 631         dev_info_t *pdip = ddi_get_parent(dip);
 632 
 633         regs->pcie_dev = 0;
 634         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
 635             DDI_PROP_DONTPASS, "device_type", &device_type)
 636             != DDI_PROP_SUCCESS) {
 637                 DEBUG2("device_type property missing for %s#%d",
 638                     ddi_get_name(pdip), ddi_get_instance(pdip));
 639                 return (DDI_FAILURE);
 640         }
 641         switch (bus_type) {
 642                 case PCICFG_DEVICE_TYPE_PCIE:
 643                         if (strcmp(device_type, "pciex") == 0) {
 644                                 rc = DDI_SUCCESS;
 645                                 regs->pcie_dev = 1;
 646                         }
 647                         break;
 648                 case PCICFG_DEVICE_TYPE_PCI:
 649                         if (strcmp(device_type, "pci") == 0)
 650                                 rc = DDI_SUCCESS;
 651                         break;
 652                 default:
 653                         break;
 654         }
 655         ddi_prop_free(device_type);
 656         return (rc);
 657 }
 658 
 659 /*ARGSUSED*/
 660 static int
 661 pcicfg_pcie_port_type(dev_info_t *dip, ddi_acc_handle_t handle)
 662 {
 663         int port_type = -1;
 664         uint16_t cap_ptr;
 665 
 666         if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_ptr)) !=
 667             DDI_FAILURE)
 668                 port_type = PCI_CAP_GET16(handle, NULL,
 669                     cap_ptr, PCIE_PCIECAP) & PCIE_PCIECAP_DEV_TYPE_MASK;
 670 
 671         return (port_type);
 672 }
 673 
 674 static int
 675 pcicfg_pcie_device_type(dev_info_t *dip, ddi_acc_handle_t handle)
 676 {
 677         int port_type = pcicfg_pcie_port_type(dip, handle);
 678 
 679         DEBUG1("device port_type = %x\n", port_type);
 680         /* No PCIe CAP regs, we are not PCIe device_type */
 681         if (port_type < 0)
 682                 return (DDI_FAILURE);
 683 
 684         /* check for all PCIe device_types */
 685         if ((port_type == PCIE_PCIECAP_DEV_TYPE_UP) ||
 686             (port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
 687             (port_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
 688             (port_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE))
 689                 return (DDI_SUCCESS);
 690 
 691         return (DDI_FAILURE);
 692 
 693 }
 694 
 695 /*
 696  * In the following functions ndi_devi_enter() without holding the
 697  * parent dip is sufficient. This is because  pci dr is driven through
 698  * opens on the nexus which is in the device tree path above the node
 699  * being operated on, and implicitly held due to the open.
 700  */
 701 
 702 /*
 703  * This entry point is called to configure a device (and
 704  * all its children) on the given bus. It is called when
 705  * a new device is added to the PCI domain.  This routine
 706  * will create the device tree and program the devices
 707  * registers.
 708  */
 709 
 710 int
 711 pcicfg_configure(dev_info_t *devi, uint_t device, uint_t function,
 712     pcicfg_flags_t flags)
 713 {
 714         uint_t bus;
 715         int len;
 716         int func;
 717         int trans_device;
 718         dev_info_t *new_device;
 719         pcicfg_bus_range_t pci_bus_range;
 720         int rv;
 721         int circ;
 722         uint_t highest_bus = 0;
 723         int ari_mode = B_FALSE;
 724         int max_function = PCICFG_MAX_FUNCTION;
 725         boolean_t is_pcie;
 726 
 727         if (flags == PCICFG_FLAG_ENABLE_ARI)
 728                 return (pcicfg_ari_configure(devi));
 729 
 730         /*
 731          * Start probing at the device specified in "device" on the
 732          * "bus" specified.
 733          */
 734         len = sizeof (pcicfg_bus_range_t);
 735         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
 736             "bus-range", (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
 737                 DEBUG0("no bus-range property\n");
 738                 return (PCICFG_FAILURE);
 739         }
 740 
 741         bus = pci_bus_range.lo; /* primary bus number of this bus node */
 742 
 743         is_pcie = is_pcie_fabric(devi);
 744 
 745         ndi_devi_enter(devi, &circ);
 746         for (func = 0; func < max_function; ) {
 747                 if ((function != PCICFG_ALL_FUNC) && (function != func))
 748                         goto next;
 749 
 750                 if (ari_mode)
 751                         trans_device = func >> 3;
 752                 else
 753                         trans_device = device;
 754 
 755                 DEBUG3("Configuring [0x%x][0x%x][0x%x]\n",
 756                     bus, trans_device, func & 7);
 757 
 758                 /*
 759                  * Try executing fcode if available.
 760                  */
 761                 switch (rv = pcicfg_fcode_probe(devi, bus, trans_device,
 762                     func & 7, &highest_bus, flags, is_pcie)) {
 763                         case PCICFG_FAILURE:
 764                                 DEBUG2("configure failed: "
 765                                     "bus [0x%x] device [0x%x]\n",
 766                                     bus, trans_device);
 767                                 break;
 768                         case PCICFG_NODEVICE:
 769                                 DEBUG3("no device : bus "
 770                                     "[0x%x] slot [0x%x] func [0x%x]\n",
 771                                     bus, trans_device, func & 7);
 772 
 773                                 /*
 774                                  * When walking the list of ARI functions
 775                                  * we don't expect to see a non-present
 776                                  * function, so we will stop walking
 777                                  * the function list.
 778                                  */
 779                                 if (ari_mode == B_TRUE)
 780                                         break;
 781 
 782                                 if (func)
 783                                         goto next;
 784                                 break;
 785                         default:
 786                                 DEBUG3("configure: bus => [%d] "
 787                                     "slot => [%d] func => [%d]\n",
 788                                     bus, trans_device, func & 7);
 789                                 break;
 790                 }
 791 
 792                 if (rv != PCICFG_SUCCESS)
 793                         break;
 794 
 795                 if ((new_device = pcicfg_devi_find(devi,
 796                     trans_device, (func & 7))) == NULL) {
 797                         DEBUG0("Did'nt find device node just created\n");
 798                         goto cleanup;
 799                 }
 800 
 801 next:
 802                 /*
 803                  * Determine if ARI Forwarding should be enabled.
 804                  */
 805                 if (func == 0) {
 806                         if ((pcie_ari_supported(devi)
 807                             == PCIE_ARI_FORW_SUPPORTED) &&
 808                             (pcie_ari_device(new_device) == PCIE_ARI_DEVICE)) {
 809                                 if (pcie_ari_enable(devi) == DDI_SUCCESS) {
 810                                         (void) ddi_prop_create(DDI_DEV_T_NONE,
 811                                             devi,  DDI_PROP_CANSLEEP,
 812                                             "ari-enabled", NULL, 0);
 813 
 814                                         ari_mode = B_TRUE;
 815                                         max_function = PCICFG_MAX_ARI_FUNCTION;
 816                                 }
 817                         }
 818                 }
 819 
 820                 if (ari_mode == B_TRUE) {
 821                         int next_function;
 822 
 823                         DEBUG0("Next Function - ARI Device\n");
 824                         if (pcie_ari_get_next_function(new_device,
 825                             &next_function) != DDI_SUCCESS)
 826                                 goto cleanup;
 827 
 828                         /*
 829                          * Check if there are more fucntions to probe.
 830                          */
 831                         if (next_function == 0) {
 832                                 DEBUG0("Next Function - "
 833                                     "No more ARI Functions\n");
 834                                 break;
 835                         }
 836                         func = next_function;
 837                 } else {
 838                         func++;
 839                 }
 840 
 841                 DEBUG1("Next Function - %x\n", func);
 842         }
 843 
 844         ndi_devi_exit(devi, circ);
 845 
 846         if (func == 0)
 847                 return (PCICFG_FAILURE);        /* probe failed */
 848         else
 849                 return (PCICFG_SUCCESS);
 850 
 851 cleanup:
 852         /*
 853          * Clean up a partially created "probe state" tree.
 854          * There are no resources allocated to the in the
 855          * probe state.
 856          */
 857         if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED)
 858                 max_function = PCICFG_MAX_ARI_FUNCTION;
 859         else
 860                 max_function = PCICFG_MAX_FUNCTION;
 861 
 862         for (func = 0; func < max_function; func++) {
 863 
 864                 if (max_function == PCICFG_MAX_ARI_FUNCTION)
 865                         trans_device = func >> 3; /* ARI Device */
 866                 else
 867                         trans_device = device;
 868 
 869                 if ((new_device = pcicfg_devi_find(devi,
 870                     trans_device, (func & 0x7))) == NULL) {
 871                         DEBUG0("No more devices to clean up\n");
 872                         continue;
 873                 }
 874 
 875                 DEBUG2("Cleaning up device [0x%x] function [0x%x]\n",
 876                     trans_device, func & 7);
 877                 /*
 878                  * If this was a bridge device it will have a
 879                  * probe handle - if not, no harm in calling this.
 880                  */
 881                 (void) pcicfg_destroy_phdl(new_device);
 882 
 883                 if (is_pcie) {
 884                         /*
 885                          * Free bus_t structure
 886                          */
 887                         if (ddi_get_child(new_device) != NULL)
 888                                 pcie_fab_fini_bus(new_device, PCIE_BUS_ALL);
 889 
 890                         pcie_fini_bus(new_device, PCIE_BUS_ALL);
 891                 }
 892                 /*
 893                  * This will free up the node
 894                  */
 895                 (void) ndi_devi_offline(new_device, NDI_DEVI_REMOVE);
 896         }
 897         ndi_devi_exit(devi, circ);
 898 
 899         return (PCICFG_FAILURE);
 900 }
 901 
 902 /*
 903  * configure the child nodes of ntbridge. new_device points to ntbridge itself
 904  */
 905 /*ARGSUSED*/
 906 static uint_t
 907 pcicfg_configure_ntbridge(dev_info_t *new_device, uint_t bus, uint_t device)
 908 {
 909         int bus_range[2], rc = PCICFG_FAILURE, rc1, max_devs = 0;
 910         int                     devno;
 911         dev_info_t              *new_ntbridgechild;
 912         ddi_acc_handle_t        config_handle;
 913         uint16_t                vid;
 914         uint64_t                next_bus;
 915         uint64_t                blen;
 916         ndi_ra_request_t        req;
 917         uint8_t                 pcie_device_type = 0;
 918 
 919         /*
 920          * If we need to do indirect config, lets create a property here
 921          * to let the child conf map routine know that it has to
 922          * go through the DDI calls, and not assume the devices are
 923          * mapped directly under the host.
 924          */
 925         if ((rc = ndi_prop_update_int(DDI_DEV_T_NONE, new_device,
 926             PCI_DEV_CONF_MAP_PROP, (int)DDI_SUCCESS))
 927             != DDI_SUCCESS) {
 928 
 929                 DEBUG0("Cannot create indirect conf map property.\n");
 930                 return ((uint_t)PCICFG_FAILURE);
 931         }
 932         if (pci_config_setup(new_device, &config_handle) != DDI_SUCCESS)
 933                 return ((uint_t)PCICFG_FAILURE);
 934         /* check if we are PCIe device */
 935         if (pcicfg_pcie_device_type(new_device, config_handle) == DDI_SUCCESS)
 936                 pcie_device_type = 1;
 937         pci_config_teardown(&config_handle);
 938 
 939         /* create Bus node properties for ntbridge. */
 940         if (pcicfg_set_busnode_props(new_device, pcie_device_type, -1, -1) !=
 941             PCICFG_SUCCESS) {
 942                 DEBUG0("Failed to set busnode props\n");
 943                 return (rc);
 944         }
 945 
 946         /* For now: Lets only support one layer of child */
 947         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
 948         req.ra_len = 1;
 949         if (ndi_ra_alloc(ddi_get_parent(new_device), &req,
 950             &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
 951             NDI_RA_PASS) != NDI_SUCCESS) {
 952                 DEBUG0("ntbridge: Failed to get a bus number\n");
 953                 return (rc);
 954         }
 955 
 956         DEBUG1("ntbridge bus range start  ->[%d]\n", next_bus);
 957 
 958         /*
 959          * Following will change, as we detect more bridges
 960          * on the way.
 961          */
 962         bus_range[0] = (int)next_bus;
 963         bus_range[1] = (int)next_bus;
 964 
 965         if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_device,
 966             "bus-range", bus_range, 2) != DDI_SUCCESS) {
 967                 DEBUG0("Cannot set ntbridge bus-range property");
 968                 return (rc);
 969         }
 970 
 971         /*
 972          * The other interface (away from the host) will be
 973          * initialized by the nexus driver when it loads.
 974          * We just have to set the registers and the nexus driver
 975          * figures out the rest.
 976          */
 977 
 978         /*
 979          * finally, lets load and attach the driver
 980          * before configuring children of ntbridge.
 981          */
 982         rc = ndi_devi_online(new_device, NDI_NO_EVENT|NDI_CONFIG);
 983         if (rc != NDI_SUCCESS) {
 984                 cmn_err(CE_WARN,
 985                     "pcicfg: Fail: can\'t load non-transparent bridge \
 986                     driver.\n");
 987                 rc = PCICFG_FAILURE;
 988                 return (rc);
 989         }
 990         DEBUG0("pcicfg: Success loading nontransparent bridge nexus driver..");
 991 
 992         /* Now set aside pci resources for our children. */
 993         if (pcicfg_ntbridge_allocate_resources(new_device) !=
 994             PCICFG_SUCCESS) {
 995                 max_devs = 0;
 996                 rc = PCICFG_FAILURE;
 997         } else
 998                 max_devs = PCICFG_MAX_DEVICE;
 999 
1000         /* Probe devices on 2nd bus */
1001         for (devno = pcicfg_start_devno; devno < max_devs; devno++) {
1002 
1003                 if (ndi_devi_alloc(new_device, DEVI_PSEUDO_NEXNAME,
1004                     (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild)
1005                     != NDI_SUCCESS) {
1006 
1007                         DEBUG0("pcicfg: Failed to alloc test node\n");
1008                         rc = PCICFG_FAILURE;
1009                         break;
1010                 }
1011 
1012                 if (pcicfg_add_config_reg(new_ntbridgechild, next_bus, devno, 0)
1013                     != DDI_PROP_SUCCESS) {
1014                         cmn_err(CE_WARN,
1015                             "Failed to add conf reg for ntbridge child.\n");
1016                         (void) ndi_devi_free(new_ntbridgechild);
1017                         rc = PCICFG_FAILURE;
1018                         break;
1019                 }
1020 
1021                 if ((rc = pci_config_setup(new_ntbridgechild,
1022                     &config_handle)) != PCICFG_SUCCESS) {
1023                         cmn_err(CE_WARN,
1024                             "Cannot map ntbridge child %x\n", devno);
1025                         (void) ndi_devi_free(new_ntbridgechild);
1026                         rc = PCICFG_FAILURE;
1027                         break;
1028                 }
1029 
1030                 /*
1031                  * See if there is any PCI HW at this location
1032                  * by reading the Vendor ID.  If it returns with 0xffff
1033                  * then there is no hardware at this location.
1034                  */
1035                 vid = pci_config_get16(config_handle, PCI_CONF_VENID);
1036 
1037                 pci_config_teardown(&config_handle);
1038                 (void) ndi_devi_free(new_ntbridgechild);
1039                 if (vid == 0xffff)
1040                         continue;
1041 
1042                 /* Lets fake attachments points for each child, */
1043                 if (pcicfg_configure(new_device, devno, PCICFG_ALL_FUNC, 0)
1044                     != PCICFG_SUCCESS) {
1045                         int old_dev = pcicfg_start_devno;
1046 
1047                         cmn_err(CE_WARN,
1048                         "Error configuring ntbridge child dev=%d\n", devno);
1049 
1050                         rc = PCICFG_FAILURE;
1051                         while (old_dev != devno) {
1052                                 if (pcicfg_ntbridge_unconfigure_child(
1053                                     new_device, old_dev) == PCICFG_FAILURE)
1054 
1055                                         cmn_err(CE_WARN,
1056                                             "Unconfig Error ntbridge child "
1057                                             "dev=%d\n", old_dev);
1058                                 old_dev++;
1059                         }
1060                         break;
1061                 }
1062         } /* devno loop */
1063         DEBUG1("ntbridge: finish probing 2nd bus, rc=%d\n", rc);
1064 
1065         if (rc != PCICFG_FAILURE)
1066                 rc = pcicfg_ntbridge_configure_done(new_device);
1067         else {
1068                 pcicfg_phdl_t *entry = pcicfg_find_phdl(new_device);
1069                 uint_t                  *bus;
1070                 int                     k;
1071 
1072                 if (ddi_getlongprop(DDI_DEV_T_ANY, new_device,
1073                     DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
1074                     &k) != DDI_PROP_SUCCESS) {
1075                         DEBUG0("Failed to read bus-range property\n");
1076                         rc = PCICFG_FAILURE;
1077                         return (rc);
1078                 }
1079 
1080                 DEBUG2("Need to free bus [%d] range [%d]\n",
1081                     bus[0], bus[1] - bus[0] + 1);
1082 
1083                 if (ndi_ra_free(ddi_get_parent(new_device),
1084                     (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
1085                     NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
1086                         DEBUG0("Failed to free a bus number\n");
1087                         rc = PCICFG_FAILURE;
1088                         /*
1089                          * Don't forget to free up memory from ddi_getlongprop
1090                          */
1091                         kmem_free((caddr_t)bus, k);
1092 
1093                         return (rc);
1094                 }
1095 
1096                 /*
1097                  * Since no memory allocations are done for non transparent
1098                  * bridges (but instead we just set the handle with the
1099                  * already allocated memory, we just need to reset the
1100                  * following values before calling the destroy_phdl()
1101                  * function next, otherwise the it will try to free
1102                  * memory allocated as in case of a transparent bridge.
1103                  */
1104                 entry->memory_len = 0;
1105                 entry->io_len = 0;
1106                 /* the following will free hole data. */
1107                 (void) pcicfg_destroy_phdl(new_device);
1108                 /*
1109                  * Don't forget to free up memory from ddi_getlongprop
1110                  */
1111                 kmem_free((caddr_t)bus, k);
1112         }
1113 
1114         /*
1115          * Unload driver just in case child configure failed!
1116          */
1117         rc1 = ndi_devi_offline(new_device, NDI_NO_EVENT);
1118         DEBUG1("pcicfg: now unloading the ntbridge driver. rc1=%d\n", rc1);
1119         if (rc1 != NDI_SUCCESS) {
1120                 cmn_err(CE_WARN,
1121                     "pcicfg: can\'t unload ntbridge driver children.\n");
1122                 rc = PCICFG_FAILURE;
1123         }
1124 
1125         return (rc);
1126 }
1127 
1128 static int
1129 pcicfg_ntbridge_allocate_resources(dev_info_t *dip)
1130 {
1131         pcicfg_phdl_t           *phdl;
1132         ndi_ra_request_t        *mem_request;
1133         ndi_ra_request_t        *io_request;
1134         uint64_t                boundbase, boundlen;
1135 
1136         phdl = pcicfg_find_phdl(dip);
1137         ASSERT(phdl);
1138 
1139         mem_request = &phdl->mem_req;
1140         io_request  = &phdl->io_req;
1141 
1142         phdl->error = PCICFG_SUCCESS;
1143 
1144         /* Set Memory space handle for ntbridge */
1145         if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1146             PCI_BASE_SPACE_MEM) != DDI_SUCCESS) {
1147                 cmn_err(CE_WARN,
1148                     "ntbridge: Mem resource information failure\n");
1149                 phdl->memory_len  = 0;
1150                 return (PCICFG_FAILURE);
1151         }
1152         mem_request->ra_boundbase = boundbase;
1153         mem_request->ra_boundlen = boundbase + boundlen;
1154         mem_request->ra_len = boundlen;
1155         mem_request->ra_align_mask =
1156             PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
1157         mem_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1158 
1159         /*
1160          * mem_request->ra_len =
1161          * PCICFG_ROUND_UP(mem_request->ra_len, PCICFG_MEMGRAN);
1162          */
1163 
1164         phdl->memory_base = phdl->memory_last = boundbase;
1165         phdl->memory_len  = boundlen;
1166         phdl->mem_hole.start = phdl->memory_base;
1167         phdl->mem_hole.len = mem_request->ra_len;
1168         phdl->mem_hole.next = (hole_t *)NULL;
1169 
1170         DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of memory\n",
1171             boundlen, mem_request->ra_len);
1172 
1173         /* set up a memory resource map for NT bridge */
1174         if (ndi_ra_map_setup(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
1175                 DEBUG0("Can not setup ntbridge memory resource map\n");
1176                 return (PCICFG_FAILURE);
1177         }
1178         /* initialize the memory map */
1179         if (ndi_ra_free(dip, boundbase, boundlen, NDI_RA_TYPE_MEM,
1180             NDI_RA_PASS) != NDI_SUCCESS) {
1181                 DEBUG0("Can not initalize ntbridge memory resource map\n");
1182                 return (PCICFG_FAILURE);
1183         }
1184         /* Set IO space handle for ntbridge */
1185         if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1186             PCI_BASE_SPACE_IO) != DDI_SUCCESS) {
1187                 cmn_err(CE_WARN, "ntbridge: IO resource information failure\n");
1188                 phdl->io_len  = 0;
1189                 return (PCICFG_FAILURE);
1190         }
1191         io_request->ra_len = boundlen;
1192         io_request->ra_align_mask =
1193             PCICFG_IOGRAN - 1;   /* 4K alignment on I/O space */
1194         io_request->ra_boundbase = boundbase;
1195         io_request->ra_boundlen = boundbase + boundlen;
1196         io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1197 
1198         /*
1199          * io_request->ra_len =
1200          * PCICFG_ROUND_UP(io_request->ra_len, PCICFG_IOGRAN);
1201          */
1202 
1203         phdl->io_base = phdl->io_last = (uint32_t)boundbase;
1204         phdl->io_len  = (uint32_t)boundlen;
1205         phdl->io_hole.start = phdl->io_base;
1206         phdl->io_hole.len = io_request->ra_len;
1207         phdl->io_hole.next = (hole_t *)NULL;
1208 
1209         DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of IO\n",
1210             boundlen, io_request->ra_len);
1211 
1212         DEBUG2("MEMORY BASE = [0x%x] length [0x%x]\n",
1213             phdl->memory_base, phdl->memory_len);
1214         DEBUG2("IO     BASE = [0x%x] length [0x%x]\n",
1215             phdl->io_base, phdl->io_len);
1216 
1217         /* set up a IO resource map for NT bridge */
1218         if (ndi_ra_map_setup(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) {
1219                 DEBUG0("Can not setup ntbridge memory resource map\n");
1220                 return (PCICFG_FAILURE);
1221         }
1222         /* initialize the IO map */
1223         if (ndi_ra_free(dip, boundbase, boundlen, NDI_RA_TYPE_IO,
1224             NDI_RA_PASS) != NDI_SUCCESS) {
1225                 DEBUG0("Can not initalize ntbridge memory resource map\n");
1226                 return (PCICFG_FAILURE);
1227         }
1228 
1229         return (PCICFG_SUCCESS);
1230 }
1231 
1232 static int
1233 pcicfg_ntbridge_configure_done(dev_info_t *dip)
1234 {
1235         pcicfg_range_t range[PCICFG_RANGE_LEN];
1236         pcicfg_phdl_t           *entry;
1237         uint_t                  len;
1238         pcicfg_bus_range_t      bus_range;
1239         int                     new_bus_range[2];
1240 
1241         DEBUG1("Configuring children for %llx\n", dip);
1242 
1243         entry = pcicfg_find_phdl(dip);
1244         ASSERT(entry);
1245 
1246         bzero((caddr_t)range,
1247             sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
1248         range[1].child_hi = range[1].parent_hi |=
1249             (PCI_REG_REL_M | PCI_ADDR_MEM32);
1250         range[1].child_lo = range[1].parent_lo = (uint32_t)entry->memory_base;
1251 
1252         range[0].child_hi = range[0].parent_hi |=
1253             (PCI_REG_REL_M | PCI_ADDR_IO);
1254         range[0].child_lo = range[0].parent_lo = (uint32_t)entry->io_base;
1255 
1256         len = sizeof (pcicfg_bus_range_t);
1257         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1258             "bus-range", (caddr_t)&bus_range, (int *)&len) != DDI_SUCCESS) {
1259                 DEBUG0("no bus-range property\n");
1260                 return (PCICFG_FAILURE);
1261         }
1262 
1263         new_bus_range[0] = bus_range.lo;        /* primary bus number */
1264         if (entry->highest_bus) {    /* secondary bus number */
1265                 if (entry->highest_bus < bus_range.lo) {
1266                         cmn_err(CE_WARN,
1267                             "ntbridge bus range invalid !(%d,%d)\n",
1268                             bus_range.lo, entry->highest_bus);
1269                         new_bus_range[1] = bus_range.lo + entry->highest_bus;
1270                 }
1271                 else
1272                         new_bus_range[1] = entry->highest_bus;
1273         }
1274         else
1275                 new_bus_range[1] = bus_range.hi;
1276 
1277         DEBUG2("ntbridge: bus range lo=%x, hi=%x\n",
1278             new_bus_range[0], new_bus_range[1]);
1279 
1280         if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1281             "bus-range", new_bus_range, 2) != DDI_SUCCESS) {
1282                 DEBUG0("Failed to set bus-range property");
1283                 entry->error = PCICFG_FAILURE;
1284                 return (PCICFG_FAILURE);
1285         }
1286 
1287 #ifdef DEBUG
1288         {
1289                 uint64_t        unused;
1290                 unused = pcicfg_unused_space(&entry->io_hole, &len);
1291                 DEBUG2("ntbridge: Unused IO space %llx bytes over %d holes\n",
1292                     unused, len);
1293         }
1294 #endif
1295 
1296         range[0].size_lo = entry->io_len;
1297         if (pcicfg_update_ranges_prop(dip, &range[0])) {
1298                 DEBUG0("Failed to update ranges (i/o)\n");
1299                 entry->error = PCICFG_FAILURE;
1300                 return (PCICFG_FAILURE);
1301         }
1302 
1303 #ifdef DEBUG
1304         {
1305                 uint64_t        unused;
1306                 unused = pcicfg_unused_space(&entry->mem_hole, &len);
1307                 DEBUG2("ntbridge: Unused Mem space %llx bytes over %d holes\n",
1308                     unused, len);
1309         }
1310 #endif
1311 
1312         range[1].size_lo = entry->memory_len;
1313         if (pcicfg_update_ranges_prop(dip, &range[1])) {
1314                 DEBUG0("Failed to update ranges (memory)\n");
1315                 entry->error = PCICFG_FAILURE;
1316                 return (PCICFG_FAILURE);
1317         }
1318 
1319         return (PCICFG_SUCCESS);
1320 }
1321 
1322 static int
1323 pcicfg_ntbridge_unconfigure_child(dev_info_t *new_device, uint_t devno)
1324 {
1325 
1326         dev_info_t      *new_ntbridgechild;
1327         int             len, bus;
1328         uint16_t        vid;
1329         ddi_acc_handle_t        config_handle;
1330         pcicfg_bus_range_t pci_bus_range;
1331 
1332         len = sizeof (pcicfg_bus_range_t);
1333         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, new_device, DDI_PROP_DONTPASS,
1334             "bus-range", (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
1335                 DEBUG0("no bus-range property\n");
1336                 return (PCICFG_FAILURE);
1337         }
1338 
1339         bus = pci_bus_range.lo; /* primary bus number of this bus node */
1340 
1341         if (ndi_devi_alloc(new_device, DEVI_PSEUDO_NEXNAME,
1342             (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild) != NDI_SUCCESS) {
1343 
1344                 DEBUG0("pcicfg: Failed to alloc test node\n");
1345                 return (PCICFG_FAILURE);
1346         }
1347 
1348         if (pcicfg_add_config_reg(new_ntbridgechild, bus, devno, 0)
1349             != DDI_PROP_SUCCESS) {
1350                 cmn_err(CE_WARN,
1351                 "Unconfigure: Failed to add conf reg prop for ntbridge "
1352                     "child.\n");
1353                 (void) ndi_devi_free(new_ntbridgechild);
1354                 return (PCICFG_FAILURE);
1355         }
1356 
1357         if (pcicfg_config_setup(new_ntbridgechild, &config_handle)
1358             != DDI_SUCCESS) {
1359                 cmn_err(CE_WARN,
1360                     "pcicfg: Cannot map ntbridge child %x\n", devno);
1361                 (void) ndi_devi_free(new_ntbridgechild);
1362                 return (PCICFG_FAILURE);
1363         }
1364 
1365         /*
1366          * See if there is any PCI HW at this location
1367          * by reading the Vendor ID.  If it returns with 0xffff
1368          * then there is no hardware at this location.
1369          */
1370         vid = pci_config_get16(config_handle, PCI_CONF_VENID);
1371 
1372         pci_config_teardown(&config_handle);
1373         (void) ndi_devi_free(new_ntbridgechild);
1374         if (vid == 0xffff)
1375                 return (PCICFG_NODEVICE);
1376 
1377         return (pcicfg_unconfigure(new_device, devno, PCICFG_ALL_FUNC, 0));
1378 }
1379 
1380 static int
1381 pcicfg_ntbridge_unconfigure(dev_info_t *dip)
1382 {
1383         pcicfg_phdl_t *entry = pcicfg_find_phdl(dip);
1384         uint_t                  *bus;
1385         int                     k, rc = PCICFG_FAILURE;
1386 
1387         if (entry->memory_len)
1388                 if (ndi_ra_map_destroy(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
1389                         DEBUG1("cannot destroy ntbridge memory map size=%x\n",
1390                             entry->memory_len);
1391                         return (PCICFG_FAILURE);
1392                 }
1393         if (entry->io_len)
1394                 if (ndi_ra_map_destroy(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) {
1395                         DEBUG1("cannot destroy ntbridge io map size=%x\n",
1396                             entry->io_len);
1397                         return (PCICFG_FAILURE);
1398                 }
1399         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
1400             DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
1401             &k) != DDI_PROP_SUCCESS) {
1402                 DEBUG0("ntbridge: Failed to read bus-range property\n");
1403                 return (rc);
1404         }
1405 
1406         DEBUG2("ntbridge: Need to free bus [%d] range [%d]\n",
1407             bus[0], bus[1] - bus[0] + 1);
1408 
1409         if (ndi_ra_free(ddi_get_parent(dip),
1410             (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
1411             NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
1412                 DEBUG0("ntbridge: Failed to free a bus number\n");
1413                 /*
1414                  * Don't forget to free up memory from ddi_getlongprop
1415                  */
1416                 kmem_free((caddr_t)bus, k);
1417 
1418                 return (rc);
1419         }
1420 
1421         /*
1422          * Don't forget to free up memory from ddi_getlongprop
1423          */
1424         kmem_free((caddr_t)bus, k);
1425 
1426         /*
1427          * Since our resources will be freed at the parent level,
1428          * just reset these values.
1429          */
1430         entry->memory_len = 0;
1431         entry->io_len = 0;
1432         /* the following will also free hole data. */
1433         return (pcicfg_destroy_phdl(dip));
1434 
1435 }
1436 
1437 static int
1438 pcicfg_is_ntbridge(dev_info_t *dip)
1439 {
1440         ddi_acc_handle_t        config_handle;
1441         uint8_t         class, subclass;
1442         int             rc = DDI_SUCCESS;
1443 
1444         if (pcicfg_config_setup(dip, &config_handle) != DDI_SUCCESS) {
1445                 cmn_err(CE_WARN,
1446                     "pcicfg: cannot map config space, to get map type\n");
1447                 return (DDI_FAILURE);
1448         }
1449         class = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
1450         subclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
1451 
1452         /* check for class=6, subclass=9, for non transparent bridges.  */
1453         if ((class != PCI_CLASS_BRIDGE) || (subclass != PCI_BRIDGE_STBRIDGE))
1454                 rc = DDI_FAILURE;
1455 
1456         DEBUG3("pcicfg: checking device %x,%x for indirect map. rc=%d\n",
1457             pci_config_get16(config_handle, PCI_CONF_VENID),
1458             pci_config_get16(config_handle, PCI_CONF_DEVID),
1459             rc);
1460         pci_config_teardown(&config_handle);
1461         return (rc);
1462 }
1463 
1464 /*
1465  * this function is called only for SPARC platforms, where we may have
1466  * a mix n' match of direct vs indirectly mapped configuration space.
1467  * On x86, this function does not get called. We always return TRUE
1468  * via a macro for x86.
1469  */
1470 /*ARGSUSED*/
1471 static int
1472 pcicfg_indirect_map(dev_info_t *dip)
1473 {
1474 #if defined(__sparc)
1475         int rc = DDI_FAILURE;
1476 
1477         if (ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), 0,
1478             PCI_DEV_CONF_MAP_PROP, DDI_FAILURE) != DDI_FAILURE)
1479                 rc = DDI_SUCCESS;
1480         else
1481                 if (ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
1482                     0, PCI_BUS_CONF_MAP_PROP,
1483                     DDI_FAILURE) != DDI_FAILURE)
1484                         rc = DDI_SUCCESS;
1485         DEBUG1("pci conf map = %d", rc);
1486         return (rc);
1487 #else
1488         return (DDI_SUCCESS);
1489 #endif
1490 }
1491 
1492 static uint_t
1493 pcicfg_get_ntbridge_child_range(dev_info_t *dip, uint64_t *boundbase,
1494                                 uint64_t *boundlen, uint_t space_type)
1495 {
1496         int             length, found = DDI_FAILURE, acount, i, ibridge;
1497         pci_regspec_t   *assigned;
1498 
1499         if ((ibridge = pcicfg_is_ntbridge(dip)) == DDI_FAILURE)
1500                 return (found);
1501 
1502         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
1503             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
1504             &length) != DDI_PROP_SUCCESS) {
1505                 DEBUG1("Failed to get assigned-addresses property %llx\n", dip);
1506                 return (found);
1507         }
1508         DEBUG1("pcicfg: ntbridge child range: dip = %s\n",
1509             ddi_driver_name(dip));
1510 
1511         acount = length / sizeof (pci_regspec_t);
1512 
1513         for (i = 0; i < acount; i++) {
1514                 if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1515                     pcicfg_indirect_map_devs[ibridge].mem_range_bar_offset) &&
1516                     (space_type == PCI_BASE_SPACE_MEM)) {
1517                         found = DDI_SUCCESS;
1518                         break;
1519                 } else {
1520                         if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1521                             pcicfg_indirect_map_devs[ibridge].\
1522                             io_range_bar_offset) &&
1523                             (space_type == PCI_BASE_SPACE_IO)) {
1524                                 found = DDI_SUCCESS;
1525                                 break;
1526                         }
1527                 }
1528         }
1529         DEBUG3("pcicfg: ntbridge child range: space=%x, base=%lx, len=%lx\n",
1530             space_type, assigned[i].pci_phys_low, assigned[i].pci_size_low);
1531 
1532         if (found == DDI_SUCCESS)  {
1533                 *boundbase = assigned[i].pci_phys_low;
1534                 *boundlen = assigned[i].pci_size_low;
1535         }
1536 
1537         kmem_free(assigned, length);
1538         return (found);
1539 }
1540 
1541 /*
1542  * This will turn  resources allocated by pcicfg_configure()
1543  * and remove the device tree from the Hotplug Connection (CN)
1544  * and below.  The routine assumes the devices have their
1545  * drivers detached.
1546  */
1547 int
1548 pcicfg_unconfigure(dev_info_t *devi, uint_t device, uint_t function,
1549     pcicfg_flags_t flags)
1550 {
1551         dev_info_t *child_dip;
1552         int func;
1553         int i;
1554         int max_function;
1555         int trans_device;
1556         int circ;
1557         boolean_t is_pcie;
1558 
1559         if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED)
1560                 max_function = PCICFG_MAX_ARI_FUNCTION;
1561         else
1562                 max_function = PCICFG_MAX_FUNCTION;
1563 
1564         /*
1565          * Cycle through devices to make sure none are busy.
1566          * If a single device is busy fail the whole unconfigure.
1567          */
1568         is_pcie = is_pcie_fabric(devi);
1569 
1570         ndi_devi_enter(devi, &circ);
1571         for (func = 0; func < max_function; func++) {
1572 
1573                 if (max_function == PCICFG_MAX_ARI_FUNCTION)
1574                         trans_device = func >> 3; /* ARI Device */
1575                 else
1576                         trans_device = device;
1577 
1578                 if ((child_dip = pcicfg_devi_find(devi, trans_device,
1579                     (func & 0x7))) == NULL)
1580                         continue;
1581 
1582                 if (ndi_devi_offline(child_dip, NDI_UNCONFIG) == NDI_SUCCESS)
1583                         continue;
1584                 /*
1585                  * Device function is busy. Before returning we have to
1586                  * put all functions back online which were taken
1587                  * offline during the process.
1588                  */
1589                 DEBUG2("Device [0x%x] function [%x] is busy\n", device, func);
1590                 /*
1591                  * If we are only asked to offline one specific function,
1592                  * and that fails, we just simply return.
1593                  */
1594                 if (function != PCICFG_ALL_FUNC)
1595                         return (PCICFG_FAILURE);
1596 
1597                 for (i = 0; i < func; i++) {
1598 
1599                         if (max_function == PCICFG_MAX_ARI_FUNCTION)
1600                                 trans_device = i >> 3;
1601 
1602                         if ((child_dip =
1603                             pcicfg_devi_find(devi, trans_device, (i & 7)))
1604                             == NULL) {
1605                                 DEBUG0(
1606                                     "No more devices to put back on line!!\n");
1607                                 /*
1608                                  * Made it through all functions
1609                                  */
1610                                 continue;
1611                         }
1612                         if (ndi_devi_online(child_dip, NDI_CONFIG)
1613                             != NDI_SUCCESS) {
1614                                 DEBUG0("Failed to put back devices state\n");
1615                                 goto fail;
1616                         }
1617                 }
1618                 goto fail;
1619         }
1620 
1621         /*
1622          * Now, tear down all devinfo nodes for this Connector.
1623          */
1624         for (func = 0; func < max_function; func++) {
1625 
1626                 if (max_function == PCICFG_MAX_ARI_FUNCTION)
1627                         trans_device = func >> 3; /* ARI Device */
1628                 else
1629                         trans_device = device;
1630 
1631                 if ((child_dip = pcicfg_devi_find(devi,
1632                     trans_device, (func & 7))) == NULL) {
1633                         DEBUG0("No more devices to tear down!\n");
1634                         continue;
1635                 }
1636 
1637                 DEBUG2("Tearing down device [0x%x] function [0x%x]\n",
1638                     trans_device, (func & 7));
1639 
1640                 if (pcicfg_is_ntbridge(child_dip) != DDI_FAILURE)
1641                         if (pcicfg_ntbridge_unconfigure(child_dip) !=
1642                             PCICFG_SUCCESS) {
1643                                 cmn_err(CE_WARN,
1644                                     "ntbridge: unconfigure failed\n");
1645                                 goto fail;
1646                         }
1647 
1648                 if (pcicfg_teardown_device(child_dip, flags, is_pcie)
1649                     != PCICFG_SUCCESS) {
1650                         DEBUG2("Failed to tear down device [0x%x]"
1651                             "function [0x%x]\n",
1652                             trans_device, func & 7);
1653                         goto fail;
1654                 }
1655         }
1656 
1657         if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED) {
1658                 (void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "ari-enabled");
1659                 (void) pcie_ari_disable(devi);
1660         }
1661 
1662         ndi_devi_exit(devi, circ);
1663         return (PCICFG_SUCCESS);
1664 
1665 fail:
1666         ndi_devi_exit(devi, circ);
1667         return (PCICFG_FAILURE);
1668 }
1669 
1670 static int
1671 pcicfg_teardown_device(dev_info_t *dip, pcicfg_flags_t flags, boolean_t is_pcie)
1672 {
1673         ddi_acc_handle_t        config_handle;
1674 
1675         /*
1676          * Free up resources associated with 'dip'
1677          */
1678         if (pcicfg_free_resources(dip, flags) != PCICFG_SUCCESS) {
1679                 DEBUG0("Failed to free resources\n");
1680                 return (PCICFG_FAILURE);
1681         }
1682 
1683         /*
1684          * This will disable the device
1685          */
1686         if (pci_config_setup(dip, &config_handle) != PCICFG_SUCCESS) {
1687                 return (PCICFG_FAILURE);
1688         }
1689 
1690         pcicfg_device_off(config_handle);
1691         pci_config_teardown(&config_handle);
1692 
1693         /*
1694          * free pcie_bus_t for the sub-tree
1695          */
1696         if (is_pcie) {
1697                 if (ddi_get_child(dip) != NULL)
1698                         pcie_fab_fini_bus(dip, PCIE_BUS_ALL);
1699 
1700                 pcie_fini_bus(dip, PCIE_BUS_ALL);
1701         }
1702 
1703         /*
1704          * The framework provides this routine which can
1705          * tear down a sub-tree.
1706          */
1707         if (ndi_devi_offline(dip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
1708                 DEBUG0("Failed to offline and remove node\n");
1709                 return (PCICFG_FAILURE);
1710         }
1711 
1712         return (PCICFG_SUCCESS);
1713 }
1714 
1715 /*
1716  * BEGIN GENERIC SUPPORT ROUTINES
1717  */
1718 static pcicfg_phdl_t *
1719 pcicfg_find_phdl(dev_info_t *dip)
1720 {
1721         pcicfg_phdl_t *entry;
1722         mutex_enter(&pcicfg_list_mutex);
1723         for (entry = pcicfg_phdl_list; entry != NULL; entry = entry->next) {
1724                 if (entry->dip == dip) {
1725                         mutex_exit(&pcicfg_list_mutex);
1726                         return (entry);
1727                 }
1728         }
1729         mutex_exit(&pcicfg_list_mutex);
1730 
1731         /*
1732          * Did'nt find entry - create one
1733          */
1734         return (pcicfg_create_phdl(dip));
1735 }
1736 
1737 static pcicfg_phdl_t *
1738 pcicfg_create_phdl(dev_info_t *dip)
1739 {
1740         pcicfg_phdl_t *new;
1741 
1742         new = (pcicfg_phdl_t *)kmem_zalloc(sizeof (pcicfg_phdl_t),
1743             KM_SLEEP);
1744 
1745         new->dip = dip;
1746         mutex_enter(&pcicfg_list_mutex);
1747         new->next = pcicfg_phdl_list;
1748         pcicfg_phdl_list = new;
1749         mutex_exit(&pcicfg_list_mutex);
1750 
1751         return (new);
1752 }
1753 
1754 static int
1755 pcicfg_destroy_phdl(dev_info_t *dip)
1756 {
1757         pcicfg_phdl_t *entry;
1758         pcicfg_phdl_t *follow = NULL;
1759 
1760         mutex_enter(&pcicfg_list_mutex);
1761         for (entry = pcicfg_phdl_list; entry != NULL; follow = entry,
1762             entry = entry->next) {
1763                 if (entry->dip == dip) {
1764                         if (entry == pcicfg_phdl_list) {
1765                                 pcicfg_phdl_list = entry->next;
1766                         } else {
1767                                 follow->next = entry->next;
1768                         }
1769                         /*
1770                          * If this entry has any allocated memory
1771                          * or IO space associated with it, that
1772                          * must be freed up.
1773                          */
1774                         if (entry->memory_len > 0) {
1775                                 (void) ndi_ra_free(ddi_get_parent(dip),
1776                                     entry->memory_base,
1777                                     entry->memory_len,
1778                                     NDI_RA_TYPE_MEM, NDI_RA_PASS);
1779                         }
1780                         pcicfg_free_hole(&entry->mem_hole);
1781 
1782                         if (entry->io_len > 0) {
1783                                 (void) ndi_ra_free(ddi_get_parent(dip),
1784                                     entry->io_base,
1785                                     entry->io_len,
1786                                     NDI_RA_TYPE_IO, NDI_RA_PASS);
1787                         }
1788                         pcicfg_free_hole(&entry->io_hole);
1789 
1790                         /*
1791                          * Destroy this entry
1792                          */
1793                         kmem_free((caddr_t)entry, sizeof (pcicfg_phdl_t));
1794                         mutex_exit(&pcicfg_list_mutex);
1795                         return (PCICFG_SUCCESS);
1796                 }
1797         }
1798         mutex_exit(&pcicfg_list_mutex);
1799         /*
1800          * Did'nt find the entry
1801          */
1802         return (PCICFG_FAILURE);
1803 }
1804 
1805 static int
1806 pcicfg_program_ap(dev_info_t *dip)
1807 {
1808         pcicfg_phdl_t *phdl;
1809         uint8_t header_type;
1810         ddi_acc_handle_t handle;
1811         pcicfg_phdl_t *entry;
1812 
1813         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
1814                 DEBUG0("Failed to map config space!\n");
1815                 return (PCICFG_FAILURE);
1816 
1817         }
1818 
1819         header_type = pci_config_get8(handle, PCI_CONF_HEADER);
1820 
1821         (void) pcicfg_config_teardown(&handle);
1822 
1823         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
1824 
1825                 if (pcicfg_allocate_chunk(dip) != PCICFG_SUCCESS) {
1826                         DEBUG0("Not enough memory to hotplug\n");
1827                         (void) pcicfg_destroy_phdl(dip);
1828                         return (PCICFG_FAILURE);
1829                 }
1830 
1831                 phdl = pcicfg_find_phdl(dip);
1832                 ASSERT(phdl);
1833 
1834                 (void) pcicfg_bridge_assign(dip, (void *)phdl);
1835 
1836                 if (phdl->error != PCICFG_SUCCESS) {
1837                         DEBUG0("Problem assigning bridge\n");
1838                         (void) pcicfg_destroy_phdl(dip);
1839                         return (phdl->error);
1840                 }
1841 
1842                 /*
1843                  * Successfully allocated and assigned
1844                  * memory.  Set the memory and IO length
1845                  * to zero so when the handle is freed up
1846                  * it will not de-allocate assigned resources.
1847                  */
1848                 entry = (pcicfg_phdl_t *)phdl;
1849 
1850                 entry->memory_len = entry->io_len = 0;
1851 
1852                 /*
1853                  * Free up the "entry" structure.
1854                  */
1855                 (void) pcicfg_destroy_phdl(dip);
1856         } else {
1857                 if (pcicfg_device_assign(dip) != PCICFG_SUCCESS) {
1858                         return (PCICFG_FAILURE);
1859                 }
1860         }
1861         return (PCICFG_SUCCESS);
1862 }
1863 
1864 static int
1865 pcicfg_bridge_assign(dev_info_t *dip, void *hdl)
1866 {
1867         ddi_acc_handle_t handle;
1868         pci_regspec_t *reg;
1869         int length;
1870         int rcount;
1871         int i;
1872         int offset;
1873         uint64_t mem_answer;
1874         uint32_t io_answer;
1875         int count;
1876         uint8_t header_type;
1877         pcicfg_range_t range[PCICFG_RANGE_LEN];
1878         int bus_range[2];
1879 
1880         pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
1881 
1882         DEBUG1("bridge assign: assigning addresses to %s\n", ddi_get_name(dip));
1883 
1884         if (entry == NULL) {
1885                 DEBUG0("Failed to get entry\n");
1886                 return (DDI_WALK_TERMINATE);
1887         }
1888 
1889         entry->error = PCICFG_SUCCESS;
1890 
1891         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
1892                 DEBUG0("Failed to map config space!\n");
1893                 entry->error = PCICFG_FAILURE;
1894                 return (DDI_WALK_TERMINATE);
1895         }
1896 
1897         header_type = pci_config_get8(handle, PCI_CONF_HEADER);
1898 
1899         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
1900 
1901                 bzero((caddr_t)range,
1902                     sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
1903 
1904                 (void) pcicfg_setup_bridge(entry, handle, dip);
1905 
1906                 range[0].child_hi = range[0].parent_hi |=
1907                     (PCI_REG_REL_M | PCI_ADDR_IO);
1908                 range[0].child_lo = range[0].parent_lo =
1909                     entry->io_last;
1910                 range[1].child_hi = range[1].parent_hi |=
1911                     (PCI_REG_REL_M | PCI_ADDR_MEM32);
1912                 range[1].child_lo = range[1].parent_lo =
1913                     entry->memory_last;
1914 
1915                 ndi_devi_enter(dip, &count);
1916                 ddi_walk_devs(ddi_get_child(dip),
1917                     pcicfg_bridge_assign, (void *)entry);
1918                 ndi_devi_exit(dip, count);
1919 
1920                 (void) pcicfg_update_bridge(entry, handle);
1921 
1922                 bus_range[0] = pci_config_get8(handle, PCI_BCNF_SECBUS);
1923                 bus_range[1] = pci_config_get8(handle, PCI_BCNF_SUBBUS);
1924 
1925                 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1926                     "bus-range", bus_range, 2) != DDI_SUCCESS) {
1927                         DEBUG0("Failed to set bus-range property");
1928                         entry->error = PCICFG_FAILURE;
1929                         return (DDI_WALK_TERMINATE);
1930                 }
1931 
1932                 if (entry->io_len > 0) {
1933                         range[0].size_lo = entry->io_last - entry->io_base;
1934                         if (pcicfg_update_ranges_prop(dip, &range[0])) {
1935                                 DEBUG0("Failed to update ranges (i/o)\n");
1936                                 entry->error = PCICFG_FAILURE;
1937                                 return (DDI_WALK_TERMINATE);
1938                         }
1939                 }
1940                 if (entry->memory_len > 0) {
1941                         range[1].size_lo =
1942                             entry->memory_last - entry->memory_base;
1943                         if (pcicfg_update_ranges_prop(dip, &range[1])) {
1944                                 DEBUG0("Failed to update ranges (memory)\n");
1945                                 entry->error = PCICFG_FAILURE;
1946                                 return (DDI_WALK_TERMINATE);
1947                         }
1948                 }
1949 
1950                 (void) pcicfg_device_on(handle);
1951 
1952                 PCICFG_DUMP_BRIDGE_CONFIG(handle);
1953 
1954                 return (DDI_WALK_PRUNECHILD);
1955         }
1956 
1957         /*
1958          * If there is an interrupt pin set program
1959          * interrupt line with default values.
1960          */
1961         if (pci_config_get8(handle, PCI_CONF_IPIN)) {
1962                 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
1963         }
1964 
1965         /*
1966          * A single device (under a bridge).
1967          * For each "reg" property with a length, allocate memory
1968          * and program the base registers.
1969          */
1970         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
1971             DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
1972             &length) != DDI_PROP_SUCCESS) {
1973                 DEBUG0("Failed to read reg property\n");
1974                 entry->error = PCICFG_FAILURE;
1975                 return (DDI_WALK_TERMINATE);
1976         }
1977 
1978         rcount = length / sizeof (pci_regspec_t);
1979         offset = PCI_CONF_BASE0;
1980         for (i = 0; i < rcount; i++) {
1981                 if ((reg[i].pci_size_low != 0)||
1982                     (reg[i].pci_size_hi != 0)) {
1983 
1984                         offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
1985 
1986                         switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
1987                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
1988 
1989                                 (void) pcicfg_get_mem(entry,
1990                                     reg[i].pci_size_low, &mem_answer);
1991                                 pci_config_put64(handle, offset, mem_answer);
1992                                 DEBUG2("REGISTER off %x (64)LO ----> [0x%x]\n",
1993                                     offset,
1994                                     pci_config_get32(handle, offset));
1995                                 DEBUG2("REGISTER off %x (64)HI ----> [0x%x]\n",
1996                                     offset + 4,
1997                                     pci_config_get32(handle, offset + 4));
1998 
1999                                 reg[i].pci_phys_low = PCICFG_HIADDR(mem_answer);
2000                                 reg[i].pci_phys_mid  =
2001                                     PCICFG_LOADDR(mem_answer);
2002 
2003                                 break;
2004 
2005                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2006                                 /* allocate memory space from the allocator */
2007 
2008                                 (void) pcicfg_get_mem(entry,
2009                                     reg[i].pci_size_low, &mem_answer);
2010                                 pci_config_put32(handle,
2011                                     offset, (uint32_t)mem_answer);
2012 
2013                                 DEBUG2("REGISTER off %x(32)LO ----> [0x%x]\n",
2014                                     offset,
2015                                     pci_config_get32(handle, offset));
2016 
2017                                 reg[i].pci_phys_low = (uint32_t)mem_answer;
2018 
2019                                 break;
2020                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2021                                 /* allocate I/O space from the allocator */
2022 
2023                                 (void) pcicfg_get_io(entry,
2024                                     reg[i].pci_size_low, &io_answer);
2025                                 pci_config_put32(handle, offset, io_answer);
2026 
2027                                 DEBUG2("REGISTER off %x (I/O)LO ----> [0x%x]\n",
2028                                     offset,
2029                                     pci_config_get32(handle, offset));
2030 
2031                                 reg[i].pci_phys_low = io_answer;
2032 
2033                                 break;
2034                         default:
2035                                 DEBUG0("Unknown register type\n");
2036                                 kmem_free(reg, length);
2037                                 (void) pcicfg_config_teardown(&handle);
2038                                 entry->error = PCICFG_FAILURE;
2039                                 return (DDI_WALK_TERMINATE);
2040                         } /* switch */
2041 
2042                         /*
2043                          * Now that memory locations are assigned,
2044                          * update the assigned address property.
2045                          */
2046                         if (pcicfg_update_assigned_prop(dip,
2047                             &reg[i]) != PCICFG_SUCCESS) {
2048                                 kmem_free(reg, length);
2049                                 (void) pcicfg_config_teardown(&handle);
2050                                 entry->error = PCICFG_FAILURE;
2051                                 return (DDI_WALK_TERMINATE);
2052                         }
2053                 }
2054         }
2055         (void) pcicfg_device_on(handle);
2056 
2057         PCICFG_DUMP_DEVICE_CONFIG(handle);
2058 
2059         (void) pcicfg_config_teardown(&handle);
2060         /*
2061          * Don't forget to free up memory from ddi_getlongprop
2062          */
2063         kmem_free((caddr_t)reg, length);
2064 
2065         return (DDI_WALK_CONTINUE);
2066 }
2067 
2068 static int
2069 pcicfg_device_assign(dev_info_t *dip)
2070 {
2071         ddi_acc_handle_t        handle;
2072         pci_regspec_t           *reg;
2073         int                     length;
2074         int                     rcount;
2075         int                     i;
2076         int                     offset;
2077         ndi_ra_request_t        request;
2078         uint64_t                answer;
2079         uint64_t                alen;
2080 
2081         DEBUG1("%llx now under configuration\n", dip);
2082 
2083         /*
2084          * XXX Failure here should be noted
2085          */
2086         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2087             DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
2088             &length) != DDI_PROP_SUCCESS) {
2089                 DEBUG0("Failed to read reg property\n");
2090                 return (PCICFG_FAILURE);
2091         }
2092 
2093         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2094                 DEBUG0("Failed to map config space!\n");
2095                 /*
2096                  * Don't forget to free up memory from ddi_getlongprop
2097                  */
2098                 kmem_free((caddr_t)reg, length);
2099 
2100                 return (PCICFG_FAILURE);
2101         }
2102 
2103         /*
2104          * A single device
2105          *
2106          * For each "reg" property with a length, allocate memory
2107          * and program the base registers.
2108          */
2109 
2110         /*
2111          * If there is an interrupt pin set program
2112          * interrupt line with default values.
2113          */
2114         if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2115                 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2116         }
2117 
2118         bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2119 
2120         request.ra_flags = NDI_RA_ALIGN_SIZE;
2121         request.ra_boundbase = 0;
2122         request.ra_boundlen = PCICFG_4GIG_LIMIT;
2123 
2124         rcount = length / sizeof (pci_regspec_t);
2125         for (i = 0; i < rcount; i++) {
2126                 if ((reg[i].pci_size_low != 0)||
2127                     (reg[i].pci_size_hi != 0)) {
2128 
2129                         offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
2130                         request.ra_len = reg[i].pci_size_low;
2131 
2132                         switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
2133                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2134                                 request.ra_flags &= ~NDI_RA_ALLOC_BOUNDED;
2135                                 /* allocate memory space from the allocator */
2136                                 if (ndi_ra_alloc(ddi_get_parent(dip),
2137                                     &request, &answer, &alen,
2138                                     NDI_RA_TYPE_MEM, NDI_RA_PASS)
2139                                     != NDI_SUCCESS) {
2140                                         DEBUG0("Failed to allocate 64b mem\n");
2141                                         kmem_free(reg, length);
2142                                         (void) pcicfg_config_teardown(&handle);
2143                                         return (PCICFG_FAILURE);
2144                                 }
2145                                 DEBUG3("64 addr = [0x%x.%x] len [0x%x]\n",
2146                                     PCICFG_HIADDR(answer),
2147                                     PCICFG_LOADDR(answer),
2148                                     alen);
2149                                 /* program the low word */
2150                                 pci_config_put32(handle,
2151                                     offset, PCICFG_LOADDR(answer));
2152 
2153                                 /* program the high word */
2154                                 pci_config_put32(handle, offset + 4,
2155                                     PCICFG_HIADDR(answer));
2156 
2157                                 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2158                                 reg[i].pci_phys_mid = PCICFG_HIADDR(answer);
2159 
2160                                 /* adjust to 32b address space when possible */
2161                                 if ((answer + alen) <= PCICFG_4GIG_LIMIT)
2162                                         reg[i].pci_phys_hi ^=
2163                                             PCI_ADDR_MEM64 ^ PCI_ADDR_MEM32;
2164                                 break;
2165 
2166                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2167                                 request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
2168                                 /* allocate memory space from the allocator */
2169                                 if (ndi_ra_alloc(ddi_get_parent(dip),
2170                                     &request, &answer, &alen,
2171                                     NDI_RA_TYPE_MEM, NDI_RA_PASS)
2172                                     != NDI_SUCCESS) {
2173                                         DEBUG0("Failed to allocate 32b mem\n");
2174                                         kmem_free(reg, length);
2175                                         (void) pcicfg_config_teardown(&handle);
2176                                         return (PCICFG_FAILURE);
2177                                 }
2178                                 DEBUG3("32 addr = [0x%x.%x] len [0x%x]\n",
2179                                     PCICFG_HIADDR(answer),
2180                                     PCICFG_LOADDR(answer),
2181                                     alen);
2182                                 /* program the low word */
2183                                 pci_config_put32(handle,
2184                                     offset, PCICFG_LOADDR(answer));
2185 
2186                                 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2187                                 break;
2188 
2189                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2190                                 /* allocate I/O space from the allocator */
2191                                 request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
2192                                 if (ndi_ra_alloc(ddi_get_parent(dip),
2193                                     &request, &answer, &alen,
2194                                     NDI_RA_TYPE_IO, NDI_RA_PASS)
2195                                     != NDI_SUCCESS) {
2196                                         DEBUG0("Failed to allocate I/O\n");
2197                                         kmem_free(reg, length);
2198                                         (void) pcicfg_config_teardown(&handle);
2199                                         return (PCICFG_FAILURE);
2200                                 }
2201                                 DEBUG3("I/O addr = [0x%x.%x] len [0x%x]\n",
2202                                     PCICFG_HIADDR(answer),
2203                                     PCICFG_LOADDR(answer),
2204                                     alen);
2205                                 pci_config_put32(handle,
2206                                     offset, PCICFG_LOADDR(answer));
2207 
2208                                 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2209                                 break;
2210 
2211                         default:
2212                                 DEBUG0("Unknown register type\n");
2213                                 kmem_free(reg, length);
2214                                 (void) pcicfg_config_teardown(&handle);
2215                                 return (PCICFG_FAILURE);
2216                         } /* switch */
2217 
2218                         /*
2219                          * Now that memory locations are assigned,
2220                          * update the assigned address property.
2221                          */
2222 
2223                         if (pcicfg_update_assigned_prop(dip,
2224                             &reg[i]) != PCICFG_SUCCESS) {
2225                                 kmem_free(reg, length);
2226                                 (void) pcicfg_config_teardown(&handle);
2227                                 return (PCICFG_FAILURE);
2228                         }
2229                 }
2230         }
2231 
2232         (void) pcicfg_device_on(handle);
2233         kmem_free(reg, length);
2234 
2235         PCICFG_DUMP_DEVICE_CONFIG(handle);
2236 
2237         (void) pcicfg_config_teardown(&handle);
2238         return (PCICFG_SUCCESS);
2239 }
2240 
2241 static int
2242 pcicfg_device_assign_readonly(dev_info_t *dip)
2243 {
2244         ddi_acc_handle_t        handle;
2245         pci_regspec_t           *assigned;
2246         int                     length;
2247         int                     acount;
2248         int                     i;
2249         ndi_ra_request_t        request;
2250         uint64_t                answer;
2251         uint64_t                alen;
2252 
2253 
2254         DEBUG1("%llx now under configuration\n", dip);
2255 
2256         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2257             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
2258             &length) != DDI_PROP_SUCCESS) {
2259                 DEBUG0("Failed to read assigned-addresses property\n");
2260                 return (PCICFG_FAILURE);
2261         }
2262 
2263         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2264                 DEBUG0("Failed to map config space!\n");
2265                 /*
2266                  * Don't forget to free up memory from ddi_getlongprop
2267                  */
2268                 kmem_free((caddr_t)assigned, length);
2269 
2270                 return (PCICFG_FAILURE);
2271         }
2272 
2273         /*
2274          * For each "assigned-addresses" property entry with a length,
2275          * call the memory allocation routines to return the
2276          * resource.
2277          */
2278         /*
2279          * If there is an interrupt pin set program
2280          * interrupt line with default values.
2281          */
2282         if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2283                 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2284         }
2285 
2286         bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2287 
2288         request.ra_flags = NDI_RA_ALLOC_SPECIFIED; /* specified addr */
2289         request.ra_boundbase = 0;
2290         request.ra_boundlen = PCICFG_4GIG_LIMIT;
2291 
2292         acount = length / sizeof (pci_regspec_t);
2293         for (i = 0; i < acount; i++) {
2294                 if ((assigned[i].pci_size_low != 0)||
2295                     (assigned[i].pci_size_hi != 0)) {
2296 
2297                         request.ra_len = assigned[i].pci_size_low;
2298 
2299                         switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
2300                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2301                                 request.ra_addr = (uint64_t)PCICFG_LADDR(
2302                                     assigned[i].pci_phys_low,
2303                                     assigned[i].pci_phys_mid);
2304 
2305                                 /* allocate memory space from the allocator */
2306                                 if (ndi_ra_alloc(ddi_get_parent(dip),
2307                                     &request, &answer, &alen,
2308                                     NDI_RA_TYPE_MEM, NDI_RA_PASS)
2309                                     != NDI_SUCCESS) {
2310                                         DEBUG0("Failed to allocate 64b mem\n");
2311                                         kmem_free(assigned, length);
2312                                         return (PCICFG_FAILURE);
2313                                 }
2314 
2315                                 break;
2316                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2317                                 request.ra_addr = (uint64_t)
2318                                     assigned[i].pci_phys_low;
2319 
2320                                 /* allocate memory space from the allocator */
2321                                 if (ndi_ra_alloc(ddi_get_parent(dip),
2322                                     &request, &answer, &alen,
2323                                     NDI_RA_TYPE_MEM, NDI_RA_PASS)
2324                                     != NDI_SUCCESS) {
2325                                         DEBUG0("Failed to allocate 32b mem\n");
2326                                         kmem_free(assigned, length);
2327                                         return (PCICFG_FAILURE);
2328                                 }
2329 
2330                                 break;
2331                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2332                                 request.ra_addr = (uint64_t)
2333                                     assigned[i].pci_phys_low;
2334 
2335                                 /* allocate I/O space from the allocator */
2336                                 if (ndi_ra_alloc(ddi_get_parent(dip),
2337                                     &request, &answer, &alen,
2338                                     NDI_RA_TYPE_IO, NDI_RA_PASS)
2339                                     != NDI_SUCCESS) {
2340                                         DEBUG0("Failed to allocate I/O\n");
2341                                         kmem_free(assigned, length);
2342                                         return (PCICFG_FAILURE);
2343                                 }
2344 
2345                                 break;
2346                         default:
2347                                 DEBUG0("Unknown register type\n");
2348                                 kmem_free(assigned, length);
2349                                 return (PCICFG_FAILURE);
2350                         } /* switch */
2351                 }
2352         }
2353 
2354         (void) pcicfg_device_on(handle);
2355         kmem_free(assigned, length);
2356 
2357         PCICFG_DUMP_DEVICE_CONFIG(handle);
2358 
2359         (void) pcicfg_config_teardown(&handle);
2360         return (PCICFG_SUCCESS);
2361 }
2362 
2363 /*
2364  * The "dip" passed to this routine is assumed to be
2365  * the device at the Hotplug Connection (CN). Currently it is
2366  * assumed to be a bridge.
2367  */
2368 static int
2369 pcicfg_allocate_chunk(dev_info_t *dip)
2370 {
2371         pcicfg_phdl_t           *phdl;
2372         ndi_ra_request_t        *mem_request;
2373         ndi_ra_request_t        *io_request;
2374         uint64_t                mem_answer;
2375         uint64_t                io_answer;
2376         int                     count;
2377         uint64_t                alen;
2378 
2379         /*
2380          * This should not find an existing entry - so
2381          * it will create a new one.
2382          */
2383         phdl = pcicfg_find_phdl(dip);
2384         ASSERT(phdl);
2385 
2386         mem_request = &phdl->mem_req;
2387         io_request  = &phdl->io_req;
2388 
2389         /*
2390          * From this point in the tree - walk the devices,
2391          * The function passed in will read and "sum" up
2392          * the memory and I/O requirements and put them in
2393          * structure "phdl".
2394          */
2395         ndi_devi_enter(ddi_get_parent(dip), &count);
2396         ddi_walk_devs(dip, pcicfg_sum_resources, (void *)phdl);
2397         ndi_devi_exit(ddi_get_parent(dip), count);
2398 
2399         if (phdl->error != PCICFG_SUCCESS) {
2400                 DEBUG0("Failure summing resources\n");
2401                 return (phdl->error);
2402         }
2403 
2404         /*
2405          * Call into the memory allocator with the request.
2406          * Record the addresses returned in the phdl
2407          */
2408         DEBUG1("Connector requires [0x%x] bytes of memory space\n",
2409             mem_request->ra_len);
2410         DEBUG1("Connector requires [0x%x] bytes of I/O space\n",
2411             io_request->ra_len);
2412 
2413         mem_request->ra_align_mask =
2414             PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
2415         io_request->ra_align_mask =
2416             PCICFG_IOGRAN - 1;   /* 4K alignment on I/O space */
2417         io_request->ra_boundbase = 0;
2418         io_request->ra_boundlen = PCICFG_4GIG_LIMIT;
2419         io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
2420 
2421         mem_request->ra_len =
2422             PCICFG_ROUND_UP(mem_request->ra_len, PCICFG_MEMGRAN);
2423 
2424         io_request->ra_len =
2425             PCICFG_ROUND_UP(io_request->ra_len, PCICFG_IOGRAN);
2426 
2427         if (ndi_ra_alloc(ddi_get_parent(dip),
2428             mem_request, &mem_answer, &alen,
2429             NDI_RA_TYPE_MEM, NDI_RA_PASS) != NDI_SUCCESS) {
2430                 DEBUG0("Failed to allocate memory\n");
2431                 return (PCICFG_FAILURE);
2432         }
2433 
2434         phdl->memory_base = phdl->memory_last = mem_answer;
2435         phdl->memory_len  = alen;
2436 
2437         phdl->mem_hole.start = phdl->memory_base;
2438         phdl->mem_hole.len = phdl->memory_len;
2439         phdl->mem_hole.next = (hole_t *)NULL;
2440 
2441         if (ndi_ra_alloc(ddi_get_parent(dip), io_request, &io_answer,
2442             &alen, NDI_RA_TYPE_IO, NDI_RA_PASS) != NDI_SUCCESS) {
2443 
2444                 DEBUG0("Failed to allocate I/O space\n");
2445                 (void) ndi_ra_free(ddi_get_parent(dip), mem_answer,
2446                     alen, NDI_RA_TYPE_MEM, NDI_RA_PASS);
2447                 phdl->memory_len = phdl->io_len = 0;
2448                 return (PCICFG_FAILURE);
2449         }
2450 
2451         phdl->io_base = phdl->io_last = (uint32_t)io_answer;
2452         phdl->io_len  = (uint32_t)alen;
2453 
2454         phdl->io_hole.start = phdl->io_base;
2455         phdl->io_hole.len = phdl->io_len;
2456         phdl->io_hole.next = (hole_t *)NULL;
2457 
2458         DEBUG2("MEMORY BASE = [0x%x] length [0x%x]\n",
2459             phdl->memory_base, phdl->memory_len);
2460         DEBUG2("IO     BASE = [0x%x] length [0x%x]\n",
2461             phdl->io_base, phdl->io_len);
2462 
2463         return (PCICFG_SUCCESS);
2464 }
2465 
2466 #ifdef  DEBUG
2467 /*
2468  * This function is useful in debug mode, where we can measure how
2469  * much memory was wasted/unallocated in bridge device's domain.
2470  */
2471 static uint64_t
2472 pcicfg_unused_space(hole_t *hole, uint32_t *hole_count)
2473 {
2474         uint64_t len = 0;
2475         uint32_t count = 0;
2476 
2477         do {
2478                 len += hole->len;
2479                 hole = hole->next;
2480                 count++;
2481         } while (hole);
2482         *hole_count = count;
2483         return (len);
2484 }
2485 #endif
2486 
2487 /*
2488  * This function frees data structures that hold the hole information
2489  * which are allocated in pcicfg_alloc_hole(). This is not freeing
2490  * any memory allocated through NDI calls.
2491  */
2492 static void
2493 pcicfg_free_hole(hole_t *addr_hole)
2494 {
2495         hole_t *nhole, *hole = addr_hole->next;
2496 
2497         while (hole) {
2498                 nhole = hole->next;
2499                 kmem_free(hole, sizeof (hole_t));
2500                 hole = nhole;
2501         }
2502 }
2503 
2504 static uint64_t
2505 pcicfg_alloc_hole(hole_t *addr_hole, uint64_t *alast, uint32_t length)
2506 {
2507         uint64_t actual_hole_start, ostart, olen;
2508         hole_t  *hole = addr_hole, *thole, *nhole;
2509 
2510         do {
2511                 actual_hole_start = PCICFG_ROUND_UP(hole->start, length);
2512                 if (((actual_hole_start - hole->start) + length) <= hole->len) {
2513                         DEBUG3("hole found. start %llx, len %llx, req=%x\n",
2514                             hole->start, hole->len, length);
2515                         ostart = hole->start;
2516                         olen = hole->len;
2517                         /* current hole parameters adjust */
2518                         if ((actual_hole_start - hole->start) == 0) {
2519                                 hole->start += length;
2520                                 hole->len -= length;
2521                                 if (hole->start > *alast)
2522                                         *alast = hole->start;
2523                         } else {
2524                                 hole->len = actual_hole_start - hole->start;
2525                                 nhole = (hole_t *)kmem_zalloc(sizeof (hole_t),
2526                                     KM_SLEEP);
2527                                 nhole->start = actual_hole_start + length;
2528                                 nhole->len = (ostart + olen) - nhole->start;
2529                                 nhole->next = NULL;
2530                                 thole = hole->next;
2531                                 hole->next = nhole;
2532                                 nhole->next = thole;
2533                                 if (nhole->start > *alast)
2534                                         *alast = nhole->start;
2535                                 DEBUG2("put new hole to %llx, %llx\n",
2536                                     nhole->start, nhole->len);
2537                         }
2538                         DEBUG2("adjust current hole to %llx, %llx\n",
2539                             hole->start, hole->len);
2540                         break;
2541                 }
2542                 actual_hole_start = 0;
2543                 hole = hole->next;
2544         } while (hole);
2545 
2546         DEBUG1("return hole at %llx\n", actual_hole_start);
2547         return (actual_hole_start);
2548 }
2549 
2550 static void
2551 pcicfg_get_mem(pcicfg_phdl_t *entry,
2552         uint32_t length, uint64_t *ans)
2553 {
2554         uint64_t new_mem;
2555 
2556         /* See if there is a hole, that can hold this request. */
2557         new_mem = pcicfg_alloc_hole(&entry->mem_hole, &entry->memory_last,
2558             length);
2559         if (new_mem) {  /* if non-zero, found a hole. */
2560                 if (ans != NULL)
2561                         *ans = new_mem;
2562         } else
2563                 cmn_err(CE_WARN, "No %u bytes memory window for %s\n",
2564                     length, ddi_get_name(entry->dip));
2565 }
2566 
2567 static void
2568 pcicfg_get_io(pcicfg_phdl_t *entry,
2569         uint32_t length, uint32_t *ans)
2570 {
2571         uint32_t new_io;
2572         uint64_t io_last;
2573 
2574         /*
2575          * See if there is a hole, that can hold this request.
2576          * Pass 64 bit parameters and then truncate to 32 bit.
2577          */
2578         io_last = entry->io_last;
2579         new_io = (uint32_t)pcicfg_alloc_hole(&entry->io_hole, &io_last, length);
2580         if (new_io) {   /* if non-zero, found a hole. */
2581                 entry->io_last = (uint32_t)io_last;
2582                 if (ans != NULL)
2583                         *ans = new_io;
2584         } else
2585                 cmn_err(CE_WARN, "No %u bytes IO space window for %s\n",
2586                     length, ddi_get_name(entry->dip));
2587 }
2588 
2589 static int
2590 pcicfg_sum_resources(dev_info_t *dip, void *hdl)
2591 {
2592         pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
2593         pci_regspec_t *pci_rp;
2594         int length;
2595         int rcount;
2596         int i;
2597         ndi_ra_request_t *mem_request;
2598         ndi_ra_request_t *io_request;
2599         uint8_t header_type;
2600         ddi_acc_handle_t handle;
2601 
2602         entry->error = PCICFG_SUCCESS;
2603 
2604         mem_request = &entry->mem_req;
2605         io_request =  &entry->io_req;
2606 
2607         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2608                 DEBUG0("Failed to map config space!\n");
2609                 entry->error = PCICFG_FAILURE;
2610                 return (DDI_WALK_TERMINATE);
2611         }
2612 
2613         header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2614 
2615         /*
2616          * If its a bridge - just record the highest bus seen
2617          */
2618         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2619 
2620                 if (entry->highest_bus < pci_config_get8(handle,
2621                     PCI_BCNF_SECBUS)) {
2622                         entry->highest_bus =
2623                             pci_config_get8(handle, PCI_BCNF_SECBUS);
2624                 }
2625 
2626                 (void) pcicfg_config_teardown(&handle);
2627                 entry->error = PCICFG_FAILURE;
2628                 return (DDI_WALK_CONTINUE);
2629         } else {
2630                 if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2631                     DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp,
2632                     &length) != DDI_PROP_SUCCESS) {
2633                         /*
2634                          * If one node in (the subtree of nodes)
2635                          * does'nt have a "reg" property fail the
2636                          * allocation.
2637                          */
2638                         entry->memory_len = 0;
2639                         entry->io_len = 0;
2640                         entry->error = PCICFG_FAILURE;
2641                         return (DDI_WALK_TERMINATE);
2642                 }
2643                 /*
2644                  * For each "reg" property with a length, add that to the
2645                  * total memory (or I/O) to allocate.
2646                  */
2647                 rcount = length / sizeof (pci_regspec_t);
2648 
2649                 for (i = 0; i < rcount; i++) {
2650 
2651                         switch (PCI_REG_ADDR_G(pci_rp[i].pci_phys_hi)) {
2652 
2653                         case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2654                                 mem_request->ra_len =
2655                                     pci_rp[i].pci_size_low +
2656                                     PCICFG_ROUND_UP(mem_request->ra_len,
2657                                     pci_rp[i].pci_size_low);
2658                                 DEBUG1("ADDING 32 --->0x%x\n",
2659                                     pci_rp[i].pci_size_low);
2660 
2661                         break;
2662                         case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2663                                 mem_request->ra_len =
2664                                     pci_rp[i].pci_size_low +
2665                                     PCICFG_ROUND_UP(mem_request->ra_len,
2666                                     pci_rp[i].pci_size_low);
2667                                 DEBUG1("ADDING 64 --->0x%x\n",
2668                                     pci_rp[i].pci_size_low);
2669 
2670                         break;
2671                         case PCI_REG_ADDR_G(PCI_ADDR_IO):
2672                                 io_request->ra_len =
2673                                     pci_rp[i].pci_size_low +
2674                                     PCICFG_ROUND_UP(io_request->ra_len,
2675                                     pci_rp[i].pci_size_low);
2676                                 DEBUG1("ADDING I/O --->0x%x\n",
2677                                     pci_rp[i].pci_size_low);
2678                         break;
2679                         default:
2680                             /* Config space register - not included */
2681                         break;
2682                         }
2683                 }
2684 
2685                 /*
2686                  * free the memory allocated by ddi_getlongprop
2687                  */
2688                 kmem_free(pci_rp, length);
2689 
2690                 /*
2691                  * continue the walk to the next sibling to sum memory
2692                  */
2693 
2694                 (void) pcicfg_config_teardown(&handle);
2695 
2696                 return (DDI_WALK_CONTINUE);
2697         }
2698 }
2699 
2700 static int
2701 pcicfg_find_resource_end(dev_info_t *dip, void *hdl)
2702 {
2703         pcicfg_phdl_t *entry_p = (pcicfg_phdl_t *)hdl;
2704         pci_regspec_t *pci_ap;
2705         pcicfg_range_t *ranges;
2706         int length;
2707         int rcount;
2708         int i;
2709 
2710         entry_p->error = PCICFG_SUCCESS;
2711 
2712         if (dip == entry_p->dip) {
2713                 DEBUG0("Don't include parent bridge node\n");
2714                 return (DDI_WALK_CONTINUE);
2715         }
2716 
2717         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2718             DDI_PROP_DONTPASS, "ranges",
2719             (caddr_t)&ranges,  &length) != DDI_PROP_SUCCESS) {
2720                 DEBUG0("Node doesn't have ranges\n");
2721                 goto ap;
2722         }
2723 
2724         rcount = length / sizeof (pcicfg_range_t);
2725 
2726         for (i = 0; i < rcount; i++) {
2727                 uint64_t base;
2728                 uint64_t mid = ranges[i].child_mid;
2729                 uint64_t lo = ranges[i].child_lo;
2730                 uint64_t size = ranges[i].size_lo;
2731 
2732                 switch (PCI_REG_ADDR_G(ranges[i].child_hi)) {
2733 
2734                 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2735                         base = entry_p->memory_base;
2736                         entry_p->memory_base = MAX(base, lo + size);
2737                         break;
2738                 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2739                         base = entry_p->memory_base;
2740                         entry_p->memory_base = MAX(base,
2741                             PCICFG_LADDR(lo, mid) + size);
2742                         break;
2743                 case PCI_REG_ADDR_G(PCI_ADDR_IO):
2744                         base = entry_p->io_base;
2745                         entry_p->io_base = MAX(base, lo + size);
2746                         break;
2747                 }
2748         }
2749 
2750         kmem_free(ranges, length);
2751         return (DDI_WALK_CONTINUE);
2752 
2753 ap:     if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2754             DDI_PROP_DONTPASS, "assigned-addresses",
2755             (caddr_t)&pci_ap,  &length) != DDI_PROP_SUCCESS) {
2756                 DEBUG0("Node doesn't have assigned-addresses\n");
2757                 return (DDI_WALK_CONTINUE);
2758         }
2759 
2760         rcount = length / sizeof (pci_regspec_t);
2761 
2762         for (i = 0; i < rcount; i++) {
2763 
2764                 switch (PCI_REG_ADDR_G(pci_ap[i].pci_phys_hi)) {
2765 
2766                 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2767                         if ((pci_ap[i].pci_phys_low +
2768                             pci_ap[i].pci_size_low) >
2769                             entry_p->memory_base) {
2770                                 entry_p->memory_base =
2771                                     pci_ap[i].pci_phys_low +
2772                                     pci_ap[i].pci_size_low;
2773                         }
2774                 break;
2775                 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2776                         if ((PCICFG_LADDR(pci_ap[i].pci_phys_low,
2777                             pci_ap[i].pci_phys_mid) +
2778                             pci_ap[i].pci_size_low) >
2779                             entry_p->memory_base) {
2780                                 entry_p->memory_base = PCICFG_LADDR(
2781                                     pci_ap[i].pci_phys_low,
2782                                     pci_ap[i].pci_phys_mid) +
2783                                     pci_ap[i].pci_size_low;
2784                         }
2785                 break;
2786                 case PCI_REG_ADDR_G(PCI_ADDR_IO):
2787                         if ((pci_ap[i].pci_phys_low +
2788                             pci_ap[i].pci_size_low) >
2789                             entry_p->io_base) {
2790                                 entry_p->io_base =
2791                                     pci_ap[i].pci_phys_low +
2792                                     pci_ap[i].pci_size_low;
2793                         }
2794                 break;
2795                 }
2796         }
2797 
2798         /*
2799          * free the memory allocated by ddi_getlongprop
2800          */
2801         kmem_free(pci_ap, length);
2802 
2803         /*
2804          * continue the walk to the next sibling to sum memory
2805          */
2806         return (DDI_WALK_CONTINUE);
2807 }
2808 
2809 static int
2810 pcicfg_free_bridge_resources(dev_info_t *dip)
2811 {
2812         pcicfg_range_t          *ranges;
2813         uint_t                  *bus;
2814         int                     k;
2815         int                     length;
2816         int                     i;
2817 
2818 
2819         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2820             DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges,
2821             &length) != DDI_PROP_SUCCESS) {
2822                 DEBUG0("Failed to read ranges property\n");
2823                 if (ddi_get_child(dip)) {
2824                         cmn_err(CE_WARN, "No ranges property found for %s",
2825                             ddi_get_name(dip));
2826                         /*
2827                          * strictly speaking, we can check for children with
2828                          * assigned-addresses but for now it is better to
2829                          * be conservative and assume that if there are child
2830                          * nodes, then they do consume PCI memory or IO
2831                          * resources, Hence return failure.
2832                          */
2833                         return (PCICFG_FAILURE);
2834                 }
2835                 length = 0;
2836 
2837         }
2838 
2839         for (i = 0; i < length / sizeof (pcicfg_range_t); i++) {
2840                 if (ranges[i].size_lo != 0 ||
2841                     ranges[i].size_hi != 0) {
2842                         switch (ranges[i].parent_hi & PCI_REG_ADDR_M) {
2843                                 case PCI_ADDR_IO:
2844                                         DEBUG2("Free I/O    "
2845                                             "base/length = [0x%x]/[0x%x]\n",
2846                                             ranges[i].child_lo,
2847                                             ranges[i].size_lo);
2848                                         if (ndi_ra_free(ddi_get_parent(dip),
2849                                             (uint64_t)ranges[i].child_lo,
2850                                             (uint64_t)ranges[i].size_lo,
2851                                             NDI_RA_TYPE_IO, NDI_RA_PASS)
2852                                             != NDI_SUCCESS) {
2853                                                 DEBUG0("Trouble freeing "
2854                                                     "PCI i/o space\n");
2855                                                 kmem_free(ranges, length);
2856                                                 return (PCICFG_FAILURE);
2857                                         }
2858                                 break;
2859                                 case PCI_ADDR_MEM32:
2860                                 case PCI_ADDR_MEM64:
2861                                         DEBUG3("Free Memory base/length = "
2862                                             "[0x%x.%x]/[0x%x]\n",
2863                                             ranges[i].child_mid,
2864                                             ranges[i].child_lo,
2865                                             ranges[i].size_lo)
2866                                         if (ndi_ra_free(ddi_get_parent(dip),
2867                                             PCICFG_LADDR(ranges[i].child_lo,
2868                                             ranges[i].child_mid),
2869                                             (uint64_t)ranges[i].size_lo,
2870                                             NDI_RA_TYPE_MEM, NDI_RA_PASS)
2871                                             != NDI_SUCCESS) {
2872                                                 DEBUG0("Trouble freeing "
2873                                                     "PCI memory space\n");
2874                                                 kmem_free(ranges, length);
2875                                                 return (PCICFG_FAILURE);
2876                                         }
2877                                 break;
2878                                 default:
2879                                         DEBUG0("Unknown memory space\n");
2880                                 break;
2881                         }
2882                 }
2883         }
2884 
2885         if (length)
2886                 kmem_free(ranges, length);
2887 
2888         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2889             DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
2890             &k) != DDI_PROP_SUCCESS) {
2891                 DEBUG0("Failed to read bus-range property\n");
2892                 return (PCICFG_FAILURE);
2893         }
2894 
2895         DEBUG2("Need to free bus [%d] range [%d]\n",
2896             bus[0], bus[1] - bus[0] + 1);
2897 
2898         if (ndi_ra_free(ddi_get_parent(dip),
2899             (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
2900             NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
2901                 /*EMPTY*/
2902                 DEBUG0("Failed to free a bus number\n");
2903         }
2904         /*
2905          * Don't forget to free up memory from ddi_getlongprop
2906          */
2907         kmem_free((caddr_t)bus, k);
2908 
2909         return (PCICFG_SUCCESS);
2910 }
2911 
2912 static int
2913 pcicfg_free_device_resources(dev_info_t *dip, pcicfg_flags_t flags)
2914 {
2915         pci_regspec_t *assigned;
2916 
2917         int length;
2918         int acount;
2919         int i;
2920 
2921         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2922             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
2923             &length) != DDI_PROP_SUCCESS) {
2924                 DEBUG0("Failed to read assigned-addresses property\n");
2925                 return (PCICFG_FAILURE);
2926         }
2927 
2928         /*
2929          * For each "assigned-addresses" property entry with a length,
2930          * call the memory allocation routines to return the
2931          * resource.
2932          */
2933         acount = length / sizeof (pci_regspec_t);
2934         for (i = 0; i < acount; i++) {
2935                 /*
2936                  * Workaround for Devconf (x86) bug to skip extra entries
2937                  * beyond the PCI_CONF_BASE5 offset. But we want to free up
2938                  * any memory for expansion roms if allocated.
2939                  */
2940                 if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) > PCI_CONF_BASE5) &&
2941                     (PCI_REG_REG_G(assigned[i].pci_phys_hi) != PCI_CONF_ROM))
2942                         break;
2943 
2944                 if (pcicfg_free_resource(dip, assigned[i], flags)) {
2945                         DEBUG1("pcicfg_free_device_resources - Trouble freeing "
2946                             "%x\n", assigned[i].pci_phys_hi);
2947                         /*
2948                          * Don't forget to free up memory from ddi_getlongprop
2949                          */
2950                         kmem_free((caddr_t)assigned, length);
2951 
2952                         return (PCICFG_FAILURE);
2953                 }
2954         }
2955         kmem_free(assigned, length);
2956         return (PCICFG_SUCCESS);
2957 }
2958 
2959 static int
2960 pcicfg_free_resources(dev_info_t *dip, pcicfg_flags_t flags)
2961 {
2962         ddi_acc_handle_t handle;
2963         uint8_t header_type;
2964 
2965         if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2966                 DEBUG0("Failed to map config space!\n");
2967                 return (PCICFG_FAILURE);
2968         }
2969 
2970         header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2971 
2972         (void) pci_config_teardown(&handle);
2973 
2974         /*
2975          * A different algorithm is used for bridges and leaf devices.
2976          */
2977         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2978                 /*
2979                  * We only support readonly probing for leaf devices.
2980                  */
2981                 if (flags & PCICFG_FLAG_READ_ONLY)
2982                         return (PCICFG_FAILURE);
2983 
2984                 if (pcicfg_free_bridge_resources(dip) != PCICFG_SUCCESS) {
2985                         DEBUG0("Failed freeing up bridge resources\n");
2986                         return (PCICFG_FAILURE);
2987                 }
2988         } else {
2989                 if (pcicfg_free_device_resources(dip, flags)
2990                     != PCICFG_SUCCESS) {
2991                         DEBUG0("Failed freeing up device resources\n");
2992                         return (PCICFG_FAILURE);
2993                 }
2994         }
2995         return (PCICFG_SUCCESS);
2996 }
2997 
2998 #ifndef _DONT_USE_1275_GENERIC_NAMES
2999 static char *
3000 pcicfg_get_class_name(uint32_t classcode)
3001 {
3002         struct pcicfg_name_entry *ptr;
3003 
3004         for (ptr = &pcicfg_class_lookup[0]; ptr->name != NULL; ptr++) {
3005                 if (ptr->class_code == classcode) {
3006                         return (ptr->name);
3007                 }
3008         }
3009         return (NULL);
3010 }
3011 #endif /* _DONT_USE_1275_GENERIC_NAMES */
3012 
3013 static dev_info_t *
3014 pcicfg_devi_find(dev_info_t *dip, uint_t device, uint_t function)
3015 {
3016         struct pcicfg_find_ctrl ctrl;
3017         int count;
3018 
3019         ctrl.device = device;
3020         ctrl.function = function;
3021         ctrl.dip = NULL;
3022 
3023         ndi_devi_enter(dip, &count);
3024         ddi_walk_devs(ddi_get_child(dip), pcicfg_match_dev, (void *)&ctrl);
3025         ndi_devi_exit(dip, count);
3026 
3027         return (ctrl.dip);
3028 }
3029 
3030 static int
3031 pcicfg_match_dev(dev_info_t *dip, void *hdl)
3032 {
3033         struct pcicfg_find_ctrl *ctrl = (struct pcicfg_find_ctrl *)hdl;
3034         pci_regspec_t *pci_rp;
3035         int length;
3036         int pci_dev;
3037         int pci_func;
3038 
3039         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
3040             DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
3041             (uint_t *)&length) != DDI_PROP_SUCCESS) {
3042                 ctrl->dip = NULL;
3043                 return (DDI_WALK_TERMINATE);
3044         }
3045 
3046         /* get the PCI device address info */
3047         pci_dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
3048         pci_func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
3049 
3050         /*
3051          * free the memory allocated by ddi_prop_lookup_int_array
3052          */
3053         ddi_prop_free(pci_rp);
3054 
3055 
3056         if ((pci_dev == ctrl->device) && (pci_func == ctrl->function)) {
3057                 /* found the match for the specified device address */
3058                 ctrl->dip = dip;
3059                 return (DDI_WALK_TERMINATE);
3060         }
3061 
3062         /*
3063          * continue the walk to the next sibling to look for a match.
3064          */
3065         return (DDI_WALK_PRUNECHILD);
3066 }
3067 
3068 static int
3069 pcicfg_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone)
3070 {
3071         int             alen;
3072         pci_regspec_t   *assigned;
3073         caddr_t         newreg;
3074         uint_t          status;
3075 
3076         DEBUG0("pcicfg_update_assigned_prop()\n");
3077         status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3078             "assigned-addresses", (caddr_t)&assigned, &alen);
3079         switch (status) {
3080                 case DDI_PROP_SUCCESS:
3081                 break;
3082                 case DDI_PROP_NO_MEMORY:
3083                         DEBUG0("no memory for assigned-addresses property\n");
3084                         return (PCICFG_FAILURE);
3085                 default:
3086                         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3087                             "assigned-addresses", (int *)newone,
3088                             sizeof (*newone)/sizeof (int));
3089 
3090                         (void) pcicfg_dump_assigned(dip);
3091 
3092                         return (PCICFG_SUCCESS);
3093         }
3094 
3095         /*
3096          * Allocate memory for the existing
3097          * assigned-addresses(s) plus one and then
3098          * build it.
3099          */
3100 
3101         newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
3102 
3103         bcopy(assigned, newreg, alen);
3104         bcopy(newone, newreg + alen, sizeof (*newone));
3105 
3106         /*
3107          * Write out the new "assigned-addresses" spec
3108          */
3109         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3110             "assigned-addresses", (int *)newreg,
3111             (alen + sizeof (*newone))/sizeof (int));
3112 
3113         kmem_free((caddr_t)newreg, alen+sizeof (*newone));
3114 
3115         /*
3116          * Don't forget to free up memory from ddi_getlongprop
3117          */
3118         kmem_free((caddr_t)assigned, alen);
3119 
3120         (void) pcicfg_dump_assigned(dip);
3121 
3122         return (PCICFG_SUCCESS);
3123 }
3124 static int
3125 pcicfg_update_ranges_prop(dev_info_t *dip, pcicfg_range_t *addition)
3126 {
3127         int             rlen;
3128         pcicfg_range_t  *ranges;
3129         caddr_t         newreg;
3130         uint_t          status;
3131 
3132         status = ddi_getlongprop(DDI_DEV_T_ANY,
3133             dip, DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges, &rlen);
3134 
3135 
3136         switch (status) {
3137                 case DDI_PROP_SUCCESS:
3138                 break;
3139                 case DDI_PROP_NO_MEMORY:
3140                         DEBUG0("ranges present, but unable to get memory\n");
3141                         return (PCICFG_FAILURE);
3142                 default:
3143                         DEBUG0("no ranges property - creating one\n");
3144                         if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
3145                             dip, "ranges", (int *)addition,
3146                             sizeof (pcicfg_range_t)/sizeof (int))
3147                             != DDI_SUCCESS) {
3148                                 DEBUG0("Did'nt create ranges property\n");
3149                                 return (PCICFG_FAILURE);
3150                         }
3151                         return (PCICFG_SUCCESS);
3152         }
3153 
3154         /*
3155          * Allocate memory for the existing reg(s) plus one and then
3156          * build it.
3157          */
3158         newreg = kmem_zalloc(rlen + sizeof (pcicfg_range_t), KM_SLEEP);
3159 
3160         bcopy(ranges, newreg, rlen);
3161         bcopy(addition, newreg + rlen, sizeof (pcicfg_range_t));
3162 
3163         /*
3164          * Write out the new "ranges" property
3165          */
3166         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
3167             dip, "ranges", (int *)newreg,
3168             (rlen + sizeof (pcicfg_range_t))/sizeof (int));
3169 
3170         kmem_free((caddr_t)newreg, rlen+sizeof (pcicfg_range_t));
3171 
3172         kmem_free((caddr_t)ranges, rlen);
3173 
3174         return (PCICFG_SUCCESS);
3175 }
3176 
3177 static int
3178 pcicfg_update_reg_prop(dev_info_t *dip, uint32_t regvalue, uint_t reg_offset)
3179 {
3180         int             rlen;
3181         pci_regspec_t   *reg;
3182         caddr_t         newreg;
3183         uint32_t        hiword;
3184         pci_regspec_t   addition;
3185         uint32_t        size;
3186         uint_t          status;
3187 
3188         status = ddi_getlongprop(DDI_DEV_T_ANY,
3189             dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
3190 
3191         switch (status) {
3192                 case DDI_PROP_SUCCESS:
3193                 break;
3194                 case DDI_PROP_NO_MEMORY:
3195                         DEBUG0("reg present, but unable to get memory\n");
3196                         return (PCICFG_FAILURE);
3197                 default:
3198                         DEBUG0("no reg property\n");
3199                         return (PCICFG_FAILURE);
3200         }
3201 
3202         /*
3203          * Allocate memory for the existing reg(s) plus one and then
3204          * build it.
3205          */
3206         newreg = kmem_zalloc(rlen+sizeof (pci_regspec_t), KM_SLEEP);
3207 
3208         /*
3209          * Build the regspec, then add it to the existing one(s)
3210          */
3211 
3212         hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3213             PCI_REG_DEV_G(reg->pci_phys_hi),
3214             PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3215 
3216         if (reg_offset == PCI_CONF_ROM) {
3217                 size = (~(PCI_BASE_ROM_ADDR_M & regvalue))+1;
3218                 hiword |= PCI_ADDR_MEM32;
3219         } else {
3220                 size = (~(PCI_BASE_M_ADDR_M & regvalue))+1;
3221 
3222                 if ((PCI_BASE_SPACE_M & regvalue) == PCI_BASE_SPACE_MEM) {
3223                         if ((PCI_BASE_TYPE_M & regvalue) == PCI_BASE_TYPE_MEM) {
3224                                 hiword |= PCI_ADDR_MEM32;
3225                         } else if ((PCI_BASE_TYPE_M & regvalue)
3226                             == PCI_BASE_TYPE_ALL) {
3227                                 hiword |= PCI_ADDR_MEM64;
3228                         }
3229                 } else {
3230                         hiword |= PCI_ADDR_IO;
3231                 }
3232         }
3233 
3234         addition.pci_phys_hi = hiword;
3235         addition.pci_phys_mid = 0;
3236         addition.pci_phys_low = 0;
3237         addition.pci_size_hi = 0;
3238         addition.pci_size_low = size;
3239 
3240         bcopy(reg, newreg, rlen);
3241         bcopy(&addition, newreg + rlen, sizeof (pci_regspec_t));
3242 
3243         /*
3244          * Write out the new "reg" property
3245          */
3246         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
3247             dip, "reg", (int *)newreg,
3248             (rlen + sizeof (pci_regspec_t))/sizeof (int));
3249 
3250         kmem_free((caddr_t)newreg, rlen+sizeof (pci_regspec_t));
3251         kmem_free((caddr_t)reg, rlen);
3252 
3253         return (PCICFG_SUCCESS);
3254 }
3255 static int
3256 pcicfg_update_available_prop(dev_info_t *dip, pci_regspec_t *newone)
3257 {
3258         int             alen;
3259         pci_regspec_t   *avail_p;
3260         caddr_t         new_avail;
3261         uint_t          status;
3262 
3263         DEBUG2("pcicfg_update_available_prop() - Address %lx Size %x\n",
3264             newone->pci_phys_low, newone->pci_size_low);
3265         status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3266             "available", (caddr_t)&avail_p, &alen);
3267         switch (status) {
3268                 case DDI_PROP_SUCCESS:
3269                         break;
3270                 case DDI_PROP_NO_MEMORY:
3271                         DEBUG0("no memory for available property\n");
3272                         return (PCICFG_FAILURE);
3273                 default:
3274                         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3275                             "available", (int *)newone,
3276                             sizeof (*newone)/sizeof (int));
3277 
3278                         return (PCICFG_SUCCESS);
3279         }
3280 
3281         /*
3282          * Allocate memory for the existing available plus one and then
3283          * build it.
3284          */
3285         new_avail = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
3286 
3287         bcopy(avail_p, new_avail, alen);
3288         bcopy(newone, new_avail + alen, sizeof (*newone));
3289 
3290         /* Write out the new "available" spec */
3291         (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3292             "available", (int *)new_avail,
3293             (alen + sizeof (*newone))/sizeof (int));
3294 
3295         kmem_free((caddr_t)new_avail, alen+sizeof (*newone));
3296 
3297         /* Don't forget to free up memory from ddi_getlongprop */
3298         kmem_free((caddr_t)avail_p, alen);
3299 
3300         return (PCICFG_SUCCESS);
3301 }
3302 
3303 static int
3304 pcicfg_update_assigned_prop_value(dev_info_t *dip, uint32_t size,
3305     uint32_t base, uint32_t base_hi, uint_t reg_offset)
3306 {
3307         int             rlen;
3308         pci_regspec_t   *reg;
3309         uint32_t        hiword;
3310         pci_regspec_t   addition;
3311         uint_t          status;
3312 
3313         status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3314             "reg", (caddr_t)&reg, &rlen);
3315 
3316         switch (status) {
3317                 case DDI_PROP_SUCCESS:
3318                 break;
3319                 case DDI_PROP_NO_MEMORY:
3320                         DEBUG0("reg present, but unable to get memory\n");
3321                         return (PCICFG_FAILURE);
3322                 default:
3323                         /*
3324                          * Since the config space "reg" entry should have been
3325                          * created, we expect a "reg" property already
3326                          * present here.
3327                          */
3328                         DEBUG0("no reg property\n");
3329                         return (PCICFG_FAILURE);
3330         }
3331 
3332         /*
3333          * Build the regspec, then add it to the existing one(s)
3334          */
3335 
3336         hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3337             PCI_REG_DEV_G(reg->pci_phys_hi),
3338             PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3339 
3340         hiword |= PCI_REG_REL_M;
3341 
3342         if (reg_offset == PCI_CONF_ROM) {
3343                 hiword |= PCI_ADDR_MEM32;
3344 
3345                 base = PCI_BASE_ROM_ADDR_M & base;
3346         } else {
3347                 if ((PCI_BASE_SPACE_M & base) == PCI_BASE_SPACE_MEM) {
3348                         if ((PCI_BASE_TYPE_M & base) == PCI_BASE_TYPE_MEM) {
3349                                 hiword |= PCI_ADDR_MEM32;
3350                         } else if ((PCI_BASE_TYPE_M & base)
3351                             == PCI_BASE_TYPE_ALL) {
3352                                 hiword |= PCI_ADDR_MEM64;
3353                         }
3354 
3355                         if (base & PCI_BASE_PREF_M)
3356                                 hiword |= PCI_REG_PF_M;
3357 
3358                         base = PCI_BASE_M_ADDR_M & base;
3359                 } else {
3360                         hiword |= PCI_ADDR_IO;
3361 
3362                         base = PCI_BASE_IO_ADDR_M & base;
3363                         base_hi = 0;
3364                 }
3365         }
3366 
3367         addition.pci_phys_hi = hiword;
3368         addition.pci_phys_mid = base_hi;
3369         addition.pci_phys_low = base;
3370         addition.pci_size_hi = 0;
3371         addition.pci_size_low = size;
3372 
3373         DEBUG3("updating BAR@off %x with %x,%x\n", reg_offset, hiword, size);
3374 
3375         kmem_free((caddr_t)reg, rlen);
3376 
3377         return (pcicfg_update_assigned_prop(dip, &addition));
3378 }
3379 
3380 static void
3381 pcicfg_device_on(ddi_acc_handle_t config_handle)
3382 {
3383         /*
3384          * Enable memory, IO, and bus mastership
3385          * XXX should we enable parity, SERR#,
3386          * fast back-to-back, and addr. stepping?
3387          */
3388         pci_config_put16(config_handle, PCI_CONF_COMM,
3389             pci_config_get16(config_handle, PCI_CONF_COMM) | 0x7);
3390 }
3391 
3392 static void
3393 pcicfg_device_off(ddi_acc_handle_t config_handle)
3394 {
3395         /*
3396          * Disable I/O and memory traffic through the bridge
3397          */
3398         pci_config_put16(config_handle, PCI_CONF_COMM, 0x0);
3399 }
3400 
3401 /*
3402  * Setup the basic 1275 properties based on information found in the config
3403  * header of the PCI device
3404  */
3405 static int
3406 pcicfg_set_standard_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3407         uint8_t pcie_dev)
3408 {
3409         int ret;
3410         uint16_t val, cap_ptr;
3411         uint32_t wordval;
3412         uint8_t byteval;
3413 
3414         /* These two exists only for non-bridges */
3415         if (((pci_config_get8(config_handle, PCI_CONF_HEADER)
3416             & PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) && !pcie_dev) {
3417                 byteval = pci_config_get8(config_handle, PCI_CONF_MIN_G);
3418                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3419                     "min-grant", byteval)) != DDI_SUCCESS) {
3420                         return (ret);
3421                 }
3422 
3423                 byteval = pci_config_get8(config_handle, PCI_CONF_MAX_L);
3424                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3425                     "max-latency", byteval)) != DDI_SUCCESS) {
3426                         return (ret);
3427                 }
3428         }
3429 
3430         /*
3431          * These should always exist and have the value of the
3432          * corresponding register value
3433          */
3434         val = pci_config_get16(config_handle, PCI_CONF_VENID);
3435 
3436         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3437             "vendor-id", val)) != DDI_SUCCESS) {
3438                 return (ret);
3439         }
3440         val = pci_config_get16(config_handle, PCI_CONF_DEVID);
3441         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3442             "device-id", val)) != DDI_SUCCESS) {
3443                 return (ret);
3444         }
3445         byteval = pci_config_get8(config_handle, PCI_CONF_REVID);
3446         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3447             "revision-id", byteval)) != DDI_SUCCESS) {
3448                 return (ret);
3449         }
3450 
3451         wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
3452             (pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
3453 
3454         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3455             "class-code", wordval)) != DDI_SUCCESS) {
3456                 return (ret);
3457         }
3458         /* devsel-speed starts at the 9th bit */
3459         val = (pci_config_get16(config_handle,
3460             PCI_CONF_STAT) & PCI_STAT_DEVSELT) >> 9;
3461         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3462             "devsel-speed", val)) != DDI_SUCCESS) {
3463                 return (ret);
3464         }
3465 
3466         /*
3467          * The next three are bits set in the status register.  The property is
3468          * present (but with no value other than its own existence) if the bit
3469          * is set, non-existent otherwise
3470          */
3471         if ((!pcie_dev) &&
3472             (pci_config_get16(config_handle, PCI_CONF_STAT) &
3473             PCI_STAT_FBBC)) {
3474                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3475                     "fast-back-to-back", 0)) != DDI_SUCCESS) {
3476                         return (ret);
3477                 }
3478         }
3479         if ((!pcie_dev) &&
3480             (pci_config_get16(config_handle, PCI_CONF_STAT) &
3481             PCI_STAT_66MHZ)) {
3482                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3483                     "66mhz-capable", 0)) != DDI_SUCCESS) {
3484                         return (ret);
3485                 }
3486         }
3487         if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_UDF) {
3488                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3489                     "udf-supported", 0)) != DDI_SUCCESS) {
3490                         return (ret);
3491                 }
3492         }
3493 
3494         /*
3495          * These next three are optional and are not present
3496          * if the corresponding register is zero.  If the value
3497          * is non-zero then the property exists with the value
3498          * of the register.
3499          */
3500         if ((val = pci_config_get16(config_handle,
3501             PCI_CONF_SUBVENID)) != 0) {
3502                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3503                     "subsystem-vendor-id", val)) != DDI_SUCCESS) {
3504                         return (ret);
3505                 }
3506         }
3507         if ((val = pci_config_get16(config_handle,
3508             PCI_CONF_SUBSYSID)) != 0) {
3509                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3510                     "subsystem-id", val)) != DDI_SUCCESS) {
3511                         return (ret);
3512                 }
3513         }
3514         if ((val = pci_config_get16(config_handle,
3515             PCI_CONF_CACHE_LINESZ)) != 0) {
3516                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3517                     "cache-line-size", val)) != DDI_SUCCESS) {
3518                         return (ret);
3519                 }
3520         }
3521 
3522         /*
3523          * If the Interrupt Pin register is non-zero then the
3524          * interrupts property exists
3525          */
3526         if ((byteval = pci_config_get8(config_handle, PCI_CONF_IPIN)) != 0) {
3527                 /*
3528                  * If interrupt pin is non-zero,
3529                  * record the interrupt line used
3530                  */
3531                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3532                     "interrupts", byteval)) != DDI_SUCCESS) {
3533                         return (ret);
3534                 }
3535         }
3536 
3537         ret = PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_E, &cap_ptr);
3538 
3539         if (pcie_dev && (ret == DDI_SUCCESS)) {
3540                 val = PCI_CAP_GET16(config_handle, NULL, cap_ptr,
3541                     PCIE_PCIECAP) & PCIE_PCIECAP_SLOT_IMPL;
3542                 /* if slot implemented, get physical slot number */
3543                 if (val) {
3544                         wordval = (PCI_CAP_GET32(config_handle, NULL,
3545                             cap_ptr, PCIE_SLOTCAP) >>
3546                             PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT) &
3547                             PCIE_SLOTCAP_PHY_SLOT_NUM_MASK;
3548                         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE,
3549                             dip, "physical-slot#", wordval))
3550                             != DDI_SUCCESS) {
3551                                 return (ret);
3552                         }
3553                 }
3554         }
3555         return (PCICFG_SUCCESS);
3556 }
3557 static int
3558 pcicfg_set_busnode_props(dev_info_t *dip, uint8_t pcie_device_type,
3559     int pbus, int sbus)
3560 {
3561         int ret;
3562         char device_type[8];
3563 
3564         if (pcie_device_type)
3565                 (void) strcpy(device_type, "pciex");
3566         else
3567                 (void) strcpy(device_type, "pci");
3568 
3569         if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3570             "device_type", device_type)) != DDI_SUCCESS) {
3571                 return (ret);
3572         }
3573         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3574             "#address-cells", 3)) != DDI_SUCCESS) {
3575                 return (ret);
3576         }
3577         if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3578             "#size-cells", 2)) != DDI_SUCCESS) {
3579                 return (ret);
3580         }
3581 
3582         /*
3583          * Create primary-bus and secondary-bus properties to be used
3584          * to restore bus numbers in the pcicfg_setup_bridge() routine.
3585          */
3586         if (pbus != -1 && sbus != -1) {
3587                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3588                     "primary-bus", pbus)) != DDI_SUCCESS) {
3589                                 return (ret);
3590                 }
3591                 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3592                     "secondary-bus", sbus)) != DDI_SUCCESS) {
3593                                 return (ret);
3594                 }
3595         }
3596         return (PCICFG_SUCCESS);
3597 }
3598 
3599 static int
3600 pcicfg_set_childnode_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3601         uint8_t pcie_dev)
3602 {
3603 
3604         int             ret;
3605         char            *name;
3606         char            buffer[64], pprefix[8];
3607         uint16_t        classcode;
3608         uint8_t         revid, pif, pclass, psubclass;
3609         char            *compat[24];
3610         int             i;
3611         int             n;
3612         uint16_t                sub_vid, sub_sid, vid, did;
3613 
3614         /* set the property prefix based on the device type */
3615         if (pcie_dev)
3616                 (void) sprintf(pprefix, "pciex");
3617         else
3618                 (void) sprintf(pprefix, "pci");
3619         sub_vid = pci_config_get16(config_handle, PCI_CONF_SUBVENID);
3620         sub_sid = pci_config_get16(config_handle, PCI_CONF_SUBSYSID);
3621         vid = pci_config_get16(config_handle, PCI_CONF_VENID);
3622         did = pci_config_get16(config_handle, PCI_CONF_DEVID);
3623         revid = pci_config_get8(config_handle, PCI_CONF_REVID);
3624         pif = pci_config_get8(config_handle, PCI_CONF_PROGCLASS);
3625         classcode = pci_config_get16(config_handle, PCI_CONF_SUBCLASS);
3626         pclass = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
3627         psubclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
3628 
3629         /*
3630          * NOTE: These are for both a child and PCI-PCI bridge node
3631          */
3632 
3633         /*
3634          *      "name" property rule
3635          *      --------------------
3636          *
3637          *
3638          * |      \svid |
3639          * |       \    |
3640          * |        \   |
3641          * |    ssid \  |       =0              |       != 0            |
3642          * |------------|-----------------------|-----------------------|
3643          * |            |                       |                       |
3644          * |    =0      |       vid,did         |       svid,ssid       |
3645          * |            |                       |                       |
3646          * |------------|-----------------------|-----------------------|
3647          * |            |                       |                       |
3648          * |    !=0     |       svid,ssid       |       svid,ssid       |
3649          * |            |                       |                       |
3650          * |------------|-----------------------|-----------------------|
3651          *
3652          * where:
3653          *    vid = vendor id
3654          *    did = device id
3655          *   svid = subsystem vendor id
3656          *   ssid = subsystem id
3657          */
3658 
3659         if ((sub_sid != 0) || (sub_vid != 0)) {
3660                 (void) sprintf(buffer, "%s%x,%x", pprefix, sub_vid, sub_sid);
3661         } else {
3662                 (void) sprintf(buffer, "%s%x,%x", pprefix, vid, did);
3663         }
3664 
3665         /*
3666          * In some environments, trying to use "generic" 1275 names is
3667          * not the convention.  In those cases use the name as created
3668          * above.  In all the rest of the cases, check to see if there
3669          * is a generic name first.
3670          */
3671 #ifdef _DONT_USE_1275_GENERIC_NAMES
3672         name = buffer;
3673 #else
3674         if ((name = pcicfg_get_class_name(classcode)) == NULL) {
3675                 /*
3676                  * Set name to the above fabricated name
3677                  */
3678                 name = buffer;
3679         }
3680 #endif
3681 
3682         /*
3683          * The node name field needs to be filled in with the name
3684          */
3685         if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
3686                 DEBUG0("Failed to set nodename for node\n");
3687                 return (PCICFG_FAILURE);
3688         }
3689 
3690         /*
3691          * Create the compatible property as an array of pointers
3692          * to strings.  Start with the buffer created above.
3693          */
3694         n = 0;
3695         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3696         (void) strcpy(compat[n++], buffer);
3697 
3698         /*
3699          * Setup 'compatible' as per the PCI2.1 bindings document.
3700          *      pci[ex]VVVV,DDDD.SSSS.ssss.RR
3701          *      pci[ex]VVVV,DDDD.SSSS.ssss
3702          *      pciSSSS.ssss  -> not created for PCIe as per PCIe bindings
3703          *      pci[ex]VVVV,DDDD.RR
3704          *      pci[ex]VVVV,DDDD
3705          *      pci[ex]class,CCSSPP
3706          *      pci[ex]class,CCSS
3707          */
3708 
3709         /* pci[ex]VVVV,DDDD.SSSS.ssss.RR */
3710         (void) sprintf(buffer, "%s%x,%x.%x.%x.%x", pprefix,  vid, did,
3711             sub_vid, sub_sid, revid);
3712         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3713         (void) strcpy(compat[n++], buffer);
3714 
3715         /* pci[ex]VVVV,DDDD.SSSS.ssss */
3716         (void) sprintf(buffer, "%s%x,%x.%x.%x", pprefix,  vid, did,
3717             sub_vid, sub_sid);
3718         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3719         (void) strcpy(compat[n++], buffer);
3720 
3721         /* pciSSSS.ssss  -> not created for PCIe as per PCIe bindings */
3722         if (!pcie_dev) {
3723                 (void) sprintf(buffer, "pci%x,%x", sub_vid, sub_sid);
3724                 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3725                 (void) strcpy(compat[n++], buffer);
3726         }
3727 
3728         /* pci[ex]VVVV,DDDD.RR */
3729         (void) sprintf(buffer, "%s%x,%x.%x", pprefix,  vid, did, revid);
3730         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3731         (void) strcpy(compat[n++], buffer);
3732 
3733         /* pci[ex]VVVV,DDDD */
3734         (void) sprintf(buffer, "%s%x,%x", pprefix, vid, did);
3735         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3736         (void) strcpy(compat[n++], buffer);
3737 
3738         /* pci[ex]class,CCSSPP */
3739         (void) sprintf(buffer, "%sclass,%02x%02x%02x", pprefix,
3740             pclass, psubclass, pif);
3741         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3742         (void) strcpy(compat[n++], buffer);
3743 
3744         /* pci[ex]class,CCSS */
3745         (void) sprintf(buffer, "%sclass,%04x", pprefix, classcode);
3746         compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3747         (void) strcpy(compat[n++], buffer);
3748 
3749         if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
3750             "compatible", (char **)compat, n)) != DDI_SUCCESS) {
3751                 return (ret);
3752         }
3753 
3754         for (i = 0; i < n; i++) {
3755                 kmem_free(compat[i], strlen(compat[i]) + 1);
3756         }
3757 
3758         DEBUG1("pcicfg_set_childnode_props - creating name=%s\n", name);
3759         if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3760             "name", name)) != DDI_SUCCESS) {
3761 
3762                 DEBUG0("pcicfg_set_childnode_props - Unable to create name "
3763                     "property\n");
3764 
3765                 return (ret);
3766         }
3767 
3768         return (PCICFG_SUCCESS);
3769 }
3770 
3771 /*
3772  * Program the bus numbers into the bridge
3773  */
3774 
3775 static void
3776 pcicfg_set_bus_numbers(ddi_acc_handle_t config_handle,
3777 uint_t primary, uint_t secondary, uint_t subordinate)
3778 {
3779         DEBUG3("Setting bridge bus-range %d,%d,%d\n", primary, secondary,
3780             subordinate);
3781         /*
3782          * Primary bus#
3783          */
3784         pci_config_put8(config_handle, PCI_BCNF_PRIBUS, primary);
3785 
3786         /*
3787          * Secondary bus#
3788          */
3789         pci_config_put8(config_handle, PCI_BCNF_SECBUS, secondary);
3790 
3791         /*
3792          * Subordinate bus#
3793          */
3794         pci_config_put8(config_handle, PCI_BCNF_SUBBUS, subordinate);
3795 }
3796 
3797 /*
3798  * Put bridge registers into initial state
3799  */
3800 static void
3801 pcicfg_setup_bridge(pcicfg_phdl_t *entry,
3802     ddi_acc_handle_t handle, dev_info_t *dip)
3803 {
3804         int pbus, sbus;
3805 
3806         /*
3807          * The highest bus seen during probing is the max-subordinate bus
3808          */
3809         pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus);
3810 
3811 
3812         /*
3813          * If there exists more than 1 downstream bridge, it
3814          * will be reset by the below secondary bus reset which
3815          * will clear the bus numbers assumed to be programmed in
3816          * the pcicfg_probe_children() routine.  We therefore restore
3817          * them here.
3818          */
3819         if (pci_config_get8(handle, PCI_BCNF_SECBUS) == 0) {
3820                 pbus = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3821                     DDI_PROP_DONTPASS, "primary-bus", -1);
3822                 sbus = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3823                     DDI_PROP_DONTPASS, "secondary-bus", -1);
3824                 if (pbus != -1 && sbus != -1) {
3825                         pci_config_put8(handle, PCI_BCNF_PRIBUS, (uint_t)pbus);
3826                         pci_config_put8(handle, PCI_BCNF_SECBUS, (uint_t)sbus);
3827                 } else {
3828                         cmn_err(CE_WARN, "Invalid Bridge number detected: \
3829                             %s%d: pbus = 0x%x, sbus = 0x%x",
3830                             ddi_get_name(dip), ddi_get_instance(dip), pbus,
3831                             sbus);
3832                 }
3833         }
3834 
3835         /*
3836          * Reset the secondary bus
3837          */
3838         pci_config_put16(handle, PCI_BCNF_BCNTRL,
3839             pci_config_get16(handle, PCI_BCNF_BCNTRL) | 0x40);
3840 
3841         drv_usecwait(100);
3842 
3843         pci_config_put16(handle, PCI_BCNF_BCNTRL,
3844             pci_config_get16(handle, PCI_BCNF_BCNTRL) & ~0x40);
3845 
3846         /*
3847          * Program the memory base register with the
3848          * start of the memory range
3849          */
3850         pci_config_put16(handle, PCI_BCNF_MEM_BASE,
3851             PCICFG_HIWORD(PCICFG_LOADDR(entry->memory_last)));
3852 
3853         /*
3854          * Program the I/O base register with the start of the I/O range
3855          */
3856         pci_config_put8(handle, PCI_BCNF_IO_BASE_LOW,
3857             PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(entry->io_last))));
3858         pci_config_put16(handle, PCI_BCNF_IO_BASE_HI,
3859             PCICFG_HIWORD(PCICFG_LOADDR(entry->io_last)));
3860 
3861         /*
3862          * Clear status bits
3863          */
3864         pci_config_put16(handle, PCI_BCNF_SEC_STATUS, 0xffff);
3865 
3866         /*
3867          * Turn off prefetchable range
3868          */
3869         pci_config_put32(handle, PCI_BCNF_PF_BASE_LOW, 0x0000ffff);
3870         pci_config_put32(handle, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
3871         pci_config_put32(handle, PCI_BCNF_PF_LIMIT_HIGH, 0x0);
3872 
3873         /*
3874          * Needs to be set to this value
3875          */
3876         pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
3877 
3878         /*
3879          * After a Reset, we need to wait 2^25 clock cycles before the
3880          * first Configuration access.  The worst case is 33MHz, which
3881          * is a 1 second wait.
3882          */
3883         drv_usecwait(pcicfg_sec_reset_delay);
3884 
3885 }
3886 
3887 static void
3888 pcicfg_update_bridge(pcicfg_phdl_t *entry,
3889         ddi_acc_handle_t handle)
3890 {
3891         uint_t length;
3892 
3893         /*
3894          * Program the memory limit register with the end of the memory range
3895          */
3896 
3897         DEBUG1("DOWN ROUNDED ===>[0x%x]\n",
3898             PCICFG_ROUND_DOWN(entry->memory_last,
3899             PCICFG_MEMGRAN));
3900 
3901         pci_config_put16(handle, PCI_BCNF_MEM_LIMIT,
3902             PCICFG_HIWORD(PCICFG_LOADDR(
3903             PCICFG_ROUND_DOWN(entry->memory_last,
3904             PCICFG_MEMGRAN))));
3905         /*
3906          * Since this is a bridge, the rest of this range will
3907          * be responded to by the bridge.  We have to round up
3908          * so no other device claims it.
3909          */
3910         if ((length = (PCICFG_ROUND_UP(entry->memory_last,
3911             PCICFG_MEMGRAN) - entry->memory_last)) > 0) {
3912                 (void) pcicfg_get_mem(entry, length, NULL);
3913                 DEBUG1("Added [0x%x]at the top of "
3914                     "the bridge (mem)\n", length);
3915         }
3916 
3917         /*
3918          * Program the I/O limit register with the end of the I/O range
3919          */
3920         pci_config_put8(handle, PCI_BCNF_IO_LIMIT_LOW,
3921             PCICFG_HIBYTE(PCICFG_LOWORD(
3922             PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last,
3923             PCICFG_IOGRAN)))));
3924 
3925         pci_config_put16(handle, PCI_BCNF_IO_LIMIT_HI,
3926             PCICFG_HIWORD(PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last,
3927             PCICFG_IOGRAN))));
3928 
3929         /*
3930          * Same as above for I/O space. Since this is a
3931          * bridge, the rest of this range will be responded
3932          * to by the bridge.  We have to round up so no
3933          * other device claims it.
3934          */
3935         if ((length = (PCICFG_ROUND_UP(entry->io_last,
3936             PCICFG_IOGRAN) - entry->io_last)) > 0) {
3937                 (void) pcicfg_get_io(entry, length, NULL);
3938                 DEBUG1("Added [0x%x]at the top of "
3939                     "the bridge (I/O)\n",  length);
3940         }
3941 }
3942 
3943 /*ARGSUSED*/
3944 static void
3945 pcicfg_disable_bridge_probe_err(dev_info_t *dip, ddi_acc_handle_t h,
3946         pcicfg_err_regs_t *regs)
3947 {
3948         uint16_t val;
3949 
3950         /* disable SERR generated in the context of Master Aborts. */
3951         regs->cmd = val = pci_config_get16(h, PCI_CONF_COMM);
3952         val &= ~PCI_COMM_SERR_ENABLE;
3953         pci_config_put16(h, PCI_CONF_COMM, val);
3954         regs->bcntl = val = pci_config_get16(h, PCI_BCNF_BCNTRL);
3955         val &= ~PCI_BCNF_BCNTRL_SERR_ENABLE;
3956         pci_config_put16(h, PCI_BCNF_BCNTRL, val);
3957         /* clear any current pending errors */
3958         pci_config_put16(h, PCI_CONF_STAT, PCI_STAT_S_TARG_AB|
3959             PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3960         pci_config_put16(h, PCI_BCNF_SEC_STATUS, PCI_STAT_S_TARG_AB|
3961             PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3962         /* if we are a PCIe device, disable the generation of UR, CE and NFE */
3963         if (regs->pcie_dev) {
3964                 uint16_t devctl;
3965                 uint16_t cap_ptr;
3966 
3967                 if ((PCI_CAP_LOCATE(h, PCI_CAP_ID_PCI_E, &cap_ptr)) ==
3968                     DDI_FAILURE)
3969                         return;
3970 
3971                 regs->pcie_cap_off = cap_ptr;
3972                 regs->devctl = devctl = PCI_CAP_GET16(h, NULL, cap_ptr,
3973                     PCIE_DEVCTL);
3974                 devctl &= ~(PCIE_DEVCTL_UR_REPORTING_EN |
3975                     PCIE_DEVCTL_CE_REPORTING_EN |
3976                     PCIE_DEVCTL_NFE_REPORTING_EN |
3977                     PCIE_DEVCTL_FE_REPORTING_EN);
3978                 PCI_CAP_PUT16(h, NULL, cap_ptr, PCIE_DEVCTL, devctl);
3979         }
3980 }
3981 
3982 /*ARGSUSED*/
3983 static void
3984 pcicfg_enable_bridge_probe_err(dev_info_t *dip, ddi_acc_handle_t h,
3985         pcicfg_err_regs_t *regs)
3986 {
3987         /* clear any pending errors */
3988         pci_config_put16(h, PCI_CONF_STAT, PCI_STAT_S_TARG_AB|
3989             PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3990         pci_config_put16(h, PCI_BCNF_SEC_STATUS, PCI_STAT_S_TARG_AB|
3991             PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3992 
3993         /* restore original settings */
3994         if (regs->pcie_dev) {
3995                 pcie_clear_errors(dip);
3996                 pci_config_put16(h, regs->pcie_cap_off + PCIE_DEVCTL,
3997                     regs->devctl);
3998         }
3999 
4000         pci_config_put16(h, PCI_BCNF_BCNTRL, regs->bcntl);
4001         pci_config_put16(h, PCI_CONF_COMM, regs->cmd);
4002 
4003 }
4004 
4005 static int
4006 pcicfg_probe_children(dev_info_t *parent, uint_t bus, uint_t device,
4007     uint_t func, uint_t *highest_bus, pcicfg_flags_t flags, boolean_t is_pcie)
4008 {
4009         dev_info_t              *new_child;
4010         ddi_acc_handle_t        config_handle;
4011         uint8_t                 header_type, pcie_dev = 0;
4012         int                     ret;
4013         pcicfg_err_regs_t       regs;
4014 
4015         /*
4016          * This node will be put immediately below
4017          * "parent". Allocate a blank device node.  It will either
4018          * be filled in or freed up based on further probing.
4019          */
4020         /*
4021          * Note: in usr/src/uts/common/io/hotplug/pcicfg/pcicfg.c
4022          * ndi_devi_alloc() is called as ndi_devi_alloc_sleep()
4023          */
4024         if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
4025             (pnode_t)DEVI_SID_NODEID, &new_child)
4026             != NDI_SUCCESS) {
4027                 DEBUG0("pcicfg_probe_children(): Failed to alloc child node\n");
4028                 return (PCICFG_FAILURE);
4029         }
4030 
4031         if (pcicfg_add_config_reg(new_child, bus,
4032             device, func) != DDI_SUCCESS) {
4033                 DEBUG0("pcicfg_probe_children():"
4034                     "Failed to add candidate REG\n");
4035                 goto failedconfig;
4036         }
4037 
4038         if ((ret = pcicfg_config_setup(new_child, &config_handle))
4039             != PCICFG_SUCCESS) {
4040                 if (ret == PCICFG_NODEVICE) {
4041                         (void) ndi_devi_free(new_child);
4042                         return (ret);
4043                 }
4044                 DEBUG0("pcicfg_probe_children():"
4045                     "Failed to setup config space\n");
4046                 goto failedconfig;
4047         }
4048 
4049         if (is_pcie)
4050                 (void) pcie_init_bus(new_child, PCI_GETBDF(bus, device, func),
4051                     PCIE_BUS_INITIAL);
4052 
4053         /*
4054          * As soon as we have access to config space,
4055          * turn off device. It will get turned on
4056          * later (after memory is assigned).
4057          */
4058         (void) pcicfg_device_off(config_handle);
4059 
4060         /* check if we are PCIe device */
4061         if (pcicfg_pcie_dev(new_child, PCICFG_DEVICE_TYPE_PCIE, &regs)
4062             == DDI_SUCCESS) {
4063                 DEBUG0("PCIe device detected\n");
4064                 pcie_dev = 1;
4065         }
4066 
4067         /*
4068          * Set 1275 properties common to all devices
4069          */
4070         if (pcicfg_set_standard_props(new_child, config_handle,
4071             pcie_dev) != PCICFG_SUCCESS) {
4072                 DEBUG0("Failed to set standard properties\n");
4073                 goto failedchild;
4074         }
4075 
4076         /*
4077          * Child node properties  NOTE: Both for PCI-PCI bridge and child node
4078          */
4079         if (pcicfg_set_childnode_props(new_child, config_handle,
4080             pcie_dev) != PCICFG_SUCCESS) {
4081                 goto failedchild;
4082         }
4083 
4084         header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
4085 
4086         /*
4087          * If this is not a multi-function card only probe function zero.
4088          */
4089         if ((!(header_type & PCI_HEADER_MULTI)) && (func != 0)) {
4090 
4091                 (void) pcicfg_config_teardown(&config_handle);
4092                 (void) ndi_devi_free(new_child);
4093                 return (PCICFG_NODEVICE);
4094         }
4095 
4096         DEBUG1("---Vendor ID = [0x%x]\n",
4097             pci_config_get16(config_handle, PCI_CONF_VENID));
4098         DEBUG1("---Device ID = [0x%x]\n",
4099             pci_config_get16(config_handle, PCI_CONF_DEVID));
4100 
4101         /*
4102          * Attach the child to its parent
4103          */
4104         (void) i_ndi_config_node(new_child, DS_LINKED, 0);
4105 
4106         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
4107 
4108                 DEBUG3("--Bridge found bus [0x%x] device"
4109                     "[0x%x] func [0x%x]\n", bus, device, func);
4110 
4111                 /* Only support read-only probe for leaf device */
4112                 if (flags & PCICFG_FLAG_READ_ONLY)
4113                         goto failedchild;
4114 
4115                 if (pcicfg_probe_bridge(new_child, config_handle,
4116                     bus, highest_bus, is_pcie) != PCICFG_SUCCESS) {
4117                         (void) pcicfg_free_bridge_resources(new_child);
4118                         goto failedchild;
4119                 }
4120 
4121         } else {
4122 
4123                 DEBUG3("--Leaf device found bus [0x%x] device"
4124                     "[0x%x] func [0x%x]\n",
4125                     bus, device, func);
4126 
4127                 if (flags & PCICFG_FLAG_READ_ONLY) {
4128                         /*
4129                          * with read-only probe, don't do any resource
4130                          * allocation, just read the BARs and update props.
4131                          */
4132                         ret = pcicfg_populate_props_from_bar(new_child,
4133                             config_handle);
4134                         if (ret != PCICFG_SUCCESS)
4135                                 goto failedchild;
4136 
4137                         /*
4138                          * for readonly probe "assigned-addresses" property
4139                          * has already been setup by reading the BAR, here
4140                          * just substract the resource from its parent here.
4141                          */
4142                         ret = pcicfg_device_assign_readonly(new_child);
4143                         if (ret != PCICFG_SUCCESS) {
4144                                 (void) pcicfg_free_device_resources(new_child,
4145                                     flags);
4146                                 goto failedchild;
4147                         }
4148                 } else {
4149                         /*
4150                          * update "reg" property by sizing the BARs.
4151                          */
4152                         ret = pcicfg_populate_reg_props(new_child,
4153                             config_handle);
4154                         if (ret != PCICFG_SUCCESS)
4155                                 goto failedchild;
4156 
4157                         /* now allocate & program the resources */
4158                         ret = pcicfg_device_assign(new_child);
4159                         if (ret != PCICFG_SUCCESS) {
4160                                 (void) pcicfg_free_device_resources(new_child,
4161                                     flags);
4162                                 goto failedchild;
4163                         }
4164                 }
4165 
4166                 (void) ndi_devi_bind_driver(new_child, 0);
4167         }
4168 
4169         (void) pcicfg_config_teardown(&config_handle);
4170 
4171         /*
4172          * Properties have been setted up, so initilize the rest fields
4173          * in bus_t.
4174          */
4175         if (is_pcie)
4176                 (void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
4177 
4178         return (PCICFG_SUCCESS);
4179 
4180 failedchild:
4181 
4182         (void) pcicfg_config_teardown(&config_handle);
4183         if (is_pcie)
4184                 pcie_fini_bus(new_child, PCIE_BUS_FINAL);
4185 
4186 failedconfig:
4187 
4188         (void) ndi_devi_free(new_child);
4189         return (PCICFG_FAILURE);
4190 }
4191 
4192 /*
4193  * Sizing the BARs and update "reg" property
4194  */
4195 static int
4196 pcicfg_populate_reg_props(dev_info_t *new_child,
4197     ddi_acc_handle_t config_handle)
4198 {
4199         int             i;
4200         uint32_t        request;
4201 
4202         i = PCI_CONF_BASE0;
4203 
4204         while (i <= PCI_CONF_BASE5) {
4205 
4206                 pci_config_put32(config_handle, i, 0xffffffff);
4207 
4208                 request = pci_config_get32(config_handle, i);
4209                 /*
4210                  * If its a zero length, don't do
4211                  * any programming.
4212                  */
4213                 if (request != 0) {
4214                         /*
4215                          * Add to the "reg" property
4216                          */
4217                         if (pcicfg_update_reg_prop(new_child,
4218                             request, i) != PCICFG_SUCCESS) {
4219                                 goto failedchild;
4220                         }
4221                 } else {
4222                         DEBUG1("BASE register [0x%x] asks for "
4223                             "[0x0]=[0x0](32)\n", i);
4224                         i += 4;
4225                         continue;
4226                 }
4227 
4228                 /*
4229                  * Increment by eight if it is 64 bit address space
4230                  */
4231                 if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
4232                         DEBUG3("BASE register [0x%x] asks for "
4233                             "[0x%x]=[0x%x] (64)\n",
4234                             i, request,
4235                             (~(PCI_BASE_M_ADDR_M & request))+1)
4236                         i += 8;
4237                 } else {
4238                         DEBUG3("BASE register [0x%x] asks for "
4239                             "[0x%x]=[0x%x](32)\n",
4240                             i, request,
4241                             (~(PCI_BASE_M_ADDR_M & request))+1)
4242                         i += 4;
4243                 }
4244         }
4245 
4246         /*
4247          * Get the ROM size and create register for it
4248          */
4249         pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
4250 
4251         request = pci_config_get32(config_handle, PCI_CONF_ROM);
4252         /*
4253          * If its a zero length, don't do
4254          * any programming.
4255          */
4256 
4257         if (request != 0) {
4258                 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4259                     PCI_CONF_ROM, request,
4260                     (~(PCI_BASE_ROM_ADDR_M & request))+1);
4261                 /*
4262                  * Add to the "reg" property
4263                  */
4264                 if (pcicfg_update_reg_prop(new_child,
4265                     request, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4266                         goto failedchild;
4267                 }
4268         }
4269 
4270         return (PCICFG_SUCCESS);
4271 
4272 failedchild:
4273         return (PCICFG_FAILURE);
4274 }
4275 
4276 static int
4277 pcicfg_fcode_probe(dev_info_t *parent, uint_t bus, uint_t device,
4278     uint_t func, uint_t *highest_bus, pcicfg_flags_t flags, boolean_t is_pcie)
4279 {
4280         dev_info_t              *new_child;
4281         int8_t                  header_type;
4282         int                     ret;
4283         ddi_acc_handle_t        h, ph;
4284         int                     error = 0;
4285         extern int              pcicfg_dont_interpret;
4286         pcicfg_err_regs_t       parent_regs, regs;
4287         char                    *status_prop = NULL;
4288 #ifdef PCICFG_INTERPRET_FCODE
4289         struct pci_ops_bus_args po;
4290         fco_handle_t            c;
4291         char                    unit_address[64];
4292         int                     fcode_size = 0;
4293         uchar_t                 *fcode_addr;
4294         uint64_t                mem_answer, mem_alen;
4295         pci_regspec_t           p;
4296         int32_t                 request;
4297         ndi_ra_request_t        req;
4298         int16_t                 vendor_id, device_id;
4299 #endif
4300 
4301         /*
4302          * check if our parent is of type pciex.
4303          * if so, program config space to disable error msgs during probe.
4304          */
4305         if (pcicfg_pcie_dev(parent, PCICFG_DEVICE_TYPE_PCIE, &parent_regs)
4306             == DDI_SUCCESS) {
4307                 DEBUG0("PCI/PCIe parent detected. Disable errors.\n");
4308                 /*
4309                  * disable parent generating URs or SERR#s during probing
4310                  * alone.
4311                  */
4312                 if (pci_config_setup(parent, &ph) != DDI_SUCCESS)
4313                         return (DDI_FAILURE);
4314 
4315                 if ((flags & PCICFG_FLAG_READ_ONLY) == 0) {
4316                         pcicfg_disable_bridge_probe_err(parent,
4317                             ph, &parent_regs);
4318                 }
4319         }
4320 
4321         /*
4322          * This node will be put immediately below
4323          * "parent". Allocate a blank device node.  It will either
4324          * be filled in or freed up based on further probing.
4325          */
4326 
4327         if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
4328             (pnode_t)DEVI_SID_NODEID, &new_child)
4329             != NDI_SUCCESS) {
4330                 DEBUG0("pcicfg_fcode_probe(): Failed to alloc child node\n");
4331                 /* return (PCICFG_FAILURE); */
4332                 ret = PCICFG_FAILURE;
4333                 goto failed2;
4334         }
4335 
4336         /*
4337          * Create a dummy reg property.  This will be replaced with
4338          * a real reg property when fcode completes or if we need to
4339          * produce one by hand.
4340          */
4341         if (pcicfg_add_config_reg(new_child, bus,
4342             device, func) != DDI_SUCCESS) {
4343                 ret = PCICFG_FAILURE;
4344                 goto failed3;
4345         }
4346 #ifdef  EFCODE21554
4347         if ((ret = pcicfg_config_setup(new_child, &h))
4348             != PCICFG_SUCCESS) {
4349                 DEBUG0("pcicfg_fcode_probe():"
4350                     "Failed to setup config space\n");
4351                 ret = PCICFG_NODEVICE;
4352                 goto failed3;
4353         }
4354 
4355 #else
4356         p.pci_phys_hi = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
4357         p.pci_phys_mid = p.pci_phys_low = 0;
4358         p.pci_size_hi = p.pci_size_low = 0;
4359 
4360         /*
4361          * Map in configuration space (temporarily)
4362          */
4363         acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
4364         acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
4365         acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
4366 
4367         if (pcicfg_map_phys(new_child, &p, &virt, &acc, &h)) {
4368                 DEBUG0("pcicfg_fcode_probe():"
4369                     "Failed to setup config space\n");
4370                 ret = PCICFG_NODEVICE;
4371                 goto failed3;
4372         }
4373 
4374         /*
4375          * First use ddi_peek16 so that if there is not a device there,
4376          * a bus error will not cause a panic.
4377          */
4378         v = virt + PCI_CONF_VENID;
4379         if (ddi_peek16(new_child, (int16_t *)v, &vendor_id)) {
4380                 DEBUG0("Can not read Vendor ID");
4381                 pcicfg_unmap_phys(&h, &p);
4382                 ret = PCICFG_NODEVICE;
4383                 goto failed3;
4384         }
4385 #endif
4386 
4387         if (is_pcie)
4388                 (void) pcie_init_bus(new_child, PCI_GETBDF(bus, device, func),
4389                     PCIE_BUS_INITIAL);
4390 
4391         DEBUG0("fcode_probe: conf space mapped.\n");
4392         /*
4393          * As soon as we have access to config space,
4394          * turn off device. It will get turned on
4395          * later (after memory is assigned).
4396          */
4397         (void) pcicfg_device_off(h);
4398 
4399         /* check if we are PCIe device */
4400         if (pcicfg_pcie_dev(new_child, PCICFG_DEVICE_TYPE_PCIE, &regs)
4401             == DDI_SUCCESS) {
4402                 /*EMPTY*/
4403                 DEBUG0("PCI/PCIe device detected\n");
4404         }
4405 
4406         /*
4407          * Set 1275 properties common to all devices
4408          */
4409         if (pcicfg_set_standard_props(new_child,
4410             h, regs.pcie_dev) != PCICFG_SUCCESS) {
4411                 DEBUG0("Failed to set standard properties\n");
4412                 goto failed;
4413         }
4414 
4415         /*
4416          * Child node properties  NOTE: Both for PCI-PCI bridge and child node
4417          */
4418         if (pcicfg_set_childnode_props(new_child,
4419             h, regs.pcie_dev) != PCICFG_SUCCESS) {
4420                 ret = PCICFG_FAILURE;
4421                 goto failed;
4422         }
4423 
4424         header_type = pci_config_get8(h, PCI_CONF_HEADER);
4425 
4426         /*
4427          * If this is not a multi-function card only probe function zero.
4428          */
4429         if (!(header_type & PCI_HEADER_MULTI) && (func > 0)) {
4430 
4431                 ret = PCICFG_NODEVICE;
4432                 goto failed;
4433         }
4434 
4435         if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
4436 
4437                 /*
4438                  * XXX - Transparent bridges are handled differently
4439                  * than other devices with regards to fcode.  Since
4440                  * no transparent bridge currently ships with fcode,
4441                  * there is no reason to try to extract it from its rom
4442                  * or call the fcode interpreter to try to load a drop-in.
4443                  * If fcode is developed to handle transparent bridges,
4444                  * this code will have to change.
4445                  */
4446 
4447                 DEBUG3("--Bridge found bus [0x%x] device"
4448                     "[0x%x] func [0x%x]\n", bus, device, func);
4449 
4450                 /* Only support read-only probe for leaf device */
4451                 if (flags & PCICFG_FLAG_READ_ONLY)
4452                         goto failed;
4453 
4454                 if ((ret = pcicfg_probe_bridge(new_child, h,
4455                     bus, highest_bus, is_pcie)) != PCICFG_SUCCESS)
4456                         (void) pcicfg_free_bridge_resources(new_child);
4457                 goto done;
4458         } else {
4459 
4460                 DEBUG3("--Leaf device found bus [0x%x] device"
4461                     "[0x%x] func [0x%x]\n",
4462                     bus, device, func);
4463 
4464                 /*
4465                  * link in tree, but don't bind driver
4466                  * We don't have compatible property yet
4467                  */
4468                 (void) i_ndi_config_node(new_child, DS_LINKED, 0);
4469 
4470                 /* XXX for now, don't run Fcode in read-only probe. */
4471                 if (flags & PCICFG_FLAG_READ_ONLY)
4472                         goto no_fcode;
4473 
4474                 if (pci_config_get8(h, PCI_CONF_IPIN)) {
4475                         pci_config_put8(h, PCI_CONF_ILINE, 0xf);
4476                 }
4477 
4478 #ifdef PCICFG_INTERPRET_FCODE
4479                 /*
4480                  * Some platforms (x86) don't run fcode, so don't interpret
4481                  * fcode that might be in the ROM.
4482                  */
4483                 if (pcicfg_dont_interpret == 0) {
4484 
4485                         /* This platform supports fcode */
4486 
4487                         vendor_id = pci_config_get16(h, PCI_CONF_VENID);
4488                         device_id = pci_config_get16(h, PCI_CONF_DEVID);
4489 
4490                         /*
4491                          * Get the ROM size and create register for it
4492                          */
4493                         pci_config_put32(h, PCI_CONF_ROM, 0xfffffffe);
4494 
4495                         request = pci_config_get32(h, PCI_CONF_ROM);
4496 
4497                         /*
4498                          * If its a zero length, don't do
4499                          * any programming.
4500                          */
4501 
4502                         if (request != 0) {
4503                                 /*
4504                                  * Add resource to assigned-addresses.
4505                                  */
4506                                 if (pcicfg_fcode_assign_bars(h, new_child,
4507                                     bus, device, func, request, &p)
4508                                     != PCICFG_SUCCESS) {
4509                                         DEBUG0("Failed to assign addresses to "
4510                                             "implemented BARs");
4511                                         ret = PCICFG_FAILURE;
4512                                         goto failed;
4513                                 }
4514 
4515                                 /* Turn device on */
4516                                 (void) pcicfg_device_on(h);
4517 
4518                                 /*
4519                                  * Attempt to load fcode.
4520                                  */
4521                                 (void) pcicfg_load_fcode(new_child, bus, device,
4522                                     func, vendor_id, device_id, &fcode_addr,
4523                                     &fcode_size, PCICFG_LOADDR(mem_answer),
4524                                     (~(PCI_BASE_ROM_ADDR_M & request)) + 1);
4525 
4526                                 /* Turn device off */
4527                                 (void) pcicfg_device_off(h);
4528 
4529                                 /*
4530                                  * Free the ROM resources.
4531                                  */
4532                                 (void) pcicfg_free_resource(new_child, p, 0);
4533 
4534                                 DEBUG2("configure: fcode addr %lx size %x\n",
4535                                     fcode_addr, fcode_size);
4536 
4537                                 /*
4538                                  * Create the fcode-rom-offset property.  The
4539                                  * buffer containing the fcode always starts
4540                                  * with 0xF1, so the fcode offset is zero.
4541                                  */
4542                                 if (ndi_prop_update_int(DDI_DEV_T_NONE,
4543                                     new_child, "fcode-rom-offset", 0)
4544                                     != DDI_SUCCESS) {
4545                                         DEBUG0("Failed to create "
4546                                             "fcode-rom-offset property\n");
4547                                         ret = PCICFG_FAILURE;
4548                                         goto failed;
4549                                 }
4550                         } else {
4551                                 DEBUG0("There is no Expansion ROM\n");
4552                                 fcode_addr = NULL;
4553                                 fcode_size = 0;
4554                         }
4555 
4556                         /*
4557                          * Fill in the bus specific arguments. For
4558                          * PCI, it is the config address.
4559                          */
4560                         po.config_address =
4561                             PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
4562 
4563                         DEBUG1("config_address=%x\n", po.config_address);
4564 
4565                         /*
4566                          * Build unit address.
4567                          */
4568                         (void) sprintf(unit_address, "%x,%x", device, func);
4569 
4570                         DEBUG3("pci_fc_ops_alloc_handle ap=%lx "
4571                             "new device=%lx unit address=%s\n",
4572                             parent, new_child, unit_address);
4573 
4574                         c = pci_fc_ops_alloc_handle(parent, new_child,
4575                             fcode_addr, fcode_size, unit_address, &po);
4576 
4577                         DEBUG0("calling fcode_interpreter()\n");
4578 
4579                         DEBUG3("Before int DIP=%lx binding name %s major %d\n",
4580                             new_child, ddi_binding_name(new_child),
4581                             ddi_driver_major(new_child));
4582 
4583                         error = fcode_interpreter(parent, &pci_fc_ops, c);
4584 
4585                         DEBUG1("returned from fcode_interpreter() - "
4586                             "returned %x\n", error);
4587 
4588                         pci_fc_ops_free_handle(c);
4589 
4590                         DEBUG1("fcode size = %x\n", fcode_size);
4591                         /*
4592                          * We don't need the fcode anymore. While allocating
4593                          * we had rounded up to a page size.
4594                          */
4595                         if (fcode_size) {
4596                                 kmem_free(fcode_addr, ptob(btopr(fcode_size)));
4597                         }
4598                 } else {
4599                         /* This platform does not support fcode */
4600 
4601                         DEBUG0("NOT calling fcode_interpreter()\n");
4602                 }
4603 
4604 #endif /* PCICFG_INTERPRET_FCODE */
4605 
4606                 if ((error == 0) && (pcicfg_dont_interpret == 0)) {
4607                         /*
4608                          * The interpreter completed successfully.
4609                          * We need to redo the resources based on the new reg
4610                          * property.
4611                          */
4612                         DEBUG3("DIP=%lx binding name %s major %d\n", new_child,
4613                             ddi_binding_name(new_child),
4614                             ddi_driver_major(new_child));
4615 
4616                         /*
4617                          * Readjust resources specified by reg property.
4618                          */
4619                         if (pcicfg_alloc_new_resources(new_child) ==
4620                             PCICFG_FAILURE) {
4621                                 ret = PCICFG_FAILURE;
4622                                 goto failed;
4623                         }
4624 
4625                         /*
4626                          * At this stage, there should be enough info to pull
4627                          * the status property if it exists.
4628                          */
4629                         if (ddi_prop_lookup_string(DDI_DEV_T_ANY,
4630                             new_child, NULL, "status", &status_prop) ==
4631                             DDI_PROP_SUCCESS) {
4632                                 if ((strncmp("disabled", status_prop, 8) ==
4633                                     0) || (strncmp("fail", status_prop, 4) ==
4634                                     0)) {
4635                                         ret = PCICFG_FAILURE;
4636                                         ddi_prop_free(status_prop);
4637                                         goto failed;
4638                                 } else {
4639                                         ddi_prop_free(status_prop);
4640                                 }
4641                         }
4642 
4643                         ret = PCICFG_SUCCESS;
4644                         /* no fcode, bind driver now */
4645                         (void) ndi_devi_bind_driver(new_child, 0);
4646 
4647                         goto done;
4648                 } else if ((error != FC_NO_FCODE) &&
4649                     (pcicfg_dont_interpret == 0))  {
4650                         /*
4651                          * The interpreter located fcode, but had an error in
4652                          * processing. Cleanup and fail the operation.
4653                          */
4654                         DEBUG0("Interpreter detected fcode failure\n");
4655                         (void) pcicfg_free_resources(new_child, flags);
4656                         ret = PCICFG_FAILURE;
4657                         goto failed;
4658                 } else {
4659 no_fcode:
4660                         /*
4661                          * Either the interpreter failed with FC_NO_FCODE or we
4662                          * chose not to run the interpreter
4663                          * (pcicfg_dont_interpret).
4664                          *
4665                          * If the interpreter failed because there was no
4666                          * dropin, then we need to probe the device ourself.
4667                          */
4668 
4669                         /*
4670                          * Free any resources that may have been assigned
4671                          * during fcode loading/execution since we need
4672                          * to start over.
4673                          */
4674                         (void) pcicfg_free_resources(new_child, flags);
4675 
4676 #ifdef  EFCODE21554
4677                         pcicfg_config_teardown(&h);
4678 #else
4679                         pcicfg_unmap_phys(&h, &p);
4680 #endif
4681                         /* destroy the bus_t before the dev node is gone */
4682                         if (is_pcie)
4683                                 pcie_fini_bus(new_child, PCIE_BUS_FINAL);
4684 
4685                         (void) ndi_devi_free(new_child);
4686 
4687                         DEBUG0("No Drop-in Probe device ourself\n");
4688 
4689                         ret = pcicfg_probe_children(parent, bus, device, func,
4690                             highest_bus, flags, is_pcie);
4691 
4692                         if (ret != PCICFG_SUCCESS) {
4693                                 DEBUG0("Could not self probe child\n");
4694                                 goto failed2;
4695                         }
4696 
4697                         /*
4698                          * We successfully self probed the device.
4699                          */
4700                         if ((new_child = pcicfg_devi_find(
4701                             parent, device, func)) == NULL) {
4702                                 DEBUG0("Did'nt find device node "
4703                                     "just created\n");
4704                                 ret = PCICFG_FAILURE;
4705                                 goto failed2;
4706                         }
4707 #ifdef  EFCODE21554
4708                         /*
4709                          * Till now, we have detected a non transparent bridge
4710                          * (ntbridge) as a part of the generic probe code and
4711                          * configured only one configuration
4712                          * header which is the side facing the host bus.
4713                          * Now, configure the other side and create children.
4714                          *
4715                          * To make the process simpler, lets load the device
4716                          * driver for the non transparent bridge as this is a
4717                          * Solaris bundled driver, and use its configuration map
4718                          * services rather than programming it here.
4719                          * If the driver is not bundled into Solaris, it must be
4720                          * first loaded and configured before performing any
4721                          * hotplug operations.
4722                          *
4723                          * This not only makes the code simpler but also more
4724                          * generic.
4725                          *
4726                          * So here we go.
4727                          */
4728                         if (pcicfg_is_ntbridge(new_child) != DDI_FAILURE) {
4729 
4730                                 DEBUG0("Found nontransparent bridge.\n");
4731 
4732                                 ret = pcicfg_configure_ntbridge(new_child,
4733                                     bus, device);
4734                         }
4735                         if (ret != PCICFG_SUCCESS) {
4736                                 /*
4737                                  * Bridge configure failed. Free up the self
4738                                  * probed entry. The bus resource allocation
4739                                  * maps need to be cleaned up to prevent
4740                                  * warnings on retries of the failed configure.
4741                                  */
4742                                 (void) pcicfg_ntbridge_unconfigure(new_child);
4743                                 (void) pcicfg_teardown_device(new_child,
4744                                     flags, is_pcie);
4745                         }
4746 #endif
4747                         goto done2;
4748                 }
4749         }
4750 done:
4751 failed:
4752         if (is_pcie) {
4753                 if (ret == PCICFG_SUCCESS)
4754                         (void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
4755                 else
4756                         pcie_fini_bus(new_child, PCIE_BUS_FINAL);
4757         }
4758 
4759 #ifdef  EFCODE21554
4760         pcicfg_config_teardown(&h);
4761 #else
4762         pcicfg_unmap_phys(&h, &p);
4763 #endif
4764 failed3:
4765         if (ret != PCICFG_SUCCESS)
4766                 (void) ndi_devi_free(new_child);
4767 done2:
4768 failed2:
4769         if (parent_regs.pcie_dev) {
4770                 if ((flags & PCICFG_FLAG_READ_ONLY) == 0) {
4771                         pcicfg_enable_bridge_probe_err(parent,
4772                             ph, &parent_regs);
4773                 }
4774                 pci_config_teardown(&ph);
4775         }
4776 
4777         return (ret);
4778 }
4779 
4780 /*
4781  * Read the BARs and update properties. Used in virtual hotplug.
4782  */
4783 static int
4784 pcicfg_populate_props_from_bar(dev_info_t *new_child,
4785     ddi_acc_handle_t config_handle)
4786 {
4787         uint32_t request, base, base_hi, size;
4788         int i;
4789 
4790         i = PCI_CONF_BASE0;
4791 
4792         while (i <= PCI_CONF_BASE5) {
4793                 /*
4794                  * determine the size of the address space
4795                  */
4796                 base = pci_config_get32(config_handle, i);
4797                 pci_config_put32(config_handle, i, 0xffffffff);
4798                 request = pci_config_get32(config_handle, i);
4799                 pci_config_put32(config_handle, i, base);
4800 
4801                 /*
4802                  * If its a zero length, don't do any programming.
4803                  */
4804                 if (request != 0) {
4805                         /*
4806                          * Add to the "reg" property
4807                          */
4808                         if (pcicfg_update_reg_prop(new_child,
4809                             request, i) != PCICFG_SUCCESS) {
4810                                 goto failedchild;
4811                         }
4812 
4813                         if ((PCI_BASE_SPACE_IO & request) == 0 &&
4814                             (PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
4815                                 base_hi = pci_config_get32(config_handle, i+4);
4816                         } else {
4817                                 base_hi = 0;
4818                         }
4819                         /*
4820                          * Add to "assigned-addresses" property
4821                          */
4822                         size = (~(PCI_BASE_M_ADDR_M & request))+1;
4823                         if (pcicfg_update_assigned_prop_value(new_child,
4824                             size, base, base_hi, i) != PCICFG_SUCCESS) {
4825                                 goto failedchild;
4826                         }
4827                 } else {
4828                         DEBUG1("BASE register [0x%x] asks for "
4829                         "[0x0]=[0x0](32)\n", i);
4830                         i += 4;
4831                         continue;
4832                 }
4833 
4834                 /*
4835                  * Increment by eight if it is 64 bit address space
4836                  */
4837                 if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
4838                         DEBUG3("BASE register [0x%x] asks for "
4839                         "[0x%x]=[0x%x] (64)\n",
4840                             i, request,
4841                             (~(PCI_BASE_M_ADDR_M & request))+1)
4842                         i += 8;
4843                 } else {
4844                         DEBUG3("BASE register [0x%x] asks for "
4845                         "[0x%x]=[0x%x](32)\n",
4846                             i, request,
4847                             (~(PCI_BASE_M_ADDR_M & request))+1)
4848                         i += 4;
4849                 }
4850         }
4851 
4852         /*
4853          * Get the ROM size and create register for it
4854          */
4855         base = pci_config_get32(config_handle, PCI_CONF_ROM);
4856         pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
4857         request = pci_config_get32(config_handle, PCI_CONF_ROM);
4858         pci_config_put32(config_handle, PCI_CONF_ROM, base);
4859 
4860         /*
4861          * If its a zero length, don't do
4862          * any programming.
4863          */
4864         if (request != 0) {
4865                 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4866                     PCI_CONF_ROM, request,
4867                     (~(PCI_BASE_ROM_ADDR_M & request))+1);
4868                 /*
4869                  * Add to the "reg" property
4870                  */
4871                 if (pcicfg_update_reg_prop(new_child,
4872                     request, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4873                         goto failedchild;
4874                 }
4875                 /*
4876                  * Add to "assigned-addresses" property
4877                  */
4878                 size = (~(PCI_BASE_ROM_ADDR_M & request))+1;
4879                 if (pcicfg_update_assigned_prop_value(new_child, size,
4880                     base, 0, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4881                         goto failedchild;
4882                 }
4883         }
4884 
4885         return (PCICFG_SUCCESS);
4886 
4887 failedchild:
4888         return (PCICFG_FAILURE);
4889 }
4890 
4891 static int
4892 pcicfg_probe_bridge(dev_info_t *new_child, ddi_acc_handle_t h, uint_t bus,
4893         uint_t *highest_bus, boolean_t is_pcie)
4894 {
4895         uint64_t next_bus;
4896         uint_t new_bus, num_slots;
4897         ndi_ra_request_t req;
4898         int rval, i, j;
4899         uint64_t mem_answer, mem_base, mem_alen, mem_size, mem_end;
4900         uint64_t io_answer, io_base, io_alen, io_size, io_end;
4901         uint64_t round_answer, round_len;
4902         pcicfg_range_t range[PCICFG_RANGE_LEN];
4903         int bus_range[2];
4904         pcicfg_phdl_t phdl;
4905         int count;
4906         uint64_t pcibus_base, pcibus_alen;
4907         uint64_t max_bus;
4908         uint8_t pcie_device_type = 0;
4909         dev_info_t *new_device;
4910         int trans_device;
4911         int ari_mode = B_FALSE;
4912         int max_function = PCICFG_MAX_FUNCTION;
4913 
4914         /*
4915          * Set "device_type" to "pci", the actual type will be set later
4916          * by pcicfg_set_busnode_props() below. This is needed as the
4917          * pcicfg_ra_free() below would update "available" property based
4918          * on "device_type".
4919          *
4920          * This code can be removed later after PCI configurator is changed
4921          * to use PCIRM, which automatically update properties upon allocation
4922          * and free, at that time we'll be able to remove the code inside
4923          * ndi_ra_alloc/free() which currently updates "available" property
4924          * for pci/pcie devices in pcie fabric.
4925          */
4926         if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
4927             "device_type", "pci") != DDI_SUCCESS) {
4928                 DEBUG0("Failed to set \"device_type\" props\n");
4929                 return (PCICFG_FAILURE);
4930         }
4931 
4932         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4933         req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4934         req.ra_boundbase = 0;
4935         req.ra_boundlen = PCICFG_MAX_BUS_DEPTH;
4936         req.ra_len = PCICFG_MAX_BUS_DEPTH;
4937         req.ra_align_mask = 0;  /* no alignment needed */
4938 
4939         rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4940             &pcibus_base, &pcibus_alen, NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4941 
4942         if (rval != NDI_SUCCESS) {
4943                 if (rval == NDI_RA_PARTIAL_REQ) {
4944                         /*EMPTY*/
4945                         DEBUG0("NDI_RA_PARTIAL_REQ returned for bus range\n");
4946                 } else {
4947                         DEBUG0(
4948                             "Failed to allocate bus range for bridge\n");
4949                         return (PCICFG_FAILURE);
4950                 }
4951         }
4952 
4953         DEBUG2("Bus Range Allocated [base=%d] [len=%d]\n",
4954             pcibus_base, pcibus_alen);
4955 
4956         if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_PCI_BUSNUM)
4957             == NDI_FAILURE) {
4958                 DEBUG0("Can not setup resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
4959                 return (PCICFG_FAILURE);
4960         }
4961 
4962         /*
4963          * Put available bus range into the pool.
4964          * Take the first one for this bridge to use and don't give
4965          * to child.
4966          */
4967         (void) ndi_ra_free(new_child, pcibus_base+1, pcibus_alen-1,
4968             NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4969 
4970         next_bus = pcibus_base;
4971         max_bus = pcibus_base + pcibus_alen - 1;
4972 
4973         new_bus = next_bus;
4974 
4975         DEBUG1("NEW bus found  ->[%d]\n", new_bus);
4976 
4977         /* Keep track of highest bus for subordinate bus programming */
4978         *highest_bus = new_bus;
4979 
4980         /*
4981          * Allocate Memory Space for Bridge
4982          */
4983         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4984         req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4985         req.ra_boundbase = 0;
4986         /*
4987          * Note: To support a 32b system, boundlen and len need to be
4988          * 32b quantities
4989          */
4990         req.ra_boundlen = PCICFG_4GIG_LIMIT + 1;
4991         req.ra_len = PCICFG_4GIG_LIMIT + 1; /* Get as big as possible */
4992         req.ra_align_mask =
4993             PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
4994 
4995         rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4996             &mem_answer, &mem_alen,  NDI_RA_TYPE_MEM, NDI_RA_PASS);
4997 
4998         if (rval != NDI_SUCCESS) {
4999                 if (rval == NDI_RA_PARTIAL_REQ) {
5000                         /*EMPTY*/
5001                         DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
5002                 } else {
5003                         DEBUG0(
5004                             "Failed to allocate memory for bridge\n");
5005                         return (PCICFG_FAILURE);
5006                 }
5007         }
5008 
5009         DEBUG3("Bridge Memory Allocated [0x%x.%x] len [0x%x]\n",
5010             PCICFG_HIADDR(mem_answer),
5011             PCICFG_LOADDR(mem_answer),
5012             mem_alen);
5013 
5014         if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
5015                 DEBUG0("Can not setup resource map - NDI_RA_TYPE_MEM\n");
5016                 return (PCICFG_FAILURE);
5017         }
5018 
5019         /*
5020          * Put available memory into the pool.
5021          */
5022         (void) ndi_ra_free(new_child, mem_answer, mem_alen, NDI_RA_TYPE_MEM,
5023             NDI_RA_PASS);
5024 
5025         mem_base = mem_answer;
5026 
5027         /*
5028          * Allocate I/O Space for Bridge
5029          */
5030         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
5031         req.ra_align_mask = PCICFG_IOGRAN - 1; /* 4k alignment */
5032         req.ra_boundbase = 0;
5033         req.ra_boundlen = PCICFG_4GIG_LIMIT;
5034         req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
5035         req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
5036 
5037         rval = ndi_ra_alloc(ddi_get_parent(new_child), &req, &io_answer,
5038             &io_alen, NDI_RA_TYPE_IO, NDI_RA_PASS);
5039 
5040         if (rval != NDI_SUCCESS) {
5041                 if (rval == NDI_RA_PARTIAL_REQ) {
5042                         /*EMPTY*/
5043                         DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
5044                 } else {
5045                         DEBUG0("Failed to allocate io space for bridge\n");
5046                         io_base = io_answer = io_alen = 0;
5047                         /* return (PCICFG_FAILURE); */
5048                 }
5049         }
5050 
5051         if (io_alen) {
5052                 DEBUG3("Bridge IO Space Allocated [0x%x.%x] len [0x%x]\n",
5053                     PCICFG_HIADDR(io_answer), PCICFG_LOADDR(io_answer),
5054                     io_alen);
5055 
5056                 if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_IO) ==
5057                     NDI_FAILURE) {
5058                         DEBUG0("Can not setup resource map - NDI_RA_TYPE_IO\n");
5059                         return (PCICFG_FAILURE);
5060                 }
5061 
5062                 /*
5063                  * Put available I/O into the pool.
5064                  */
5065                 (void) ndi_ra_free(new_child, io_answer, io_alen,
5066                     NDI_RA_TYPE_IO, NDI_RA_PASS);
5067                 io_base = io_answer;
5068         }
5069 
5070         pcicfg_set_bus_numbers(h, bus, new_bus, max_bus);
5071 
5072         /*
5073          * Setup "bus-range" property before onlining the bridge.
5074          */
5075         bus_range[0] = new_bus;
5076         bus_range[1] = max_bus;
5077 
5078         if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
5079             "bus-range", bus_range, 2) != DDI_SUCCESS) {
5080                 DEBUG0("Failed to set bus-range property");
5081                 return (PCICFG_FAILURE);
5082         }
5083 
5084         /*
5085          * Reset the secondary bus
5086          */
5087         pci_config_put16(h, PCI_BCNF_BCNTRL,
5088             pci_config_get16(h, PCI_BCNF_BCNTRL) | 0x40);
5089 
5090         drv_usecwait(100);
5091 
5092         pci_config_put16(h, PCI_BCNF_BCNTRL,
5093             pci_config_get16(h, PCI_BCNF_BCNTRL) & ~0x40);
5094 
5095         /*
5096          * Program the memory base register with the
5097          * start of the memory range
5098          */
5099         pci_config_put16(h, PCI_BCNF_MEM_BASE,
5100             PCICFG_HIWORD(PCICFG_LOADDR(mem_answer)));
5101 
5102         /*
5103          * Program the memory limit register with the
5104          * end of the memory range.
5105          */
5106 
5107         pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
5108             PCICFG_HIWORD(PCICFG_LOADDR(
5109             PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN) - 1)));
5110 
5111         /*
5112          * Allocate the chunk of memory (if any) not programmed into the
5113          * bridge because of the round down.
5114          */
5115         if (PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN)
5116             != (mem_answer + mem_alen)) {
5117                 DEBUG0("Need to allocate Memory round off chunk\n");
5118                 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
5119                 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
5120                 req.ra_addr = PCICFG_ROUND_DOWN((mem_answer + mem_alen),
5121                     PCICFG_MEMGRAN);
5122                 req.ra_len =  (mem_answer + mem_alen) -
5123                     (PCICFG_ROUND_DOWN((mem_answer + mem_alen),
5124                     PCICFG_MEMGRAN));
5125 
5126                 (void) ndi_ra_alloc(new_child, &req,
5127                     &round_answer, &round_len,  NDI_RA_TYPE_MEM, NDI_RA_PASS);
5128         }
5129 
5130         /*
5131          * Program the I/O Space Base
5132          */
5133         pci_config_put8(h, PCI_BCNF_IO_BASE_LOW,
5134             PCICFG_HIBYTE(PCICFG_LOWORD(
5135             PCICFG_LOADDR(io_answer))));
5136 
5137         pci_config_put16(h, PCI_BCNF_IO_BASE_HI,
5138             PCICFG_HIWORD(PCICFG_LOADDR(io_answer)));
5139 
5140         /*
5141          * Program the I/O Space Limit
5142          */
5143         pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
5144             PCICFG_HIBYTE(PCICFG_LOWORD(
5145             PCICFG_LOADDR(PCICFG_ROUND_DOWN(io_answer + io_alen,
5146             PCICFG_IOGRAN)))) - 1);
5147 
5148         pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
5149             PCICFG_HIWORD(PCICFG_LOADDR(
5150             PCICFG_ROUND_DOWN(io_answer + io_alen, PCICFG_IOGRAN)))
5151             - 1);
5152 
5153         /*
5154          * Allocate the chunk of I/O (if any) not programmed into the
5155          * bridge because of the round down.
5156          */
5157         if (PCICFG_ROUND_DOWN((io_answer + io_alen), PCICFG_IOGRAN)
5158             != (io_answer + io_alen)) {
5159                 DEBUG0("Need to allocate I/O round off chunk\n");
5160                 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
5161                 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
5162                 req.ra_addr = PCICFG_ROUND_DOWN((io_answer + io_alen),
5163                     PCICFG_IOGRAN);
5164                 req.ra_len =  (io_answer + io_alen) -
5165                     (PCICFG_ROUND_DOWN((io_answer + io_alen),
5166                     PCICFG_IOGRAN));
5167 
5168                 (void) ndi_ra_alloc(new_child, &req,
5169                     &round_answer, &round_len,  NDI_RA_TYPE_IO, NDI_RA_PASS);
5170         }
5171 
5172         /*
5173          * Setup "ranges" property before onlining the bridge.
5174          */
5175         bzero((caddr_t)range, sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
5176 
5177         range[0].child_hi = range[0].parent_hi |= (PCI_REG_REL_M | PCI_ADDR_IO);
5178         range[0].child_lo = range[0].parent_lo = io_base;
5179         range[1].child_hi = range[1].parent_hi |=
5180             (PCI_REG_REL_M | PCI_ADDR_MEM32);
5181         range[1].child_lo = range[1].parent_lo = mem_base;
5182 
5183         range[0].size_lo = io_alen;
5184         if (pcicfg_update_ranges_prop(new_child, &range[0])) {
5185                 DEBUG0("Failed to update ranges (io)\n");
5186                 return (PCICFG_FAILURE);
5187         }
5188         range[1].size_lo = mem_alen;
5189         if (pcicfg_update_ranges_prop(new_child, &range[1])) {
5190                 DEBUG0("Failed to update ranges (memory)\n");
5191                 return (PCICFG_FAILURE);
5192         }
5193 
5194         /*
5195          * Clear status bits
5196          */
5197         pci_config_put16(h, PCI_BCNF_SEC_STATUS, 0xffff);
5198 
5199         /*
5200          * Turn off prefetchable range
5201          */
5202         pci_config_put32(h, PCI_BCNF_PF_BASE_LOW, 0x0000ffff);
5203         pci_config_put32(h, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
5204         pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH, 0x0);
5205 
5206         /*
5207          * Needs to be set to this value
5208          */
5209         pci_config_put8(h, PCI_CONF_ILINE, 0xf);
5210 
5211         /* check our device_type as defined by Open Firmware */
5212         if (pcicfg_pcie_device_type(new_child, h) == DDI_SUCCESS)
5213                 pcie_device_type = 1;
5214 
5215         /*
5216          * Set bus properties
5217          */
5218         if (pcicfg_set_busnode_props(new_child, pcie_device_type,
5219             (int)bus, (int)new_bus) != PCICFG_SUCCESS) {
5220                 DEBUG0("Failed to set busnode props\n");
5221                 return (PCICFG_FAILURE);
5222         }
5223 
5224         (void) pcicfg_device_on(h);
5225 
5226         if (is_pcie)
5227                 (void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
5228         if (ndi_devi_online(new_child, NDI_NO_EVENT|NDI_CONFIG)
5229             != NDI_SUCCESS) {
5230                 DEBUG0("Unable to online bridge\n");
5231                 return (PCICFG_FAILURE);
5232         }
5233 
5234         DEBUG0("Bridge is ONLINE\n");
5235 
5236         /*
5237          * After a Reset, we need to wait 2^25 clock cycles before the
5238          * first Configuration access.  The worst case is 33MHz, which
5239          * is a 1 second wait.
5240          */
5241         drv_usecwait(pcicfg_sec_reset_delay);
5242 
5243         /*
5244          * Probe all children devices
5245          */
5246         DEBUG0("Bridge Programming Complete - probe children\n");
5247         ndi_devi_enter(new_child, &count);
5248         for (i = 0; ((i < PCICFG_MAX_DEVICE) && (ari_mode == B_FALSE));
5249             i++) {
5250                 for (j = 0; j < max_function; ) {
5251                         if (ari_mode)
5252                                 trans_device = j >> 3;
5253                         else
5254                                 trans_device = i;
5255 
5256                         if ((rval = pcicfg_fcode_probe(new_child,
5257                             new_bus, trans_device, (j & 7), highest_bus,
5258                             0, is_pcie))
5259                             != PCICFG_SUCCESS) {
5260                                 if (rval == PCICFG_NODEVICE) {
5261                                         DEBUG3("No Device at bus [0x%x]"
5262                                             "device [0x%x] "
5263                                             "func [0x%x]\n", new_bus,
5264                                             trans_device, j & 7);
5265 
5266                                         if (j)
5267                                                 goto next;
5268                                 } else {
5269                                         DEBUG3("Failed to configure bus "
5270                                             "[0x%x] device [0x%x] "
5271                                             "func [0x%x]\n", new_bus,
5272                                             trans_device, j & 7);
5273 
5274                                         rval = PCICFG_FAILURE;
5275                                 }
5276                                 break;
5277                         }
5278 next:
5279                         new_device = pcicfg_devi_find(new_child,
5280                             trans_device, (j & 7));
5281 
5282                         /*
5283                          * Determine if ARI Forwarding should be enabled.
5284                          */
5285                         if (j == 0) {
5286                                 if (new_device == NULL)
5287                                         break;
5288 
5289                                 if ((pcie_ari_supported(new_child) ==
5290                                     PCIE_ARI_FORW_ENABLED) &&
5291                                     (pcie_ari_device(new_device) ==
5292                                     PCIE_ARI_DEVICE)) {
5293                                         if (pcie_ari_enable(new_child) ==
5294                                             DDI_SUCCESS) {
5295                                                 (void) ddi_prop_create(
5296                                                     DDI_DEV_T_NONE,
5297                                                     new_child,
5298                                                     DDI_PROP_CANSLEEP,
5299                                                     "ari-enabled", NULL, 0);
5300                                                 ari_mode = B_TRUE;
5301                                                 max_function =
5302                                                     PCICFG_MAX_ARI_FUNCTION;
5303                                         }
5304                                 }
5305                         }
5306 
5307                         if (ari_mode == B_TRUE) {
5308                                 int next_function;
5309 
5310                                 if (new_device == NULL)
5311                                         break;
5312 
5313                                 if (pcie_ari_get_next_function(new_device,
5314                                     &next_function) != DDI_SUCCESS)
5315                                         break;
5316 
5317                                 j = next_function;
5318 
5319                                 if (next_function == 0)
5320                                         break;
5321                         } else
5322                                 j++;
5323                 }
5324         }
5325 
5326         ndi_devi_exit(new_child, count);
5327 
5328         /* if empty topology underneath, it is still a success. */
5329         if (rval != PCICFG_FAILURE)
5330                 rval = PCICFG_SUCCESS;
5331 
5332         /*
5333          * Offline the bridge to allow reprogramming of resources.
5334          *
5335          * This should always succeed since nobody else has started to
5336          * use it yet, failing to detach the driver would indicate a bug.
5337          * Also in that case it's better just panic than allowing the
5338          * configurator to proceed with BAR reprogramming without bridge
5339          * driver detached.
5340          */
5341         VERIFY(ndi_devi_offline(new_child, NDI_NO_EVENT|NDI_UNCONFIG)
5342             == NDI_SUCCESS);
5343         if (is_pcie)
5344                 pcie_fini_bus(new_child, PCIE_BUS_INITIAL);
5345 
5346         phdl.dip = new_child;
5347         phdl.memory_base = mem_answer;
5348         phdl.io_base = (uint32_t)io_answer;
5349         phdl.error = PCICFG_SUCCESS;    /* in case of empty child tree */
5350 
5351         ndi_devi_enter(ddi_get_parent(new_child), &count);
5352         ddi_walk_devs(new_child, pcicfg_find_resource_end, (void *)&phdl);
5353         ndi_devi_exit(ddi_get_parent(new_child), count);
5354 
5355         if (phdl.error != PCICFG_SUCCESS) {
5356                 DEBUG0("Failure summing resources\n");
5357                 return (PCICFG_FAILURE);
5358         }
5359 
5360         num_slots = pcicfg_get_nslots(new_child, h);
5361         mem_end = PCICFG_ROUND_UP(phdl.memory_base, PCICFG_MEMGRAN);
5362         io_end = PCICFG_ROUND_UP(phdl.io_base, PCICFG_IOGRAN);
5363 
5364         DEBUG3("Start of Unallocated Bridge(%d slots) Resources "
5365             "Mem=0x%lx I/O=0x%lx\n", num_slots, mem_end, io_end);
5366 
5367         /*
5368          * Before probing the children we've allocated maximum MEM/IO
5369          * resources from parent, and updated "available" property
5370          * accordingly. Later we'll be giving up unused resources to
5371          * the parent, thus we need to destroy "available" property
5372          * here otherwise it will be out-of-sync with the actual free
5373          * resources this bridge has. This property will be rebuilt below
5374          * with the actual free resources reserved for hotplug slots
5375          * (if any).
5376          */
5377         (void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "available");
5378         /*
5379          * if the bridge a slots, then preallocate. If not, assume static
5380          * configuration. Also check for preallocation limits and spit
5381          * warning messages appropriately (perhaps some can be in debug mode).
5382          */
5383         if (num_slots) {
5384                 pci_regspec_t reg;
5385                 uint64_t mem_assigned = mem_end;
5386                 uint64_t io_assigned = io_end;
5387                 uint64_t mem_reqd = mem_answer + (num_slots *
5388                     pcicfg_slot_memsize);
5389                 uint64_t io_reqd = io_answer + (num_slots *
5390                     pcicfg_slot_iosize);
5391                 uint8_t highest_bus_reqd = new_bus + (num_slots *
5392                     pcicfg_slot_busnums);
5393 #ifdef DEBUG
5394                 if (mem_end > mem_reqd)
5395                         DEBUG3("Memory space consumed by bridge"
5396                             " more than planned for %d slot(s)(%lx, %lx)",
5397                             num_slots, mem_answer, mem_end);
5398                 if (io_end > io_reqd)
5399                         DEBUG3("IO space consumed by bridge"
5400                             " more than planned for %d slot(s)(%lx, %lx)",
5401                             num_slots, io_answer, io_end);
5402                 if (*highest_bus > highest_bus_reqd)
5403                         DEBUG3("Buses consumed by bridge"
5404                             " more than planned for %d slot(s)(%x, %x)",
5405                             num_slots, new_bus, *highest_bus);
5406 
5407                 if (mem_reqd > (mem_answer + mem_alen))
5408                         DEBUG3("Memory space required by bridge"
5409                             " more than available for %d slot(s)(%lx, %lx)",
5410                             num_slots, mem_answer, mem_end);
5411 
5412                 if (io_reqd > (io_answer + io_alen))
5413                         DEBUG3("IO space required by bridge"
5414                             " more than available for %d slot(s)(%lx, %lx)",
5415                             num_slots, io_answer, io_end);
5416                 if (highest_bus_reqd > max_bus)
5417                         DEBUG3("Bus numbers required by bridge"
5418                             " more than available for %d slot(s)(%x, %x)",
5419                             num_slots, new_bus, *highest_bus);
5420 #endif
5421                 mem_end = MAX((MIN(mem_reqd, (mem_answer + mem_alen))),
5422                     mem_end);
5423                 io_end = MAX((MIN(io_reqd, (io_answer + io_alen))), io_end);
5424                 *highest_bus = MAX((MIN(highest_bus_reqd, max_bus)),
5425                     *highest_bus);
5426                 DEBUG3("mem_end %lx, io_end %lx, highest_bus %x\n",
5427                     mem_end, io_end, *highest_bus);
5428 
5429                 mem_size = mem_end - mem_assigned;
5430                 io_size = io_end - io_assigned;
5431 
5432                 reg.pci_phys_mid = reg.pci_size_hi = 0;
5433                 if (io_size > 0) {
5434                         reg.pci_phys_hi = (PCI_REG_REL_M | PCI_ADDR_IO);
5435                         reg.pci_phys_low = io_assigned;
5436                         reg.pci_size_low = io_size;
5437                         if (pcicfg_update_available_prop(new_child, &reg)) {
5438                                 DEBUG0("Failed to update available prop "
5439                                     "(io)\n");
5440                                 return (PCICFG_FAILURE);
5441                         }
5442                 }
5443                 if (mem_size > 0) {
5444                         reg.pci_phys_hi = (PCI_REG_REL_M | PCI_ADDR_MEM32);
5445                         reg.pci_phys_low = mem_assigned;
5446                         reg.pci_size_low = mem_size;
5447                         if (pcicfg_update_available_prop(new_child, &reg)) {
5448                                 DEBUG0("Failed to update available prop "
5449                                     "(memory)\n");
5450                                 return (PCICFG_FAILURE);
5451                         }
5452                 }
5453         }
5454 
5455         /*
5456          * Give back unused memory space to parent.
5457          */
5458         (void) ndi_ra_free(ddi_get_parent(new_child),
5459             mem_end, (mem_answer + mem_alen) - mem_end, NDI_RA_TYPE_MEM,
5460             NDI_RA_PASS);
5461 
5462         if (mem_end == mem_answer) {
5463                 DEBUG0("No memory resources used\n");
5464                 /*
5465                  * To prevent the bridge from forwarding any Memory
5466                  * transactions, the Memory Limit will be programmed
5467                  * with a smaller value than the Memory Base.
5468                  */
5469                 pci_config_put16(h, PCI_BCNF_MEM_BASE, 0xffff);
5470                 pci_config_put16(h, PCI_BCNF_MEM_LIMIT, 0);
5471 
5472                 mem_size = 0;
5473         } else {
5474                 /*
5475                  * Reprogram the end of the memory.
5476                  */
5477                 pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
5478                     PCICFG_HIWORD(mem_end) - 1);
5479                 mem_size = mem_end - mem_base;
5480         }
5481 
5482         /*
5483          * Give back unused io space to parent.
5484          */
5485         (void) ndi_ra_free(ddi_get_parent(new_child),
5486             io_end, (io_answer + io_alen) - io_end,
5487             NDI_RA_TYPE_IO, NDI_RA_PASS);
5488 
5489         if (io_end == io_answer) {
5490                 DEBUG0("No IO Space resources used\n");
5491 
5492                 /*
5493                  * To prevent the bridge from forwarding any I/O
5494                  * transactions, the I/O Limit will be programmed
5495                  * with a smaller value than the I/O Base.
5496                  */
5497                 pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW, 0);
5498                 pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI, 0);
5499                 pci_config_put8(h, PCI_BCNF_IO_BASE_LOW, 0xff);
5500                 pci_config_put16(h, PCI_BCNF_IO_BASE_HI, 0);
5501 
5502                 io_size = 0;
5503         } else {
5504                 /*
5505                  * Reprogram the end of the io space.
5506                  */
5507                 pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
5508                     PCICFG_HIBYTE(PCICFG_LOWORD(
5509                     PCICFG_LOADDR(io_end) - 1)));
5510 
5511                 pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
5512                     PCICFG_HIWORD(PCICFG_LOADDR(io_end - 1)));
5513 
5514                 io_size = io_end - io_base;
5515         }
5516 
5517         if ((max_bus - *highest_bus) > 0) {
5518                 /*
5519                  * Give back unused bus numbers
5520                  */
5521                 (void) ndi_ra_free(ddi_get_parent(new_child),
5522                     *highest_bus+1, max_bus - *highest_bus,
5523                     NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
5524         }
5525 
5526         /*
5527          * Set bus numbers to ranges encountered during scan
5528          */
5529         pcicfg_set_bus_numbers(h, bus, new_bus, *highest_bus);
5530 
5531         bus_range[0] = pci_config_get8(h, PCI_BCNF_SECBUS);
5532         bus_range[1] = pci_config_get8(h, PCI_BCNF_SUBBUS);
5533         DEBUG1("End of bridge probe: bus_range[0] =  %d\n", bus_range[0]);
5534         DEBUG1("End of bridge probe: bus_range[1] =  %d\n", bus_range[1]);
5535 
5536         if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
5537             "bus-range", bus_range, 2) != DDI_SUCCESS) {
5538                 DEBUG0("Failed to set bus-range property");
5539                 return (PCICFG_FAILURE);
5540         }
5541 
5542         /*
5543          * Remove the ranges property if it exists since we will create
5544          * a new one.
5545          */
5546         (void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "ranges");
5547 
5548         DEBUG2("Creating Ranges property - Mem Address %lx Mem Size %x\n",
5549             mem_base, mem_size);
5550         DEBUG2("                         - I/O Address %lx I/O Size %x\n",
5551             io_base, io_size);
5552 
5553         bzero((caddr_t)range, sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
5554 
5555         range[0].child_hi = range[0].parent_hi |= (PCI_REG_REL_M | PCI_ADDR_IO);
5556         range[0].child_lo = range[0].parent_lo = io_base;
5557         range[1].child_hi = range[1].parent_hi |=
5558             (PCI_REG_REL_M | PCI_ADDR_MEM32);
5559         range[1].child_lo = range[1].parent_lo = mem_base;
5560 
5561         if (io_size > 0) {
5562                 range[0].size_lo = io_size;
5563                 if (pcicfg_update_ranges_prop(new_child, &range[0])) {
5564                         DEBUG0("Failed to update ranges (io)\n");
5565                         return (PCICFG_FAILURE);
5566                 }
5567         }
5568         if (mem_size > 0) {
5569                 range[1].size_lo = mem_size;
5570                 if (pcicfg_update_ranges_prop(new_child, &range[1])) {
5571                         DEBUG0("Failed to update ranges (memory)\n");
5572                         return (PCICFG_FAILURE);
5573                 }
5574         }
5575 
5576         /*
5577          * Remove the resource maps for the bridge since we no longer
5578          * need them.  Note that the failure is ignored since the
5579          * ndi_devi_offline above may have already taken care of it via
5580          * driver detach.
5581          * It has been checked that there are no other reasons for
5582          * failure other than map itself being non-existent. So we are Ok.
5583          */
5584         if (ndi_ra_map_destroy(new_child, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
5585                 /*EMPTY*/
5586                 DEBUG0("Can not destroy resource map - NDI_RA_TYPE_MEM\n");
5587         }
5588 
5589         if (ndi_ra_map_destroy(new_child, NDI_RA_TYPE_IO) == NDI_FAILURE) {
5590                 /*EMPTY*/
5591                 DEBUG0("Can not destroy resource map - NDI_RA_TYPE_IO\n");
5592         }
5593 
5594         if (ndi_ra_map_destroy(new_child, NDI_RA_TYPE_PCI_BUSNUM)
5595             == NDI_FAILURE) {
5596                 /*EMPTY*/
5597                 DEBUG0("Can't destroy resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
5598         }
5599 
5600         return (rval);
5601 }
5602 
5603 /*
5604  * Return PCICFG_SUCCESS if device exists at the specified address.
5605  * Return PCICFG_NODEVICE is no device exists at the specified address.
5606  *
5607  */
5608 int
5609 pcicfg_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle)
5610 {
5611         caddr_t                 virt;
5612         ddi_device_acc_attr_t   attr;
5613         int                     status;
5614         int                     rlen;
5615         pci_regspec_t           *reg;
5616         int                     ret = DDI_SUCCESS;
5617         int16_t                 tmp;
5618         /*
5619          * flags = PCICFG_CONF_INDIRECT_MAP if configuration space is indirectly
5620          * mapped, otherwise it is 0. "flags" is introduced in support of any
5621          * non transparent bridges, where configuration space is indirectly
5622          * mapped.
5623          * Indirect mapping is always true on sun4v systems.
5624          */
5625         int                     flags = 0;
5626 
5627 
5628         /*
5629          * Get the pci register spec from the node
5630          */
5631         status = ddi_getlongprop(DDI_DEV_T_ANY,
5632             dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
5633 
5634         switch (status) {
5635                 case DDI_PROP_SUCCESS:
5636                 break;
5637                 case DDI_PROP_NO_MEMORY:
5638                         DEBUG0("reg present, but unable to get memory\n");
5639                         return (PCICFG_FAILURE);
5640                 default:
5641                         DEBUG0("no reg property\n");
5642                         return (PCICFG_FAILURE);
5643         }
5644 
5645         if (pcicfg_indirect_map(dip) == DDI_SUCCESS)
5646                 flags |= PCICFG_CONF_INDIRECT_MAP;
5647 
5648         /*
5649          * Map in configuration space (temporarily)
5650          */
5651         attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
5652         attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
5653         attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
5654         attr.devacc_attr_access = DDI_CAUTIOUS_ACC;
5655 
5656 #ifdef  EFCODE21554
5657         if (ddi_regs_map_setup(dip, 0, &virt,
5658             0, 0, &attr, handle) != DDI_SUCCESS)
5659 #else
5660         if (pcicfg_map_phys(dip, reg, &virt, &attr, handle)
5661             != DDI_SUCCESS)
5662 #endif
5663         {
5664                 DEBUG0("pcicfg_config_setup():"
5665                 "Failed to setup config space\n");
5666 
5667                 kmem_free((caddr_t)reg, rlen);
5668                 return (PCICFG_FAILURE);
5669         }
5670 
5671         if (flags & PCICFG_CONF_INDIRECT_MAP) {
5672                 /*
5673                  * need to use DDI interfaces as the conf space is
5674                  * cannot be directly accessed by the host.
5675                  */
5676                 tmp = (int16_t)ddi_get16(*handle, (uint16_t *)virt);
5677         } else {
5678                 ret = ddi_peek16(dip, (int16_t *)virt, &tmp);
5679         }
5680 
5681         if (ret == DDI_SUCCESS) {
5682                 if (tmp == -1) {
5683                         DEBUG1("NO DEVICEFOUND, read %x\n", tmp);
5684                         ret = PCICFG_NODEVICE;
5685                 } else {
5686                         /* XXX - Need to check why HV is returning 0 */
5687                         if (tmp == 0) {
5688                                 DEBUG0("Device Not Ready yet ?");
5689                                 ret = PCICFG_NODEVICE;
5690                         } else {
5691                                 DEBUG1("DEVICEFOUND, read %x\n", tmp);
5692                                 ret = PCICFG_SUCCESS;
5693                         }
5694                 }
5695         } else {
5696                 DEBUG0("ddi_peek failed, must be NODEVICE\n");
5697                 ret = PCICFG_NODEVICE;
5698         }
5699 
5700         /*
5701          * A bug in XMITS 3.0 causes us to miss the Master Abort Split
5702          * Completion message.  The result is the error message being
5703          * sent back as part of the config data.  If the first two words
5704          * of the config space happen to be the same as the Master Abort
5705          * message, then report back that there is no device there.
5706          */
5707         if ((ret == PCICFG_SUCCESS) && !(flags & PCICFG_CONF_INDIRECT_MAP)) {
5708                 int32_t pcix_scm;
5709 
5710 #define         PCICFG_PCIX_SCM 0x10000004
5711 
5712                 pcix_scm = 0;
5713                 (void) ddi_peek32(dip, (int32_t *)virt, &pcix_scm);
5714                 if (pcix_scm == PCICFG_PCIX_SCM) {
5715                         pcix_scm = 0;
5716                         (void) ddi_peek32(dip,
5717                             (int32_t *)(virt + 4), &pcix_scm);
5718                         if (pcix_scm == PCICFG_PCIX_SCM)
5719                                 ret = PCICFG_NODEVICE;
5720                 }
5721         }
5722 
5723         if (ret == PCICFG_NODEVICE)
5724 #ifdef  EFCODE21554
5725                 ddi_regs_map_free(handle);
5726 #else
5727                 pcicfg_unmap_phys(handle, reg);
5728 #endif
5729 
5730         kmem_free((caddr_t)reg, rlen);
5731 
5732         return (ret);
5733 
5734 }
5735 
5736 static void
5737 pcicfg_config_teardown(ddi_acc_handle_t *handle)
5738 {
5739         (void) ddi_regs_map_free(handle);
5740 }
5741 
5742 static int
5743 pcicfg_add_config_reg(dev_info_t *dip,
5744         uint_t bus, uint_t device, uint_t func)
5745 {
5746         int reg[10] = { PCI_ADDR_CONFIG, 0, 0, 0, 0};
5747 
5748         reg[0] = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
5749 
5750         return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
5751             "reg", reg, 5));
5752 }
5753 
5754 static int
5755 pcicfg_dump_assigned(dev_info_t *dip)
5756 {
5757         pci_regspec_t           *reg;
5758         int                     length;
5759         int                     rcount;
5760         int                     i;
5761 
5762         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
5763             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&reg,
5764             &length) != DDI_PROP_SUCCESS) {
5765                 DEBUG0("Failed to read assigned-addresses property\n");
5766                 return (PCICFG_FAILURE);
5767         }
5768 
5769         rcount = length / sizeof (pci_regspec_t);
5770         for (i = 0; i < rcount; i++) {
5771                 DEBUG4("pcicfg_dump_assigned - size=%x low=%x mid=%x high=%x\n",
5772                     reg[i].pci_size_low, reg[i].pci_phys_low,
5773                     reg[i].pci_phys_mid, reg[i].pci_phys_hi);
5774         }
5775         /*
5776          * Don't forget to free up memory from ddi_getlongprop
5777          */
5778         kmem_free((caddr_t)reg, length);
5779 
5780         return (PCICFG_SUCCESS);
5781 }
5782 
5783 #ifdef PCICFG_INTERPRET_FCODE
5784 static int
5785 pcicfg_load_fcode(dev_info_t *dip, uint_t bus, uint_t device, uint_t func,
5786     uint16_t vendor_id, uint16_t device_id, uchar_t **fcode_addr,
5787     int *fcode_size, int rom_paddr, int rom_size)
5788 {
5789         pci_regspec_t           p;
5790         int                     pci_data;
5791         int                     start_of_fcode;
5792         int                     image_length;
5793         int                     code_type;
5794         ddi_acc_handle_t        h;
5795         ddi_device_acc_attr_t   acc;
5796         uint8_t                 *addr;
5797         int8_t                  image_not_found, indicator;
5798         uint16_t                vendor_id_img, device_id_img;
5799         int16_t                 rom_sig;
5800 #ifdef DEBUG
5801         int i;
5802 #endif
5803 
5804         DEBUG4("pcicfg_load_fcode() - "
5805             "bus %x device =%x func=%x rom_paddr=%lx\n",
5806             bus, device, func, rom_paddr);
5807         DEBUG2("pcicfg_load_fcode() - vendor_id=%x device_id=%x\n",
5808             vendor_id, device_id);
5809 
5810         *fcode_size = 0;
5811         *fcode_addr = NULL;
5812 
5813         acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
5814         acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
5815         acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
5816 
5817         p.pci_phys_hi = PCI_ADDR_MEM32 | PCICFG_MAKE_REG_HIGH(bus, device,
5818             func, PCI_CONF_ROM);
5819 
5820         p.pci_phys_mid = 0;
5821         p.pci_phys_low = 0;
5822 
5823         p.pci_size_low = rom_size;
5824         p.pci_size_hi = 0;
5825 
5826         if (pcicfg_map_phys(dip, &p, (caddr_t *)&addr, &acc, &h)) {
5827                 DEBUG1("Can Not map in ROM %x\n", p.pci_phys_low);
5828                 return (PCICFG_FAILURE);
5829         }
5830 
5831         /*
5832          * Walk the ROM to find the proper image for this device.
5833          */
5834         image_not_found = 1;
5835         while (image_not_found) {
5836                 DEBUG1("Expansion ROM maps to %lx\n", addr);
5837 
5838 #ifdef DEBUG
5839                 if (pcicfg_dump_fcode) {
5840                         for (i = 0; i < 100; i++)
5841                                 DEBUG2("ROM 0x%x --> 0x%x\n", i,
5842                                     ddi_get8(h, (uint8_t *)(addr + i)));
5843                 }
5844 #endif
5845 
5846                 /*
5847                  * Some device say they have an Expansion ROM, but do not, so
5848                  * for non-21554 devices use peek so we don't panic due to
5849                  * accessing non existent memory.
5850                  */
5851                 if (pcicfg_indirect_map(dip) == DDI_SUCCESS) {
5852                         rom_sig = ddi_get16(h,
5853                             (uint16_t *)(addr + PCI_ROM_SIGNATURE));
5854                 } else {
5855                         if (ddi_peek16(dip,
5856                             (int16_t *)(addr + PCI_ROM_SIGNATURE), &rom_sig)) {
5857                                 cmn_err(CE_WARN,
5858                                     "PCI Expansion ROM is not accessible");
5859                                 pcicfg_unmap_phys(&h, &p);
5860                                 return (PCICFG_FAILURE);
5861                         }
5862                 }
5863 
5864                 /*
5865                  * Validate the ROM Signature.
5866                  */
5867                 if ((uint16_t)rom_sig != 0xaa55) {
5868                         DEBUG1("Invalid ROM Signature %x\n", (uint16_t)rom_sig);
5869                         pcicfg_unmap_phys(&h, &p);
5870                         return (PCICFG_FAILURE);
5871                 }
5872 
5873                 DEBUG0("Valid ROM Signature Found\n");
5874 
5875                 start_of_fcode = ddi_get16(h, (uint16_t *)(addr + 2));
5876 
5877                 pci_data =  ddi_get16(h,
5878                     (uint16_t *)(addr + PCI_ROM_PCI_DATA_STRUCT_PTR));
5879 
5880                 DEBUG2("Pointer To PCI Data Structure %x %x\n", pci_data,
5881                     addr);
5882 
5883                 /*
5884                  * Validate the PCI Data Structure Signature.
5885                  * 0x52494350 = "PCIR"
5886                  */
5887 
5888                 if (ddi_get8(h, (uint8_t *)(addr + pci_data)) != 0x50) {
5889                         DEBUG0("Invalid PCI Data Structure Signature\n");
5890                         pcicfg_unmap_phys(&h, &p);
5891                         return (PCICFG_FAILURE);
5892                 }
5893 
5894                 if (ddi_get8(h, (uint8_t *)(addr + pci_data + 1)) != 0x43) {
5895                         DEBUG0("Invalid PCI Data Structure Signature\n");
5896                         pcicfg_unmap_phys(&h, &p);
5897                         return (PCICFG_FAILURE);
5898                 }
5899                 if (ddi_get8(h, (uint8_t *)(addr + pci_data + 2)) != 0x49) {
5900                         DEBUG0("Invalid PCI Data Structure Signature\n");
5901                         pcicfg_unmap_phys(&h, &p);
5902                         return (PCICFG_FAILURE);
5903                 }
5904                 if (ddi_get8(h, (uint8_t *)(addr + pci_data + 3)) != 0x52) {
5905                         DEBUG0("Invalid PCI Data Structure Signature\n");
5906                         pcicfg_unmap_phys(&h, &p);
5907                         return (PCICFG_FAILURE);
5908                 }
5909 
5910                 /*
5911                  * Is this image for this device?
5912                  */
5913                 vendor_id_img = ddi_get16(h,
5914                     (uint16_t *)(addr + pci_data + PCI_PDS_VENDOR_ID));
5915                 device_id_img = ddi_get16(h,
5916                     (uint16_t *)(addr + pci_data + PCI_PDS_DEVICE_ID));
5917 
5918                 DEBUG2("This image is for vendor_id=%x device_id=%x\n",
5919                     vendor_id_img, device_id_img);
5920 
5921                 code_type = ddi_get8(h, addr + pci_data + PCI_PDS_CODE_TYPE);
5922 
5923                 switch (code_type) {
5924                 case PCI_PDS_CODE_TYPE_PCAT:
5925                         DEBUG0("ROM is of x86/PC-AT Type\n");
5926                         break;
5927                 case PCI_PDS_CODE_TYPE_OPEN_FW:
5928                         DEBUG0("ROM is of Open Firmware Type\n");
5929                         break;
5930                 default:
5931                         DEBUG1("ROM is of Unknown Type 0x%x\n", code_type);
5932                         break;
5933                 }
5934 
5935                 if ((vendor_id_img != vendor_id) ||
5936                     (device_id_img != device_id) ||
5937                     (code_type != PCI_PDS_CODE_TYPE_OPEN_FW)) {
5938                         DEBUG0("Firmware Image is not for this device..."
5939                             "goto next image\n");
5940                         /*
5941                          * Read indicator byte to see if there is another
5942                          * image in the ROM
5943                          */
5944                         indicator = ddi_get8(h,
5945                             (uint8_t *)(addr + pci_data + PCI_PDS_INDICATOR));
5946 
5947                         if (indicator != 1) {
5948                                 /*
5949                                  * There is another image in the ROM.
5950                                  */
5951                                 image_length = ddi_get16(h,  (uint16_t *)(addr +
5952                                     pci_data + PCI_PDS_IMAGE_LENGTH)) * 512;
5953 
5954                                 addr += image_length;
5955                         } else {
5956                                 /*
5957                                  * There are no more images.
5958                                  */
5959                                 DEBUG0("There are no more images in the ROM\n");
5960                                 pcicfg_unmap_phys(&h, &p);
5961 
5962                                 return (PCICFG_FAILURE);
5963                         }
5964                 } else {
5965                         DEBUG0("Correct image was found\n");
5966                         image_not_found = 0;  /* Image was found */
5967                 }
5968         }
5969 
5970         *fcode_size =  (ddi_get8(h, addr + start_of_fcode + 4) << 24) |
5971             (ddi_get8(h, addr + start_of_fcode + 5) << 16) |
5972             (ddi_get8(h, addr + start_of_fcode + 6) << 8) |
5973             (ddi_get8(h, addr + start_of_fcode + 7));
5974 
5975         DEBUG1("Fcode Size %x\n", *fcode_size);
5976 
5977         /*
5978          * Allocate page aligned buffer space
5979          */
5980         *fcode_addr = kmem_zalloc(ptob(btopr(*fcode_size)), KM_SLEEP);
5981 
5982         if (*fcode_addr == NULL) {
5983                 DEBUG0("kmem_zalloc returned NULL\n");
5984                 pcicfg_unmap_phys(&h, &p);
5985                 return (PCICFG_FAILURE);
5986         }
5987 
5988         DEBUG1("Fcode Addr %lx\n", *fcode_addr);
5989 
5990         ddi_rep_get8(h, *fcode_addr, addr + start_of_fcode, *fcode_size,
5991             DDI_DEV_AUTOINCR);
5992 
5993         pcicfg_unmap_phys(&h, &p);
5994 
5995         return (PCICFG_SUCCESS);
5996 }
5997 
5998 static int
5999 pcicfg_fcode_assign_bars(ddi_acc_handle_t h, dev_info_t *dip, uint_t bus,
6000     uint_t device, uint_t func, int32_t fc_request, pci_regspec_t *rom_regspec)
6001 {
6002         /*
6003          * Assign values to all BARs so that it is safe to turn on the
6004          * device for accessing the fcode on the PROM. On successful
6005          * exit from this function, "assigned-addresses" are created
6006          * for all BARs and ROM BAR is enabled. Also, rom_regspec is
6007          * filled with the values that can be used to free up this
6008          * resource later.
6009          */
6010         uint32_t request, hiword, size;
6011         pci_regspec_t phys_spec;
6012         ndi_ra_request_t req;
6013         uint64_t mem_answer, mem_alen;
6014         int i;
6015 
6016         DEBUG1("pcicfg_fcode_assign_bars :%s\n", DEVI(dip)->devi_name);
6017 
6018         /*
6019          * Process the BARs.
6020          */
6021         for (i = PCI_CONF_BASE0; i <= PCI_CONF_BASE5; ) {
6022                 pci_config_put32(h, i, 0xffffffff);
6023                 request = pci_config_get32(h, i);
6024                 /*
6025                  * Check if implemented
6026                  */
6027                 if (request == 0) {
6028                         DEBUG1("pcicfg_fcode_assign_bars :"
6029                             "BASE register [0x%x] asks for 0(32)\n", i);
6030                         i += 4;
6031                         continue;
6032                 }
6033                 /*
6034                  * Build the phys_spec for this BAR
6035                  */
6036                 hiword = PCICFG_MAKE_REG_HIGH(bus, device, func, i);
6037                 size = (~(PCI_BASE_M_ADDR_M & request)) + 1;
6038 
6039                 DEBUG3("pcicfg_fcode_assign_bars :"
6040                     "BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
6041                     i, request, size);
6042 
6043                 if ((PCI_BASE_SPACE_M & request) == PCI_BASE_SPACE_MEM) {
6044                         if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_MEM) {
6045                                 hiword |= PCI_ADDR_MEM32;
6046                         } else if ((PCI_BASE_TYPE_M & request)
6047                             == PCI_BASE_TYPE_ALL) {
6048                                 hiword |= PCI_ADDR_MEM64;
6049                         }
6050                         if (request & PCI_BASE_PREF_M)
6051                                 hiword |= PCI_REG_PF_M;
6052                 } else {
6053                         hiword |= PCI_ADDR_IO;
6054                 }
6055                 phys_spec.pci_phys_hi = hiword;
6056                 phys_spec.pci_phys_mid = 0;
6057                 phys_spec.pci_phys_low = 0;
6058                 phys_spec.pci_size_hi = 0;
6059                 phys_spec.pci_size_low = size;
6060 
6061                 /*
6062                  * The following function
6063                  * - allocates address space
6064                  * - programs the BAR
6065                  * - adds an "assigned-addresses" property
6066                  */
6067                 if (pcicfg_alloc_resource(dip, phys_spec)) {
6068                         cmn_err(CE_WARN, "failed to allocate %d bytes"
6069                             " for dev %s BASE register [0x%x]\n",
6070                             size, DEVI(dip)->devi_name, i);
6071                         goto failure;
6072                 }
6073                 if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
6074                         /*
6075                          * 64 bit, should be in memory space.
6076                          */
6077                         i += 8;
6078                 } else {
6079                         /*
6080                          * 32 bit, either memory or I/O space.
6081                          */
6082                         i += 4;
6083                 }
6084         }
6085 
6086         /*
6087          * Handle ROM BAR. We do not use the common
6088          * resource allocator function because we need to
6089          * return reg spec to the caller.
6090          */
6091         size = (~(PCI_BASE_ROM_ADDR_M & fc_request)) + 1;
6092 
6093         DEBUG3("BASE register [0x%x] asks for "
6094             "[0x%x]=[0x%x]\n", PCI_CONF_ROM, fc_request, size);
6095 
6096         bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
6097 
6098         req.ra_boundbase = 0;
6099         req.ra_boundlen = PCICFG_4GIG_LIMIT;
6100         req.ra_len = size;
6101         req.ra_flags = (NDI_RA_ALIGN_SIZE | NDI_RA_ALLOC_BOUNDED);
6102 
6103         if (ndi_ra_alloc(ddi_get_parent(dip),
6104             &req, &mem_answer, &mem_alen,
6105             NDI_RA_TYPE_MEM, NDI_RA_PASS)) {
6106                 cmn_err(CE_WARN, "failed to allocate %d bytes"
6107                     " for dev %s ROM BASE register\n",
6108                     size, DEVI(dip)->devi_name);
6109                 goto failure;
6110         }
6111 
6112         DEBUG3("ROM addr = [0x%x.%x] len [0x%x]\n",
6113             PCICFG_HIADDR(mem_answer),
6114             PCICFG_LOADDR(mem_answer), mem_alen);
6115 
6116         /*
6117          * Assign address space and enable ROM.
6118          */
6119         pci_config_put32(h, PCI_CONF_ROM,
6120             PCICFG_LOADDR(mem_answer) | PCI_BASE_ROM_ENABLE);
6121 
6122         /*
6123          * Add resource to assigned-addresses.
6124          */
6125         phys_spec.pci_phys_hi = PCICFG_MAKE_REG_HIGH(bus, device, func, \
6126             PCI_CONF_ROM) | PCI_ADDR_MEM32;
6127         if (fc_request & PCI_BASE_PREF_M)
6128                 phys_spec.pci_phys_hi |= PCI_REG_PF_M;
6129         phys_spec.pci_phys_mid = 0;
6130         phys_spec.pci_phys_low = PCICFG_LOADDR(mem_answer);
6131         phys_spec.pci_size_hi = 0;
6132         phys_spec.pci_size_low = size;
6133 
6134         if (pcicfg_update_assigned_prop(dip, &phys_spec)
6135             != PCICFG_SUCCESS) {
6136                 cmn_err(CE_WARN, "failed to update"
6137                     " assigned-address property for dev %s\n",
6138                     DEVI(dip)->devi_name);
6139                 goto failure;
6140         }
6141         /*
6142          * Copy out the reg spec.
6143          */
6144         *rom_regspec = phys_spec;
6145 
6146         return (PCICFG_SUCCESS);
6147 
6148 failure:
6149         /*
6150          * We came in with no "assigned-addresses".
6151          * Free up the resources we may have allocated.
6152          */
6153         (void) pcicfg_free_device_resources(dip, 0);
6154 
6155         return (PCICFG_FAILURE);
6156 }
6157 
6158 #endif /* PCICFG_INTERPRET_FCODE */
6159 
6160 static int
6161 pcicfg_free_all_resources(dev_info_t *dip)
6162 {
6163         pci_regspec_t           *assigned;
6164         int                     assigned_len;
6165         int                     acount;
6166         int                     i;
6167 
6168         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6169             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
6170             &assigned_len) != DDI_PROP_SUCCESS) {
6171                 DEBUG0("Failed to read assigned-addresses property\n");
6172                 return (PCICFG_FAILURE);
6173         }
6174 
6175         acount = assigned_len / sizeof (pci_regspec_t);
6176 
6177         for (i = 0; i < acount; i++) {
6178                 if (pcicfg_free_resource(dip, assigned[i], 0)) {
6179                         /*
6180                          * Dont forget to free mem from ddi_getlongprop
6181                          */
6182                         kmem_free((caddr_t)assigned, assigned_len);
6183                         return (PCICFG_FAILURE);
6184                 }
6185         }
6186 
6187         /*
6188          * Don't forget to free up memory from ddi_getlongprop
6189          */
6190         if (assigned_len)
6191                 kmem_free((caddr_t)assigned, assigned_len);
6192 
6193         return (PCICFG_SUCCESS);
6194 }
6195 static int
6196 pcicfg_alloc_new_resources(dev_info_t *dip)
6197 {
6198         pci_regspec_t           *assigned, *reg;
6199         int                     assigned_len, reg_len;
6200         int                     acount, rcount;
6201         int                     i, j, alloc_size;
6202         boolean_t               alloc;
6203 
6204         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6205             DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
6206             &reg_len) != DDI_PROP_SUCCESS) {
6207                 DEBUG0("Failed to read reg property\n");
6208                 return (PCICFG_FAILURE);
6209         }
6210         rcount = reg_len / sizeof (pci_regspec_t);
6211 
6212         DEBUG2("pcicfg_alloc_new_resources() reg size=%x entries=%x\n",
6213             reg_len, rcount);
6214 
6215         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6216             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
6217             &assigned_len) != DDI_PROP_SUCCESS) {
6218                 acount = 0;
6219         } else {
6220                 acount = assigned_len / sizeof (pci_regspec_t);
6221         }
6222 
6223         DEBUG1("assigned-addresses property len=%x\n", acount);
6224 
6225         /*
6226          * For each address described by reg, search for it in the
6227          * assigned-addresses property. If it does not exist, allocate
6228          * resources for it. If it does exist, check the size in both.
6229          * The size needs to be bigger of the two.
6230          */
6231         for (i = 1; i < rcount; i++) {
6232                 alloc = B_TRUE;
6233                 alloc_size = reg[i].pci_size_low;
6234                 for (j = 0; j < acount; j++) {
6235                         if (assigned[j].pci_phys_hi == reg[i].pci_phys_hi) {
6236                                 /*
6237                                  * There is an exact match. Check size.
6238                                  */
6239                                 DEBUG1("pcicfg_alloc_new_resources "
6240                                     "- %x - MATCH\n",
6241                                     reg[i].pci_phys_hi);
6242 
6243                                 if (reg[i].pci_size_low >
6244                                     assigned[j].pci_size_low) {
6245                                         /*
6246                                          * Fcode wants more.
6247                                          */
6248                                         DEBUG3("pcicfg_alloc_new_resources"
6249                                             " - %x - RESIZE"
6250                                             " assigned 0x%x reg 0x%x\n",
6251                                             assigned[j].pci_phys_hi,
6252                                             assigned[j].pci_size_low,
6253                                             reg[i].pci_size_low);
6254 
6255                                         /*
6256                                          * Free the old resource.
6257                                          */
6258                                         (void) pcicfg_free_resource(dip,
6259                                             assigned[j], 0);
6260                                 } else {
6261                                         DEBUG3("pcicfg_alloc_new_resources"
6262                                             " - %x - ENOUGH"
6263                                             " assigned 0x%x reg 0x%x\n",
6264                                             assigned[j].pci_phys_hi,
6265                                             assigned[j].pci_size_low,
6266                                             reg[i].pci_size_low);
6267 
6268                                         alloc = B_FALSE;
6269                                 }
6270                                 break;
6271                         }
6272                         /*
6273                          * Fcode may have set one or more of the
6274                          * NPT bits in phys.hi.
6275                          */
6276                         if (PCI_REG_BDFR_G(assigned[j].pci_phys_hi) ==
6277                             PCI_REG_BDFR_G(reg[i].pci_phys_hi)) {
6278 
6279                                 DEBUG2("pcicfg_alloc_new_resources "
6280                                     "- PARTIAL MATCH assigned 0x%x "
6281                                     "reg 0x%x\n", assigned[j].pci_phys_hi,
6282                                     reg[i].pci_phys_hi);
6283                                 /*
6284                                  * Changing the SS bits is an error
6285                                  */
6286                                 if (PCI_REG_ADDR_G(
6287                                     assigned[j].pci_phys_hi) !=
6288                                     PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
6289 
6290                                         DEBUG2("Fcode changing"
6291                                             " SS bits of - 0x%x -"
6292                                             " on %s\n", reg[i].pci_phys_hi,
6293                                             DEVI(dip)->devi_name);
6294 
6295                                 }
6296 
6297 
6298                                 /*
6299                                  * We are going to allocate new resource.
6300                                  * Free the old resource. Again, adjust
6301                                  * the size to be safe.
6302                                  */
6303                                 (void) pcicfg_free_resource(dip,
6304                                     assigned[j], 0);
6305 
6306                                 alloc_size = MAX(reg[i].pci_size_low,
6307                                     assigned[j].pci_size_low);
6308 
6309                                 break;
6310                         }
6311                 }
6312                 /*
6313                  * We are allocating resources for one of three reasons -
6314                  * - Fcode wants a larger address space
6315                  * - Fcode has set changed/set n, p, t bits.
6316                  * - It is a new "reg", it should be only ROM bar, but
6317                  *   we don't do the checking.
6318                  */
6319                 if (alloc == B_TRUE) {
6320                         DEBUG1("pcicfg_alloc_new_resources : creating 0x%x\n",
6321                             reg[i].pci_phys_hi);
6322 
6323                         reg[i].pci_size_low = alloc_size;
6324                         if (pcicfg_alloc_resource(dip, reg[i])) {
6325                                 /*
6326                                  * Dont forget to free mem from
6327                                  * ddi_getlongprop
6328                                  */
6329                                 if (acount != 0)
6330                                         kmem_free((caddr_t)assigned,
6331                                             assigned_len);
6332                                 kmem_free((caddr_t)reg, reg_len);
6333                                 return (PCICFG_FAILURE);
6334                         }
6335                 }
6336         }
6337 
6338         /*
6339          * Don't forget to free up memory from ddi_getlongprop
6340          */
6341         if (acount != 0)
6342                 kmem_free((caddr_t)assigned, assigned_len);
6343         kmem_free((caddr_t)reg, reg_len);
6344 
6345         return (PCICFG_SUCCESS);
6346 }
6347 
6348 static int
6349 pcicfg_alloc_resource(dev_info_t *dip, pci_regspec_t phys_spec)
6350 {
6351         uint64_t answer;
6352         uint64_t alen;
6353         int offset;
6354         pci_regspec_t config;
6355         caddr_t virt, v;
6356         ddi_device_acc_attr_t acc;
6357         ddi_acc_handle_t h;
6358         ndi_ra_request_t request;
6359         pci_regspec_t *assigned;
6360         int assigned_len, entries, i;
6361 
6362         if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6363             DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
6364             &assigned_len) == DDI_PROP_SUCCESS) {
6365                 DEBUG0("pcicfg_alloc_resource - "
6366                     "searching assigned-addresses\n");
6367 
6368                 entries = assigned_len / (sizeof (pci_regspec_t));
6369 
6370                 /*
6371                  * Walk through the assigned-addresses entries. If there is
6372                  * a match, there is no need to allocate the resource.
6373                  */
6374                 for (i = 0; i < entries; i++) {
6375                         if (assigned[i].pci_phys_hi == phys_spec.pci_phys_hi) {
6376                                 DEBUG1("pcicfg_alloc_resource - MATCH %x\n",
6377                                     assigned[i].pci_phys_hi);
6378                                 kmem_free(assigned, assigned_len);
6379                                 return (0);
6380                         }
6381                 }
6382                 kmem_free(assigned, assigned_len);
6383         }
6384 
6385         bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
6386 
6387         config.pci_phys_hi = PCI_CONF_ADDR_MASK & phys_spec.pci_phys_hi;
6388         config.pci_phys_hi &= ~PCI_REG_REG_M;
6389         config.pci_phys_mid = config.pci_phys_low = 0;
6390         config.pci_size_hi = config.pci_size_low = 0;
6391 
6392         /*
6393          * Map in configuration space (temporarily)
6394          */
6395         acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
6396         acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
6397         acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
6398 
6399         if (pcicfg_map_phys(dip, &config, &virt, &acc, &h)) {
6400                 DEBUG0("Can not map in config space\n");
6401                 return (1);
6402         }
6403 
6404         request.ra_flags = NDI_RA_ALIGN_SIZE;
6405         request.ra_boundbase = 0;
6406         request.ra_boundlen = PCICFG_4GIG_LIMIT;
6407         /*
6408          * Use size stored in phys_spec parameter.
6409          */
6410         request.ra_len = phys_spec.pci_size_low;
6411 
6412         offset = PCI_REG_REG_G(phys_spec.pci_phys_hi);
6413 
6414         v = virt + offset;
6415 
6416         if (PCI_REG_REG_G(phys_spec.pci_phys_hi) == PCI_CONF_ROM) {
6417 
6418                 request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
6419 
6420                 /* allocate memory space from the allocator */
6421 
6422                 if (ndi_ra_alloc(ddi_get_parent(dip),
6423                     &request, &answer, &alen,
6424                     NDI_RA_TYPE_MEM, NDI_RA_PASS)
6425                     != NDI_SUCCESS) {
6426                         DEBUG0("(ROM)Failed to allocate 32b mem");
6427                         pcicfg_unmap_phys(&h, &config);
6428                         return (1);
6429                 }
6430                 DEBUG3("ROM addr = [0x%x.%x] len [0x%x]\n",
6431                     PCICFG_HIADDR(answer),
6432                     PCICFG_LOADDR(answer),
6433                     alen);
6434 
6435                 /* program the low word */
6436 
6437                 ddi_put32(h, (uint32_t *)v, (uint32_t)PCICFG_LOADDR(answer));
6438 
6439                 phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6440                 phys_spec.pci_phys_mid = PCICFG_HIADDR(answer);
6441         } else {
6442 
6443                 switch (PCI_REG_ADDR_G(phys_spec.pci_phys_hi)) {
6444                 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
6445                         request.ra_flags &= ~NDI_RA_ALLOC_BOUNDED;
6446                         /* allocate memory space from the allocator */
6447                         if (ndi_ra_alloc(ddi_get_parent(dip),
6448                             &request, &answer, &alen,
6449                             NDI_RA_TYPE_MEM, NDI_RA_PASS)
6450                             != NDI_SUCCESS) {
6451                                 DEBUG0("Failed to allocate 64b mem\n");
6452                                 pcicfg_unmap_phys(&h, &config);
6453                                 return (1);
6454                         }
6455                         DEBUG3("64 addr = [0x%x.%x] len [0x%x]\n",
6456                             PCICFG_HIADDR(answer),
6457                             PCICFG_LOADDR(answer),
6458                             alen);
6459 
6460                         /* program the low word */
6461 
6462                         ddi_put32(h, (uint32_t *)v,
6463                             (uint32_t)PCICFG_LOADDR(answer));
6464 
6465                         /* program the high word with value zero */
6466                         v += 4;
6467                         ddi_put32(h, (uint32_t *)v,
6468                             (uint32_t)PCICFG_HIADDR(answer));
6469 
6470                         phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6471                         phys_spec.pci_phys_mid = PCICFG_HIADDR(answer);
6472                         /*
6473                          * currently support 32b address space
6474                          * assignments only.
6475                          */
6476                         phys_spec.pci_phys_hi ^= PCI_ADDR_MEM64 ^
6477                             PCI_ADDR_MEM32;
6478 
6479                         break;
6480 
6481                 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
6482                         request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
6483                         /* allocate memory space from the allocator */
6484                         if (ndi_ra_alloc(ddi_get_parent(dip),
6485                             &request, &answer, &alen,
6486                             NDI_RA_TYPE_MEM, NDI_RA_PASS)
6487                             != NDI_SUCCESS) {
6488                                 DEBUG0("Failed to allocate 32b mem\n");
6489                                 pcicfg_unmap_phys(&h, &config);
6490                                 return (1);
6491                         }
6492 
6493                         DEBUG3("32 addr = [0x%x.%x] len [0x%x]\n",
6494                             PCICFG_HIADDR(answer),
6495                             PCICFG_LOADDR(answer),
6496                             alen);
6497 
6498                         /* program the low word */
6499 
6500                         ddi_put32(h, (uint32_t *)v,
6501                             (uint32_t)PCICFG_LOADDR(answer));
6502 
6503                         phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6504 
6505                         break;
6506                 case PCI_REG_ADDR_G(PCI_ADDR_IO):
6507                         /* allocate I/O space from the allocator */
6508                         request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
6509                         if (ndi_ra_alloc(ddi_get_parent(dip),
6510                             &request, &answer, &alen,
6511                             NDI_RA_TYPE_IO, NDI_RA_PASS)
6512                             != NDI_SUCCESS) {
6513                                 DEBUG0("Failed to allocate I/O\n");
6514                                 pcicfg_unmap_phys(&h, &config);
6515                                 return (1);
6516                         }
6517                         DEBUG3("I/O addr = [0x%x.%x] len [0x%x]\n",
6518                             PCICFG_HIADDR(answer),
6519                             PCICFG_LOADDR(answer),
6520                             alen);
6521 
6522                         ddi_put32(h, (uint32_t *)v,
6523                             (uint32_t)PCICFG_LOADDR(answer));
6524 
6525                         phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6526 
6527                         break;
6528                 default:
6529                         DEBUG0("Unknown register type\n");
6530                         pcicfg_unmap_phys(&h, &config);
6531                         return (1);
6532                 } /* switch */
6533         }
6534 
6535         /*
6536          * Now that memory locations are assigned,
6537          * update the assigned address property.
6538          */
6539 
6540         DEBUG1("updating assigned-addresss for %x\n",  phys_spec.pci_phys_hi);
6541 
6542         if (pcicfg_update_assigned_prop(dip, &phys_spec)) {
6543                 pcicfg_unmap_phys(&h, &config);
6544                 return (1);
6545         }
6546 
6547         pcicfg_unmap_phys(&h, &config);
6548 
6549         return (0);
6550 }
6551 
6552 static int
6553 pcicfg_free_resource(dev_info_t *dip, pci_regspec_t phys_spec,
6554     pcicfg_flags_t flags)
6555 {
6556         int offset;
6557         pci_regspec_t config;
6558         caddr_t virt, v;
6559         ddi_device_acc_attr_t acc;
6560         ddi_acc_handle_t h;
6561         ndi_ra_request_t request;
6562         int l;
6563 
6564         bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
6565 
6566         config.pci_phys_hi = PCI_CONF_ADDR_MASK & phys_spec.pci_phys_hi;
6567         config.pci_phys_hi &= ~PCI_REG_REG_M;
6568         config.pci_phys_mid = config.pci_phys_low = 0;
6569         config.pci_size_hi = config.pci_size_low = 0;
6570 
6571         /*
6572          * Map in configuration space (temporarily)
6573          */
6574         acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
6575         acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
6576         acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
6577 
6578         if (pcicfg_map_phys(dip, &config, &virt, &acc, &h)) {
6579                 DEBUG0("Can not map in config space\n");
6580                 return (1);
6581         }
6582 
6583         offset = PCI_REG_REG_G(phys_spec.pci_phys_hi);
6584 
6585         v = virt + offset;
6586 
6587         /*
6588          * Use size stored in phys_spec parameter.
6589          */
6590         l = phys_spec.pci_size_low;
6591 
6592         if (PCI_REG_REG_G(phys_spec.pci_phys_hi) == PCI_CONF_ROM) {
6593 
6594                 /* free memory back to the allocator */
6595                 if (ndi_ra_free(ddi_get_parent(dip), phys_spec.pci_phys_low,
6596                     l, NDI_RA_TYPE_MEM, NDI_RA_PASS) != NDI_SUCCESS) {
6597                         DEBUG0("(ROM)Can not free 32b mem");
6598                         pcicfg_unmap_phys(&h, &config);
6599                         return (1);
6600                 }
6601 
6602                 /* Unmap the BAR by writing a zero */
6603 
6604                 if ((flags & PCICFG_FLAG_READ_ONLY) == 0)
6605                         ddi_put32(h, (uint32_t *)v, (uint32_t)0);
6606         } else {
6607 
6608                 switch (PCI_REG_ADDR_G(phys_spec.pci_phys_hi)) {
6609 
6610                 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
6611                 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
6612                         /* free memory back to the allocator */
6613                         if (ndi_ra_free(ddi_get_parent(dip),
6614                             PCICFG_LADDR(phys_spec.pci_phys_low,
6615                             phys_spec.pci_phys_mid),
6616                             l, NDI_RA_TYPE_MEM,
6617                             NDI_RA_PASS) != NDI_SUCCESS) {
6618                                 DEBUG0("Cannot free mem");
6619                                 pcicfg_unmap_phys(&h, &config);
6620                                 return (1);
6621                         }
6622                         break;
6623 
6624                 case PCI_REG_ADDR_G(PCI_ADDR_IO):
6625                         /* free I/O space back to the allocator */
6626                         if (ndi_ra_free(ddi_get_parent(dip),
6627                             phys_spec.pci_phys_low,
6628                             l, NDI_RA_TYPE_IO,
6629                             NDI_RA_PASS) != NDI_SUCCESS) {
6630                                 DEBUG0("Can not free I/O space");
6631                                 pcicfg_unmap_phys(&h, &config);
6632                                 return (1);
6633                         }
6634                         break;
6635 
6636                 default:
6637                         DEBUG0("Unknown register type\n");
6638                         pcicfg_unmap_phys(&h, &config);
6639                         return (1);
6640                 } /* switch */
6641         }
6642 
6643         /*
6644          * Now that memory locations are assigned,
6645          * update the assigned address property.
6646          */
6647 
6648         DEBUG1("updating assigned-addresss for %x\n", phys_spec.pci_phys_hi);
6649 
6650         if (pcicfg_remove_assigned_prop(dip, &phys_spec)) {
6651                 pcicfg_unmap_phys(&h, &config);
6652                 return (1);
6653         }
6654 
6655         pcicfg_unmap_phys(&h, &config);
6656 
6657         return (0);
6658 }
6659 
6660 static int
6661 pcicfg_remove_assigned_prop(dev_info_t *dip, pci_regspec_t *oldone)
6662 {
6663         int             alen, num_entries, i;
6664         pci_regspec_t   *assigned, *assigned_copy;
6665         uint_t          status;
6666 
6667         status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
6668             "assigned-addresses", (caddr_t)&assigned, &alen);
6669         switch (status) {
6670                 case DDI_PROP_SUCCESS:
6671                 break;
6672                 case DDI_PROP_NO_MEMORY:
6673                         DEBUG0("no memory for assigned-addresses property\n");
6674                         return (1);
6675                 default:
6676                         DEBUG0("assigned-addresses property does not exist\n");
6677                         return (0);
6678         }
6679 
6680         /*
6681          * Make a copy of old assigned-addresses property.
6682          */
6683         assigned_copy = kmem_alloc(alen, KM_SLEEP);
6684         bcopy(assigned, assigned_copy, alen);
6685 
6686         status = ndi_prop_remove(DDI_DEV_T_NONE, dip, "assigned-addresses");
6687 
6688         if (status != DDI_PROP_SUCCESS) {
6689                 /*
6690                  * If "assigned-addresses" is retrieved from PROM, the
6691                  * ndi_prop_remove() will fail.
6692                  */
6693                 DEBUG1("pcicfg_remove_assigned_prop: 0x%x not removed\n",
6694                     oldone->pci_phys_hi);
6695 
6696                 /*
6697                  * Free up allocated memory
6698                  */
6699                 kmem_free(assigned_copy, alen);
6700                 kmem_free((caddr_t)assigned, alen);
6701 
6702                 return (0);
6703         }
6704 
6705         num_entries = alen / sizeof (pci_regspec_t);
6706 
6707         /*
6708          * Rebuild the assigned-addresses property.
6709          */
6710         for (i = 0; i < num_entries; i++) {
6711                 if (assigned_copy[i].pci_phys_hi != oldone->pci_phys_hi) {
6712                         (void) pcicfg_update_assigned_prop(dip,
6713                             &assigned_copy[i]);
6714                 }
6715         }
6716 
6717         /*
6718          * Free the copy of the original assigned-addresses.
6719          */
6720         kmem_free(assigned_copy, alen);
6721 
6722         /*
6723          * Don't forget to free up memory from ddi_getlongprop
6724          */
6725         kmem_free((caddr_t)assigned, alen);
6726 
6727         return (0);
6728 }
6729 
6730 static int
6731 pcicfg_map_phys(dev_info_t *dip, pci_regspec_t *phys_spec,
6732         caddr_t *addrp, ddi_device_acc_attr_t *accattrp,
6733         ddi_acc_handle_t *handlep)
6734 {
6735         ddi_map_req_t mr;
6736         ddi_acc_hdl_t *hp;
6737         int result;
6738 
6739         *handlep = impl_acc_hdl_alloc(KM_SLEEP, NULL);
6740         hp = impl_acc_hdl_get(*handlep);
6741         hp->ah_vers = VERS_ACCHDL;
6742         hp->ah_dip = dip;
6743         hp->ah_rnumber = 0;
6744         hp->ah_offset = 0;
6745         hp->ah_len = 0;
6746         hp->ah_acc = *accattrp;
6747 
6748         mr.map_op = DDI_MO_MAP_LOCKED;
6749         mr.map_type = DDI_MT_REGSPEC;
6750         mr.map_obj.rp = (struct regspec *)phys_spec;
6751         mr.map_prot = PROT_READ | PROT_WRITE;
6752         mr.map_flags = DDI_MF_KERNEL_MAPPING;
6753         mr.map_handlep = hp;
6754         mr.map_vers = DDI_MAP_VERSION;
6755 
6756         result = ddi_map(dip, &mr, 0, 0, addrp);
6757 
6758         if (result != DDI_SUCCESS) {
6759                 impl_acc_hdl_free(*handlep);
6760                 *handlep = (ddi_acc_handle_t)NULL;
6761         } else {
6762                 hp->ah_addr = *addrp;
6763         }
6764 
6765         return (result);
6766 }
6767 
6768 void
6769 pcicfg_unmap_phys(ddi_acc_handle_t *handlep,  pci_regspec_t *ph)
6770 {
6771         ddi_map_req_t mr;
6772         ddi_acc_hdl_t *hp;
6773 
6774         hp = impl_acc_hdl_get(*handlep);
6775         ASSERT(hp);
6776 
6777         mr.map_op = DDI_MO_UNMAP;
6778         mr.map_type = DDI_MT_REGSPEC;
6779         mr.map_obj.rp = (struct regspec *)ph;
6780         mr.map_prot = PROT_READ | PROT_WRITE;
6781         mr.map_flags = DDI_MF_KERNEL_MAPPING;
6782         mr.map_handlep = hp;
6783         mr.map_vers = DDI_MAP_VERSION;
6784 
6785         (void) ddi_map(hp->ah_dip, &mr, hp->ah_offset,
6786             hp->ah_len, &hp->ah_addr);
6787 
6788         impl_acc_hdl_free(*handlep);
6789         *handlep = (ddi_acc_handle_t)NULL;
6790 }
6791 
6792 static int
6793 pcicfg_ari_configure(dev_info_t *dip)
6794 {
6795         if (pcie_ari_supported(dip) == PCIE_ARI_FORW_NOT_SUPPORTED)
6796                 return (DDI_FAILURE);
6797 
6798         /*
6799          * Until we have resource balancing, dynamically configure
6800          * ARI functions without firmware assistamce.
6801          */
6802         return (DDI_FAILURE);
6803 }
6804 
6805 #ifdef DEBUG
6806 static void
6807 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
6808         uintptr_t a4, uintptr_t a5)
6809 {
6810         if (pcicfg_debug == 1) {
6811                 prom_printf("pcicfg: ");
6812                 prom_printf(fmt, a1, a2, a3, a4, a5);
6813         } else
6814                 if (pcicfg_debug)
6815                         cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
6816 }
6817 #endif
6818 
6819 /*
6820  * Return true if the devinfo node is in a PCI Express hierarchy.
6821  */
6822 static boolean_t
6823 is_pcie_fabric(dev_info_t *dip)
6824 {
6825         dev_info_t *root = ddi_root_node();
6826         dev_info_t *pdip;
6827         boolean_t found = B_FALSE;
6828         char *bus;
6829 
6830         /*
6831          * Does this device reside in a pcie fabric ?
6832          */
6833         for (pdip = dip; pdip && (pdip != root) && !found;
6834             pdip = ddi_get_parent(pdip)) {
6835                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
6836                     DDI_PROP_DONTPASS, "device_type", &bus) !=
6837                     DDI_PROP_SUCCESS)
6838                         break;
6839 
6840                 if (strcmp(bus, "pciex") == 0)
6841                         found = B_TRUE;
6842 
6843                 ddi_prop_free(bus);
6844         }
6845 
6846         return (found);
6847 }