3973
|
1 /*
|
|
2 (C) 2002 - library implementation by Nick Kyrshev
|
|
3 XFree86 3.3.3 scanpci.c, modified for GATOS/win/gfxdump by Øyvind Aabling.
|
|
4 */
|
|
5
|
|
6 #include "libdha.h"
|
|
7
|
|
8 #include <errno.h>
|
|
9 #include <string.h>
|
|
10 #include "AsmMacros.h"
|
|
11 #ifdef __unix__
|
|
12 #include <unistd.h>
|
|
13 #include <sys/mman.h>
|
|
14 #elif defined ( _WIN32 )
|
|
15 #include <windows.h>
|
|
16 #else
|
|
17 #include <dos.h>
|
|
18 #endif
|
|
19
|
|
20 #define outb pcioutb
|
|
21 #define outl pcioutl
|
|
22 #define inb pciinb
|
|
23 #define inl pciinl
|
|
24
|
|
25 /* $XConsortium: scanpci.c /main/25 1996/10/27 11:48:40 kaleb $ */
|
|
26 /*
|
|
27 * name: scanpci.c
|
|
28 *
|
|
29 * purpose: This program will scan for and print details of
|
|
30 * devices on the PCI bus.
|
|
31
|
|
32 * author: Robin Cutshaw (robin@xfree86.org)
|
|
33 *
|
|
34 * supported O/S's: SVR4, UnixWare, SCO, Solaris,
|
|
35 * FreeBSD, NetBSD, 386BSD, BSDI BSD/386,
|
|
36 * Linux, Mach/386, ISC
|
|
37 * DOS (WATCOM 9.5 compiler)
|
|
38 *
|
|
39 * compiling: [g]cc scanpci.c -o scanpci
|
|
40 * for SVR4 (not Solaris), UnixWare use:
|
|
41 * [g]cc -DSVR4 scanpci.c -o scanpci
|
|
42 * for DOS, watcom 9.5:
|
|
43 * wcc386p -zq -omaxet -7 -4s -s -w3 -d2 name.c
|
|
44 * and link with PharLap or other dos extender for exe
|
|
45 *
|
|
46 */
|
|
47
|
|
48 /* $XFree86: xc/programs/Xserver/hw/xfree86/etc/scanpci.c,v 3.34.2.17 1998/11/10 11:55:40 dawes Exp $ */
|
|
49
|
|
50 /*
|
|
51 * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org>
|
|
52 *
|
|
53 * Permission to use, copy, modify, distribute, and sell this software and its
|
|
54 * documentation for any purpose is hereby granted without fee, provided that
|
|
55 * the above copyright notice appear in all copies and that both that
|
|
56 * copyright notice and this permission notice appear in supporting
|
|
57 * documentation, and that the names of the above listed copyright holder(s)
|
|
58 * not be used in advertising or publicity pertaining to distribution of
|
|
59 * the software without specific, written prior permission. The above listed
|
|
60 * copyright holder(s) make(s) no representations about the suitability of this
|
|
61 * software for any purpose. It is provided "as is" without express or
|
|
62 * implied warranty.
|
|
63 *
|
|
64 * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
|
|
65 * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
66 * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
|
|
67 * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
|
|
68 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
|
69 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
70 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
71 *
|
|
72 */
|
|
73
|
|
74 #if defined(__SVR4)
|
|
75 #if !defined(SVR4)
|
|
76 #define SVR4
|
|
77 #endif
|
|
78 #endif
|
|
79
|
|
80 #ifdef __EMX__
|
|
81 #define INCL_DOSFILEMGR
|
|
82 #include <os2.h>
|
|
83 #endif
|
|
84
|
|
85 #include <stdio.h>
|
|
86 #include <sys/types.h>
|
|
87 #if defined(SVR4)
|
|
88 #if defined(sun)
|
|
89 #ifndef __EXTENSIONS__
|
|
90 #define __EXTENSIONS__
|
|
91 #endif
|
|
92 #endif
|
|
93 #include <sys/proc.h>
|
|
94 #include <sys/tss.h>
|
|
95 #if defined(NCR)
|
|
96 #define __STDC
|
|
97 #include <sys/sysi86.h>
|
|
98 #undef __STDC
|
|
99 #else
|
|
100 #include <sys/sysi86.h>
|
|
101 #endif
|
|
102 #if defined(__SUNPRO_C) || defined(sun) || defined(__sun)
|
|
103 #include <sys/psw.h>
|
|
104 #else
|
|
105 #include <sys/seg.h>
|
|
106 #endif
|
|
107 #include <sys/v86.h>
|
|
108 #endif
|
|
109 #if defined(__FreeBSD__) || defined(__386BSD__)
|
|
110 #include <sys/file.h>
|
|
111 #include <machine/console.h>
|
|
112 #ifndef GCCUSESGAS
|
|
113 #define GCCUSESGAS
|
|
114 #endif
|
|
115 #endif
|
|
116 #if defined(__NetBSD__)
|
|
117 #include <sys/param.h>
|
|
118 #include <sys/file.h>
|
|
119 #include <machine/sysarch.h>
|
|
120 #ifndef GCCUSESGAS
|
|
121 #define GCCUSESGAS
|
|
122 #endif
|
|
123 #endif
|
|
124 #if defined(__bsdi__)
|
|
125 #include <sys/file.h>
|
|
126 #include <sys/ioctl.h>
|
|
127 #include <i386/isa/pcconsioctl.h>
|
|
128 #ifndef GCCUSESGAS
|
|
129 #define GCCUSESGAS
|
|
130 #endif
|
|
131 #endif
|
|
132 #if defined(SCO) || defined(ISC)
|
|
133 #ifndef ISC
|
|
134 #include <sys/console.h>
|
|
135 #endif
|
|
136 #include <sys/param.h>
|
|
137 #include <sys/immu.h>
|
|
138 #include <sys/region.h>
|
|
139 #include <sys/proc.h>
|
|
140 #include <sys/tss.h>
|
|
141 #include <sys/sysi86.h>
|
|
142 #include <sys/v86.h>
|
|
143 #endif
|
|
144 #if defined(Lynx_22)
|
|
145 #ifndef GCCUSESGAS
|
|
146 #define GCCUSESGAS
|
|
147 #endif
|
|
148 #endif
|
|
149
|
|
150
|
|
151 #if defined(__WATCOMC__)
|
|
152
|
|
153 #include <stdlib.h>
|
|
154 static void outl(unsigned port, unsigned data);
|
|
155 #pragma aux outl = "out dx, eax" parm [dx] [eax];
|
|
156 static void outb(unsigned port, unsigned data);
|
|
157 #pragma aux outb = "out dx, al" parm [dx] [eax];
|
|
158 static unsigned inl(unsigned port);
|
|
159 #pragma aux inl = "in eax, dx" parm [dx];
|
|
160 static unsigned inb(unsigned port);
|
|
161 #pragma aux inb = "xor eax,eax" "in al, dx" parm [dx];
|
|
162
|
|
163 #else /* __WATCOMC__ */
|
|
164
|
|
165 #if defined(__GNUC__)
|
|
166
|
|
167 #if !defined(__alpha__) && !defined(__powerpc__)
|
|
168 #if defined(GCCUSESGAS)
|
|
169 #define OUTB_GCC "outb %0,%1"
|
|
170 #define OUTL_GCC "outl %0,%1"
|
|
171 #define INB_GCC "inb %1,%0"
|
|
172 #define INL_GCC "inl %1,%0"
|
|
173 #else
|
|
174 #define OUTB_GCC "out%B0 (%1)"
|
|
175 #define OUTL_GCC "out%L0 (%1)"
|
|
176 #define INB_GCC "in%B0 (%1)"
|
|
177 #define INL_GCC "in%L0 (%1)"
|
|
178 #endif /* GCCUSESGAS */
|
|
179
|
|
180 static void outb(unsigned short port, unsigned char val) {
|
|
181 __asm__ __volatile__(OUTB_GCC : :"a" (val), "d" (port)); }
|
|
182 static void outl(unsigned short port, unsigned long val) {
|
|
183 __asm__ __volatile__(OUTL_GCC : :"a" (val), "d" (port)); }
|
|
184 static unsigned char inb(unsigned short port) { unsigned char ret;
|
|
185 __asm__ __volatile__(INB_GCC : "=a" (ret) : "d" (port)); return ret; }
|
|
186 static unsigned long inl(unsigned short port) { unsigned long ret;
|
|
187 __asm__ __volatile__(INL_GCC : "=a" (ret) : "d" (port)); return ret; }
|
|
188
|
|
189 #endif /* !defined(__alpha__) && !defined(__powerpc__) */
|
|
190 #else /* __GNUC__ */
|
|
191
|
|
192 #if defined(__STDC__) && (__STDC__ == 1)
|
|
193 # if !defined(NCR)
|
|
194 # define asm __asm
|
|
195 # endif
|
|
196 #endif
|
|
197
|
|
198 #if defined(__SUNPRO_C)
|
|
199 /*
|
|
200 * This section is a gross hack in if you tell anyone that I wrote it,
|
|
201 * I'll deny it. :-)
|
|
202 * The leave/ret instructions are the big hack to leave %eax alone on return.
|
|
203 */
|
|
204 static unsigned char inb(int port) {
|
|
205 asm(" movl 8(%esp),%edx");
|
|
206 asm(" subl %eax,%eax");
|
|
207 asm(" inb (%dx)");
|
|
208 asm(" leave");
|
|
209 asm(" ret");
|
|
210 }
|
|
211
|
|
212 static unsigned short inw(int port) {
|
|
213 asm(" movl 8(%esp),%edx");
|
|
214 asm(" subl %eax,%eax");
|
|
215 asm(" inw (%dx)");
|
|
216 asm(" leave");
|
|
217 asm(" ret");
|
|
218 }
|
|
219
|
|
220 static unsigned long inl(int port) {
|
|
221 asm(" movl 8(%esp),%edx");
|
|
222 asm(" inl (%dx)");
|
|
223 asm(" leave");
|
|
224 asm(" ret");
|
|
225 }
|
|
226
|
|
227 static void outb(int port, unsigned char value) {
|
|
228 asm(" movl 8(%esp),%edx");
|
|
229 asm(" movl 12(%esp),%eax");
|
|
230 asm(" outb (%dx)");
|
|
231 }
|
|
232
|
|
233 static void outw(int port, unsigned short value) {
|
|
234 asm(" movl 8(%esp),%edx");
|
|
235 asm(" movl 12(%esp),%eax");
|
|
236 asm(" outw (%dx)");
|
|
237 }
|
|
238
|
|
239 static void outl(int port, unsigned long value) {
|
|
240 asm(" movl 8(%esp),%edx");
|
|
241 asm(" movl 12(%esp),%eax");
|
|
242 asm(" outl (%dx)");
|
|
243 }
|
|
244 #else
|
|
245
|
|
246 #if defined(SVR4)
|
|
247 # if !defined(__USLC__)
|
|
248 # define __USLC__
|
|
249 # endif
|
|
250 #endif
|
|
251
|
|
252 #ifdef __unix__
|
|
253 #ifndef SCO325
|
|
254 # include <sys/inline.h>
|
|
255 #else
|
|
256 # include "scoasm.h"
|
|
257 #endif
|
|
258 #endif
|
|
259
|
|
260 #endif /* SUNPRO_C */
|
|
261
|
|
262 #endif /* __GNUC__ */
|
|
263 #endif /* __WATCOMC__ */
|
|
264
|
|
265 #undef outb
|
|
266 #undef outl
|
|
267 #undef inb
|
|
268 #undef inl
|
|
269
|
|
270 #if defined(__GLIBC__) && __GLIBC__ >= 2
|
|
271 #if defined(linux)
|
|
272 #include <sys/perm.h>
|
|
273 #endif
|
|
274 #endif
|
|
275
|
|
276 #if defined(__alpha__)
|
|
277 #if defined(linux)
|
|
278 #include <asm/unistd.h>
|
|
279 #define BUS(tag) (((tag)>>16)&0xff)
|
|
280 #define DFN(tag) (((tag)>>8)&0xff)
|
|
281 static int pciconfig_read(
|
|
282 unsigned char bus,
|
|
283 unsigned char dfn,
|
|
284 unsigned char off,
|
|
285 unsigned char len,
|
|
286 void * buf)
|
|
287 {
|
|
288 return syscall(__NR_pciconfig_read, bus, dfn, off, len, buf);
|
|
289 }
|
|
290
|
|
291 static int pciconfig_write(
|
|
292 unsigned char bus,
|
|
293 unsigned char dfn,
|
|
294 unsigned char off,
|
|
295 unsigned char len,
|
|
296 void * buf)
|
|
297 {
|
|
298 return syscall(__NR_pciconfig_write, bus, dfn, off, len, buf);
|
|
299 }
|
|
300 #else
|
|
301 Generate compiler error - scanpci unsupported on non-linux alpha platforms
|
|
302 #endif /* linux */
|
|
303 #endif /* __alpha__ */
|
|
304 #if defined(Lynx) && defined(__powerpc__)
|
|
305 /* let's mimick the Linux Alpha stuff for LynxOS so we don't have
|
|
306 * to change too much code
|
|
307 */
|
|
308 #include <smem.h>
|
|
309
|
|
310 static unsigned char *pciConfBase;
|
|
311
|
|
312 static __inline__ unsigned long
|
|
313 static swapl(unsigned long val)
|
|
314 {
|
|
315 unsigned char *p = (unsigned char *)&val;
|
|
316 return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0));
|
|
317 }
|
|
318
|
|
319
|
|
320 #define BUS(tag) (((tag)>>16)&0xff)
|
|
321 #define DFN(tag) (((tag)>>8)&0xff)
|
|
322
|
|
323 #define PCIBIOS_DEVICE_NOT_FOUND 0x86
|
|
324 #define PCIBIOS_SUCCESSFUL 0x00
|
|
325
|
|
326 static int pciconfig_read(
|
|
327 unsigned char bus,
|
|
328 unsigned char dev,
|
|
329 unsigned char offset,
|
|
330 int len, /* unused, alway 4 */
|
|
331 unsigned long *val)
|
|
332 {
|
|
333 unsigned long _val;
|
|
334 unsigned long *ptr;
|
|
335
|
|
336 dev >>= 3;
|
|
337 if (bus || dev >= 16) {
|
|
338 *val = 0xFFFFFFFF;
|
|
339 return PCIBIOS_DEVICE_NOT_FOUND;
|
|
340 } else {
|
|
341 ptr = (unsigned long *)(pciConfBase + ((1<<dev) | offset));
|
|
342 _val = swapl(*ptr);
|
|
343 }
|
|
344 *val = _val;
|
|
345 return PCIBIOS_SUCCESSFUL;
|
|
346 }
|
|
347
|
|
348 static int pciconfig_write(
|
|
349 unsigned char bus,
|
|
350 unsigned char dev,
|
|
351 unsigned char offset,
|
|
352 int len, /* unused, alway 4 */
|
|
353 unsigned long val)
|
|
354 {
|
|
355 unsigned long _val;
|
|
356 unsigned long *ptr;
|
|
357
|
|
358 dev >>= 3;
|
|
359 _val = swapl(val);
|
|
360 if (bus || dev >= 16) {
|
|
361 return PCIBIOS_DEVICE_NOT_FOUND;
|
|
362 } else {
|
|
363 ptr = (unsigned long *)(pciConfBase + ((1<<dev) | offset));
|
|
364 *ptr = _val;
|
|
365 }
|
|
366 return PCIBIOS_SUCCESSFUL;
|
|
367 }
|
|
368 #endif
|
|
369
|
|
370 #if !defined(__powerpc__)
|
|
371 struct pci_config_reg {
|
|
372 /* start of official PCI config space header */
|
|
373 union {
|
|
374 unsigned long device_vendor;
|
|
375 struct {
|
|
376 unsigned short vendor;
|
|
377 unsigned short device;
|
|
378 } dv;
|
|
379 } dv_id;
|
|
380 #define _device_vendor dv_id.device_vendor
|
|
381 #define _vendor dv_id.dv.vendor
|
|
382 #define _device dv_id.dv.device
|
|
383 union {
|
|
384 unsigned long status_command;
|
|
385 struct {
|
|
386 unsigned short command;
|
|
387 unsigned short status;
|
|
388 } sc;
|
|
389 } stat_cmd;
|
|
390 #define _status_command stat_cmd.status_command
|
|
391 #define _command stat_cmd.sc.command
|
|
392 #define _status stat_cmd.sc.status
|
|
393 union {
|
|
394 unsigned long class_revision;
|
|
395 struct {
|
|
396 unsigned char rev_id;
|
|
397 unsigned char prog_if;
|
|
398 unsigned char sub_class;
|
|
399 unsigned char base_class;
|
|
400 } cr;
|
|
401 } class_rev;
|
|
402 #define _class_revision class_rev.class_revision
|
|
403 #define _rev_id class_rev.cr.rev_id
|
|
404 #define _prog_if class_rev.cr.prog_if
|
|
405 #define _sub_class class_rev.cr.sub_class
|
|
406 #define _base_class class_rev.cr.base_class
|
|
407 union {
|
|
408 unsigned long bist_header_latency_cache;
|
|
409 struct {
|
|
410 unsigned char cache_line_size;
|
|
411 unsigned char latency_timer;
|
|
412 unsigned char header_type;
|
|
413 unsigned char bist;
|
|
414 } bhlc;
|
|
415 } bhlc;
|
|
416 #define _bist_header_latency_cache bhlc.bist_header_latency_cache
|
|
417 #define _cache_line_size bhlc.bhlc.cache_line_size
|
|
418 #define _latency_timer bhlc.bhlc.latency_timer
|
|
419 #define _header_type bhlc.bhlc.header_type
|
|
420 #define _bist bhlc.bhlc.bist
|
|
421 union {
|
|
422 struct {
|
|
423 unsigned long dv_base0;
|
|
424 unsigned long dv_base1;
|
|
425 unsigned long dv_base2;
|
|
426 unsigned long dv_base3;
|
|
427 unsigned long dv_base4;
|
|
428 unsigned long dv_base5;
|
|
429 } dv;
|
|
430 struct {
|
|
431 unsigned long bg_rsrvd[2];
|
|
432 unsigned char primary_bus_number;
|
|
433 unsigned char secondary_bus_number;
|
|
434 unsigned char subordinate_bus_number;
|
|
435 unsigned char secondary_latency_timer;
|
|
436 unsigned char io_base;
|
|
437 unsigned char io_limit;
|
|
438 unsigned short secondary_status;
|
|
439 unsigned short mem_base;
|
|
440 unsigned short mem_limit;
|
|
441 unsigned short prefetch_mem_base;
|
|
442 unsigned short prefetch_mem_limit;
|
|
443 } bg;
|
|
444 } bc;
|
|
445 #define _base0 bc.dv.dv_base0
|
|
446 #define _base1 bc.dv.dv_base1
|
|
447 #define _base2 bc.dv.dv_base2
|
|
448 #define _base3 bc.dv.dv_base3
|
|
449 #define _base4 bc.dv.dv_base4
|
|
450 #define _base5 bc.dv.dv_base5
|
|
451 #define _primary_bus_number bc.bg.primary_bus_number
|
|
452 #define _secondary_bus_number bc.bg.secondary_bus_number
|
|
453 #define _subordinate_bus_number bc.bg.subordinate_bus_number
|
|
454 #define _secondary_latency_timer bc.bg.secondary_latency_timer
|
|
455 #define _io_base bc.bg.io_base
|
|
456 #define _io_limit bc.bg.io_limit
|
|
457 #define _secondary_status bc.bg.secondary_status
|
|
458 #define _mem_base bc.bg.mem_base
|
|
459 #define _mem_limit bc.bg.mem_limit
|
|
460 #define _prefetch_mem_base bc.bg.prefetch_mem_base
|
|
461 #define _prefetch_mem_limit bc.bg.prefetch_mem_limit
|
|
462 unsigned long rsvd1;
|
|
463 unsigned long rsvd2;
|
|
464 unsigned long _baserom;
|
|
465 unsigned long rsvd3;
|
|
466 unsigned long rsvd4;
|
|
467 union {
|
|
468 unsigned long max_min_ipin_iline;
|
|
469 struct {
|
|
470 unsigned char int_line;
|
|
471 unsigned char int_pin;
|
|
472 unsigned char min_gnt;
|
|
473 unsigned char max_lat;
|
|
474 } mmii;
|
|
475 } mmii;
|
|
476 #define _max_min_ipin_iline mmii.max_min_ipin_iline
|
|
477 #define _int_line mmii.mmii.int_line
|
|
478 #define _int_pin mmii.mmii.int_pin
|
|
479 #define _min_gnt mmii.mmii.min_gnt
|
|
480 #define _max_lat mmii.mmii.max_lat
|
|
481 /* I don't know how accurate or standard this is (DHD) */
|
|
482 union {
|
|
483 unsigned long user_config;
|
|
484 struct {
|
|
485 unsigned char user_config_0;
|
|
486 unsigned char user_config_1;
|
|
487 unsigned char user_config_2;
|
|
488 unsigned char user_config_3;
|
|
489 } uc;
|
|
490 } uc;
|
|
491 #define _user_config uc.user_config
|
|
492 #define _user_config_0 uc.uc.user_config_0
|
|
493 #define _user_config_1 uc.uc.user_config_1
|
|
494 #define _user_config_2 uc.uc.user_config_2
|
|
495 #define _user_config_3 uc.uc.user_config_3
|
|
496 /* end of official PCI config space header */
|
|
497 unsigned long _pcibusidx;
|
|
498 unsigned long _pcinumbus;
|
|
499 unsigned long _pcibuses[16];
|
|
500 unsigned short _configtype; /* config type found */
|
|
501 unsigned short _ioaddr; /* config type 1 - private I/O addr */
|
|
502 unsigned long _cardnum; /* config type 2 - private card number */
|
|
503 };
|
|
504 #else
|
|
505 /* ppc is big endian, swapping bytes is not quite enough
|
|
506 * to interpret the PCI config registers...
|
|
507 */
|
|
508 struct pci_config_reg {
|
|
509 /* start of official PCI config space header */
|
|
510 union {
|
|
511 unsigned long device_vendor;
|
|
512 struct {
|
|
513 unsigned short device;
|
|
514 unsigned short vendor;
|
|
515 } dv;
|
|
516 } dv_id;
|
|
517 #define _device_vendor dv_id.device_vendor
|
|
518 #define _vendor dv_id.dv.vendor
|
|
519 #define _device dv_id.dv.device
|
|
520 union {
|
|
521 unsigned long status_command;
|
|
522 struct {
|
|
523 unsigned short status;
|
|
524 unsigned short command;
|
|
525 } sc;
|
|
526 } stat_cmd;
|
|
527 #define _status_command stat_cmd.status_command
|
|
528 #define _command stat_cmd.sc.command
|
|
529 #define _status stat_cmd.sc.status
|
|
530 union {
|
|
531 unsigned long class_revision;
|
|
532 struct {
|
|
533 unsigned char base_class;
|
|
534 unsigned char sub_class;
|
|
535 unsigned char prog_if;
|
|
536 unsigned char rev_id;
|
|
537 } cr;
|
|
538 } class_rev;
|
|
539 #define _class_revision class_rev.class_revision
|
|
540 #define _rev_id class_rev.cr.rev_id
|
|
541 #define _prog_if class_rev.cr.prog_if
|
|
542 #define _sub_class class_rev.cr.sub_class
|
|
543 #define _base_class class_rev.cr.base_class
|
|
544 union {
|
|
545 unsigned long bist_header_latency_cache;
|
|
546 struct {
|
|
547 unsigned char bist;
|
|
548 unsigned char header_type;
|
|
549 unsigned char latency_timer;
|
|
550 unsigned char cache_line_size;
|
|
551 } bhlc;
|
|
552 } bhlc;
|
|
553 #define _bist_header_latency_cache bhlc.bist_header_latency_cache
|
|
554 #define _cache_line_size bhlc.bhlc.cache_line_size
|
|
555 #define _latency_timer bhlc.bhlc.latency_timer
|
|
556 #define _header_type bhlc.bhlc.header_type
|
|
557 #define _bist bhlc.bhlc.bist
|
|
558 union {
|
|
559 struct {
|
|
560 unsigned long dv_base0;
|
|
561 unsigned long dv_base1;
|
|
562 unsigned long dv_base2;
|
|
563 unsigned long dv_base3;
|
|
564 unsigned long dv_base4;
|
|
565 unsigned long dv_base5;
|
|
566 } dv;
|
|
567 /* ?? */
|
|
568 struct {
|
|
569 unsigned long bg_rsrvd[2];
|
|
570
|
|
571 unsigned char secondary_latency_timer;
|
|
572 unsigned char subordinate_bus_number;
|
|
573 unsigned char secondary_bus_number;
|
|
574 unsigned char primary_bus_number;
|
|
575
|
|
576 unsigned short secondary_status;
|
|
577 unsigned char io_limit;
|
|
578 unsigned char io_base;
|
|
579
|
|
580 unsigned short mem_limit;
|
|
581 unsigned short mem_base;
|
|
582
|
|
583 unsigned short prefetch_mem_limit;
|
|
584 unsigned short prefetch_mem_base;
|
|
585 } bg;
|
|
586 } bc;
|
|
587 #define _base0 bc.dv.dv_base0
|
|
588 #define _base1 bc.dv.dv_base1
|
|
589 #define _base2 bc.dv.dv_base2
|
|
590 #define _base3 bc.dv.dv_base3
|
|
591 #define _base4 bc.dv.dv_base4
|
|
592 #define _base5 bc.dv.dv_base5
|
|
593 #define _primary_bus_number bc.bg.primary_bus_number
|
|
594 #define _secondary_bus_number bc.bg.secondary_bus_number
|
|
595 #define _subordinate_bus_number bc.bg.subordinate_bus_number
|
|
596 #define _secondary_latency_timer bc.bg.secondary_latency_timer
|
|
597 #define _io_base bc.bg.io_base
|
|
598 #define _io_limit bc.bg.io_limit
|
|
599 #define _secondary_status bc.bg.secondary_status
|
|
600 #define _mem_base bc.bg.mem_base
|
|
601 #define _mem_limit bc.bg.mem_limit
|
|
602 #define _prefetch_mem_base bc.bg.prefetch_mem_base
|
|
603 #define _prefetch_mem_limit bc.bg.prefetch_mem_limit
|
|
604 unsigned long rsvd1;
|
|
605 unsigned long rsvd2;
|
|
606 unsigned long _baserom;
|
|
607 unsigned long rsvd3;
|
|
608 unsigned long rsvd4;
|
|
609 union {
|
|
610 unsigned long max_min_ipin_iline;
|
|
611 struct {
|
|
612 unsigned char max_lat;
|
|
613 unsigned char min_gnt;
|
|
614 unsigned char int_pin;
|
|
615 unsigned char int_line;
|
|
616 } mmii;
|
|
617 } mmii;
|
|
618 #define _max_min_ipin_iline mmii.max_min_ipin_iline
|
|
619 #define _int_line mmii.mmii.int_line
|
|
620 #define _int_pin mmii.mmii.int_pin
|
|
621 #define _min_gnt mmii.mmii.min_gnt
|
|
622 #define _max_lat mmii.mmii.max_lat
|
|
623 /* I don't know how accurate or standard this is (DHD) */
|
|
624 union {
|
|
625 unsigned long user_config;
|
|
626 struct {
|
|
627 unsigned char user_config_3;
|
|
628 unsigned char user_config_2;
|
|
629 unsigned char user_config_1;
|
|
630 unsigned char user_config_0;
|
|
631 } uc;
|
|
632 } uc;
|
|
633 #define _user_config uc.user_config
|
|
634 #define _user_config_0 uc.uc.user_config_0
|
|
635 #define _user_config_1 uc.uc.user_config_1
|
|
636 #define _user_config_2 uc.uc.user_config_2
|
|
637 #define _user_config_3 uc.uc.user_config_3
|
|
638 /* end of official PCI config space header */
|
|
639 unsigned long _pcibusidx;
|
|
640 unsigned long _pcinumbus;
|
|
641 unsigned long _pcibuses[16];
|
|
642 unsigned short _ioaddr; /* config type 1 - private I/O addr */
|
|
643 unsigned short _configtype; /* config type found */
|
|
644 unsigned long _cardnum; /* config type 2 - private card number */
|
|
645 };
|
|
646 #endif
|
|
647
|
|
648 #define MAX_DEV_PER_VENDOR_CFG1 64
|
|
649 #define MAX_PCI_DEVICES_PER_BUS 32
|
|
650 #define MAX_PCI_DEVICES 64
|
|
651 #define NF ((void (*)())NULL), { 0.0, 0, 0, NULL }
|
|
652 #define PCI_MULTIFUNC_DEV 0x80
|
|
653 #if defined(__alpha__) || defined(__powerpc__)
|
|
654 #define PCI_ID_REG 0x00
|
|
655 #define PCI_CMD_STAT_REG 0x04
|
|
656 #define PCI_CLASS_REG 0x08
|
|
657 #define PCI_HEADER_MISC 0x0C
|
|
658 #define PCI_MAP_REG_START 0x10
|
|
659 #define PCI_MAP_ROM_REG 0x30
|
|
660 #define PCI_INTERRUPT_REG 0x3C
|
|
661 #define PCI_REG_USERCONFIG 0x40
|
|
662 #endif
|
|
663
|
|
664 static int pcibus=-1, pcicard=-1, pcifunc=-1 ;
|
|
665 /*static struct pci_device *pcidev=NULL ;*/
|
|
666
|
|
667 #if defined(__alpha__)
|
|
668 #define PCI_EN 0x00000000
|
|
669 #else
|
|
670 #define PCI_EN 0x80000000
|
|
671 #endif
|
|
672
|
|
673 #define PCI_MODE1_ADDRESS_REG 0xCF8
|
|
674 #define PCI_MODE1_DATA_REG 0xCFC
|
|
675
|
|
676 #define PCI_MODE2_ENABLE_REG 0xCF8
|
|
677 #ifdef PC98
|
|
678 #define PCI_MODE2_FORWARD_REG 0xCF9
|
|
679 #else
|
|
680 #define PCI_MODE2_FORWARD_REG 0xCFA
|
|
681 #endif
|
|
682
|
|
683 static int pcicards=0 ;
|
|
684 static pciinfo_t *pci_lst;
|
|
685
|
|
686 static void identify_card(struct pci_config_reg *pcr)
|
|
687 {
|
|
688
|
|
689 if (pcicards>=MAX_PCI_DEVICES) return ;
|
|
690
|
|
691 pci_lst[pcicards].bus = pcibus ;
|
|
692 pci_lst[pcicards].card = pcicard ;
|
|
693 pci_lst[pcicards].func = pcifunc ;
|
|
694 pci_lst[pcicards].vendor = pcr->_vendor ;
|
|
695 pci_lst[pcicards].device = pcr->_device ;
|
|
696 pci_lst[pcicards].base0 = 0xFFFFFFFF ;
|
|
697 pci_lst[pcicards].base1 = 0xFFFFFFFF ;
|
|
698 pci_lst[pcicards].base2 = 0xFFFFFFFF ;
|
|
699 pci_lst[pcicards].baserom = 0x000C0000 ;
|
|
700 if (pcr->_base0) pci_lst[pcicards].base0 = pcr->_base0 &
|
|
701 ((pcr->_base0&0x1) ? 0xFFFFFFFC : 0xFFFFFFF0) ;
|
|
702 if (pcr->_base1) pci_lst[pcicards].base1 = pcr->_base1 &
|
|
703 ((pcr->_base1&0x1) ? 0xFFFFFFFC : 0xFFFFFFF0) ;
|
|
704 if (pcr->_base2) pci_lst[pcicards].base2 = pcr->_base2 &
|
|
705 ((pcr->_base2&0x1) ? 0xFFFFFFFC : 0xFFFFFFF0) ;
|
|
706 if (pcr->_baserom) pci_lst[pcicards].baserom = pcr->_baserom ;
|
|
707
|
|
708 pcicards++;
|
|
709 }
|
|
710
|
|
711 static int io_fd;
|
|
712 #ifdef __EMX__
|
|
713 static USHORT callgate[3] = {0,0,0};
|
|
714 #endif
|
|
715
|
|
716 static void enable_os_io(void)
|
|
717 {
|
|
718 io_fd = -1 ;
|
|
719 #if defined(SVR4) || defined(SCO) || defined(ISC)
|
|
720 #if defined(SI86IOPL)
|
|
721 sysi86(SI86IOPL, 3);
|
|
722 #else
|
|
723 sysi86(SI86V86, V86SC_IOPL, PS_IOPL);
|
|
724 #endif
|
|
725 #endif
|
|
726 #if defined(linux)
|
|
727 iopl(3);
|
|
728 #endif
|
|
729 #if defined(__FreeBSD__) || defined(__386BSD__) || defined(__bsdi__)
|
|
730 if ((io_fd = open("/dev/console", O_RDWR, 0)) < 0) {
|
|
731 perror("/dev/console");
|
|
732 exit(1);
|
|
733 }
|
|
734 #if defined(__FreeBSD__) || defined(__386BSD__)
|
|
735 if (ioctl(io_fd, KDENABIO, 0) < 0) {
|
|
736 perror("ioctl(KDENABIO)");
|
|
737 exit(1);
|
|
738 }
|
|
739 #endif
|
|
740 #if defined(__bsdi__)
|
|
741 if (ioctl(io_fd, PCCONENABIOPL, 0) < 0) {
|
|
742 perror("ioctl(PCCONENABIOPL)");
|
|
743 exit(1);
|
|
744 }
|
|
745 #endif
|
|
746 #endif
|
|
747 #if defined(__NetBSD__)
|
|
748 #if !defined(USE_I386_IOPL)
|
|
749 if ((io_fd = open("/dev/io", O_RDWR, 0)) < 0) {
|
|
750 perror("/dev/io");
|
|
751 exit(1);
|
|
752 }
|
|
753 #else
|
|
754 if (i386_iopl(1) < 0) {
|
|
755 perror("i386_iopl");
|
|
756 exit(1);
|
|
757 }
|
|
758 #endif /* USE_I386_IOPL */
|
|
759 #endif /* __NetBSD__ */
|
|
760 #if defined(__OpenBSD__)
|
|
761 if (i386_iopl(1) < 0) {
|
|
762 perror("i386_iopl");
|
|
763 exit(1);
|
|
764 }
|
|
765 #endif /* __OpenBSD__ */
|
|
766 #if defined(MACH386)
|
|
767 if ((io_fd = open("/dev/iopl", O_RDWR, 0)) < 0) {
|
|
768 perror("/dev/iopl");
|
|
769 exit(1);
|
|
770 }
|
|
771 #endif
|
|
772 #ifdef __EMX__
|
|
773 {
|
|
774 HFILE hfd;
|
|
775 ULONG dlen,action;
|
|
776 APIRET rc;
|
|
777 static char *ioDrvPath = "/dev/fastio$";
|
|
778
|
|
779 if (DosOpen((PSZ)ioDrvPath, (PHFILE)&hfd, (PULONG)&action,
|
|
780 (ULONG)0, FILE_SYSTEM, FILE_OPEN,
|
|
781 OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT|OPEN_ACCESS_READONLY,
|
|
782 (ULONG)0) != 0) {
|
|
783 fprintf(stderr,"Error opening fastio$ driver...\n");
|
|
784 fprintf(stderr,"Please install xf86sup.sys in config.sys!\n");
|
|
785 exit(42);
|
|
786 }
|
|
787 callgate[0] = callgate[1] = 0;
|
|
788
|
|
789 /* Get callgate from driver for fast io to ports and other stuff */
|
|
790
|
|
791 rc = DosDevIOCtl(hfd, (ULONG)0x76, (ULONG)0x64,
|
|
792 NULL, 0, NULL,
|
|
793 (ULONG*)&callgate[2], sizeof(USHORT), &dlen);
|
|
794 if (rc) {
|
|
795 fprintf(stderr,"xf86-OS/2: EnableIOPorts failed, rc=%d, dlen=%d; emergency exit\n",
|
|
796 rc,dlen);
|
|
797 DosClose(hfd);
|
|
798 exit(42);
|
|
799 }
|
|
800
|
|
801 /* Calling callgate with function 13 sets IOPL for the program */
|
|
802
|
|
803 asm volatile ("movl $13,%%ebx;.byte 0xff,0x1d;.long _callgate"
|
|
804 : /*no outputs */
|
|
805 : /*no inputs */
|
|
806 : "eax","ebx","ecx","edx","cc");
|
|
807
|
|
808 DosClose(hfd);
|
|
809 }
|
|
810 #endif
|
|
811 #if defined(Lynx) && defined(__powerpc__)
|
|
812 pciConfBase = (unsigned char *) smem_create("PCI-CONF",
|
|
813 (char *)0x80800000, 64*1024, SM_READ|SM_WRITE);
|
|
814 if (pciConfBase == (void *) -1)
|
|
815 exit(1);
|
|
816 #endif
|
|
817 }
|
|
818
|
|
819
|
|
820 static void disable_os_io(void)
|
|
821 {
|
|
822 #if defined(SVR4) || defined(SCO) || defined(ISC)
|
|
823 #if defined(SI86IOPL)
|
|
824 sysi86(SI86IOPL, 0);
|
|
825 #else
|
|
826 sysi86(SI86V86, V86SC_IOPL, 0);
|
|
827 #endif
|
|
828 #endif
|
|
829 #if defined(linux)
|
|
830 iopl(0);
|
|
831 #endif
|
|
832 #if defined(__FreeBSD__) || defined(__386BSD__)
|
|
833 if (ioctl(io_fd, KDDISABIO, 0) < 0) {
|
|
834 perror("ioctl(KDDISABIO)");
|
|
835 close(io_fd);
|
|
836 exit(1);
|
|
837 }
|
|
838 close(io_fd);
|
|
839 #endif
|
|
840 #if defined(__NetBSD__)
|
|
841 #if !defined(USE_I386_IOPL)
|
|
842 close(io_fd);
|
|
843 #else
|
|
844 if (i386_iopl(0) < 0) {
|
|
845 perror("i386_iopl");
|
|
846 exit(1);
|
|
847 }
|
|
848 #endif /* NetBSD1_1 */
|
|
849 #endif /* __NetBSD__ */
|
|
850 #if defined(__bsdi__)
|
|
851 if (ioctl(io_fd, PCCONDISABIOPL, 0) < 0) {
|
|
852 perror("ioctl(PCCONDISABIOPL)");
|
|
853 close(io_fd);
|
|
854 exit(1);
|
|
855 }
|
|
856 close(io_fd);
|
|
857 #endif
|
|
858 #if defined(MACH386)
|
|
859 close(io_fd);
|
|
860 #endif
|
|
861 #if defined(Lynx) && defined(__powerpc__)
|
|
862 smem_create(NULL, (char *) pciConfBase, 0, SM_DETACH);
|
|
863 smem_remove("PCI-CONF");
|
|
864 pciConfBase = NULL;
|
|
865 #endif
|
|
866 }
|
|
867
|
|
868 /*main(int argc, char *argv[])*/
|
|
869 int pci_scan(pciinfo_t *pci_list,unsigned *num_pci)
|
|
870 {
|
|
871 unsigned long tmplong1, tmplong2, config_cmd;
|
|
872 unsigned char tmp1, tmp2;
|
|
873 unsigned int idx;
|
|
874 struct pci_config_reg pcr;
|
|
875 int do_mode1_scan = 0, do_mode2_scan = 0;
|
|
876 int func, hostbridges=0;
|
|
877
|
|
878 pci_lst = pci_list;
|
|
879
|
|
880 enable_os_io();
|
|
881
|
|
882 #if !defined(__alpha__) && !defined(__powerpc__)
|
|
883 pcr._configtype = 0;
|
|
884
|
|
885 outb(PCI_MODE2_ENABLE_REG, 0x00);
|
|
886 outb(PCI_MODE2_FORWARD_REG, 0x00);
|
|
887 tmp1 = inb(PCI_MODE2_ENABLE_REG);
|
|
888 tmp2 = inb(PCI_MODE2_FORWARD_REG);
|
|
889 if ((tmp1 == 0x00) && (tmp2 == 0x00)) {
|
|
890 pcr._configtype = 2;
|
|
891 /*printf("PCI says configuration type 2\n");*/
|
|
892 } else {
|
|
893 tmplong1 = inl(PCI_MODE1_ADDRESS_REG);
|
|
894 outl(PCI_MODE1_ADDRESS_REG, PCI_EN);
|
|
895 tmplong2 = inl(PCI_MODE1_ADDRESS_REG);
|
|
896 outl(PCI_MODE1_ADDRESS_REG, tmplong1);
|
|
897 if (tmplong2 == PCI_EN) {
|
|
898 pcr._configtype = 1;
|
|
899 /*printf("PCI says configuration type 1\n");*/
|
|
900 } else {
|
|
901 /*printf("No PCI !\n");*/
|
|
902 disable_os_io();
|
|
903 /*exit(1);*/
|
|
904 return ENODEV ;
|
|
905 }
|
|
906 }
|
|
907 #else
|
|
908 pcr._configtype = 1;
|
|
909 #endif
|
|
910
|
|
911 /* Try pci config 1 probe first */
|
|
912
|
|
913 if ((pcr._configtype == 1) || do_mode1_scan) {
|
|
914 /*printf("\nPCI probing configuration type 1\n");*/
|
|
915
|
|
916 pcr._ioaddr = 0xFFFF;
|
|
917
|
|
918 pcr._pcibuses[0] = 0;
|
|
919 pcr._pcinumbus = 1;
|
|
920 pcr._pcibusidx = 0;
|
|
921 idx = 0;
|
|
922
|
|
923 do {
|
|
924 /*printf("Probing for devices on PCI bus %d:\n\n", pcr._pcibusidx);*/
|
|
925
|
|
926 for (pcr._cardnum = 0x0; pcr._cardnum < MAX_PCI_DEVICES_PER_BUS;
|
|
927 pcr._cardnum += 0x1) {
|
|
928 func = 0;
|
|
929 do { /* loop over the different functions, if present */
|
|
930 #if !defined(__alpha__) && !defined(__powerpc__)
|
|
931 config_cmd = PCI_EN | (pcr._pcibuses[pcr._pcibusidx]<<16) |
|
|
932 (pcr._cardnum<<11) | (func<<8);
|
|
933
|
|
934 outl(PCI_MODE1_ADDRESS_REG, config_cmd); /* ioreg 0 */
|
|
935 pcr._device_vendor = inl(PCI_MODE1_DATA_REG);
|
|
936 #else
|
|
937 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
938 PCI_ID_REG, 4, &pcr._device_vendor);
|
|
939 #endif
|
|
940
|
|
941 if ((pcr._vendor == 0xFFFF) || (pcr._device == 0xFFFF))
|
|
942 break; /* nothing there */
|
|
943
|
|
944 /*printf("\npci bus 0x%x cardnum 0x%02x function 0x%04x: vendor 0x%04x device 0x%04x\n",
|
|
945 pcr._pcibuses[pcr._pcibusidx], pcr._cardnum, func,
|
|
946 pcr._vendor, pcr._device);*/
|
|
947 pcibus = pcr._pcibuses[pcr._pcibusidx] ;
|
|
948 pcicard = pcr._cardnum ; pcifunc = func ;
|
|
949
|
|
950 #if !defined(__alpha__) && !defined(__powerpc__)
|
|
951 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x04);
|
|
952 pcr._status_command = inl(PCI_MODE1_DATA_REG);
|
|
953 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x08);
|
|
954 pcr._class_revision = inl(PCI_MODE1_DATA_REG);
|
|
955 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x0C);
|
|
956 pcr._bist_header_latency_cache = inl(PCI_MODE1_DATA_REG);
|
|
957 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x10);
|
|
958 pcr._base0 = inl(PCI_MODE1_DATA_REG);
|
|
959 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x14);
|
|
960 pcr._base1 = inl(PCI_MODE1_DATA_REG);
|
|
961 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x18);
|
|
962 pcr._base2 = inl(PCI_MODE1_DATA_REG);
|
|
963 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x1C);
|
|
964 pcr._base3 = inl(PCI_MODE1_DATA_REG);
|
|
965 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x20);
|
|
966 pcr._base4 = inl(PCI_MODE1_DATA_REG);
|
|
967 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x24);
|
|
968 pcr._base5 = inl(PCI_MODE1_DATA_REG);
|
|
969 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x30);
|
|
970 pcr._baserom = inl(PCI_MODE1_DATA_REG);
|
|
971 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x3C);
|
|
972 pcr._max_min_ipin_iline = inl(PCI_MODE1_DATA_REG);
|
|
973 outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x40);
|
|
974 pcr._user_config = inl(PCI_MODE1_DATA_REG);
|
|
975 #else
|
|
976 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
977 PCI_CMD_STAT_REG, 4, &pcr._status_command);
|
|
978 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
979 PCI_CLASS_REG, 4, &pcr._class_revision);
|
|
980 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
981 PCI_HEADER_MISC, 4, &pcr._bist_header_latency_cache);
|
|
982 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
983 PCI_MAP_REG_START, 4, &pcr._base0);
|
|
984 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
985 PCI_MAP_REG_START + 0x04, 4, &pcr._base1);
|
|
986 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
987 PCI_MAP_REG_START + 0x08, 4, &pcr._base2);
|
|
988 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
989 PCI_MAP_REG_START + 0x0C, 4, &pcr._base3);
|
|
990 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
991 PCI_MAP_REG_START + 0x10, 4, &pcr._base4);
|
|
992 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
993 PCI_MAP_REG_START + 0x14, 4, &pcr._base5);
|
|
994 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
995 PCI_MAP_ROM_REG, 4, &pcr._baserom);
|
|
996 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
997 PCI_INTERRUPT_REG, 4, &pcr._max_min_ipin_iline);
|
|
998 pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
|
|
999 PCI_REG_USERCONFIG, 4, &pcr._user_config);
|
|
1000 #endif
|
|
1001
|
|
1002 /* check for pci-pci bridges */
|
|
1003 #define PCI_CLASS_MASK 0xff000000
|
|
1004 #define PCI_SUBCLASS_MASK 0x00ff0000
|
|
1005 #define PCI_CLASS_BRIDGE 0x06000000
|
|
1006 #define PCI_SUBCLASS_BRIDGE_PCI 0x00040000
|
|
1007 switch(pcr._class_revision & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
|
|
1008 case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
|
|
1009 if (pcr._secondary_bus_number > 0) {
|
|
1010 pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number;
|
|
1011 }
|
|
1012 break;
|
|
1013 case PCI_CLASS_BRIDGE:
|
|
1014 if ( ++hostbridges > 1) {
|
|
1015 pcr._pcibuses[pcr._pcinumbus] = pcr._pcinumbus;
|
|
1016 pcr._pcinumbus++;
|
|
1017 }
|
|
1018 break;
|
|
1019 default:
|
|
1020 break;
|
|
1021 }
|
|
1022 if((func==0) && ((pcr._header_type & PCI_MULTIFUNC_DEV) == 0)) {
|
|
1023 /* not a multi function device */
|
|
1024 func = 8;
|
|
1025 } else {
|
|
1026 func++;
|
|
1027 }
|
|
1028
|
|
1029 if (idx++ >= MAX_PCI_DEVICES)
|
|
1030 continue;
|
|
1031
|
|
1032 identify_card(&pcr);
|
|
1033 } while( func < 8 );
|
|
1034 }
|
|
1035 } while (++pcr._pcibusidx < pcr._pcinumbus);
|
|
1036 }
|
|
1037
|
|
1038 #if !defined(__alpha__) && !defined(__powerpc__)
|
|
1039 /* Now try pci config 2 probe (deprecated) */
|
|
1040
|
|
1041 if ((pcr._configtype == 2) || do_mode2_scan) {
|
|
1042 outb(PCI_MODE2_ENABLE_REG, 0xF1);
|
|
1043 outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
|
|
1044
|
|
1045 /*printf("\nPCI probing configuration type 2\n");*/
|
|
1046
|
|
1047 pcr._pcibuses[0] = 0;
|
|
1048 pcr._pcinumbus = 1;
|
|
1049 pcr._pcibusidx = 0;
|
|
1050 idx = 0;
|
|
1051
|
|
1052 do {
|
|
1053 for (pcr._ioaddr = 0xC000; pcr._ioaddr < 0xD000; pcr._ioaddr += 0x0100){
|
|
1054 outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */
|
|
1055 pcr._device_vendor = inl(pcr._ioaddr);
|
|
1056 outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
|
|
1057
|
|
1058 if ((pcr._vendor == 0xFFFF) || (pcr._device == 0xFFFF))
|
|
1059 continue;
|
|
1060 if ((pcr._vendor == 0xF0F0) || (pcr._device == 0xF0F0))
|
|
1061 continue; /* catch ASUS P55TP4XE motherboards */
|
|
1062
|
|
1063 /*printf("\npci bus 0x%x slot at 0x%04x, vendor 0x%04x device 0x%04x\n",
|
|
1064 pcr._pcibuses[pcr._pcibusidx], pcr._ioaddr, pcr._vendor,
|
|
1065 pcr._device);*/
|
|
1066 pcibus = pcr._pcibuses[pcr._pcibusidx] ;
|
|
1067 pcicard = pcr._ioaddr ; pcifunc = 0 ;
|
|
1068
|
|
1069 outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */
|
|
1070 pcr._status_command = inl(pcr._ioaddr + 0x04);
|
|
1071 pcr._class_revision = inl(pcr._ioaddr + 0x08);
|
|
1072 pcr._bist_header_latency_cache = inl(pcr._ioaddr + 0x0C);
|
|
1073 pcr._base0 = inl(pcr._ioaddr + 0x10);
|
|
1074 pcr._base1 = inl(pcr._ioaddr + 0x14);
|
|
1075 pcr._base2 = inl(pcr._ioaddr + 0x18);
|
|
1076 pcr._base3 = inl(pcr._ioaddr + 0x1C);
|
|
1077 pcr._base4 = inl(pcr._ioaddr + 0x20);
|
|
1078 pcr._base5 = inl(pcr._ioaddr + 0x24);
|
|
1079 pcr._baserom = inl(pcr._ioaddr + 0x30);
|
|
1080 pcr._max_min_ipin_iline = inl(pcr._ioaddr + 0x3C);
|
|
1081 pcr._user_config = inl(pcr._ioaddr + 0x40);
|
|
1082 outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
|
|
1083
|
|
1084 /* check for pci-pci bridges (currently we only know Digital) */
|
|
1085 if ((pcr._vendor == 0x1011) && (pcr._device == 0x0001))
|
|
1086 if (pcr._secondary_bus_number > 0)
|
|
1087 pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number;
|
|
1088
|
|
1089 if (idx++ >= MAX_PCI_DEVICES)
|
|
1090 continue;
|
|
1091
|
|
1092 identify_card(&pcr);
|
|
1093 }
|
|
1094 } while (++pcr._pcibusidx < pcr._pcinumbus);
|
|
1095
|
|
1096 outb(PCI_MODE2_ENABLE_REG, 0x00);
|
|
1097 }
|
|
1098
|
|
1099 #endif /* __alpha__ */
|
|
1100
|
|
1101 disable_os_io();
|
|
1102 *num_pci = pcicards;
|
|
1103
|
|
1104 return 0 ;
|
|
1105
|
|
1106 }
|
|
1107
|
|
1108 #if 0
|
|
1109 void
|
|
1110 print_i128(struct pci_config_reg *pcr)
|
|
1111 {
|
|
1112 /*
|
|
1113 if (pcr->_status_command)
|
|
1114 printf(" STATUS 0x%04x COMMAND 0x%04x\n",
|
|
1115 pcr->_status, pcr->_command);
|
|
1116 if (pcr->_class_revision)
|
|
1117 printf(" CLASS 0x%02x 0x%02x 0x%02x REVISION 0x%02x\n",
|
|
1118 pcr->_base_class, pcr->_sub_class, pcr->_prog_if, pcr->_rev_id);
|
|
1119 if (pcr->_bist_header_latency_cache)
|
|
1120 printf(" BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n",
|
|
1121 pcr->_bist, pcr->_header_type, pcr->_latency_timer,
|
|
1122 pcr->_cache_line_size);
|
|
1123 printf(" MW0_AD 0x%08x addr 0x%08x %spre-fetchable\n",
|
|
1124 pcr->_base0, pcr->_base0 & 0xFFC00000,
|
|
1125 pcr->_base0 & 0x8 ? "" : "not-");
|
|
1126 printf(" MW1_AD 0x%08x addr 0x%08x %spre-fetchable\n",
|
|
1127 pcr->_base1, pcr->_base1 & 0xFFC00000,
|
|
1128 pcr->_base1 & 0x8 ? "" : "not-");
|
|
1129 printf(" XYW_AD(A) 0x%08x addr 0x%08x\n",
|
|
1130 pcr->_base2, pcr->_base2 & 0xFFC00000);
|
|
1131 printf(" XYW_AD(B) 0x%08x addr 0x%08x\n",
|
|
1132 pcr->_base3, pcr->_base3 & 0xFFC00000);
|
|
1133 printf(" RBASE_G 0x%08x addr 0x%08x\n",
|
|
1134 pcr->_base4, pcr->_base4 & 0xFFFF0000);
|
|
1135 printf(" IO 0x%08x addr 0x%08x\n",
|
|
1136 pcr->_base5, pcr->_base5 & 0xFFFFFF00);
|
|
1137 printf(" RBASE_E 0x%08x addr 0x%08x %sdecode-enabled\n",
|
|
1138 pcr->_baserom, pcr->_baserom & 0xFFFF8000,
|
|
1139 pcr->_baserom & 0x1 ? "" : "not-");
|
|
1140 if (pcr->_max_min_ipin_iline)
|
|
1141 printf(" MAX_LAT 0x%02x MIN_GNT 0x%02x INT_PIN 0x%02x INT_LINE 0x%02x\n",
|
|
1142 pcr->_max_lat, pcr->_min_gnt, pcr->_int_pin, pcr->_int_line);
|
|
1143 */
|
|
1144 }
|
|
1145
|
|
1146 void
|
|
1147 print_pcibridge(struct pci_config_reg *pcr)
|
|
1148 {
|
|
1149 /*
|
|
1150 if (pcr->_status_command)
|
|
1151 printf(" STATUS 0x%04x COMMAND 0x%04x\n",
|
|
1152 pcr->_status, pcr->_command);
|
|
1153 if (pcr->_class_revision)
|
|
1154 printf(" CLASS 0x%02x 0x%02x 0x%02x REVISION 0x%02x\n",
|
|
1155 pcr->_base_class, pcr->_sub_class, pcr->_prog_if, pcr->_rev_id);
|
|
1156 if (pcr->_bist_header_latency_cache)
|
|
1157 printf(" BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n",
|
|
1158 pcr->_bist, pcr->_header_type, pcr->_latency_timer,
|
|
1159 pcr->_cache_line_size);
|
|
1160 printf(" PRIBUS 0x%02x SECBUS 0x%02x SUBBUS 0x%02x SECLT 0x%02x\n",
|
|
1161 pcr->_primary_bus_number, pcr->_secondary_bus_number,
|
|
1162 pcr->_subordinate_bus_number, pcr->_secondary_latency_timer);
|
|
1163 printf(" IOBASE: 0x%02x00 IOLIM 0x%02x00 SECSTATUS 0x%04x\n",
|
|
1164 pcr->_io_base, pcr->_io_limit, pcr->_secondary_status);
|
|
1165 printf(" NOPREFETCH MEMBASE: 0x%08x MEMLIM 0x%08x\n",
|
|
1166 pcr->_mem_base, pcr->_mem_limit);
|
|
1167 printf(" PREFETCH MEMBASE: 0x%08x MEMLIM 0x%08x\n",
|
|
1168 pcr->_prefetch_mem_base, pcr->_prefetch_mem_limit);
|
|
1169 printf(" RBASE_E 0x%08x addr 0x%08x %sdecode-enabled\n",
|
|
1170 pcr->_baserom, pcr->_baserom & 0xFFFF8000,
|
|
1171 pcr->_baserom & 0x1 ? "" : "not-");
|
|
1172 if (pcr->_max_min_ipin_iline)
|
|
1173 printf(" MAX_LAT 0x%02x MIN_GNT 0x%02x INT_PIN 0x%02x INT_LINE 0x%02x\n",
|
|
1174 pcr->_max_lat, pcr->_min_gnt, pcr->_int_pin, pcr->_int_line);
|
|
1175 */
|
|
1176 }
|
|
1177 #endif
|