xref: /illumos-gate/usr/src/uts/common/sys/plat/pci_prd.h (revision c43efa7f6b109f90d7f4962df8c0e1a94008d2d1)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2023 Oxide Computer Company
14  */
15 
16 #ifndef _SYS_PLAT_PCI_PRD_H
17 #define	_SYS_PLAT_PCI_PRD_H
18 
19 /*
20  * PCI Platform Resource Discovery (PRD)
21  *
22  * This file forms the platform-specific interfaces that a given platform must
23  * implement to support the discovery of PCI resources. In particular:
24  *
25  *  o Any root complexes that do not show up through the use of normal scanning
26  *  o Available resources per root-port including:
27  *	+ I/O ports
28  *	+ Prefetchable Memory
29  *	+ Normal Memory
30  *	+ PCI buses
31  *  o The naming of slots (the platform uses the PCIe default)
32  *
33  * These interfaces are all expected to be implemented by a platform's 'pci_prd'
34  * module. This is left as a module and not a part of say, unix, so that it can
35  * in turn depend on other modules that a platform might require, such as ACPI.
36  *
37  * In general, unless otherwise indicated, these interfaces will always be
38  * called from kernel context, typically during boot. The interfaces will only
39  * be called from a single thread at this time and any locking is managed at a
40  * layer outside of the pci_prd interfaces. If the subsystem is using some other
41  * interfaces that may be used by multiple consumers and needs locking (e.g.
42  * ACPI), then that still must be considered in the design and implementation.
43  */
44 
45 #include <sys/types.h>
46 #include <sys/memlist.h>
47 #include <sys/sunddi.h>
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 /*
54  * Resource types that can be asked after.
55  */
56 typedef enum pci_prd_rsrc {
57 	PCI_PRD_R_IO,
58 	PCI_PRD_R_MMIO,
59 	PCI_PRD_R_PREFETCH,
60 	PCI_PRD_R_BUS
61 } pci_prd_rsrc_t;
62 
63 typedef struct pci_prd_upcalls {
64 	/*
65 	 * Return a dev_info_t, if one exists, for this PCI bus.
66 	 */
67 	dev_info_t *(*pru_bus2dip_f)(uint32_t);
68 } pci_prd_upcalls_t;
69 
70 /*
71  * Initialization and teardown functions that will be used by the PCI
72  * enumeration code when it attaches and detaches. If all work is done before
73  * these come up, there is nothing to do; however, after a call to the _init()
74  * function, it is expected that the platform module will be ready to respond to
75  * all function calls.
76  *
77  * Note that the _fini function may never be called as on a typical system, as
78  * any PCI(e) devices with attached drivers will result in the PRD consumer
79  * remaining loaded.
80  */
81 extern int pci_prd_init(pci_prd_upcalls_t *);
82 extern void pci_prd_fini(void);
83 
84 /*
85  * Return the maximum PCI bus on this platform that should be searched. This
86  * number is the last bus number that should be scanned. e.g. a value of 0x10
87  * indicates that we will search buses [0, 0x10]. In general, it is expected
88  * that platforms will just return 0xff (PCI_MAX_BUS_NUM - 1) unless for some
89  * reason it has other knowledge here.
90  */
91 extern uint32_t pci_prd_max_bus(void);
92 
93 /*
94  * Look up a set of resources that should be assigned to the PCI bus. In
95  * general, it is expected that these are only the buses that are assigned to
96  * root complexes.
97  */
98 extern struct memlist *pci_prd_find_resource(uint32_t, pci_prd_rsrc_t);
99 
100 /*
101  * Originally when only using BIOS-derived (pre-ACPI) sources on i86pc, the
102  * ability to utilize data about multiple buses was considered suspect. As such,
103  * this exists as a way to indicate that resources on each root complex are
104  * actually valid.
105  */
106 extern boolean_t pci_prd_multi_root_ok(void);
107 
108 /*
109  * This is used to allow the PCI enumeration code to ask the platform about any
110  * PCI root complexes that it might know about which might not be discovered
111  * through the normal scanning process. One callback will be emitted for each
112  * PCI bus via a call to the callback function. The return value of the callback
113  * function determines whether we should continue iterating (B_TRUE) or
114  * terminate (B_FALSE).
115  */
116 typedef boolean_t (*pci_prd_root_complex_f)(uint32_t, void *);
117 extern void pci_prd_root_complex_iter(pci_prd_root_complex_f, void *);
118 
119 /*
120  * Give the chance for a platform to go through and use knowledge that it
121  * has (such as the traditional BIOS PCI IRQ routing table) to name the PCI(e)
122  * slot.
123  */
124 extern void pci_prd_slot_name(uint32_t, dev_info_t *);
125 
126 /*
127  * These are a series of flags that indicate how certain compatibility options
128  * should be specified and handled throughout the generic PCI stack. Unless
129  * there is history here (i.e. you are on some kind of x86 system), this should
130  * probably just return PCI_PRD_COMPAT_NONE.
131  */
132 typedef enum {
133 	PCI_PRD_COMPAT_NONE	= 0,
134 	/*
135 	 * Indicates that ISA is supported and ISA bridge nodes should be
136 	 * created.
137 	 */
138 	PCI_PRD_COMPAT_ISA		= 1 << 0,
139 	/*
140 	 * Indicates that the node name should only be "pci" and we should not
141 	 * entertain "pciex" for reasons of platform tradition. This also tells
142 	 * us that we should generate PCI alises for PCI Express devices.
143 	 */
144 	PCI_PRD_COMPAT_PCI_NODE_NAME	= 1 << 1,
145 	/*
146 	 * Indicates that we need subsystem compatibility. In particular this
147 	 * means that bridges will not use subsystem IDs for their node names
148 	 * and unqualified (',p' and ',s') aliases will be created for PCI.  See
149 	 * uts/common/io/pciex/pcie_props.c.
150 	 */
151 	PCI_PRD_COMPAT_SUBSYS		= 1 << 2
152 } pci_prd_compat_flags_t;
153 
154 extern pci_prd_compat_flags_t pci_prd_compat_flags(void);
155 
156 #ifdef __cplusplus
157 }
158 #endif
159 
160 #endif /* _SYS_PLAT_PCI_PRD_H */
161