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.
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.
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]
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2016 Joyent, Inc.
26 #include <sys/types.h>
28 #include <sys/sysmacros.h>
29 #include <sys/sunndi.h>
31 #include <sys/pci_impl.h>
32 #include <sys/pcie_impl.h>
33 #include <sys/memlist.h>
34 #include <sys/bootconf.h>
35 #include <io/pci/mps_table.h>
36 #include <sys/pci_cfgacc.h>
37 #include <sys/pci_cfgspace.h>
38 #include <sys/pci_cfgspace_impl.h>
40 #include "../../../../common/pci/pci_strings.h"
42 #include <io/pciex/pcie_nvidia.h>
43 #include <sys/hotplug/pci/pciehpc_acpi.h>
44 #include <sys/acpi/acpi.h>
45 #include <sys/acpica.h>
46 #include <sys/iommulib.h>
47 #include <sys/devcache.h>
48 #include <sys/pci_cfgacc_x86.h>
50 #define pci_getb (*pci_getb_func)
51 #define pci_getw (*pci_getw_func)
52 #define pci_getl (*pci_getl_func)
53 #define pci_putb (*pci_putb_func)
54 #define pci_putw (*pci_putw_func)
55 #define pci_putl (*pci_putl_func)
56 #define dcmn_err if (pci_boot_debug) cmn_err
59 #define CONFIG_UPDATE 1
62 #define COMPAT_BUFSIZE 512
64 #define PPB_IO_ALIGNMENT 0x1000 /* 4K aligned */
65 #define PPB_MEM_ALIGNMENT 0x100000 /* 1M aligned */
66 /* round down to nearest power of two */
75 /* for is_vga and list_is_vga_only */
82 /* See AMD-8111 Datasheet Rev 3.03, Page 149: */
83 #define LPC_IO_CONTROL_REG_1 0x40
84 #define AMD8111_ENABLENMI (uint8_t)0x80
85 #define DEVID_AMD8111_LPC 0x7468
91 void (*undofn
)(uint8_t, uint8_t, uint8_t);
92 struct pci_fixundo
*next
;
96 struct pci_devfunc
*next
;
100 boolean_t reprogram
; /* this device needs to be reprogrammed */
103 extern int apic_nvidia_io_max
;
104 extern int pseudo_isa
;
105 extern int pci_bios_maxbus
;
106 static uchar_t max_dev_pci
= 32; /* PCI standard */
107 int pci_boot_debug
= 0;
108 extern struct memlist
*find_bus_res(int, int);
109 static struct pci_fixundo
*undolist
= NULL
;
110 static int num_root_bus
= 0; /* count of root buses */
111 extern volatile int acpi_resource_discovery
;
112 extern uint64_t mcfg_mem_base
;
113 extern void pci_cfgacc_add_workaround(uint16_t, uchar_t
, uchar_t
);
114 extern dev_info_t
*pcie_get_rc_dip(dev_info_t
*);
119 static void enumerate_bus_devs(uchar_t bus
, int config_op
);
120 static void create_root_bus_dip(uchar_t bus
);
121 static void process_devfunc(uchar_t
, uchar_t
, uchar_t
, uchar_t
,
123 static void add_compatible(dev_info_t
*, ushort_t
, ushort_t
,
124 ushort_t
, ushort_t
, uchar_t
, uint_t
, int);
125 static int add_reg_props(dev_info_t
*, uchar_t
, uchar_t
, uchar_t
, int, int);
126 static void add_ppb_props(dev_info_t
*, uchar_t
, uchar_t
, uchar_t
, int,
128 static void add_model_prop(dev_info_t
*, uint_t
);
129 static void add_bus_range_prop(int);
130 static void add_bus_slot_names_prop(int);
131 static void add_ranges_prop(int, int);
132 static void add_bus_available_prop(int);
133 static int get_pci_cap(uchar_t bus
, uchar_t dev
, uchar_t func
, uint8_t cap_id
);
134 static void fix_ppb_res(uchar_t
, boolean_t
);
135 static void alloc_res_array();
136 static void create_ioapic_node(int bus
, int dev
, int fn
, ushort_t vendorid
,
138 static void pciex_slot_names_prop(dev_info_t
*, ushort_t
);
139 static void populate_bus_res(uchar_t bus
);
140 static void memlist_remove_list(struct memlist
**list
,
141 struct memlist
*remove_list
);
142 static void ck804_fix_aer_ptr(dev_info_t
*, pcie_req_id_t
);
144 static void pci_scan_bbn(void);
145 static int pci_unitaddr_cache_valid(void);
146 static int pci_bus_unitaddr(int);
147 static void pci_unitaddr_cache_create(void);
149 static int pci_cache_unpack_nvlist(nvf_handle_t
, nvlist_t
*, char *);
150 static int pci_cache_pack_nvlist(nvf_handle_t
, nvlist_t
**);
151 static void pci_cache_free_list(nvf_handle_t
);
153 extern int pci_slot_names_prop(int, char *, int);
155 /* set non-zero to force PCI peer-bus renumbering */
156 int pci_bus_always_renumber
= 0;
159 * used to register ISA resource usage which must not be made
160 * "available" from other PCI node' resource maps
163 struct memlist
*io_used
;
164 struct memlist
*mem_used
;
168 * PCI unit-address cache management
170 static nvf_ops_t pci_unitaddr_cache_ops
= {
171 "/etc/devices/pci_unitaddr_persistent", /* path to cache */
172 pci_cache_unpack_nvlist
, /* read in nvlist form */
173 pci_cache_pack_nvlist
, /* convert to nvlist form */
174 pci_cache_free_list
, /* free data list */
175 NULL
/* write complete callback */
179 list_node_t pua_nodes
;
184 nvf_handle_t puafd_handle
;
185 int pua_cache_valid
= 0;
190 pci_process_acpi_device(ACPI_HANDLE hdl
, UINT32 level
, void *ctx
, void **rv
)
194 ACPI_DEVICE_INFO
*adi
;
198 * Use AcpiGetObjectInfo() to find the device _HID
199 * If not a PCI root-bus, ignore this device and continue
202 if (ACPI_FAILURE(AcpiGetObjectInfo(hdl
, &adi
)))
205 if (!(adi
->Valid
& ACPI_VALID_HID
)) {
210 if (strncmp(adi
->HardwareId
.String
, PCI_ROOT_HID_STRING
,
211 sizeof (PCI_ROOT_HID_STRING
)) &&
212 strncmp(adi
->HardwareId
.String
, PCI_EXPRESS_ROOT_HID_STRING
,
213 sizeof (PCI_EXPRESS_ROOT_HID_STRING
))) {
221 * XXX: ancient Big Bear broken _BBN will result in two
222 * bus 0 _BBNs being found, so we need to handle duplicate
223 * bus 0 gracefully. However, broken _BBN does not
224 * hide a childless root-bridge so no need to work-around it
228 rb
.Length
= sizeof (ro
);
229 if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl
, "_BBN",
230 NULL
, &rb
, ACPI_TYPE_INTEGER
))) {
231 busnum
= ro
.Integer
.Value
;
234 * Ignore invalid _BBN return values here (rather
235 * than panic) and emit a warning; something else
236 * may suffer failure as a result of the broken BIOS.
238 if ((busnum
< 0) || (busnum
> pci_bios_maxbus
)) {
240 "pci_process_acpi_device: invalid _BBN 0x%x\n",
242 return (AE_CTRL_DEPTH
);
245 /* PCI with valid _BBN */
246 if (pci_bus_res
[busnum
].par_bus
== (uchar_t
)-1 &&
247 pci_bus_res
[busnum
].dip
== NULL
)
248 create_root_bus_dip((uchar_t
)busnum
);
249 return (AE_CTRL_DEPTH
);
252 /* PCI and no _BBN, continue walk */
257 * Scan the ACPI namespace for all top-level instances of _BBN
258 * in order to discover childless root-bridges (which enumeration
259 * may not find; root-bridges are inferred by the existence of
260 * children). This scan should find all root-bridges that have
261 * been enumerated, and any childless root-bridges not enumerated.
262 * Root-bridge for bus 0 may not have a _BBN object.
269 (void) AcpiGetDevices(NULL
, pci_process_acpi_device
, NULL
, &rv
);
273 pci_unitaddr_cache_init(void)
276 puafd_handle
= nvf_register_file(&pci_unitaddr_cache_ops
);
277 ASSERT(puafd_handle
);
279 list_create(nvf_list(puafd_handle
), sizeof (pua_node_t
),
280 offsetof(pua_node_t
, pua_nodes
));
282 rw_enter(nvf_lock(puafd_handle
), RW_WRITER
);
283 (void) nvf_read_file(puafd_handle
);
284 rw_exit(nvf_lock(puafd_handle
));
288 * Format of /etc/devices/pci_unitaddr_persistent:
290 * The persistent record of unit-address assignments contains
291 * a list of name/value pairs, where name is a string representation
292 * of the "index value" of the PCI root-bus and the value is
293 * the assigned unit-address.
295 * The "index value" is simply the zero-based index of the PCI
296 * root-buses ordered by physical bus number; first PCI bus is 0,
297 * second is 1, and so on.
302 pci_cache_unpack_nvlist(nvf_handle_t hdl
, nvlist_t
*nvl
, char *name
)
310 while ((np
= nvlist_next_nvpair(nvl
, np
)) != NULL
) {
311 /* name of nvpair is index value */
312 if (ddi_strtol(nvpair_name(np
), NULL
, 10, &index
) != 0)
315 if (nvpair_value_int32(np
, &value
) != 0)
318 node
= kmem_zalloc(sizeof (pua_node_t
), KM_SLEEP
);
319 node
->pua_index
= index
;
320 node
->pua_addr
= value
;
321 list_insert_tail(nvf_list(hdl
), node
);
325 return (DDI_SUCCESS
);
329 pci_cache_pack_nvlist(nvf_handle_t hdl
, nvlist_t
**ret_nvl
)
332 nvlist_t
*nvl
, *sub_nvl
;
337 ASSERT(RW_WRITE_HELD(nvf_lock(hdl
)));
339 rval
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, KM_SLEEP
);
340 if (rval
!= DDI_SUCCESS
) {
341 nvf_error("%s: nvlist alloc error %d\n",
342 nvf_cache_name(hdl
), rval
);
343 return (DDI_FAILURE
);
347 rval
= nvlist_alloc(&sub_nvl
, NV_UNIQUE_NAME
, KM_SLEEP
);
348 if (rval
!= DDI_SUCCESS
)
351 listp
= nvf_list(hdl
);
352 for (pua
= list_head(listp
); pua
!= NULL
;
353 pua
= list_next(listp
, pua
)) {
354 (void) snprintf(buf
, sizeof (buf
), "%d", pua
->pua_index
);
355 rval
= nvlist_add_int32(sub_nvl
, buf
, pua
->pua_addr
);
356 if (rval
!= DDI_SUCCESS
)
360 rval
= nvlist_add_nvlist(nvl
, "table", sub_nvl
);
361 if (rval
!= DDI_SUCCESS
)
363 nvlist_free(sub_nvl
);
366 return (DDI_SUCCESS
);
369 nvlist_free(sub_nvl
);
373 return (DDI_FAILURE
);
377 pci_cache_free_list(nvf_handle_t hdl
)
382 ASSERT(RW_WRITE_HELD(nvf_lock(hdl
)));
384 listp
= nvf_list(hdl
);
385 for (pua
= list_head(listp
); pua
!= NULL
;
386 pua
= list_next(listp
, pua
)) {
387 list_remove(listp
, pua
);
388 kmem_free(pua
, sizeof (pua_node_t
));
394 pci_unitaddr_cache_valid(void)
397 /* read only, no need for rw lock */
398 return (pua_cache_valid
);
403 pci_bus_unitaddr(int index
)
409 rw_enter(nvf_lock(puafd_handle
), RW_READER
);
411 addr
= -1; /* default return if no match */
412 listp
= nvf_list(puafd_handle
);
413 for (pua
= list_head(listp
); pua
!= NULL
;
414 pua
= list_next(listp
, pua
)) {
415 if (pua
->pua_index
== index
) {
416 addr
= pua
->pua_addr
;
421 rw_exit(nvf_lock(puafd_handle
));
426 pci_unitaddr_cache_create(void)
432 rw_enter(nvf_lock(puafd_handle
), RW_WRITER
);
435 listp
= nvf_list(puafd_handle
);
436 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
437 /* skip non-root (peer) PCI busses */
438 if ((pci_bus_res
[i
].par_bus
!= (uchar_t
)-1) ||
439 (pci_bus_res
[i
].dip
== NULL
))
441 node
= kmem_zalloc(sizeof (pua_node_t
), KM_SLEEP
);
442 node
->pua_index
= index
++;
443 node
->pua_addr
= pci_bus_res
[i
].root_addr
;
444 list_insert_tail(listp
, node
);
447 (void) nvf_mark_dirty(puafd_handle
);
448 rw_exit(nvf_lock(puafd_handle
));
454 * Enumerate all PCI devices
459 uint_t i
, root_bus_addr
= 0;
462 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
463 pci_bus_res
[i
].par_bus
= (uchar_t
)-1;
464 pci_bus_res
[i
].root_addr
= (uchar_t
)-1;
465 pci_bus_res
[i
].sub_bus
= i
;
468 pci_bus_res
[0].root_addr
= root_bus_addr
++;
469 create_root_bus_dip(0);
470 enumerate_bus_devs(0, CONFIG_INFO
);
473 * Now enumerate peer busses
475 * We loop till pci_bios_maxbus. On most systems, there is
476 * one more bus at the high end, which implements the ISA
477 * compatibility bus. We don't care about that.
479 * Note: In the old (bootconf) enumeration, the peer bus
480 * address did not use the bus number, and there were
481 * too many peer busses created. The root_bus_addr is
482 * used to maintain the old peer bus address assignment.
483 * However, we stop enumerating phantom peers with no
486 for (i
= 1; i
<= pci_bios_maxbus
; i
++) {
487 if (pci_bus_res
[i
].dip
== NULL
) {
488 pci_bus_res
[i
].root_addr
= root_bus_addr
++;
490 enumerate_bus_devs(i
, CONFIG_INFO
);
492 /* add slot-names property for named pci hot-plug slots */
493 add_bus_slot_names_prop(i
);
498 * >0 = present, 0 = not present, <0 = error
501 pci_bbn_present(int bus
)
506 /* no dip means no _BBN */
507 if (pci_bus_res
[bus
].dip
== NULL
)
510 rv
= -1; /* default return value in case of error below */
511 if (ACPI_SUCCESS(acpica_get_handle(pci_bus_res
[bus
].dip
, &hdl
))) {
512 switch (AcpiEvaluateObject(hdl
, "_BBN", NULL
, NULL
)) {
528 * Return non-zero if any PCI bus in the system has an associated
529 * _BBN object, 0 otherwise.
532 pci_roots_have_bbn(void)
537 * Scan the PCI busses and look for at least 1 _BBN
539 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
540 /* skip non-root (peer) PCI busses */
541 if (pci_bus_res
[i
].par_bus
!= (uchar_t
)-1)
544 if (pci_bbn_present(i
) > 0)
552 * return non-zero if the machine is one on which we renumber
553 * the internal pci unit-addresses
558 ACPI_TABLE_HEADER
*fadt
;
560 if (pci_bus_always_renumber
)
564 if (AcpiGetTable(ACPI_SIG_FADT
, 1, (ACPI_TABLE_HEADER
**)&fadt
) !=
568 /* compare OEM Table ID to "SUNm31" */
569 if (strncmp("SUNm31", fadt
->OemId
, 6))
576 * Initial enumeration of the physical PCI bus hierarchy can
577 * leave 'gaps' in the order of peer PCI bus unit-addresses.
578 * Systems with more than one peer PCI bus *must* have an ACPI
579 * _BBN object associated with each peer bus; use the presence
580 * of this object to remove gaps in the numbering of the peer
581 * PCI bus unit-addresses - only peer busses with an associated
585 pci_renumber_root_busses(void)
587 int pci_regs
[] = {0, 0, 0};
588 int i
, root_addr
= 0;
591 * Currently, we only enable the re-numbering on specific
592 * Sun machines; this is a work-around for the more complicated
593 * issue of upgrade changing physical device paths
595 if (!pci_bus_renumber())
599 * If we find no _BBN objects at all, we either don't need
600 * to do anything or can't do anything anyway
602 if (!pci_roots_have_bbn())
605 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
606 /* skip non-root (peer) PCI busses */
607 if (pci_bus_res
[i
].par_bus
!= (uchar_t
)-1)
610 if (pci_bbn_present(i
) < 1) {
611 pci_bus_res
[i
].root_addr
= (uchar_t
)-1;
615 ASSERT(pci_bus_res
[i
].dip
!= NULL
);
616 if (pci_bus_res
[i
].root_addr
!= root_addr
) {
617 /* update reg property for node */
618 pci_bus_res
[i
].root_addr
= root_addr
;
619 pci_regs
[0] = pci_bus_res
[i
].root_addr
;
620 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
,
621 pci_bus_res
[i
].dip
, "reg", (int *)pci_regs
, 3);
628 pci_register_isa_resources(int type
, uint32_t base
, uint32_t size
)
630 (void) memlist_insert(
631 (type
== 1) ? &isa_res
.io_used
: &isa_res
.mem_used
,
636 * Remove the resources which are already used by devices under a subtractive
637 * bridge from the bus's resources lists, because they're not available, and
638 * shouldn't be allocated to other buses. This is necessary because tracking
639 * resources for subtractive bridges is not complete. (Subtractive bridges only
640 * track some of their claimed resources, not "the rest of the address space" as
641 * they should, so that allocation to peer non-subtractive PPBs is easier. We
642 * need a fully-capable global resource allocator).
645 remove_subtractive_res()
648 struct memlist
*list
;
650 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
651 if (pci_bus_res
[i
].subtractive
) {
652 /* remove used io ports */
653 list
= pci_bus_res
[i
].io_used
;
655 for (j
= 0; j
<= pci_bios_maxbus
; j
++)
656 (void) memlist_remove(
657 &pci_bus_res
[j
].io_avail
,
658 list
->ml_address
, list
->ml_size
);
659 list
= list
->ml_next
;
661 /* remove used mem resource */
662 list
= pci_bus_res
[i
].mem_used
;
664 for (j
= 0; j
<= pci_bios_maxbus
; j
++) {
665 (void) memlist_remove(
666 &pci_bus_res
[j
].mem_avail
,
667 list
->ml_address
, list
->ml_size
);
668 (void) memlist_remove(
669 &pci_bus_res
[j
].pmem_avail
,
670 list
->ml_address
, list
->ml_size
);
672 list
= list
->ml_next
;
674 /* remove used prefetchable mem resource */
675 list
= pci_bus_res
[i
].pmem_used
;
677 for (j
= 0; j
<= pci_bios_maxbus
; j
++) {
678 (void) memlist_remove(
679 &pci_bus_res
[j
].pmem_avail
,
680 list
->ml_address
, list
->ml_size
);
681 (void) memlist_remove(
682 &pci_bus_res
[j
].mem_avail
,
683 list
->ml_address
, list
->ml_size
);
685 list
= list
->ml_next
;
692 * Set up (or complete the setup of) the bus_avail resource list
695 setup_bus_res(int bus
)
699 if (pci_bus_res
[bus
].dip
== NULL
) /* unused bus */
703 * Set up bus_avail if not already filled in by populate_bus_res()
705 if (pci_bus_res
[bus
].bus_avail
== NULL
) {
706 ASSERT(pci_bus_res
[bus
].sub_bus
>= bus
);
707 memlist_insert(&pci_bus_res
[bus
].bus_avail
, bus
,
708 pci_bus_res
[bus
].sub_bus
- bus
+ 1);
711 ASSERT(pci_bus_res
[bus
].bus_avail
!= NULL
);
714 * Remove resources from parent bus node if this is not a
717 par_bus
= pci_bus_res
[bus
].par_bus
;
718 if (par_bus
!= (uchar_t
)-1) {
719 ASSERT(pci_bus_res
[par_bus
].bus_avail
!= NULL
);
720 memlist_remove_list(&pci_bus_res
[par_bus
].bus_avail
,
721 pci_bus_res
[bus
].bus_avail
);
724 /* remove self from bus_avail */;
725 (void) memlist_remove(&pci_bus_res
[bus
].bus_avail
, bus
, 1);
729 get_parbus_io_res(uchar_t parbus
, uchar_t bus
, uint64_t size
, uint64_t align
)
735 * Skip root(peer) buses in multiple-root-bus systems when
736 * ACPI resource discovery was not successfully done.
738 if ((pci_bus_res
[parbus
].par_bus
== (uchar_t
)-1) &&
739 (num_root_bus
> 1) && (acpi_resource_discovery
<= 0))
743 while (pci_bus_res
[res_bus
].subtractive
) {
744 if (pci_bus_res
[res_bus
].io_avail
)
746 res_bus
= pci_bus_res
[res_bus
].par_bus
;
747 if (res_bus
== (uchar_t
)-1)
748 break; /* root bus already */
751 if (pci_bus_res
[res_bus
].io_avail
) {
752 addr
= memlist_find(&pci_bus_res
[res_bus
].io_avail
,
755 memlist_insert(&pci_bus_res
[res_bus
].io_used
,
758 /* free the old resource */
759 memlist_free_all(&pci_bus_res
[bus
].io_avail
);
760 memlist_free_all(&pci_bus_res
[bus
].io_used
);
762 /* add the new resource */
763 memlist_insert(&pci_bus_res
[bus
].io_avail
, addr
, size
);
771 get_parbus_mem_res(uchar_t parbus
, uchar_t bus
, uint64_t size
, uint64_t align
)
777 * Skip root(peer) buses in multiple-root-bus systems when
778 * ACPI resource discovery was not successfully done.
780 if ((pci_bus_res
[parbus
].par_bus
== (uchar_t
)-1) &&
781 (num_root_bus
> 1) && (acpi_resource_discovery
<= 0))
785 while (pci_bus_res
[res_bus
].subtractive
) {
786 if (pci_bus_res
[res_bus
].mem_avail
)
788 res_bus
= pci_bus_res
[res_bus
].par_bus
;
789 if (res_bus
== (uchar_t
)-1)
790 break; /* root bus already */
793 if (pci_bus_res
[res_bus
].mem_avail
) {
794 addr
= memlist_find(&pci_bus_res
[res_bus
].mem_avail
,
797 memlist_insert(&pci_bus_res
[res_bus
].mem_used
,
799 (void) memlist_remove(&pci_bus_res
[res_bus
].pmem_avail
,
802 /* free the old resource */
803 memlist_free_all(&pci_bus_res
[bus
].mem_avail
);
804 memlist_free_all(&pci_bus_res
[bus
].mem_used
);
806 /* add the new resource */
807 memlist_insert(&pci_bus_res
[bus
].mem_avail
, addr
, size
);
815 * given a cap_id, return its cap_id location in config space
818 get_pci_cap(uchar_t bus
, uchar_t dev
, uchar_t func
, uint8_t cap_id
)
820 uint8_t curcap
, cap_id_loc
;
825 * Need to check the Status register for ECP support first.
826 * Also please note that for type 1 devices, the
827 * offset could change. Should support type 1 next.
829 status
= pci_getw(bus
, dev
, func
, PCI_CONF_STAT
);
830 if (!(status
& PCI_STAT_CAP
)) {
833 cap_id_loc
= pci_getb(bus
, dev
, func
, PCI_CONF_CAP_PTR
);
835 /* Walk the list of capabilities */
836 while (cap_id_loc
&& cap_id_loc
!= (uint8_t)-1) {
837 curcap
= pci_getb(bus
, dev
, func
, cap_id_loc
);
839 if (curcap
== cap_id
) {
840 location
= cap_id_loc
;
843 cap_id_loc
= pci_getb(bus
, dev
, func
, cap_id_loc
+ 1);
849 * Does this resource element live in the legacy VGA range?
853 is_vga(struct memlist
*elem
, enum io_mem io
)
857 if ((elem
->ml_address
== 0x3b0 && elem
->ml_size
== 0xc) ||
858 (elem
->ml_address
== 0x3c0 && elem
->ml_size
== 0x20))
861 if (elem
->ml_address
== 0xa0000 && elem
->ml_size
== 0x20000)
868 * Does this entire resource list consist only of legacy VGA resources?
872 list_is_vga_only(struct memlist
*l
, enum io_mem io
)
877 } while ((l
= l
->ml_next
) != NULL
);
882 * Assign valid resources to unconfigured pci(e) bridges. We are trying
883 * to reprogram the bridge when its
884 * i) SECBUS == SUBBUS ||
885 * ii) IOBASE > IOLIM ||
886 * iii) MEMBASE > MEMLIM
887 * This must be done after one full pass through the PCI tree to collect
888 * all BIOS-configured resources, so that we know what resources are
889 * free and available to assign to the unconfigured PPBs.
892 fix_ppb_res(uchar_t secbus
, boolean_t prog_sub
)
894 uchar_t bus
, dev
, func
;
895 uchar_t parbus
, subbus
;
896 uint_t io_base
, io_limit
, mem_base
, mem_limit
;
897 uint_t io_size
, mem_size
, io_align
, mem_align
;
901 int rv
, cap_ptr
, physhi
;
904 struct memlist
*list
, *scratch_list
;
906 /* skip root (peer) PCI busses */
907 if (pci_bus_res
[secbus
].par_bus
== (uchar_t
)-1)
910 /* skip subtractive PPB when prog_sub is not TRUE */
911 if (pci_bus_res
[secbus
].subtractive
&& !prog_sub
)
914 /* some entries may be empty due to discontiguous bus numbering */
915 dip
= pci_bus_res
[secbus
].dip
;
919 rv
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
920 "reg", ®p
, ®len
);
921 if (rv
!= DDI_PROP_SUCCESS
|| reglen
== 0)
926 func
= (uchar_t
)PCI_REG_FUNC_G(physhi
);
927 dev
= (uchar_t
)PCI_REG_DEV_G(physhi
);
928 bus
= (uchar_t
)PCI_REG_BUS_G(physhi
);
931 * If pcie bridge, check to see if link is enabled
933 cap_ptr
= get_pci_cap(bus
, dev
, func
, PCI_CAP_ID_PCI_E
);
935 cmd_reg
= pci_getw(bus
, dev
, func
,
936 (uint16_t)cap_ptr
+ PCIE_LINKCTL
);
937 if (cmd_reg
& PCIE_LINKCTL_LINK_DISABLE
) {
939 "!fix_ppb_res: ppb[%x/%x/%x] link is disabled.\n",
945 subbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SUBBUS
);
946 parbus
= pci_bus_res
[secbus
].par_bus
;
947 ASSERT(parbus
== bus
);
948 cmd_reg
= pci_getw(bus
, dev
, func
, PCI_CONF_COMM
);
951 * If we have a Cardbus bridge, but no bus space
953 if (pci_bus_res
[secbus
].num_cbb
!= 0 &&
954 pci_bus_res
[secbus
].bus_avail
== NULL
) {
957 /* normally there are 2 buses under a cardbus bridge */
958 range
= pci_bus_res
[secbus
].num_cbb
* 2;
961 * Try to find and allocate a bus-range starting at subbus+1
962 * from the parent of the PPB.
964 for (; range
!= 0; range
--) {
965 if (memlist_find_with_startaddr(
966 &pci_bus_res
[parbus
].bus_avail
,
967 subbus
+ 1, range
, 1) != NULL
)
968 break; /* find bus range resource at parent */
971 memlist_insert(&pci_bus_res
[secbus
].bus_avail
,
973 subbus
= subbus
+ range
;
974 pci_bus_res
[secbus
].sub_bus
= subbus
;
975 pci_putb(bus
, dev
, func
, PCI_BCNF_SUBBUS
, subbus
);
976 add_bus_range_prop(secbus
);
978 cmn_err(CE_NOTE
, "!reprogram bus-range on ppb"
979 "[%x/%x/%x]: %x ~ %x\n", bus
, dev
, func
,
985 * Calculate required IO size and alignment
986 * If bus io_size is zero, we are going to assign 512 bytes per bus,
987 * otherwise, we'll choose the maximum value of such calculation and
988 * bus io_size. The size needs to be 4K aligned.
990 * We calculate alignment as the largest power of two less than the
991 * the sum of all children's IO size requirements, because this will
992 * align to the size of the largest child request within that size
993 * (which is always a power of two).
995 io_size
= (subbus
- secbus
+ 1) * 0x200;
996 if (io_size
< pci_bus_res
[secbus
].io_size
)
997 io_size
= pci_bus_res
[secbus
].io_size
;
998 io_size
= P2ROUNDUP(io_size
, PPB_IO_ALIGNMENT
);
1003 * Calculate required MEM size and alignment
1004 * If bus mem_size is zero, we are going to assign 1M bytes per bus,
1005 * otherwise, we'll choose the maximum value of such calculation and
1006 * bus mem_size. The size needs to be 1M aligned.
1008 * For the alignment, refer to the I/O comment above.
1010 mem_size
= (subbus
- secbus
+ 1) * PPB_MEM_ALIGNMENT
;
1011 if (mem_size
< pci_bus_res
[secbus
].mem_size
) {
1012 mem_size
= pci_bus_res
[secbus
].mem_size
;
1013 mem_size
= P2ROUNDUP(mem_size
, PPB_MEM_ALIGNMENT
);
1015 mem_align
= mem_size
;
1018 /* Subtractive bridge */
1019 if (pci_bus_res
[secbus
].subtractive
&& prog_sub
) {
1021 * We program an arbitrary amount of I/O and memory resource
1022 * for the subtractive bridge so that child dynamic-resource-
1023 * allocating devices (such as Cardbus bridges) have a chance
1024 * of success. Until we have full-tree resource rebalancing,
1025 * dynamic resource allocation (thru busra) only looks at the
1026 * parent bridge, so all PPBs must have some allocatable
1027 * resource. For non-subtractive bridges, the resources come
1028 * from the base/limit register "windows", but subtractive
1029 * bridges often don't program those (since they don't need to).
1030 * If we put all the remaining resources on the subtractive
1031 * bridge, then peer non-subtractive bridges can't allocate
1032 * more space (even though this is probably most correct).
1033 * If we put the resources only on the parent, then allocations
1034 * from children of subtractive bridges will fail without
1035 * special-case code for bypassing the subtractive bridge.
1036 * This solution is the middle-ground temporary solution until
1037 * we have fully-capable resource allocation.
1041 * Add an arbitrary I/O resource to the subtractive PPB
1043 if (pci_bus_res
[secbus
].io_avail
== NULL
) {
1044 addr
= get_parbus_io_res(parbus
, secbus
, io_size
,
1047 add_ranges_prop(secbus
, 1);
1048 pci_bus_res
[secbus
].io_reprogram
=
1049 pci_bus_res
[parbus
].io_reprogram
;
1051 cmn_err(CE_NOTE
, "!add io-range on subtractive"
1052 " ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
1053 bus
, dev
, func
, (uint32_t)addr
,
1054 (uint32_t)addr
+ io_size
- 1);
1058 * Add an arbitrary memory resource to the subtractive PPB
1060 if (pci_bus_res
[secbus
].mem_avail
== NULL
) {
1061 addr
= get_parbus_mem_res(parbus
, secbus
, mem_size
,
1064 add_ranges_prop(secbus
, 1);
1065 pci_bus_res
[secbus
].mem_reprogram
=
1066 pci_bus_res
[parbus
].mem_reprogram
;
1068 cmn_err(CE_NOTE
, "!add mem-range on "
1069 "subtractive ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
1070 bus
, dev
, func
, (uint32_t)addr
,
1071 (uint32_t)addr
+ mem_size
- 1);
1079 * Check to see if we need to reprogram I/O space, either because the
1080 * parent bus needed reprogramming and so do we, or because I/O space is
1081 * disabled in base/limit or command register.
1083 io_base
= pci_getb(bus
, dev
, func
, PCI_BCNF_IO_BASE_LOW
);
1084 io_limit
= pci_getb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_LOW
);
1085 io_base
= (io_base
& PCI_BCNF_IO_MASK
) << PCI_BCNF_IO_SHIFT
;
1086 io_limit
= ((io_limit
& PCI_BCNF_IO_MASK
) << PCI_BCNF_IO_SHIFT
) | 0xfff;
1087 if ((io_base
& PCI_BCNF_ADDR_MASK
) == PCI_BCNF_IO_32BIT
) {
1088 uint16_t io_base_hi
, io_limit_hi
;
1089 io_base_hi
= pci_getw(bus
, dev
, func
, PCI_BCNF_IO_BASE_HI
);
1090 io_limit_hi
= pci_getw(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_HI
);
1092 io_base
|= (uint_t
)io_base_hi
<< 16;
1093 io_limit
|= (uint_t
)io_limit_hi
<< 16;
1096 /* Form list of all resources passed (avail + used) */
1097 scratch_list
= memlist_dup(pci_bus_res
[secbus
].io_avail
);
1098 memlist_merge(&pci_bus_res
[secbus
].io_used
, &scratch_list
);
1100 if ((pci_bus_res
[parbus
].io_reprogram
||
1101 (io_base
> io_limit
) ||
1102 (!(cmd_reg
& PCI_COMM_IO
))) &&
1103 !list_is_vga_only(scratch_list
, IO
)) {
1104 if (pci_bus_res
[secbus
].io_used
) {
1105 memlist_subsume(&pci_bus_res
[secbus
].io_used
,
1106 &pci_bus_res
[secbus
].io_avail
);
1108 if (pci_bus_res
[secbus
].io_avail
&&
1109 (!pci_bus_res
[parbus
].io_reprogram
) &&
1110 (!pci_bus_res
[parbus
].subtractive
)) {
1111 /* rechoose old io ports info */
1112 list
= pci_bus_res
[secbus
].io_avail
;
1115 if (is_vga(list
, IO
))
1118 io_base
= (uint_t
)list
->ml_address
;
1119 io_limit
= (uint_t
)list
->ml_address
+
1122 P2ALIGN(io_base
, PPB_IO_ALIGNMENT
);
1124 if (list
->ml_address
+ list
->ml_size
>
1131 } while ((list
= list
->ml_next
) != NULL
);
1133 io_limit
= P2ROUNDUP(io_limit
, PPB_IO_ALIGNMENT
) - 1;
1134 io_size
= io_limit
- io_base
+ 1;
1135 ASSERT(io_base
<= io_limit
);
1136 memlist_free_all(&pci_bus_res
[secbus
].io_avail
);
1137 memlist_insert(&pci_bus_res
[secbus
].io_avail
,
1139 memlist_insert(&pci_bus_res
[parbus
].io_used
,
1141 (void) memlist_remove(&pci_bus_res
[parbus
].io_avail
,
1143 pci_bus_res
[secbus
].io_reprogram
= B_TRUE
;
1145 /* get new io ports from parent bus */
1146 addr
= get_parbus_io_res(parbus
, secbus
, io_size
,
1150 io_limit
= addr
+ io_size
- 1;
1151 pci_bus_res
[secbus
].io_reprogram
= B_TRUE
;
1154 if (pci_bus_res
[secbus
].io_reprogram
) {
1155 /* reprogram PPB regs */
1156 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_BASE_LOW
,
1157 (uchar_t
)((io_base
>>8) & 0xf0));
1158 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_LOW
,
1159 (uchar_t
)((io_limit
>>8) & 0xf0));
1160 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_BASE_HI
, 0);
1161 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_HI
, 0);
1162 add_ranges_prop(secbus
, 1);
1164 cmn_err(CE_NOTE
, "!reprogram io-range on"
1165 " ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
1166 bus
, dev
, func
, io_base
, io_limit
);
1169 memlist_free_all(&scratch_list
);
1172 * Check memory space as we did I/O space.
1174 mem_base
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_BASE
);
1175 mem_base
= (mem_base
& 0xfff0) << 16;
1176 mem_limit
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_LIMIT
);
1177 mem_limit
= ((mem_limit
& 0xfff0) << 16) | 0xfffff;
1179 scratch_list
= memlist_dup(pci_bus_res
[secbus
].mem_avail
);
1180 memlist_merge(&pci_bus_res
[secbus
].mem_used
, &scratch_list
);
1182 if ((pci_bus_res
[parbus
].mem_reprogram
||
1183 (mem_base
> mem_limit
) ||
1184 (!(cmd_reg
& PCI_COMM_MAE
))) &&
1185 !list_is_vga_only(scratch_list
, MEM
)) {
1186 if (pci_bus_res
[secbus
].mem_used
) {
1187 memlist_subsume(&pci_bus_res
[secbus
].mem_used
,
1188 &pci_bus_res
[secbus
].mem_avail
);
1190 if (pci_bus_res
[secbus
].mem_avail
&&
1191 (!pci_bus_res
[parbus
].mem_reprogram
) &&
1192 (!pci_bus_res
[parbus
].subtractive
)) {
1193 /* rechoose old mem resource */
1194 list
= pci_bus_res
[secbus
].mem_avail
;
1197 if (is_vga(list
, MEM
))
1199 if (mem_base
== 0) {
1200 mem_base
= (uint_t
)list
->ml_address
;
1201 mem_base
= P2ALIGN(mem_base
,
1203 mem_limit
= (uint_t
)(list
->ml_address
+
1206 if ((list
->ml_address
+ list
->ml_size
) >
1208 mem_limit
= (uint_t
)
1213 } while ((list
= list
->ml_next
) != NULL
);
1214 mem_limit
= P2ROUNDUP(mem_limit
, PPB_MEM_ALIGNMENT
) - 1;
1215 mem_size
= mem_limit
+ 1 - mem_base
;
1216 ASSERT(mem_base
<= mem_limit
);
1217 memlist_free_all(&pci_bus_res
[secbus
].mem_avail
);
1218 memlist_insert(&pci_bus_res
[secbus
].mem_avail
,
1219 mem_base
, mem_size
);
1220 memlist_insert(&pci_bus_res
[parbus
].mem_used
,
1221 mem_base
, mem_size
);
1222 (void) memlist_remove(&pci_bus_res
[parbus
].mem_avail
,
1223 mem_base
, mem_size
);
1224 pci_bus_res
[secbus
].mem_reprogram
= B_TRUE
;
1226 /* get new mem resource from parent bus */
1227 addr
= get_parbus_mem_res(parbus
, secbus
, mem_size
,
1231 mem_limit
= addr
+ mem_size
- 1;
1232 pci_bus_res
[secbus
].mem_reprogram
= B_TRUE
;
1236 if (pci_bus_res
[secbus
].mem_reprogram
) {
1237 /* reprogram PPB MEM regs */
1238 pci_putw(bus
, dev
, func
, PCI_BCNF_MEM_BASE
,
1239 (uint16_t)((mem_base
>>16) & 0xfff0));
1240 pci_putw(bus
, dev
, func
, PCI_BCNF_MEM_LIMIT
,
1241 (uint16_t)((mem_limit
>>16) & 0xfff0));
1243 * Disable PMEM window by setting base > limit.
1244 * We currently don't reprogram the PMEM like we've
1245 * done for I/O and MEM. (Devices that support prefetch
1246 * can use non-prefetch MEM.) Anyway, if the MEM access
1247 * bit is initially disabled by BIOS, we disable the
1248 * PMEM window manually by setting PMEM base > PMEM
1249 * limit here, in case there are incorrect values in
1250 * them from BIOS, so that we won't get in trouble once
1251 * the MEM access bit is enabled at the end of this
1254 if (!(cmd_reg
& PCI_COMM_MAE
)) {
1255 pci_putw(bus
, dev
, func
, PCI_BCNF_PF_BASE_LOW
,
1257 pci_putw(bus
, dev
, func
, PCI_BCNF_PF_LIMIT_LOW
,
1259 pci_putl(bus
, dev
, func
, PCI_BCNF_PF_BASE_HIGH
,
1261 pci_putl(bus
, dev
, func
, PCI_BCNF_PF_LIMIT_HIGH
,
1265 add_ranges_prop(secbus
, 1);
1267 cmn_err(CE_NOTE
, "!reprogram mem-range on"
1268 " ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
1269 bus
, dev
, func
, mem_base
, mem_limit
);
1272 memlist_free_all(&scratch_list
);
1275 if (pci_bus_res
[secbus
].io_avail
)
1276 cmd_reg
|= PCI_COMM_IO
| PCI_COMM_ME
;
1277 if (pci_bus_res
[secbus
].mem_avail
)
1278 cmd_reg
|= PCI_COMM_MAE
| PCI_COMM_ME
;
1279 pci_putw(bus
, dev
, func
, PCI_CONF_COMM
, cmd_reg
);
1285 int i
, pci_reconfig
= 1;
1290 * Scan ACPI namespace for _BBN objects, make sure that
1291 * childless root-bridges appear in devinfo tree
1294 pci_unitaddr_cache_init();
1297 * Fix-up unit-address assignments if cache is available
1299 if (pci_unitaddr_cache_valid()) {
1300 int pci_regs
[] = {0, 0, 0};
1304 for (bus
= 0; bus
<= pci_bios_maxbus
; bus
++) {
1305 /* skip non-root (peer) PCI busses */
1306 if ((pci_bus_res
[bus
].par_bus
!= (uchar_t
)-1) ||
1307 (pci_bus_res
[bus
].dip
== NULL
))
1310 new_addr
= pci_bus_unitaddr(index
);
1311 if (pci_bus_res
[bus
].root_addr
!= new_addr
) {
1312 /* update reg property for node */
1313 pci_regs
[0] = pci_bus_res
[bus
].root_addr
=
1315 (void) ndi_prop_update_int_array(
1316 DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
1317 "reg", (int *)pci_regs
, 3);
1322 /* perform legacy processing */
1323 pci_renumber_root_busses();
1324 pci_unitaddr_cache_create();
1328 * Do root-bus resource discovery
1330 for (bus
= 0; bus
<= pci_bios_maxbus
; bus
++) {
1331 /* skip non-root (peer) PCI busses */
1332 if (pci_bus_res
[bus
].par_bus
!= (uchar_t
)-1)
1336 * 1. find resources associated with this root bus
1338 populate_bus_res(bus
);
1342 * 2. Remove used PCI and ISA resources from bus resource map
1345 memlist_remove_list(&pci_bus_res
[bus
].io_avail
,
1346 pci_bus_res
[bus
].io_used
);
1347 memlist_remove_list(&pci_bus_res
[bus
].mem_avail
,
1348 pci_bus_res
[bus
].mem_used
);
1349 memlist_remove_list(&pci_bus_res
[bus
].pmem_avail
,
1350 pci_bus_res
[bus
].pmem_used
);
1351 memlist_remove_list(&pci_bus_res
[bus
].mem_avail
,
1352 pci_bus_res
[bus
].pmem_used
);
1353 memlist_remove_list(&pci_bus_res
[bus
].pmem_avail
,
1354 pci_bus_res
[bus
].mem_used
);
1356 memlist_remove_list(&pci_bus_res
[bus
].io_avail
,
1358 memlist_remove_list(&pci_bus_res
[bus
].mem_avail
,
1362 * 3. Exclude <1M address range here in case below reserved
1363 * ranges for BIOS data area, ROM area etc are wrongly reported
1364 * in ACPI resource producer entries for PCI root bus.
1365 * 00000000 - 000003FF RAM
1366 * 00000400 - 000004FF BIOS data area
1367 * 00000500 - 0009FFFF RAM
1368 * 000A0000 - 000BFFFF VGA RAM
1369 * 000C0000 - 000FFFFF ROM area
1371 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
, 0, 0x100000);
1372 (void) memlist_remove(&pci_bus_res
[bus
].pmem_avail
,
1376 memlist_free_all(&isa_res
.io_used
);
1377 memlist_free_all(&isa_res
.mem_used
);
1379 /* add bus-range property for root/peer bus nodes */
1380 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
1381 /* create bus-range property on root/peer buses */
1382 if (pci_bus_res
[i
].par_bus
== (uchar_t
)-1)
1383 add_bus_range_prop(i
);
1385 /* setup bus range resource on each bus */
1389 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, ddi_root_node(),
1390 DDI_PROP_DONTPASS
, "pci-reprog", &onoff
) == DDI_SUCCESS
) {
1391 if (strcmp(onoff
, "off") == 0) {
1393 cmn_err(CE_NOTE
, "pci device reprogramming disabled");
1395 ddi_prop_free(onoff
);
1398 remove_subtractive_res();
1400 /* reprogram the non-subtractive PPB */
1402 for (i
= 0; i
<= pci_bios_maxbus
; i
++)
1403 fix_ppb_res(i
, B_FALSE
);
1405 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
1406 /* configure devices not configured by BIOS */
1409 * Reprogram the subtractive PPB. At this time, all its
1410 * siblings should have got their resources already.
1412 if (pci_bus_res
[i
].subtractive
)
1413 fix_ppb_res(i
, B_TRUE
);
1414 enumerate_bus_devs(i
, CONFIG_NEW
);
1418 /* All dev programmed, so we can create available prop */
1419 for (i
= 0; i
<= pci_bios_maxbus
; i
++)
1420 add_bus_available_prop(i
);
1424 * populate bus resources
1427 populate_bus_res(uchar_t bus
)
1430 /* scan BIOS structures */
1431 pci_bus_res
[bus
].pmem_avail
= find_bus_res(bus
, PREFETCH_TYPE
);
1432 pci_bus_res
[bus
].mem_avail
= find_bus_res(bus
, MEM_TYPE
);
1433 pci_bus_res
[bus
].io_avail
= find_bus_res(bus
, IO_TYPE
);
1434 pci_bus_res
[bus
].bus_avail
= find_bus_res(bus
, BUSRANGE_TYPE
);
1437 * attempt to initialize sub_bus from the largest range-end
1438 * in the bus_avail list
1440 if (pci_bus_res
[bus
].bus_avail
!= NULL
) {
1441 struct memlist
*entry
;
1444 entry
= pci_bus_res
[bus
].bus_avail
;
1445 while (entry
!= NULL
) {
1446 current
= entry
->ml_address
+ entry
->ml_size
- 1;
1447 if (current
> pci_bus_res
[bus
].sub_bus
)
1448 pci_bus_res
[bus
].sub_bus
= current
;
1449 entry
= entry
->ml_next
;
1455 * Special treatment of bus 0:
1456 * If no IO/MEM resource from ACPI/MPSPEC/HRT, copy
1457 * pcimem from boot and make I/O space the entire range
1458 * starting at 0x100.
1460 if (pci_bus_res
[0].mem_avail
== NULL
)
1461 pci_bus_res
[0].mem_avail
=
1462 memlist_dup(bootops
->boot_mem
->pcimem
);
1463 /* Exclude 0x00 to 0xff of the I/O space, used by all PCs */
1464 if (pci_bus_res
[0].io_avail
== NULL
)
1465 memlist_insert(&pci_bus_res
[0].io_avail
, 0x100, 0xffff);
1469 * Create 'ranges' property here before any resources are
1470 * removed from the resource lists
1472 add_ranges_prop(bus
, 0);
1477 * Create top-level bus dips, i.e. /pci@0,0, /pci@1,0...
1480 create_root_bus_dip(uchar_t bus
)
1482 int pci_regs
[] = {0, 0, 0};
1485 ASSERT(pci_bus_res
[bus
].par_bus
== (uchar_t
)-1);
1488 ndi_devi_alloc_sleep(ddi_root_node(), "pci",
1489 (pnode_t
)DEVI_SID_NODEID
, &dip
);
1490 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1491 "#address-cells", 3);
1492 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1494 pci_regs
[0] = pci_bus_res
[bus
].root_addr
;
1495 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
1496 "reg", (int *)pci_regs
, 3);
1499 * If system has PCIe bus, then create different properties
1501 if (create_pcie_root_bus(bus
, dip
) == B_FALSE
)
1502 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
1503 "device_type", "pci");
1505 (void) ndi_devi_bind_driver(dip
, 0);
1506 pci_bus_res
[bus
].dip
= dip
;
1510 * For any fixed configuration (often compatability) pci devices
1511 * and those with their own expansion rom, create device nodes
1512 * to hold the already configured device details.
1515 enumerate_bus_devs(uchar_t bus
, int config_op
)
1517 uchar_t dev
, func
, nfunc
, header
;
1519 struct pci_devfunc
*devlist
= NULL
, *entry
;
1521 if (config_op
== CONFIG_NEW
) {
1522 dcmn_err(CE_NOTE
, "configuring pci bus 0x%x", bus
);
1523 } else if (config_op
== CONFIG_FIX
) {
1524 dcmn_err(CE_NOTE
, "fixing devices on pci bus 0x%x", bus
);
1526 dcmn_err(CE_NOTE
, "enumerating pci bus 0x%x", bus
);
1528 if (config_op
== CONFIG_NEW
) {
1529 devlist
= (struct pci_devfunc
*)pci_bus_res
[bus
].privdata
;
1532 devlist
= entry
->next
;
1533 if (entry
->reprogram
||
1534 pci_bus_res
[bus
].io_reprogram
||
1535 pci_bus_res
[bus
].mem_reprogram
) {
1536 /* reprogram device(s) */
1537 (void) add_reg_props(entry
->dip
, bus
,
1538 entry
->dev
, entry
->func
, CONFIG_NEW
, 0);
1540 kmem_free(entry
, sizeof (*entry
));
1542 pci_bus_res
[bus
].privdata
= NULL
;
1546 for (dev
= 0; dev
< max_dev_pci
; dev
++) {
1548 for (func
= 0; func
< nfunc
; func
++) {
1550 dcmn_err(CE_NOTE
, "probing dev 0x%x, func 0x%x",
1553 venid
= pci_getw(bus
, dev
, func
, PCI_CONF_VENID
);
1555 if ((venid
== 0xffff) || (venid
== 0)) {
1556 /* no function at this address */
1560 header
= pci_getb(bus
, dev
, func
, PCI_CONF_HEADER
);
1561 if (header
== 0xff) {
1562 continue; /* illegal value */
1566 * according to some mail from Microsoft posted
1567 * to the pci-drivers alias, their only requirement
1568 * for a multifunction device is for the 1st
1569 * function to have to PCI_HEADER_MULTI bit set.
1571 if ((func
== 0) && (header
& PCI_HEADER_MULTI
)) {
1575 if (config_op
== CONFIG_FIX
||
1576 config_op
== CONFIG_INFO
) {
1578 * Create the node, unconditionally, on the
1579 * first pass only. It may still need
1580 * resource assignment, which will be
1581 * done on the second, CONFIG_NEW, pass.
1583 process_devfunc(bus
, dev
, func
, header
,
1590 /* percolate bus used resources up through parents to root */
1591 if (config_op
== CONFIG_INFO
) {
1594 par_bus
= pci_bus_res
[bus
].par_bus
;
1595 while (par_bus
!= (uchar_t
)-1) {
1596 pci_bus_res
[par_bus
].io_size
+=
1597 pci_bus_res
[bus
].io_size
;
1598 pci_bus_res
[par_bus
].mem_size
+=
1599 pci_bus_res
[bus
].mem_size
;
1601 if (pci_bus_res
[bus
].io_used
)
1602 memlist_merge(&pci_bus_res
[bus
].io_used
,
1603 &pci_bus_res
[par_bus
].io_used
);
1605 if (pci_bus_res
[bus
].mem_used
)
1606 memlist_merge(&pci_bus_res
[bus
].mem_used
,
1607 &pci_bus_res
[par_bus
].mem_used
);
1609 if (pci_bus_res
[bus
].pmem_used
)
1610 memlist_merge(&pci_bus_res
[bus
].pmem_used
,
1611 &pci_bus_res
[par_bus
].pmem_used
);
1614 par_bus
= pci_bus_res
[par_bus
].par_bus
;
1620 check_pciide_prop(uchar_t revid
, ushort_t venid
, ushort_t devid
,
1621 ushort_t subvenid
, ushort_t subdevid
)
1623 static int prop_exist
= -1;
1624 static char *pciide_str
;
1627 if (prop_exist
== -1) {
1628 prop_exist
= (ddi_prop_lookup_string(DDI_DEV_T_ANY
,
1629 ddi_root_node(), DDI_PROP_DONTPASS
, "pci-ide",
1630 &pciide_str
) == DDI_SUCCESS
);
1636 /* compare property value against various forms of compatible */
1638 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x.%x.%x.%x",
1639 venid
, devid
, subvenid
, subdevid
, revid
);
1640 if (strcmp(pciide_str
, compat
) == 0)
1643 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x.%x.%x",
1644 venid
, devid
, subvenid
, subdevid
);
1645 if (strcmp(pciide_str
, compat
) == 0)
1648 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x",
1649 subvenid
, subdevid
);
1650 if (strcmp(pciide_str
, compat
) == 0)
1653 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x.%x",
1654 venid
, devid
, revid
);
1655 if (strcmp(pciide_str
, compat
) == 0)
1658 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x", venid
, devid
);
1659 if (strcmp(pciide_str
, compat
) == 0)
1666 is_pciide(uchar_t basecl
, uchar_t subcl
, uchar_t revid
,
1667 ushort_t venid
, ushort_t devid
, ushort_t subvenid
, ushort_t subdevid
)
1669 struct ide_table
{ /* table for PCI_MASS_OTHER */
1674 /* XXX SATA and other devices: need a way to add dynamically */
1675 static struct ide_table ide_other
[] = {
1679 {0x1095, 0x680}, /* Sil0680 */
1680 {0x1283, 0x8211}, /* ITE 8211F is subcl PCI_MASS_OTHER */
1684 if (basecl
!= PCI_CLASS_MASS
)
1687 if (subcl
== PCI_MASS_IDE
) {
1691 if (check_pciide_prop(revid
, venid
, devid
, subvenid
, subdevid
))
1694 if (subcl
!= PCI_MASS_OTHER
&& subcl
!= PCI_MASS_SATA
) {
1698 entry
= &ide_other
[0];
1699 while (entry
->venid
) {
1700 if (entry
->venid
== venid
&& entry
->devid
== devid
)
1708 is_display(uint_t classcode
)
1710 static uint_t disp_classes
[] = {
1715 int i
, nclasses
= sizeof (disp_classes
) / sizeof (uint_t
);
1717 for (i
= 0; i
< nclasses
; i
++) {
1718 if (classcode
== disp_classes
[i
])
1725 add_undofix_entry(uint8_t bus
, uint8_t dev
, uint8_t fn
,
1726 void (*undofn
)(uint8_t, uint8_t, uint8_t))
1728 struct pci_fixundo
*newundo
;
1730 newundo
= kmem_alloc(sizeof (struct pci_fixundo
), KM_SLEEP
);
1733 * Adding an item to this list means that we must turn its NMIENABLE
1734 * bit back on at a later time.
1739 newundo
->undofn
= undofn
;
1740 newundo
->next
= undolist
;
1742 /* add to the undo list in LIFO order */
1751 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
1753 * For each bus, apply needed fixes to the appropriate devices.
1754 * This must be done before the main enumeration loop because
1755 * some fixes must be applied to devices normally encountered
1756 * later in the pci scan (e.g. if a fix to device 7 must be
1757 * applied before scanning device 6, applying fixes in the
1758 * normal enumeration loop would obviously be too late).
1760 enumerate_bus_devs(i
, CONFIG_FIX
);
1765 undo_pci_fixes(void)
1767 struct pci_fixundo
*nextundo
;
1768 uint8_t bus
, dev
, fn
;
1771 * All fixes in the undo list are performed unconditionally. Future
1772 * fixes may require selective undo.
1774 while (undolist
!= NULL
) {
1776 bus
= undolist
->bus
;
1777 dev
= undolist
->dev
;
1780 (*(undolist
->undofn
))(bus
, dev
, fn
);
1782 nextundo
= undolist
->next
;
1783 kmem_free(undolist
, sizeof (struct pci_fixundo
));
1784 undolist
= nextundo
;
1789 undo_amd8111_pci_fix(uint8_t bus
, uint8_t dev
, uint8_t fn
)
1793 val8
= pci_getb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
);
1795 * The NMIONERR bit is turned back on to allow the SMM BIOS
1796 * to handle more critical PCI errors (e.g. PERR#).
1798 val8
|= AMD8111_ENABLENMI
;
1799 pci_putb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
, val8
);
1803 pci_fix_amd8111(uint8_t bus
, uint8_t dev
, uint8_t fn
)
1807 val8
= pci_getb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
);
1809 if ((val8
& AMD8111_ENABLENMI
) == 0)
1813 * We reset NMIONERR in the LPC because master-abort on the PCI
1814 * bridge side of the 8111 will cause NMI, which might cause SMI,
1815 * which sometimes prevents all devices from being enumerated.
1817 val8
&= ~AMD8111_ENABLENMI
;
1819 pci_putb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
, val8
);
1821 add_undofix_entry(bus
, dev
, fn
, undo_amd8111_pci_fix
);
1825 set_devpm_d0(uchar_t bus
, uchar_t dev
, uchar_t func
)
1833 status
= pci_getw(bus
, dev
, func
, PCI_CONF_STAT
);
1834 if (!(status
& PCI_STAT_CAP
))
1835 return; /* No capabilities list */
1837 header
= pci_getb(bus
, dev
, func
, PCI_CONF_HEADER
) & PCI_HEADER_TYPE_M
;
1838 if (header
== PCI_HEADER_CARDBUS
)
1839 cap_ptr
= pci_getb(bus
, dev
, func
, PCI_CBUS_CAP_PTR
);
1841 cap_ptr
= pci_getb(bus
, dev
, func
, PCI_CONF_CAP_PTR
);
1843 * Walk the capabilities list searching for a PM entry.
1845 while (cap_ptr
!= PCI_CAP_NEXT_PTR_NULL
&& cap_ptr
>= PCI_CAP_PTR_OFF
) {
1846 cap_ptr
&= PCI_CAP_PTR_MASK
;
1847 cap_id
= pci_getb(bus
, dev
, func
, cap_ptr
+ PCI_CAP_ID
);
1848 if (cap_id
== PCI_CAP_ID_PM
) {
1849 pmcsr
= pci_getw(bus
, dev
, func
, cap_ptr
+ PCI_PMCSR
);
1850 pmcsr
&= ~(PCI_PMCSR_STATE_MASK
);
1851 pmcsr
|= PCI_PMCSR_D0
; /* D0 state */
1852 pci_putw(bus
, dev
, func
, cap_ptr
+ PCI_PMCSR
, pmcsr
);
1855 cap_ptr
= pci_getb(bus
, dev
, func
, cap_ptr
+ PCI_CAP_NEXT_PTR
);
1860 #define is_isa(bc, sc) \
1861 (((bc) == PCI_CLASS_BRIDGE) && ((sc) == PCI_BRIDGE_ISA))
1864 process_devfunc(uchar_t bus
, uchar_t dev
, uchar_t func
, uchar_t header
,
1865 ushort_t vendorid
, int config_op
)
1867 char nodename
[32], unitaddr
[5];
1869 uchar_t basecl
, subcl
, progcl
, intr
, revid
;
1870 ushort_t subvenid
, subdevid
, status
;
1872 uint_t classcode
, revclass
;
1873 int reprogram
= 0, pciide
= 0;
1874 int power
[2] = {1, 1};
1876 ushort_t is_pci_bridge
= 0;
1877 struct pci_devfunc
*devlist
= NULL
, *entry
= NULL
;
1878 boolean_t slot_valid
;
1882 ushort_t deviceid
= pci_getw(bus
, dev
, func
, PCI_CONF_DEVID
);
1884 switch (header
& PCI_HEADER_TYPE_M
) {
1885 case PCI_HEADER_ZERO
:
1886 subvenid
= pci_getw(bus
, dev
, func
, PCI_CONF_SUBVENID
);
1887 subdevid
= pci_getw(bus
, dev
, func
, PCI_CONF_SUBSYSID
);
1889 case PCI_HEADER_CARDBUS
:
1890 subvenid
= pci_getw(bus
, dev
, func
, PCI_CBUS_SUBVENID
);
1891 subdevid
= pci_getw(bus
, dev
, func
, PCI_CBUS_SUBSYSID
);
1892 /* Record the # of cardbus bridges found on the bus */
1893 if (config_op
== CONFIG_INFO
)
1894 pci_bus_res
[bus
].num_cbb
++;
1902 if (config_op
== CONFIG_FIX
) {
1903 if (vendorid
== VENID_AMD
&& deviceid
== DEVID_AMD8111_LPC
) {
1904 pci_fix_amd8111(bus
, dev
, func
);
1909 /* XXX should be use generic names? derive from class? */
1910 revclass
= pci_getl(bus
, dev
, func
, PCI_CONF_REVID
);
1911 classcode
= revclass
>> 8;
1912 revid
= revclass
& 0xff;
1914 /* figure out if this is pci-ide */
1915 basecl
= classcode
>> 16;
1916 subcl
= (classcode
>> 8) & 0xff;
1917 progcl
= classcode
& 0xff;
1920 if (is_display(classcode
))
1921 (void) snprintf(nodename
, sizeof (nodename
), "display");
1922 else if (!pseudo_isa
&& is_isa(basecl
, subcl
))
1923 (void) snprintf(nodename
, sizeof (nodename
), "isa");
1924 else if (subvenid
!= 0)
1925 (void) snprintf(nodename
, sizeof (nodename
),
1926 "pci%x,%x", subvenid
, subdevid
);
1928 (void) snprintf(nodename
, sizeof (nodename
),
1929 "pci%x,%x", vendorid
, deviceid
);
1931 /* make sure parent bus dip has been created */
1932 if (pci_bus_res
[bus
].dip
== NULL
)
1933 create_root_bus_dip(bus
);
1935 ndi_devi_alloc_sleep(pci_bus_res
[bus
].dip
, nodename
,
1936 DEVI_SID_NODEID
, &dip
);
1938 if (check_if_device_is_pciex(dip
, bus
, dev
, func
, &slot_valid
,
1939 &slot_num
, &is_pci_bridge
) == B_TRUE
)
1942 bdf
= PCI_GETBDF(bus
, dev
, func
);
1944 * Record BAD AMD bridges which don't support MMIO config access.
1946 if (IS_BAD_AMD_NTBRIDGE(vendorid
, deviceid
) ||
1947 IS_AMD_8132_CHIP(vendorid
, deviceid
)) {
1951 if ((basecl
== PCI_CLASS_BRIDGE
) &&
1952 (subcl
== PCI_BRIDGE_PCI
)) {
1953 secbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SECBUS
);
1954 subbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SUBBUS
);
1956 pci_cfgacc_add_workaround(bdf
, secbus
, subbus
);
1960 * Only populate bus_t if this device is sitting under a PCIE root
1961 * complex. Some particular machines have both a PCIE root complex and
1962 * a PCI hostbridge, in which case only devices under the PCIE root
1963 * complex will have their bus_t populated.
1965 if (pcie_get_rc_dip(dip
) != NULL
) {
1966 ck804_fix_aer_ptr(dip
, bdf
);
1967 (void) pcie_init_bus(dip
, bdf
, PCIE_BUS_INITIAL
);
1970 /* add properties */
1971 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "device-id", deviceid
);
1972 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "vendor-id", vendorid
);
1973 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "revision-id", revid
);
1974 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1975 "class-code", classcode
);
1977 (void) snprintf(unitaddr
, sizeof (unitaddr
), "%x", dev
);
1979 (void) snprintf(unitaddr
, sizeof (unitaddr
),
1980 "%x,%x", dev
, func
);
1981 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
1982 "unit-address", unitaddr
);
1984 /* add device_type for display nodes */
1985 if (is_display(classcode
)) {
1986 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
1987 "device_type", "display");
1989 /* add special stuff for header type */
1990 if ((header
& PCI_HEADER_TYPE_M
) == PCI_HEADER_ZERO
) {
1991 uchar_t mingrant
= pci_getb(bus
, dev
, func
, PCI_CONF_MIN_G
);
1992 uchar_t maxlatency
= pci_getb(bus
, dev
, func
, PCI_CONF_MAX_L
);
1994 if (subvenid
!= 0) {
1995 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1996 "subsystem-id", subdevid
);
1997 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1998 "subsystem-vendor-id", subvenid
);
2001 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2002 "min-grant", mingrant
);
2004 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2005 "max-latency", maxlatency
);
2008 /* interrupt, record if not 0 */
2009 intr
= pci_getb(bus
, dev
, func
, PCI_CONF_IPIN
);
2011 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2012 "interrupts", intr
);
2015 * Add support for 133 mhz pci eventually
2017 status
= pci_getw(bus
, dev
, func
, PCI_CONF_STAT
);
2019 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2020 "devsel-speed", (status
& PCI_STAT_DEVSELT
) >> 9);
2021 if (!pciex
&& (status
& PCI_STAT_FBBC
))
2022 (void) ndi_prop_create_boolean(DDI_DEV_T_NONE
, dip
,
2023 "fast-back-to-back");
2024 if (!pciex
&& (status
& PCI_STAT_66MHZ
))
2025 (void) ndi_prop_create_boolean(DDI_DEV_T_NONE
, dip
,
2027 if (status
& PCI_STAT_UDF
)
2028 (void) ndi_prop_create_boolean(DDI_DEV_T_NONE
, dip
,
2030 if (pciex
&& slot_valid
) {
2031 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2032 "physical-slot#", slot_num
);
2034 pciex_slot_names_prop(dip
, slot_num
);
2037 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
2038 "power-consumption", power
, 2);
2040 /* Set the device PM state to D0 */
2041 set_devpm_d0(bus
, dev
, func
);
2043 if ((basecl
== PCI_CLASS_BRIDGE
) && (subcl
== PCI_BRIDGE_PCI
))
2044 add_ppb_props(dip
, bus
, dev
, func
, pciex
, is_pci_bridge
);
2047 * Record the non-PPB devices on the bus for possible
2048 * reprogramming at 2nd bus enumeration.
2049 * Note: PPB reprogramming is done in fix_ppb_res()
2051 devlist
= (struct pci_devfunc
*)pci_bus_res
[bus
].privdata
;
2052 entry
= kmem_zalloc(sizeof (*entry
), KM_SLEEP
);
2056 entry
->next
= devlist
;
2057 pci_bus_res
[bus
].privdata
= entry
;
2060 if (IS_CLASS_IOAPIC(basecl
, subcl
, progcl
)) {
2061 create_ioapic_node(bus
, dev
, func
, vendorid
, deviceid
);
2064 /* check for NVIDIA CK8-04/MCP55 based LPC bridge */
2065 if (NVIDIA_IS_LPC_BRIDGE(vendorid
, deviceid
) && (dev
== 1) &&
2067 add_nvidia_isa_bridge_props(dip
, bus
, dev
, func
);
2068 /* each LPC bridge has an integrated IOAPIC */
2069 apic_nvidia_io_max
++;
2072 if (pciex
&& is_pci_bridge
)
2073 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
, "model",
2074 (char *)"PCIe-PCI bridge");
2076 add_model_prop(dip
, classcode
);
2078 add_compatible(dip
, subvenid
, subdevid
, vendorid
, deviceid
,
2079 revid
, classcode
, pciex
);
2082 * See if this device is a controller that advertises
2083 * itself to be a standard ATA task file controller, or one that
2084 * has been hard coded.
2086 * If it is, check if any other higher precedence driver listed in
2087 * driver_aliases will claim the node by calling
2088 * ddi_compatibile_driver_major. If so, clear pciide and do not
2089 * create a pci-ide node or any other special handling.
2091 * If another driver does not bind, set the node name to pci-ide
2092 * and then let the special pci-ide handling for registers and
2093 * child pci-ide nodes proceed below.
2095 if (is_pciide(basecl
, subcl
, revid
, vendorid
, deviceid
,
2096 subvenid
, subdevid
) == 1) {
2097 if (ddi_compatible_driver_major(dip
, NULL
) == (major_t
)-1) {
2098 (void) ndi_devi_set_nodename(dip
, "pci-ide", 0);
2104 reprogram
= add_reg_props(dip
, bus
, dev
, func
, config_op
, pciide
);
2105 (void) ndi_devi_bind_driver(dip
, 0);
2107 /* special handling for pci-ide */
2112 * Create properties specified by P1275 Working Group
2113 * Proposal #414 Version 1
2115 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
2116 "device_type", "pci-ide");
2117 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2118 "#address-cells", 1);
2119 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2122 /* allocate two child nodes */
2123 ndi_devi_alloc_sleep(dip
, "ide",
2124 (pnode_t
)DEVI_SID_NODEID
, &cdip
);
2125 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
,
2127 (void) ndi_devi_bind_driver(cdip
, 0);
2128 ndi_devi_alloc_sleep(dip
, "ide",
2129 (pnode_t
)DEVI_SID_NODEID
, &cdip
);
2130 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
,
2132 (void) ndi_devi_bind_driver(cdip
, 0);
2134 reprogram
= 0; /* don't reprogram pci-ide bridge */
2137 if (is_display(classcode
)) {
2138 gfxp
= kmem_zalloc(sizeof (*gfxp
), KM_SLEEP
);
2140 gfxp
->g_prev
= NULL
;
2141 gfxp
->g_next
= gfx_devinfo_list
;
2142 gfx_devinfo_list
= gfxp
;
2144 gfxp
->g_next
->g_prev
= gfxp
;
2147 /* special handling for isa */
2148 if (!pseudo_isa
&& is_isa(basecl
, subcl
)) {
2149 /* add device_type */
2150 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
2151 "device_type", "isa");
2154 if (reprogram
&& (entry
!= NULL
))
2155 entry
->reprogram
= B_TRUE
;
2160 * Some vendors do not use unique subsystem IDs in their products, which
2161 * makes the use of form 2 compatible names (pciSSSS,ssss) inappropriate.
2162 * Allow for these compatible forms to be excluded on a per-device basis.
2166 subsys_compat_exclude(ushort_t venid
, ushort_t devid
, ushort_t subvenid
,
2167 ushort_t subdevid
, uchar_t revid
, uint_t classcode
)
2169 /* Nvidia display adapters */
2170 if ((venid
== 0x10de) && (is_display(classcode
)))
2177 * Set the compatible property to a value compliant with
2178 * rev 2.1 of the IEEE1275 PCI binding.
2179 * (Also used for PCI-Express devices).
2181 * pciVVVV,DDDD.SSSS.ssss.RR (0)
2182 * pciVVVV,DDDD.SSSS.ssss (1)
2184 * pciVVVV,DDDD.RR (3)
2186 * pciclass,CCSSPP (5)
2189 * The Subsystem (SSSS) forms are not inserted if
2190 * subsystem-vendor-id is 0.
2192 * NOTE: For PCI-Express devices "pci" is replaced with "pciex" in 0-6 above
2193 * property 2 is not created as per "1275 bindings for PCI Express Interconnect"
2195 * Set with setprop and \x00 between each
2196 * to generate the encoded string array form.
2199 add_compatible(dev_info_t
*dip
, ushort_t subvenid
, ushort_t subdevid
,
2200 ushort_t vendorid
, ushort_t deviceid
, uchar_t revid
, uint_t classcode
,
2204 int size
= COMPAT_BUFSIZE
;
2208 curr
= buf
= kmem_alloc(size
, KM_SLEEP
);
2212 compat
[i
++] = curr
; /* form 0 */
2213 (void) snprintf(curr
, size
, "pciex%x,%x.%x.%x.%x",
2214 vendorid
, deviceid
, subvenid
, subdevid
, revid
);
2215 size
-= strlen(curr
) + 1;
2216 curr
+= strlen(curr
) + 1;
2218 compat
[i
++] = curr
; /* form 1 */
2219 (void) snprintf(curr
, size
, "pciex%x,%x.%x.%x",
2220 vendorid
, deviceid
, subvenid
, subdevid
);
2221 size
-= strlen(curr
) + 1;
2222 curr
+= strlen(curr
) + 1;
2225 compat
[i
++] = curr
; /* form 3 */
2226 (void) snprintf(curr
, size
, "pciex%x,%x.%x",
2227 vendorid
, deviceid
, revid
);
2228 size
-= strlen(curr
) + 1;
2229 curr
+= strlen(curr
) + 1;
2231 compat
[i
++] = curr
; /* form 4 */
2232 (void) snprintf(curr
, size
, "pciex%x,%x", vendorid
, deviceid
);
2233 size
-= strlen(curr
) + 1;
2234 curr
+= strlen(curr
) + 1;
2236 compat
[i
++] = curr
; /* form 5 */
2237 (void) snprintf(curr
, size
, "pciexclass,%06x", classcode
);
2238 size
-= strlen(curr
) + 1;
2239 curr
+= strlen(curr
) + 1;
2241 compat
[i
++] = curr
; /* form 6 */
2242 (void) snprintf(curr
, size
, "pciexclass,%04x",
2244 size
-= strlen(curr
) + 1;
2245 curr
+= strlen(curr
) + 1;
2249 compat
[i
++] = curr
; /* form 0 */
2250 (void) snprintf(curr
, size
, "pci%x,%x.%x.%x.%x",
2251 vendorid
, deviceid
, subvenid
, subdevid
, revid
);
2252 size
-= strlen(curr
) + 1;
2253 curr
+= strlen(curr
) + 1;
2255 compat
[i
++] = curr
; /* form 1 */
2256 (void) snprintf(curr
, size
, "pci%x,%x.%x.%x",
2257 vendorid
, deviceid
, subvenid
, subdevid
);
2258 size
-= strlen(curr
) + 1;
2259 curr
+= strlen(curr
) + 1;
2261 if (subsys_compat_exclude(vendorid
, deviceid
, subvenid
,
2262 subdevid
, revid
, classcode
) == B_FALSE
) {
2263 compat
[i
++] = curr
; /* form 2 */
2264 (void) snprintf(curr
, size
, "pci%x,%x", subvenid
,
2266 size
-= strlen(curr
) + 1;
2267 curr
+= strlen(curr
) + 1;
2270 compat
[i
++] = curr
; /* form 3 */
2271 (void) snprintf(curr
, size
, "pci%x,%x.%x", vendorid
, deviceid
, revid
);
2272 size
-= strlen(curr
) + 1;
2273 curr
+= strlen(curr
) + 1;
2275 compat
[i
++] = curr
; /* form 4 */
2276 (void) snprintf(curr
, size
, "pci%x,%x", vendorid
, deviceid
);
2277 size
-= strlen(curr
) + 1;
2278 curr
+= strlen(curr
) + 1;
2280 compat
[i
++] = curr
; /* form 5 */
2281 (void) snprintf(curr
, size
, "pciclass,%06x", classcode
);
2282 size
-= strlen(curr
) + 1;
2283 curr
+= strlen(curr
) + 1;
2285 compat
[i
++] = curr
; /* form 6 */
2286 (void) snprintf(curr
, size
, "pciclass,%04x", (classcode
>> 8));
2287 size
-= strlen(curr
) + 1;
2288 curr
+= strlen(curr
) + 1;
2290 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE
, dip
,
2291 "compatible", compat
, i
);
2292 kmem_free(buf
, COMPAT_BUFSIZE
);
2296 * Adjust the reg properties for a dual channel PCI-IDE device.
2298 * NOTE: don't do anything that changes the order of the hard-decodes
2299 * and programmed BARs. The kernel driver depends on these values
2300 * being in this order regardless of whether they're for a 'native'
2304 * config info for pci-ide devices
2307 uchar_t native_mask
; /* 0 == 'compatibility' mode, 1 == native */
2308 uchar_t bar_offset
; /* offset for alt status register */
2309 ushort_t addr
; /* compatibility mode base address */
2310 ushort_t length
; /* number of ports for this BAR */
2312 { 0x01, 0, 0x1f0, 8 }, /* primary lower BAR */
2313 { 0x01, 2, 0x3f6, 1 }, /* primary upper BAR */
2314 { 0x04, 0, 0x170, 8 }, /* secondary lower BAR */
2315 { 0x04, 2, 0x376, 1 } /* secondary upper BAR */
2319 pciIdeAdjustBAR(uchar_t progcl
, int index
, uint_t
*basep
, uint_t
*lenp
)
2321 int hard_decode
= 0;
2324 * Adjust the base and len for the BARs of the PCI-IDE
2325 * device's primary and secondary controllers. The first
2326 * two BARs are for the primary controller and the next
2327 * two BARs are for the secondary controller. The fifth
2328 * and sixth bars are never adjusted.
2330 if (index
>= 0 && index
<= 3) {
2331 *lenp
= pciide_bar
[index
].length
;
2333 if (progcl
& pciide_bar
[index
].native_mask
) {
2334 *basep
+= pciide_bar
[index
].bar_offset
;
2336 *basep
= pciide_bar
[index
].addr
;
2342 * if either base or len is zero make certain both are zero
2344 if (*basep
== 0 || *lenp
== 0) {
2350 return (hard_decode
);
2355 * Add the "reg" and "assigned-addresses" property
2358 add_reg_props(dev_info_t
*dip
, uchar_t bus
, uchar_t dev
, uchar_t func
,
2359 int config_op
, int pciide
)
2361 uchar_t baseclass
, subclass
, progclass
, header
;
2363 uint_t value
= 0, len
, devloc
;
2364 uint_t base
, base_hi
, type
;
2365 ushort_t offset
, end
;
2366 int max_basereg
, j
, reprogram
= 0;
2368 struct memlist
**io_avail
, **io_used
;
2369 struct memlist
**mem_avail
, **mem_used
;
2370 struct memlist
**pmem_avail
, **pmem_used
;
2373 pci_regspec_t regs
[16] = {{0}};
2374 pci_regspec_t assigned
[15] = {{0}};
2377 io_avail
= &pci_bus_res
[bus
].io_avail
;
2378 io_used
= &pci_bus_res
[bus
].io_used
;
2379 mem_avail
= &pci_bus_res
[bus
].mem_avail
;
2380 mem_used
= &pci_bus_res
[bus
].mem_used
;
2381 pmem_avail
= &pci_bus_res
[bus
].pmem_avail
;
2382 pmem_used
= &pci_bus_res
[bus
].pmem_used
;
2384 devloc
= (uint_t
)bus
<< 16 | (uint_t
)dev
<< 11 | (uint_t
)func
<< 8;
2385 regs
[0].pci_phys_hi
= devloc
;
2386 nreg
= 1; /* rest of regs[0] is all zero */
2389 baseclass
= pci_getb(bus
, dev
, func
, PCI_CONF_BASCLASS
);
2390 subclass
= pci_getb(bus
, dev
, func
, PCI_CONF_SUBCLASS
);
2391 progclass
= pci_getb(bus
, dev
, func
, PCI_CONF_PROGCLASS
);
2392 header
= pci_getb(bus
, dev
, func
, PCI_CONF_HEADER
) & PCI_HEADER_TYPE_M
;
2395 case PCI_HEADER_ZERO
:
2396 max_basereg
= PCI_BASE_NUM
;
2398 case PCI_HEADER_PPB
:
2399 max_basereg
= PCI_BCNF_BASE_NUM
;
2401 case PCI_HEADER_CARDBUS
:
2402 max_basereg
= PCI_CBUS_BASE_NUM
;
2411 * Create the register property by saving the current
2412 * value of the base register. Write 0xffffffff to the
2413 * base register. Read the value back to determine the
2414 * required size of the address space. Restore the base
2415 * register contents.
2417 * Do not disable I/O and memory access for bridges; this
2418 * has the side-effect of making the bridge transparent to
2419 * secondary-bus activity (see sections 4.1-4.3 of the
2420 * PCI-PCI Bridge Spec V1.2). For non-bridges, disable
2421 * I/O and memory access to avoid difficulty with USB
2422 * emulation (see OHCI spec1.0a appendix B
2423 * "Host Controller Mapping")
2425 end
= PCI_CONF_BASE0
+ max_basereg
* sizeof (uint_t
);
2426 for (j
= 0, offset
= PCI_CONF_BASE0
; offset
< end
;
2427 j
++, offset
+= bar_sz
) {
2430 /* determine the size of the address space */
2431 base
= pci_getl(bus
, dev
, func
, offset
);
2432 if (baseclass
!= PCI_CLASS_BRIDGE
) {
2433 command
= (uint_t
)pci_getw(bus
, dev
, func
,
2435 pci_putw(bus
, dev
, func
, PCI_CONF_COMM
,
2436 command
& ~(PCI_COMM_MAE
| PCI_COMM_IO
));
2438 pci_putl(bus
, dev
, func
, offset
, 0xffffffff);
2439 value
= pci_getl(bus
, dev
, func
, offset
);
2440 pci_putl(bus
, dev
, func
, offset
, base
);
2441 if (baseclass
!= PCI_CLASS_BRIDGE
)
2442 pci_putw(bus
, dev
, func
, PCI_CONF_COMM
, command
);
2444 /* construct phys hi,med.lo, size hi, lo */
2445 if ((pciide
&& j
< 4) || (base
& PCI_BASE_SPACE_IO
)) {
2446 int hard_decode
= 0;
2449 bar_sz
= PCI_BAR_SZ_32
;
2450 value
&= PCI_BASE_IO_ADDR_M
;
2451 len
= ((value
^ (value
-1)) + 1) >> 1;
2453 /* XXX Adjust first 4 IDE registers */
2455 if (subclass
!= PCI_MASS_IDE
)
2456 progclass
= (PCI_IDE_IF_NATIVE_PRI
|
2457 PCI_IDE_IF_NATIVE_SEC
);
2458 hard_decode
= pciIdeAdjustBAR(progclass
, j
,
2460 } else if (value
== 0) {
2461 /* skip base regs with size of 0 */
2465 regs
[nreg
].pci_phys_hi
= PCI_ADDR_IO
| devloc
|
2466 (hard_decode
? PCI_RELOCAT_B
: offset
);
2467 regs
[nreg
].pci_phys_low
= hard_decode
?
2468 base
& PCI_BASE_IO_ADDR_M
: 0;
2469 assigned
[nasgn
].pci_phys_hi
=
2470 PCI_RELOCAT_B
| regs
[nreg
].pci_phys_hi
;
2471 regs
[nreg
].pci_size_low
=
2472 assigned
[nasgn
].pci_size_low
= len
;
2473 type
= base
& (~PCI_BASE_IO_ADDR_M
);
2474 base
&= PCI_BASE_IO_ADDR_M
;
2476 * A device under a subtractive PPB can allocate
2477 * resources from its parent bus if there is no resource
2478 * available on its own bus.
2480 if ((config_op
== CONFIG_NEW
) && (*io_avail
== NULL
)) {
2482 while (pci_bus_res
[res_bus
].subtractive
) {
2483 res_bus
= pci_bus_res
[res_bus
].par_bus
;
2484 if (res_bus
== (uchar_t
)-1)
2485 break; /* root bus already */
2486 if (pci_bus_res
[res_bus
].io_avail
) {
2487 io_avail
= &pci_bus_res
2495 * first pass - gather what's there
2496 * update/second pass - adjust/allocate regions
2497 * config - allocate regions
2499 if (config_op
== CONFIG_INFO
) { /* first pass */
2500 /* take out of the resource map of the bus */
2502 (void) memlist_remove(io_avail
, base
,
2504 memlist_insert(io_used
, base
, len
);
2508 pci_bus_res
[bus
].io_size
+= len
;
2509 } else if ((*io_avail
&& base
== 0) ||
2510 pci_bus_res
[bus
].io_reprogram
) {
2511 base
= (uint_t
)memlist_find(io_avail
, len
, len
);
2513 memlist_insert(io_used
, base
, len
);
2514 /* XXX need to worry about 64-bit? */
2515 pci_putl(bus
, dev
, func
, offset
,
2517 base
= pci_getl(bus
, dev
, func
, offset
);
2518 base
&= PCI_BASE_IO_ADDR_M
;
2521 cmn_err(CE_WARN
, "failed to program"
2522 " IO space [%d/%d/%d] BAR@0x%x"
2524 bus
, dev
, func
, offset
, len
);
2527 assigned
[nasgn
].pci_phys_low
= base
;
2532 if ((base
& PCI_BASE_TYPE_M
) == PCI_BASE_TYPE_ALL
) {
2533 bar_sz
= PCI_BAR_SZ_64
;
2534 base_hi
= pci_getl(bus
, dev
, func
, offset
+ 4);
2535 phys_hi
= PCI_ADDR_MEM64
;
2537 bar_sz
= PCI_BAR_SZ_32
;
2539 phys_hi
= PCI_ADDR_MEM32
;
2542 /* skip base regs with size of 0 */
2543 value
&= PCI_BASE_M_ADDR_M
;
2548 len
= ((value
^ (value
-1)) + 1) >> 1;
2549 regs
[nreg
].pci_size_low
=
2550 assigned
[nasgn
].pci_size_low
= len
;
2552 phys_hi
|= (devloc
| offset
);
2553 if (base
& PCI_BASE_PREF_M
)
2554 phys_hi
|= PCI_PREFETCH_B
;
2557 * A device under a subtractive PPB can allocate
2558 * resources from its parent bus if there is no resource
2559 * available on its own bus.
2561 if ((config_op
== CONFIG_NEW
) && (*mem_avail
== NULL
)) {
2563 while (pci_bus_res
[res_bus
].subtractive
) {
2564 res_bus
= pci_bus_res
[res_bus
].par_bus
;
2565 if (res_bus
== (uchar_t
)-1)
2566 break; /* root bus already */
2568 &pci_bus_res
[res_bus
].mem_avail
;
2570 &pci_bus_res
[res_bus
].pmem_avail
;
2572 * Break out as long as at least
2573 * mem_avail is available
2576 (phys_hi
& PCI_PREFETCH_B
)) ||
2582 regs
[nreg
].pci_phys_hi
=
2583 assigned
[nasgn
].pci_phys_hi
= phys_hi
;
2584 assigned
[nasgn
].pci_phys_hi
|= PCI_RELOCAT_B
;
2585 assigned
[nasgn
].pci_phys_mid
= base_hi
;
2586 type
= base
& ~PCI_BASE_M_ADDR_M
;
2587 base
&= PCI_BASE_M_ADDR_M
;
2589 if (config_op
== CONFIG_INFO
) {
2590 /* take out of the resource map of the bus */
2592 /* remove from PMEM and MEM space */
2593 (void) memlist_remove(mem_avail
,
2595 (void) memlist_remove(pmem_avail
,
2597 /* only note as used in correct map */
2598 if (phys_hi
& PCI_PREFETCH_B
)
2599 memlist_insert(pmem_used
,
2602 memlist_insert(mem_used
,
2607 pci_bus_res
[bus
].mem_size
+= len
;
2608 } else if ((*mem_avail
&& base
== NULL
) ||
2609 pci_bus_res
[bus
].mem_reprogram
) {
2611 * When desired, attempt a prefetchable
2614 if (phys_hi
& PCI_PREFETCH_B
) {
2615 base
= (uint_t
)memlist_find(pmem_avail
,
2618 memlist_insert(pmem_used
,
2620 (void) memlist_remove(mem_avail
,
2625 * If prefetchable allocation was not
2626 * desired, or failed, attempt ordinary
2630 base
= (uint_t
)memlist_find(mem_avail
,
2633 memlist_insert(mem_used
,
2635 (void) memlist_remove(
2636 pmem_avail
, base
, len
);
2640 pci_putl(bus
, dev
, func
, offset
,
2642 base
= pci_getl(bus
, dev
, func
, offset
);
2643 base
&= PCI_BASE_M_ADDR_M
;
2645 cmn_err(CE_WARN
, "failed to program "
2646 "mem space [%d/%d/%d] BAR@0x%x"
2648 bus
, dev
, func
, offset
, len
);
2650 assigned
[nasgn
].pci_phys_low
= base
;
2655 case PCI_HEADER_ZERO
:
2656 offset
= PCI_CONF_ROM
;
2658 case PCI_HEADER_PPB
:
2659 offset
= PCI_BCNF_ROM
;
2661 default: /* including PCI_HEADER_CARDBUS */
2666 * Add the expansion rom memory space
2667 * Determine the size of the ROM base reg; don't write reserved bits
2668 * ROM isn't in the PCI memory space.
2670 base
= pci_getl(bus
, dev
, func
, offset
);
2671 pci_putl(bus
, dev
, func
, offset
, PCI_BASE_ROM_ADDR_M
);
2672 value
= pci_getl(bus
, dev
, func
, offset
);
2673 pci_putl(bus
, dev
, func
, offset
, base
);
2674 if (value
& PCI_BASE_ROM_ENABLE
)
2675 value
&= PCI_BASE_ROM_ADDR_M
;
2680 regs
[nreg
].pci_phys_hi
= (PCI_ADDR_MEM32
| devloc
) + offset
;
2681 assigned
[nasgn
].pci_phys_hi
= (PCI_RELOCAT_B
|
2682 PCI_ADDR_MEM32
| devloc
) + offset
;
2683 base
&= PCI_BASE_ROM_ADDR_M
;
2684 assigned
[nasgn
].pci_phys_low
= base
;
2685 len
= ((value
^ (value
-1)) + 1) >> 1;
2686 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= len
;
2688 /* take it out of the memory resource */
2690 (void) memlist_remove(mem_avail
, base
, len
);
2691 memlist_insert(mem_used
, base
, len
);
2692 pci_bus_res
[bus
].mem_size
+= len
;
2697 * Account for "legacy" (alias) video adapter resources
2700 /* add the three hard-decode, aliased address spaces for VGA */
2701 if ((baseclass
== PCI_CLASS_DISPLAY
&& subclass
== PCI_DISPLAY_VGA
) ||
2702 (baseclass
== PCI_CLASS_NONE
&& subclass
== PCI_NONE_VGA
)) {
2704 /* VGA hard decode 0x3b0-0x3bb */
2705 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2706 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2707 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x3b0;
2708 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0xc;
2710 (void) memlist_remove(io_avail
, 0x3b0, 0xc);
2711 memlist_insert(io_used
, 0x3b0, 0xc);
2712 pci_bus_res
[bus
].io_size
+= 0xc;
2714 /* VGA hard decode 0x3c0-0x3df */
2715 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2716 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2717 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x3c0;
2718 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0x20;
2720 (void) memlist_remove(io_avail
, 0x3c0, 0x20);
2721 memlist_insert(io_used
, 0x3c0, 0x20);
2722 pci_bus_res
[bus
].io_size
+= 0x20;
2725 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2726 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_MEM32
| devloc
);
2727 regs
[nreg
].pci_phys_low
=
2728 assigned
[nasgn
].pci_phys_low
= 0xa0000;
2729 regs
[nreg
].pci_size_low
=
2730 assigned
[nasgn
].pci_size_low
= 0x20000;
2732 /* remove from MEM and PMEM space */
2733 (void) memlist_remove(mem_avail
, 0xa0000, 0x20000);
2734 (void) memlist_remove(pmem_avail
, 0xa0000, 0x20000);
2735 memlist_insert(mem_used
, 0xa0000, 0x20000);
2736 pci_bus_res
[bus
].mem_size
+= 0x20000;
2739 /* add the hard-decode, aliased address spaces for 8514 */
2740 if ((baseclass
== PCI_CLASS_DISPLAY
) &&
2741 (subclass
== PCI_DISPLAY_VGA
) &&
2742 (progclass
& PCI_DISPLAY_IF_8514
)) {
2744 /* hard decode 0x2e8 */
2745 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2746 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2747 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x2e8;
2748 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0x1;
2750 (void) memlist_remove(io_avail
, 0x2e8, 0x1);
2751 memlist_insert(io_used
, 0x2e8, 0x1);
2752 pci_bus_res
[bus
].io_size
+= 0x1;
2754 /* hard decode 0x2ea-0x2ef */
2755 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2756 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2757 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x2ea;
2758 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0x6;
2760 (void) memlist_remove(io_avail
, 0x2ea, 0x6);
2761 memlist_insert(io_used
, 0x2ea, 0x6);
2762 pci_bus_res
[bus
].io_size
+= 0x6;
2766 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
, "reg",
2767 (int *)regs
, nreg
* sizeof (pci_regspec_t
) / sizeof (int));
2768 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
2769 "assigned-addresses",
2770 (int *)assigned
, nasgn
* sizeof (pci_regspec_t
) / sizeof (int));
2776 add_ppb_props(dev_info_t
*dip
, uchar_t bus
, uchar_t dev
, uchar_t func
,
2777 int pciex
, ushort_t is_pci_bridge
)
2782 uint64_t io_range
[2], mem_range
[2], pmem_range
[2];
2783 uchar_t secbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SECBUS
);
2784 uchar_t subbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SUBBUS
);
2787 ASSERT(secbus
<= subbus
);
2790 * Check if it's a subtractive PPB.
2792 progclass
= pci_getb(bus
, dev
, func
, PCI_CONF_PROGCLASS
);
2793 if (progclass
== PCI_BRIDGE_PCI_IF_SUBDECODE
)
2794 pci_bus_res
[secbus
].subtractive
= B_TRUE
;
2797 * Some BIOSes lie about max pci busses, we allow for
2798 * such mistakes here
2800 if (subbus
> pci_bios_maxbus
) {
2801 pci_bios_maxbus
= subbus
;
2805 ASSERT(pci_bus_res
[secbus
].dip
== NULL
);
2806 pci_bus_res
[secbus
].dip
= dip
;
2807 pci_bus_res
[secbus
].par_bus
= bus
;
2809 dev_type
= (pciex
&& !is_pci_bridge
) ? "pciex" : "pci";
2811 /* setup bus number hierarchy */
2812 pci_bus_res
[secbus
].sub_bus
= subbus
;
2814 * Keep track of the largest subordinate bus number (this is essential
2815 * for peer busses because there is no other way of determining its
2816 * subordinate bus number).
2818 if (subbus
> pci_bus_res
[bus
].sub_bus
)
2819 pci_bus_res
[bus
].sub_bus
= subbus
;
2821 * Loop through subordinate busses, initializing their parent bus
2822 * field to this bridge's parent. The subordinate busses' parent
2823 * fields may very well be further refined later, as child bridges
2824 * are enumerated. (The value is to note that the subordinate busses
2825 * are not peer busses by changing their par_bus fields to anything
2828 for (i
= secbus
+ 1; i
<= subbus
; i
++)
2829 pci_bus_res
[i
].par_bus
= bus
;
2831 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
2832 "device_type", dev_type
);
2833 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2834 "#address-cells", 3);
2835 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2839 * Collect bridge window specifications, and use them to populate
2840 * the "avail" resources for the bus. Not all of those resources will
2841 * end up being available; this is done top-down, and so the initial
2842 * collection of windows populates the 'ranges' property for the
2843 * bus node. Later, as children are found, resources are removed from
2844 * the 'avail' list, so that it becomes the freelist for
2845 * this point in the tree. ranges may be set again after bridge
2846 * reprogramming in fix_ppb_res(), in which case it's set from
2849 * According to PPB spec, the base register should be programmed
2850 * with a value bigger than the limit register when there are
2851 * no resources available. This applies to io, memory, and
2852 * prefetchable memory.
2857 * We determine i/o windows that are left unconfigured by BIOS
2858 * through its i/o enable bit as Microsoft recommends OEMs to do.
2859 * If it is unset, we disable i/o and mark it for reconfiguration in
2860 * later passes by setting the base > limit
2862 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_CONF_COMM
);
2863 if (val
& PCI_COMM_IO
) {
2864 val
= (uint_t
)pci_getb(bus
, dev
, func
, PCI_BCNF_IO_BASE_LOW
);
2865 io_range
[0] = ((val
& PCI_BCNF_IO_MASK
) << PCI_BCNF_IO_SHIFT
);
2866 val
= (uint_t
)pci_getb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_LOW
);
2867 io_range
[1] = ((val
& PCI_BCNF_IO_MASK
) << PCI_BCNF_IO_SHIFT
) |
2869 if ((io_range
[0] & PCI_BCNF_ADDR_MASK
) == PCI_BCNF_IO_32BIT
) {
2870 uint16_t io_base_hi
, io_limit_hi
;
2871 io_base_hi
= pci_getw(bus
, dev
, func
,
2872 PCI_BCNF_IO_BASE_HI
);
2873 io_limit_hi
= pci_getw(bus
, dev
, func
,
2874 PCI_BCNF_IO_LIMIT_HI
);
2876 io_range
[0] |= (uint32_t)io_base_hi
<< 16;
2877 io_range
[1] |= (uint32_t)io_limit_hi
<< 16;
2880 io_range
[0] = 0x9fff;
2881 io_range
[1] = 0x1000;
2882 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_BASE_LOW
,
2883 (uint8_t)((io_range
[0] >> 8) & 0xf0));
2884 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_LOW
,
2885 (uint8_t)((io_range
[1] >> 8) & 0xf0));
2886 pci_putw(bus
, dev
, func
, PCI_BCNF_IO_BASE_HI
, 0);
2887 pci_putw(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_HI
, 0);
2890 if (io_range
[0] != 0 && io_range
[0] < io_range
[1]) {
2891 memlist_insert(&pci_bus_res
[secbus
].io_avail
,
2892 io_range
[0], (io_range
[1] - io_range
[0] + 1));
2893 memlist_insert(&pci_bus_res
[bus
].io_used
,
2894 io_range
[0], (io_range
[1] - io_range
[0] + 1));
2895 if (pci_bus_res
[bus
].io_avail
!= NULL
) {
2896 (void) memlist_remove(&pci_bus_res
[bus
].io_avail
,
2897 io_range
[0], (io_range
[1] - io_range
[0] + 1));
2899 dcmn_err(CE_NOTE
, "bus %d io-range: 0x%" PRIx64
"-%" PRIx64
,
2900 secbus
, io_range
[0], io_range
[1]);
2904 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_BASE
);
2905 mem_range
[0] = ((val
& PCI_BCNF_MEM_MASK
) << PCI_BCNF_MEM_SHIFT
);
2906 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_LIMIT
);
2907 mem_range
[1] = ((val
& PCI_BCNF_MEM_MASK
) << PCI_BCNF_MEM_SHIFT
) |
2909 if (mem_range
[0] != 0 && mem_range
[0] < mem_range
[1]) {
2910 memlist_insert(&pci_bus_res
[secbus
].mem_avail
,
2911 (uint64_t)mem_range
[0],
2912 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2913 memlist_insert(&pci_bus_res
[bus
].mem_used
,
2914 (uint64_t)mem_range
[0],
2915 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2916 /* remove from parent resource list */
2917 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
,
2918 (uint64_t)mem_range
[0],
2919 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2920 (void) memlist_remove(&pci_bus_res
[bus
].pmem_avail
,
2921 (uint64_t)mem_range
[0],
2922 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2923 dcmn_err(CE_NOTE
, "bus %d mem-range: 0x%" PRIx64
"-%" PRIx64
,
2924 secbus
, mem_range
[0], mem_range
[1]);
2927 /* prefetchable memory range */
2928 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_PF_BASE_LOW
);
2929 pmem_range
[0] = ((val
& PCI_BCNF_MEM_MASK
) << PCI_BCNF_MEM_SHIFT
);
2930 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_PF_LIMIT_LOW
);
2931 pmem_range
[1] = ((val
& PCI_BCNF_MEM_MASK
) << PCI_BCNF_MEM_SHIFT
) |
2933 if ((pmem_range
[0] & PCI_BCNF_ADDR_MASK
) == PCI_BCNF_PF_MEM_64BIT
) {
2934 uint32_t pf_addr_hi
, pf_limit_hi
;
2935 pf_addr_hi
= pci_getl(bus
, dev
, func
, PCI_BCNF_PF_BASE_HIGH
);
2936 pf_limit_hi
= pci_getl(bus
, dev
, func
, PCI_BCNF_PF_LIMIT_HIGH
);
2937 pmem_range
[0] |= (uint64_t)pf_addr_hi
<< 32;
2938 pmem_range
[1] |= (uint64_t)pf_limit_hi
<< 32;
2940 if (pmem_range
[0] != 0 && pmem_range
[0] < pmem_range
[1]) {
2941 memlist_insert(&pci_bus_res
[secbus
].pmem_avail
,
2942 (uint64_t)pmem_range
[0],
2943 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2944 memlist_insert(&pci_bus_res
[bus
].pmem_used
,
2945 (uint64_t)pmem_range
[0],
2946 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2947 /* remove from parent resource list */
2948 (void) memlist_remove(&pci_bus_res
[bus
].pmem_avail
,
2949 (uint64_t)pmem_range
[0],
2950 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2951 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
,
2952 (uint64_t)pmem_range
[0],
2953 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2954 dcmn_err(CE_NOTE
, "bus %d pmem-range: 0x%" PRIx64
"-%" PRIx64
,
2955 secbus
, pmem_range
[0], pmem_range
[1]);
2959 * Add VGA legacy resources to the bridge's pci_bus_res if it
2960 * has VGA_ENABLE set. Note that we put them in 'avail',
2961 * because that's used to populate the ranges prop; they'll be
2962 * removed from there by the VGA device once it's found. Also,
2963 * remove them from the parent's available list and note them as
2964 * used in the parent.
2967 if (pci_getw(bus
, dev
, func
, PCI_BCNF_BCNTRL
) &
2968 PCI_BCNF_BCNTRL_VGA_ENABLE
) {
2970 memlist_insert(&pci_bus_res
[secbus
].io_avail
, 0x3b0, 0xc);
2972 memlist_insert(&pci_bus_res
[bus
].io_used
, 0x3b0, 0xc);
2973 if (pci_bus_res
[bus
].io_avail
!= NULL
) {
2974 (void) memlist_remove(&pci_bus_res
[bus
].io_avail
,
2978 memlist_insert(&pci_bus_res
[secbus
].io_avail
, 0x3c0, 0x20);
2980 memlist_insert(&pci_bus_res
[bus
].io_used
, 0x3c0, 0x20);
2981 if (pci_bus_res
[bus
].io_avail
!= NULL
) {
2982 (void) memlist_remove(&pci_bus_res
[bus
].io_avail
,
2986 memlist_insert(&pci_bus_res
[secbus
].mem_avail
, 0xa0000,
2989 memlist_insert(&pci_bus_res
[bus
].mem_used
, 0xa0000, 0x20000);
2990 if (pci_bus_res
[bus
].mem_avail
!= NULL
) {
2991 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
,
2995 add_bus_range_prop(secbus
);
2996 add_ranges_prop(secbus
, 1);
2999 extern const struct pci_class_strings_s class_pci
[];
3000 extern int class_pci_items
;
3003 add_model_prop(dev_info_t
*dip
, uint_t classcode
)
3007 uchar_t baseclass
= classcode
>> 16;
3008 uchar_t subclass
= (classcode
>> 8) & 0xff;
3009 uchar_t progclass
= classcode
& 0xff;
3011 if ((baseclass
== PCI_CLASS_MASS
) && (subclass
== PCI_MASS_IDE
)) {
3012 desc
= "IDE controller";
3014 for (desc
= 0, i
= 0; i
< class_pci_items
; i
++) {
3015 if ((baseclass
== class_pci
[i
].base_class
) &&
3016 (subclass
== class_pci
[i
].sub_class
) &&
3017 (progclass
== class_pci
[i
].prog_class
)) {
3018 desc
= class_pci
[i
].actual_desc
;
3022 if (i
== class_pci_items
)
3023 desc
= "Unknown class of pci/pnpbios device";
3026 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
, "model",
3031 add_bus_range_prop(int bus
)
3035 if (pci_bus_res
[bus
].dip
== NULL
)
3038 bus_range
[1] = pci_bus_res
[bus
].sub_bus
;
3039 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
3040 "bus-range", (int *)bus_range
, 2);
3044 * Add slot-names property for any named pci hot-plug slots
3047 add_bus_slot_names_prop(int bus
)
3051 extern int pci_irq_nroutes
;
3055 * If no irq routing table, then go with the slot-names as set up
3056 * in pciex_slot_names_prop() from slot capability register (if any).
3058 if (pci_irq_nroutes
== 0)
3062 * Otherise delete the slot-names we already have and use the irq
3063 * routing table values as returned by pci_slot_names_prop() instead,
3064 * but keep any property of value "pcie0" as that can't be represented
3065 * in the irq routing table.
3067 if (pci_bus_res
[bus
].dip
!= NULL
) {
3068 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, pci_bus_res
[bus
].dip
,
3069 DDI_PROP_DONTPASS
, "slot-names", &slotcap_name
) !=
3070 DDI_SUCCESS
|| strcmp(slotcap_name
, "pcie0") != 0)
3071 (void) ndi_prop_remove(DDI_DEV_T_NONE
,
3072 pci_bus_res
[bus
].dip
, "slot-names");
3075 len
= pci_slot_names_prop(bus
, slotprop
, sizeof (slotprop
));
3078 * Only create a peer bus node if this bus may be a peer bus.
3079 * It may be a peer bus if the dip is NULL and if par_bus is
3080 * -1 (par_bus is -1 if this bus was not found to be
3081 * subordinate to any PCI-PCI bridge).
3082 * If it's not a peer bus, then the ACPI BBN-handling code
3083 * will remove it later.
3085 if (pci_bus_res
[bus
].par_bus
== (uchar_t
)-1 &&
3086 pci_bus_res
[bus
].dip
== NULL
) {
3088 create_root_bus_dip(bus
);
3090 if (pci_bus_res
[bus
].dip
!= NULL
) {
3091 ASSERT((len
% sizeof (int)) == 0);
3092 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
,
3093 pci_bus_res
[bus
].dip
, "slot-names",
3094 (int *)slotprop
, len
/ sizeof (int));
3096 cmn_err(CE_NOTE
, "!BIOS BUG: Invalid bus number in PCI "
3097 "IRQ routing table; Not adding slot-names "
3098 "property for incorrect bus %d", bus
);
3104 * Handle both PCI root and PCI-PCI bridge range properties;
3105 * non-zero 'ppb' argument select PCI-PCI bridges versus root.
3108 memlist_to_ranges(void **rp
, struct memlist
*entry
, uint_t type
, int ppb
)
3110 ppb_ranges_t
*ppb_rp
= *rp
;
3111 pci_ranges_t
*pci_rp
= *rp
;
3113 while (entry
!= NULL
) {
3114 uint_t atype
= type
;
3115 if ((type
& PCI_REG_ADDR_M
) == PCI_ADDR_MEM32
&&
3116 (entry
->ml_address
>= UINT32_MAX
||
3117 entry
->ml_size
>= UINT32_MAX
)) {
3118 atype
&= ~PCI_ADDR_MEM32
;
3119 atype
|= PCI_ADDR_MEM64
;
3122 ppb_rp
->child_high
= ppb_rp
->parent_high
= atype
;
3123 ppb_rp
->child_mid
= ppb_rp
->parent_mid
=
3124 (uint32_t)(entry
->ml_address
>> 32);
3125 ppb_rp
->child_low
= ppb_rp
->parent_low
=
3126 (uint32_t)entry
->ml_address
;
3128 (uint32_t)(entry
->ml_size
>> 32);
3129 ppb_rp
->size_low
= (uint32_t)entry
->ml_size
;
3132 pci_rp
->child_high
= atype
;
3133 pci_rp
->child_mid
= pci_rp
->parent_high
=
3134 (uint32_t)(entry
->ml_address
>> 32);
3135 pci_rp
->child_low
= pci_rp
->parent_low
=
3136 (uint32_t)entry
->ml_address
;
3138 (uint32_t)(entry
->ml_size
>> 32);
3139 pci_rp
->size_low
= (uint32_t)entry
->ml_size
;
3142 entry
= entry
->ml_next
;
3147 add_ranges_prop(int bus
, int ppb
)
3149 int total
, alloc_size
;
3151 struct memlist
*iolist
, *memlist
, *pmemlist
;
3153 /* no devinfo node - unused bus, return */
3154 if (pci_bus_res
[bus
].dip
== NULL
)
3157 iolist
= memlist
= pmemlist
= (struct memlist
*)NULL
;
3159 memlist_merge(&pci_bus_res
[bus
].io_avail
, &iolist
);
3160 memlist_merge(&pci_bus_res
[bus
].io_used
, &iolist
);
3161 memlist_merge(&pci_bus_res
[bus
].mem_avail
, &memlist
);
3162 memlist_merge(&pci_bus_res
[bus
].mem_used
, &memlist
);
3163 memlist_merge(&pci_bus_res
[bus
].pmem_avail
, &pmemlist
);
3164 memlist_merge(&pci_bus_res
[bus
].pmem_used
, &pmemlist
);
3166 total
= memlist_count(iolist
);
3167 total
+= memlist_count(memlist
);
3168 total
+= memlist_count(pmemlist
);
3170 /* no property is created if no ranges are present */
3174 alloc_size
= total
*
3175 (ppb
? sizeof (ppb_ranges_t
) : sizeof (pci_ranges_t
));
3177 next_rp
= rp
= kmem_alloc(alloc_size
, KM_SLEEP
);
3179 memlist_to_ranges(&next_rp
, iolist
, PCI_ADDR_IO
| PCI_REG_REL_M
, ppb
);
3180 memlist_to_ranges(&next_rp
, memlist
,
3181 PCI_ADDR_MEM32
| PCI_REG_REL_M
, ppb
);
3182 memlist_to_ranges(&next_rp
, pmemlist
,
3183 PCI_ADDR_MEM32
| PCI_REG_REL_M
| PCI_REG_PF_M
, ppb
);
3185 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
3186 "ranges", (int *)rp
, alloc_size
/ sizeof (int));
3188 kmem_free(rp
, alloc_size
);
3189 memlist_free_all(&iolist
);
3190 memlist_free_all(&memlist
);
3191 memlist_free_all(&pmemlist
);
3195 memlist_remove_list(struct memlist
**list
, struct memlist
*remove_list
)
3197 while (list
&& *list
&& remove_list
) {
3198 (void) memlist_remove(list
, remove_list
->ml_address
,
3199 remove_list
->ml_size
);
3200 remove_list
= remove_list
->ml_next
;
3205 memlist_to_spec(struct pci_phys_spec
*sp
, struct memlist
*list
, int type
)
3210 /* assume 32-bit addresses */
3211 sp
->pci_phys_hi
= type
;
3212 sp
->pci_phys_mid
= 0;
3213 sp
->pci_phys_low
= (uint32_t)list
->ml_address
;
3214 sp
->pci_size_hi
= 0;
3215 sp
->pci_size_low
= (uint32_t)list
->ml_size
;
3217 list
= list
->ml_next
;
3224 add_bus_available_prop(int bus
)
3227 struct pci_phys_spec
*sp
;
3229 /* no devinfo node - unused bus, return */
3230 if (pci_bus_res
[bus
].dip
== NULL
)
3233 count
= memlist_count(pci_bus_res
[bus
].io_avail
) +
3234 memlist_count(pci_bus_res
[bus
].mem_avail
) +
3235 memlist_count(pci_bus_res
[bus
].pmem_avail
);
3237 if (count
== 0) /* nothing available */
3240 sp
= kmem_alloc(count
* sizeof (*sp
), KM_SLEEP
);
3241 i
= memlist_to_spec(&sp
[0], pci_bus_res
[bus
].io_avail
,
3242 PCI_ADDR_IO
| PCI_REG_REL_M
);
3243 i
+= memlist_to_spec(&sp
[i
], pci_bus_res
[bus
].mem_avail
,
3244 PCI_ADDR_MEM32
| PCI_REG_REL_M
);
3245 i
+= memlist_to_spec(&sp
[i
], pci_bus_res
[bus
].pmem_avail
,
3246 PCI_ADDR_MEM32
| PCI_REG_REL_M
| PCI_REG_PF_M
);
3249 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
3250 "available", (int *)sp
,
3251 i
* sizeof (struct pci_phys_spec
) / sizeof (int));
3252 kmem_free(sp
, count
* sizeof (*sp
));
3256 alloc_res_array(void)
3258 static int array_size
= 0;
3262 if (array_size
> pci_bios_maxbus
+ 1)
3263 return; /* array is big enough */
3265 old_size
= array_size
;
3266 old_res
= pci_bus_res
;
3268 if (array_size
== 0)
3269 array_size
= 16; /* start with a reasonable number */
3271 while (array_size
<= pci_bios_maxbus
+ 1)
3273 pci_bus_res
= (struct pci_bus_resource
*)kmem_zalloc(
3274 array_size
* sizeof (struct pci_bus_resource
), KM_SLEEP
);
3276 if (old_res
) { /* copy content and free old array */
3277 bcopy(old_res
, pci_bus_res
,
3278 old_size
* sizeof (struct pci_bus_resource
));
3279 kmem_free(old_res
, old_size
* sizeof (struct pci_bus_resource
));
3284 create_ioapic_node(int bus
, int dev
, int fn
, ushort_t vendorid
,
3287 static dev_info_t
*ioapicsnode
= NULL
;
3288 static int numioapics
= 0;
3289 dev_info_t
*ioapic_node
;
3291 uint32_t lobase
, hibase
= 0;
3293 /* BAR 0 contains the IOAPIC's memory-mapped I/O address */
3294 lobase
= (*pci_getl_func
)(bus
, dev
, fn
, PCI_CONF_BASE0
);
3296 /* We (and the rest of the world) only support memory-mapped IOAPICs */
3297 if ((lobase
& PCI_BASE_SPACE_M
) != PCI_BASE_SPACE_MEM
)
3300 if ((lobase
& PCI_BASE_TYPE_M
) == PCI_BASE_TYPE_ALL
)
3301 hibase
= (*pci_getl_func
)(bus
, dev
, fn
, PCI_CONF_BASE0
+ 4);
3303 lobase
&= PCI_BASE_M_ADDR_M
;
3305 physaddr
= (((uint64_t)hibase
) << 32) | lobase
;
3308 * Create a nexus node for all IOAPICs under the root node.
3310 if (ioapicsnode
== NULL
) {
3311 if (ndi_devi_alloc(ddi_root_node(), IOAPICS_NODE_NAME
,
3312 (pnode_t
)DEVI_SID_NODEID
, &ioapicsnode
) != NDI_SUCCESS
) {
3315 (void) ndi_devi_online(ioapicsnode
, 0);
3319 * Create a child node for this IOAPIC
3321 ioapic_node
= ddi_add_child(ioapicsnode
, IOAPICS_CHILD_NAME
,
3322 DEVI_SID_NODEID
, numioapics
++);
3323 if (ioapic_node
== NULL
) {
3327 /* Vendor and Device ID */
3328 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, ioapic_node
,
3329 IOAPICS_PROP_VENID
, vendorid
);
3330 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, ioapic_node
,
3331 IOAPICS_PROP_DEVID
, deviceid
);
3334 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, ioapic_node
,
3335 "device_type", IOAPICS_DEV_TYPE
);
3338 (void) ndi_prop_update_int64(DDI_DEV_T_NONE
, ioapic_node
,
3343 * NOTE: For PCIe slots, the name is generated from the slot number
3344 * information obtained from Slot Capabilities register.
3345 * For non-PCIe slots, it is generated based on the slot number
3346 * information in the PCI IRQ table.
3349 pciex_slot_names_prop(dev_info_t
*dip
, ushort_t slot_num
)
3354 bzero(slotprop
, sizeof (slotprop
));
3356 /* set mask to 1 as there is only one slot (i.e dev 0) */
3357 *(uint32_t *)slotprop
= 1;
3359 (void) snprintf(slotprop
+ len
, sizeof (slotprop
) - len
, "pcie%d",
3361 len
+= strlen(slotprop
+ len
) + 1;
3363 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
, "slot-names",
3364 (int *)slotprop
, len
/ sizeof (int));
3368 * Enable reporting of AER capability next pointer.
3369 * This needs to be done only for CK8-04 devices
3370 * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13
3371 * NOTE: BIOS is disabling this, it needs to be enabled temporarily
3373 * This function is adapted from npe_ck804_fix_aer_ptr(), and is
3374 * called from pci_boot.c.
3377 ck804_fix_aer_ptr(dev_info_t
*dip
, pcie_req_id_t bdf
)
3382 rcdip
= pcie_get_rc_dip(dip
);
3383 ASSERT(rcdip
!= NULL
);
3385 if ((pci_cfgacc_get16(rcdip
, bdf
, PCI_CONF_VENID
) ==
3386 NVIDIA_VENDOR_ID
) &&
3387 (pci_cfgacc_get16(rcdip
, bdf
, PCI_CONF_DEVID
) ==
3388 NVIDIA_CK804_DEVICE_ID
) &&
3389 (pci_cfgacc_get8(rcdip
, bdf
, PCI_CONF_REVID
) >=
3390 NVIDIA_CK804_AER_VALID_REVID
)) {
3391 cya1
= pci_cfgacc_get16(rcdip
, bdf
, NVIDIA_CK804_VEND_CYA1_OFF
);
3392 if (!(cya1
& ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK
))
3393 (void) pci_cfgacc_put16(rcdip
, bdf
,
3394 NVIDIA_CK804_VEND_CYA1_OFF
,
3395 cya1
| NVIDIA_CK804_VEND_CYA1_ERPT_VAL
);