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 2015 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
& 0xf0) << 8;
1086 io_limit
= ((io_limit
& 0xf0) << 8) | 0xfff;
1088 /* Form list of all resources passed (avail + used) */
1089 scratch_list
= memlist_dup(pci_bus_res
[secbus
].io_avail
);
1090 memlist_merge(&pci_bus_res
[secbus
].io_used
, &scratch_list
);
1092 if ((pci_bus_res
[parbus
].io_reprogram
||
1093 (io_base
> io_limit
) ||
1094 (!(cmd_reg
& PCI_COMM_IO
))) &&
1095 !list_is_vga_only(scratch_list
, IO
)) {
1096 if (pci_bus_res
[secbus
].io_used
) {
1097 memlist_subsume(&pci_bus_res
[secbus
].io_used
,
1098 &pci_bus_res
[secbus
].io_avail
);
1100 if (pci_bus_res
[secbus
].io_avail
&&
1101 (!pci_bus_res
[parbus
].io_reprogram
) &&
1102 (!pci_bus_res
[parbus
].subtractive
)) {
1103 /* rechoose old io ports info */
1104 list
= pci_bus_res
[secbus
].io_avail
;
1107 if (is_vga(list
, IO
))
1110 io_base
= (uint_t
)list
->ml_address
;
1111 io_limit
= (uint_t
)list
->ml_address
+
1114 P2ALIGN(io_base
, PPB_IO_ALIGNMENT
);
1116 if (list
->ml_address
+ list
->ml_size
>
1123 } while ((list
= list
->ml_next
) != NULL
);
1125 io_limit
= P2ROUNDUP(io_limit
, PPB_IO_ALIGNMENT
) - 1;
1126 io_size
= io_limit
- io_base
+ 1;
1127 ASSERT(io_base
<= io_limit
);
1128 memlist_free_all(&pci_bus_res
[secbus
].io_avail
);
1129 memlist_insert(&pci_bus_res
[secbus
].io_avail
,
1131 memlist_insert(&pci_bus_res
[parbus
].io_used
,
1133 (void) memlist_remove(&pci_bus_res
[parbus
].io_avail
,
1135 pci_bus_res
[secbus
].io_reprogram
= B_TRUE
;
1137 /* get new io ports from parent bus */
1138 addr
= get_parbus_io_res(parbus
, secbus
, io_size
,
1142 io_limit
= addr
+ io_size
- 1;
1143 pci_bus_res
[secbus
].io_reprogram
= B_TRUE
;
1146 if (pci_bus_res
[secbus
].io_reprogram
) {
1147 /* reprogram PPB regs */
1148 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_BASE_LOW
,
1149 (uchar_t
)((io_base
>>8) & 0xf0));
1150 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_LOW
,
1151 (uchar_t
)((io_limit
>>8) & 0xf0));
1152 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_BASE_HI
, 0);
1153 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_HI
, 0);
1154 add_ranges_prop(secbus
, 1);
1156 cmn_err(CE_NOTE
, "!reprogram io-range on"
1157 " ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
1158 bus
, dev
, func
, io_base
, io_limit
);
1161 memlist_free_all(&scratch_list
);
1164 * Check memory space as we did I/O space.
1166 mem_base
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_BASE
);
1167 mem_base
= (mem_base
& 0xfff0) << 16;
1168 mem_limit
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_LIMIT
);
1169 mem_limit
= ((mem_limit
& 0xfff0) << 16) | 0xfffff;
1171 scratch_list
= memlist_dup(pci_bus_res
[secbus
].mem_avail
);
1172 memlist_merge(&pci_bus_res
[secbus
].mem_used
, &scratch_list
);
1174 if ((pci_bus_res
[parbus
].mem_reprogram
||
1175 (mem_base
> mem_limit
) ||
1176 (!(cmd_reg
& PCI_COMM_MAE
))) &&
1177 !list_is_vga_only(scratch_list
, MEM
)) {
1178 if (pci_bus_res
[secbus
].mem_used
) {
1179 memlist_subsume(&pci_bus_res
[secbus
].mem_used
,
1180 &pci_bus_res
[secbus
].mem_avail
);
1182 if (pci_bus_res
[secbus
].mem_avail
&&
1183 (!pci_bus_res
[parbus
].mem_reprogram
) &&
1184 (!pci_bus_res
[parbus
].subtractive
)) {
1185 /* rechoose old mem resource */
1186 list
= pci_bus_res
[secbus
].mem_avail
;
1189 if (is_vga(list
, MEM
))
1191 if (mem_base
== 0) {
1192 mem_base
= (uint_t
)list
->ml_address
;
1193 mem_base
= P2ALIGN(mem_base
,
1195 mem_limit
= (uint_t
)(list
->ml_address
+
1198 if ((list
->ml_address
+ list
->ml_size
) >
1200 mem_limit
= (uint_t
)
1205 } while ((list
= list
->ml_next
) != NULL
);
1206 mem_limit
= P2ROUNDUP(mem_limit
, PPB_MEM_ALIGNMENT
) - 1;
1207 mem_size
= mem_limit
+ 1 - mem_base
;
1208 ASSERT(mem_base
<= mem_limit
);
1209 memlist_free_all(&pci_bus_res
[secbus
].mem_avail
);
1210 memlist_insert(&pci_bus_res
[secbus
].mem_avail
,
1211 mem_base
, mem_size
);
1212 memlist_insert(&pci_bus_res
[parbus
].mem_used
,
1213 mem_base
, mem_size
);
1214 (void) memlist_remove(&pci_bus_res
[parbus
].mem_avail
,
1215 mem_base
, mem_size
);
1216 pci_bus_res
[secbus
].mem_reprogram
= B_TRUE
;
1218 /* get new mem resource from parent bus */
1219 addr
= get_parbus_mem_res(parbus
, secbus
, mem_size
,
1223 mem_limit
= addr
+ mem_size
- 1;
1224 pci_bus_res
[secbus
].mem_reprogram
= B_TRUE
;
1228 if (pci_bus_res
[secbus
].mem_reprogram
) {
1229 /* reprogram PPB MEM regs */
1230 pci_putw(bus
, dev
, func
, PCI_BCNF_MEM_BASE
,
1231 (uint16_t)((mem_base
>>16) & 0xfff0));
1232 pci_putw(bus
, dev
, func
, PCI_BCNF_MEM_LIMIT
,
1233 (uint16_t)((mem_limit
>>16) & 0xfff0));
1235 * Disable PMEM window by setting base > limit.
1236 * We currently don't reprogram the PMEM like we've
1237 * done for I/O and MEM. (Devices that support prefetch
1238 * can use non-prefetch MEM.) Anyway, if the MEM access
1239 * bit is initially disabled by BIOS, we disable the
1240 * PMEM window manually by setting PMEM base > PMEM
1241 * limit here, in case there are incorrect values in
1242 * them from BIOS, so that we won't get in trouble once
1243 * the MEM access bit is enabled at the end of this
1246 if (!(cmd_reg
& PCI_COMM_MAE
)) {
1247 pci_putw(bus
, dev
, func
, PCI_BCNF_PF_BASE_LOW
,
1249 pci_putw(bus
, dev
, func
, PCI_BCNF_PF_LIMIT_LOW
,
1251 pci_putl(bus
, dev
, func
, PCI_BCNF_PF_BASE_HIGH
,
1253 pci_putl(bus
, dev
, func
, PCI_BCNF_PF_LIMIT_HIGH
,
1257 add_ranges_prop(secbus
, 1);
1259 cmn_err(CE_NOTE
, "!reprogram mem-range on"
1260 " ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
1261 bus
, dev
, func
, mem_base
, mem_limit
);
1264 memlist_free_all(&scratch_list
);
1267 if (pci_bus_res
[secbus
].io_avail
)
1268 cmd_reg
|= PCI_COMM_IO
| PCI_COMM_ME
;
1269 if (pci_bus_res
[secbus
].mem_avail
)
1270 cmd_reg
|= PCI_COMM_MAE
| PCI_COMM_ME
;
1271 pci_putw(bus
, dev
, func
, PCI_CONF_COMM
, cmd_reg
);
1277 int i
, pci_reconfig
= 1;
1282 * Scan ACPI namespace for _BBN objects, make sure that
1283 * childless root-bridges appear in devinfo tree
1286 pci_unitaddr_cache_init();
1289 * Fix-up unit-address assignments if cache is available
1291 if (pci_unitaddr_cache_valid()) {
1292 int pci_regs
[] = {0, 0, 0};
1296 for (bus
= 0; bus
<= pci_bios_maxbus
; bus
++) {
1297 /* skip non-root (peer) PCI busses */
1298 if ((pci_bus_res
[bus
].par_bus
!= (uchar_t
)-1) ||
1299 (pci_bus_res
[bus
].dip
== NULL
))
1302 new_addr
= pci_bus_unitaddr(index
);
1303 if (pci_bus_res
[bus
].root_addr
!= new_addr
) {
1304 /* update reg property for node */
1305 pci_regs
[0] = pci_bus_res
[bus
].root_addr
=
1307 (void) ndi_prop_update_int_array(
1308 DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
1309 "reg", (int *)pci_regs
, 3);
1314 /* perform legacy processing */
1315 pci_renumber_root_busses();
1316 pci_unitaddr_cache_create();
1320 * Do root-bus resource discovery
1322 for (bus
= 0; bus
<= pci_bios_maxbus
; bus
++) {
1323 /* skip non-root (peer) PCI busses */
1324 if (pci_bus_res
[bus
].par_bus
!= (uchar_t
)-1)
1328 * 1. find resources associated with this root bus
1330 populate_bus_res(bus
);
1334 * 2. Remove used PCI and ISA resources from bus resource map
1337 memlist_remove_list(&pci_bus_res
[bus
].io_avail
,
1338 pci_bus_res
[bus
].io_used
);
1339 memlist_remove_list(&pci_bus_res
[bus
].mem_avail
,
1340 pci_bus_res
[bus
].mem_used
);
1341 memlist_remove_list(&pci_bus_res
[bus
].pmem_avail
,
1342 pci_bus_res
[bus
].pmem_used
);
1343 memlist_remove_list(&pci_bus_res
[bus
].mem_avail
,
1344 pci_bus_res
[bus
].pmem_used
);
1345 memlist_remove_list(&pci_bus_res
[bus
].pmem_avail
,
1346 pci_bus_res
[bus
].mem_used
);
1348 memlist_remove_list(&pci_bus_res
[bus
].io_avail
,
1350 memlist_remove_list(&pci_bus_res
[bus
].mem_avail
,
1354 * 3. Exclude <1M address range here in case below reserved
1355 * ranges for BIOS data area, ROM area etc are wrongly reported
1356 * in ACPI resource producer entries for PCI root bus.
1357 * 00000000 - 000003FF RAM
1358 * 00000400 - 000004FF BIOS data area
1359 * 00000500 - 0009FFFF RAM
1360 * 000A0000 - 000BFFFF VGA RAM
1361 * 000C0000 - 000FFFFF ROM area
1363 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
, 0, 0x100000);
1364 (void) memlist_remove(&pci_bus_res
[bus
].pmem_avail
,
1368 memlist_free_all(&isa_res
.io_used
);
1369 memlist_free_all(&isa_res
.mem_used
);
1371 /* add bus-range property for root/peer bus nodes */
1372 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
1373 /* create bus-range property on root/peer buses */
1374 if (pci_bus_res
[i
].par_bus
== (uchar_t
)-1)
1375 add_bus_range_prop(i
);
1377 /* setup bus range resource on each bus */
1381 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, ddi_root_node(),
1382 DDI_PROP_DONTPASS
, "pci-reprog", &onoff
) == DDI_SUCCESS
) {
1383 if (strcmp(onoff
, "off") == 0) {
1385 cmn_err(CE_NOTE
, "pci device reprogramming disabled");
1387 ddi_prop_free(onoff
);
1390 remove_subtractive_res();
1392 /* reprogram the non-subtractive PPB */
1394 for (i
= 0; i
<= pci_bios_maxbus
; i
++)
1395 fix_ppb_res(i
, B_FALSE
);
1397 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
1398 /* configure devices not configured by BIOS */
1401 * Reprogram the subtractive PPB. At this time, all its
1402 * siblings should have got their resources already.
1404 if (pci_bus_res
[i
].subtractive
)
1405 fix_ppb_res(i
, B_TRUE
);
1406 enumerate_bus_devs(i
, CONFIG_NEW
);
1410 /* All dev programmed, so we can create available prop */
1411 for (i
= 0; i
<= pci_bios_maxbus
; i
++)
1412 add_bus_available_prop(i
);
1416 * populate bus resources
1419 populate_bus_res(uchar_t bus
)
1422 /* scan BIOS structures */
1423 pci_bus_res
[bus
].pmem_avail
= find_bus_res(bus
, PREFETCH_TYPE
);
1424 pci_bus_res
[bus
].mem_avail
= find_bus_res(bus
, MEM_TYPE
);
1425 pci_bus_res
[bus
].io_avail
= find_bus_res(bus
, IO_TYPE
);
1426 pci_bus_res
[bus
].bus_avail
= find_bus_res(bus
, BUSRANGE_TYPE
);
1429 * attempt to initialize sub_bus from the largest range-end
1430 * in the bus_avail list
1432 if (pci_bus_res
[bus
].bus_avail
!= NULL
) {
1433 struct memlist
*entry
;
1436 entry
= pci_bus_res
[bus
].bus_avail
;
1437 while (entry
!= NULL
) {
1438 current
= entry
->ml_address
+ entry
->ml_size
- 1;
1439 if (current
> pci_bus_res
[bus
].sub_bus
)
1440 pci_bus_res
[bus
].sub_bus
= current
;
1441 entry
= entry
->ml_next
;
1447 * Special treatment of bus 0:
1448 * If no IO/MEM resource from ACPI/MPSPEC/HRT, copy
1449 * pcimem from boot and make I/O space the entire range
1450 * starting at 0x100.
1452 if (pci_bus_res
[0].mem_avail
== NULL
)
1453 pci_bus_res
[0].mem_avail
=
1454 memlist_dup(bootops
->boot_mem
->pcimem
);
1455 /* Exclude 0x00 to 0xff of the I/O space, used by all PCs */
1456 if (pci_bus_res
[0].io_avail
== NULL
)
1457 memlist_insert(&pci_bus_res
[0].io_avail
, 0x100, 0xffff);
1461 * Create 'ranges' property here before any resources are
1462 * removed from the resource lists
1464 add_ranges_prop(bus
, 0);
1469 * Create top-level bus dips, i.e. /pci@0,0, /pci@1,0...
1472 create_root_bus_dip(uchar_t bus
)
1474 int pci_regs
[] = {0, 0, 0};
1477 ASSERT(pci_bus_res
[bus
].par_bus
== (uchar_t
)-1);
1480 ndi_devi_alloc_sleep(ddi_root_node(), "pci",
1481 (pnode_t
)DEVI_SID_NODEID
, &dip
);
1482 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1483 "#address-cells", 3);
1484 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1486 pci_regs
[0] = pci_bus_res
[bus
].root_addr
;
1487 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
1488 "reg", (int *)pci_regs
, 3);
1491 * If system has PCIe bus, then create different properties
1493 if (create_pcie_root_bus(bus
, dip
) == B_FALSE
)
1494 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
1495 "device_type", "pci");
1497 (void) ndi_devi_bind_driver(dip
, 0);
1498 pci_bus_res
[bus
].dip
= dip
;
1502 * For any fixed configuration (often compatability) pci devices
1503 * and those with their own expansion rom, create device nodes
1504 * to hold the already configured device details.
1507 enumerate_bus_devs(uchar_t bus
, int config_op
)
1509 uchar_t dev
, func
, nfunc
, header
;
1511 struct pci_devfunc
*devlist
= NULL
, *entry
;
1513 if (config_op
== CONFIG_NEW
) {
1514 dcmn_err(CE_NOTE
, "configuring pci bus 0x%x", bus
);
1515 } else if (config_op
== CONFIG_FIX
) {
1516 dcmn_err(CE_NOTE
, "fixing devices on pci bus 0x%x", bus
);
1518 dcmn_err(CE_NOTE
, "enumerating pci bus 0x%x", bus
);
1520 if (config_op
== CONFIG_NEW
) {
1521 devlist
= (struct pci_devfunc
*)pci_bus_res
[bus
].privdata
;
1524 devlist
= entry
->next
;
1525 if (entry
->reprogram
||
1526 pci_bus_res
[bus
].io_reprogram
||
1527 pci_bus_res
[bus
].mem_reprogram
) {
1528 /* reprogram device(s) */
1529 (void) add_reg_props(entry
->dip
, bus
,
1530 entry
->dev
, entry
->func
, CONFIG_NEW
, 0);
1532 kmem_free(entry
, sizeof (*entry
));
1534 pci_bus_res
[bus
].privdata
= NULL
;
1538 for (dev
= 0; dev
< max_dev_pci
; dev
++) {
1540 for (func
= 0; func
< nfunc
; func
++) {
1542 dcmn_err(CE_NOTE
, "probing dev 0x%x, func 0x%x",
1545 venid
= pci_getw(bus
, dev
, func
, PCI_CONF_VENID
);
1547 if ((venid
== 0xffff) || (venid
== 0)) {
1548 /* no function at this address */
1552 header
= pci_getb(bus
, dev
, func
, PCI_CONF_HEADER
);
1553 if (header
== 0xff) {
1554 continue; /* illegal value */
1558 * according to some mail from Microsoft posted
1559 * to the pci-drivers alias, their only requirement
1560 * for a multifunction device is for the 1st
1561 * function to have to PCI_HEADER_MULTI bit set.
1563 if ((func
== 0) && (header
& PCI_HEADER_MULTI
)) {
1567 if (config_op
== CONFIG_FIX
||
1568 config_op
== CONFIG_INFO
) {
1570 * Create the node, unconditionally, on the
1571 * first pass only. It may still need
1572 * resource assignment, which will be
1573 * done on the second, CONFIG_NEW, pass.
1575 process_devfunc(bus
, dev
, func
, header
,
1582 /* percolate bus used resources up through parents to root */
1583 if (config_op
== CONFIG_INFO
) {
1586 par_bus
= pci_bus_res
[bus
].par_bus
;
1587 while (par_bus
!= (uchar_t
)-1) {
1588 pci_bus_res
[par_bus
].io_size
+=
1589 pci_bus_res
[bus
].io_size
;
1590 pci_bus_res
[par_bus
].mem_size
+=
1591 pci_bus_res
[bus
].mem_size
;
1593 if (pci_bus_res
[bus
].io_used
)
1594 memlist_merge(&pci_bus_res
[bus
].io_used
,
1595 &pci_bus_res
[par_bus
].io_used
);
1597 if (pci_bus_res
[bus
].mem_used
)
1598 memlist_merge(&pci_bus_res
[bus
].mem_used
,
1599 &pci_bus_res
[par_bus
].mem_used
);
1601 if (pci_bus_res
[bus
].pmem_used
)
1602 memlist_merge(&pci_bus_res
[bus
].pmem_used
,
1603 &pci_bus_res
[par_bus
].pmem_used
);
1606 par_bus
= pci_bus_res
[par_bus
].par_bus
;
1612 check_pciide_prop(uchar_t revid
, ushort_t venid
, ushort_t devid
,
1613 ushort_t subvenid
, ushort_t subdevid
)
1615 static int prop_exist
= -1;
1616 static char *pciide_str
;
1619 if (prop_exist
== -1) {
1620 prop_exist
= (ddi_prop_lookup_string(DDI_DEV_T_ANY
,
1621 ddi_root_node(), DDI_PROP_DONTPASS
, "pci-ide",
1622 &pciide_str
) == DDI_SUCCESS
);
1628 /* compare property value against various forms of compatible */
1630 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x.%x.%x.%x",
1631 venid
, devid
, subvenid
, subdevid
, revid
);
1632 if (strcmp(pciide_str
, compat
) == 0)
1635 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x.%x.%x",
1636 venid
, devid
, subvenid
, subdevid
);
1637 if (strcmp(pciide_str
, compat
) == 0)
1640 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x",
1641 subvenid
, subdevid
);
1642 if (strcmp(pciide_str
, compat
) == 0)
1645 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x.%x",
1646 venid
, devid
, revid
);
1647 if (strcmp(pciide_str
, compat
) == 0)
1650 (void) snprintf(compat
, sizeof (compat
), "pci%x,%x", venid
, devid
);
1651 if (strcmp(pciide_str
, compat
) == 0)
1658 is_pciide(uchar_t basecl
, uchar_t subcl
, uchar_t revid
,
1659 ushort_t venid
, ushort_t devid
, ushort_t subvenid
, ushort_t subdevid
)
1661 struct ide_table
{ /* table for PCI_MASS_OTHER */
1666 /* XXX SATA and other devices: need a way to add dynamically */
1667 static struct ide_table ide_other
[] = {
1671 {0x1095, 0x680}, /* Sil0680 */
1672 {0x1283, 0x8211}, /* ITE 8211F is subcl PCI_MASS_OTHER */
1676 if (basecl
!= PCI_CLASS_MASS
)
1679 if (subcl
== PCI_MASS_IDE
) {
1683 if (check_pciide_prop(revid
, venid
, devid
, subvenid
, subdevid
))
1686 if (subcl
!= PCI_MASS_OTHER
&& subcl
!= PCI_MASS_SATA
) {
1690 entry
= &ide_other
[0];
1691 while (entry
->venid
) {
1692 if (entry
->venid
== venid
&& entry
->devid
== devid
)
1700 is_display(uint_t classcode
)
1702 static uint_t disp_classes
[] = {
1707 int i
, nclasses
= sizeof (disp_classes
) / sizeof (uint_t
);
1709 for (i
= 0; i
< nclasses
; i
++) {
1710 if (classcode
== disp_classes
[i
])
1717 add_undofix_entry(uint8_t bus
, uint8_t dev
, uint8_t fn
,
1718 void (*undofn
)(uint8_t, uint8_t, uint8_t))
1720 struct pci_fixundo
*newundo
;
1722 newundo
= kmem_alloc(sizeof (struct pci_fixundo
), KM_SLEEP
);
1725 * Adding an item to this list means that we must turn its NMIENABLE
1726 * bit back on at a later time.
1731 newundo
->undofn
= undofn
;
1732 newundo
->next
= undolist
;
1734 /* add to the undo list in LIFO order */
1743 for (i
= 0; i
<= pci_bios_maxbus
; i
++) {
1745 * For each bus, apply needed fixes to the appropriate devices.
1746 * This must be done before the main enumeration loop because
1747 * some fixes must be applied to devices normally encountered
1748 * later in the pci scan (e.g. if a fix to device 7 must be
1749 * applied before scanning device 6, applying fixes in the
1750 * normal enumeration loop would obviously be too late).
1752 enumerate_bus_devs(i
, CONFIG_FIX
);
1757 undo_pci_fixes(void)
1759 struct pci_fixundo
*nextundo
;
1760 uint8_t bus
, dev
, fn
;
1763 * All fixes in the undo list are performed unconditionally. Future
1764 * fixes may require selective undo.
1766 while (undolist
!= NULL
) {
1768 bus
= undolist
->bus
;
1769 dev
= undolist
->dev
;
1772 (*(undolist
->undofn
))(bus
, dev
, fn
);
1774 nextundo
= undolist
->next
;
1775 kmem_free(undolist
, sizeof (struct pci_fixundo
));
1776 undolist
= nextundo
;
1781 undo_amd8111_pci_fix(uint8_t bus
, uint8_t dev
, uint8_t fn
)
1785 val8
= pci_getb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
);
1787 * The NMIONERR bit is turned back on to allow the SMM BIOS
1788 * to handle more critical PCI errors (e.g. PERR#).
1790 val8
|= AMD8111_ENABLENMI
;
1791 pci_putb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
, val8
);
1795 pci_fix_amd8111(uint8_t bus
, uint8_t dev
, uint8_t fn
)
1799 val8
= pci_getb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
);
1801 if ((val8
& AMD8111_ENABLENMI
) == 0)
1805 * We reset NMIONERR in the LPC because master-abort on the PCI
1806 * bridge side of the 8111 will cause NMI, which might cause SMI,
1807 * which sometimes prevents all devices from being enumerated.
1809 val8
&= ~AMD8111_ENABLENMI
;
1811 pci_putb(bus
, dev
, fn
, LPC_IO_CONTROL_REG_1
, val8
);
1813 add_undofix_entry(bus
, dev
, fn
, undo_amd8111_pci_fix
);
1817 set_devpm_d0(uchar_t bus
, uchar_t dev
, uchar_t func
)
1825 status
= pci_getw(bus
, dev
, func
, PCI_CONF_STAT
);
1826 if (!(status
& PCI_STAT_CAP
))
1827 return; /* No capabilities list */
1829 header
= pci_getb(bus
, dev
, func
, PCI_CONF_HEADER
) & PCI_HEADER_TYPE_M
;
1830 if (header
== PCI_HEADER_CARDBUS
)
1831 cap_ptr
= pci_getb(bus
, dev
, func
, PCI_CBUS_CAP_PTR
);
1833 cap_ptr
= pci_getb(bus
, dev
, func
, PCI_CONF_CAP_PTR
);
1835 * Walk the capabilities list searching for a PM entry.
1837 while (cap_ptr
!= PCI_CAP_NEXT_PTR_NULL
&& cap_ptr
>= PCI_CAP_PTR_OFF
) {
1838 cap_ptr
&= PCI_CAP_PTR_MASK
;
1839 cap_id
= pci_getb(bus
, dev
, func
, cap_ptr
+ PCI_CAP_ID
);
1840 if (cap_id
== PCI_CAP_ID_PM
) {
1841 pmcsr
= pci_getw(bus
, dev
, func
, cap_ptr
+ PCI_PMCSR
);
1842 pmcsr
&= ~(PCI_PMCSR_STATE_MASK
);
1843 pmcsr
|= PCI_PMCSR_D0
; /* D0 state */
1844 pci_putw(bus
, dev
, func
, cap_ptr
+ PCI_PMCSR
, pmcsr
);
1847 cap_ptr
= pci_getb(bus
, dev
, func
, cap_ptr
+ PCI_CAP_NEXT_PTR
);
1852 #define is_isa(bc, sc) \
1853 (((bc) == PCI_CLASS_BRIDGE) && ((sc) == PCI_BRIDGE_ISA))
1856 process_devfunc(uchar_t bus
, uchar_t dev
, uchar_t func
, uchar_t header
,
1857 ushort_t vendorid
, int config_op
)
1859 char nodename
[32], unitaddr
[5];
1861 uchar_t basecl
, subcl
, progcl
, intr
, revid
;
1862 ushort_t subvenid
, subdevid
, status
;
1864 uint_t classcode
, revclass
;
1865 int reprogram
= 0, pciide
= 0;
1866 int power
[2] = {1, 1};
1868 ushort_t is_pci_bridge
= 0;
1869 struct pci_devfunc
*devlist
= NULL
, *entry
= NULL
;
1870 boolean_t slot_valid
;
1874 ushort_t deviceid
= pci_getw(bus
, dev
, func
, PCI_CONF_DEVID
);
1876 switch (header
& PCI_HEADER_TYPE_M
) {
1877 case PCI_HEADER_ZERO
:
1878 subvenid
= pci_getw(bus
, dev
, func
, PCI_CONF_SUBVENID
);
1879 subdevid
= pci_getw(bus
, dev
, func
, PCI_CONF_SUBSYSID
);
1881 case PCI_HEADER_CARDBUS
:
1882 subvenid
= pci_getw(bus
, dev
, func
, PCI_CBUS_SUBVENID
);
1883 subdevid
= pci_getw(bus
, dev
, func
, PCI_CBUS_SUBSYSID
);
1884 /* Record the # of cardbus bridges found on the bus */
1885 if (config_op
== CONFIG_INFO
)
1886 pci_bus_res
[bus
].num_cbb
++;
1894 if (config_op
== CONFIG_FIX
) {
1895 if (vendorid
== VENID_AMD
&& deviceid
== DEVID_AMD8111_LPC
) {
1896 pci_fix_amd8111(bus
, dev
, func
);
1901 /* XXX should be use generic names? derive from class? */
1902 revclass
= pci_getl(bus
, dev
, func
, PCI_CONF_REVID
);
1903 classcode
= revclass
>> 8;
1904 revid
= revclass
& 0xff;
1906 /* figure out if this is pci-ide */
1907 basecl
= classcode
>> 16;
1908 subcl
= (classcode
>> 8) & 0xff;
1909 progcl
= classcode
& 0xff;
1912 if (is_display(classcode
))
1913 (void) snprintf(nodename
, sizeof (nodename
), "display");
1914 else if (!pseudo_isa
&& is_isa(basecl
, subcl
))
1915 (void) snprintf(nodename
, sizeof (nodename
), "isa");
1916 else if (subvenid
!= 0)
1917 (void) snprintf(nodename
, sizeof (nodename
),
1918 "pci%x,%x", subvenid
, subdevid
);
1920 (void) snprintf(nodename
, sizeof (nodename
),
1921 "pci%x,%x", vendorid
, deviceid
);
1923 /* make sure parent bus dip has been created */
1924 if (pci_bus_res
[bus
].dip
== NULL
)
1925 create_root_bus_dip(bus
);
1927 ndi_devi_alloc_sleep(pci_bus_res
[bus
].dip
, nodename
,
1928 DEVI_SID_NODEID
, &dip
);
1930 if (check_if_device_is_pciex(dip
, bus
, dev
, func
, &slot_valid
,
1931 &slot_num
, &is_pci_bridge
) == B_TRUE
)
1934 bdf
= PCI_GETBDF(bus
, dev
, func
);
1936 * Record BAD AMD bridges which don't support MMIO config access.
1938 if (IS_BAD_AMD_NTBRIDGE(vendorid
, deviceid
) ||
1939 IS_AMD_8132_CHIP(vendorid
, deviceid
)) {
1943 if ((basecl
== PCI_CLASS_BRIDGE
) &&
1944 (subcl
== PCI_BRIDGE_PCI
)) {
1945 secbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SECBUS
);
1946 subbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SUBBUS
);
1948 pci_cfgacc_add_workaround(bdf
, secbus
, subbus
);
1952 * Only populate bus_t if this device is sitting under a PCIE root
1953 * complex. Some particular machines have both a PCIE root complex and
1954 * a PCI hostbridge, in which case only devices under the PCIE root
1955 * complex will have their bus_t populated.
1957 if (pcie_get_rc_dip(dip
) != NULL
) {
1958 ck804_fix_aer_ptr(dip
, bdf
);
1959 (void) pcie_init_bus(dip
, bdf
, PCIE_BUS_INITIAL
);
1962 /* add properties */
1963 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "device-id", deviceid
);
1964 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "vendor-id", vendorid
);
1965 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "revision-id", revid
);
1966 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1967 "class-code", classcode
);
1969 (void) snprintf(unitaddr
, sizeof (unitaddr
), "%x", dev
);
1971 (void) snprintf(unitaddr
, sizeof (unitaddr
),
1972 "%x,%x", dev
, func
);
1973 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
1974 "unit-address", unitaddr
);
1976 /* add device_type for display nodes */
1977 if (is_display(classcode
)) {
1978 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
1979 "device_type", "display");
1981 /* add special stuff for header type */
1982 if ((header
& PCI_HEADER_TYPE_M
) == PCI_HEADER_ZERO
) {
1983 uchar_t mingrant
= pci_getb(bus
, dev
, func
, PCI_CONF_MIN_G
);
1984 uchar_t maxlatency
= pci_getb(bus
, dev
, func
, PCI_CONF_MAX_L
);
1986 if (subvenid
!= 0) {
1987 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1988 "subsystem-id", subdevid
);
1989 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1990 "subsystem-vendor-id", subvenid
);
1993 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1994 "min-grant", mingrant
);
1996 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
1997 "max-latency", maxlatency
);
2000 /* interrupt, record if not 0 */
2001 intr
= pci_getb(bus
, dev
, func
, PCI_CONF_IPIN
);
2003 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2004 "interrupts", intr
);
2007 * Add support for 133 mhz pci eventually
2009 status
= pci_getw(bus
, dev
, func
, PCI_CONF_STAT
);
2011 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2012 "devsel-speed", (status
& PCI_STAT_DEVSELT
) >> 9);
2013 if (!pciex
&& (status
& PCI_STAT_FBBC
))
2014 (void) ndi_prop_create_boolean(DDI_DEV_T_NONE
, dip
,
2015 "fast-back-to-back");
2016 if (!pciex
&& (status
& PCI_STAT_66MHZ
))
2017 (void) ndi_prop_create_boolean(DDI_DEV_T_NONE
, dip
,
2019 if (status
& PCI_STAT_UDF
)
2020 (void) ndi_prop_create_boolean(DDI_DEV_T_NONE
, dip
,
2022 if (pciex
&& slot_valid
) {
2023 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2024 "physical-slot#", slot_num
);
2026 pciex_slot_names_prop(dip
, slot_num
);
2029 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
2030 "power-consumption", power
, 2);
2032 /* Set the device PM state to D0 */
2033 set_devpm_d0(bus
, dev
, func
);
2035 if ((basecl
== PCI_CLASS_BRIDGE
) && (subcl
== PCI_BRIDGE_PCI
))
2036 add_ppb_props(dip
, bus
, dev
, func
, pciex
, is_pci_bridge
);
2039 * Record the non-PPB devices on the bus for possible
2040 * reprogramming at 2nd bus enumeration.
2041 * Note: PPB reprogramming is done in fix_ppb_res()
2043 devlist
= (struct pci_devfunc
*)pci_bus_res
[bus
].privdata
;
2044 entry
= kmem_zalloc(sizeof (*entry
), KM_SLEEP
);
2048 entry
->next
= devlist
;
2049 pci_bus_res
[bus
].privdata
= entry
;
2052 if (IS_CLASS_IOAPIC(basecl
, subcl
, progcl
)) {
2053 create_ioapic_node(bus
, dev
, func
, vendorid
, deviceid
);
2056 /* check for NVIDIA CK8-04/MCP55 based LPC bridge */
2057 if (NVIDIA_IS_LPC_BRIDGE(vendorid
, deviceid
) && (dev
== 1) &&
2059 add_nvidia_isa_bridge_props(dip
, bus
, dev
, func
);
2060 /* each LPC bridge has an integrated IOAPIC */
2061 apic_nvidia_io_max
++;
2064 if (pciex
&& is_pci_bridge
)
2065 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
, "model",
2066 (char *)"PCIe-PCI bridge");
2068 add_model_prop(dip
, classcode
);
2070 add_compatible(dip
, subvenid
, subdevid
, vendorid
, deviceid
,
2071 revid
, classcode
, pciex
);
2074 * See if this device is a controller that advertises
2075 * itself to be a standard ATA task file controller, or one that
2076 * has been hard coded.
2078 * If it is, check if any other higher precedence driver listed in
2079 * driver_aliases will claim the node by calling
2080 * ddi_compatibile_driver_major. If so, clear pciide and do not
2081 * create a pci-ide node or any other special handling.
2083 * If another driver does not bind, set the node name to pci-ide
2084 * and then let the special pci-ide handling for registers and
2085 * child pci-ide nodes proceed below.
2087 if (is_pciide(basecl
, subcl
, revid
, vendorid
, deviceid
,
2088 subvenid
, subdevid
) == 1) {
2089 if (ddi_compatible_driver_major(dip
, NULL
) == (major_t
)-1) {
2090 (void) ndi_devi_set_nodename(dip
, "pci-ide", 0);
2096 reprogram
= add_reg_props(dip
, bus
, dev
, func
, config_op
, pciide
);
2097 (void) ndi_devi_bind_driver(dip
, 0);
2099 /* special handling for pci-ide */
2104 * Create properties specified by P1275 Working Group
2105 * Proposal #414 Version 1
2107 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
2108 "device_type", "pci-ide");
2109 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2110 "#address-cells", 1);
2111 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2114 /* allocate two child nodes */
2115 ndi_devi_alloc_sleep(dip
, "ide",
2116 (pnode_t
)DEVI_SID_NODEID
, &cdip
);
2117 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
,
2119 (void) ndi_devi_bind_driver(cdip
, 0);
2120 ndi_devi_alloc_sleep(dip
, "ide",
2121 (pnode_t
)DEVI_SID_NODEID
, &cdip
);
2122 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
,
2124 (void) ndi_devi_bind_driver(cdip
, 0);
2126 reprogram
= 0; /* don't reprogram pci-ide bridge */
2129 if (is_display(classcode
)) {
2130 gfxp
= kmem_zalloc(sizeof (*gfxp
), KM_SLEEP
);
2132 gfxp
->g_prev
= NULL
;
2133 gfxp
->g_next
= gfx_devinfo_list
;
2134 gfx_devinfo_list
= gfxp
;
2136 gfxp
->g_next
->g_prev
= gfxp
;
2139 /* special handling for isa */
2140 if (!pseudo_isa
&& is_isa(basecl
, subcl
)) {
2141 /* add device_type */
2142 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
2143 "device_type", "isa");
2146 if (reprogram
&& (entry
!= NULL
))
2147 entry
->reprogram
= B_TRUE
;
2152 * Some vendors do not use unique subsystem IDs in their products, which
2153 * makes the use of form 2 compatible names (pciSSSS,ssss) inappropriate.
2154 * Allow for these compatible forms to be excluded on a per-device basis.
2158 subsys_compat_exclude(ushort_t venid
, ushort_t devid
, ushort_t subvenid
,
2159 ushort_t subdevid
, uchar_t revid
, uint_t classcode
)
2161 /* Nvidia display adapters */
2162 if ((venid
== 0x10de) && (is_display(classcode
)))
2169 * Set the compatible property to a value compliant with
2170 * rev 2.1 of the IEEE1275 PCI binding.
2171 * (Also used for PCI-Express devices).
2173 * pciVVVV,DDDD.SSSS.ssss.RR (0)
2174 * pciVVVV,DDDD.SSSS.ssss (1)
2176 * pciVVVV,DDDD.RR (3)
2178 * pciclass,CCSSPP (5)
2181 * The Subsystem (SSSS) forms are not inserted if
2182 * subsystem-vendor-id is 0.
2184 * NOTE: For PCI-Express devices "pci" is replaced with "pciex" in 0-6 above
2185 * property 2 is not created as per "1275 bindings for PCI Express Interconnect"
2187 * Set with setprop and \x00 between each
2188 * to generate the encoded string array form.
2191 add_compatible(dev_info_t
*dip
, ushort_t subvenid
, ushort_t subdevid
,
2192 ushort_t vendorid
, ushort_t deviceid
, uchar_t revid
, uint_t classcode
,
2196 int size
= COMPAT_BUFSIZE
;
2200 curr
= buf
= kmem_alloc(size
, KM_SLEEP
);
2204 compat
[i
++] = curr
; /* form 0 */
2205 (void) snprintf(curr
, size
, "pciex%x,%x.%x.%x.%x",
2206 vendorid
, deviceid
, subvenid
, subdevid
, revid
);
2207 size
-= strlen(curr
) + 1;
2208 curr
+= strlen(curr
) + 1;
2210 compat
[i
++] = curr
; /* form 1 */
2211 (void) snprintf(curr
, size
, "pciex%x,%x.%x.%x",
2212 vendorid
, deviceid
, subvenid
, subdevid
);
2213 size
-= strlen(curr
) + 1;
2214 curr
+= strlen(curr
) + 1;
2217 compat
[i
++] = curr
; /* form 3 */
2218 (void) snprintf(curr
, size
, "pciex%x,%x.%x",
2219 vendorid
, deviceid
, revid
);
2220 size
-= strlen(curr
) + 1;
2221 curr
+= strlen(curr
) + 1;
2223 compat
[i
++] = curr
; /* form 4 */
2224 (void) snprintf(curr
, size
, "pciex%x,%x", vendorid
, deviceid
);
2225 size
-= strlen(curr
) + 1;
2226 curr
+= strlen(curr
) + 1;
2228 compat
[i
++] = curr
; /* form 5 */
2229 (void) snprintf(curr
, size
, "pciexclass,%06x", classcode
);
2230 size
-= strlen(curr
) + 1;
2231 curr
+= strlen(curr
) + 1;
2233 compat
[i
++] = curr
; /* form 6 */
2234 (void) snprintf(curr
, size
, "pciexclass,%04x",
2236 size
-= strlen(curr
) + 1;
2237 curr
+= strlen(curr
) + 1;
2241 compat
[i
++] = curr
; /* form 0 */
2242 (void) snprintf(curr
, size
, "pci%x,%x.%x.%x.%x",
2243 vendorid
, deviceid
, subvenid
, subdevid
, revid
);
2244 size
-= strlen(curr
) + 1;
2245 curr
+= strlen(curr
) + 1;
2247 compat
[i
++] = curr
; /* form 1 */
2248 (void) snprintf(curr
, size
, "pci%x,%x.%x.%x",
2249 vendorid
, deviceid
, subvenid
, subdevid
);
2250 size
-= strlen(curr
) + 1;
2251 curr
+= strlen(curr
) + 1;
2253 if (subsys_compat_exclude(vendorid
, deviceid
, subvenid
,
2254 subdevid
, revid
, classcode
) == B_FALSE
) {
2255 compat
[i
++] = curr
; /* form 2 */
2256 (void) snprintf(curr
, size
, "pci%x,%x", subvenid
,
2258 size
-= strlen(curr
) + 1;
2259 curr
+= strlen(curr
) + 1;
2262 compat
[i
++] = curr
; /* form 3 */
2263 (void) snprintf(curr
, size
, "pci%x,%x.%x", vendorid
, deviceid
, revid
);
2264 size
-= strlen(curr
) + 1;
2265 curr
+= strlen(curr
) + 1;
2267 compat
[i
++] = curr
; /* form 4 */
2268 (void) snprintf(curr
, size
, "pci%x,%x", vendorid
, deviceid
);
2269 size
-= strlen(curr
) + 1;
2270 curr
+= strlen(curr
) + 1;
2272 compat
[i
++] = curr
; /* form 5 */
2273 (void) snprintf(curr
, size
, "pciclass,%06x", classcode
);
2274 size
-= strlen(curr
) + 1;
2275 curr
+= strlen(curr
) + 1;
2277 compat
[i
++] = curr
; /* form 6 */
2278 (void) snprintf(curr
, size
, "pciclass,%04x", (classcode
>> 8));
2279 size
-= strlen(curr
) + 1;
2280 curr
+= strlen(curr
) + 1;
2282 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE
, dip
,
2283 "compatible", compat
, i
);
2284 kmem_free(buf
, COMPAT_BUFSIZE
);
2288 * Adjust the reg properties for a dual channel PCI-IDE device.
2290 * NOTE: don't do anything that changes the order of the hard-decodes
2291 * and programmed BARs. The kernel driver depends on these values
2292 * being in this order regardless of whether they're for a 'native'
2296 * config info for pci-ide devices
2299 uchar_t native_mask
; /* 0 == 'compatibility' mode, 1 == native */
2300 uchar_t bar_offset
; /* offset for alt status register */
2301 ushort_t addr
; /* compatibility mode base address */
2302 ushort_t length
; /* number of ports for this BAR */
2304 { 0x01, 0, 0x1f0, 8 }, /* primary lower BAR */
2305 { 0x01, 2, 0x3f6, 1 }, /* primary upper BAR */
2306 { 0x04, 0, 0x170, 8 }, /* secondary lower BAR */
2307 { 0x04, 2, 0x376, 1 } /* secondary upper BAR */
2311 pciIdeAdjustBAR(uchar_t progcl
, int index
, uint_t
*basep
, uint_t
*lenp
)
2313 int hard_decode
= 0;
2316 * Adjust the base and len for the BARs of the PCI-IDE
2317 * device's primary and secondary controllers. The first
2318 * two BARs are for the primary controller and the next
2319 * two BARs are for the secondary controller. The fifth
2320 * and sixth bars are never adjusted.
2322 if (index
>= 0 && index
<= 3) {
2323 *lenp
= pciide_bar
[index
].length
;
2325 if (progcl
& pciide_bar
[index
].native_mask
) {
2326 *basep
+= pciide_bar
[index
].bar_offset
;
2328 *basep
= pciide_bar
[index
].addr
;
2334 * if either base or len is zero make certain both are zero
2336 if (*basep
== 0 || *lenp
== 0) {
2342 return (hard_decode
);
2347 * Add the "reg" and "assigned-addresses" property
2350 add_reg_props(dev_info_t
*dip
, uchar_t bus
, uchar_t dev
, uchar_t func
,
2351 int config_op
, int pciide
)
2353 uchar_t baseclass
, subclass
, progclass
, header
;
2355 uint_t value
= 0, len
, devloc
;
2356 uint_t base
, base_hi
, type
;
2357 ushort_t offset
, end
;
2358 int max_basereg
, j
, reprogram
= 0;
2360 struct memlist
**io_avail
, **io_used
;
2361 struct memlist
**mem_avail
, **mem_used
;
2362 struct memlist
**pmem_avail
, **pmem_used
;
2365 pci_regspec_t regs
[16] = {{0}};
2366 pci_regspec_t assigned
[15] = {{0}};
2369 io_avail
= &pci_bus_res
[bus
].io_avail
;
2370 io_used
= &pci_bus_res
[bus
].io_used
;
2371 mem_avail
= &pci_bus_res
[bus
].mem_avail
;
2372 mem_used
= &pci_bus_res
[bus
].mem_used
;
2373 pmem_avail
= &pci_bus_res
[bus
].pmem_avail
;
2374 pmem_used
= &pci_bus_res
[bus
].pmem_used
;
2376 devloc
= (uint_t
)bus
<< 16 | (uint_t
)dev
<< 11 | (uint_t
)func
<< 8;
2377 regs
[0].pci_phys_hi
= devloc
;
2378 nreg
= 1; /* rest of regs[0] is all zero */
2381 baseclass
= pci_getb(bus
, dev
, func
, PCI_CONF_BASCLASS
);
2382 subclass
= pci_getb(bus
, dev
, func
, PCI_CONF_SUBCLASS
);
2383 progclass
= pci_getb(bus
, dev
, func
, PCI_CONF_PROGCLASS
);
2384 header
= pci_getb(bus
, dev
, func
, PCI_CONF_HEADER
) & PCI_HEADER_TYPE_M
;
2387 case PCI_HEADER_ZERO
:
2388 max_basereg
= PCI_BASE_NUM
;
2390 case PCI_HEADER_PPB
:
2391 max_basereg
= PCI_BCNF_BASE_NUM
;
2393 case PCI_HEADER_CARDBUS
:
2394 max_basereg
= PCI_CBUS_BASE_NUM
;
2403 * Create the register property by saving the current
2404 * value of the base register. Write 0xffffffff to the
2405 * base register. Read the value back to determine the
2406 * required size of the address space. Restore the base
2407 * register contents.
2409 * Do not disable I/O and memory access for bridges; this
2410 * has the side-effect of making the bridge transparent to
2411 * secondary-bus activity (see sections 4.1-4.3 of the
2412 * PCI-PCI Bridge Spec V1.2). For non-bridges, disable
2413 * I/O and memory access to avoid difficulty with USB
2414 * emulation (see OHCI spec1.0a appendix B
2415 * "Host Controller Mapping")
2417 end
= PCI_CONF_BASE0
+ max_basereg
* sizeof (uint_t
);
2418 for (j
= 0, offset
= PCI_CONF_BASE0
; offset
< end
;
2419 j
++, offset
+= bar_sz
) {
2422 /* determine the size of the address space */
2423 base
= pci_getl(bus
, dev
, func
, offset
);
2424 if (baseclass
!= PCI_CLASS_BRIDGE
) {
2425 command
= (uint_t
)pci_getw(bus
, dev
, func
,
2427 pci_putw(bus
, dev
, func
, PCI_CONF_COMM
,
2428 command
& ~(PCI_COMM_MAE
| PCI_COMM_IO
));
2430 pci_putl(bus
, dev
, func
, offset
, 0xffffffff);
2431 value
= pci_getl(bus
, dev
, func
, offset
);
2432 pci_putl(bus
, dev
, func
, offset
, base
);
2433 if (baseclass
!= PCI_CLASS_BRIDGE
)
2434 pci_putw(bus
, dev
, func
, PCI_CONF_COMM
, command
);
2436 /* construct phys hi,med.lo, size hi, lo */
2437 if ((pciide
&& j
< 4) || (base
& PCI_BASE_SPACE_IO
)) {
2438 int hard_decode
= 0;
2441 bar_sz
= PCI_BAR_SZ_32
;
2442 value
&= PCI_BASE_IO_ADDR_M
;
2443 len
= ((value
^ (value
-1)) + 1) >> 1;
2445 /* XXX Adjust first 4 IDE registers */
2447 if (subclass
!= PCI_MASS_IDE
)
2448 progclass
= (PCI_IDE_IF_NATIVE_PRI
|
2449 PCI_IDE_IF_NATIVE_SEC
);
2450 hard_decode
= pciIdeAdjustBAR(progclass
, j
,
2452 } else if (value
== 0) {
2453 /* skip base regs with size of 0 */
2457 regs
[nreg
].pci_phys_hi
= PCI_ADDR_IO
| devloc
|
2458 (hard_decode
? PCI_RELOCAT_B
: offset
);
2459 regs
[nreg
].pci_phys_low
= hard_decode
?
2460 base
& PCI_BASE_IO_ADDR_M
: 0;
2461 assigned
[nasgn
].pci_phys_hi
=
2462 PCI_RELOCAT_B
| regs
[nreg
].pci_phys_hi
;
2463 regs
[nreg
].pci_size_low
=
2464 assigned
[nasgn
].pci_size_low
= len
;
2465 type
= base
& (~PCI_BASE_IO_ADDR_M
);
2466 base
&= PCI_BASE_IO_ADDR_M
;
2468 * A device under a subtractive PPB can allocate
2469 * resources from its parent bus if there is no resource
2470 * available on its own bus.
2472 if ((config_op
== CONFIG_NEW
) && (*io_avail
== NULL
)) {
2474 while (pci_bus_res
[res_bus
].subtractive
) {
2475 res_bus
= pci_bus_res
[res_bus
].par_bus
;
2476 if (res_bus
== (uchar_t
)-1)
2477 break; /* root bus already */
2478 if (pci_bus_res
[res_bus
].io_avail
) {
2479 io_avail
= &pci_bus_res
2487 * first pass - gather what's there
2488 * update/second pass - adjust/allocate regions
2489 * config - allocate regions
2491 if (config_op
== CONFIG_INFO
) { /* first pass */
2492 /* take out of the resource map of the bus */
2494 (void) memlist_remove(io_avail
, base
,
2496 memlist_insert(io_used
, base
, len
);
2500 pci_bus_res
[bus
].io_size
+= len
;
2501 } else if ((*io_avail
&& base
== 0) ||
2502 pci_bus_res
[bus
].io_reprogram
) {
2503 base
= (uint_t
)memlist_find(io_avail
, len
, len
);
2505 memlist_insert(io_used
, base
, len
);
2506 /* XXX need to worry about 64-bit? */
2507 pci_putl(bus
, dev
, func
, offset
,
2509 base
= pci_getl(bus
, dev
, func
, offset
);
2510 base
&= PCI_BASE_IO_ADDR_M
;
2513 cmn_err(CE_WARN
, "failed to program"
2514 " IO space [%d/%d/%d] BAR@0x%x"
2516 bus
, dev
, func
, offset
, len
);
2519 assigned
[nasgn
].pci_phys_low
= base
;
2524 if ((base
& PCI_BASE_TYPE_M
) == PCI_BASE_TYPE_ALL
) {
2525 bar_sz
= PCI_BAR_SZ_64
;
2526 base_hi
= pci_getl(bus
, dev
, func
, offset
+ 4);
2527 phys_hi
= PCI_ADDR_MEM64
;
2529 bar_sz
= PCI_BAR_SZ_32
;
2531 phys_hi
= PCI_ADDR_MEM32
;
2534 /* skip base regs with size of 0 */
2535 value
&= PCI_BASE_M_ADDR_M
;
2540 len
= ((value
^ (value
-1)) + 1) >> 1;
2541 regs
[nreg
].pci_size_low
=
2542 assigned
[nasgn
].pci_size_low
= len
;
2544 phys_hi
|= (devloc
| offset
);
2545 if (base
& PCI_BASE_PREF_M
)
2546 phys_hi
|= PCI_PREFETCH_B
;
2549 * A device under a subtractive PPB can allocate
2550 * resources from its parent bus if there is no resource
2551 * available on its own bus.
2553 if ((config_op
== CONFIG_NEW
) && (*mem_avail
== NULL
)) {
2555 while (pci_bus_res
[res_bus
].subtractive
) {
2556 res_bus
= pci_bus_res
[res_bus
].par_bus
;
2557 if (res_bus
== (uchar_t
)-1)
2558 break; /* root bus already */
2560 &pci_bus_res
[res_bus
].mem_avail
;
2562 &pci_bus_res
[res_bus
].pmem_avail
;
2564 * Break out as long as at least
2565 * mem_avail is available
2568 (phys_hi
& PCI_PREFETCH_B
)) ||
2574 regs
[nreg
].pci_phys_hi
=
2575 assigned
[nasgn
].pci_phys_hi
= phys_hi
;
2576 assigned
[nasgn
].pci_phys_hi
|= PCI_RELOCAT_B
;
2577 assigned
[nasgn
].pci_phys_mid
= base_hi
;
2578 type
= base
& ~PCI_BASE_M_ADDR_M
;
2579 base
&= PCI_BASE_M_ADDR_M
;
2581 if (config_op
== CONFIG_INFO
) {
2582 /* take out of the resource map of the bus */
2584 /* remove from PMEM and MEM space */
2585 (void) memlist_remove(mem_avail
,
2587 (void) memlist_remove(pmem_avail
,
2589 /* only note as used in correct map */
2590 if (phys_hi
& PCI_PREFETCH_B
)
2591 memlist_insert(pmem_used
,
2594 memlist_insert(mem_used
,
2599 pci_bus_res
[bus
].mem_size
+= len
;
2600 } else if ((*mem_avail
&& base
== NULL
) ||
2601 pci_bus_res
[bus
].mem_reprogram
) {
2603 * When desired, attempt a prefetchable
2606 if (phys_hi
& PCI_PREFETCH_B
) {
2607 base
= (uint_t
)memlist_find(pmem_avail
,
2610 memlist_insert(pmem_used
,
2612 (void) memlist_remove(mem_avail
,
2617 * If prefetchable allocation was not
2618 * desired, or failed, attempt ordinary
2622 base
= (uint_t
)memlist_find(mem_avail
,
2625 memlist_insert(mem_used
,
2627 (void) memlist_remove(
2628 pmem_avail
, base
, len
);
2632 pci_putl(bus
, dev
, func
, offset
,
2634 base
= pci_getl(bus
, dev
, func
, offset
);
2635 base
&= PCI_BASE_M_ADDR_M
;
2637 cmn_err(CE_WARN
, "failed to program "
2638 "mem space [%d/%d/%d] BAR@0x%x"
2640 bus
, dev
, func
, offset
, len
);
2642 assigned
[nasgn
].pci_phys_low
= base
;
2647 case PCI_HEADER_ZERO
:
2648 offset
= PCI_CONF_ROM
;
2650 case PCI_HEADER_PPB
:
2651 offset
= PCI_BCNF_ROM
;
2653 default: /* including PCI_HEADER_CARDBUS */
2658 * Add the expansion rom memory space
2659 * Determine the size of the ROM base reg; don't write reserved bits
2660 * ROM isn't in the PCI memory space.
2662 base
= pci_getl(bus
, dev
, func
, offset
);
2663 pci_putl(bus
, dev
, func
, offset
, PCI_BASE_ROM_ADDR_M
);
2664 value
= pci_getl(bus
, dev
, func
, offset
);
2665 pci_putl(bus
, dev
, func
, offset
, base
);
2666 if (value
& PCI_BASE_ROM_ENABLE
)
2667 value
&= PCI_BASE_ROM_ADDR_M
;
2672 regs
[nreg
].pci_phys_hi
= (PCI_ADDR_MEM32
| devloc
) + offset
;
2673 assigned
[nasgn
].pci_phys_hi
= (PCI_RELOCAT_B
|
2674 PCI_ADDR_MEM32
| devloc
) + offset
;
2675 base
&= PCI_BASE_ROM_ADDR_M
;
2676 assigned
[nasgn
].pci_phys_low
= base
;
2677 len
= ((value
^ (value
-1)) + 1) >> 1;
2678 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= len
;
2680 /* take it out of the memory resource */
2682 (void) memlist_remove(mem_avail
, base
, len
);
2683 memlist_insert(mem_used
, base
, len
);
2684 pci_bus_res
[bus
].mem_size
+= len
;
2689 * Account for "legacy" (alias) video adapter resources
2692 /* add the three hard-decode, aliased address spaces for VGA */
2693 if ((baseclass
== PCI_CLASS_DISPLAY
&& subclass
== PCI_DISPLAY_VGA
) ||
2694 (baseclass
== PCI_CLASS_NONE
&& subclass
== PCI_NONE_VGA
)) {
2696 /* VGA hard decode 0x3b0-0x3bb */
2697 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2698 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2699 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x3b0;
2700 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0xc;
2702 (void) memlist_remove(io_avail
, 0x3b0, 0xc);
2703 memlist_insert(io_used
, 0x3b0, 0xc);
2704 pci_bus_res
[bus
].io_size
+= 0xc;
2706 /* VGA hard decode 0x3c0-0x3df */
2707 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2708 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2709 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x3c0;
2710 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0x20;
2712 (void) memlist_remove(io_avail
, 0x3c0, 0x20);
2713 memlist_insert(io_used
, 0x3c0, 0x20);
2714 pci_bus_res
[bus
].io_size
+= 0x20;
2717 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2718 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_MEM32
| devloc
);
2719 regs
[nreg
].pci_phys_low
=
2720 assigned
[nasgn
].pci_phys_low
= 0xa0000;
2721 regs
[nreg
].pci_size_low
=
2722 assigned
[nasgn
].pci_size_low
= 0x20000;
2724 /* remove from MEM and PMEM space */
2725 (void) memlist_remove(mem_avail
, 0xa0000, 0x20000);
2726 (void) memlist_remove(pmem_avail
, 0xa0000, 0x20000);
2727 memlist_insert(mem_used
, 0xa0000, 0x20000);
2728 pci_bus_res
[bus
].mem_size
+= 0x20000;
2731 /* add the hard-decode, aliased address spaces for 8514 */
2732 if ((baseclass
== PCI_CLASS_DISPLAY
) &&
2733 (subclass
== PCI_DISPLAY_VGA
) &&
2734 (progclass
& PCI_DISPLAY_IF_8514
)) {
2736 /* hard decode 0x2e8 */
2737 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2738 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2739 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x2e8;
2740 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0x1;
2742 (void) memlist_remove(io_avail
, 0x2e8, 0x1);
2743 memlist_insert(io_used
, 0x2e8, 0x1);
2744 pci_bus_res
[bus
].io_size
+= 0x1;
2746 /* hard decode 0x2ea-0x2ef */
2747 regs
[nreg
].pci_phys_hi
= assigned
[nasgn
].pci_phys_hi
=
2748 (PCI_RELOCAT_B
| PCI_ALIAS_B
| PCI_ADDR_IO
| devloc
);
2749 regs
[nreg
].pci_phys_low
= assigned
[nasgn
].pci_phys_low
= 0x2ea;
2750 regs
[nreg
].pci_size_low
= assigned
[nasgn
].pci_size_low
= 0x6;
2752 (void) memlist_remove(io_avail
, 0x2ea, 0x6);
2753 memlist_insert(io_used
, 0x2ea, 0x6);
2754 pci_bus_res
[bus
].io_size
+= 0x6;
2758 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
, "reg",
2759 (int *)regs
, nreg
* sizeof (pci_regspec_t
) / sizeof (int));
2760 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
2761 "assigned-addresses",
2762 (int *)assigned
, nasgn
* sizeof (pci_regspec_t
) / sizeof (int));
2768 add_ppb_props(dev_info_t
*dip
, uchar_t bus
, uchar_t dev
, uchar_t func
,
2769 int pciex
, ushort_t is_pci_bridge
)
2773 uint_t val
, io_range
[2], mem_range
[2], pmem_range
[2];
2774 uchar_t secbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SECBUS
);
2775 uchar_t subbus
= pci_getb(bus
, dev
, func
, PCI_BCNF_SUBBUS
);
2778 ASSERT(secbus
<= subbus
);
2781 * Check if it's a subtractive PPB.
2783 progclass
= pci_getb(bus
, dev
, func
, PCI_CONF_PROGCLASS
);
2784 if (progclass
== PCI_BRIDGE_PCI_IF_SUBDECODE
)
2785 pci_bus_res
[secbus
].subtractive
= B_TRUE
;
2788 * Some BIOSes lie about max pci busses, we allow for
2789 * such mistakes here
2791 if (subbus
> pci_bios_maxbus
) {
2792 pci_bios_maxbus
= subbus
;
2796 ASSERT(pci_bus_res
[secbus
].dip
== NULL
);
2797 pci_bus_res
[secbus
].dip
= dip
;
2798 pci_bus_res
[secbus
].par_bus
= bus
;
2800 dev_type
= (pciex
&& !is_pci_bridge
) ? "pciex" : "pci";
2802 /* setup bus number hierarchy */
2803 pci_bus_res
[secbus
].sub_bus
= subbus
;
2805 * Keep track of the largest subordinate bus number (this is essential
2806 * for peer busses because there is no other way of determining its
2807 * subordinate bus number).
2809 if (subbus
> pci_bus_res
[bus
].sub_bus
)
2810 pci_bus_res
[bus
].sub_bus
= subbus
;
2812 * Loop through subordinate busses, initializing their parent bus
2813 * field to this bridge's parent. The subordinate busses' parent
2814 * fields may very well be further refined later, as child bridges
2815 * are enumerated. (The value is to note that the subordinate busses
2816 * are not peer busses by changing their par_bus fields to anything
2819 for (i
= secbus
+ 1; i
<= subbus
; i
++)
2820 pci_bus_res
[i
].par_bus
= bus
;
2822 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
2823 "device_type", dev_type
);
2824 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2825 "#address-cells", 3);
2826 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
2830 * Collect bridge window specifications, and use them to populate
2831 * the "avail" resources for the bus. Not all of those resources will
2832 * end up being available; this is done top-down, and so the initial
2833 * collection of windows populates the 'ranges' property for the
2834 * bus node. Later, as children are found, resources are removed from
2835 * the 'avail' list, so that it becomes the freelist for
2836 * this point in the tree. ranges may be set again after bridge
2837 * reprogramming in fix_ppb_res(), in which case it's set from
2840 * According to PPB spec, the base register should be programmed
2841 * with a value bigger than the limit register when there are
2842 * no resources available. This applies to io, memory, and
2843 * prefetchable memory.
2848 * We determine i/o windows that are left unconfigured by BIOS
2849 * through its i/o enable bit as Microsoft recommends OEMs to do.
2850 * If it is unset, we disable i/o and mark it for reconfiguration in
2851 * later passes by setting the base > limit
2853 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_CONF_COMM
);
2854 if (val
& PCI_COMM_IO
) {
2855 val
= (uint_t
)pci_getb(bus
, dev
, func
, PCI_BCNF_IO_BASE_LOW
);
2856 io_range
[0] = ((val
& 0xf0) << 8);
2857 val
= (uint_t
)pci_getb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_LOW
);
2858 io_range
[1] = ((val
& 0xf0) << 8) | 0xFFF;
2860 io_range
[0] = 0x9fff;
2861 io_range
[1] = 0x1000;
2862 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_BASE_LOW
,
2863 (uint8_t)((io_range
[0] >> 8) & 0xf0));
2864 pci_putb(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_LOW
,
2865 (uint8_t)((io_range
[1] >> 8) & 0xf0));
2866 pci_putw(bus
, dev
, func
, PCI_BCNF_IO_BASE_HI
, 0);
2867 pci_putw(bus
, dev
, func
, PCI_BCNF_IO_LIMIT_HI
, 0);
2870 if (io_range
[0] != 0 && io_range
[0] < io_range
[1]) {
2871 memlist_insert(&pci_bus_res
[secbus
].io_avail
,
2872 (uint64_t)io_range
[0],
2873 (uint64_t)(io_range
[1] - io_range
[0] + 1));
2874 memlist_insert(&pci_bus_res
[bus
].io_used
,
2875 (uint64_t)io_range
[0],
2876 (uint64_t)(io_range
[1] - io_range
[0] + 1));
2877 if (pci_bus_res
[bus
].io_avail
!= NULL
) {
2878 (void) memlist_remove(&pci_bus_res
[bus
].io_avail
,
2879 (uint64_t)io_range
[0],
2880 (uint64_t)(io_range
[1] - io_range
[0] + 1));
2882 dcmn_err(CE_NOTE
, "bus %d io-range: 0x%x-%x",
2883 secbus
, io_range
[0], io_range
[1]);
2884 /* if 32-bit supported, make sure upper bits are not set */
2885 if ((val
& 0xf) == 1 &&
2886 pci_getw(bus
, dev
, func
, PCI_BCNF_IO_BASE_HI
)) {
2887 cmn_err(CE_NOTE
, "unsupported 32-bit IO address on"
2888 " pci-pci bridge [%d/%d/%d]", bus
, dev
, func
);
2893 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_BASE
);
2894 mem_range
[0] = ((val
& 0xFFF0) << 16);
2895 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_MEM_LIMIT
);
2896 mem_range
[1] = ((val
& 0xFFF0) << 16) | 0xFFFFF;
2897 if (mem_range
[0] != 0 && mem_range
[0] < mem_range
[1]) {
2898 memlist_insert(&pci_bus_res
[secbus
].mem_avail
,
2899 (uint64_t)mem_range
[0],
2900 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2901 memlist_insert(&pci_bus_res
[bus
].mem_used
,
2902 (uint64_t)mem_range
[0],
2903 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2904 /* remove from parent resource list */
2905 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
,
2906 (uint64_t)mem_range
[0],
2907 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2908 (void) memlist_remove(&pci_bus_res
[bus
].pmem_avail
,
2909 (uint64_t)mem_range
[0],
2910 (uint64_t)(mem_range
[1] - mem_range
[0] + 1));
2911 dcmn_err(CE_NOTE
, "bus %d mem-range: 0x%x-%x",
2912 secbus
, mem_range
[0], mem_range
[1]);
2915 /* prefetchable memory range */
2916 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_PF_BASE_LOW
);
2917 pmem_range
[0] = ((val
& 0xFFF0) << 16);
2918 val
= (uint_t
)pci_getw(bus
, dev
, func
, PCI_BCNF_PF_LIMIT_LOW
);
2919 pmem_range
[1] = ((val
& 0xFFF0) << 16) | 0xFFFFF;
2920 if (pmem_range
[0] != 0 && pmem_range
[0] < pmem_range
[1]) {
2921 memlist_insert(&pci_bus_res
[secbus
].pmem_avail
,
2922 (uint64_t)pmem_range
[0],
2923 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2924 memlist_insert(&pci_bus_res
[bus
].pmem_used
,
2925 (uint64_t)pmem_range
[0],
2926 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2927 /* remove from parent resource list */
2928 (void) memlist_remove(&pci_bus_res
[bus
].pmem_avail
,
2929 (uint64_t)pmem_range
[0],
2930 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2931 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
,
2932 (uint64_t)pmem_range
[0],
2933 (uint64_t)(pmem_range
[1] - pmem_range
[0] + 1));
2934 dcmn_err(CE_NOTE
, "bus %d pmem-range: 0x%x-%x",
2935 secbus
, pmem_range
[0], pmem_range
[1]);
2936 /* if 64-bit supported, make sure upper bits are not set */
2937 if ((val
& 0xf) == 1 &&
2938 pci_getl(bus
, dev
, func
, PCI_BCNF_PF_BASE_HIGH
)) {
2939 cmn_err(CE_NOTE
, "unsupported 64-bit prefetch memory on"
2940 " pci-pci bridge [%d/%d/%d]", bus
, dev
, func
);
2945 * Add VGA legacy resources to the bridge's pci_bus_res if it
2946 * has VGA_ENABLE set. Note that we put them in 'avail',
2947 * because that's used to populate the ranges prop; they'll be
2948 * removed from there by the VGA device once it's found. Also,
2949 * remove them from the parent's available list and note them as
2950 * used in the parent.
2953 if (pci_getw(bus
, dev
, func
, PCI_BCNF_BCNTRL
) &
2954 PCI_BCNF_BCNTRL_VGA_ENABLE
) {
2956 memlist_insert(&pci_bus_res
[secbus
].io_avail
, 0x3b0, 0xc);
2958 memlist_insert(&pci_bus_res
[bus
].io_used
, 0x3b0, 0xc);
2959 if (pci_bus_res
[bus
].io_avail
!= NULL
) {
2960 (void) memlist_remove(&pci_bus_res
[bus
].io_avail
,
2964 memlist_insert(&pci_bus_res
[secbus
].io_avail
, 0x3c0, 0x20);
2966 memlist_insert(&pci_bus_res
[bus
].io_used
, 0x3c0, 0x20);
2967 if (pci_bus_res
[bus
].io_avail
!= NULL
) {
2968 (void) memlist_remove(&pci_bus_res
[bus
].io_avail
,
2972 memlist_insert(&pci_bus_res
[secbus
].mem_avail
, 0xa0000,
2975 memlist_insert(&pci_bus_res
[bus
].mem_used
, 0xa0000, 0x20000);
2976 if (pci_bus_res
[bus
].mem_avail
!= NULL
) {
2977 (void) memlist_remove(&pci_bus_res
[bus
].mem_avail
,
2981 add_bus_range_prop(secbus
);
2982 add_ranges_prop(secbus
, 1);
2985 extern const struct pci_class_strings_s class_pci
[];
2986 extern int class_pci_items
;
2989 add_model_prop(dev_info_t
*dip
, uint_t classcode
)
2993 uchar_t baseclass
= classcode
>> 16;
2994 uchar_t subclass
= (classcode
>> 8) & 0xff;
2995 uchar_t progclass
= classcode
& 0xff;
2997 if ((baseclass
== PCI_CLASS_MASS
) && (subclass
== PCI_MASS_IDE
)) {
2998 desc
= "IDE controller";
3000 for (desc
= 0, i
= 0; i
< class_pci_items
; i
++) {
3001 if ((baseclass
== class_pci
[i
].base_class
) &&
3002 (subclass
== class_pci
[i
].sub_class
) &&
3003 (progclass
== class_pci
[i
].prog_class
)) {
3004 desc
= class_pci
[i
].actual_desc
;
3008 if (i
== class_pci_items
)
3009 desc
= "Unknown class of pci/pnpbios device";
3012 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, dip
, "model",
3017 add_bus_range_prop(int bus
)
3021 if (pci_bus_res
[bus
].dip
== NULL
)
3024 bus_range
[1] = pci_bus_res
[bus
].sub_bus
;
3025 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
3026 "bus-range", (int *)bus_range
, 2);
3030 * Add slot-names property for any named pci hot-plug slots
3033 add_bus_slot_names_prop(int bus
)
3037 extern int pci_irq_nroutes
;
3041 * If no irq routing table, then go with the slot-names as set up
3042 * in pciex_slot_names_prop() from slot capability register (if any).
3044 if (pci_irq_nroutes
== 0)
3048 * Otherise delete the slot-names we already have and use the irq
3049 * routing table values as returned by pci_slot_names_prop() instead,
3050 * but keep any property of value "pcie0" as that can't be represented
3051 * in the irq routing table.
3053 if (pci_bus_res
[bus
].dip
!= NULL
) {
3054 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, pci_bus_res
[bus
].dip
,
3055 DDI_PROP_DONTPASS
, "slot-names", &slotcap_name
) !=
3056 DDI_SUCCESS
|| strcmp(slotcap_name
, "pcie0") != 0)
3057 (void) ndi_prop_remove(DDI_DEV_T_NONE
,
3058 pci_bus_res
[bus
].dip
, "slot-names");
3061 len
= pci_slot_names_prop(bus
, slotprop
, sizeof (slotprop
));
3064 * Only create a peer bus node if this bus may be a peer bus.
3065 * It may be a peer bus if the dip is NULL and if par_bus is
3066 * -1 (par_bus is -1 if this bus was not found to be
3067 * subordinate to any PCI-PCI bridge).
3068 * If it's not a peer bus, then the ACPI BBN-handling code
3069 * will remove it later.
3071 if (pci_bus_res
[bus
].par_bus
== (uchar_t
)-1 &&
3072 pci_bus_res
[bus
].dip
== NULL
) {
3074 create_root_bus_dip(bus
);
3076 if (pci_bus_res
[bus
].dip
!= NULL
) {
3077 ASSERT((len
% sizeof (int)) == 0);
3078 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
,
3079 pci_bus_res
[bus
].dip
, "slot-names",
3080 (int *)slotprop
, len
/ sizeof (int));
3082 cmn_err(CE_NOTE
, "!BIOS BUG: Invalid bus number in PCI "
3083 "IRQ routing table; Not adding slot-names "
3084 "property for incorrect bus %d", bus
);
3090 * Handle both PCI root and PCI-PCI bridge range properties;
3091 * non-zero 'ppb' argument select PCI-PCI bridges versus root.
3094 memlist_to_ranges(void **rp
, struct memlist
*entry
, int type
, int ppb
)
3096 ppb_ranges_t
*ppb_rp
= *rp
;
3097 pci_ranges_t
*pci_rp
= *rp
;
3099 while (entry
!= NULL
) {
3101 ppb_rp
->child_high
= ppb_rp
->parent_high
= type
;
3102 ppb_rp
->child_mid
= ppb_rp
->parent_mid
=
3103 (uint32_t)(entry
->ml_address
>> 32); /* XXX */
3104 ppb_rp
->child_low
= ppb_rp
->parent_low
=
3105 (uint32_t)entry
->ml_address
;
3107 (uint32_t)(entry
->ml_size
>> 32); /* XXX */
3108 ppb_rp
->size_low
= (uint32_t)entry
->ml_size
;
3111 pci_rp
->child_high
= type
;
3112 pci_rp
->child_mid
= pci_rp
->parent_high
=
3113 (uint32_t)(entry
->ml_address
>> 32); /* XXX */
3114 pci_rp
->child_low
= pci_rp
->parent_low
=
3115 (uint32_t)entry
->ml_address
;
3117 (uint32_t)(entry
->ml_size
>> 32); /* XXX */
3118 pci_rp
->size_low
= (uint32_t)entry
->ml_size
;
3121 entry
= entry
->ml_next
;
3126 add_ranges_prop(int bus
, int ppb
)
3128 int total
, alloc_size
;
3130 struct memlist
*iolist
, *memlist
, *pmemlist
;
3132 /* no devinfo node - unused bus, return */
3133 if (pci_bus_res
[bus
].dip
== NULL
)
3136 iolist
= memlist
= pmemlist
= (struct memlist
*)NULL
;
3138 memlist_merge(&pci_bus_res
[bus
].io_avail
, &iolist
);
3139 memlist_merge(&pci_bus_res
[bus
].io_used
, &iolist
);
3140 memlist_merge(&pci_bus_res
[bus
].mem_avail
, &memlist
);
3141 memlist_merge(&pci_bus_res
[bus
].mem_used
, &memlist
);
3142 memlist_merge(&pci_bus_res
[bus
].pmem_avail
, &pmemlist
);
3143 memlist_merge(&pci_bus_res
[bus
].pmem_used
, &pmemlist
);
3145 total
= memlist_count(iolist
);
3146 total
+= memlist_count(memlist
);
3147 total
+= memlist_count(pmemlist
);
3149 /* no property is created if no ranges are present */
3153 alloc_size
= total
*
3154 (ppb
? sizeof (ppb_ranges_t
) : sizeof (pci_ranges_t
));
3156 next_rp
= rp
= kmem_alloc(alloc_size
, KM_SLEEP
);
3158 memlist_to_ranges(&next_rp
, iolist
, PCI_ADDR_IO
| PCI_REG_REL_M
, ppb
);
3159 memlist_to_ranges(&next_rp
, memlist
,
3160 PCI_ADDR_MEM32
| PCI_REG_REL_M
, ppb
);
3161 memlist_to_ranges(&next_rp
, pmemlist
,
3162 PCI_ADDR_MEM32
| PCI_REG_REL_M
| PCI_REG_PF_M
, ppb
);
3164 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
3165 "ranges", (int *)rp
, alloc_size
/ sizeof (int));
3167 kmem_free(rp
, alloc_size
);
3168 memlist_free_all(&iolist
);
3169 memlist_free_all(&memlist
);
3170 memlist_free_all(&pmemlist
);
3174 memlist_remove_list(struct memlist
**list
, struct memlist
*remove_list
)
3176 while (list
&& *list
&& remove_list
) {
3177 (void) memlist_remove(list
, remove_list
->ml_address
,
3178 remove_list
->ml_size
);
3179 remove_list
= remove_list
->ml_next
;
3184 memlist_to_spec(struct pci_phys_spec
*sp
, struct memlist
*list
, int type
)
3189 /* assume 32-bit addresses */
3190 sp
->pci_phys_hi
= type
;
3191 sp
->pci_phys_mid
= 0;
3192 sp
->pci_phys_low
= (uint32_t)list
->ml_address
;
3193 sp
->pci_size_hi
= 0;
3194 sp
->pci_size_low
= (uint32_t)list
->ml_size
;
3196 list
= list
->ml_next
;
3203 add_bus_available_prop(int bus
)
3206 struct pci_phys_spec
*sp
;
3208 /* no devinfo node - unused bus, return */
3209 if (pci_bus_res
[bus
].dip
== NULL
)
3212 count
= memlist_count(pci_bus_res
[bus
].io_avail
) +
3213 memlist_count(pci_bus_res
[bus
].mem_avail
) +
3214 memlist_count(pci_bus_res
[bus
].pmem_avail
);
3216 if (count
== 0) /* nothing available */
3219 sp
= kmem_alloc(count
* sizeof (*sp
), KM_SLEEP
);
3220 i
= memlist_to_spec(&sp
[0], pci_bus_res
[bus
].io_avail
,
3221 PCI_ADDR_IO
| PCI_REG_REL_M
);
3222 i
+= memlist_to_spec(&sp
[i
], pci_bus_res
[bus
].mem_avail
,
3223 PCI_ADDR_MEM32
| PCI_REG_REL_M
);
3224 i
+= memlist_to_spec(&sp
[i
], pci_bus_res
[bus
].pmem_avail
,
3225 PCI_ADDR_MEM32
| PCI_REG_REL_M
| PCI_REG_PF_M
);
3228 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, pci_bus_res
[bus
].dip
,
3229 "available", (int *)sp
,
3230 i
* sizeof (struct pci_phys_spec
) / sizeof (int));
3231 kmem_free(sp
, count
* sizeof (*sp
));
3235 alloc_res_array(void)
3237 static int array_size
= 0;
3241 if (array_size
> pci_bios_maxbus
+ 1)
3242 return; /* array is big enough */
3244 old_size
= array_size
;
3245 old_res
= pci_bus_res
;
3247 if (array_size
== 0)
3248 array_size
= 16; /* start with a reasonable number */
3250 while (array_size
<= pci_bios_maxbus
+ 1)
3252 pci_bus_res
= (struct pci_bus_resource
*)kmem_zalloc(
3253 array_size
* sizeof (struct pci_bus_resource
), KM_SLEEP
);
3255 if (old_res
) { /* copy content and free old array */
3256 bcopy(old_res
, pci_bus_res
,
3257 old_size
* sizeof (struct pci_bus_resource
));
3258 kmem_free(old_res
, old_size
* sizeof (struct pci_bus_resource
));
3263 create_ioapic_node(int bus
, int dev
, int fn
, ushort_t vendorid
,
3266 static dev_info_t
*ioapicsnode
= NULL
;
3267 static int numioapics
= 0;
3268 dev_info_t
*ioapic_node
;
3270 uint32_t lobase
, hibase
= 0;
3272 /* BAR 0 contains the IOAPIC's memory-mapped I/O address */
3273 lobase
= (*pci_getl_func
)(bus
, dev
, fn
, PCI_CONF_BASE0
);
3275 /* We (and the rest of the world) only support memory-mapped IOAPICs */
3276 if ((lobase
& PCI_BASE_SPACE_M
) != PCI_BASE_SPACE_MEM
)
3279 if ((lobase
& PCI_BASE_TYPE_M
) == PCI_BASE_TYPE_ALL
)
3280 hibase
= (*pci_getl_func
)(bus
, dev
, fn
, PCI_CONF_BASE0
+ 4);
3282 lobase
&= PCI_BASE_M_ADDR_M
;
3284 physaddr
= (((uint64_t)hibase
) << 32) | lobase
;
3287 * Create a nexus node for all IOAPICs under the root node.
3289 if (ioapicsnode
== NULL
) {
3290 if (ndi_devi_alloc(ddi_root_node(), IOAPICS_NODE_NAME
,
3291 (pnode_t
)DEVI_SID_NODEID
, &ioapicsnode
) != NDI_SUCCESS
) {
3294 (void) ndi_devi_online(ioapicsnode
, 0);
3298 * Create a child node for this IOAPIC
3300 ioapic_node
= ddi_add_child(ioapicsnode
, IOAPICS_CHILD_NAME
,
3301 DEVI_SID_NODEID
, numioapics
++);
3302 if (ioapic_node
== NULL
) {
3306 /* Vendor and Device ID */
3307 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, ioapic_node
,
3308 IOAPICS_PROP_VENID
, vendorid
);
3309 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, ioapic_node
,
3310 IOAPICS_PROP_DEVID
, deviceid
);
3313 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, ioapic_node
,
3314 "device_type", IOAPICS_DEV_TYPE
);
3317 (void) ndi_prop_update_int64(DDI_DEV_T_NONE
, ioapic_node
,
3322 * NOTE: For PCIe slots, the name is generated from the slot number
3323 * information obtained from Slot Capabilities register.
3324 * For non-PCIe slots, it is generated based on the slot number
3325 * information in the PCI IRQ table.
3328 pciex_slot_names_prop(dev_info_t
*dip
, ushort_t slot_num
)
3333 bzero(slotprop
, sizeof (slotprop
));
3335 /* set mask to 1 as there is only one slot (i.e dev 0) */
3336 *(uint32_t *)slotprop
= 1;
3338 (void) snprintf(slotprop
+ len
, sizeof (slotprop
) - len
, "pcie%d",
3340 len
+= strlen(slotprop
+ len
) + 1;
3342 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
, "slot-names",
3343 (int *)slotprop
, len
/ sizeof (int));
3347 * Enable reporting of AER capability next pointer.
3348 * This needs to be done only for CK8-04 devices
3349 * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13
3350 * NOTE: BIOS is disabling this, it needs to be enabled temporarily
3352 * This function is adapted from npe_ck804_fix_aer_ptr(), and is
3353 * called from pci_boot.c.
3356 ck804_fix_aer_ptr(dev_info_t
*dip
, pcie_req_id_t bdf
)
3361 rcdip
= pcie_get_rc_dip(dip
);
3362 ASSERT(rcdip
!= NULL
);
3364 if ((pci_cfgacc_get16(rcdip
, bdf
, PCI_CONF_VENID
) ==
3365 NVIDIA_VENDOR_ID
) &&
3366 (pci_cfgacc_get16(rcdip
, bdf
, PCI_CONF_DEVID
) ==
3367 NVIDIA_CK804_DEVICE_ID
) &&
3368 (pci_cfgacc_get8(rcdip
, bdf
, PCI_CONF_REVID
) >=
3369 NVIDIA_CK804_AER_VALID_REVID
)) {
3370 cya1
= pci_cfgacc_get16(rcdip
, bdf
, NVIDIA_CK804_VEND_CYA1_OFF
);
3371 if (!(cya1
& ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK
))
3372 (void) pci_cfgacc_put16(rcdip
, bdf
,
3373 NVIDIA_CK804_VEND_CYA1_OFF
,
3374 cya1
| NVIDIA_CK804_VEND_CYA1_ERPT_VAL
);