]> git.saurik.com Git - apple/boot.git/blob - i386/libsaio/pci.c
7fd0542fa205735d24f9838b35afadface850ea0
[apple/boot.git] / i386 / libsaio / pci.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1994 NeXT Computer, Inc.
26 *
27 * PCI bus probing.
28 *
29 * HISTORY
30 *
31 * 03 May 1994 Dean Reece at NeXT
32 * Created
33 */
34
35 #include <mach/mach_types.h>
36 // #include "legacy/KernDevice.h"
37 #include "legacy/PCI.h"
38
39 #include "kernBootStruct.h"
40 #include "libsaio.h"
41 #include "io_inline.h"
42 #include "pci.h"
43
44 static BOOL testMethod1(void);
45 static BOOL testMethod2(void);
46 typedef unsigned long (*_pci_bus_method_t)(
47 unsigned char addr,
48 unsigned char dev,
49 unsigned char func,
50 unsigned char bus
51 );
52 static unsigned long getMethod1(
53 unsigned char addr,
54 unsigned char dev,
55 unsigned char func,
56 unsigned char bus
57 );
58 static unsigned long getMethod2(
59 unsigned char addr,
60 unsigned char dev,
61 unsigned char func,
62 unsigned char bus
63 );
64 static unsigned
65 scanBus(
66 unsigned maxBusNum,
67 unsigned maxDevNum,
68 _pci_bus_method_t method,
69 _pci_slot_info_t *slot_array
70 );
71
72 _pci_slot_info_t *PCISlotInfo;
73
74 _pci_slot_info_t *
75 PCI_Bus_Init(
76 PCI_bus_info_t *info /* pass in the PCI boot info struct */
77 )
78 {
79
80 unsigned int maxBusNum = 0, maxDevNum = 0, useMethod = 0;
81 _pci_bus_method_t method = NULL;
82 _pci_slot_info_t *slot_array;
83 unsigned nslots;
84
85 maxBusNum = info->maxBusNum;
86 if (info->BIOSPresent) {
87 if (info->u_bus.s.configMethod1) {
88 useMethod=1;
89 maxDevNum=31;
90 }
91 else if (info->u_bus.s.configMethod2) {
92 useMethod=2;
93 maxDevNum=15;
94 }
95 }
96 else {
97 if (testMethod1()) {
98 useMethod=1;
99 maxDevNum=31;
100 }
101 else if (testMethod2()) {
102 useMethod=2;
103 maxDevNum=15;
104 }
105 }
106
107
108 if (useMethod == 1)
109 method = getMethod1;
110 else if (useMethod == 2)
111 method = getMethod2;
112 else
113 return NULL;
114
115 nslots = scanBus(maxBusNum, maxDevNum, method, NULL);
116 slot_array = (_pci_slot_info_t *)
117 malloc(sizeof(_pci_slot_info_t) * nslots +1);
118 (void)scanBus(maxBusNum, maxDevNum, method, slot_array);
119 slot_array[nslots].pid = 0x00;
120 slot_array[nslots].sid = 0x00;
121 PCISlotInfo = slot_array;
122 return slot_array;
123 }
124
125 static unsigned
126 scanBus(
127 unsigned maxBusNum,
128 unsigned maxDevNum,
129 _pci_bus_method_t method,
130 _pci_slot_info_t *slot_array
131 )
132 {
133 unsigned int bus, dev, func;
134 unsigned int pid=0, sid=0;
135 unsigned count = 0;
136
137 for (bus=0; bus<=maxBusNum; bus++) {
138 for (dev=0; dev<=maxDevNum; dev++) {
139 for (func=0; func<8; func++) {
140 pid = (*method)(0x00, dev, func, bus);
141 if ( ((pid&0xffff) != 0xffff) &&
142 ((pid&0xffff) != 0x0000) ) {
143
144 /* device found, do whatever here */
145 count++;
146 if (slot_array) {
147 sid = (*method)(0x2c, dev, func, bus);
148 slot_array->pid = pid;
149 slot_array->sid = sid;
150 slot_array->dev = dev;
151 slot_array->func = func;
152 slot_array->bus = bus;
153 slot_array++;
154 #if DEBUG
155 printf ("{\"0x%08x:%08x\" = {\"Location\" = \"Dev:%d Func:%d Bus:%d\"; }\n",
156 pid, sid, dev, func, bus);
157 #endif
158 }
159
160 /* skip 1..7 if not multi-func device */
161 pid = (*method)(12, dev, func, bus);
162 if ((pid & 0x00800000)==0) break;
163 }
164 }
165 }
166 }
167 return count;
168 }
169
170 /* defines for Configuration Method #1 (PCI 2.0 Spec, sec 3.6.4.1.1) */
171 #define PCI_CONFIG_ADDRESS 0x0cf8
172 #define PCI_CONFIG_DATA 0x0cfc
173
174 static BOOL
175 testMethod1(void)
176 {
177 unsigned long address, data;
178
179 for (address = 0x80000000; address < 0x80010000; address += 0x800) {
180 outl (PCI_CONFIG_ADDRESS, address);
181 if (inl (PCI_CONFIG_ADDRESS) != address) {
182 return NO;
183 }
184 data = inl(PCI_CONFIG_DATA);
185 if ((data != PCI_DEFAULT_DATA) && (data != 0x00)) {
186 outl (PCI_CONFIG_ADDRESS, 0);
187 return YES;
188 }
189 }
190
191 outl (PCI_CONFIG_ADDRESS, 0);
192 return NO;
193 }
194
195 static unsigned long
196 getMethod1(
197 unsigned char addr,
198 unsigned char dev,
199 unsigned char func,
200 unsigned char bus
201 )
202 {
203 unsigned long ret=PCI_DEFAULT_DATA;
204
205 union {
206 unsigned long d;
207 struct {
208 unsigned long addr:8;
209 unsigned long func:3;
210 unsigned long dev:5;
211 unsigned long bus:8;
212 unsigned long key:8;
213 } s;
214 } address;
215
216 address.d = 0x00000000;
217 address.s.key=0x80;
218 address.s.addr=addr;
219 address.s.dev=dev;
220 address.s.func=func;
221 address.s.bus=bus;
222 outl (PCI_CONFIG_ADDRESS, address.d);
223
224 if (inl (PCI_CONFIG_ADDRESS) == address.d)
225 ret = inl(PCI_CONFIG_DATA);
226
227 outl (PCI_CONFIG_ADDRESS, 0);
228 return ret;
229 }
230
231
232 /* defines for Configuration Method #2 (PCI 2.0 Spec, sec 3.6.4.1.3) */
233 #define PCI_CSE_REGISTER 0x0cf8
234 #define PCI_BUS_FORWARD 0x0cfa
235
236 static BOOL
237 testMethod2(void)
238 {
239 unsigned long address, data;
240
241 /* Enable configuration space at I/O ports Cxxx. */
242
243 outb (PCI_CSE_REGISTER, 0xF0);
244 if (inb (PCI_CSE_REGISTER) != 0xF0) {
245 return NO;
246 }
247
248 outb (PCI_BUS_FORWARD, 0x00);
249 if (inb (PCI_BUS_FORWARD) != 0x00) {
250 return NO;
251 }
252 /* Search all devices on the bus. */
253 for (address = 0xc000; address <= 0xcfff; address += 0x100) {
254 data = inl(address);
255 if ((data != PCI_DEFAULT_DATA) && (data != 0x00)) {
256 outb (PCI_CSE_REGISTER, 0);
257 return YES;
258 }
259 }
260
261 outb (PCI_CSE_REGISTER, 0);
262 return NO;
263 }
264
265 static unsigned long
266 getMethod2(
267 unsigned char addr,
268 unsigned char dev,
269 unsigned char func,
270 unsigned char bus
271 )
272 {
273 unsigned long ret=PCI_DEFAULT_DATA;
274 unsigned short address;
275 unsigned char cse;
276
277 cse = 0xf0 | (func<<1);
278 outb(PCI_CSE_REGISTER, cse);
279 if (inb(PCI_CSE_REGISTER) == cse) {
280 outb(PCI_BUS_FORWARD, bus);
281 if (inb(PCI_BUS_FORWARD) == bus) {
282 address = 0xc000 | (addr&0xfc) | ((dev&0x0f)<<8);
283 ret = inl(address);
284 }
285 outb(PCI_BUS_FORWARD, 0x00);
286 }
287 outb(PCI_CSE_REGISTER, 0x00);
288
289 return ret;
290 }
291