2 * Copyright (C) 2001-2003 The XFree86 Project, Inc. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 * Except as contained in this notice, the name of the XFree86 Project shall
22 * not be used in advertising or otherwise to promote the sale, use or other
23 * dealings in this Software without prior written authorization from the
27 #ifdef HAVE_XORG_CONFIG_H
28 #include <xorg-config.h>
33 #include "xf86_OSlib.h"
35 #include "xf86sbusBus.h"
39 extern char *apertureDevName
;
40 static int apertureFd
= -1;
43 * A version of xf86MapVidMem() that allows for 64-bit displacements (but not
44 * sizes). Areas thus mapped can be unmapped by xf86UnMapVidMem().
47 sparcMapAperture(int iScreen
, int Flags
,
48 unsigned long long Base
, unsigned long Size
)
51 static int lastFlags
= 0;
53 /* Assume both Base & Size are multiples of the page size */
55 if ((apertureFd
< 0) || (Flags
!= lastFlags
)) {
59 apertureFd
= open(apertureDevName
,
60 (Flags
& VIDMEM_READONLY
) ? O_RDONLY
: O_RDWR
);
62 FatalError("sparcMapAperture: open failure: %s\n",
66 result
= mmap(NULL
, Size
,
67 (Flags
& VIDMEM_READONLY
) ?
68 PROT_READ
: (PROT_READ
| PROT_WRITE
),
69 MAP_SHARED
, apertureFd
, (off_t
)Base
);
71 if (result
== MAP_FAILED
)
72 FatalError("sparcMapAperture: mmap failure: %s\n", strerror(errno
));
78 * Platform-specific bus privates.
80 typedef struct _sparcDomainRec
{
81 unsigned long long io_addr
, io_size
;
82 unsigned long long mem_addr
, mem_size
;
85 unsigned char dfn_mask
[256 / 8];
86 } sparcDomainRec
, *sparcDomainPtr
;
88 #define SetBitInMap(bit, map) \
91 (map)[_bit >> 3] |= 1 << (_bit & 7); \
94 #define IsBitSetInMap(bit, map) \
95 ((map)[(bit) >> 3] & (1 << ((bit) & 7)))
98 * Domain 0 is reserved for the one that represents the system as a whole, i.e.
99 * the one without any resource relocations.
101 #define MAX_DOMAINS (MAX_PCI_BUSES / 256)
102 static sparcDomainPtr xf86DomainInfo
[MAX_DOMAINS
];
103 static int pciNumDomains
= 1;
105 /* Variables that are assigned this must be declared volatile */
106 #define PciReg(base, tag, off, type) \
107 *(volatile type *)(pointer)((char *)(base) + \
108 (PCI_TAG_NO_DOMAIN(tag) | (off)))
110 /* Generic SPARC PCI access functions */
112 sparcPciCfgRead32(PCITAG tag
, int off
)
114 pciBusInfo_t
*pBusInfo
;
115 sparcDomainPtr pDomain
;
116 volatile CARD32 result
= (CARD32
)(-1); /* Must be volatile */
119 if ((off
>= 0) && (off
<= 252) && !(off
& 3) &&
120 ((bus
= PCI_BUS_FROM_TAG(tag
)) < pciNumBuses
) &&
121 (pBusInfo
= pciBusInfo
[bus
]) && (pDomain
= pBusInfo
->pciBusPriv
) &&
122 (bus
>= pDomain
->bus_min
) && (bus
< pDomain
->bus_max
) &&
123 ((bus
> pDomain
->bus_min
) ||
124 IsBitSetInMap(PCI_DFN_FROM_TAG(tag
), pDomain
->dfn_mask
))) {
125 result
= PciReg(pDomain
->pci
, tag
, off
, CARD32
);
127 result
= PCI_CPU(result
);
134 sparcPciCfgWrite32(PCITAG tag
, int off
, CARD32 val
)
136 pciBusInfo_t
*pBusInfo
;
137 sparcDomainPtr pDomain
;
140 if ((off
< 0) || (off
> 252) || (off
& 3) ||
141 ((bus
= PCI_BUS_FROM_TAG(tag
)) >= pciNumBuses
) ||
142 !(pBusInfo
= pciBusInfo
[bus
]) || !(pDomain
= pBusInfo
->pciBusPriv
) ||
143 (bus
< pDomain
->bus_min
) || (bus
>= pDomain
->bus_max
) ||
144 ((bus
== pDomain
->bus_min
) &&
145 !IsBitSetInMap(PCI_DFN_FROM_TAG(tag
), pDomain
->dfn_mask
)))
149 PciReg(pDomain
->pci
, tag
, off
, CARD32
) = val
;
153 sparcPciCfgSetBits32(PCITAG tag
, int off
, CARD32 mask
, CARD32 bits
)
157 PciVal
= sparcPciCfgRead32(tag
, off
);
160 sparcPciCfgWrite32(tag
, off
, PciVal
);
163 static pciBusFuncs_t sparcPCIFunctions
=
167 sparcPciCfgSetBits32
,
173 * Sabre-specific versions of the above because of its peculiar access size
177 sabrePciCfgRead32(PCITAG tag
, int off
)
179 pciBusInfo_t
*pBusInfo
;
180 sparcDomainPtr pDomain
;
181 volatile CARD32 result
; /* Must be volatile */
184 if (PCI_BDEV_FROM_TAG(tag
))
185 return sparcPciCfgRead32(tag
, off
);
187 if (PCI_FUNC_FROM_TAG(tag
) || (off
< 0) || (off
> 252) || (off
& 3) ||
188 ((bus
= PCI_BUS_FROM_TAG(tag
)) >= pciNumBuses
) ||
189 !(pBusInfo
= pciBusInfo
[bus
]) || !(pDomain
= pBusInfo
->pciBusPriv
) ||
190 (bus
!= pDomain
->bus_min
))
194 result
= (PciReg(pDomain
->pci
, tag
, off
, CARD16
) << 16) |
195 PciReg(pDomain
->pci
, tag
, off
+ 2, CARD16
);
196 return PCI_CPU(result
);
199 result
= (PciReg(pDomain
->pci
, tag
, off
+ 3, CARD8
) << 24) |
200 (PciReg(pDomain
->pci
, tag
, off
+ 2, CARD8
) << 16) |
201 (PciReg(pDomain
->pci
, tag
, off
+ 1, CARD8
) << 8) |
202 (PciReg(pDomain
->pci
, tag
, off
, CARD8
) );
207 sabrePciCfgWrite32(PCITAG tag
, int off
, CARD32 val
)
209 pciBusInfo_t
*pBusInfo
;
210 sparcDomainPtr pDomain
;
213 if (PCI_BDEV_FROM_TAG(tag
))
214 sparcPciCfgWrite32(tag
, off
, val
);
215 else if (!PCI_FUNC_FROM_TAG(tag
) &&
216 (off
>= 0) && (off
<= 252) && !(off
& 3) &&
217 ((bus
= PCI_BUS_FROM_TAG(tag
)) < pciNumBuses
) &&
218 (pBusInfo
= pciBusInfo
[bus
]) &&
219 (pDomain
= pBusInfo
->pciBusPriv
) &&
220 (bus
== pDomain
->bus_min
)) {
223 PciReg(pDomain
->pci
, tag
, off
, CARD16
) = val
>> 16;
224 PciReg(pDomain
->pci
, tag
, off
+ 2, CARD16
) = val
;
226 PciReg(pDomain
->pci
, tag
, off
, CARD8
) = val
;
227 PciReg(pDomain
->pci
, tag
, off
+ 1, CARD8
) = val
>> 8;
228 PciReg(pDomain
->pci
, tag
, off
+ 2, CARD8
) = val
>> 16;
229 PciReg(pDomain
->pci
, tag
, off
+ 3, CARD8
) = val
>> 24;
235 sabrePciCfgSetBits32(PCITAG tag
, int off
, CARD32 mask
, CARD32 bits
)
239 PciVal
= sabrePciCfgRead32(tag
, off
);
242 sabrePciCfgWrite32(tag
, off
, PciVal
);
245 static pciBusFuncs_t sabrePCIFunctions
=
249 sabrePciCfgSetBits32
,
256 /* Scan PROM for all PCI host bridges in the system */
262 if (!xf86LinearVidMem())
265 apertureFd
= open(apertureDevName
, O_RDWR
);
266 if (apertureFd
< 0) {
268 "sparcPciInit: open failure: %s\n", strerror(errno
));
273 pagemask
= xf86getpagesize() - 1;
275 for (node
= promGetChild(promRootNode
);
277 node
= promGetSibling(node
)) {
278 unsigned long long pci_addr
;
279 sparcDomainRec domain
;
280 sparcDomainPtr pDomain
;
281 pciBusFuncs_p pFunctions
;
285 prop_val
= promGetProperty("name", &prop_len
);
286 /* Some PROMs include the trailing null; some don't */
287 if (!prop_val
|| (prop_len
< 3) || (prop_len
> 4) ||
288 strcmp(prop_val
, "pci"))
291 prop_val
= promGetProperty("model", &prop_len
);
292 if (!prop_val
|| (prop_len
<= 0)) {
293 prop_val
= promGetProperty("compatible", &prop_len
);
294 if (!prop_val
|| (prop_len
<= 0))
298 pFunctions
= &sparcPCIFunctions
;
299 (void)memset(&domain
, 0, sizeof(domain
));
301 if (!strncmp("SUNW,sabre", prop_val
, prop_len
) ||
302 !strncmp("pci108e,a000", prop_val
, prop_len
) ||
303 !strncmp("pci108e,a001", prop_val
, prop_len
)) {
305 * There can only be one "Sabre" bridge in a system. It provides
306 * PCI configuration space, a 24-bit I/O space and a 32-bit memory
307 * space, all three of which are at fixed physical CPU addresses.
309 static Bool sabre_seen
= FALSE
;
312 "Sabre or Hummingbird PCI host bridge found (\"%s\")\n",
315 /* There can only be one Sabre */
320 /* Get "bus-range" property */
321 prop_val
= promGetProperty("bus-range", &prop_len
);
322 if (!prop_val
|| (prop_len
!= 8) ||
323 (((unsigned int *)prop_val
)[0]) ||
324 (((unsigned int *)prop_val
)[1] >= 256))
327 pci_addr
= 0x01fe01000000ull
;
328 domain
.io_addr
= 0x01fe02000000ull
;
329 domain
.io_size
= 0x000001000000ull
;
330 domain
.mem_addr
= 0x01ff00000000ull
;
331 domain
.mem_size
= 0x000100000000ull
;
332 domain
.bus_min
= 0; /* Always */
333 domain
.bus_max
= ((int *)prop_val
)[1];
335 pFunctions
= &sabrePCIFunctions
;
337 if (!strncmp("SUNW,psycho", prop_val
, prop_len
) ||
338 !strncmp("pci108e,8000", prop_val
, prop_len
)) {
340 * A "Psycho" host bridge provides two PCI interfaces, each with
341 * its own 16-bit I/O and 31-bit memory spaces. Both share the
342 * same PCI configuration space. Here, they are assigned separate
343 * domain numbers to prevent unintentional I/O and/or memory
344 * resource conflicts.
347 "Psycho PCI host bridge found (\"%s\")\n", prop_val
);
349 /* Get "bus-range" property */
350 prop_val
= promGetProperty("bus-range", &prop_len
);
351 if (!prop_val
|| (prop_len
!= 8) ||
352 (((unsigned int *)prop_val
)[1] >= 256) ||
353 (((unsigned int *)prop_val
)[0] > ((unsigned int *)prop_val
)[1]))
356 domain
.bus_min
= ((int *)prop_val
)[0];
357 domain
.bus_max
= ((int *)prop_val
)[1];
359 /* Get "ranges" property */
360 prop_val
= promGetProperty("ranges", &prop_len
);
361 if (!prop_val
|| (prop_len
!= 112) ||
362 prop_val
[0] || (prop_val
[28] != 0x01u
) ||
363 (prop_val
[56] != 0x02u
) || (prop_val
[84] != 0x03u
) ||
364 (((unsigned int *)prop_val
)[4] != 0x01000000u
) ||
365 ((unsigned int *)prop_val
)[5] ||
366 ((unsigned int *)prop_val
)[12] ||
367 (((unsigned int *)prop_val
)[13] != 0x00010000u
) ||
368 ((unsigned int *)prop_val
)[19] ||
369 (((unsigned int *)prop_val
)[20] != 0x80000000u
) ||
370 ((((unsigned int *)prop_val
)[11] & ~0x00010000u
) !=
372 (((unsigned int *)prop_val
)[18] & ~0x80000000u
) ||
373 (((unsigned int *)prop_val
)[3] !=
374 ((unsigned int *)prop_val
)[10]) ||
375 (((unsigned int *)prop_val
)[17] !=
376 ((unsigned int *)prop_val
)[24]) ||
377 (((unsigned int *)prop_val
)[18] !=
378 ((unsigned int *)prop_val
)[25]) ||
379 (((unsigned int *)prop_val
)[19] !=
380 ((unsigned int *)prop_val
)[26]) ||
381 (((unsigned int *)prop_val
)[20] !=
382 ((unsigned int *)prop_val
)[27]))
385 /* Use memcpy() to avoid alignment issues */
386 (void)memcpy(&pci_addr
, prop_val
+ 12,
388 (void)memcpy(&domain
.io_addr
, prop_val
+ 40,
389 sizeof(domain
.io_addr
));
390 (void)memcpy(&domain
.mem_addr
, prop_val
+ 68,
391 sizeof(domain
.mem_addr
));
393 domain
.io_size
= 0x000000010000ull
;
394 domain
.mem_size
= 0x000080000000ull
;
396 if (!strncmp("SUNW,schizo", prop_val
, prop_len
) ||
397 !strncmp("pci108e,8001", prop_val
, prop_len
)) {
399 * I have no docs on the "Schizo", but judging from the Linux
400 * kernel, it also provides two PCI domains. Each PCI
401 * configuration space is the usual 16M in size, followed by a
402 * variable-length I/O space. Each domain also provides a
403 * variable-length memory space. The kernel seems to think the I/O
404 * spaces are 16M long, and the memory spaces, 2G, but these
405 * assumptions are actually only present in source code comments.
406 * Sun has, however, confirmed to me the validity of these
409 volatile unsigned long long mem_match
, mem_mask
, io_match
, io_mask
;
410 unsigned long Offset
;
414 "Schizo PCI host bridge found (\"%s\")\n", prop_val
);
416 /* Get "bus-range" property */
417 prop_val
= promGetProperty("bus-range", &prop_len
);
418 if (!prop_val
|| (prop_len
!= 8) ||
419 (((unsigned int *)prop_val
)[1] >= 256) ||
420 (((unsigned int *)prop_val
)[0] > ((unsigned int *)prop_val
)[1]))
423 domain
.bus_min
= ((int *)prop_val
)[0];
424 domain
.bus_max
= ((int *)prop_val
)[1];
426 /* Get "reg" property */
427 prop_val
= promGetProperty("reg", &prop_len
);
428 if (!prop_val
|| (prop_len
!= 48))
431 /* Temporarily map some of Schizo's registers */
432 pSchizo
= sparcMapAperture(-1, VIDMEM_MMIO
,
433 ((unsigned long long *)prop_val
)[2] - 0x000000010000ull
,
436 /* Determine where PCI config, I/O and memory spaces reside */
437 if ((((unsigned long long *)prop_val
)[0] & 0x000000700000ull
) ==
443 mem_match
= PciReg(pSchizo
, 0, Offset
, unsigned long long);
444 mem_mask
= PciReg(pSchizo
, 0, Offset
+ 8, unsigned long long);
445 io_match
= PciReg(pSchizo
, 0, Offset
+ 16, unsigned long long);
446 io_mask
= PciReg(pSchizo
, 0, Offset
+ 24, unsigned long long);
448 /* Unmap Schizo registers */
449 xf86UnMapVidMem(-1, pSchizo
, 0x00010000ul
);
451 /* Calculate sizes */
452 mem_mask
= (((mem_mask
- 1) ^ mem_mask
) >> 1) + 1;
453 io_mask
= (((io_mask
- 1) ^ io_mask
) >> 1) + 1;
455 if (io_mask
<= 0x000001000000ull
) /* Nothing left for I/O */
458 domain
.mem_addr
= mem_match
& ~0x8000000000000000ull
;
459 domain
.mem_size
= mem_mask
;
460 pci_addr
= io_match
& ~0x8000000000000000ull
;
461 domain
.io_addr
= pci_addr
+ 0x0000000001000000ull
;
462 domain
.io_size
= io_mask
- 0x0000000001000000ull
;
464 xf86Msg(X_WARNING
, "Unknown PCI host bridge: \"%s\"\n", prop_val
);
468 /* Only map as much PCI configuration as we need */
469 domain
.pci
= (char *)sparcMapAperture(-1, VIDMEM_MMIO
,
470 pci_addr
+ PCI_MAKE_TAG(domain
.bus_min
, 0, 0),
471 PCI_MAKE_TAG(domain
.bus_max
- domain
.bus_min
+ 1, 0, 0)) -
472 PCI_MAKE_TAG(domain
.bus_min
, 0, 0);
474 /* Allocate a domain record */
475 pDomain
= xnfalloc(sizeof(sparcDomainRec
));
479 * Allocate and prime pciBusInfo records. These are allocated one at a
480 * time because those for empty buses are eventually released.
482 bus
= pDomain
->bus_min
=
483 PCI_MAKE_BUS(pciNumDomains
, domain
.bus_min
);
484 pciNumBuses
= pDomain
->bus_max
=
485 PCI_MAKE_BUS(pciNumDomains
, domain
.bus_max
) + 1;
487 pciBusInfo
[bus
] = xnfcalloc(1, sizeof(pciBusInfo_t
));
488 pciBusInfo
[bus
]->configMech
= PCI_CFG_MECH_OTHER
;
489 pciBusInfo
[bus
]->numDevices
= 32;
490 pciBusInfo
[bus
]->funcs
= pFunctions
;
491 pciBusInfo
[bus
]->pciBusPriv
= pDomain
;
492 while (++bus
< pciNumBuses
) {
493 pciBusInfo
[bus
] = xnfalloc(sizeof(pciBusInfo_t
));
494 *(pciBusInfo
[bus
]) = *(pciBusInfo
[bus
- 1]);
495 pciBusInfo
[bus
]->funcs
= &sparcPCIFunctions
;
498 /* Next domain, please... */
499 xf86DomainInfo
[pciNumDomains
++] = pDomain
;
502 * OK, enough of the straight-forward stuff. Time to deal with some
505 * The PCI specs require that when a bus transaction remains unclaimed
506 * for too long, the master entity on that bus is to cancel the
507 * transaction it issued or passed on with a master abort. Two
508 * outcomes are possible:
510 * - the master abort can be treated as an error that is propogated
511 * back through the bus tree to the entity that ultimately originated
512 * the transaction; or
513 * - the transaction can be allowed to complete normally, which means
514 * that writes are ignored and reads return all ones.
516 * In the first case, if the CPU happens to be at the tail end of the
517 * tree path through one of its host bridges, it will be told there is
518 * a hardware mal-function, despite being generated by software.
520 * For a software function (be it firmware, OS or userland application)
521 * to determine how a PCI bus tree is populated, it must be able to
522 * detect when master aborts occur. Obviously, PCI discovery is much
523 * simpler when master aborts are allowed to complete normally.
525 * Unfortunately, a number of non-Intel PCI implementations have chosen
526 * to treat master aborts as severe errors. The net effect is to
527 * cripple PCI discovery algorithms in userland.
529 * On SPARCs, master aborts cause a number of different behaviours,
530 * including delivering a signal to the userland application, rebooting
531 * the system, "dropping down" to firmware, or, worst of all, bus
532 * lockouts. Even in the first case, the SIGBUS signal that is
533 * eventually generated isn't delivered in a timely enough fashion to
534 * allow an application to reliably detect the master abort that
535 * ultimately caused it.
537 * This can be somewhat mitigated. On all architectures, master aborts
538 * that occur on secondary buses can be forced to complete normally
539 * because the PCI-to-PCI bridges that serve them are governed by an
540 * industry-wide specification. (This is just another way of saying
541 * that whatever justification there might be for erroring out master
542 * aborts is deemed by the industry as insufficient to generate more
543 * PCI non-compliance than there already is...)
545 * This leaves us with master aborts that occur on primary buses.
546 * There is no specification for host-to-PCI bridges. Bridges used in
547 * SPARCs can be told to ignore all PCI errors, but not specifically
548 * master aborts. Not only is this too coarse-grained, but
549 * master-aborted read transactions on the primary bus end up returning
550 * garbage rather than all ones.
552 * I have elected to work around this the only way I can think of doing
553 * so right now. The following scans an additional PROM level and
554 * builds a device/function map for the primary bus. I can only hope
555 * this PROM information represents all devices on the primary bus,
556 * rather than only a subset of them.
558 * Master aborts are useful in other ways too, that are not addressed
559 * here. These include determining whether or not a domain provides
560 * VGA, or if a PCI device actually implements PCI disablement.
562 * --- TSI @ UQV 2001.09.19
564 for (node2
= promGetChild(node
);
566 node2
= promGetSibling(node2
)) {
567 /* Get "reg" property */
568 prop_val
= promGetProperty("reg", &prop_len
);
569 if (!prop_val
|| (prop_len
% 20))
573 * It's unnecessary to scan the entire "reg" property, but I'll do
577 for (; prop_len
--; prop_val
+= 20)
578 SetBitInMap(PCI_DFN_FROM_TAG(*(PCITAG
*)prop_val
),
582 /* Assume the host bridge is device 0, function 0 on its bus */
583 SetBitInMap(0, pDomain
->dfn_mask
);
592 #ifndef INCLUDE_XF86_NO_DOMAIN
595 xf86GetPciDomain(PCITAG Tag
)
597 return PCI_DOM_FROM_TAG(Tag
);
601 xf86MapDomainMemory(int ScreenNum
, int Flags
, PCITAG Tag
,
602 ADDRESS Base
, unsigned long Size
)
604 sparcDomainPtr pDomain
;
606 int domain
= PCI_DOM_FROM_TAG(Tag
);
608 if ((domain
<= 0) || (domain
>= pciNumDomains
) ||
609 !(pDomain
= xf86DomainInfo
[domain
]) ||
610 (((unsigned long long)Base
+ (unsigned long long)Size
) >
612 FatalError("xf86MapDomainMemory() called with invalid parameters.\n");
614 result
= sparcMapAperture(ScreenNum
, Flags
, pDomain
->mem_addr
+ Base
, Size
);
616 if (apertureFd
>= 0) {
625 xf86MapDomainIO(int ScreenNum
, int Flags
, PCITAG Tag
,
626 IOADDRESS Base
, unsigned long Size
)
628 sparcDomainPtr pDomain
;
629 int domain
= PCI_DOM_FROM_TAG(Tag
);
631 if ((domain
<= 0) || (domain
>= pciNumDomains
) ||
632 !(pDomain
= xf86DomainInfo
[domain
]) ||
633 (((unsigned long long)Base
+ (unsigned long long)Size
) >
635 FatalError("xf86MapDomainIO() called with invalid parameters.\n");
637 /* Permanently map all of I/O space */
639 pDomain
->io
= sparcMapAperture(ScreenNum
, Flags
,
640 pDomain
->io_addr
, pDomain
->io_size
);
642 if (apertureFd
>= 0) {
648 return (IOADDRESS
)pDomain
->io
+ Base
;
652 xf86ReadDomainMemory(PCITAG Tag
, ADDRESS Base
, int Len
, unsigned char *Buf
)
654 unsigned char *ptr
, *src
;
659 /* Ensure page boundaries */
660 offset
= Base
& ~pagemask
;
661 size
= ((Base
+ Len
+ pagemask
) & ~pagemask
) - offset
;
663 ptr
= xf86MapDomainMemory(-1, VIDMEM_READONLY
, Tag
, offset
, size
);
665 /* Using memcpy() here hangs the system */
666 src
= ptr
+ (Base
- offset
);
667 for (len
= Len
; len
-- > 0;)
670 xf86UnMapVidMem(-1, ptr
, size
);
676 xf86BusAccWindowsFromOS(void)
678 sparcDomainPtr pDomain
;
683 for (domain
= 1; domain
< pciNumDomains
; domain
++) {
684 if (!(pDomain
= xf86DomainInfo
[domain
]))
687 RANGE(range
, 0, pDomain
->mem_size
- 1,
688 RANGE_TYPE(ResExcMemBlock
, domain
));
689 pRes
= xf86AddResToList(pRes
, &range
, -1);
691 RANGE(range
, 0, pDomain
->io_size
- 1,
692 RANGE_TYPE(ResExcIoBlock
, domain
));
693 pRes
= xf86AddResToList(pRes
, &range
, -1);
700 xf86PciBusAccWindowsFromOS(void)
702 sparcDomainPtr pDomain
;
707 for (domain
= 1; domain
< pciNumDomains
; domain
++) {
708 if (!(pDomain
= xf86DomainInfo
[domain
]))
711 RANGE(range
, 0, pDomain
->mem_size
- 1,
712 RANGE_TYPE(ResExcMemBlock
, domain
));
713 pRes
= xf86AddResToList(pRes
, &range
, -1);
715 RANGE(range
, 0, pDomain
->io_size
- 1,
716 RANGE_TYPE(ResExcIoBlock
, domain
));
717 pRes
= xf86AddResToList(pRes
, &range
, -1);
724 xf86AccResFromOS(resPtr pRes
)
726 sparcDomainPtr pDomain
;
730 for (domain
= 1; domain
< pciNumDomains
; domain
++) {
731 if (!(pDomain
= xf86DomainInfo
[domain
]))
735 * At minimum, the top and bottom resources must be claimed, so that
736 * resources that are (or appear to be) unallocated can be relocated.
738 RANGE(range
, 0x00000000u
, 0x0009ffffu
,
739 RANGE_TYPE(ResExcMemBlock
, domain
));
740 pRes
= xf86AddResToList(pRes
, &range
, -1);
741 RANGE(range
, 0x000c0000u
, 0x000effffu
,
742 RANGE_TYPE(ResExcMemBlock
, domain
));
743 pRes
= xf86AddResToList(pRes
, &range
, -1);
744 RANGE(range
, 0x000f0000u
, 0x000fffffu
,
745 RANGE_TYPE(ResExcMemBlock
, domain
));
746 pRes
= xf86AddResToList(pRes
, &range
, -1);
748 RANGE(range
, pDomain
->mem_size
- 1, pDomain
->mem_size
- 1,
749 RANGE_TYPE(ResExcMemBlock
, domain
));
750 pRes
= xf86AddResToList(pRes
, &range
, -1);
752 RANGE(range
, 0x00000000u
, 0x00000000u
,
753 RANGE_TYPE(ResExcIoBlock
, domain
));
754 pRes
= xf86AddResToList(pRes
, &range
, -1);
755 RANGE(range
, pDomain
->io_size
- 1, pDomain
->io_size
- 1,
756 RANGE_TYPE(ResExcIoBlock
, domain
));
757 pRes
= xf86AddResToList(pRes
, &range
, -1);
763 #endif /* !INCLUDE_XF86_NO_DOMAIN */
765 #endif /* defined(sun) */
767 #if defined(ARCH_PCI_PCI_BRIDGE)
769 /* Definitions specific to Sun's APB P2P bridge (a.k.a. Simba) */
770 #define APB_IO_ADDRESS_MAP 0xDE
771 #define APB_MEM_ADDRESS_MAP 0xDF
774 * Simba's can only occur on bus 0. Furthermore, Simba's must have a non-zero
775 * device/function number because the Sabre interface they must connect to
776 * occupies the 0:0:0 slot. Also, there can be only one Sabre interface in the
777 * system, and therefore, only one Simba function can route any particular
778 * resource. Thus, it is appropriate to use a single set of static variables
779 * to hold the tag of the Simba function routing a VGA resource range at any
780 * one time, and to test these variables for non-zero to determine whether or
781 * not the Sabre would master-abort a VGA access (and kill the system).
783 * The trick is to determine when it is safe to re-route VGA, because doing so
784 * re-routes much more.
786 static PCITAG simbavgaIOTag
= 0, simbavgaMemTag
= 0;
787 static Bool simbavgaRoutingAllow
= TRUE
;
790 * Scan the bus subtree rooted at 'bus' for a non-display device that might be
791 * decoding the bottom 2 MB of I/O space and/or the bottom 512 MB of memory
792 * space. Reset simbavgaRoutingAllow if such a device is found.
794 * XXX For now, this is very conservative and should be made less so as the
798 simbaCheckBus(CARD16 pcicommand
, int bus
)
800 pciConfigPtr pPCI
, *ppPCI
= xf86scanpci(0);
802 while ((pPCI
= *ppPCI
++)) {
803 if (pPCI
->busnum
< bus
)
805 if (pPCI
->busnum
> bus
)
808 /* XXX Assume all devices respect PCI disablement */
809 if (!(pcicommand
& pPCI
->pci_command
))
812 /* XXX This doesn't deal with mis-advertised classes */
813 switch (pPCI
->pci_base_class
) {
814 case PCI_CLASS_PREHISTORIC
:
815 if (pPCI
->pci_sub_class
== PCI_SUBCLASS_PREHISTORIC_VGA
)
816 continue; /* Ignore VGA */
819 case PCI_CLASS_DISPLAY
:
822 case PCI_CLASS_BRIDGE
:
823 switch (pPCI
->pci_sub_class
) {
824 case PCI_SUBCLASS_BRIDGE_PCI
:
825 case PCI_SUBCLASS_BRIDGE_CARDBUS
:
826 /* Scan secondary bus */
827 /* XXX First check bridge routing? */
828 simbaCheckBus(pcicommand
& pPCI
->pci_command
,
829 PCI_SECONDARY_BUS_EXTRACT(pPCI
->pci_pp_bus_register
,
831 if (!simbavgaRoutingAllow
)
843 * XXX We could check the device's bases here, but PCI doesn't limit
844 * the device's decoding to them.
847 simbavgaRoutingAllow
= FALSE
;
853 simbaVerifyBus(int bus
)
856 if ((bus
< 0) || (bus
>= pciNumBuses
) ||
857 !pciBusInfo
[bus
] || !(pPCI
= pciBusInfo
[bus
]->bridge
) ||
858 (pPCI
->pci_device_vendor
!= DEVID(VENDOR_SUN
, CHIP_SIMBA
)))
865 simbaControlBridge(int bus
, CARD16 mask
, CARD16 value
)
868 CARD16 current
= 0, tmp
;
871 if ((pPCI
= simbaVerifyBus(bus
))) {
873 * The Simba does not implement VGA enablement as described in the P2P
874 * spec. It does however route I/O and memory in large enough chunks
875 * so that we can determine were VGA resources would be routed
876 * (including ISA VGA I/O aliases). We can allow changes to that
877 * routing only under certain circumstances.
879 iomap
= pciReadByte(pPCI
->tag
, APB_IO_ADDRESS_MAP
);
880 memmap
= pciReadByte(pPCI
->tag
, APB_MEM_ADDRESS_MAP
);
881 if (iomap
& memmap
& 0x01) {
882 current
|= PCI_PCI_BRIDGE_VGA_EN
;
883 if ((mask
& PCI_PCI_BRIDGE_VGA_EN
) &&
884 !(value
& PCI_PCI_BRIDGE_VGA_EN
)) {
885 if (!simbavgaRoutingAllow
) {
886 xf86MsgVerb(X_WARNING
, 3, "Attempt to disable VGA routing"
887 " through Simba at %x:%x:%x disallowed.\n",
888 pPCI
->busnum
, pPCI
->devnum
, pPCI
->funcnum
);
889 value
|= PCI_PCI_BRIDGE_VGA_EN
;
891 pciWriteByte(pPCI
->tag
, APB_IO_ADDRESS_MAP
,
893 pciWriteByte(pPCI
->tag
, APB_MEM_ADDRESS_MAP
,
895 simbavgaIOTag
= simbavgaMemTag
= 0;
899 if (mask
& value
& PCI_PCI_BRIDGE_VGA_EN
) {
900 if (!simbavgaRoutingAllow
) {
901 xf86MsgVerb(X_WARNING
, 3, "Attempt to enable VGA routing"
902 " through Simba at %x:%x:%x disallowed.\n",
903 pPCI
->busnum
, pPCI
->devnum
, pPCI
->funcnum
);
904 value
&= ~PCI_PCI_BRIDGE_VGA_EN
;
906 if (pPCI
->tag
!= simbavgaIOTag
) {
908 tmp
= pciReadByte(simbavgaIOTag
,
910 pciWriteByte(simbavgaIOTag
, APB_IO_ADDRESS_MAP
,
914 pciWriteByte(pPCI
->tag
, APB_IO_ADDRESS_MAP
,
916 simbavgaIOTag
= pPCI
->tag
;
919 if (pPCI
->tag
!= simbavgaMemTag
) {
920 if (simbavgaMemTag
) {
921 tmp
= pciReadByte(simbavgaMemTag
,
922 APB_MEM_ADDRESS_MAP
);
923 pciWriteByte(simbavgaMemTag
, APB_MEM_ADDRESS_MAP
,
927 pciWriteByte(pPCI
->tag
, APB_MEM_ADDRESS_MAP
,
929 simbavgaMemTag
= pPCI
->tag
;
935 /* Move on to master abort failure enablement (as per P2P spec) */
936 tmp
= pciReadWord(pPCI
->tag
, PCI_PCI_BRIDGE_CONTROL_REG
);
938 if (tmp
& PCI_PCI_BRIDGE_MASTER_ABORT_EN
) {
939 if ((mask
& PCI_PCI_BRIDGE_MASTER_ABORT_EN
) &&
940 !(value
& PCI_PCI_BRIDGE_MASTER_ABORT_EN
))
941 pciWriteWord(pPCI
->tag
, PCI_PCI_BRIDGE_CONTROL_REG
,
942 tmp
& ~PCI_PCI_BRIDGE_MASTER_ABORT_EN
);
944 if (mask
& value
& PCI_PCI_BRIDGE_MASTER_ABORT_EN
)
945 pciWriteWord(pPCI
->tag
, PCI_PCI_BRIDGE_CONTROL_REG
,
946 tmp
| PCI_PCI_BRIDGE_MASTER_ABORT_EN
);
949 /* Insert emulation of other P2P controls here */
952 return (current
& ~mask
) | (value
& mask
);
956 simbaGetBridgeResources(int bus
,
961 pciConfigPtr pPCI
= simbaVerifyBus(bus
);
969 xf86FreeResList(*ppIoRes
);
972 if (pPCI
->pci_command
& PCI_CMD_IO_ENABLE
) {
973 unsigned char iomap
= pciReadByte(pPCI
->tag
, APB_IO_ADDRESS_MAP
);
974 if (simbavgaRoutingAllow
)
976 for (i
= 0; i
< 8; i
++) {
977 if (iomap
& (1 << i
)) {
978 RANGE(range
, i
<< 21, ((i
+ 1) << 21) - 1,
979 RANGE_TYPE(ResExcIoBlock
,
980 xf86GetPciDomain(pPCI
->tag
)));
981 *ppIoRes
= xf86AddResToList(*ppIoRes
, &range
, -1);
988 xf86FreeResList(*ppMemRes
);
991 if (pPCI
->pci_command
& PCI_CMD_MEM_ENABLE
) {
992 unsigned char memmap
= pciReadByte(pPCI
->tag
, APB_MEM_ADDRESS_MAP
);
993 if (simbavgaRoutingAllow
)
995 for (i
= 0; i
< 8; i
++) {
996 if (memmap
& (1 << i
)) {
997 RANGE(range
, i
<< 29, ((i
+ 1) << 29) - 1,
998 RANGE_TYPE(ResExcMemBlock
,
999 xf86GetPciDomain(pPCI
->tag
)));
1000 *ppMemRes
= xf86AddResToList(*ppMemRes
, &range
, -1);
1007 xf86FreeResList(*ppPmemRes
);
1012 void ARCH_PCI_PCI_BRIDGE(pciConfigPtr pPCI
)
1014 static pciBusFuncs_t simbaBusFuncs
;
1015 pciBusInfo_t
*pBusInfo
;
1018 if (pPCI
->pci_device_vendor
!= DEVID(VENDOR_SUN
, CHIP_SIMBA
))
1021 pBusInfo
= pPCI
->businfo
;
1023 simbaBusFuncs
= *(pBusInfo
->funcs
);
1024 simbaBusFuncs
.pciControlBridge
= simbaControlBridge
;
1025 simbaBusFuncs
.pciGetBridgeResources
= simbaGetBridgeResources
;
1027 pBusInfo
->funcs
= &simbaBusFuncs
;
1029 if (!simbavgaRoutingAllow
)
1034 if (pciReadByte(pPCI
->tag
, APB_IO_ADDRESS_MAP
) & 0x01) {
1035 pcicommand
|= PCI_CMD_IO_ENABLE
;
1036 simbavgaIOTag
= pPCI
->tag
;
1039 if (pciReadByte(pPCI
->tag
, APB_MEM_ADDRESS_MAP
) & 0x01) {
1040 pcicommand
|= PCI_CMD_MEM_ENABLE
;
1041 simbavgaMemTag
= pPCI
->tag
;
1047 simbaCheckBus(pcicommand
,
1048 PCI_SECONDARY_BUS_EXTRACT(pPCI
->pci_pp_bus_register
, pPCI
->tag
));
1051 #endif /* defined(ARCH_PCI_PCI_BRIDGE) */