~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c,v 1.71 2003/01/23 16:22:13 tsi Exp $ */
 
2
/*
 
3
 * Pci.c - New server PCI access functions
 
4
 *
 
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.
 
8
 *
 
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
 
23
 *                               function
 
24
 *      pciTag()               - Return tag for a given PCI bus, device, &
 
25
 *                               function
 
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
 
29
 *                               addr mapping
 
30
 *      xf86MapPciMem()        - Like xf86MapVidMem() except function expects
 
31
 *                               a PCI address and a PCITAG that identifies
 
32
 *                               a PCI device
 
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
 
42
 *
 
43
 * The actual PCI backend driver is selected by the pciInit() function
 
44
 * (see below)  using either compile time definitions, run-time checks,
 
45
 * or both.
 
46
 *
 
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.
 
50
 *
 
51
 * Less well behaved platforms/OS's can roll their own functions.
 
52
 *
 
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
 
55
 * conditional.
 
56
 *
 
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).
 
61
 *
 
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.
 
66
 *
 
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.
 
71
 *
 
72
 * Gary Barton
 
73
 * Concurrent Computer Corporation
 
74
 * garyb@gate.net
 
75
 *
 
76
 */
 
77
 
 
78
/*
 
79
 * Copyright 1998 by Concurrent Computer Corporation
 
80
 *
 
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.
 
91
 *
 
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
 
99
 * SOFTWARE.
 
100
 *
 
101
 * Copyright 1998 by Metro Link Incorporated
 
102
 *
 
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.
 
113
 *
 
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
 
121
 * SOFTWARE.
 
122
 *
 
123
 * This software is derived from the original XFree86 PCI code
 
124
 * which includes the following copyright notices as well:
 
125
 *
 
126
 * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org>
 
127
 *
 
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
 
137
 * implied warranty.
 
138
 *
 
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.
 
146
 *
 
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:
 
149
 *
 
150
 * Redistribution and use in source and binary forms, with or without
 
151
 * modification, are permitted provided that the following conditions
 
152
 * are met:
 
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.
 
160
 *
 
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.
 
171
 *
 
172
 */
 
173
#include <errno.h>
 
174
#include <signal.h>
 
175
#include "Xarch.h"
 
176
#include "compiler.h"
 
177
#include "xf86.h"
 
178
#include "xf86Priv.h"
 
179
#define XF86_OS_PRIVS
 
180
#include "xf86_OSproc.h"
 
181
#include "Pci.h"
 
182
 
 
183
#define PCI_MFDEV_SUPPORT   1 /* Include PCI multifunction device support */
 
184
#define PCI_BRIDGE_SUPPORT  1 /* Include support for PCI-to-PCI bridges */
 
185
 
 
186
#ifdef PC98
 
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)
 
191
#endif
 
192
 
 
193
/*
 
194
 * Global data
 
195
 */
 
196
static int    pciInitialized = 0;
 
197
 
 
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           */
 
201
 
 
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 */
 
206
 
 
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;
 
211
 
 
212
static pciConfigPtr pci_devp[MAX_PCI_DEVICES + 1] = {NULL, };
 
213
 
 
214
/*
 
215
 * Platform specific PCI function pointers.
 
216
 *
 
217
 * NOTE: A platform/OS specific pci init procedure can override these defaults
 
218
 *       by setting them to the appropriate platform dependent functions.
 
219
 */
 
220
PCITAG     (*pciFindFirstFP)(void) = pciGenFindFirst;
 
221
PCITAG     (*pciFindNextFP)(void) = pciGenFindNext;
 
222
 
 
223
/*
 
224
 * pciInit - choose correct platform/OS specific PCI init routine
 
225
 */
 
226
void
 
227
pciInit()
 
228
{
 
229
        if (pciInitialized)
 
230
                return;
 
231
 
 
232
        pciInitialized = 1;
 
233
 
 
234
        /* XXX */
 
235
#if defined(DEBUGPCI)
 
236
        if (DEBUGPCI >= xf86Verbose)
 
237
                xf86Verbose = DEBUGPCI;
 
238
#endif
 
239
 
 
240
        ARCH_PCI_INIT();
 
241
#if defined(ARCH_PCI_OS_INIT)
 
242
        if (pciNumBuses <= 0)
 
243
            ARCH_PCI_OS_INIT();
 
244
#endif
 
245
}
 
246
 
 
247
PCITAG
 
248
pciFindFirst(CARD32 id, CARD32 mask)
 
249
{
 
250
#ifdef DEBUGPCI
 
251
  ErrorF("pciFindFirst(0x%lx, 0x%lx), pciInit = %d\n", id, mask, pciInitialized);
 
252
#endif
 
253
  pciInit();
 
254
 
 
255
  pciDevid = id & mask;
 
256
  pciDevidMask = mask;
 
257
 
 
258
  return((*pciFindFirstFP)());
 
259
}
 
260
 
 
261
PCITAG
 
262
pciFindNext(void)
 
263
{
 
264
#ifdef DEBUGPCI
 
265
  ErrorF("pciFindNext(), pciInit = %d\n", pciInitialized);
 
266
#endif
 
267
  pciInit();
 
268
 
 
269
  return((*pciFindNextFP)());
 
270
}
 
271
 
 
272
CARD32
 
273
pciReadLong(PCITAG tag, int offset)
 
274
{
 
275
  int bus = PCI_BUS_FROM_TAG(tag);
 
276
 
 
277
#ifdef DEBUGPCI
 
278
  ErrorF("pciReadLong(0x%lx, %d)\n", tag, offset);
 
279
#endif
 
280
  pciInit();
 
281
 
 
282
  if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] &&
 
283
        pciBusInfo[bus]->funcs->pciReadLong) {
 
284
    CARD32 rv = (*pciBusInfo[bus]->funcs->pciReadLong)(tag, offset);
 
285
 
 
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));
 
288
    return(rv);
 
289
   }
 
290
 
 
291
  return(PCI_NOT_FOUND);
 
292
}
 
293
 
 
294
CARD16
 
295
pciReadWord(PCITAG tag, int offset)
 
296
{
 
297
  CARD32 tmp;
 
298
  int    shift = (offset & 3) * 8;
 
299
  int    aligned_offset = offset & ~3;
 
300
 
 
301
  if (shift != 0 && shift != 16)
 
302
          FatalError("pciReadWord: Alignment error: Cannot read 16 bits "
 
303
                     "at offset %d\n", offset);
 
304
 
 
305
  tmp = pciReadLong(tag, aligned_offset);
 
306
 
 
307
  return((CARD16)((tmp >> shift) & 0xffff));
 
308
}
 
309
 
 
310
CARD8
 
311
pciReadByte(PCITAG tag, int offset)
 
312
{
 
313
  CARD32 tmp;
 
314
  int    shift = (offset & 3) * 8;
 
315
  int    aligned_offset = offset & ~3;
 
316
 
 
317
  tmp = pciReadLong(tag, aligned_offset);
 
318
 
 
319
  return((CARD8)((tmp >> shift) & 0xff));
 
320
}
 
321
 
 
322
void
 
323
pciWriteLong(PCITAG tag, int offset, CARD32 val)
 
324
{
 
325
  int bus = PCI_BUS_FROM_TAG(tag);
 
326
 
 
327
  pciInit();
 
328
 
 
329
  if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
 
330
        pciBusInfo[bus]->funcs->pciWriteLong)
 
331
          (*pciBusInfo[bus]->funcs->pciWriteLong)(tag, offset, val);
 
332
}
 
333
 
 
334
void
 
335
pciWriteWord(PCITAG tag, int offset, CARD16 val)
 
336
{
 
337
  CARD32 tmp;
 
338
  int    aligned_offset = offset & ~3;
 
339
  int    shift = (offset & 3) * 8;
 
340
 
 
341
  if (shift != 0 && shift != 16)
 
342
          FatalError("pciWriteWord: Alignment Error: Cannot read 16 bits "
 
343
                        "from offset %d\n", offset);
 
344
 
 
345
  tmp = pciReadLong(tag, aligned_offset);
 
346
 
 
347
  tmp &= ~(0xffffL << shift);
 
348
  tmp |= (((CARD32)val) << shift);
 
349
 
 
350
  pciWriteLong(tag, aligned_offset, tmp);
 
351
}
 
352
 
 
353
void
 
354
pciWriteByte(PCITAG tag, int offset, CARD8 val)
 
355
{
 
356
  CARD32 tmp;
 
357
  int    aligned_offset = offset & ~3;
 
358
  int    shift = (offset & 3) *8 ;
 
359
 
 
360
  tmp = pciReadLong(tag, aligned_offset);
 
361
 
 
362
  tmp &= ~(0xffL << shift);
 
363
  tmp |= (((CARD32)val) << shift);
 
364
 
 
365
  pciWriteLong(tag, aligned_offset, tmp);
 
366
}
 
367
 
 
368
void
 
369
pciSetBitsLong(PCITAG tag, int offset, CARD32 mask, CARD32 val)
 
370
{
 
371
    int bus = PCI_BUS_FROM_TAG(tag);
 
372
 
 
373
#ifdef DEBUGPCI
 
374
    ErrorF("pciReadLong(0x%lx, %d)\n", tag, offset);
 
375
#endif
 
376
    pciInit();
 
377
 
 
378
    if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
 
379
        pciBusInfo[bus]->funcs->pciReadLong) {
 
380
        (*pciBusInfo[bus]->funcs->pciSetBitsLong)(tag, offset, mask, val);
 
381
    }
 
382
}
 
383
 
 
384
void
 
385
pciSetBitsByte(PCITAG tag, int offset, CARD8 mask, CARD8 val)
 
386
{
 
387
  CARD32 tmp_mask, tmp_val;
 
388
  int    aligned_offset = offset & ~3;
 
389
  int    shift = (offset & 3) *8 ;
 
390
 
 
391
  tmp_mask = mask << shift;
 
392
  tmp_val = val << shift;
 
393
  pciSetBitsLong(tag, aligned_offset, tmp_mask, tmp_val);
 
394
}
 
395
 
 
396
pointer
 
397
pciLongFunc(PCITAG tag, pciFunc func)
 
398
{
 
399
    int bus = PCI_BUS_FROM_TAG(tag);
 
400
 
 
401
    pciInit();
 
402
 
 
403
    if ((bus < 0) || (bus > pciNumBuses) || !pciBusInfo[bus] ||
 
404
        !pciBusInfo[bus]->funcs->pciReadLong) return NULL;
 
405
 
 
406
    switch (func) {
 
407
    case WRITE:
 
408
        return (void *)pciBusInfo[bus]->funcs->pciWriteLong;
 
409
    case READ:
 
410
        return (void *)pciBusInfo[bus]->funcs->pciReadLong;
 
411
    case SET_BITS:
 
412
        return (void *)pciBusInfo[bus]->funcs->pciSetBitsLong;
 
413
    }
 
414
    return NULL;
 
415
}
 
416
 
 
417
ADDRESS
 
418
pciBusAddrToHostAddr(PCITAG tag, PciAddrType type, ADDRESS addr)
 
419
{
 
420
  int bus = PCI_BUS_FROM_TAG(tag);
 
421
 
 
422
  pciInit();
 
423
 
 
424
  if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
 
425
        pciBusInfo[bus]->funcs->pciAddrBusToHost)
 
426
          return (*pciBusInfo[bus]->funcs->pciAddrBusToHost)(tag, type, addr);
 
427
  else
 
428
          return(addr);
 
429
}
 
430
 
 
431
ADDRESS
 
432
pciHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr)
 
433
{
 
434
  int bus = PCI_BUS_FROM_TAG(tag);
 
435
 
 
436
  pciInit();
 
437
 
 
438
  if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] &&
 
439
        pciBusInfo[bus]->funcs->pciAddrHostToBus)
 
440
          return (*pciBusInfo[bus]->funcs->pciAddrHostToBus)(tag, type, addr);
 
441
  else
 
442
          return(addr);
 
443
}
 
444
 
 
445
/*
 
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.
 
455
 */
 
456
 
 
457
int
 
458
pciGetBaseSize(PCITAG tag, int index, Bool destructive, Bool *min)
 
459
{
 
460
  int offset;
 
461
  CARD32 addr1;
 
462
  CARD32 addr2;
 
463
  CARD32 mask1;
 
464
  CARD32 mask2;
 
465
  int bits = 0;
 
466
 
 
467
  /*
 
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
 
470
   * allocated address.
 
471
   */
 
472
 
 
473
  /*
 
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.
 
476
   */
 
477
  if (index < 0 || index > 6)
 
478
    return 0;
 
479
 
 
480
  pciInit();
 
481
 
 
482
  if (xf86GetPciSizeFromOS(tag, index, &bits)) {
 
483
      if (min)
 
484
          *min = TRUE;
 
485
      return bits;
 
486
  }
 
487
 
 
488
  if (min)
 
489
    *min = destructive;
 
490
 
 
491
  /* Get the PCI offset */
 
492
  if (index == 6)
 
493
    offset = PCI_MAP_ROM_REG;
 
494
  else
 
495
    offset = PCI_MAP_REG_START + (index << 2);
 
496
 
 
497
  addr1 = pciReadLong(tag, offset);
 
498
  /*
 
499
   * Check if this is the second part of a 64 bit address.
 
500
   * XXX need to check how endianness affects 64 bit addresses.
 
501
   */
 
502
  if (index > 0 && index < 6) {
 
503
    addr2 = pciReadLong(tag, offset - 4);
 
504
    if (PCI_MAP_IS_MEM(addr2) && PCI_MAP_IS64BITMEM(addr2))
 
505
      return 0;
 
506
  }
 
507
 
 
508
  if (destructive) {
 
509
    pciWriteLong(tag, offset, 0xffffffff);
 
510
    mask1 = pciReadLong(tag, offset);
 
511
    pciWriteLong(tag, offset, addr1);
 
512
  } else {
 
513
    mask1 = addr1;
 
514
  }
 
515
 
 
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);
 
520
      if (destructive) {
 
521
        pciWriteLong(tag, offset + 4, 0xffffffff);
 
522
        mask2 = pciReadLong(tag, offset + 4);
 
523
        pciWriteLong(tag, offset + 4, addr2);
 
524
      } else {
 
525
        mask2 = addr2;
 
526
      }
 
527
      if (mask2 == 0)
 
528
        return 0;
 
529
      bits = 32;
 
530
      while ((mask2 & 1) == 0) {
 
531
        bits++;
 
532
        mask2 >>= 1;
 
533
      }
 
534
      if (bits > 32)
 
535
          return bits;
 
536
    }
 
537
  }
 
538
  if (index < 6)
 
539
    if (PCI_MAP_IS_MEM(mask1))
 
540
      mask1 = PCIGETMEMORY(mask1);
 
541
    else
 
542
      mask1 = PCIGETIO(mask1);
 
543
  else
 
544
    mask1 = PCIGETROM(mask1);
 
545
  if (mask1 == 0)
 
546
    return 0;
 
547
  bits = 0;
 
548
  while ((mask1 & 1) == 0) {
 
549
    bits++;
 
550
    mask1 >>= 1;
 
551
  }
 
552
  /* I/O maps can be no larger than 8 bits */
 
553
 
 
554
#if defined(Lynx) && defined(__powerpc__)
 
555
  if (PCI_MAP_IS_IO(addr1) && bits > 8)
 
556
#else
 
557
  if ((index < 6) && PCI_MAP_IS_IO(addr1) && bits > 8)
 
558
#endif
 
559
    bits = 8;
 
560
  /* ROM maps can be no larger than 24 bits */
 
561
  if (index == 6 && bits > 24)
 
562
    bits = 24;
 
563
  return bits;
 
564
}
 
565
 
 
566
PCITAG
 
567
pciTag(int busnum, int devnum, int funcnum)
 
568
{
 
569
        return(PCI_MAKE_TAG(busnum,devnum,funcnum));
 
570
}
 
571
 
 
572
Bool
 
573
pciMfDev(int busnum, int devnum)
 
574
{
 
575
    PCITAG tag0, tag1;
 
576
    unsigned long id0, id1;
 
577
 
 
578
    /* Detect a multi-function device that complies to the PCI 2.0 spec */
 
579
 
 
580
    tag0 = PCI_MAKE_TAG(busnum, devnum, 0);
 
581
    id0  = pciReadLong(tag0, PCI_ID_REG);
 
582
    if (id0 == 0xffffffff)
 
583
        return FALSE;
 
584
 
 
585
    if (pciReadLong(tag0, PCI_HEADER_MISC) & PCI_HEADER_MULTIFUNCTION)
 
586
        return TRUE;
 
587
 
 
588
    /*
 
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.
 
593
     */
 
594
    tag1 = PCI_MAKE_TAG(busnum, devnum, 1);
 
595
    id1  = pciReadLong(tag1, PCI_ID_REG);
 
596
    if (id1 == 0xffffffff || id1 == 0x00000000)
 
597
        return FALSE;
 
598
 
 
599
    if ((id0 != id1) ||
 
600
        (pciReadLong(tag0, PCI_MAP_REG_START) !=
 
601
         pciReadLong(tag1, PCI_MAP_REG_START)))
 
602
        return TRUE;
 
603
 
 
604
    return FALSE;
 
605
}
 
606
 
 
607
/*
 
608
 * Generic find/read/write functions
 
609
 */
 
610
PCITAG
 
611
pciGenFindNext(void)
 
612
{
 
613
    CARD32 devid, tmp;
 
614
    int sec_bus, pri_bus;
 
615
    static int previousBus = 0;
 
616
    Bool speculativeProbe = FALSE;
 
617
    unsigned char base_class, sub_class;
 
618
 
 
619
#ifdef DEBUGPCI
 
620
    ErrorF("pciGenFindNext\n");
 
621
#endif
 
622
 
 
623
    for (;;) {
 
624
 
 
625
#ifdef DEBUGPCI
 
626
        ErrorF("pciGenFindNext: pciBusNum %d\n", pciBusNum);
 
627
#endif
 
628
        if (pciBusNum == -1) {
 
629
            /*
 
630
             * Start at top of the order
 
631
             */
 
632
            if (pciNumBuses <= 0)
 
633
                return(PCI_NOT_FOUND);
 
634
 
 
635
            /* Skip ahead to the first bus defined by pciInit() */
 
636
            for (pciBusNum = 0;  !pciBusInfo[pciBusNum];  ++pciBusNum);
 
637
            pciFuncNum = 0;
 
638
            pciDevNum = 0;
 
639
            previousBus = pciBusNum; /* make sure previousBus exists */
 
640
        } else {
 
641
#ifdef PCI_MFDEV_SUPPORT
 
642
#ifdef DEBUGPCI
 
643
            ErrorF("pciGenFindNext: pciFuncNum %d\n", pciFuncNum);
 
644
#endif
 
645
            /*
 
646
             * Somewhere in middle of order.  Determine who's
 
647
             * next up
 
648
             */
 
649
            if (pciFuncNum == 0) {
 
650
                /*
 
651
                 * Is current dev a multifunction device?
 
652
                 */
 
653
                if (!speculativeProbe && pciMfDev(pciBusNum, pciDevNum))
 
654
                    /* Probe for other functions */
 
655
                    pciFuncNum = 1;
 
656
                else
 
657
                    /*
 
658
                     * No more functions this device. Next
 
659
                     * device please
 
660
                     */
 
661
                    pciDevNum ++;
 
662
            } else if (++pciFuncNum >= 8) {
 
663
                /* No more functions for this device. Next device please */
 
664
                pciFuncNum = 0;
 
665
                pciDevNum ++;
 
666
            }
 
667
#else
 
668
            pciDevNum ++;
 
669
#endif
 
670
            if (pciDevNum >= 32 ||
 
671
                !pciBusInfo[pciBusNum] ||
 
672
                pciDevNum >= pciBusInfo[pciBusNum]->numDevices) {
 
673
#ifdef DEBUGPCI
 
674
                ErrorF("pciGenFindNext: next bus\n");
 
675
#endif
 
676
                /*
 
677
                 * No more devices for this bus. Next bus please
 
678
                 */
 
679
                if (speculativeProbe) {
 
680
                    xfree(pciBusInfo[pciBusNum]);
 
681
                    pciBusInfo[pciBusNum] = NULL;
 
682
                    speculativeProbe = FALSE;
 
683
                }
 
684
 
 
685
                if (++pciBusNum >= pciMaxBusNum) {
 
686
#ifdef DEBUGPCI
 
687
                    ErrorF("pciGenFindNext: out of buses\n");
 
688
#endif
 
689
                    /* No more buses.  All done for now */
 
690
                    return(PCI_NOT_FOUND);
 
691
                }
 
692
 
 
693
                pciDevNum = 0;
 
694
            }
 
695
        }
 
696
 
 
697
#ifdef DEBUGPCI
 
698
        ErrorF("pciGenFindNext: pciBusInfo[%d] = 0x%lx\n", pciBusNum, pciBusInfo[pciBusNum]);
 
699
#endif
 
700
        if (!pciBusInfo[pciBusNum]) {
 
701
            pciBusInfo[pciBusNum] = xnfalloc(sizeof(pciBusInfo_t));
 
702
            *pciBusInfo[pciBusNum] = *pciBusInfo[previousBus];
 
703
 
 
704
            speculativeProbe = TRUE;
 
705
        }
 
706
 
 
707
        /*
 
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.
 
711
         */
 
712
#ifdef DEBUGPCI
 
713
        ErrorF("pciGenFindNext: [%d, %d, %d]\n", pciBusNum, pciDevNum, pciFuncNum);
 
714
#endif
 
715
        pciDeviceTag = PCI_MAKE_TAG(pciBusNum, pciDevNum, pciFuncNum);
 
716
        inProbe = TRUE;
 
717
        devid = pciReadLong(pciDeviceTag, 0);
 
718
        inProbe = FALSE;
 
719
#ifdef DEBUGPCI
 
720
        ErrorF("pciGenFindNext: pciDeviceTag = 0x%lx, devid = 0x%lx\n", pciDeviceTag, devid);
 
721
#endif
 
722
        if ((CARD16)(devid + 1U) <= (CARD16)1UL)
 
723
            continue; /* Nobody home.  Next device please */
 
724
 
 
725
        if (pciNumBuses <= pciBusNum)
 
726
            pciNumBuses = pciBusNum + 1;
 
727
 
 
728
        speculativeProbe = FALSE;
 
729
        previousBus = pciBusNum;
 
730
 
 
731
        /*
 
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).
 
735
         */
 
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);
 
746
#ifdef DEBUGPCI
 
747
            ErrorF("pciGenFindNext: pri_bus %d sec_bus %d\n",
 
748
                   pri_bus, sec_bus);
 
749
#endif
 
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))
 
754
                    xf86Msg(X_WARNING,
 
755
                            "pciGenFindNext:  primary bus mismatch on PCI"
 
756
                            " bridge 0x%08x (0x%02x, 0x%02x)\n",
 
757
                            pciDeviceTag, pciBusNum, pri_bus);
 
758
                pri_bus = pciBusNum;
 
759
            }
 
760
            if ((pri_bus < sec_bus) && (sec_bus < pciMaxBusNum) &&
 
761
                pciBusInfo[pri_bus]) {
 
762
                /*
 
763
                 * Found a secondary PCI bus
 
764
                 */
 
765
                if (!pciBusInfo[sec_bus]) {
 
766
                    pciBusInfo[sec_bus] = xnfalloc(sizeof(pciBusInfo_t));
 
767
 
 
768
                    /* Copy parents settings... */
 
769
                    *pciBusInfo[sec_bus] = *pciBusInfo[pri_bus];
 
770
                }
 
771
 
 
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;
 
776
 
 
777
                if (pciNumBuses <= sec_bus)
 
778
                    pciNumBuses = sec_bus + 1;
 
779
            }
 
780
        }
 
781
#endif
 
782
 
 
783
        /*
 
784
         * Does this device match the requested devid after
 
785
         * applying mask?
 
786
         */
 
787
#ifdef DEBUGPCI
 
788
        ErrorF("pciGenFindNext: pciDevidMask = 0x%lx, pciDevid = 0x%lx\n", pciDevidMask, pciDevid);
 
789
#endif
 
790
        if ((devid & pciDevidMask) == pciDevid)
 
791
            /* Yes - Return it.  Otherwise, next device */
 
792
            return(pciDeviceTag); /* got a match */
 
793
 
 
794
    } /* for */
 
795
    /*NOTREACHED*/
 
796
}
 
797
 
 
798
PCITAG
 
799
pciGenFindFirst(void)
 
800
{
 
801
  /* Reset PCI bus number to start from top */
 
802
  pciBusNum = -1;
 
803
 
 
804
  return pciGenFindNext();
 
805
}
 
806
 
 
807
#if defined (__powerpc__)
 
808
static int buserr_detected;
 
809
 
 
810
static
 
811
void buserr(int sig)
 
812
{
 
813
        buserr_detected = 1;
 
814
}
 
815
#endif
 
816
 
 
817
CARD32
 
818
pciCfgMech1Read(PCITAG tag, int offset)
 
819
{
 
820
  unsigned long rv = 0xffffffff;
 
821
#ifdef DEBUGPCI
 
822
  ErrorF("pciCfgMech1Read(tag=%08x,offset=%08x)\n", tag, offset);
 
823
#endif
 
824
 
 
825
#if defined(__powerpc__)
 
826
  signal(SIGBUS, buserr);
 
827
  buserr_detected = 0;
 
828
#endif
 
829
 
 
830
  outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
 
831
  rv = inl(0xCFC);
 
832
 
 
833
#if defined(__powerpc__)
 
834
  signal(SIGBUS, SIG_DFL);
 
835
  if (buserr_detected)
 
836
  {
 
837
#ifdef DEBUGPCI
 
838
    ErrorF("pciCfgMech1Read() BUS ERROR\n");
 
839
#endif
 
840
    return(0xffffffff);
 
841
  }
 
842
  else
 
843
#endif
 
844
    return(rv);
 
845
}
 
846
 
 
847
void
 
848
pciCfgMech1Write(PCITAG tag, int offset, CARD32 val)
 
849
{
 
850
#ifdef DEBUGPCI
 
851
  ErrorF("pciCfgMech1Write(tag=%08x,offset=%08x,val=%08x)\n",
 
852
        tag, offset,val);
 
853
#endif
 
854
 
 
855
#if defined(__powerpc__)
 
856
  signal(SIGBUS, SIG_IGN);
 
857
#endif
 
858
 
 
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 */
 
864
#endif
 
865
  outl(0xCFC, val);
 
866
 
 
867
#if defined(__powerpc__)
 
868
  signal(SIGBUS, SIG_DFL);
 
869
#endif
 
870
}
 
871
 
 
872
void
 
873
pciCfgMech1SetBits(PCITAG tag, int offset, CARD32 mask, CARD32 val)
 
874
{
 
875
    unsigned long rv = 0xffffffff;
 
876
 
 
877
#if defined(__powerpc__)
 
878
    signal(SIGBUS, buserr);
 
879
#endif
 
880
 
 
881
    outl(0xCF8, PCI_EN | tag | (offset & 0xfc));
 
882
    rv = inl(0xCFC);
 
883
    rv = (rv & ~mask) | val;
 
884
    outl(0xCFC, rv);
 
885
 
 
886
#if defined(__powerpc__)
 
887
    signal(SIGBUS, SIG_DFL);
 
888
#endif
 
889
}
 
890
 
 
891
CARD32
 
892
pciByteSwap(CARD32 u)
 
893
{
 
894
#if X_BYTE_ORDER == X_BIG_ENDIAN
 
895
# if defined(__powerpc__) && defined(PowerMAX_OS)
 
896
  CARD32 tmp;
 
897
 
 
898
  __inst_stwbrx(u, &tmp, 0);
 
899
 
 
900
  return(tmp);
 
901
 
 
902
# else /* !PowerMAX_OS */
 
903
 
 
904
  return lswapl(u);
 
905
 
 
906
# endif /* !PowerMAX_OS */
 
907
 
 
908
#else /* !BIG_ENDIAN */
 
909
 
 
910
  return(u);
 
911
 
 
912
#endif
 
913
}
 
914
 
 
915
ADDRESS
 
916
pciAddrNOOP(PCITAG tag, PciAddrType type, ADDRESS addr)
 
917
{
 
918
        return(addr);
 
919
}
 
920
 
 
921
pciConfigPtr *
 
922
xf86scanpci(int flags)
 
923
{
 
924
    pciConfigPtr devp;
 
925
    pciBusInfo_t *busp;
 
926
    int          idx = 0, i;
 
927
    PCITAG       tag;
 
928
 
 
929
    if (pci_devp[0])
 
930
        return pci_devp;
 
931
 
 
932
    pciInit();
 
933
 
 
934
#ifdef XF86SCANPCI_WRAPPER
 
935
    XF86SCANPCI_WRAPPER(SCANPCI_INIT);
 
936
#endif
 
937
 
 
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);
 
943
#endif
 
944
        return NULL;
 
945
    }
 
946
 
 
947
#ifdef DEBUGPCI
 
948
    ErrorF("xf86scanpci: tag = 0x%lx\n", tag);
 
949
#endif
 
950
#ifndef OLD_FORMAT
 
951
    xf86MsgVerb(X_INFO, 2, "PCI: PCI scan (all values are in hex)\n");
 
952
#endif
 
953
 
 
954
    while (idx < MAX_PCI_DEVICES && tag != PCI_NOT_FOUND) {
 
955
        devp = xcalloc(1, sizeof(pciDevice));
 
956
        if (!devp) {
 
957
            xf86Msg(X_ERROR,
 
958
                "xf86scanpci: Out of memory after %d devices!!\n", idx);
 
959
            return (pciConfigPtr *)NULL;
 
960
        }
 
961
 
 
962
        /* Identify pci device by bus, dev, func, and tag */
 
963
        devp->tag = 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);
 
967
 
 
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));
 
971
 
 
972
        switch (devp->pci_header_type & 0x7f) {
 
973
        case 0:
 
974
            /* Get base address sizes for type 0 headers */
 
975
            for (i = 0; i < 7; i++)
 
976
                devp->basesize[i] =
 
977
                    pciGetBaseSize(tag, i, FALSE, &devp->minBasesize);
 
978
            break;
 
979
 
 
980
        case 1:
 
981
        case 2:
 
982
            /* Allow master aborts to complete normally on secondary buses */
 
983
            if (!(devp->pci_bridge_control & PCI_PCI_BRIDGE_MASTER_ABORT_EN))
 
984
                break;
 
985
            pciWriteByte(tag, PCI_PCI_BRIDGE_CONTROL_REG,
 
986
                devp->pci_bridge_control & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN);
 
987
            break;
 
988
 
 
989
        default:
 
990
            break;
 
991
        }
 
992
 
 
993
#ifdef OLD_FORMAT
 
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);
 
999
#else
 
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);
 
1008
#endif
 
1009
 
 
1010
        pci_devp[idx++] = devp;
 
1011
        tag = pciFindNext();
 
1012
 
 
1013
#ifdef DEBUGPCI
 
1014
        ErrorF("xf86scanpci: tag = pciFindNext = 0x%lx\n", tag);
 
1015
#endif
 
1016
    }
 
1017
 
 
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) {
 
1022
        case 0:
 
1023
            if ((devp->pci_base_class != PCI_CLASS_BRIDGE) ||
 
1024
                (devp->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST))
 
1025
                break;
 
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);
 
1030
#endif
 
1031
            break;
 
1032
 
 
1033
        case 1:
 
1034
        case 2:
 
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;
 
1039
                    /*
 
1040
                     * The back link needs to be set here, and is unlikely to
 
1041
                     * change.
 
1042
                     */
 
1043
                    devp->businfo = pciBusInfo[i];
 
1044
                }
 
1045
#ifdef ARCH_PCI_PCI_BRIDGE
 
1046
                ARCH_PCI_PCI_BRIDGE(devp);
 
1047
#endif
 
1048
            }
 
1049
            if (!(devp->pci_bridge_control & PCI_PCI_BRIDGE_MASTER_ABORT_EN))
 
1050
                break;
 
1051
            pciWriteByte(devp->tag, PCI_PCI_BRIDGE_CONTROL_REG,
 
1052
                devp->pci_bridge_control);
 
1053
            break;
 
1054
 
 
1055
        default:
 
1056
            break;
 
1057
        }
 
1058
    }
 
1059
 
 
1060
#ifdef XF86SCANPCI_WRAPPER
 
1061
    XF86SCANPCI_WRAPPER(SCANPCI_TERM);
 
1062
#endif
 
1063
 
 
1064
    /*
 
1065
     * Lastly, link bridges to their secondary bus, after the architecture has
 
1066
     * had a chance to modify these assignments.
 
1067
     */
 
1068
    for (idx = 0;  idx < pciNumBuses;  idx++) {
 
1069
        if (!(busp = pciBusInfo[idx]) || !(devp = busp->bridge))
 
1070
            continue;
 
1071
        devp->businfo = busp;
 
1072
    }
 
1073
 
 
1074
#ifndef OLD_FORMAT
 
1075
    xf86MsgVerb(X_INFO, 2, "PCI: End of PCI scan\n");
 
1076
#endif
 
1077
 
 
1078
    return pci_devp;
 
1079
}
 
1080
 
 
1081
CARD32
 
1082
pciCheckForBrokenBase(PCITAG Tag,int basereg)
 
1083
{
 
1084
    pciWriteLong(Tag, PCI_MAP_REG_START + (basereg << 2), 0xffffffff);
 
1085
    return pciReadLong(Tag, PCI_MAP_REG_START + (basereg << 2));
 
1086
}
 
1087
 
 
1088
#if defined(INCLUDE_XF86_MAP_PCI_MEM)
 
1089
 
 
1090
pointer
 
1091
xf86MapPciMem(int ScreenNum, int Flags, PCITAG Tag, ADDRESS Base,
 
1092
                unsigned long Size)
 
1093
{
 
1094
        ADDRESS hostbase = pciBusAddrToHostAddr(Tag, PCI_MEM,Base);
 
1095
        pointer base;
 
1096
        CARD32 save = 0;
 
1097
 
 
1098
        /*
 
1099
         * If there are possible read side-effects, disable memory while
 
1100
         * doing the mapping.
 
1101
         */
 
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);
 
1106
        }
 
1107
        base = xf86MapDomainMemory(ScreenNum, Flags, Tag, hostbase, Size);
 
1108
        if (!base)      {
 
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));
 
1112
        }
 
1113
        /*
 
1114
         * If read side-effects, do whatever might be needed to prevent
 
1115
         * unintended reads, then restore PCI_CMD_STAT_REG.
 
1116
         */
 
1117
        if (Flags & VIDMEM_READSIDEEFFECT) {
 
1118
                xf86MapReadSideEffects(ScreenNum, Flags, base, Size);
 
1119
                pciWriteLong(Tag, PCI_CMD_STAT_REG, save);
 
1120
        }
 
1121
        return((pointer)base);
 
1122
}
 
1123
 
 
1124
static int
 
1125
handlePciBIOS(PCITAG Tag, int basereg,
 
1126
                int (*func)(PCITAG, CARD8*, ADDRESS, pointer),
 
1127
                pointer args)
 
1128
{
 
1129
    CARD32 romsave = 0;
 
1130
    int i;
 
1131
    romBaseSource b_reg;
 
1132
    ADDRESS hostbase;
 
1133
    CARD8 tmp[64];
 
1134
    int ret = 0;
 
1135
 
 
1136
    romsave = pciReadLong(Tag, PCI_MAP_ROM_REG);
 
1137
 
 
1138
    for (i = ROM_BASE_PRESET; i <= ROM_BASE_FIND; i++) {
 
1139
        memType savebase = 0, newbase, romaddr;
 
1140
 
 
1141
        if (i == ROM_BASE_PRESET) {
 
1142
            /* Does the driver have a preference? */
 
1143
            if (basereg > ROM_BASE_PRESET && basereg <= ROM_BASE_FIND)
 
1144
                b_reg = basereg;
 
1145
            else
 
1146
                b_reg = ++i;
 
1147
        } else
 
1148
            b_reg = i;
 
1149
 
 
1150
        if (!(newbase = getValidBIOSBase(Tag, b_reg)))
 
1151
            continue;  /* no valid address found */
 
1152
 
 
1153
        romaddr = PCIGETROM(newbase);
 
1154
 
 
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),
 
1163
                         (CARD32)~0);
 
1164
        }
 
1165
        /* Set ROM base address and enable ROM address decoding */
 
1166
        pciWriteLong(Tag, PCI_MAP_ROM_REG, romaddr
 
1167
                     | PCI_MAP_ROM_DECODE_ENABLE);
 
1168
 
 
1169
        hostbase = pciBusAddrToHostAddr(Tag, PCI_MEM, PCIGETROM(romaddr));
 
1170
 
 
1171
        if ((xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp) !=
 
1172
             sizeof(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),
 
1176
                                       (CARD32) savebase);
 
1177
 
 
1178
            /* No BIOS found: try another address */
 
1179
            continue;
 
1180
        }
 
1181
 
 
1182
        ret = (*func)(Tag, tmp, hostbase, args);
 
1183
 
 
1184
        /* Restore the base register if it was changed. */
 
1185
        if (savebase) pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2),
 
1186
                                   (CARD32) savebase);
 
1187
        /* Restore ROM address decoding */
 
1188
        pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave);
 
1189
 
 
1190
        return ret;
 
1191
    }
 
1192
    /* Restore ROM address decoding */
 
1193
    pciWriteLong(Tag, PCI_MAP_ROM_REG, romsave);
 
1194
    return 0;
 
1195
}
 
1196
 
 
1197
typedef struct {
 
1198
  unsigned long Offset;
 
1199
  int Len;
 
1200
  unsigned char *Buf;
 
1201
  PciBiosType BiosType;
 
1202
} readBios, *readBiosPtr;
 
1203
 
 
1204
static int
 
1205
readPciBios(PCITAG Tag, CARD8* tmp, ADDRESS hostbase, pointer args)
 
1206
{
 
1207
    unsigned int image_length = 0;
 
1208
    readBiosPtr rd =  args;
 
1209
    int ret;
 
1210
 
 
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];
 
1215
    unsigned char type;
 
1216
 
 
1217
    if ((xf86ReadDomainMemory(Tag, hostbase + data_off, sizeof(data), data)
 
1218
         != sizeof(data)) ||
 
1219
        (data[0] != 'P')  ||
 
1220
        (data[1] != 'C')  ||
 
1221
        (data[2] != 'I')  ||
 
1222
        (data[3] != 'R'))
 
1223
      break;
 
1224
    type = data[0x14];
 
1225
#ifdef PRINT_PCI
 
1226
    ErrorF("data segment in BIOS: 0x%x, type: 0x%x\n", data_off, type);
 
1227
#endif
 
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 */
 
1232
        break;
 
1233
      i_length = (data[0x10] | (data[0x11] << 8)) << 9;
 
1234
#ifdef PRINT_PCI
 
1235
      ErrorF("data image length: 0x%x, ind: 0x%x\n",
 
1236
             image_length, indicator);
 
1237
#endif
 
1238
      hostbase += i_length;
 
1239
      if (xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp)
 
1240
          != sizeof(tmp))
 
1241
        break;
 
1242
      continue;
 
1243
    }
 
1244
    /* OK, we have a PCI BIOS Image of the correct type */
 
1245
 
 
1246
    if (rd->BiosType == PCI_BIOS_PC)
 
1247
      image_length = tmp[2] << 9;
 
1248
    else
 
1249
      image_length = (data[0x10] | (data[0x11] << 8)) << 9;
 
1250
#ifdef PRINT_PCI
 
1251
    ErrorF("BIOS length: 0x%x\n", image_length);
 
1252
#endif
 
1253
    break;
 
1254
  }
 
1255
 
 
1256
  ret = 0;
 
1257
  if (image_length) {
 
1258
 
 
1259
    /*
 
1260
     * if no length is given return the full lenght,
 
1261
     * Offset 0. Beware: Area pointed to by Buf must
 
1262
     * be large enough!
 
1263
     */
 
1264
    if (rd->Len == 0) {
 
1265
      rd->Len = image_length;
 
1266
      rd->Offset = 0;
 
1267
    }
 
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));
 
1271
    } else {
 
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);
 
1275
      }
 
1276
    }
 
1277
 
 
1278
    /* Read BIOS */
 
1279
    ret = xf86ReadDomainMemory(Tag, hostbase + rd->Offset, rd->Len, rd->Buf);
 
1280
  }
 
1281
 
 
1282
  return ret;
 
1283
}
 
1284
 
 
1285
static int
 
1286
getPciBIOSTypes(PCITAG Tag, CARD8* tmp, ADDRESS hostbase, pointer arg)
 
1287
{
 
1288
  int n = 0;
 
1289
  PciBiosType *Buf = arg;
 
1290
 
 
1291
  /* We found a PCI BIOS Image. Now we collect the types type */
 
1292
  do {
 
1293
    unsigned short data_off = tmp[0x18] | (tmp[0x19] << 8);
 
1294
    unsigned char data[16];
 
1295
    unsigned int i_length;
 
1296
 
 
1297
    if ((xf86ReadDomainMemory(Tag, hostbase + data_off, sizeof(data), data)
 
1298
         != sizeof(data)) ||
 
1299
        (data[0] != 'P')  ||
 
1300
        (data[1] != 'C')  ||
 
1301
        (data[2] != 'I')  ||
 
1302
        (data[3] != 'R'))
 
1303
      break;
 
1304
 
 
1305
    if (data[0x14] >= PCI_BIOS_OTHER)
 
1306
        *Buf++ = PCI_BIOS_OTHER;
 
1307
    else
 
1308
        *Buf++ = data[0x14];
 
1309
 
 
1310
      n++;
 
1311
    if (data[0x15] & 0x80)      /* last image */
 
1312
      break;
 
1313
#ifdef PRINT_PCI
 
1314
    ErrorF("data segment in BIOS: 0x%x, type: 0x%x\n", data_off, type);
 
1315
#endif
 
1316
    i_length = (data[0x10] | (data[0x11] << 8)) << 9;
 
1317
#ifdef PRINT_PCI
 
1318
    ErrorF("data image length: 0x%x, ind: 0x%x\n",
 
1319
           image_length, indicator);
 
1320
#endif
 
1321
    hostbase += i_length;
 
1322
    if (xf86ReadDomainMemory(Tag, hostbase, sizeof(tmp), tmp)
 
1323
        != sizeof(tmp))
 
1324
      break;
 
1325
    continue;
 
1326
  }   while ((tmp[0] == 0x55) && (tmp[1] == 0xAA));
 
1327
  return n;
 
1328
}
 
1329
 
 
1330
typedef CARD32 (*ReadProcPtr)(PCITAG, int);
 
1331
typedef void (*WriteProcPtr)(PCITAG, int, CARD32);
 
1332
 
 
1333
static int
 
1334
HandlePciBios(PCITAG Tag, int basereg,
 
1335
                int (*func)(PCITAG, CARD8*, ADDRESS, pointer),
 
1336
                pointer ptr)
 
1337
{
 
1338
  int n, num;
 
1339
  CARD32 Acc1, Acc2;
 
1340
  PCITAG *pTag;
 
1341
  int i;
 
1342
 
 
1343
  n = handlePciBIOS(Tag,basereg,func,ptr);
 
1344
  if (n)
 
1345
      return n;
 
1346
 
 
1347
  num = pciTestMultiDeviceCard(PCI_BUS_FROM_TAG(Tag),
 
1348
                               PCI_DEV_FROM_TAG(Tag),
 
1349
                               PCI_FUNC_FROM_TAG(Tag),&pTag);
 
1350
 
 
1351
  if (!num) return 0;
 
1352
 
 
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));
 
1357
 
 
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));
 
1362
 
 
1363
    n = handlePciBIOS(pTag[i],0,func,ptr);
 
1364
 
 
1365
    ((WriteProcPtr)(pciLongFunc(pTag[i],WRITE)))(pTag[i],PCI_CMD_STAT_REG,Acc2);
 
1366
    if (n)
 
1367
      break;
 
1368
  }
 
1369
  ((WriteProcPtr)(pciLongFunc(Tag,WRITE)))(Tag,PCI_CMD_STAT_REG,Acc1);
 
1370
  return n;
 
1371
}
 
1372
 
 
1373
int
 
1374
xf86ReadPciBIOS(unsigned long Offset, PCITAG Tag, int basereg,
 
1375
                unsigned char *Buf, int Len)
 
1376
{
 
1377
    return xf86ReadPciBIOSByType(Offset, Tag, basereg, Buf, Len, PCI_BIOS_PC);
 
1378
}
 
1379
 
 
1380
int
 
1381
xf86ReadPciBIOSByType(unsigned long Offset, PCITAG Tag, int basereg,
 
1382
                unsigned char *Buf, int Len, PciBiosType Type)
 
1383
{
 
1384
 
 
1385
  readBios rb;
 
1386
  rb.Offset = Offset;
 
1387
  rb.Len = Len;
 
1388
  rb.Buf = Buf;
 
1389
  rb.BiosType = Type;
 
1390
 
 
1391
  return HandlePciBios(Tag, basereg, readPciBios, &rb);
 
1392
}
 
1393
 
 
1394
int
 
1395
xf86GetAvailablePciBIOSTypes(PCITAG Tag, int basereg, PciBiosType *Buf)
 
1396
{
 
1397
  return HandlePciBios(Tag, basereg, getPciBIOSTypes, (pointer) Buf);
 
1398
}
 
1399
 
 
1400
#endif /* INCLUDE_XF86_MAP_PCI_MEM */
 
1401
 
 
1402
#ifdef INCLUDE_XF86_NO_DOMAIN
 
1403
 
 
1404
int
 
1405
xf86GetPciDomain(PCITAG Tag)
 
1406
{
 
1407
    return 0;
 
1408
}
 
1409
 
 
1410
pointer
 
1411
xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag,
 
1412
                    ADDRESS Base, unsigned long Size)
 
1413
{
 
1414
    return xf86MapVidMem(ScreenNum, Flags, Base, Size);
 
1415
}
 
1416
 
 
1417
IOADDRESS
 
1418
xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag,
 
1419
                IOADDRESS Base, unsigned long Size)
 
1420
{
 
1421
    return Base;
 
1422
}
 
1423
 
 
1424
int
 
1425
xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf)
 
1426
{
 
1427
    int ret, length, rlength;
 
1428
 
 
1429
    /* Read in 64kB chunks */
 
1430
    ret = 0;
 
1431
    while ((length = Len) > 0) {
 
1432
        if (length > 0x010000) length = 0x010000;
 
1433
        rlength = xf86ReadBIOS(Base, 0, Buf, length);
 
1434
        if (rlength < 0) {
 
1435
            ret = rlength;
 
1436
            break;
 
1437
        }
 
1438
        ret += rlength;
 
1439
        if (rlength < length) break;
 
1440
        Base += rlength;
 
1441
        Buf += rlength;
 
1442
        Len -= rlength;
 
1443
    }
 
1444
 
 
1445
    return ret;
 
1446
}
 
1447
 
 
1448
#endif /* INCLUDE_XF86_NO_DOMAIN */