Print this page
XXX nobios
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/os/pci_bios.c
+++ new/usr/src/uts/i86pc/os/pci_bios.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
25 25 #include <sys/types.h>
26 26 #include <sys/stat.h>
27 27 #include <sys/sunndi.h>
28 28 #include <sys/pci.h>
29 29 #include <sys/pci_impl.h>
30 30 #include <sys/pci_cfgspace.h>
31 31 #include <sys/pci_cfgspace_impl.h>
32 32 #include <sys/memlist.h>
33 33 #include <sys/bootconf.h>
34 34 #include <sys/psw.h>
35 +#include <sys/machsystm.h>
35 36
36 37 /*
37 38 * pci irq routing information table
38 39 */
39 40 int pci_irq_nroutes;
40 41 static pci_irq_route_t *pci_irq_routes;
41 42
42 43
43 44 static int pci_bios_get_irq_routing(pci_irq_route_t *, int, int *);
44 45 static void pci_get_irq_routing_table(void);
45 46
46 47
47 48 /*
48 49 * Retrieve information from the bios needed for system
49 50 * configuration early during startup.
50 51 */
51 52 void
52 53 startup_pci_bios(void)
53 54 {
54 55 pci_get_irq_routing_table();
55 56 }
56 57
57 58
58 59 /*
59 60 * Issue the bios get irq routing information table interrupt
60 61 *
61 62 * Despite the name, the information in the table is only
62 63 * used to derive slot names for some named pci hot-plug slots.
63 64 *
64 65 * Returns the number of irq routing table entries returned
65 66 * by the bios, or 0 and optionally, the number of entries required.
66 67 */
67 68 static int
68 69 pci_bios_get_irq_routing(pci_irq_route_t *routes, int nroutes, int *nneededp)
69 70 {
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
70 71 struct bop_regs regs;
71 72 uchar_t *hdrp;
72 73 uchar_t *bufp;
73 74 int i, n;
74 75 int rval = 0;
75 76
76 77 if (nneededp)
77 78 *nneededp = 0;
78 79
79 80 /*
81 + * If this system does not support BIOS calls, we can't use this
82 + * mechanism.
83 + */
84 + if (!bios_calls_available)
85 + return (0);
86 +
87 + /*
80 88 * Set up irq routing header with the size and address
81 89 * of some useable low-memory data addresses. Initalize
82 90 * data area to zero, avoiding memcpy/bzero.
83 91 */
84 92 hdrp = (uchar_t *)BIOS_IRQ_ROUTING_HDR;
85 93 bufp = (uchar_t *)BIOS_IRQ_ROUTING_DATA;
86 94
87 95 n = nroutes * sizeof (pci_irq_route_t);
88 96 for (i = 0; i < n; i++)
89 97 bufp[i] = 0;
90 98 ((pci_irq_route_hdr_t *)hdrp)->pir_size = n;
91 99 ((pci_irq_route_hdr_t *)hdrp)->pir_addr = (uint32_t)(uintptr_t)bufp;
92 100
93 101 bzero(®s, sizeof (regs));
94 102 regs.eax.word.ax = (PCI_FUNCTION_ID << 8) | PCI_GET_IRQ_ROUTING;
95 103
96 104 regs.ds = 0xf000;
97 105 regs.es = FP_SEG((uint_t)(uintptr_t)hdrp);
98 106 regs.edi.word.di = FP_OFF((uint_t)(uintptr_t)hdrp);
99 107
100 108 BOP_DOINT(bootops, 0x1a, ®s);
101 109
102 110 n = (int)(((pci_irq_route_hdr_t *)hdrp)->pir_size /
103 111 sizeof (pci_irq_route_t));
104 112
105 113 if ((regs.eflags & PS_C) != 0) {
106 114 if (nneededp)
107 115 *nneededp = n;
108 116 } else {
109 117 /*
110 118 * Copy resulting irq routing data from low memory up to
111 119 * the kernel address space, avoiding memcpy as usual.
112 120 */
113 121 if (n <= nroutes) {
114 122 for (i = 0; i < n * sizeof (pci_irq_route_t); i++)
115 123 ((uchar_t *)routes)[i] = bufp[i];
116 124 rval = n;
117 125 }
118 126 }
119 127 return (rval);
120 128 }
121 129
122 130 static void
123 131 pci_get_irq_routing_table(void)
124 132 {
125 133 pci_irq_route_t *routes;
126 134 int n = N_PCI_IRQ_ROUTES;
127 135 int nneeded = 0;
128 136 int nroutes;
129 137
130 138 /*
131 139 * Get irq routing table information.
132 140 * Allocate a buffer for an initial default number of entries.
133 141 * If the bios indicates it needs a larger buffer, try it again.
134 142 * Drive on if it still won't cooperate and play nice after that.
135 143 */
136 144 routes = kmem_zalloc(n * sizeof (pci_irq_route_t), KM_SLEEP);
137 145 nroutes = pci_bios_get_irq_routing(routes, n, &nneeded);
138 146 if (nroutes == 0 && nneeded > n) {
139 147 kmem_free(routes, n * sizeof (pci_irq_route_t));
140 148 if (nneeded > N_PCI_IRQ_ROUTES_MAX) {
141 149 cmn_err(CE_CONT,
142 150 "pci: unable to get IRQ routing information, "
143 151 "required buffer space of %d entries exceeds max\n",
144 152 nneeded);
145 153 return;
146 154 }
147 155 n = nneeded;
148 156 routes = kmem_zalloc(n * sizeof (pci_irq_route_t), KM_SLEEP);
149 157 nroutes = pci_bios_get_irq_routing(routes, n, NULL);
150 158 if (nroutes == 0) {
151 159 cmn_err(CE_CONT,
152 160 "pci: unable to get IRQ routing information, "
153 161 "required buffer space for %d entries\n", n);
154 162 kmem_free(routes, n * sizeof (pci_irq_route_t));
155 163 }
156 164 }
157 165
158 166 if (nroutes > 0) {
159 167 pci_irq_routes = routes;
160 168 pci_irq_nroutes = nroutes;
161 169 }
162 170 }
163 171
164 172 /*
165 173 * Use the results of the PCI BIOS call that returned the routing tables
166 174 * to build the 1275 slot-names property for the indicated bus.
167 175 * Results are returned in buf. Length is return value, -1 is returned on
168 176 * overflow and zero is returned if no data exists to build a property.
169 177 */
170 178 int
171 179 pci_slot_names_prop(int bus, char *buf, int len)
172 180 {
173 181 uchar_t dev;
174 182 uchar_t slot[N_PCI_IRQ_ROUTES_MAX+1];
175 183 uint32_t mask;
176 184 int i, nnames, plen;
177 185
178 186 ASSERT(pci_irq_nroutes <= N_PCI_IRQ_ROUTES_MAX);
179 187
180 188 if (pci_irq_nroutes == 0)
181 189 return (0);
182 190 nnames = 0;
183 191 mask = 0;
184 192 for (i = 0; i < pci_irq_nroutes; i++)
185 193 slot[i] = 0xff;
186 194 for (i = 0; i < pci_irq_nroutes; i++) {
187 195 if (pci_irq_routes[i].pir_bus != bus)
188 196 continue;
189 197 if (pci_irq_routes[i].pir_slot != 0) {
190 198 dev = (pci_irq_routes[i].pir_dev & 0xf8) >> 3;
191 199 slot[dev] = pci_irq_routes[i].pir_slot;
192 200 mask |= (1 << dev);
193 201 nnames++;
194 202 }
195 203 }
196 204
197 205 if (nnames == 0)
198 206 return (0);
199 207
200 208 if (len < (4 + nnames * 8))
201 209 return (-1);
202 210 *(uint32_t *)buf = mask;
203 211 plen = 4;
204 212 for (i = 0; i < pci_irq_nroutes; i++) {
205 213 if (slot[i] == 0xff)
206 214 continue;
207 215 (void) sprintf(buf + plen, "Slot%d", slot[i]);
208 216 plen += strlen(buf+plen) + 1;
209 217 *(buf + plen) = 0;
210 218 }
211 219 for (; plen % 4; plen++)
212 220 *(buf + plen) = 0;
213 221 return (plen);
214 222 }
↓ open down ↓ |
125 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX