First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / os-support / bus / sparcPci.c
blob5dd6b93692064b1a4c3f49f828983696974d2cfb
1 /*
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
24 * XFree86 Project.
27 #ifdef HAVE_XORG_CONFIG_H
28 #include <xorg-config.h>
29 #endif
31 #include "xf86.h"
32 #include "xf86Priv.h"
33 #include "xf86_OSlib.h"
34 #include "Pci.h"
35 #include "xf86sbusBus.h"
37 #if defined(sun)
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().
46 static pointer
47 sparcMapAperture(int iScreen, int Flags,
48 unsigned long long Base, unsigned long Size)
50 pointer result;
51 static int lastFlags = 0;
53 /* Assume both Base & Size are multiples of the page size */
55 if ((apertureFd < 0) || (Flags != lastFlags)) {
56 if (apertureFd >= 0)
57 close(apertureFd);
58 lastFlags = Flags;
59 apertureFd = open(apertureDevName,
60 (Flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR);
61 if (apertureFd < 0)
62 FatalError("sparcMapAperture: open failure: %s\n",
63 strerror(errno));
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));
74 return result;
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;
83 pointer pci, io;
84 int bus_min, bus_max;
85 unsigned char dfn_mask[256 / 8];
86 } sparcDomainRec, *sparcDomainPtr;
88 #define SetBitInMap(bit, map) \
89 do { \
90 int _bit = (bit); \
91 (map)[_bit >> 3] |= 1 << (_bit & 7); \
92 } while (0)
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 */
111 static CARD32
112 sparcPciCfgRead32(PCITAG tag, int off)
114 pciBusInfo_t *pBusInfo;
115 sparcDomainPtr pDomain;
116 volatile CARD32 result = (CARD32)(-1); /* Must be volatile */
117 int bus;
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);
130 return result;
133 static void
134 sparcPciCfgWrite32(PCITAG tag, int off, CARD32 val)
136 pciBusInfo_t *pBusInfo;
137 sparcDomainPtr pDomain;
138 int bus;
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)))
146 return;
148 val = PCI_CPU(val);
149 PciReg(pDomain->pci, tag, off, CARD32) = val;
152 static void
153 sparcPciCfgSetBits32(PCITAG tag, int off, CARD32 mask, CARD32 bits)
155 CARD32 PciVal;
157 PciVal = sparcPciCfgRead32(tag, off);
158 PciVal &= ~mask;
159 PciVal |= bits;
160 sparcPciCfgWrite32(tag, off, PciVal);
163 static pciBusFuncs_t sparcPCIFunctions =
165 sparcPciCfgRead32,
166 sparcPciCfgWrite32,
167 sparcPciCfgSetBits32,
168 pciAddrNOOP,
169 pciAddrNOOP
173 * Sabre-specific versions of the above because of its peculiar access size
174 * requirements.
176 static CARD32
177 sabrePciCfgRead32(PCITAG tag, int off)
179 pciBusInfo_t *pBusInfo;
180 sparcDomainPtr pDomain;
181 volatile CARD32 result; /* Must be volatile */
182 int bus;
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))
191 return (CARD32)(-1);
193 if (off < 8) {
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) );
203 return result;
206 static void
207 sabrePciCfgWrite32(PCITAG tag, int off, CARD32 val)
209 pciBusInfo_t *pBusInfo;
210 sparcDomainPtr pDomain;
211 int bus;
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)) {
221 if (off < 8) {
222 val = PCI_CPU(val);
223 PciReg(pDomain->pci, tag, off , CARD16) = val >> 16;
224 PciReg(pDomain->pci, tag, off + 2, CARD16) = val;
225 } else {
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;
234 static void
235 sabrePciCfgSetBits32(PCITAG tag, int off, CARD32 mask, CARD32 bits)
237 CARD32 PciVal;
239 PciVal = sabrePciCfgRead32(tag, off);
240 PciVal &= ~mask;
241 PciVal |= bits;
242 sabrePciCfgWrite32(tag, off, PciVal);
245 static pciBusFuncs_t sabrePCIFunctions =
247 sabrePciCfgRead32,
248 sabrePciCfgWrite32,
249 sabrePciCfgSetBits32,
250 pciAddrNOOP,
251 pciAddrNOOP
254 static int pagemask;
256 /* Scan PROM for all PCI host bridges in the system */
257 void
258 sparcPciInit(void)
260 int node, node2;
262 if (!xf86LinearVidMem())
263 return;
265 apertureFd = open(apertureDevName, O_RDWR);
266 if (apertureFd < 0) {
267 xf86Msg(X_ERROR,
268 "sparcPciInit: open failure: %s\n", strerror(errno));
269 return;
272 sparcPromInit();
273 pagemask = xf86getpagesize() - 1;
275 for (node = promGetChild(promRootNode);
276 node;
277 node = promGetSibling(node)) {
278 unsigned long long pci_addr;
279 sparcDomainRec domain;
280 sparcDomainPtr pDomain;
281 pciBusFuncs_p pFunctions;
282 char *prop_val;
283 int prop_len, bus;
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"))
289 continue;
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))
295 continue;
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;
311 xf86Msg(X_INFO,
312 "Sabre or Hummingbird PCI host bridge found (\"%s\")\n",
313 prop_val);
315 /* There can only be one Sabre */
316 if (sabre_seen)
317 continue;
318 sabre_seen = TRUE;
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))
325 continue;
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;
336 } else
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.
346 xf86Msg(X_INFO,
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]))
354 continue;
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) !=
371 0x02000000u) ||
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]))
383 continue;
385 /* Use memcpy() to avoid alignment issues */
386 (void)memcpy(&pci_addr, prop_val + 12,
387 sizeof(pci_addr));
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;
395 } else
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
407 * assumptions.
409 volatile unsigned long long mem_match, mem_mask, io_match, io_mask;
410 unsigned long Offset;
411 pointer pSchizo;
413 xf86Msg(X_INFO,
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]))
421 continue;
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))
429 continue;
431 /* Temporarily map some of Schizo's registers */
432 pSchizo = sparcMapAperture(-1, VIDMEM_MMIO,
433 ((unsigned long long *)prop_val)[2] - 0x000000010000ull,
434 0x00010000ul);
436 /* Determine where PCI config, I/O and memory spaces reside */
437 if ((((unsigned long long *)prop_val)[0] & 0x000000700000ull) ==
438 0x000000600000ull)
439 Offset = 0x0040;
440 else
441 Offset = 0x0060;
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 */
456 continue;
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;
463 } else {
464 xf86Msg(X_WARNING, "Unknown PCI host bridge: \"%s\"\n", prop_val);
465 continue;
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));
476 *pDomain = domain;
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
503 * brokenness...
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);
565 node2;
566 node2 = promGetSibling(node2)) {
567 /* Get "reg" property */
568 prop_val = promGetProperty("reg", &prop_len);
569 if (!prop_val || (prop_len % 20))
570 continue;
573 * It's unnecessary to scan the entire "reg" property, but I'll do
574 * so anyway.
576 prop_len /= 20;
577 for (; prop_len--; prop_val += 20)
578 SetBitInMap(PCI_DFN_FROM_TAG(*(PCITAG *)prop_val),
579 pDomain->dfn_mask);
582 /* Assume the host bridge is device 0, function 0 on its bus */
583 SetBitInMap(0, pDomain->dfn_mask);
586 sparcPromClose();
588 close(apertureFd);
589 apertureFd = -1;
592 #ifndef INCLUDE_XF86_NO_DOMAIN
594 _X_EXPORT int
595 xf86GetPciDomain(PCITAG Tag)
597 return PCI_DOM_FROM_TAG(Tag);
600 _X_EXPORT pointer
601 xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag,
602 ADDRESS Base, unsigned long Size)
604 sparcDomainPtr pDomain;
605 pointer result;
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) >
611 pDomain->mem_size))
612 FatalError("xf86MapDomainMemory() called with invalid parameters.\n");
614 result = sparcMapAperture(ScreenNum, Flags, pDomain->mem_addr + Base, Size);
616 if (apertureFd >= 0) {
617 close(apertureFd);
618 apertureFd = -1;
621 return result;
624 _X_EXPORT IOADDRESS
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) >
634 pDomain->io_size))
635 FatalError("xf86MapDomainIO() called with invalid parameters.\n");
637 /* Permanently map all of I/O space */
638 if (!pDomain->io) {
639 pDomain->io = sparcMapAperture(ScreenNum, Flags,
640 pDomain->io_addr, pDomain->io_size);
642 if (apertureFd >= 0) {
643 close(apertureFd);
644 apertureFd = -1;
648 return (IOADDRESS)pDomain->io + Base;
651 _X_EXPORT int
652 xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf)
654 unsigned char *ptr, *src;
655 ADDRESS offset;
656 unsigned long size;
657 int len;
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;)
668 *Buf++ = *src++;
670 xf86UnMapVidMem(-1, ptr, size);
672 return Len;
675 resPtr
676 xf86BusAccWindowsFromOS(void)
678 sparcDomainPtr pDomain;
679 resPtr pRes = NULL;
680 resRange range;
681 int domain;
683 for (domain = 1; domain < pciNumDomains; domain++) {
684 if (!(pDomain = xf86DomainInfo[domain]))
685 continue;
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);
696 return pRes;
699 resPtr
700 xf86PciBusAccWindowsFromOS(void)
702 sparcDomainPtr pDomain;
703 resPtr pRes = NULL;
704 resRange range;
705 int domain;
707 for (domain = 1; domain < pciNumDomains; domain++) {
708 if (!(pDomain = xf86DomainInfo[domain]))
709 continue;
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);
720 return pRes;
723 resPtr
724 xf86AccResFromOS(resPtr pRes)
726 sparcDomainPtr pDomain;
727 resRange range;
728 int domain;
730 for (domain = 1; domain < pciNumDomains; domain++) {
731 if (!(pDomain = xf86DomainInfo[domain]))
732 continue;
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);
760 return pRes;
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
795 * need arises.
797 static void
798 simbaCheckBus(CARD16 pcicommand, int bus)
800 pciConfigPtr pPCI, *ppPCI = xf86scanpci(0);
802 while ((pPCI = *ppPCI++)) {
803 if (pPCI->busnum < bus)
804 continue;
805 if (pPCI->busnum > bus)
806 break;
808 /* XXX Assume all devices respect PCI disablement */
809 if (!(pcicommand & pPCI->pci_command))
810 continue;
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 */
817 break;
819 case PCI_CLASS_DISPLAY:
820 continue;
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,
830 pPCI->tag));
831 if (!simbavgaRoutingAllow)
832 return;
834 default:
835 break;
838 default:
839 break;
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;
848 break;
852 static pciConfigPtr
853 simbaVerifyBus(int bus)
855 pciConfigPtr pPCI;
856 if ((bus < 0) || (bus >= pciNumBuses) ||
857 !pciBusInfo[bus] || !(pPCI = pciBusInfo[bus]->bridge) ||
858 (pPCI->pci_device_vendor != DEVID(VENDOR_SUN, CHIP_SIMBA)))
859 return NULL;
861 return pPCI;
864 static CARD16
865 simbaControlBridge(int bus, CARD16 mask, CARD16 value)
867 pciConfigPtr pPCI;
868 CARD16 current = 0, tmp;
869 CARD8 iomap, memmap;
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;
890 } else {
891 pciWriteByte(pPCI->tag, APB_IO_ADDRESS_MAP,
892 iomap & ~0x01);
893 pciWriteByte(pPCI->tag, APB_MEM_ADDRESS_MAP,
894 memmap & ~0x01);
895 simbavgaIOTag = simbavgaMemTag = 0;
898 } else {
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;
905 } else {
906 if (pPCI->tag != simbavgaIOTag) {
907 if (simbavgaIOTag) {
908 tmp = pciReadByte(simbavgaIOTag,
909 APB_IO_ADDRESS_MAP);
910 pciWriteByte(simbavgaIOTag, APB_IO_ADDRESS_MAP,
911 tmp & ~0x01);
914 pciWriteByte(pPCI->tag, APB_IO_ADDRESS_MAP,
915 iomap | 0x01);
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,
924 tmp & ~0x01);
927 pciWriteByte(pPCI->tag, APB_MEM_ADDRESS_MAP,
928 memmap | 0x01);
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);
937 current |= tmp;
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);
943 } else {
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);
955 static void
956 simbaGetBridgeResources(int bus,
957 pointer *ppIoRes,
958 pointer *ppMemRes,
959 pointer *ppPmemRes)
961 pciConfigPtr pPCI = simbaVerifyBus(bus);
962 resRange range;
963 int i;
965 if (!pPCI)
966 return;
968 if (ppIoRes) {
969 xf86FreeResList(*ppIoRes);
970 *ppIoRes = NULL;
972 if (pPCI->pci_command & PCI_CMD_IO_ENABLE) {
973 unsigned char iomap = pciReadByte(pPCI->tag, APB_IO_ADDRESS_MAP);
974 if (simbavgaRoutingAllow)
975 iomap |= 0x01;
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);
987 if (ppMemRes) {
988 xf86FreeResList(*ppMemRes);
989 *ppMemRes = NULL;
991 if (pPCI->pci_command & PCI_CMD_MEM_ENABLE) {
992 unsigned char memmap = pciReadByte(pPCI->tag, APB_MEM_ADDRESS_MAP);
993 if (simbavgaRoutingAllow)
994 memmap |= 0x01;
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);
1006 if (ppPmemRes) {
1007 xf86FreeResList(*ppPmemRes);
1008 *ppPmemRes = NULL;
1012 void ARCH_PCI_PCI_BRIDGE(pciConfigPtr pPCI)
1014 static pciBusFuncs_t simbaBusFuncs;
1015 pciBusInfo_t *pBusInfo;
1016 CARD16 pcicommand;
1018 if (pPCI->pci_device_vendor != DEVID(VENDOR_SUN, CHIP_SIMBA))
1019 return;
1021 pBusInfo = pPCI->businfo;
1023 simbaBusFuncs = *(pBusInfo->funcs);
1024 simbaBusFuncs.pciControlBridge = simbaControlBridge;
1025 simbaBusFuncs.pciGetBridgeResources = simbaGetBridgeResources;
1027 pBusInfo->funcs = &simbaBusFuncs;
1029 if (!simbavgaRoutingAllow)
1030 return;
1032 pcicommand = 0;
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;
1044 if (!pcicommand)
1045 return;
1047 simbaCheckBus(pcicommand,
1048 PCI_SECONDARY_BUS_EXTRACT(pPCI->pci_pp_bus_register, pPCI->tag));
1051 #endif /* defined(ARCH_PCI_PCI_BRIDGE) */