pci_boot.c revision 4876:ecd69ba0713a
1178479Sjb/* 2178479Sjb * CDDL HEADER START 3178479Sjb * 4178479Sjb * The contents of this file are subject to the terms of the 5178479Sjb * Common Development and Distribution License (the "License"). 6178479Sjb * You may not use this file except in compliance with the License. 7178479Sjb * 8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178479Sjb * or http://www.opensolaris.org/os/licensing. 10178479Sjb * See the License for the specific language governing permissions 11178479Sjb * and limitations under the License. 12178479Sjb * 13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178479Sjb * If applicable, add the following below this CDDL HEADER, with the 16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178479Sjb * 19178479Sjb * CDDL HEADER END 20178479Sjb */ 21178479Sjb/* 22178479Sjb * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23178573Sjb * Use is subject to license terms. 24178479Sjb */ 25178479Sjb 26178479Sjb#pragma ident "%Z%%M% %I% %E% SMI" 27178479Sjb 28178479Sjb#include <sys/types.h> 29178479Sjb#include <sys/stat.h> 30178479Sjb#include <sys/sunndi.h> 31178479Sjb#include <sys/pci.h> 32178479Sjb#include <sys/pci_impl.h> 33178573Sjb#include <sys/pci_cfgspace.h> 34178479Sjb#include <sys/memlist.h> 35178573Sjb#include <sys/bootconf.h> 36178573Sjb#include <io/pci/mps_table.h> 37178573Sjb#include <sys/pci_cfgspace.h> 38178479Sjb#include <sys/pci_cfgspace_impl.h> 39178479Sjb#include <sys/psw.h> 40178479Sjb#include "../../../../common/pci/pci_strings.h" 41178573Sjb#include <sys/apic.h> 42178479Sjb#include <io/pciex/pcie_nvidia.h> 43178573Sjb#include <sys/acpi/acpi.h> 44178479Sjb#include <sys/acpica.h> 45178479Sjb 46178479Sjb#define pci_getb (*pci_getb_func) 47178479Sjb#define pci_getw (*pci_getw_func) 48178479Sjb#define pci_getl (*pci_getl_func) 49178479Sjb#define pci_putb (*pci_putb_func) 50178573Sjb#define pci_putw (*pci_putw_func) 51178479Sjb#define pci_putl (*pci_putl_func) 52178573Sjb#define dcmn_err if (pci_boot_debug) cmn_err 53178573Sjb 54211554Srpaulo#define CONFIG_INFO 0 55211554Srpaulo#define CONFIG_UPDATE 1 56211554Srpaulo#define CONFIG_NEW 2 57178573Sjb#define CONFIG_FIX 3 58178479Sjb#define COMPAT_BUFSIZE 512 59178479Sjb 60178479Sjb/* See AMD-8111 Datasheet Rev 3.03, Page 149: */ 61178479Sjb#define LPC_IO_CONTROL_REG_1 0x40 62178479Sjb#define AMD8111_ENABLENMI (uint8_t)0x80 63178479Sjb#define DEVID_AMD8111_LPC 0x7468 64178479Sjb 65178479Sjbstruct pci_fixundo { 66178479Sjb uint8_t bus; 67178479Sjb uint8_t dev; 68178479Sjb uint8_t fn; 69178479Sjb void (*undofn)(uint8_t, uint8_t, uint8_t); 70178479Sjb struct pci_fixundo *next; 71178479Sjb}; 72178479Sjb 73178479Sjbextern int pci_bios_nbus; 74178479Sjbstatic uchar_t max_dev_pci = 32; /* PCI standard */ 75178479Sjbint pci_boot_debug = 0; 76178479Sjbextern struct memlist *find_bus_res(int, int); 77178479Sjbstatic struct pci_fixundo *undolist = NULL; 78178479Sjb 79178479Sjb/* 80178479Sjb * Module prototypes 81178479Sjb */ 82178479Sjbstatic void enumerate_bus_devs(uchar_t bus, int config_op); 83178479Sjbstatic void create_root_bus_dip(uchar_t bus); 84178479Sjbstatic dev_info_t *process_devfunc(uchar_t, uchar_t, uchar_t, uchar_t, 85178479Sjb ushort_t, int); 86178479Sjbstatic void add_compatible(dev_info_t *, ushort_t, ushort_t, 87178479Sjb ushort_t, ushort_t, uchar_t, uint_t, int); 88178479Sjbstatic int add_reg_props(dev_info_t *, uchar_t, uchar_t, uchar_t, int, int); 89178479Sjbstatic void add_ppb_props(dev_info_t *, uchar_t, uchar_t, uchar_t, int); 90178479Sjbstatic void add_model_prop(dev_info_t *, uint_t); 91178479Sjbstatic void add_bus_range_prop(int); 92178479Sjbstatic void add_bus_slot_names_prop(int); 93178479Sjbstatic void add_ppb_ranges_prop(int); 94178479Sjbstatic void add_bus_available_prop(int); 95178479Sjbstatic void fix_ppb_res(uchar_t); 96178479Sjbstatic void alloc_res_array(); 97178479Sjbstatic void create_ioapic_node(int bus, int dev, int fn, ushort_t vendorid, 98178479Sjb ushort_t deviceid); 99178479Sjb 100178479Sjbextern int pci_slot_names_prop(int, char *, int); 101178479Sjb 102178479Sjb/* set non-zero to force PCI peer-bus renumbering */ 103178479Sjbint pci_bus_always_renumber = 0; 104178479Sjb 105178479Sjb/* get the subordinate bus # for a root/peer bus */ 106178479Sjbstatic int 107178479Sjbpci_root_subbus(int bus, uchar_t *subbus) 108178479Sjb{ 109178479Sjb ACPI_HANDLE hdl; 110178479Sjb ACPI_BUFFER rb; 111178479Sjb ACPI_RESOURCE *rp; 112178479Sjb int rv; 113178479Sjb 114178479Sjb if (pci_bus_res[bus].dip == NULL) { 115178479Sjb /* non-used bus # */ 116178479Sjb return (AE_ERROR); 117178479Sjb } 118178479Sjb if (acpica_get_handle(pci_bus_res[bus].dip, &hdl) != AE_OK) { 119178479Sjb cmn_err(CE_WARN, "!No ACPI obj for bus%d, ACPI OFF?\n", bus); 120178479Sjb return (AE_ERROR); 121178479Sjb } 122178479Sjb 123178479Sjb rb.Length = ACPI_ALLOCATE_BUFFER; 124178479Sjb if (AcpiGetCurrentResources(hdl, &rb) != AE_OK) { 125178479Sjb cmn_err(CE_WARN, "!_CRS failed on pci%d\n", bus); 126178479Sjb return (AE_ERROR); 127178479Sjb } 128178479Sjb 129178479Sjb rv = AE_ERROR; 130178479Sjb 131178479Sjb for (rp = rb.Pointer; rp->Type != ACPI_RESOURCE_TYPE_END_TAG; 132178479Sjb rp = ACPI_NEXT_RESOURCE(rp)) { 133178479Sjb 134178479Sjb switch (rp->Type) { 135178479Sjb case ACPI_RESOURCE_TYPE_ADDRESS16: 136178479Sjb if (rp->Data.Address.ResourceType != 137178479Sjb ACPI_BUS_NUMBER_RANGE) 138178479Sjb continue; 139178479Sjb *subbus = (uchar_t)rp->Data.Address16.Maximum; 140178479Sjb dcmn_err(CE_NOTE, "Address16,subbus=%d\n", *subbus); 141178479Sjb break; 142178479Sjb case ACPI_RESOURCE_TYPE_ADDRESS32: 143178479Sjb if (rp->Data.Address.ResourceType != 144178479Sjb ACPI_BUS_NUMBER_RANGE) 145178479Sjb continue; 146178479Sjb *subbus = (uchar_t)rp->Data.Address32.Maximum; 147178479Sjb dcmn_err(CE_NOTE, "Address32,subbus=%d\n", *subbus); 148178479Sjb break; 149178479Sjb case ACPI_RESOURCE_TYPE_ADDRESS64: 150178479Sjb if (rp->Data.Address.ResourceType != 151178479Sjb ACPI_BUS_NUMBER_RANGE) 152178479Sjb continue; 153178479Sjb *subbus = (uchar_t)rp->Data.Address64.Maximum; 154178479Sjb dcmn_err(CE_NOTE, "Address64,subbus=%d\n", *subbus); 155178479Sjb break; 156178479Sjb case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 157178479Sjb if (rp->Data.Address.ResourceType != 158178479Sjb ACPI_BUS_NUMBER_RANGE) 159178479Sjb continue; 160178479Sjb *subbus = (uchar_t)rp->Data.ExtAddress64.Maximum; 161178479Sjb dcmn_err(CE_NOTE, "ExtAdr64,subbus=%d\n", *subbus); 162178479Sjb break; 163178479Sjb default: 164178479Sjb dcmn_err(CE_NOTE, "rp->Type=%d\n", rp->Type); 165178479Sjb continue; 166178479Sjb } 167178479Sjb 168178479Sjb /* found the bus-range resource */ 169178479Sjb dcmn_err(CE_NOTE, "pci%d, subbus=%d\n", bus, *subbus); 170178479Sjb rv = AE_OK; 171178479Sjb 172178479Sjb /* This breaks out of the resource scanning loop */ 173178479Sjb break; 174178479Sjb } 175178479Sjb 176178479Sjb AcpiOsFree(rb.Pointer); 177178479Sjb if (rv != AE_OK) 178178479Sjb cmn_err(CE_NOTE, "!No bus-range resource for pci%d\n", bus); 179178479Sjb 180178479Sjb return (rv); 181178479Sjb 182178479Sjb} 183178479Sjb 184178479Sjb/* 185178479Sjb * Enumerate all PCI devices 186178479Sjb */ 187178479Sjbvoid 188178479Sjbpci_setup_tree() 189178479Sjb{ 190178479Sjb uchar_t i, root_bus_addr = 0; 191178479Sjb 192178479Sjb alloc_res_array(); 193178479Sjb for (i = 0; i <= pci_bios_nbus; i++) { 194178479Sjb pci_bus_res[i].par_bus = (uchar_t)-1; 195178479Sjb pci_bus_res[i].root_addr = (uchar_t)-1; 196178479Sjb pci_bus_res[i].sub_bus = i; 197178479Sjb } 198178479Sjb 199178479Sjb pci_bus_res[0].root_addr = root_bus_addr++; 200178479Sjb create_root_bus_dip(0); 201178479Sjb enumerate_bus_devs(0, CONFIG_INFO); 202178479Sjb 203178479Sjb /* 204178479Sjb * Now enumerate peer busses 205178479Sjb * 206178479Sjb * We loop till pci_bios_nbus. On most systems, there is 207178479Sjb * one more bus at the high end, which implements the ISA 208178479Sjb * compatibility bus. We don't care about that. 209178479Sjb * 210178479Sjb * Note: In the old (bootconf) enumeration, the peer bus 211178479Sjb * address did not use the bus number, and there were 212178479Sjb * too many peer busses created. The root_bus_addr is 213178479Sjb * used to maintain the old peer bus address assignment. 214178479Sjb * However, we stop enumerating phantom peers with no 215178479Sjb * device below. 216178479Sjb */ 217178479Sjb for (i = 1; i <= pci_bios_nbus; i++) { 218178479Sjb if (pci_bus_res[i].dip == NULL) { 219178479Sjb pci_bus_res[i].root_addr = root_bus_addr++; 220178479Sjb } 221178479Sjb enumerate_bus_devs(i, CONFIG_INFO); 222178479Sjb 223178479Sjb /* add slot-names property for named pci hot-plug slots */ 224178479Sjb add_bus_slot_names_prop(i); 225178479Sjb } 226178479Sjb 227178479Sjb} 228178479Sjb 229178479Sjb/* 230178573Sjb * >0 = present, 0 = not present, <0 = error 231178573Sjb */ 232178573Sjbstatic int 233178573Sjbpci_bbn_present(int bus) 234178573Sjb{ 235178573Sjb ACPI_HANDLE hdl; 236178573Sjb ACPI_BUFFER rb; 237178479Sjb int rv; 238178479Sjb 239178479Sjb /* no dip means no _BBN */ 240178479Sjb if (pci_bus_res[bus].dip == NULL) 241178573Sjb return (0); 242178573Sjb 243178573Sjb rv = acpica_get_handle(pci_bus_res[bus].dip, &hdl); 244178573Sjb if (rv != AE_OK) 245178573Sjb return (-1); 246178573Sjb 247178479Sjb rb.Length = ACPI_ALLOCATE_BUFFER; 248178479Sjb 249178479Sjb rv = AcpiEvaluateObject(hdl, "_BBN", NULL, &rb); 250178479Sjb 251178479Sjb if (rb.Length > 0) 252178479Sjb AcpiOsFree(rb.Pointer); 253178479Sjb 254178479Sjb if (rv == AE_OK) 255178479Sjb return (1); 256178479Sjb else if (rv == AE_NOT_FOUND) 257178479Sjb return (0); 258178479Sjb else 259178479Sjb return (-1); 260178479Sjb} 261178479Sjb 262178479Sjb/* 263178479Sjb * Return non-zero if any PCI bus in the system has an associated 264178479Sjb * _BBN object, 0 otherwise. 265178479Sjb */ 266178479Sjbstatic int 267178479Sjbpci_roots_have_bbn(void) 268178479Sjb{ 269178479Sjb int i; 270178479Sjb 271178479Sjb /* 272178479Sjb * Scan the PCI busses and look for at least 1 _BBN 273178479Sjb */ 274178479Sjb for (i = 0; i <= pci_bios_nbus; i++) { 275178479Sjb /* skip non-root (peer) PCI busses */ 276178479Sjb if (pci_bus_res[i].par_bus != (uchar_t)-1) 277178479Sjb continue; 278178479Sjb 279178479Sjb if (pci_bbn_present(i) > 0) 280178479Sjb return (1); 281178479Sjb } 282178479Sjb return (0); 283178479Sjb 284178479Sjb} 285178479Sjb 286178479Sjb/* 287178479Sjb * return non-zero if the machine is one on which we renumber 288178479Sjb * the internal pci unit-addresses 289178479Sjb */ 290178479Sjbstatic int 291178479Sjbpci_bus_renumber() 292178479Sjb{ 293178479Sjb ACPI_TABLE_HEADER *fadt; 294178479Sjb 295178479Sjb if (pci_bus_always_renumber) 296178479Sjb return (1); 297178479Sjb 298178479Sjb /* get the FADT */ 299178479Sjb if (AcpiGetFirmwareTable(FADT_SIG, 1, ACPI_LOGICAL_ADDRESSING, 300178479Sjb (ACPI_TABLE_HEADER **)&fadt) != AE_OK) 301178479Sjb return (0); 302178479Sjb 303178479Sjb /* compare OEM Table ID to "SUNm31" */ 304178479Sjb if (strncmp("SUNm31", fadt->OemId, 6)) 305178479Sjb return (0); 306178479Sjb else 307178479Sjb return (1); 308178479Sjb} 309178479Sjb 310178479Sjb/* 311178479Sjb * Initial enumeration of the physical PCI bus hierarchy can 312178479Sjb * leave 'gaps' in the order of peer PCI bus unit-addresses. 313178479Sjb * Systems with more than one peer PCI bus *must* have an ACPI 314178479Sjb * _BBN object associated with each peer bus; use the presence 315178479Sjb * of this object to remove gaps in the numbering of the peer 316178479Sjb * PCI bus unit-addresses - only peer busses with an associated 317178479Sjb * _BBN are counted. 318178479Sjb */ 319178479Sjbstatic void 320178479Sjbpci_renumber_root_busses(void) 321178479Sjb{ 322178479Sjb int pci_regs[] = {0, 0, 0}; 323178479Sjb int i, root_addr = 0; 324178479Sjb 325178479Sjb /* 326178479Sjb * Currently, we only enable the re-numbering on specific 327178479Sjb * Sun machines; this is a work-around for the more complicated 328178479Sjb * issue of upgrade changing physical device paths 329178479Sjb */ 330178479Sjb if (!pci_bus_renumber()) 331178479Sjb return; 332178479Sjb 333178479Sjb /* 334178479Sjb * If we find no _BBN objects at all, we either don't need 335178479Sjb * to do anything or can't do anything anyway 336178479Sjb */ 337178479Sjb if (!pci_roots_have_bbn()) 338178479Sjb return; 339178479Sjb 340178479Sjb for (i = 0; i <= pci_bios_nbus; i++) { 341178479Sjb /* skip non-root (peer) PCI busses */ 342178479Sjb if (pci_bus_res[i].par_bus != (uchar_t)-1) 343178479Sjb continue; 344178479Sjb 345178479Sjb if (pci_bbn_present(i) < 1) { 346178479Sjb pci_bus_res[i].root_addr = (uchar_t)-1; 347178479Sjb continue; 348178479Sjb } 349178479Sjb 350178479Sjb ASSERT(pci_bus_res[i].dip != NULL); 351178479Sjb if (pci_bus_res[i].root_addr != root_addr) { 352178479Sjb /* update reg property for node */ 353178479Sjb pci_bus_res[i].root_addr = root_addr; 354178479Sjb pci_regs[0] = pci_bus_res[i].root_addr; 355178479Sjb (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 356178479Sjb pci_bus_res[i].dip, "reg", (int *)pci_regs, 3); 357178479Sjb } 358178479Sjb root_addr++; 359178479Sjb } 360178479Sjb} 361178479Sjb 362178479Sjbstatic void 363178479Sjbremove_resource_range(struct memlist **list, int *ranges, int range_count) 364178479Sjb{ 365178479Sjb struct range { 366178479Sjb uint32_t base; 367178479Sjb uint32_t len; 368178479Sjb }; 369178479Sjb int index; 370178479Sjb 371178479Sjb for (index = 0; index < range_count; index++) { 372178479Sjb /* all done if list is or has become empty */ 373178479Sjb if (*list == NULL) 374178479Sjb break; 375178479Sjb (void) memlist_remove(list, 376178479Sjb (uint64_t)((struct range *)ranges)[index].base, 377178479Sjb (uint64_t)((struct range *)ranges)[index].len); 378178479Sjb } 379178479Sjb} 380178479Sjb 381178479Sjbstatic void 382178479Sjbremove_used_resources() 383178479Sjb{ 384178479Sjb dev_info_t *used; 385178479Sjb int *narray; 386178479Sjb uint_t ncount; 387178479Sjb int status; 388178479Sjb int bus; 389178479Sjb 390178479Sjb used = ddi_find_devinfo("used-resources", -1, 0); 391178479Sjb if (used == NULL) 392178479Sjb return; 393178479Sjb 394178479Sjb status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used, 395178479Sjb DDI_PROP_DONTPASS, "io-space", &narray, &ncount); 396178479Sjb if (status == DDI_PROP_SUCCESS) { 397178479Sjb for (bus = 0; bus <= pci_bios_nbus; bus++) 398178479Sjb remove_resource_range(&pci_bus_res[bus].io_ports, 399178479Sjb narray, ncount / 2); 400178479Sjb ddi_prop_free(narray); 401178479Sjb } 402178479Sjb 403178479Sjb status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used, 404178479Sjb DDI_PROP_DONTPASS, "device-memory", &narray, &ncount); 405178479Sjb if (status == DDI_PROP_SUCCESS) { 406178479Sjb for (bus = 0; bus <= pci_bios_nbus; bus++) 407178479Sjb remove_resource_range(&pci_bus_res[bus].mem_space, 408178479Sjb narray, ncount / 2); 409178479Sjb ddi_prop_free(narray); 410178479Sjb } 411178479Sjb} 412178479Sjb 413178479Sjb/* 414178479Sjb * Assign i/o resources to unconfigured hotplug bridges after the first pass. 415178479Sjb * It must be after the first pass in order to use the ports left over after 416178479Sjb * accounting for i/o resources of bridges that have been configured by bios. 417178479Sjb * We are expecting unconfigured bridges to be empty bridges otherwise 418178573Sjb * this resource assignment needs to be done at an earlier stage. 419178573Sjb */ 420178573Sjbstatic void 421178573Sjbfix_ppb_res(uchar_t secbus) 422178573Sjb{ 423178573Sjb uchar_t bus, dev, func; 424178573Sjb uint_t io_base, io_limit, io_size = 0x1000; 425178573Sjb uint64_t addr = 0; 426178573Sjb int *regp = NULL, rv; 427178573Sjb uint_t reglen; 428178479Sjb dev_info_t *dip; 429178479Sjb 430178479Sjb dip = pci_bus_res[secbus].dip; 431178479Sjb /* some entries may be empty due to discontiguous bus numbering */ 432178479Sjb if (dip == NULL) 433178479Sjb return; 434178479Sjb 435178479Sjb if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 436178479Sjb "pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE) 437178479Sjb return; 438178479Sjb 439178479Sjb rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 440178573Sjb "reg", ®p, ®len); 441178479Sjb if (rv != DDI_PROP_SUCCESS || reglen == 0) { 442178479Sjb /* panic to enforce proper calling order */ 443178479Sjb cmn_err(CE_PANIC, "reg property unset for bus %d\n", secbus); 444178479Sjb return; 445178479Sjb } 446178479Sjb 447178479Sjb func = (uchar_t)((regp[0] >> 8) & 0x7); 448178479Sjb dev = (uchar_t)((regp[0] >> 11) & 0x1f); 449178479Sjb bus = (uchar_t)((regp[0] >> 16) & 0xff); 450178479Sjb ASSERT(bus == pci_bus_res[secbus].par_bus); 451178479Sjb 452178479Sjb /* 453178479Sjb * io_base >= io_limit means that the bridge was not configured 454178479Sjb * This may have been set by the bios or by add_ppb_props() 455178479Sjb */ 456178479Sjb io_base = pci_getb(bus, dev, func, PCI_BCNF_IO_BASE_LOW); 457178479Sjb io_limit = pci_getb(bus, dev, func, PCI_BCNF_IO_LIMIT_LOW); 458178479Sjb ASSERT(io_base != 0xff && io_limit != 0xff); 459178479Sjb 460178479Sjb io_base = (io_base & 0xf0) << 8; 461178479Sjb io_limit = ((io_limit & 0xf0) << 8) | 0xfff; 462178479Sjb if (io_base < io_limit && io_base != 0) 463178479Sjb return; 464178479Sjb 465178479Sjb if (ddi_get_child(dip) != NULL) { 466178479Sjb cmn_err(CE_WARN, "detected unsupported configuration: " 467178479Sjb "non-empty bridge (bus 0x%x, dev 0x%x, func 0x%x) without " 468178479Sjb "I/O resources assigned by bios for secondary bus 0x%x\n", 469178479Sjb bus, dev, func, secbus); 470178479Sjb goto IOFAIL; 471178479Sjb } 472178479Sjb 473178479Sjb if (pci_bus_res[bus].io_ports != NULL) 474178479Sjb addr = memlist_find(&pci_bus_res[bus].io_ports, io_size, 475178479Sjb 0x1000); 476178479Sjb 477178479Sjb ASSERT(addr <= 0xf000); 478178479Sjb if (addr == 0) { 479178479Sjb cmn_err(CE_WARN, "out of I/O resources on bridge: bus 0x%x, " 480178479Sjb "dev 0x%x, func 0x%x, for secondary bus 0x%x\n", 481178479Sjb bus, dev, func, secbus); 482178479Sjb goto IOFAIL; 483178479Sjb } 484178479Sjb 485178479Sjb memlist_insert(&pci_bus_res[secbus].io_ports, addr, io_size); 486178479Sjb io_base = addr; 487178479Sjb io_limit = addr + io_size - 1; 488178479Sjb pci_putb(bus, dev, func, PCI_BCNF_IO_BASE_LOW, 489178479Sjb (uint8_t)((io_base >> 8) & 0xf0)); 490178479Sjb pci_putb(bus, dev, func, PCI_BCNF_IO_LIMIT_LOW, 491178479Sjb (uint8_t)((io_limit >> 8) & 0xf0)); 492178479Sjb 493178479Sjb add_ppb_ranges_prop(secbus); 494178479Sjb return; 495178479Sjb 496178479Sjb /*NOTREACHED*/ 497178479SjbIOFAIL: 498178479Sjb cmn_err(CE_WARN, "devices under bridge bus 0x%x, dev 0x%x, func 0x%x " 499178479Sjb "will not be assigned I/O ports\n", bus, dev, func); 500178479Sjb} 501178479Sjb 502178479Sjbvoid 503178479Sjbpci_reprogram(void) 504178479Sjb{ 505178479Sjb int i, pci_reconfig = 1; 506178479Sjb char *onoff; 507178479Sjb 508178479Sjb /* 509178479Sjb * Excise phantom roots if possible 510178479Sjb */ 511178479Sjb pci_renumber_root_busses(); 512178479Sjb 513178479Sjb /* add bus-range property for root/peer bus nodes */ 514178479Sjb for (i = 0; i <= pci_bios_nbus; i++) { 515178479Sjb if (pci_bus_res[i].par_bus == (uchar_t)-1) { 516178479Sjb uchar_t subbus; 517178479Sjb if (pci_root_subbus(i, &subbus) == AE_OK) 518178573Sjb pci_bus_res[i].sub_bus = subbus; 519178479Sjb add_bus_range_prop(i); 520178573Sjb } 521178479Sjb } 522178479Sjb 523178573Sjb if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 524178573Sjb DDI_PROP_DONTPASS, "pci-reprog", &onoff) == DDI_SUCCESS) { 525178573Sjb if (strcmp(onoff, "off") == 0) { 526178479Sjb pci_reconfig = 0; 527178573Sjb cmn_err(CE_NOTE, "pci device reprogramming disabled"); 528178573Sjb } 529178573Sjb ddi_prop_free(onoff); 530178573Sjb } 531178573Sjb 532178573Sjb /* remove used-resources from PCI resource maps */ 533178573Sjb remove_used_resources(); 534178573Sjb 535178573Sjb for (i = 0; i <= pci_bios_nbus; i++) { 536178479Sjb /* configure devices not configured by bios */ 537178479Sjb if (pci_reconfig) { 538178479Sjb fix_ppb_res(i); 539178479Sjb enumerate_bus_devs(i, CONFIG_NEW); 540178479Sjb } 541178479Sjb /* All dev programmed, so we can create available prop */ 542178479Sjb add_bus_available_prop(i); 543178479Sjb } 544178479Sjb} 545178479Sjb 546178479Sjb/* 547178479Sjb * Create top-level bus dips, i.e. /pci@0,0, /pci@1,0... 548178479Sjb */ 549178479Sjbstatic void 550178479Sjbcreate_root_bus_dip(uchar_t bus) 551178479Sjb{ 552178479Sjb int pci_regs[] = {0, 0, 0}; 553178479Sjb dev_info_t *dip; 554178479Sjb 555178479Sjb ASSERT(pci_bus_res[bus].par_bus == (uchar_t)-1); 556178479Sjb 557178479Sjb ndi_devi_alloc_sleep(ddi_root_node(), "pci", 558178479Sjb (pnode_t)DEVI_SID_NODEID, &dip); 559178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 560178479Sjb "#address-cells", 3); 561178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 562178479Sjb "#size-cells", 2); 563178479Sjb pci_regs[0] = pci_bus_res[bus].root_addr; 564178479Sjb (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 565178479Sjb "reg", (int *)pci_regs, 3); 566178479Sjb 567178479Sjb /* 568178479Sjb * If system has PCIe bus, then create different properties 569178479Sjb */ 570178479Sjb if (create_pcie_root_bus(bus, dip) == B_FALSE) 571178479Sjb (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 572178479Sjb "device_type", "pci"); 573178479Sjb 574178479Sjb (void) ndi_devi_bind_driver(dip, 0); 575178479Sjb pci_bus_res[bus].dip = dip; 576178479Sjb pci_bus_res[bus].pmem_space = find_bus_res(bus, PREFETCH_TYPE); 577178479Sjb pci_bus_res[bus].mem_space = find_bus_res(bus, MEM_TYPE); 578178479Sjb pci_bus_res[bus].io_ports = find_bus_res(bus, IO_TYPE); 579178479Sjb 580178479Sjb if (bus != 0) 581178479Sjb return; 582178479Sjb 583178479Sjb /* 584178479Sjb * Special treatment of bus 0: 585178479Sjb * If no resource from MPSPEC/HRT, copy pcimem from boot 586178479Sjb * and make I/O space the entire range starting at 0x100. There 587178479Sjb * is no difference between prefetchable memory or not. 588178479Sjb */ 589178479Sjb if (pci_bus_res[0].mem_space == NULL) 590178479Sjb pci_bus_res[0].mem_space = 591178479Sjb memlist_dup(bootops->boot_mem->pcimem); 592178479Sjb /* Exclude 0x00 to 0xff of the I/O space, used by all PCs */ 593178479Sjb if (pci_bus_res[0].io_ports == NULL) 594178479Sjb memlist_insert(&pci_bus_res[0].io_ports, 0x100, 0xff00); 595178479Sjb} 596178479Sjb 597178479Sjb/* 598178479Sjb * For any fixed configuration (often compatability) pci devices 599178479Sjb * and those with their own expansion rom, create device nodes 600178479Sjb * to hold the already configured device details. 601178479Sjb */ 602178479Sjbvoid 603178479Sjbenumerate_bus_devs(uchar_t bus, int config_op) 604178479Sjb{ 605178479Sjb uchar_t dev, func, nfunc, header; 606178479Sjb ushort_t venid; 607178479Sjb dev_info_t *dip; 608178479Sjb struct pci_devfunc { 609178479Sjb struct pci_devfunc *next; 610178479Sjb dev_info_t *dip; 611178479Sjb uchar_t bus; 612178479Sjb uchar_t dev; 613178479Sjb uchar_t func; 614178479Sjb } *devlist = NULL, *entry; 615178479Sjb 616178479Sjb if (config_op == CONFIG_NEW) { 617178479Sjb dcmn_err(CE_NOTE, "configuring pci bus 0x%x", bus); 618178479Sjb } else if (config_op == CONFIG_FIX) { 619178479Sjb dcmn_err(CE_NOTE, "fixing devices on pci bus 0x%x", bus); 620178479Sjb } else 621178479Sjb dcmn_err(CE_NOTE, "enumerating pci bus 0x%x", bus); 622178479Sjb 623178479Sjb for (dev = 0; dev < max_dev_pci; dev++) { 624178479Sjb nfunc = 1; 625178479Sjb for (func = 0; func < nfunc; func++) { 626178479Sjb 627178479Sjb dcmn_err(CE_NOTE, "probing dev 0x%x, func 0x%x", 628178479Sjb dev, func); 629178479Sjb 630178479Sjb venid = pci_getw(bus, dev, func, PCI_CONF_VENID); 631178479Sjb 632178479Sjb if ((venid == 0xffff) || (venid == 0)) { 633178479Sjb /* no function at this address */ 634178479Sjb continue; 635178479Sjb } 636178479Sjb 637178479Sjb header = pci_getb(bus, dev, func, PCI_CONF_HEADER); 638178479Sjb if (header == 0xff) { 639178479Sjb continue; /* illegal value */ 640178479Sjb } 641178479Sjb 642178479Sjb /* 643178479Sjb * according to some mail from Microsoft posted 644178479Sjb * to the pci-drivers alias, their only requirement 645178479Sjb * for a multifunction device is for the 1st 646178479Sjb * function to have to PCI_HEADER_MULTI bit set. 647178479Sjb */ 648178479Sjb if ((func == 0) && (header & PCI_HEADER_MULTI)) { 649178479Sjb nfunc = 8; 650178479Sjb } 651178479Sjb 652178479Sjb if (config_op == CONFIG_FIX) { 653178479Sjb /* 654178479Sjb * If we're processing PCI fixes, no dip 655178479Sjb * will be returned. 656178479Sjb */ 657178479Sjb (void) process_devfunc(bus, dev, func, header, 658178479Sjb venid, config_op); 659178479Sjb 660178479Sjb } else if (config_op == CONFIG_INFO) { 661178479Sjb /* 662178479Sjb * Create the node, unconditionally, on the 663178479Sjb * first pass only. It may still need 664178479Sjb * resource assignment, which will be 665178479Sjb * done on the second, CONFIG_NEW, pass. 666178573Sjb */ 667178479Sjb dip = process_devfunc(bus, dev, func, header, 668178573Sjb venid, config_op); 669178479Sjb /* 670178479Sjb * If dip isn't null, put on a list to 671178573Sjb * save for reprogramming when config_op 672178573Sjb * is CONFIG_NEW. 673178573Sjb */ 674178479Sjb 675178573Sjb if (dip) { 676178573Sjb entry = kmem_alloc(sizeof (*entry), 677178573Sjb KM_SLEEP); 678178573Sjb entry->dip = dip; 679178573Sjb entry->dev = dev; 680178573Sjb entry->func = func; 681178573Sjb entry->next = devlist; 682178573Sjb devlist = entry; 683178573Sjb } 684178479Sjb } 685178479Sjb } 686178479Sjb } 687178479Sjb 688178479Sjb if (config_op == CONFIG_NEW) { 689178479Sjb devlist = (struct pci_devfunc *)pci_bus_res[bus].privdata; 690178479Sjb while (devlist) { 691178479Sjb entry = devlist; 692178479Sjb devlist = entry->next; 693178479Sjb cmn_err(CE_NOTE, 694178479Sjb "!reprogram pci device [%d/%d/%d] (%s)", 695178479Sjb bus, entry->dev, entry->func, 696178479Sjb ddi_driver_name(entry->dip)); 697178479Sjb (void) add_reg_props(entry->dip, bus, entry->dev, 698178479Sjb entry->func, CONFIG_UPDATE, 0); 699178479Sjb kmem_free(entry, sizeof (*entry)); 700178479Sjb } 701178479Sjb pci_bus_res[bus].privdata = NULL; 702178479Sjb } else if (config_op != CONFIG_FIX) { 703178479Sjb pci_bus_res[bus].privdata = devlist; 704178479Sjb } 705178479Sjb} 706178479Sjb 707178479Sjbstatic int 708178479Sjbcheck_pciide_prop(uchar_t revid, ushort_t venid, ushort_t devid, 709178479Sjb ushort_t subvenid, ushort_t subdevid) 710178479Sjb{ 711178479Sjb static int prop_exist = -1; 712178479Sjb static char *pciide_str; 713178479Sjb char compat[32]; 714178479Sjb 715178479Sjb if (prop_exist == -1) { 716178479Sjb prop_exist = (ddi_prop_lookup_string(DDI_DEV_T_ANY, 717178479Sjb ddi_root_node(), DDI_PROP_DONTPASS, "pci-ide", 718178479Sjb &pciide_str) == DDI_SUCCESS); 719178479Sjb } 720178479Sjb 721178479Sjb if (!prop_exist) 722178479Sjb return (0); 723178479Sjb 724178479Sjb /* compare property value against various forms of compatible */ 725178479Sjb if (subvenid) { 726178479Sjb (void) snprintf(compat, sizeof (compat), "pci%x,%x.%x.%x.%x", 727178479Sjb venid, devid, subvenid, subdevid, revid); 728178479Sjb if (strcmp(pciide_str, compat) == 0) 729178479Sjb return (1); 730178479Sjb 731178479Sjb (void) snprintf(compat, sizeof (compat), "pci%x,%x.%x.%x", 732178479Sjb venid, devid, subvenid, subdevid); 733178479Sjb if (strcmp(pciide_str, compat) == 0) 734178479Sjb return (1); 735178479Sjb 736178479Sjb (void) snprintf(compat, sizeof (compat), "pci%x,%x", 737178479Sjb subvenid, subdevid); 738178479Sjb if (strcmp(pciide_str, compat) == 0) 739178479Sjb return (1); 740178479Sjb } 741178479Sjb (void) snprintf(compat, sizeof (compat), "pci%x,%x.%x", 742178479Sjb venid, devid, revid); 743178479Sjb if (strcmp(pciide_str, compat) == 0) 744178479Sjb return (1); 745178479Sjb 746178479Sjb (void) snprintf(compat, sizeof (compat), "pci%x,%x", venid, devid); 747178479Sjb if (strcmp(pciide_str, compat) == 0) 748178479Sjb return (1); 749178479Sjb 750178479Sjb return (0); 751178479Sjb} 752178479Sjb 753178479Sjbstatic int 754178479Sjbis_pciide(uchar_t basecl, uchar_t subcl, uchar_t revid, 755178479Sjb ushort_t venid, ushort_t devid, ushort_t subvenid, ushort_t subdevid) 756178479Sjb{ 757178479Sjb struct ide_table { /* table for PCI_MASS_OTHER */ 758178479Sjb ushort_t venid; 759178479Sjb ushort_t devid; 760178479Sjb } *entry; 761178479Sjb 762178479Sjb /* XXX SATA devices: need a way to add dynamically */ 763178479Sjb static struct ide_table ide_other[] = { 764178479Sjb {0x1095, 0x3112}, 765178479Sjb {0x1095, 0x3114}, 766178479Sjb {0x1095, 0x3512}, 767178479Sjb {0, 0} 768178479Sjb }; 769178479Sjb 770178479Sjb if (basecl != PCI_CLASS_MASS) 771178479Sjb return (0); 772178479Sjb 773178479Sjb if (subcl == PCI_MASS_IDE) { 774178479Sjb return (1); 775178479Sjb } 776178479Sjb 777178479Sjb if (subcl != PCI_MASS_OTHER && subcl != PCI_MASS_SATA) { 778178479Sjb return (0); 779178479Sjb } 780178479Sjb 781178479Sjb entry = &ide_other[0]; 782178479Sjb while (entry->venid) { 783178479Sjb if (entry->venid == venid && entry->devid == devid) 784178479Sjb return (1); 785178479Sjb entry++; 786178479Sjb } 787178479Sjb return (check_pciide_prop(revid, venid, devid, subvenid, subdevid)); 788178479Sjb} 789178479Sjb 790178479Sjbstatic int 791178479Sjbis_display(uint_t classcode) 792178479Sjb{ 793178479Sjb static uint_t disp_classes[] = { 794178479Sjb 0x000100, 795178479Sjb 0x030000, 796178479Sjb 0x030001 797178479Sjb }; 798178479Sjb int i, nclasses = sizeof (disp_classes) / sizeof (uint_t); 799178573Sjb 800178573Sjb for (i = 0; i < nclasses; i++) { 801178573Sjb if (classcode == disp_classes[i]) 802178573Sjb return (1); 803178573Sjb } 804178573Sjb return (0); 805178573Sjb} 806178573Sjb 807178573Sjbstatic void 808178573Sjbadd_undofix_entry(uint8_t bus, uint8_t dev, uint8_t fn, 809178573Sjb void (*undofn)(uint8_t, uint8_t, uint8_t)) 810178573Sjb{ 811178573Sjb struct pci_fixundo *newundo; 812178573Sjb 813178573Sjb newundo = kmem_alloc(sizeof (struct pci_fixundo), KM_SLEEP); 814178573Sjb 815178573Sjb /* 816178573Sjb * Adding an item to this list means that we must turn its NMIENABLE 817178573Sjb * bit back on at a later time. 818178573Sjb */ 819178573Sjb newundo->bus = bus; 820178573Sjb newundo->dev = dev; 821178573Sjb newundo->fn = fn; 822178573Sjb newundo->undofn = undofn; 823178573Sjb newundo->next = undolist; 824178573Sjb 825178573Sjb /* add to the undo list in LIFO order */ 826178573Sjb undolist = newundo; 827178573Sjb} 828178573Sjb 829178573Sjbvoid 830178573Sjbadd_pci_fixes(void) 831178573Sjb{ 832178573Sjb int i; 833178573Sjb 834178573Sjb for (i = 0; i <= pci_bios_nbus; i++) { 835178479Sjb /* 836178573Sjb * For each bus, apply needed fixes to the appropriate devices. 837178573Sjb * This must be done before the main enumeration loop because 838178479Sjb * some fixes must be applied to devices normally encountered 839178479Sjb * later in the pci scan (e.g. if a fix to device 7 must be 840178479Sjb * applied before scanning device 6, applying fixes in the 841178479Sjb * normal enumeration loop would obviously be too late). 842178479Sjb */ 843178479Sjb enumerate_bus_devs(i, CONFIG_FIX); 844178479Sjb } 845178479Sjb} 846178479Sjb 847178479Sjbvoid 848178479Sjbundo_pci_fixes(void) 849178479Sjb{ 850178479Sjb struct pci_fixundo *nextundo; 851178479Sjb uint8_t bus, dev, fn; 852178479Sjb 853178479Sjb /* 854178479Sjb * All fixes in the undo list are performed unconditionally. Future 855178479Sjb * fixes may require selective undo. 856178479Sjb */ 857178479Sjb while (undolist != NULL) { 858178479Sjb 859178479Sjb bus = undolist->bus; 860178479Sjb dev = undolist->dev; 861178479Sjb fn = undolist->fn; 862178479Sjb 863178479Sjb (*(undolist->undofn))(bus, dev, fn); 864178479Sjb 865178479Sjb nextundo = undolist->next; 866178479Sjb kmem_free(undolist, sizeof (struct pci_fixundo)); 867178479Sjb undolist = nextundo; 868178479Sjb } 869178479Sjb} 870178479Sjb 871178479Sjbstatic void 872178479Sjbundo_amd8111_pci_fix(uint8_t bus, uint8_t dev, uint8_t fn) 873184696Srodrigc{ 874178479Sjb uint8_t val8; 875178479Sjb 876184696Srodrigc val8 = pci_getb(bus, dev, fn, LPC_IO_CONTROL_REG_1); 877184696Srodrigc /* 878178479Sjb * The NMIONERR bit is turned back on to allow the SMM BIOS 879184696Srodrigc * to handle more critical PCI errors (e.g. PERR#). 880178479Sjb */ 881178479Sjb val8 |= AMD8111_ENABLENMI; 882184696Srodrigc pci_putb(bus, dev, fn, LPC_IO_CONTROL_REG_1, val8); 883184696Srodrigc} 884178479Sjb 885184696Srodrigcstatic void 886178479Sjbpci_fix_amd8111(uint8_t bus, uint8_t dev, uint8_t fn) 887178479Sjb{ 888178479Sjb uint8_t val8; 889178479Sjb 890178479Sjb val8 = pci_getb(bus, dev, fn, LPC_IO_CONTROL_REG_1); 891178479Sjb 892178479Sjb if ((val8 & AMD8111_ENABLENMI) == 0) 893178479Sjb return; 894178479Sjb 895178479Sjb /* 896178479Sjb * We reset NMIONERR in the LPC because master-abort on the PCI 897178479Sjb * bridge side of the 8111 will cause NMI, which might cause SMI, 898178479Sjb * which sometimes prevents all devices from being enumerated. 899178479Sjb */ 900178479Sjb val8 &= ~AMD8111_ENABLENMI; 901178479Sjb 902178479Sjb pci_putb(bus, dev, fn, LPC_IO_CONTROL_REG_1, val8); 903178479Sjb 904178479Sjb add_undofix_entry(bus, dev, fn, undo_amd8111_pci_fix); 905178479Sjb} 906178479Sjb 907178479Sjbstatic dev_info_t * 908178479Sjbprocess_devfunc(uchar_t bus, uchar_t dev, uchar_t func, uchar_t header, 909178479Sjb ushort_t vendorid, int config_op) 910178479Sjb{ 911178479Sjb char nodename[32], unitaddr[5]; 912178479Sjb dev_info_t *dip; 913178479Sjb uchar_t basecl, subcl, progcl, intr, revid; 914178479Sjb ushort_t subvenid, subdevid, status; 915178479Sjb ushort_t slot_num; 916178479Sjb uint_t classcode, revclass; 917178479Sjb int reprogram = 0, pciide = 0; 918178479Sjb int power[2] = {1, 1}; 919184696Srodrigc int pciex = 0; 920184696Srodrigc ushort_t is_pci_bridge = 0; 921184696Srodrigc 922184696Srodrigc ushort_t deviceid = pci_getw(bus, dev, func, PCI_CONF_DEVID); 923184696Srodrigc 924184696Srodrigc switch (header & PCI_HEADER_TYPE_M) { 925184696Srodrigc case PCI_HEADER_ZERO: 926184696Srodrigc subvenid = pci_getw(bus, dev, func, PCI_CONF_SUBVENID); 927184696Srodrigc subdevid = pci_getw(bus, dev, func, PCI_CONF_SUBSYSID); 928184696Srodrigc break; 929184696Srodrigc case PCI_HEADER_CARDBUS: 930178479Sjb subvenid = pci_getw(bus, dev, func, PCI_CBUS_SUBVENID); 931178479Sjb subdevid = pci_getw(bus, dev, func, PCI_CBUS_SUBSYSID); 932178479Sjb break; 933178479Sjb default: 934178479Sjb subvenid = 0; 935178479Sjb subdevid = 0; 936178479Sjb break; 937178479Sjb } 938184696Srodrigc 939184696Srodrigc if (config_op == CONFIG_FIX) { 940184696Srodrigc if (vendorid == VENID_AMD && deviceid == DEVID_AMD8111_LPC) { 941184696Srodrigc pci_fix_amd8111(bus, dev, func); 942184696Srodrigc } 943184696Srodrigc return (NULL); 944184696Srodrigc } 945184696Srodrigc 946184696Srodrigc /* XXX should be use generic names? derive from class? */ 947184696Srodrigc revclass = pci_getl(bus, dev, func, PCI_CONF_REVID); 948178479Sjb classcode = revclass >> 8; 949178479Sjb revid = revclass & 0xff; 950178479Sjb 951178479Sjb /* figure out if this is pci-ide */ 952178479Sjb basecl = classcode >> 16; 953178479Sjb subcl = (classcode >> 8) & 0xff; 954178479Sjb progcl = classcode & 0xff; 955178479Sjb 956178479Sjb 957178479Sjb if (is_display(classcode)) 958178479Sjb (void) snprintf(nodename, sizeof (nodename), "display"); 959178479Sjb else if (subvenid != 0) 960178479Sjb (void) snprintf(nodename, sizeof (nodename), 961178479Sjb "pci%x,%x", subvenid, subdevid); 962178479Sjb else 963178479Sjb (void) snprintf(nodename, sizeof (nodename), 964178479Sjb "pci%x,%x", vendorid, deviceid); 965178479Sjb 966178573Sjb /* make sure parent bus dip has been created */ 967178479Sjb if (pci_bus_res[bus].dip == NULL) { 968178573Sjb create_root_bus_dip(bus); 969178479Sjb } 970178479Sjb 971178479Sjb ndi_devi_alloc_sleep(pci_bus_res[bus].dip, nodename, 972178479Sjb DEVI_SID_NODEID, &dip); 973178479Sjb 974178479Sjb if (check_if_device_is_pciex(dip, bus, dev, func, &slot_num, 975178479Sjb &is_pci_bridge) == B_TRUE) 976178479Sjb pciex = 1; 977178479Sjb 978178573Sjb /* add properties */ 979178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "device-id", deviceid); 980178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vendor-id", vendorid); 981178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "revision-id", revid); 982178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 983178479Sjb "class-code", classcode); 984178479Sjb if (func == 0) 985178479Sjb (void) snprintf(unitaddr, sizeof (unitaddr), "%x", dev); 986178479Sjb else 987178479Sjb (void) snprintf(unitaddr, sizeof (unitaddr), 988178479Sjb "%x,%x", dev, func); 989178479Sjb (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 990178479Sjb "unit-address", unitaddr); 991178479Sjb 992178479Sjb /* add device_type for display nodes */ 993178479Sjb if (is_display(classcode)) { 994178479Sjb (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 995178479Sjb "device_type", "display"); 996178479Sjb } 997178479Sjb /* add special stuff for header type */ 998178479Sjb if ((header & PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) { 999178479Sjb uchar_t mingrant = pci_getb(bus, dev, func, PCI_CONF_MIN_G); 1000178479Sjb uchar_t maxlatency = pci_getb(bus, dev, func, PCI_CONF_MAX_L); 1001178479Sjb 1002178573Sjb if (subvenid != 0) { 1003178573Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1004178479Sjb "subsystem-id", subdevid); 1005178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1006178573Sjb "subsystem-vendor-id", subvenid); 1007178573Sjb } 1008178573Sjb if (!pciex) 1009178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1010178479Sjb "min-grant", mingrant); 1011178479Sjb if (!pciex) 1012178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1013178573Sjb "max-latency", maxlatency); 1014178573Sjb } 1015178479Sjb 1016178479Sjb /* interrupt, record if not 0 */ 1017178479Sjb intr = pci_getb(bus, dev, func, PCI_CONF_IPIN); 1018178479Sjb if (intr != 0) 1019178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1020178573Sjb "interrupts", intr); 1021178573Sjb 1022178479Sjb /* 1023178479Sjb * Add support for 133 mhz pci eventually 1024178479Sjb */ 1025178479Sjb status = pci_getw(bus, dev, func, PCI_CONF_STAT); 1026178479Sjb 1027178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1028178573Sjb "devsel-speed", (status & PCI_STAT_DEVSELT) >> 9); 1029178573Sjb if (!pciex && (status & PCI_STAT_FBBC)) 1030178479Sjb (void) ndi_prop_create_boolean(DDI_DEV_T_NONE, dip, 1031178573Sjb "fast-back-to-back"); 1032178573Sjb if (!pciex && (status & PCI_STAT_66MHZ)) 1033178573Sjb (void) ndi_prop_create_boolean(DDI_DEV_T_NONE, dip, 1034178479Sjb "66mhz-capable"); 1035178479Sjb if (status & PCI_STAT_UDF) 1036178479Sjb (void) ndi_prop_create_boolean(DDI_DEV_T_NONE, dip, 1037178573Sjb "udf-supported"); 1038178573Sjb if (pciex && slot_num) 1039178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1040178479Sjb "physical-slot#", slot_num); 1041178479Sjb 1042178479Sjb (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 1043178479Sjb "power-consumption", power, 2); 1044178479Sjb 1045178479Sjb if ((basecl == PCI_CLASS_BRIDGE) && (subcl == PCI_BRIDGE_PCI)) 1046178479Sjb add_ppb_props(dip, bus, dev, func, pciex); 1047178573Sjb 1048178479Sjb if (config_op == CONFIG_INFO && 1049178479Sjb IS_CLASS_IOAPIC(basecl, subcl, progcl)) { 1050178479Sjb create_ioapic_node(bus, dev, func, vendorid, deviceid); 1051178479Sjb } 1052178479Sjb 1053178479Sjb /* check for ck8-04 based PCI ISA bridge only */ 1054178479Sjb if (NVIDIA_IS_LPC_BRIDGE(vendorid, deviceid) && (dev == 1) && 1055178479Sjb (func == 0)) 1056178573Sjb add_nvidia_isa_bridge_props(dip, bus, dev, func); 1057178479Sjb 1058178479Sjb if (pciex && is_pci_bridge) 1059178479Sjb (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "model", 1060178479Sjb (char *)"PCIe-PCI bridge"); 1061178479Sjb else 1062178573Sjb add_model_prop(dip, classcode); 1063178479Sjb 1064178479Sjb add_compatible(dip, subvenid, subdevid, vendorid, deviceid, 1065178479Sjb revid, classcode, pciex); 1066178479Sjb 1067178479Sjb /* 1068178479Sjb * See if this device is a controller that advertises 1069178479Sjb * itself to be a standard ATA task file controller, or one that 1070178479Sjb * has been hard coded. 1071178479Sjb * 1072178479Sjb * If it is, check if any other higher precedence driver listed in 1073178479Sjb * driver_aliases will claim the node by calling 1074178479Sjb * ddi_compatibile_driver_major. If so, clear pciide and do not 1075178479Sjb * create a pci-ide node or any other special handling. 1076178479Sjb * 1077178479Sjb * If another driver does not bind, set the node name to pci-ide 1078178479Sjb * and then let the special pci-ide handling for registers and 1079178479Sjb * child pci-ide nodes proceed below. 1080178479Sjb */ 1081178479Sjb if (is_pciide(basecl, subcl, revid, vendorid, deviceid, 1082178479Sjb subvenid, subdevid) == 1) { 1083178479Sjb if (ddi_compatible_driver_major(dip, NULL) == (major_t)-1) { 1084178479Sjb (void) ndi_devi_set_nodename(dip, "pci-ide", 0); 1085178479Sjb pciide = 1; 1086178479Sjb } 1087178479Sjb } 1088178479Sjb 1089178479Sjb reprogram = add_reg_props(dip, bus, dev, func, config_op, pciide); 1090178479Sjb (void) ndi_devi_bind_driver(dip, 0); 1091178479Sjb 1092178479Sjb /* special handling for pci-ide */ 1093178479Sjb if (pciide) { 1094178479Sjb dev_info_t *cdip; 1095178479Sjb 1096178479Sjb /* 1097178479Sjb * Create properties specified by P1275 Working Group 1098178479Sjb * Proposal #414 Version 1 1099178479Sjb */ 1100178479Sjb (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 1101178479Sjb "device_type", "pci-ide"); 1102178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1103178479Sjb "#address-cells", 1); 1104178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1105178479Sjb "#size-cells", 0); 1106178479Sjb 1107178479Sjb /* allocate two child nodes */ 1108178479Sjb ndi_devi_alloc_sleep(dip, "ide", 1109178479Sjb (pnode_t)DEVI_SID_NODEID, &cdip); 1110178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 1111178479Sjb "reg", 0); 1112178479Sjb (void) ndi_devi_bind_driver(cdip, 0); 1113178479Sjb ndi_devi_alloc_sleep(dip, "ide", 1114178479Sjb (pnode_t)DEVI_SID_NODEID, &cdip); 1115178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 1116178479Sjb "reg", 1); 1117178479Sjb (void) ndi_devi_bind_driver(cdip, 0); 1118178479Sjb 1119178479Sjb reprogram = 0; /* don't reprogram pci-ide bridge */ 1120178479Sjb } 1121178479Sjb 1122178479Sjb 1123178479Sjb if (reprogram) 1124178479Sjb return (dip); 1125178479Sjb return (NULL); 1126178479Sjb} 1127178479Sjb 1128178479Sjb/* 1129178479Sjb * Set the compatible property to a value compliant with 1130178479Sjb * rev 2.1 of the IEEE1275 PCI binding. 1131178479Sjb * (Also used for PCI-Express devices). 1132178479Sjb * 1133178479Sjb * pciVVVV,DDDD.SSSS.ssss.RR (0) 1134178479Sjb * pciVVVV,DDDD.SSSS.ssss (1) 1135178479Sjb * pciSSSS,ssss (2) 1136178479Sjb * pciVVVV,DDDD.RR (3) 1137178479Sjb * pciVVVV,DDDD (4) 1138178479Sjb * pciclass,CCSSPP (5) 1139178479Sjb * pciclass,CCSS (6) 1140178479Sjb * 1141178479Sjb * The Subsystem (SSSS) forms are not inserted if 1142178479Sjb * subsystem-vendor-id is 0. 1143178479Sjb * 1144178479Sjb * NOTE: For PCI-Express devices "pci" is replaced with "pciex" in 0-6 above 1145178479Sjb * property 2 is not created as per "1275 bindings for PCI Express Interconnect" 1146178479Sjb * 1147178479Sjb * Set with setprop and \x00 between each 1148178479Sjb * to generate the encoded string array form. 1149178479Sjb */ 1150178479Sjbvoid 1151178479Sjbadd_compatible(dev_info_t *dip, ushort_t subvenid, ushort_t subdevid, 1152178479Sjb ushort_t vendorid, ushort_t deviceid, uchar_t revid, uint_t classcode, 1153178479Sjb int pciex) 1154178479Sjb{ 1155178479Sjb int i = 0; 1156178479Sjb int size = COMPAT_BUFSIZE; 1157178573Sjb char *compat[13]; 1158178573Sjb char *buf, *curr; 1159178573Sjb 1160178573Sjb curr = buf = kmem_alloc(size, KM_SLEEP); 1161178573Sjb 1162178573Sjb if (pciex) { 1163178573Sjb if (subvenid) { 1164178479Sjb compat[i++] = curr; /* form 0 */ 1165178479Sjb (void) snprintf(curr, size, "pciex%x,%x.%x.%x.%x", 1166178479Sjb vendorid, deviceid, subvenid, subdevid, revid); 1167178479Sjb size -= strlen(curr) + 1; 1168178479Sjb curr += strlen(curr) + 1; 1169178479Sjb 1170178479Sjb compat[i++] = curr; /* form 1 */ 1171178573Sjb (void) snprintf(curr, size, "pciex%x,%x.%x.%x", 1172178573Sjb vendorid, deviceid, subvenid, subdevid); 1173178573Sjb size -= strlen(curr) + 1; 1174178573Sjb curr += strlen(curr) + 1; 1175178573Sjb 1176178573Sjb } 1177178573Sjb compat[i++] = curr; /* form 3 */ 1178178479Sjb (void) snprintf(curr, size, "pciex%x,%x.%x", 1179178479Sjb vendorid, deviceid, revid); 1180178573Sjb size -= strlen(curr) + 1; 1181178479Sjb curr += strlen(curr) + 1; 1182178479Sjb 1183178479Sjb compat[i++] = curr; /* form 4 */ 1184178479Sjb (void) snprintf(curr, size, "pciex%x,%x", vendorid, deviceid); 1185178479Sjb size -= strlen(curr) + 1; 1186178479Sjb curr += strlen(curr) + 1; 1187178479Sjb 1188178479Sjb compat[i++] = curr; /* form 5 */ 1189178479Sjb (void) snprintf(curr, size, "pciexclass,%06x", classcode); 1190178479Sjb size -= strlen(curr) + 1; 1191178479Sjb curr += strlen(curr) + 1; 1192178479Sjb 1193178479Sjb compat[i++] = curr; /* form 6 */ 1194178479Sjb (void) snprintf(curr, size, "pciexclass,%04x", 1195178479Sjb (classcode >> 8)); 1196178479Sjb size -= strlen(curr) + 1; 1197178479Sjb curr += strlen(curr) + 1; 1198178479Sjb } 1199178479Sjb 1200178479Sjb if (subvenid) { 1201178479Sjb compat[i++] = curr; /* form 0 */ 1202178479Sjb (void) snprintf(curr, size, "pci%x,%x.%x.%x.%x", 1203178479Sjb vendorid, deviceid, subvenid, subdevid, revid); 1204178479Sjb size -= strlen(curr) + 1; 1205178479Sjb curr += strlen(curr) + 1; 1206178479Sjb 1207178479Sjb compat[i++] = curr; /* form 1 */ 1208178479Sjb (void) snprintf(curr, size, "pci%x,%x.%x.%x", 1209178479Sjb vendorid, deviceid, subvenid, subdevid); 1210178479Sjb size -= strlen(curr) + 1; 1211178479Sjb curr += strlen(curr) + 1; 1212178479Sjb 1213178479Sjb compat[i++] = curr; /* form 2 */ 1214178479Sjb (void) snprintf(curr, size, "pci%x,%x", subvenid, subdevid); 1215178479Sjb size -= strlen(curr) + 1; 1216178479Sjb curr += strlen(curr) + 1; 1217178479Sjb } 1218178479Sjb compat[i++] = curr; /* form 3 */ 1219178479Sjb (void) snprintf(curr, size, "pci%x,%x.%x", vendorid, deviceid, revid); 1220178479Sjb size -= strlen(curr) + 1; 1221178479Sjb curr += strlen(curr) + 1; 1222178479Sjb 1223178479Sjb compat[i++] = curr; /* form 4 */ 1224178479Sjb (void) snprintf(curr, size, "pci%x,%x", vendorid, deviceid); 1225178479Sjb size -= strlen(curr) + 1; 1226178479Sjb curr += strlen(curr) + 1; 1227178479Sjb 1228178479Sjb compat[i++] = curr; /* form 5 */ 1229178479Sjb (void) snprintf(curr, size, "pciclass,%06x", classcode); 1230178479Sjb size -= strlen(curr) + 1; 1231178479Sjb curr += strlen(curr) + 1; 1232178479Sjb 1233178479Sjb compat[i++] = curr; /* form 6 */ 1234178479Sjb (void) snprintf(curr, size, "pciclass,%04x", (classcode >> 8)); 1235178479Sjb size -= strlen(curr) + 1; 1236178479Sjb curr += strlen(curr) + 1; 1237178479Sjb 1238178479Sjb (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, 1239178479Sjb "compatible", compat, i); 1240178479Sjb kmem_free(buf, COMPAT_BUFSIZE); 1241178479Sjb} 1242178479Sjb 1243178479Sjb/* 1244178479Sjb * Adjust the reg properties for a dual channel PCI-IDE device. 1245178479Sjb * 1246178479Sjb * NOTE: don't do anything that changes the order of the hard-decodes 1247178479Sjb * and programmed BARs. The kernel driver depends on these values 1248178479Sjb * being in this order regardless of whether they're for a 'native' 1249178479Sjb * mode BAR or not. 1250178479Sjb */ 1251178479Sjb/* 1252178479Sjb * config info for pci-ide devices 1253178479Sjb */ 1254178479Sjbstatic struct { 1255178479Sjb uchar_t native_mask; /* 0 == 'compatibility' mode, 1 == native */ 1256178479Sjb uchar_t bar_offset; /* offset for alt status register */ 1257178479Sjb ushort_t addr; /* compatibility mode base address */ 1258178479Sjb ushort_t length; /* number of ports for this BAR */ 1259178479Sjb} pciide_bar[] = { 1260178479Sjb { 0x01, 0, 0x1f0, 8 }, /* primary lower BAR */ 1261178479Sjb { 0x01, 2, 0x3f6, 1 }, /* primary upper BAR */ 1262178479Sjb { 0x04, 0, 0x170, 8 }, /* secondary lower BAR */ 1263178479Sjb { 0x04, 2, 0x376, 1 } /* secondary upper BAR */ 1264178479Sjb}; 1265178479Sjb 1266178479Sjbstatic int 1267178479SjbpciIdeAdjustBAR(uchar_t progcl, int index, uint_t *basep, uint_t *lenp) 1268178479Sjb{ 1269178479Sjb int hard_decode = 0; 1270178479Sjb 1271178479Sjb /* 1272178479Sjb * Adjust the base and len for the BARs of the PCI-IDE 1273178479Sjb * device's primary and secondary controllers. The first 1274178479Sjb * two BARs are for the primary controller and the next 1275178479Sjb * two BARs are for the secondary controller. The fifth 1276178479Sjb * and sixth bars are never adjusted. 1277178479Sjb */ 1278178479Sjb if (index >= 0 && index <= 3) { 1279178479Sjb *lenp = pciide_bar[index].length; 1280178479Sjb 1281178479Sjb if (progcl & pciide_bar[index].native_mask) { 1282178479Sjb *basep += pciide_bar[index].bar_offset; 1283178479Sjb } else { 1284178479Sjb *basep = pciide_bar[index].addr; 1285178479Sjb hard_decode = 1; 1286178479Sjb } 1287178479Sjb } 1288178479Sjb 1289178479Sjb /* 1290178479Sjb * if either base or len is zero make certain both are zero 1291178479Sjb */ 1292178479Sjb if (*basep == 0 || *lenp == 0) { 1293178479Sjb *basep = 0; 1294178479Sjb *lenp = 0; 1295178479Sjb hard_decode = 0; 1296178479Sjb } 1297178479Sjb 1298178479Sjb return (hard_decode); 1299178479Sjb} 1300178479Sjb 1301178479Sjb 1302178479Sjb/* 1303178479Sjb * Add the "reg" and "assigned-addresses" property 1304178479Sjb */ 1305178479Sjbstatic int 1306178479Sjbadd_reg_props(dev_info_t *dip, uchar_t bus, uchar_t dev, uchar_t func, 1307178479Sjb int config_op, int pciide) 1308178479Sjb{ 1309178479Sjb uchar_t baseclass, subclass, progclass, header; 1310178479Sjb ushort_t bar_sz; 1311178479Sjb uint_t value = 0, len, devloc; 1312178479Sjb uint_t base, base_hi, type; 1313178479Sjb ushort_t offset, end; 1314178479Sjb int max_basereg, j, reprogram = 0; 1315178479Sjb uint_t phys_hi; 1316178479Sjb struct memlist **io_res, **mres, **mem_res, **pmem_res; 1317178479Sjb uint16_t cmd_reg; 1318178479Sjb 1319178479Sjb pci_regspec_t regs[16] = {{0}}; 1320178479Sjb pci_regspec_t assigned[15] = {{0}}; 1321178479Sjb int nreg, nasgn, enable = 0; 1322178479Sjb 1323178479Sjb io_res = &pci_bus_res[bus].io_ports; 1324178479Sjb mem_res = &pci_bus_res[bus].mem_space; 1325178479Sjb if (bus == 0) /* for bus 0, there is only mem_space */ 1326178479Sjb pmem_res = mem_res; 1327178479Sjb else 1328178479Sjb pmem_res = &pci_bus_res[bus].pmem_space; 1329178479Sjb 1330178479Sjb devloc = (uint_t)bus << 16 | (uint_t)dev << 11 | (uint_t)func << 8; 1331178479Sjb regs[0].pci_phys_hi = devloc; 1332178479Sjb nreg = 1; /* rest of regs[0] is all zero */ 1333178479Sjb nasgn = 0; 1334178479Sjb 1335178479Sjb baseclass = pci_getb(bus, dev, func, PCI_CONF_BASCLASS); 1336178479Sjb subclass = pci_getb(bus, dev, func, PCI_CONF_SUBCLASS); 1337178479Sjb progclass = pci_getb(bus, dev, func, PCI_CONF_PROGCLASS); 1338178479Sjb header = pci_getb(bus, dev, func, PCI_CONF_HEADER) & PCI_HEADER_TYPE_M; 1339178479Sjb 1340178479Sjb switch (header) { 1341178479Sjb case PCI_HEADER_ZERO: 1342178479Sjb max_basereg = PCI_BASE_NUM; 1343178479Sjb break; 1344178479Sjb case PCI_HEADER_PPB: 1345178479Sjb max_basereg = PCI_BCNF_BASE_NUM; 1346178479Sjb break; 1347178479Sjb case PCI_HEADER_CARDBUS: 1348178479Sjb max_basereg = PCI_CBUS_BASE_NUM; 1349178479Sjb break; 1350178479Sjb default: 1351178479Sjb max_basereg = 0; 1352178479Sjb break; 1353178479Sjb } 1354178479Sjb 1355178479Sjb /* 1356178479Sjb * Create the register property by saving the current 1357178479Sjb * value of the base register. Write 0xffffffff to the 1358178479Sjb * base register. Read the value back to determine the 1359178479Sjb * required size of the address space. Restore the base 1360178479Sjb * register contents. 1361178479Sjb * 1362178479Sjb * Do not disable I/O and memory access; this isn't necessary 1363178479Sjb * since no driver is yet attached to this device, and disabling 1364178479Sjb * I/O and memory access has the side-effect of disabling PCI-PCI 1365178479Sjb * bridge mappings, which makes the bridge transparent to secondary- 1366178479Sjb * bus activity (see sections 4.1-4.3 of the PCI-PCI Bridge 1367178479Sjb * Spec V1.2). 1368178479Sjb */ 1369178479Sjb end = PCI_CONF_BASE0 + max_basereg * sizeof (uint_t); 1370178479Sjb for (j = 0, offset = PCI_CONF_BASE0; offset < end; 1371178479Sjb j++, offset += bar_sz) { 1372178479Sjb int hard_decode = 0; 1373178479Sjb 1374178479Sjb /* determine the size of the address space */ 1375178479Sjb base = pci_getl(bus, dev, func, offset); 1376178479Sjb pci_putl(bus, dev, func, offset, 0xffffffff); 1377178479Sjb value = pci_getl(bus, dev, func, offset); 1378178479Sjb pci_putl(bus, dev, func, offset, base); 1379178479Sjb 1380178479Sjb /* construct phys hi,med.lo, size hi, lo */ 1381178479Sjb if ((pciide && j < 4) || (base & PCI_BASE_SPACE_IO)) { 1382178479Sjb /* i/o space */ 1383178479Sjb bar_sz = PCI_BAR_SZ_32; 1384178479Sjb value &= PCI_BASE_IO_ADDR_M; 1385178479Sjb len = ((value ^ (value-1)) + 1) >> 1; 1386178479Sjb 1387178479Sjb /* XXX Adjust first 4 IDE registers */ 1388178479Sjb if (pciide) { 1389178479Sjb if (subclass != PCI_MASS_IDE) 1390178479Sjb progclass = (PCI_IDE_IF_NATIVE_PRI | 1391178479Sjb PCI_IDE_IF_NATIVE_SEC); 1392178479Sjb hard_decode = pciIdeAdjustBAR(progclass, j, 1393178479Sjb &base, &len); 1394178479Sjb } else if (value == 0) { 1395178479Sjb /* skip base regs with size of 0 */ 1396178479Sjb continue; 1397178479Sjb } 1398178479Sjb 1399178479Sjb regs[nreg].pci_size_low = 1400178479Sjb assigned[nasgn].pci_size_low = len; 1401178479Sjb if (!hard_decode) { 1402178479Sjb regs[nreg].pci_phys_hi = 1403178479Sjb (PCI_ADDR_IO | devloc) + offset; 1404178479Sjb } else { 1405178479Sjb regs[nreg].pci_phys_hi = 1406178479Sjb (PCI_RELOCAT_B | PCI_ADDR_IO | devloc) + 1407178479Sjb offset; 1408178479Sjb regs[nreg].pci_phys_low = 1409178479Sjb base & PCI_BASE_IO_ADDR_M; 1410178479Sjb } 1411178479Sjb assigned[nasgn].pci_phys_hi = 1412178479Sjb (PCI_RELOCAT_B | PCI_ADDR_IO | devloc) + offset; 1413178479Sjb type = base & (~PCI_BASE_IO_ADDR_M); 1414178479Sjb base &= PCI_BASE_IO_ADDR_M; 1415178479Sjb 1416178479Sjb /* 1417178479Sjb * first pass - gather what's there 1418178479Sjb * update/second pass - adjust/allocate regions 1419178479Sjb * config - allocate regions 1420178479Sjb */ 1421178479Sjb if (config_op == CONFIG_INFO) { /* first pass */ 1422178479Sjb /* take out of the resource map of the bus */ 1423178479Sjb if (*io_res && base != 0) 1424178479Sjb (void) memlist_remove(io_res, 1425178479Sjb (uint64_t)base, (uint64_t)len); 1426178479Sjb else if (*io_res) 1427178479Sjb reprogram = 1; 1428178479Sjb } else if (*io_res && base == 0) { 1429178479Sjb base = (uint_t)memlist_find(io_res, 1430178479Sjb (uint64_t)len, (uint64_t)0x4); 1431178479Sjb if (base != 0) { 1432178479Sjb /* XXX need to worry about 64-bit? */ 1433178479Sjb pci_putl(bus, dev, func, offset, 1434178479Sjb base | type); 1435178479Sjb base = pci_getl(bus, dev, func, offset); 1436178479Sjb base &= PCI_BASE_IO_ADDR_M; 1437178479Sjb } 1438178479Sjb if (base == 0) { 1439178479Sjb cmn_err(CE_WARN, "failed to program" 1440178479Sjb " IO space [%d/%d/%d] BAR@0x%x" 1441178479Sjb " length 0x%x", 1442178479Sjb bus, dev, func, offset, len); 1443178479Sjb } else 1444178479Sjb enable |= PCI_COMM_IO; 1445178479Sjb } 1446178479Sjb assigned[nasgn].pci_phys_low = base; 1447178479Sjb nreg++, nasgn++; 1448178479Sjb 1449178479Sjb } else { 1450178479Sjb /* memory space */ 1451178479Sjb if ((base & PCI_BASE_TYPE_M) == PCI_BASE_TYPE_ALL) { 1452178479Sjb bar_sz = PCI_BAR_SZ_64; 1453178479Sjb base_hi = pci_getl(bus, dev, func, offset + 4); 1454178479Sjb phys_hi = PCI_ADDR_MEM64; 1455178479Sjb } else { 1456178479Sjb bar_sz = PCI_BAR_SZ_32; 1457178479Sjb base_hi = 0; 1458178479Sjb phys_hi = PCI_ADDR_MEM32; 1459178479Sjb } 1460178479Sjb 1461178479Sjb /* skip base regs with size of 0 */ 1462178479Sjb value &= PCI_BASE_M_ADDR_M; 1463178479Sjb 1464178479Sjb if (value == 0) { 1465178479Sjb continue; 1466178479Sjb } 1467178479Sjb len = ((value ^ (value-1)) + 1) >> 1; 1468178479Sjb regs[nreg].pci_size_low = 1469178479Sjb assigned[nasgn].pci_size_low = len; 1470178479Sjb 1471178479Sjb phys_hi |= (devloc | offset); 1472178479Sjb if (base & PCI_BASE_PREF_M) { 1473178479Sjb mres = pmem_res; 1474178479Sjb phys_hi |= PCI_PREFETCH_B; 1475178479Sjb } else { 1476178479Sjb mres = mem_res; 1477178479Sjb } 1478178479Sjb regs[nreg].pci_phys_hi = 1479178479Sjb assigned[nasgn].pci_phys_hi = phys_hi; 1480178479Sjb assigned[nasgn].pci_phys_hi |= PCI_RELOCAT_B; 1481178479Sjb assigned[nasgn].pci_phys_mid = base_hi; 1482178479Sjb type = base & ~PCI_BASE_M_ADDR_M; 1483178479Sjb base &= PCI_BASE_M_ADDR_M; 1484178479Sjb 1485178479Sjb if (config_op == CONFIG_INFO) { 1486178479Sjb /* take out of the resource map of the bus */ 1487178479Sjb if (*mres && base != 0) { 1488178479Sjb (void) memlist_remove(mres, 1489178479Sjb (uint64_t)base, (uint64_t)len); 1490178479Sjb } else if (*mres) 1491178479Sjb reprogram = 1; 1492178479Sjb } else if (*mres && base == 0) { 1493178479Sjb base = (uint_t)memlist_find(mres, 1494178479Sjb (uint64_t)len, (uint64_t)0x1000); 1495178479Sjb if (base != NULL) { 1496178479Sjb pci_putl(bus, dev, func, offset, 1497178479Sjb base | type); 1498178479Sjb base = pci_getl(bus, dev, func, offset); 1499178479Sjb base &= PCI_BASE_M_ADDR_M; 1500178479Sjb } 1501178479Sjb 1502178479Sjb if (base == 0) { 1503178479Sjb cmn_err(CE_WARN, "failed to program " 1504178479Sjb "mem space [%d/%d/%d] BAR@0x%x" 1505178479Sjb " length 0x%x", 1506178479Sjb bus, dev, func, offset, len); 1507178479Sjb } else 1508178479Sjb enable |= PCI_COMM_MAE; 1509178479Sjb } 1510178479Sjb assigned[nasgn].pci_phys_low = base; 1511178479Sjb nreg++, nasgn++; 1512178479Sjb } 1513178479Sjb } 1514178479Sjb switch (header) { 1515178479Sjb case PCI_HEADER_ZERO: 1516178479Sjb offset = PCI_CONF_ROM; 1517178479Sjb break; 1518178479Sjb case PCI_HEADER_PPB: 1519178479Sjb offset = PCI_BCNF_ROM; 1520178479Sjb break; 1521178479Sjb default: /* including PCI_HEADER_CARDBUS */ 1522178479Sjb goto done; 1523178479Sjb } 1524211554Srpaulo 1525178479Sjb /* 1526178479Sjb * Add the expansion rom memory space 1527178479Sjb * Determine the size of the ROM base reg; don't write reserved bits 1528178479Sjb * ROM isn't in the PCI memory space. 1529178479Sjb */ 1530178479Sjb base = pci_getl(bus, dev, func, offset); 1531211554Srpaulo pci_putl(bus, dev, func, offset, PCI_BASE_ROM_ADDR_M); 1532211554Srpaulo value = pci_getl(bus, dev, func, offset); 1533211554Srpaulo pci_putl(bus, dev, func, offset, base); 1534211554Srpaulo if (value & PCI_BASE_ROM_ENABLE) 1535211554Srpaulo value &= PCI_BASE_ROM_ADDR_M; 1536211554Srpaulo else 1537211554Srpaulo value = 0; 1538211554Srpaulo 1539211554Srpaulo if (value != 0) { 1540211554Srpaulo regs[nreg].pci_phys_hi = (PCI_ADDR_MEM32 | devloc) + offset; 1541211554Srpaulo assigned[nasgn].pci_phys_hi = (PCI_RELOCAT_B | 1542211554Srpaulo PCI_ADDR_MEM32 | devloc) + offset; 1543211554Srpaulo base &= PCI_BASE_ROM_ADDR_M; 1544211554Srpaulo assigned[nasgn].pci_phys_low = base; 1545211554Srpaulo len = ((value ^ (value-1)) + 1) >> 1; 1546211554Srpaulo regs[nreg].pci_size_low = assigned[nasgn].pci_size_low = len; 1547178479Sjb nreg++, nasgn++; 1548178479Sjb /* take it out of the memory resource */ 1549178479Sjb if (*mem_res && base != 0) 1550178479Sjb (void) memlist_remove(mem_res, 1551178479Sjb (uint64_t)base, (uint64_t)len); 1552178479Sjb } 1553178479Sjb 1554178479Sjb /* 1555178479Sjb * The following are ISA resources. There are not part 1556178479Sjb * of the PCI local bus resources. So don't attempt to 1557178479Sjb * do resource accounting against PCI. 1558211554Srpaulo */ 1559211554Srpaulo 1560211554Srpaulo /* add the three hard-decode, aliased address spaces for VGA */ 1561178479Sjb if ((baseclass == PCI_CLASS_DISPLAY && subclass == PCI_DISPLAY_VGA) || 1562178479Sjb (baseclass == PCI_CLASS_NONE && subclass == PCI_NONE_VGA)) { 1563178479Sjb 1564178479Sjb /* VGA hard decode 0x3b0-0x3bb */ 1565178479Sjb regs[nreg].pci_phys_hi = assigned[nasgn].pci_phys_hi = 1566178479Sjb (PCI_RELOCAT_B | PCI_ALIAS_B | PCI_ADDR_IO | devloc); 1567178479Sjb regs[nreg].pci_phys_low = assigned[nasgn].pci_phys_low = 0x3b0; 1568178479Sjb regs[nreg].pci_size_low = assigned[nasgn].pci_size_low = 0xc; 1569178479Sjb nreg++, nasgn++; 1570178479Sjb 1571178479Sjb /* VGA hard decode 0x3c0-0x3df */ 1572178479Sjb regs[nreg].pci_phys_hi = assigned[nasgn].pci_phys_hi = 1573178479Sjb (PCI_RELOCAT_B | PCI_ALIAS_B | PCI_ADDR_IO | devloc); 1574211554Srpaulo regs[nreg].pci_phys_low = assigned[nasgn].pci_phys_low = 0x3c0; 1575211554Srpaulo regs[nreg].pci_size_low = assigned[nasgn].pci_size_low = 0x20; 1576211554Srpaulo nreg++, nasgn++; 1577178479Sjb 1578178479Sjb /* Video memory */ 1579178479Sjb regs[nreg].pci_phys_hi = assigned[nasgn].pci_phys_hi = 1580178479Sjb (PCI_RELOCAT_B | PCI_ADDR_MEM32 | devloc); 1581178479Sjb regs[nreg].pci_phys_low = 1582178479Sjb assigned[nasgn].pci_phys_low = 0xa0000; 1583178479Sjb regs[nreg].pci_size_low = 1584178479Sjb assigned[nasgn].pci_size_low = 0x20000; 1585178479Sjb nreg++, nasgn++; 1586178479Sjb } 1587178479Sjb 1588178479Sjb /* add the hard-decode, aliased address spaces for 8514 */ 1589178479Sjb if ((baseclass == PCI_CLASS_DISPLAY) && 1590178479Sjb (subclass == PCI_DISPLAY_VGA) && 1591178479Sjb (progclass & PCI_DISPLAY_IF_8514)) { 1592178479Sjb 1593178479Sjb /* hard decode 0x2e8 */ 1594178479Sjb regs[nreg].pci_phys_hi = assigned[nasgn].pci_phys_hi = 1595178573Sjb (PCI_RELOCAT_B | PCI_ALIAS_B | PCI_ADDR_IO | devloc); 1596178573Sjb regs[nreg].pci_phys_low = assigned[nasgn].pci_phys_low = 0x2e8; 1597211554Srpaulo regs[nreg].pci_size_low = assigned[nasgn].pci_size_low = 0x1; 1598211554Srpaulo nreg++, nasgn++; 1599211554Srpaulo 1600211554Srpaulo /* hard decode 0x2ea-0x2ef */ 1601211554Srpaulo regs[nreg].pci_phys_hi = assigned[nasgn].pci_phys_hi = 1602211554Srpaulo (PCI_RELOCAT_B | PCI_ALIAS_B | PCI_ADDR_IO | devloc); 1603211554Srpaulo regs[nreg].pci_phys_low = assigned[nasgn].pci_phys_low = 0x2ea; 1604211554Srpaulo regs[nreg].pci_size_low = assigned[nasgn].pci_size_low = 0x6; 1605211554Srpaulo nreg++, nasgn++; 1606211554Srpaulo } 1607211554Srpaulo 1608211554Srpaulodone: 1609211554Srpaulo (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "reg", 1610178573Sjb (int *)regs, nreg * sizeof (pci_regspec_t) / sizeof (int)); 1611178479Sjb (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 1612178479Sjb "assigned-addresses", 1613178479Sjb (int *)assigned, nasgn * sizeof (pci_regspec_t) / sizeof (int)); 1614178479Sjb if (config_op == CONFIG_NEW && enable) { 1615178479Sjb cmn_err(CE_NOTE, 1616178479Sjb "!enable PCI device [%d/%d/%d]", bus, dev, func); 1617178479Sjb cmd_reg = pci_getw(bus, dev, func, PCI_CONF_COMM); 1618178573Sjb cmd_reg |= (enable | PCI_COMM_ME); 1619178573Sjb pci_putw(bus, dev, func, PCI_CONF_COMM, cmd_reg); 1620178573Sjb } 1621178573Sjb return (reprogram); 1622178573Sjb} 1623178479Sjb 1624178479Sjbstatic void 1625178479Sjbadd_ppb_props(dev_info_t *dip, uchar_t bus, uchar_t dev, uchar_t func, 1626178479Sjb int pciex) 1627178479Sjb{ 1628178479Sjb char *dev_type; 1629178479Sjb int i; 1630178479Sjb uint_t val, io_range[2], mem_range[2], pmem_range[2]; 1631178479Sjb uchar_t secbus = pci_getb(bus, dev, func, PCI_BCNF_SECBUS); 1632178479Sjb uchar_t subbus = pci_getb(bus, dev, func, PCI_BCNF_SUBBUS); 1633178479Sjb ASSERT(secbus <= subbus); 1634178479Sjb 1635178479Sjb /* 1636178479Sjb * Some BIOSes lie about max pci busses, we allow for 1637178479Sjb * such mistakes here 1638178479Sjb */ 1639178479Sjb if (subbus > pci_bios_nbus) { 1640178479Sjb pci_bios_nbus = subbus; 1641178479Sjb alloc_res_array(); 1642178479Sjb } 1643178479Sjb 1644178479Sjb ASSERT(pci_bus_res[secbus].dip == NULL); 1645178479Sjb pci_bus_res[secbus].dip = dip; 1646178479Sjb pci_bus_res[secbus].par_bus = bus; 1647178479Sjb 1648178479Sjb dev_type = pciex ? "pciex" : "pci"; 1649178479Sjb 1650178479Sjb /* setup bus number hierarchy */ 1651178479Sjb pci_bus_res[secbus].sub_bus = subbus; 1652178479Sjb /* 1653178479Sjb * Keep track of the largest subordinate bus number (this is essential 1654178479Sjb * for peer busses because there is no other way of determining its 1655178479Sjb * subordinate bus number). 1656178479Sjb */ 1657178479Sjb if (subbus > pci_bus_res[bus].sub_bus) 1658178479Sjb pci_bus_res[bus].sub_bus = subbus; 1659178479Sjb /* 1660178479Sjb * Loop through subordinate busses, initializing their parent bus 1661178479Sjb * field to this bridge's parent. The subordinate busses' parent 1662178479Sjb * fields may very well be further refined later, as child bridges 1663178479Sjb * are enumerated. (The value is to note that the subordinate busses 1664178479Sjb * are not peer busses by changing their par_bus fields to anything 1665178479Sjb * other than -1.) 1666178479Sjb */ 1667178479Sjb for (i = secbus + 1; i <= subbus; i++) 1668178479Sjb pci_bus_res[i].par_bus = bus; 1669178479Sjb 1670178479Sjb (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 1671178479Sjb "device_type", dev_type); 1672178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1673178479Sjb "#address-cells", 3); 1674178479Sjb (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 1675178479Sjb "#size-cells", 2); 1676178479Sjb 1677178479Sjb /* 1678178479Sjb * According to PPB spec, the base register should be programmed 1679178479Sjb * with a value bigger than the limit register when there are 1680178479Sjb * no resources available. This applies to io, memory, and 1681178479Sjb * prefetchable memory. 1682178479Sjb */ 1683178479Sjb 1684178573Sjb /* 1685178479Sjb * io range 1686178479Sjb * We determine i/o windows that are left unconfigured by bios 1687178479Sjb * through its i/o enable bit as Microsoft recommends OEMs to do. 1688178479Sjb * If it is unset, we disable i/o and mark it for reconfiguration in 1689178479Sjb * later passes by setting the base > limit 1690178479Sjb */ 1691178479Sjb val = (uint_t)pci_getw(bus, dev, func, PCI_CONF_COMM); 1692178479Sjb if (val & PCI_COMM_IO) { 1693178479Sjb val = (uint_t)pci_getb(bus, dev, func, PCI_BCNF_IO_BASE_LOW); 1694178573Sjb io_range[0] = ((val & 0xf0) << 8); 1695178573Sjb val = (uint_t)pci_getb(bus, dev, func, PCI_BCNF_IO_LIMIT_LOW); 1696178573Sjb io_range[1] = ((val & 0xf0) << 8) | 0xFFF; 1697178573Sjb } else { 1698178573Sjb io_range[0] = 0x9fff; 1699178479Sjb io_range[1] = 0x1000; 1700178479Sjb pci_putb(bus, dev, func, PCI_BCNF_IO_BASE_LOW, 1701178479Sjb (uint8_t)((io_range[0] >> 8) & 0xf0)); 1702178479Sjb pci_putb(bus, dev, func, PCI_BCNF_IO_LIMIT_LOW, 1703178479Sjb (uint8_t)((io_range[1] >> 8) & 0xf0)); 1704178479Sjb pci_putw(bus, dev, func, PCI_BCNF_IO_BASE_HI, 0); 1705178479Sjb pci_putw(bus, dev, func, PCI_BCNF_IO_LIMIT_HI, 0); 1706178479Sjb } 1707178479Sjb 1708178479Sjb if (io_range[0] != 0 && io_range[0] < io_range[1]) { 1709178479Sjb memlist_insert(&pci_bus_res[secbus].io_ports, 1710178479Sjb (uint64_t)io_range[0], 1711178479Sjb (uint64_t)(io_range[1] - io_range[0] + 1)); 1712178479Sjb if (pci_bus_res[bus].io_ports != NULL) { 1713178479Sjb (void) memlist_remove(&pci_bus_res[bus].io_ports, 1714178479Sjb (uint64_t)io_range[0], 1715178479Sjb (uint64_t)(io_range[1] - io_range[0] + 1)); 1716178479Sjb } 1717178479Sjb dcmn_err(CE_NOTE, "bus %d io-range: 0x%x-%x", 1718178479Sjb secbus, io_range[0], io_range[1]); 1719178479Sjb /* if 32-bit supported, make sure upper bits are not set */ 1720178479Sjb if ((val & 0xf) == 1 && 1721178479Sjb pci_getw(bus, dev, func, PCI_BCNF_IO_BASE_HI)) { 1722178479Sjb cmn_err(CE_NOTE, "unsupported 32-bit IO address on" 1723178479Sjb " pci-pci bridge [%d/%d/%d]", bus, dev, func); 1724178479Sjb } 1725178479Sjb } 1726178479Sjb 1727178479Sjb /* mem range */ 1728178573Sjb val = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_MEM_BASE); 1729178479Sjb mem_range[0] = ((val & 0xFFF0) << 16); 1730178479Sjb val = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_MEM_LIMIT); 1731178573Sjb mem_range[1] = ((val & 0xFFF0) << 16) | 0xFFFFF; 1732178479Sjb if (mem_range[0] != 0 && mem_range[0] < mem_range[1]) { 1733211554Srpaulo memlist_insert(&pci_bus_res[secbus].mem_space, 1734178479Sjb (uint64_t)mem_range[0], 1735178479Sjb (uint64_t)(mem_range[1] - mem_range[0] + 1)); 1736178479Sjb /* remove from parent resouce list */ 1737178479Sjb if (pci_bus_res[bus].mem_space != NULL) { 1738178479Sjb (void) memlist_remove(&pci_bus_res[bus].mem_space, 1739178479Sjb (uint64_t)mem_range[0], 1740211554Srpaulo (uint64_t)(mem_range[1] - mem_range[0] + 1)); 1741211554Srpaulo } 1742211554Srpaulo dcmn_err(CE_NOTE, "bus %d mem-range: 0x%x-%x", 1743211554Srpaulo secbus, mem_range[0], mem_range[1]); 1744178479Sjb } 1745178479Sjb 1746178479Sjb /* prefetchable memory range */ 1747178479Sjb val = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_PF_BASE_LOW); 1748178479Sjb pmem_range[0] = ((val & 0xFFF0) << 16); 1749178573Sjb val = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_PF_LIMIT_LOW); 1750178479Sjb pmem_range[1] = ((val & 0xFFF0) << 16) | 0xFFFFF; 1751178479Sjb if (pmem_range[0] != 0 && pmem_range[0] < pmem_range[1]) { 1752178479Sjb memlist_insert(&pci_bus_res[secbus].pmem_space, 1753178479Sjb (uint64_t)pmem_range[0], 1754178479Sjb (uint64_t)(pmem_range[1] - pmem_range[0] + 1)); 1755178479Sjb if (pci_bus_res[bus].pmem_space != NULL) { 1756178479Sjb (void) memlist_remove(&pci_bus_res[bus].pmem_space, 1757178479Sjb (uint64_t)pmem_range[0], 1758178479Sjb (uint64_t)(pmem_range[1] - pmem_range[0] + 1)); 1759178479Sjb } 1760178479Sjb dcmn_err(CE_NOTE, "bus %d pmem-range: 0x%x-%x", 1761178479Sjb secbus, pmem_range[0], pmem_range[1]); 1762178479Sjb /* if 64-bit supported, make sure upper bits are not set */ 1763178479Sjb if ((val & 0xf) == 1 && 1764178479Sjb pci_getl(bus, dev, func, PCI_BCNF_PF_BASE_HIGH)) { 1765178479Sjb cmn_err(CE_NOTE, "unsupported 64-bit prefetch memory on" 1766178573Sjb " pci-pci bridge [%d/%d/%d]", bus, dev, func); 1767211554Srpaulo } 1768178479Sjb } 1769178573Sjb 1770178573Sjb add_bus_range_prop(secbus); 1771178573Sjb add_ppb_ranges_prop(secbus); 1772178573Sjb} 1773178573Sjb 1774178573Sjbextern const struct pci_class_strings_s class_pci[]; 1775178573Sjbextern int class_pci_items; 1776178573Sjb 1777178573Sjbstatic void 1778178573Sjbadd_model_prop(dev_info_t *dip, uint_t classcode) 1779178573Sjb{ 1780178573Sjb const char *desc; 1781178573Sjb int i; 1782178573Sjb uchar_t baseclass = classcode >> 16; 1783178573Sjb uchar_t subclass = (classcode >> 8) & 0xff; 1784187347Sjhb uchar_t progclass = classcode & 0xff; 1785178573Sjb 1786178573Sjb if ((baseclass == PCI_CLASS_MASS) && (subclass == PCI_MASS_IDE)) { 1787178573Sjb desc = "IDE controller"; 1788178573Sjb } else { 1789211554Srpaulo for (desc = 0, i = 0; i < class_pci_items; i++) { 1790211554Srpaulo if ((baseclass == class_pci[i].base_class) && 1791211554Srpaulo (subclass == class_pci[i].sub_class) && 1792178573Sjb (progclass == class_pci[i].prog_class)) { 1793178573Sjb desc = class_pci[i].actual_desc; 1794211554Srpaulo break; 1795211554Srpaulo } 1796178573Sjb } 1797178479Sjb if (i == class_pci_items) 1798178479Sjb desc = "Unknown class of pci/pnpbios device"; 1799178479Sjb } 1800178479Sjb 1801178479Sjb (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "model", 1802178479Sjb (char *)desc); 1803178479Sjb} 1804178479Sjb 1805178479Sjbstatic void 1806178479Sjbadd_bus_range_prop(int bus) 1807178479Sjb{ 1808178479Sjb int bus_range[2]; 1809178479Sjb 1810178479Sjb if (pci_bus_res[bus].dip == NULL) 1811178479Sjb return; 1812178479Sjb bus_range[0] = bus; 1813178479Sjb bus_range[1] = pci_bus_res[bus].sub_bus; 1814178479Sjb (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, pci_bus_res[bus].dip, 1815178479Sjb "bus-range", (int *)bus_range, 2); 1816178479Sjb} 1817211554Srpaulo 1818211554Srpaulo/* 1819211554Srpaulo * Add slot-names property for any named pci hot-plug slots 1820211554Srpaulo */ 1821211554Srpaulostatic void 1822211554Srpauloadd_bus_slot_names_prop(int bus) 1823211554Srpaulo{ 1824211554Srpaulo char slotprop[256]; 1825211554Srpaulo int len; 1826211554Srpaulo 1827211554Srpaulo len = pci_slot_names_prop(bus, slotprop, sizeof (slotprop)); 1828211554Srpaulo if (len > 0) { 1829211554Srpaulo /* 1830211554Srpaulo * Only create a peer bus node if this bus may be a peer bus. 1831211554Srpaulo * It may be a peer bus if the dip is NULL and if par_bus is 1832211554Srpaulo * -1 (par_bus is -1 if this bus was not found to be 1833211554Srpaulo * subordinate to any PCI-PCI bridge). 1834211554Srpaulo * If it's not a peer bus, then the ACPI BBN-handling code 1835211554Srpaulo * will remove it later. 1836211554Srpaulo */ 1837211554Srpaulo if (pci_bus_res[bus].par_bus == (uchar_t)-1 && 1838211554Srpaulo pci_bus_res[bus].dip == NULL) { 1839211554Srpaulo 1840211554Srpaulo create_root_bus_dip(bus); 1841211554Srpaulo } 1842211554Srpaulo if (pci_bus_res[bus].dip != NULL) { 1843211554Srpaulo ASSERT((len % sizeof (int)) == 0); 1844211554Srpaulo (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 1845211554Srpaulo pci_bus_res[bus].dip, "slot-names", 1846211554Srpaulo (int *)slotprop, len / sizeof (int)); 1847211554Srpaulo } else { 1848211554Srpaulo cmn_err(CE_NOTE, "!BIOS BUG: Invalid bus number in PCI " 1849211554Srpaulo "IRQ routing table; Not adding slot-names " 1850211554Srpaulo "property for incorrect bus %d", bus); 1851211554Srpaulo } 1852211554Srpaulo } 1853211554Srpaulo} 1854211554Srpaulo 1855211554Srpaulostatic int 1856211554Srpaulomemlist_to_range(ppb_ranges_t *rp, struct memlist *entry, int type) 1857211554Srpaulo{ 1858211554Srpaulo if (entry == NULL) 1859211554Srpaulo return (0); 1860211554Srpaulo 1861211554Srpaulo /* assume 32-bit addresses */ 1862211554Srpaulo rp->child_high = rp->parent_high = type; 1863211554Srpaulo rp->child_mid = rp->parent_mid = 0; 1864211554Srpaulo rp->child_low = rp->parent_low = (uint32_t)entry->address; 1865211554Srpaulo rp->size_high = 0; 1866211554Srpaulo rp->size_low = (uint32_t)entry->size; 1867211554Srpaulo return (1); 1868211554Srpaulo} 1869211554Srpaulo 1870211554Srpaulostatic void 1871211554Srpauloadd_ppb_ranges_prop(int bus) 1872211554Srpaulo{ 1873211554Srpaulo int i = 0; 1874211554Srpaulo ppb_ranges_t *rp; 1875211554Srpaulo 1876211554Srpaulo rp = kmem_alloc(3 * sizeof (*rp), KM_SLEEP); 1877211554Srpaulo 1878211554Srpaulo i = memlist_to_range(&rp[0], pci_bus_res[bus].io_ports, 1879211554Srpaulo PCI_ADDR_IO | PCI_REG_REL_M); 1880211554Srpaulo i += memlist_to_range(&rp[i], pci_bus_res[bus].mem_space, 1881211554Srpaulo PCI_ADDR_MEM32 | PCI_REG_REL_M); 1882211554Srpaulo i += memlist_to_range(&rp[i], pci_bus_res[bus].pmem_space, 1883211554Srpaulo PCI_ADDR_MEM32 | PCI_REG_REL_M | PCI_REG_PF_M); 1884211554Srpaulo 1885211554Srpaulo if (i != 0) 1886211554Srpaulo (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 1887211554Srpaulo pci_bus_res[bus].dip, "ranges", (int *)rp, 1888211554Srpaulo i * sizeof (ppb_ranges_t) / sizeof (int)); 1889211554Srpaulo kmem_free(rp, 3 * sizeof (*rp)); 1890211554Srpaulo} 1891211554Srpaulo 1892211554Srpaulostatic int 1893211554Srpaulomemlist_to_spec(struct pci_phys_spec *sp, struct memlist *list, int type) 1894211554Srpaulo{ 1895211554Srpaulo int i = 0; 1896211554Srpaulo 1897211554Srpaulo while (list) { 1898211554Srpaulo /* assume 32-bit addresses */ 1899211554Srpaulo sp->pci_phys_hi = type; 1900211554Srpaulo sp->pci_phys_mid = 0; 1901211554Srpaulo sp->pci_phys_low = (uint32_t)list->address; 1902211554Srpaulo sp->pci_size_hi = 0; 1903211554Srpaulo sp->pci_size_low = (uint32_t)list->size; 1904211554Srpaulo 1905211554Srpaulo list = list->next; 1906211554Srpaulo sp++, i++; 1907211554Srpaulo } 1908211554Srpaulo return (i); 1909211554Srpaulo} 1910211554Srpaulo 1911211554Srpaulostatic void 1912211554Srpauloadd_bus_available_prop(int bus) 1913211554Srpaulo{ 1914211554Srpaulo int i, count; 1915211554Srpaulo struct pci_phys_spec *sp; 1916211554Srpaulo 1917211554Srpaulo count = memlist_count(pci_bus_res[bus].io_ports) + 1918211554Srpaulo memlist_count(pci_bus_res[bus].mem_space) + 1919211554Srpaulo memlist_count(pci_bus_res[bus].pmem_space); 1920211554Srpaulo 1921211554Srpaulo if (count == 0) /* nothing available */ 1922211554Srpaulo return; 1923211554Srpaulo 1924211554Srpaulo sp = kmem_alloc(count * sizeof (*sp), KM_SLEEP); 1925211554Srpaulo i = memlist_to_spec(&sp[0], pci_bus_res[bus].io_ports, 1926211554Srpaulo PCI_ADDR_IO | PCI_REG_REL_M); 1927211554Srpaulo i += memlist_to_spec(&sp[i], pci_bus_res[bus].mem_space, 1928211554Srpaulo PCI_ADDR_MEM32 | PCI_REG_REL_M); 1929211554Srpaulo i += memlist_to_spec(&sp[i], pci_bus_res[bus].pmem_space, 1930211554Srpaulo PCI_ADDR_MEM32 | PCI_REG_REL_M | PCI_REG_PF_M); 1931211554Srpaulo ASSERT(i == count); 1932211554Srpaulo 1933211554Srpaulo (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, pci_bus_res[bus].dip, 1934211554Srpaulo "available", (int *)sp, 1935211554Srpaulo i * sizeof (struct pci_phys_spec) / sizeof (int)); 1936211554Srpaulo kmem_free(sp, count * sizeof (*sp)); 1937211554Srpaulo} 1938211554Srpaulo 1939211554Srpaulostatic void 1940211554Srpauloalloc_res_array(void) 1941211554Srpaulo{ 1942211554Srpaulo static int array_max = 0; 1943211554Srpaulo int old_max; 1944211554Srpaulo void *old_res; 1945211554Srpaulo 1946211554Srpaulo if (array_max > pci_bios_nbus + 1) 1947211554Srpaulo return; /* array is big enough */ 1948211554Srpaulo 1949178479Sjb old_max = array_max; 1950178479Sjb old_res = pci_bus_res; 1951178479Sjb 1952178479Sjb if (array_max == 0) 1953178479Sjb array_max = 16; /* start with a reasonable number */ 1954178479Sjb 1955178573Sjb while (array_max < pci_bios_nbus + 1) 1956178573Sjb array_max <<= 1; 1957178573Sjb pci_bus_res = (struct pci_bus_resource *)kmem_zalloc( 1958178573Sjb array_max * sizeof (struct pci_bus_resource), KM_SLEEP); 1959178479Sjb 1960178479Sjb if (old_res) { /* copy content and free old array */ 1961 bcopy(old_res, pci_bus_res, 1962 old_max * sizeof (struct pci_bus_resource)); 1963 kmem_free(old_res, old_max * sizeof (struct pci_bus_resource)); 1964 } 1965} 1966 1967static void 1968create_ioapic_node(int bus, int dev, int fn, ushort_t vendorid, 1969 ushort_t deviceid) 1970{ 1971 static dev_info_t *ioapicsnode = NULL; 1972 static int numioapics = 0; 1973 dev_info_t *ioapic_node; 1974 uint64_t physaddr; 1975 uint32_t lobase, hibase = 0; 1976 1977 /* BAR 0 contains the IOAPIC's memory-mapped I/O address */ 1978 lobase = (*pci_getl_func)(bus, dev, fn, PCI_CONF_BASE0); 1979 1980 /* We (and the rest of the world) only support memory-mapped IOAPICs */ 1981 if ((lobase & PCI_BASE_SPACE_M) != PCI_BASE_SPACE_MEM) 1982 return; 1983 1984 if ((lobase & PCI_BASE_TYPE_M) == PCI_BASE_TYPE_ALL) 1985 hibase = (*pci_getl_func)(bus, dev, fn, PCI_CONF_BASE0 + 4); 1986 1987 lobase &= PCI_BASE_M_ADDR_M; 1988 1989 physaddr = (((uint64_t)hibase) << 32) | lobase; 1990 1991 /* 1992 * Create a nexus node for all IOAPICs under the root node. 1993 */ 1994 if (ioapicsnode == NULL) { 1995 if (ndi_devi_alloc(ddi_root_node(), IOAPICS_NODE_NAME, 1996 (pnode_t)DEVI_SID_NODEID, &ioapicsnode) != NDI_SUCCESS) { 1997 return; 1998 } 1999 (void) ndi_devi_online(ioapicsnode, 0); 2000 } 2001 2002 /* 2003 * Create a child node for this IOAPIC 2004 */ 2005 ioapic_node = ddi_add_child(ioapicsnode, IOAPICS_CHILD_NAME, 2006 DEVI_SID_NODEID, numioapics++); 2007 if (ioapic_node == NULL) { 2008 return; 2009 } 2010 2011 /* Vendor and Device ID */ 2012 (void) ndi_prop_update_int(DDI_DEV_T_NONE, ioapic_node, 2013 IOAPICS_PROP_VENID, vendorid); 2014 (void) ndi_prop_update_int(DDI_DEV_T_NONE, ioapic_node, 2015 IOAPICS_PROP_DEVID, deviceid); 2016 2017 /* device_type */ 2018 (void) ndi_prop_update_string(DDI_DEV_T_NONE, ioapic_node, 2019 "device_type", IOAPICS_DEV_TYPE); 2020 2021 /* reg */ 2022 (void) ndi_prop_update_int64(DDI_DEV_T_NONE, ioapic_node, 2023 "reg", physaddr); 2024} 2025