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