1
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c,v 1.71 2003/01/23 16:22:13 tsi Exp $ */
3
* Pci.c - New server PCI access functions
5
* The XFree86 server PCI access functions have been reimplemented as a
6
* framework that allows each supported platform/OS to have their own
7
* platform/OS specific pci driver.
9
* All of the public PCI access functions exported to the other parts of
10
* the server are declared in Pci.h and defined herein. These include:
11
* pciInit() - Initialize PCI access functions
12
* pciFindFirst() - Find a PCI device by dev/vend id
13
* pciFindNext() - Find another PCI device by dev/vend id
14
* pciReadLong() - Read a 32 bit value from a device's cfg space
15
* pciReadWord() - Read a 16 bit value from a device's cfg space
16
* pciReadByte() - Read an 8 bit value from a device's cfg space
17
* pciWriteLong() - Write a 32 bit value to a device's cfg space
18
* pciWriteWord() - Write a 16 bit value to a device's cfg space
19
* pciWriteByte() - Write an 8 bit value to a device's cfg space
20
* pciSetBitsLong() - Write a 32 bit value against a mask
21
* pciSetBitsByte() - Write an 8 bit value against a mask
22
* pciLongFunc() - Return pointer to the requested low level
24
* pciTag() - Return tag for a given PCI bus, device, &
26
* pciBusAddrToHostAddr() - Convert a PCI address to a host address
27
* pciHostAddrToBusAddr() - Convert a host address to a PCI address
28
* pciGetBaseSize() - Returns the number of bits in a PCI base
30
* xf86MapPciMem() - Like xf86MapVidMem() except function expects
31
* a PCI address and a PCITAG that identifies
33
* xf86ReadPciBIOS() - Like xf86ReadBIOS() but can handle PCI/host
34
* address translation and BIOS decode enabling
35
* xf86scanpci() - Return info about all PCI devices
36
* xf86GetPciDomain() - Return domain number from a PCITAG
37
* xf86MapDomainMemory() - Like xf86MapPciMem() but can handle
38
* domain/host address translation
39
* xf86MapDomainIO() - Maps PCI I/O spaces
40
* xf86ReadDomainMemory() - Like xf86ReadPciBIOS() but can handle
41
* domain/host address translation
43
* The actual PCI backend driver is selected by the pciInit() function
44
* (see below) using either compile time definitions, run-time checks,
47
* Certain generic functions are provided that make the implementation
48
* of certain well behaved platforms (e.g. those supporting PCI config
49
* mechanism 1 or some thing close to it) very easy.
51
* Less well behaved platforms/OS's can roll their own functions.
53
* To add support for another platform/OS, add a call to fooPciInit() within
54
* pciInit() below under the correct compile time definition or run-time
57
* The fooPciInit() procedure must do three things:
58
* 1) Initialize the pciBusTable[] for all primary PCI buses including
59
* the per domain PCI access functions (readLong, writeLong,
60
* addrBusToHost, and addrHostToBus).
62
* 2) Add entries to pciBusTable[] for configured secondary buses. This
63
* step may be skipped if a platform is using the generic findFirst/
64
* findNext functions because these procedures will automatically
65
* discover and add secondary buses dynamically.
67
* 3) Overide default settings for global PCI access functions if
68
* required. These include pciFindFirstFP, pciFindNextFP,
69
* Of course, if you choose not to use one of the generic
70
* functions, you will need to provide a platform specifc replacement.
73
* Concurrent Computer Corporation
79
* Copyright 1998 by Concurrent Computer Corporation
81
* Permission to use, copy, modify, distribute, and sell this software
82
* and its documentation for any purpose is hereby granted without fee,
83
* provided that the above copyright notice appear in all copies and that
84
* both that copyright notice and this permission notice appear in
85
* supporting documentation, and that the name of Concurrent Computer
86
* Corporation not be used in advertising or publicity pertaining to
87
* distribution of the software without specific, written prior
88
* permission. Concurrent Computer Corporation makes no representations
89
* about the suitability of this software for any purpose. It is
90
* provided "as is" without express or implied warranty.
92
* CONCURRENT COMPUTER CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD
93
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
94
* AND FITNESS, IN NO EVENT SHALL CONCURRENT COMPUTER CORPORATION BE
95
* LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
96
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
97
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
98
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
101
* Copyright 1998 by Metro Link Incorporated
103
* Permission to use, copy, modify, distribute, and sell this software
104
* and its documentation for any purpose is hereby granted without fee,
105
* provided that the above copyright notice appear in all copies and that
106
* both that copyright notice and this permission notice appear in
107
* supporting documentation, and that the name of Metro Link
108
* Incorporated not be used in advertising or publicity pertaining to
109
* distribution of the software without specific, written prior
110
* permission. Metro Link Incorporated makes no representations
111
* about the suitability of this software for any purpose. It is
112
* provided "as is" without express or implied warranty.
114
* METRO LINK INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD
115
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
116
* AND FITNESS, IN NO EVENT SHALL METRO LINK INCORPORATED BE
117
* LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
118
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
119
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
120
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
123
* This software is derived from the original XFree86 PCI code
124
* which includes the following copyright notices as well:
126
* Copyright 1995 by Robin Cutshaw <robin@XFree86.Org>
128
* Permission to use, copy, modify, distribute, and sell this software and its
129
* documentation for any purpose is hereby granted without fee, provided that
130
* the above copyright notice appear in all copies and that both that
131
* copyright notice and this permission notice appear in supporting
132
* documentation, and that the names of the above listed copyright holder(s)
133
* not be used in advertising or publicity pertaining to distribution of
134
* the software without specific, written prior permission. The above listed
135
* copyright holder(s) make(s) no representations about the suitability of this
136
* software for any purpose. It is provided "as is" without express or
139
* THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
140
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
141
* AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
142
* LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
143
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
144
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
145
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
147
* This code is also based heavily on the code in FreeBSD-current, which was
148
* written by Wolfgang Stanglmeier, and contains the following copyright:
150
* Redistribution and use in source and binary forms, with or without
151
* modification, are permitted provided that the following conditions
153
* 1. Redistributions of source code must retain the above copyright
154
* notice, this list of conditions and the following disclaimer.
155
* 2. Redistributions in binary form must reproduce the above copyright
156
* notice, this list of conditions and the following disclaimer in the
157
* documentation and/or other materials provided with the distribution.
158
* 3. The name of the author may not be used to endorse or promote products
159
* derived from this software without specific prior written permission.
161
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
162
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
163
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
164
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
165
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
166
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
167
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
168
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
169
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
170
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
176
#include "compiler.h"
178
#include "xf86Priv.h"
179
#define XF86_OS_PRIVS
180
#include "xf86_OSproc.h"
183
#define PCI_MFDEV_SUPPORT 1 /* Include PCI multifunction device support */
184
#define PCI_BRIDGE_SUPPORT 1 /* Include support for PCI-to-PCI bridges */
187
#define outb(port,data) _outb(port,data)
188
#define outl(port,data) _outl(port,data)
189
#define inb(port) _inb(port)
190
#define inl(port) _inl(port)
196
static int pciInitialized = 0;
198
CARD32 pciDevid; /* Requested device/vendor ID (after mask) */
199
CARD32 pciDevidMask; /* Bit mask applied (AND) before comparison */
200
/* of real devid's with requested */
202
int pciBusNum; /* Bus Number of current device */
203
int pciDevNum; /* Device number of current device */
204
int pciFuncNum; /* Function number of current device */
205
PCITAG pciDeviceTag; /* Tag for current device */
207
pciBusInfo_t *pciBusInfo[MAX_PCI_BUSES] = { NULL, };
208
int pciNumBuses = 0; /* Actual number of PCI buses */
209
int pciMaxBusNum = MAX_PCI_BUSES;
210
static Bool inProbe = FALSE;
212
static pciConfigPtr pci_devp[MAX_PCI_DEVICES + 1] = {NULL, };
215
* Platform specific PCI function pointers.
217
* NOTE: A platform/OS specific pci init procedure can override these defaults
218
* by setting them to the appropriate platform dependent functions.
220
PCITAG (*pciFindFirstFP)(void) = pciGenFindFirst;
221
PCITAG (*pciFindNextFP)(void) = pciGenFindNext;
224
* pciInit - choose correct platform/OS specific PCI init routine
235
#if defined(DEBUGPCI)
236
if (DEBUGPCI >= xf86Verbose)
237
xf86Verbose = DEBUGPCI;
241
#if defined(ARCH_PCI_OS_INIT)
242
if (pciNumBuses <= 0)
248
pciFindFirst(CARD32 id, CARD32 mask)
251
ErrorF("pciFindFirst(0x%lx, 0x%lx), pciInit = %d\n", id, mask, pciInitialized);
255
pciDevid = id & mask;
258
return((*pciFindFirstFP)());
265
ErrorF("pciFindNext(), pciInit = %d\n", pciInitialized);
269
return((*pciFindNextFP)());
273
pciReadLong(PCITAG tag, int offset)
275
int bus = PCI_BUS_FROM_TAG(tag);
278
ErrorF("pciReadLong(0x%lx, %d)\n", tag, offset);
282
if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] &&
283
pciBusInfo[bus]->funcs->pciReadLong) {
284
CARD32 rv = (*pciBusInfo[bus]->funcs->pciReadLong)(tag, offset);
286
PCITRACE(1, ("pciReadLong: tag=0x%x [b=%d,d=%d,f=%d] returns 0x%08x\n",
287
tag, bus, PCI_DEV_FROM_TAG(tag), PCI_FUNC_FROM_TAG(tag), rv));
291
return(PCI_NOT_FOUND);
295
pciReadWord(PCITAG tag, int offset)
298
int shift = (offset & 3) * 8;
299
int aligned_offset = offset & ~3;
301
if (shift != 0 && shift != 16)
302
FatalError("pciReadWord: Alignment error: Cannot read 16 bits "
303
"at offset %d\n", offset);
305
tmp = pciReadLong(tag, aligned_offset);
307
return((CARD16)((tmp >> shift) & 0xffff));
311
pciReadByte(PCITAG tag, int offset)
314
int shift = (offset & 3) * 8;
315
int aligned_offset = offset & ~3;
317
tmp = pciReadLong(tag, aligned_offset);
319
return((CARD8)((tmp >> shift) & 0xff));
323
pciWriteLong(PCITAG tag, int offset, CARD32 val)
325
int bus = PCI_BUS_FROM_TAG(tag);
329
if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
330
pciBusInfo[bus]->funcs->pciWriteLong)
331
(*pciBusInfo[bus]->funcs->pciWriteLong)(tag, offset, val);
335
pciWriteWord(PCITAG tag, int offset, CARD16 val)
338
int aligned_offset = offset & ~3;
339
int shift = (offset & 3) * 8;
341
if (shift != 0 && shift != 16)
342
FatalError("pciWriteWord: Alignment Error: Cannot read 16 bits "
343
"from offset %d\n", offset);
345
tmp = pciReadLong(tag, aligned_offset);
347
tmp &= ~(0xffffL << shift);
348
tmp |= (((CARD32)val) << shift);
350
pciWriteLong(tag, aligned_offset, tmp);
354
pciWriteByte(PCITAG tag, int offset, CARD8 val)
357
int aligned_offset = offset & ~3;
358
int shift = (offset & 3) *8 ;
360
tmp = pciReadLong(tag, aligned_offset);
362
tmp &= ~(0xffL << shift);
363
tmp |= (((CARD32)val) << shift);
365
pciWriteLong(tag, aligned_offset, tmp);
369
pciSetBitsLong(PCITAG tag, int offset, CARD32 mask, CARD32 val)
371
int bus = PCI_BUS_FROM_TAG(tag);
374
ErrorF("pciReadLong(0x%lx, %d)\n", tag, offset);
378
if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
379
pciBusInfo[bus]->funcs->pciReadLong) {
380
(*pciBusInfo[bus]->funcs->pciSetBitsLong)(tag, offset, mask, val);
385
pciSetBitsByte(PCITAG tag, int offset, CARD8 mask, CARD8 val)
387
CARD32 tmp_mask, tmp_val;
388
int aligned_offset = offset & ~3;
389
int shift = (offset & 3) *8 ;
391
tmp_mask = mask << shift;
392
tmp_val = val << shift;
393
pciSetBitsLong(tag, aligned_offset, tmp_mask, tmp_val);
397
pciLongFunc(PCITAG tag, pciFunc func)
399
int bus = PCI_BUS_FROM_TAG(tag);
403
if ((bus < 0) || (bus > pciNumBuses) || !pciBusInfo[bus] ||
404
!pciBusInfo[bus]->funcs->pciReadLong) return NULL;
408
return (void *)pciBusInfo[bus]->funcs->pciWriteLong;
410
return (void *)pciBusInfo[bus]->funcs->pciReadLong;
412
return (void *)pciBusInfo[bus]->funcs->pciSetBitsLong;
418
pciBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr)
420
int bus = PCI_BUS_FROM_TAG(tag);
424
if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
425
pciBusInfo[bus]->funcs->pciAddrBusToHost)
426
return (*pciBusInfo[bus]->funcs->pciAddrBusToHost)(tag, type, addr);
432
pciHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr)
434
int bus = PCI_BUS_FROM_TAG(tag);
438
if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
439
pciBusInfo[bus]->funcs->pciAddrHostToBus)
440
return (*pciBusInfo[bus]->funcs->pciAddrHostToBus)(tag, type, addr);
446
* pciGetBaseSize() returns the size of a PCI base address mapping in bits.
447
* The index identifies the base register: 0-5 are the six standard registers,
448
* and 6 is the ROM base register. If destructive is TRUE, it will write
449
* to the base address register to get an accurate result. Otherwise it
450
* makes a conservative guess based on the alignment of the already allocated
451
* address. If the result is accurate (ie, not an over-estimate), this is
452
* indicated by setting *min to TRUE (when min is non-NULL). This currently
453
* only happens when the destructive flag is set, but in future it may be
454
* possible to get the information from the OS when supported.
458
pciGetBaseSize(PCITAG tag, int index, Bool destructive, Bool *min)
468
* Eventually a function for this should be added to pciBusFuncs_t, but for
469
* now we'll just use a simple method based on the alignment of the already
474
* silently ignore bogus index values. Valid values are 0-6. 0-5 are
475
* the 6 base address registers, and 6 is the ROM base address register.
477
if (index < 0 || index > 6)
482
if (xf86GetPciSizeFromOS(tag, index, &bits)) {
491
/* Get the PCI offset */
493
offset = PCI_MAP_ROM_REG;
495
offset = PCI_MAP_REG_START + (index << 2);
497
addr1 = pciReadLong(tag, offset);
499
* Check if this is the second part of a 64 bit address.
500
* XXX need to check how endianness affects 64 bit addresses.
502
if (index > 0 && index < 6) {
503
addr2 = pciReadLong(tag, offset - 4);
504
if (PCI_MAP_IS_MEM(addr2) && PCI_MAP_IS64BITMEM(addr2))
509
pciWriteLong(tag, offset, 0xffffffff);
510
mask1 = pciReadLong(tag, offset);
511
pciWriteLong(tag, offset, addr1);
516
/* Check if this is the first part of a 64 bit address. */
517
if (index < 5 && PCI_MAP_IS_MEM(mask1) && PCI_MAP_IS64BITMEM(mask1)) {
518
if (PCIGETMEMORY(mask1) == 0) {
519
addr2 = pciReadLong(tag, offset + 4);
521
pciWriteLong(tag, offset + 4, 0xffffffff);
522
mask2 = pciReadLong(tag, offset + 4);
523
pciWriteLong(tag, offset + 4, addr2);
530
while ((mask2 & 1) == 0) {
539
if (PCI_MAP_IS_MEM(mask1))
540
mask1 = PCIGETMEMORY(mask1);
542
mask1 = PCIGETIO(mask1);
544
mask1 = PCIGETROM(mask1);
548
while ((mask1 & 1) == 0) {
552
/* I/O maps can be no larger than 8 bits */
554
#if defined(Lynx) && defined(__powerpc__)
555
if (PCI_MAP_IS_IO(addr1) && bits > 8)
557
if ((index < 6) && PCI_MAP_IS_IO(addr1) && bits > 8)
560
/* ROM maps can be no larger than 24 bits */
561
if (index == 6 && bits > 24)
567
pciTag(int busnum, int devnum, int funcnum)
569
return(PCI_MAKE_TAG(busnum,devnum,funcnum));
573
pciMfDev(int busnum, int devnum)
576
unsigned long id0, id1;
578
/* Detect a multi-function device that complies to the PCI 2.0 spec */
580
tag0 = PCI_MAKE_TAG(busnum, devnum, 0);
581
id0 = pciReadLong(tag0, PCI_ID_REG);
582
if (id0 == 0xffffffff)
585
if (pciReadLong(tag0, PCI_HEADER_MISC) & PCI_HEADER_MULTIFUNCTION)
589
* Now, to find non-compliant devices...
590
* If there is a valid ID for function 1 and the ID for func 0 and 1
591
* are different, or the base0 values of func 0 and 1 are differend,
592
* then assume there is a multi-function device.
594
tag1 = PCI_MAKE_TAG(busnum, devnum, 1);
595
id1 = pciReadLong(tag1, PCI_ID_REG);
596
if (id1 == 0xffffffff || id1 == 0x00000000)
600
(pciReadLong(tag0, PCI_MAP_REG_START) !=
601
pciReadLong(tag1, PCI_MAP_REG_START)))
608
* Generic find/read/write functions
614
int sec_bus, pri_bus;
615
static int previousBus = 0;
616
Bool speculativeProbe = FALSE;
617
unsigned char base_class, sub_class;
620
ErrorF("pciGenFindNext\n");
626
ErrorF("pciGenFindNext: pciBusNum %d\n", pciBusNum);
628
if (pciBusNum == -1) {
630
* Start at top of the order
632
if (pciNumBuses <= 0)
633
return(PCI_NOT_FOUND);
635
/* Skip ahead to the first bus defined by pciInit() */
636
for (pciBusNum = 0; !pciBusInfo[pciBusNum]; ++pciBusNum);
639
previousBus = pciBusNum; /* make sure previousBus exists */
641
#ifdef PCI_MFDEV_SUPPORT
643
ErrorF("pciGenFindNext: pciFuncNum %d\n", pciFuncNum);
646
* Somewhere in middle of order. Determine who's
649
if (pciFuncNum == 0) {
651
* Is current dev a multifunction device?
653
if (!speculativeProbe && pciMfDev(pciBusNum, pciDevNum))
654
/* Probe for other functions */
658
* No more functions this device. Next
662
} else if (++pciFuncNum >= 8) {
663
/* No more functions for this device. Next device please */
670
if (pciDevNum >= 32 ||
671
!pciBusInfo[pciBusNum] ||
672
pciDevNum >= pciBusInfo[pciBusNum]->numDevices) {
674
ErrorF("pciGenFindNext: next bus\n");
677
* No more devices for this bus. Next bus please
679
if (speculativeProbe) {
680
xfree(pciBusInfo[pciBusNum]);
681
pciBusInfo[pciBusNum] = NULL;
682
speculativeProbe = FALSE;
685
if (++pciBusNum >= pciMaxBusNum) {
687
ErrorF("pciGenFindNext: out of buses\n");
689
/* No more buses. All done for now */
690
return(PCI_NOT_FOUND);
698
ErrorF("pciGenFindNext: pciBusInfo[%d] = 0x%lx\n", pciBusNum, pciBusInfo[pciBusNum]);
700
if (!pciBusInfo[pciBusNum]) {
701
pciBusInfo[pciBusNum] = xnfalloc(sizeof(pciBusInfo_t));
702
*pciBusInfo[pciBusNum] = *pciBusInfo[previousBus];
704
speculativeProbe = TRUE;
708
* At this point, pciBusNum, pciDevNum, and pciFuncNum have been
709
* advanced to the next device. Compute the tag, and read the
710
* device/vendor ID field.
713
ErrorF("pciGenFindNext: [%d, %d, %d]\n", pciBusNum, pciDevNum, pciFuncNum);
715
pciDeviceTag = PCI_MAKE_TAG(pciBusNum, pciDevNum, pciFuncNum);
717
devid = pciReadLong(pciDeviceTag, 0);
720
ErrorF("pciGenFindNext: pciDeviceTag = 0x%lx, devid = 0x%lx\n", pciDeviceTag, devid);
722
if ((CARD16)(devid + 1U) <= (CARD16)1UL)
723
continue; /* Nobody home. Next device please */
725
if (pciNumBuses <= pciBusNum)
726
pciNumBuses = pciBusNum + 1;
728
speculativeProbe = FALSE;
729
previousBus = pciBusNum;
732
* Before checking for a specific devid, look for enabled
733
* PCI to PCI bridge devices. If one is found, create and
734
* initialize a bus info record (if one does not already exist).
736
#ifdef PCI_BRIDGE_SUPPORT
737
tmp = pciReadLong(pciDeviceTag, PCI_CLASS_REG);
738
base_class = PCI_CLASS_EXTRACT(tmp);
739
sub_class = PCI_SUBCLASS_EXTRACT(tmp);
740
if ((base_class == PCI_CLASS_BRIDGE) &&
741
((sub_class == PCI_SUBCLASS_BRIDGE_PCI) ||
742
(sub_class == PCI_SUBCLASS_BRIDGE_CARDBUS))) {
743
tmp = pciReadLong(pciDeviceTag, PCI_PCI_BRIDGE_BUS_REG);
744
sec_bus = PCI_SECONDARY_BUS_EXTRACT(tmp, pciDeviceTag);
745
pri_bus = PCI_PRIMARY_BUS_EXTRACT(tmp, pciDeviceTag);
747
ErrorF("pciGenFindNext: pri_bus %d sec_bus %d\n",
750
if (pciBusNum != pri_bus) {
751
/* Some bridges do not implement the primary bus register */
752
if ((PCI_BUS_NO_DOMAIN(pri_bus) != 0) ||
753
(sub_class != PCI_SUBCLASS_BRIDGE_CARDBUS))
755
"pciGenFindNext: primary bus mismatch on PCI"
756
" bridge 0x%08x (0x%02x, 0x%02x)\n",
757
pciDeviceTag, pciBusNum, pri_bus);
760
if ((pri_bus < sec_bus) && (sec_bus < pciMaxBusNum) &&
761
pciBusInfo[pri_bus]) {
763
* Found a secondary PCI bus
765
if (!pciBusInfo[sec_bus]) {
766
pciBusInfo[sec_bus] = xnfalloc(sizeof(pciBusInfo_t));
768
/* Copy parents settings... */
769
*pciBusInfo[sec_bus] = *pciBusInfo[pri_bus];
772
/* ...but not everything same as parent */
773
pciBusInfo[sec_bus]->primary_bus = pri_bus;
774
pciBusInfo[sec_bus]->secondary = TRUE;
775
pciBusInfo[sec_bus]->numDevices = 32;
777
if (pciNumBuses <= sec_bus)
778
pciNumBuses = sec_bus + 1;
784
* Does this device match the requested devid after
788
ErrorF("pciGenFindNext: pciDevidMask = 0x%lx, pciDevid = 0x%lx\n", pciDevidMask, pciDevid);
790
if ((devid & pciDevidMask) == pciDevid)
791
/* Yes - Return it. Otherwise, next device */
792
return(pciDeviceTag); /* got a match */
799
pciGenFindFirst(void)
801
/* Reset PCI bus number to start from top */
804
return pciGenFindNext();
807
#if defined (__powerpc__)
808
static int buserr_detected;
818
pciCfgMech1Read(PCITAG tag, int offset)
820
unsigned long rv = 0xffffffff;
822
ErrorF("pciCfgMech1Read(tag=%08x,offset=%08x)\n", tag, offset);
825
#if defined(__powerpc__)
826
signal(SIGBUS, buserr);
830
outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
833
#if defined(__powerpc__)
834
signal(SIGBUS, SIG_DFL);
838
ErrorF("pciCfgMech1Read() BUS ERROR\n");
848
pciCfgMech1Write(PCITAG tag, int offset, CARD32 val)
851
ErrorF("pciCfgMech1Write(tag=%08x,offset=%08x,val=%08x)\n",
855
#if defined(__powerpc__)
856
signal(SIGBUS, SIG_IGN);
859
outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
860
#if defined(Lynx) && defined(__powerpc__)
861
outb(0x80, 0x00); /* without this the next access fails
862
* on my Powerstack system when we use
863
* assembler inlines for outl */
867
#if defined(__powerpc__)
868
signal(SIGBUS, SIG_DFL);
873
pciCfgMech1SetBits(PCITAG tag, int offset, CARD32 mask, CARD32 val)
875
unsigned long rv = 0xffffffff;
877
#if defined(__powerpc__)
878
signal(SIGBUS, buserr);
881
outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
883
rv = (rv & ~mask) | val;
886
#if defined(__powerpc__)
887
signal(SIGBUS, SIG_DFL);
892
pciByteSwap(CARD32 u)
894
#if X_BYTE_ORDER == X_BIG_ENDIAN
895
# if defined(__powerpc__) && defined(PowerMAX_OS)
898
__inst_stwbrx(u, &tmp, 0);
902
# else /* !PowerMAX_OS */
906
# endif /* !PowerMAX_OS */
908
#else /* !BIG_ENDIAN */
916
pciAddrNOOP(PCITAG tag, PciAddrType type, ADDRESS addr)
922
xf86scanpci(int flags)
934
#ifdef XF86SCANPCI_WRAPPER
935
XF86SCANPCI_WRAPPER(SCANPCI_INIT);
938
tag = pciFindFirst(0,0); /* 0 mask means match any valid device */
939
/* Check if no devices, return now */
940
if (tag == PCI_NOT_FOUND) {
941
#ifdef XF86SCANPCI_WRAPPER
942
XF86SCANPCI_WRAPPER(SCANPCI_TERM);
948
ErrorF("xf86scanpci: tag = 0x%lx\n", tag);
951
xf86MsgVerb(X_INFO, 2, "PCI: PCI scan (all values are in hex)\n");
954
while (idx < MAX_PCI_DEVICES && tag != PCI_NOT_FOUND) {
955
devp = xcalloc(1, sizeof(pciDevice));
958
"xf86scanpci: Out of memory after %d devices!!\n", idx);
959
return (pciConfigPtr *)NULL;
962
/* Identify pci device by bus, dev, func, and tag */
964
devp->busnum = PCI_BUS_FROM_TAG(tag);
965
devp->devnum = PCI_DEV_FROM_TAG(tag);
966
devp->funcnum = PCI_FUNC_FROM_TAG(tag);
968
/* Read config space for this device */
969
for (i = 0; i < 17; i++) /* PCI hdr plus 1st dev spec dword */
970
devp->cfgspc.dwords[i] = pciReadLong(tag, i * sizeof(CARD32));
972
switch (devp->pci_header_type & 0x7f) {
974
/* Get base address sizes for type 0 headers */
975
for (i = 0; i < 7; i++)
977
pciGetBaseSize(tag, i, FALSE, &devp->minBasesize);
982
/* Allow master aborts to complete normally on secondary buses */
983
if (!(devp->pci_bridge_control & PCI_PCI_BRIDGE_MASTER_ABORT_EN))
985
pciWriteByte(tag, PCI_PCI_BRIDGE_CONTROL_REG,
986
devp->pci_bridge_control & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN);
994
xf86MsgVerb(X_INFO, 2, "PCI: BusID 0x%.2x,0x%02x,0x%1x "
995
"ID 0x%04x,0x%04x Rev 0x%02x Class 0x%02x,0x%02x\n",
996
devp->busnum, devp->devnum, devp->funcnum,
997
devp->pci_vendor, devp->pci_device, devp->pci_rev_id,
998
devp->pci_base_class, devp->pci_sub_class);
1000
xf86MsgVerb(X_INFO, 2, "PCI: %.2x:%02x:%1x: chip %04x,%04x"
1001
" card %04x,%04x rev %02x class %02x,%02x,%02x hdr %02x\n",
1002
devp->busnum, devp->devnum, devp->funcnum,
1003
devp->pci_vendor, devp->pci_device,
1004
devp->pci_subsys_vendor, devp->pci_subsys_card,
1005
devp->pci_rev_id, devp->pci_base_class,
1006
devp->pci_sub_class, devp->pci_prog_if,
1007
devp->pci_header_type);
1010
pci_devp[idx++] = devp;
1011
tag = pciFindNext();
1014
ErrorF("xf86scanpci: tag = pciFindNext = 0x%lx\n", tag);
1018
/* Restore modified data (in reverse order), and link buses */
1019
while (--idx >= 0) {
1020
devp = pci_devp[idx];
1021
switch (devp->pci_header_type & 0x7f) {
1023
if ((devp->pci_base_class != PCI_CLASS_BRIDGE) ||
1024
(devp->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST))
1026
pciBusInfo[devp->busnum]->bridge = devp;
1027
pciBusInfo[devp->busnum]->primary_bus = devp->busnum;
1028
#ifdef ARCH_PCI_HOST_BRIDGE
1029
ARCH_PCI_HOST_BRIDGE(devp);
1035
i = PCI_SECONDARY_BUS_EXTRACT(devp->pci_pp_bus_register, devp->tag);
1036
if (i > devp->busnum) {
1037
if (pciBusInfo[i]) {
1038
pciBusInfo[i]->bridge = devp;
1040
* The back link needs to be set here, and is unlikely to
1043
devp->businfo = pciBusInfo[i];
1045
#ifdef ARCH_PCI_PCI_BRIDGE
1046
ARCH_PCI_PCI_BRIDGE(devp);
1049
if (!(devp->pci_bridge_control & PCI_PCI_BRIDGE_MASTER_ABORT_EN))
1051
pciWriteByte(devp->tag, PCI_PCI_BRIDGE_CONTROL_REG,
1052
devp->pci_bridge_control);
1060
#ifdef XF86SCANPCI_WRAPPER
1061
XF86SCANPCI_WRAPPER(SCANPCI_TERM);
1065
* Lastly, link bridges to their secondary bus, after the architecture has
1066
* had a chance to modify these assignments.
1068
for (idx = 0; idx < pciNumBuses; idx++) {
1069
if (!(busp = pciBusInfo[idx]) || !(devp = busp->bridge))
1071
devp->businfo = busp;
1075
xf86MsgVerb(X_INFO, 2, "PCI: End of PCI scan\n");
1082
pciCheckForBrokenBase(PCITAG Tag,int basereg)
1084
pciWriteLong(Tag, PCI_MAP_REG_START + (basereg << 2), 0xffffffff);
1085
return pciReadLong(Tag, PCI_MAP_REG_START + (basereg << 2));
1088
#if defined(INCLUDE_XF86_MAP_PCI_MEM)
1091
xf86MapPciMem(int ScreenNum, int Flags, PCITAG Tag, ADDRESS Base,
1094
ADDRESS hostbase = pciBusAddrToHostAddr(Tag, PCI_MEM,Base);
1099
* If there are possible read side-effects, disable memory while
1100
* doing the mapping.
1102
if (Flags & VIDMEM_READSIDEEFFECT) {
1103
save = pciReadLong(Tag, PCI_CMD_STAT_REG);
1104
pciWriteLong(Tag, PCI_CMD_STAT_REG,
1105
save & ~PCI_CMD_MEM_ENABLE);
1107
base = xf86MapDomainMemory(ScreenNum, Flags, Tag, hostbase, Size);
1109
FatalError("xf86MapPciMem: Could not mmap PCI memory "
1110
"[base=0x%x,hostbase=0x%x,size=%x] (%s)\n",
1111
Base, hostbase, Size, strerror(errno));
1114
* If read side-effects, do whatever might be needed to prevent
1115
* unintended reads, then restore PCI_CMD_STAT_REG.
1117
if (Flags & VIDMEM_READSIDEEFFECT) {
1118
xf86MapReadSideEffects(ScreenNum, Flags, base, Size);
1119
pciWriteLong(Tag, PCI_CMD_STAT_REG, save);
1121
return((pointer)base);
1125
handlePciBIOS(PCITAG Tag, int basereg,
1126
int (*func)(PCITAG, CARD8*, ADDRESS, pointer),
1131
romBaseSource b_reg;
1136
romsave = pciReadLong(Tag, PCI_MAP_ROM_REG);
1138
for (i = ROM_BASE_PRESET; i <= ROM_BASE_FIND; i++) {
1139
memType savebase = 0, newbase, romaddr;
1141
if (i == ROM_BASE_PRESET) {
1142
/* Does the driver have a preference? */
1143
if (basereg > ROM_BASE_PRESET && basereg <= ROM_BASE_FIND)
1150
if (!(newbase = getValidBIOSBase(Tag, b_reg)))
1151
continue; /* no valid address found */
1153
romaddr = PCIGETROM(newbase);
1155
/* if we use a mem base save it and move it out of the way */
1156
if (b_reg >= 0 && b_reg <= 5) {
1157
savebase = pciReadLong(Tag, PCI_MAP_REG_START+(b_reg<<2));
1158
xf86MsgVerb(X_INFO,5,"xf86ReadPciBios: modifying membase[%i]"
1159
" for device %i:%i:%i\n", basereg,
1160
PCI_BUS_FROM_TAG(Tag), PCI_DEV_FROM_TAG(Tag),
1161
PCI_FUNC_FROM_TAG(Tag));
1162
pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2),
1165
/* Set ROM base address and enable ROM address decoding */
1166
pciWriteLong(Tag, PCI_MAP_ROM_REG, romaddr
1167
| PCI_MAP_ROM_DECODE_ENABLE);
1169
hostbase = pciBusAddrToHostAddr(Tag, PCI_MEM, PCIGETROM(romaddr));
1171
if ((xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp) !=
1173
(tmp[0] != 0x55) || (tmp[1] != 0xaa) || !tmp[2] ) {
1174
/* Restore the base register if it was changed. */
1175
if (savebase) pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2),
1178
/* No BIOS found: try another address */
1182
ret = (*func)(Tag, tmp, hostbase, args);
1184
/* Restore the base register if it was changed. */
1185
if (savebase) pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2),
1187
/* Restore ROM address decoding */
1188
pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave);
1192
/* Restore ROM address decoding */
1193
pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave);
1198
unsigned long Offset;
1201
PciBiosType BiosType;
1202
} readBios, *readBiosPtr;
1205
readPciBios(PCITAG Tag, CARD8* tmp, ADDRESS hostbase, pointer args)
1207
unsigned int image_length = 0;
1208
readBiosPtr rd = args;
1211
/* We found a PCI BIOS Image. Now we look for the correct type */
1212
while ((tmp[0] == 0x55) && (tmp[1] == 0xAA)) {
1213
unsigned short data_off = tmp[0x18] | (tmp[0x19] << 8);
1214
unsigned char data[0x18];
1217
if ((xf86ReadDomainMemory(Tag, hostbase + data_off, sizeof(data), data)
1226
ErrorF("data segment in BIOS: 0x%x, type: 0x%x\n", data_off, type);
1228
if (type != rd->BiosType) { /* not correct image: find next one */
1229
unsigned char indicator = data[0x15];
1230
unsigned int i_length;
1231
if (indicator & 0x80) /* last image */
1233
i_length = (data[0x10] | (data[0x11] << 8)) << 9;
1235
ErrorF("data image length: 0x%x, ind: 0x%x\n",
1236
image_length, indicator);
1238
hostbase += i_length;
1239
if (xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp)
1244
/* OK, we have a PCI BIOS Image of the correct type */
1246
if (rd->BiosType == PCI_BIOS_PC)
1247
image_length = tmp[2] << 9;
1249
image_length = (data[0x10] | (data[0x11] << 8)) << 9;
1251
ErrorF("BIOS length: 0x%x\n", image_length);
1260
* if no length is given return the full lenght,
1261
* Offset 0. Beware: Area pointed to by Buf must
1265
rd->Len = image_length;
1268
if ((rd->Offset) > (image_length)) {
1269
xf86Msg(X_WARNING,"xf86ReadPciBios: requesting data past "
1270
"end of BIOS %i > %i\n",(rd->Offset) , (image_length));
1272
if ((rd->Offset + rd->Len) > (image_length)) {
1273
rd->Len = (image_length) - rd->Offset;
1274
xf86MsgVerb(X_INFO,3,"Truncating PCI BIOS Length to %i\n",rd->Len);
1279
ret = xf86ReadDomainMemory(Tag, hostbase + rd->Offset, rd->Len, rd->Buf);
1286
getPciBIOSTypes(PCITAG Tag, CARD8* tmp, ADDRESS hostbase, pointer arg)
1289
PciBiosType *Buf = arg;
1291
/* We found a PCI BIOS Image. Now we collect the types type */
1293
unsigned short data_off = tmp[0x18] | (tmp[0x19] << 8);
1294
unsigned char data[16];
1295
unsigned int i_length;
1297
if ((xf86ReadDomainMemory(Tag, hostbase + data_off, sizeof(data), data)
1305
if (data[0x14] >= PCI_BIOS_OTHER)
1306
*Buf++ = PCI_BIOS_OTHER;
1308
*Buf++ = data[0x14];
1311
if (data[0x15] & 0x80) /* last image */
1314
ErrorF("data segment in BIOS: 0x%x, type: 0x%x\n", data_off, type);
1316
i_length = (data[0x10] | (data[0x11] << 8)) << 9;
1318
ErrorF("data image length: 0x%x, ind: 0x%x\n",
1319
image_length, indicator);
1321
hostbase += i_length;
1322
if (xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp)
1326
} while ((tmp[0] == 0x55) && (tmp[1] == 0xAA));
1330
typedef CARD32 (*ReadProcPtr)(PCITAG, int);
1331
typedef void (*WriteProcPtr)(PCITAG, int, CARD32);
1334
HandlePciBios(PCITAG Tag, int basereg,
1335
int (*func)(PCITAG, CARD8*, ADDRESS, pointer),
1343
n = handlePciBIOS(Tag,basereg,func,ptr);
1347
num = pciTestMultiDeviceCard(PCI_BUS_FROM_TAG(Tag),
1348
PCI_DEV_FROM_TAG(Tag),
1349
PCI_FUNC_FROM_TAG(Tag),&pTag);
1353
#define PCI_ENA (PCI_CMD_MEM_ENABLE | PCI_CMD_IO_ENABLE)
1354
Acc1 = ((ReadProcPtr)(pciLongFunc(Tag,READ)))(Tag,PCI_CMD_STAT_REG);
1355
((WriteProcPtr)(pciLongFunc(Tag,WRITE)))(Tag,
1356
PCI_CMD_STAT_REG,(Acc1 & ~PCI_ENA));
1358
for (i = 0; i < num; i++) {
1359
Acc2 = ((ReadProcPtr)(pciLongFunc(pTag[i],READ)))(pTag[i],PCI_CMD_STAT_REG);
1360
((WriteProcPtr)(pciLongFunc(pTag[i],WRITE)))(pTag[i],
1361
PCI_CMD_STAT_REG,(Acc2 | PCI_ENA));
1363
n = handlePciBIOS(pTag[i],0,func,ptr);
1365
((WriteProcPtr)(pciLongFunc(pTag[i],WRITE)))(pTag[i],PCI_CMD_STAT_REG,Acc2);
1369
((WriteProcPtr)(pciLongFunc(Tag,WRITE)))(Tag,PCI_CMD_STAT_REG,Acc1);
1374
xf86ReadPciBIOS(unsigned long Offset, PCITAG Tag, int basereg,
1375
unsigned char *Buf, int Len)
1377
return xf86ReadPciBIOSByType(Offset, Tag, basereg, Buf, Len, PCI_BIOS_PC);
1381
xf86ReadPciBIOSByType(unsigned long Offset, PCITAG Tag, int basereg,
1382
unsigned char *Buf, int Len, PciBiosType Type)
1391
return HandlePciBios(Tag, basereg, readPciBios, &rb);
1395
xf86GetAvailablePciBIOSTypes(PCITAG Tag, int basereg, PciBiosType *Buf)
1397
return HandlePciBios(Tag, basereg, getPciBIOSTypes, (pointer) Buf);
1400
#endif /* INCLUDE_XF86_MAP_PCI_MEM */
1402
#ifdef INCLUDE_XF86_NO_DOMAIN
1405
xf86GetPciDomain(PCITAG Tag)
1411
xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag,
1412
ADDRESS Base, unsigned long Size)
1414
return xf86MapVidMem(ScreenNum, Flags, Base, Size);
1418
xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag,
1419
IOADDRESS Base, unsigned long Size)
1425
xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf)
1427
int ret, length, rlength;
1429
/* Read in 64kB chunks */
1431
while ((length = Len) > 0) {
1432
if (length > 0x010000) length = 0x010000;
1433
rlength = xf86ReadBIOS(Base, 0, Buf, length);
1439
if (rlength < length) break;
1448
#endif /* INCLUDE_XF86_NO_DOMAIN */