#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "Pci.h"
#include "xf86sbusBus.h"
#if defined(sun)
extern char *apertureDevName;
static int apertureFd = -1;
static pointer
sparcMapAperture(int iScreen, int Flags,
unsigned long long Base, unsigned long Size)
{
pointer result;
static int lastFlags = 0;
if ((apertureFd < 0) || (Flags != lastFlags)) {
if (apertureFd >= 0)
close(apertureFd);
lastFlags = Flags;
apertureFd = open(apertureDevName,
(Flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR);
if (apertureFd < 0)
FatalError("sparcMapAperture: open failure: %s\n",
strerror(errno));
}
result = mmap(NULL, Size,
(Flags & VIDMEM_READONLY) ?
PROT_READ : (PROT_READ | PROT_WRITE),
MAP_SHARED, apertureFd, (off_t)Base);
if (result == MAP_FAILED)
FatalError("sparcMapAperture: mmap failure: %s\n", strerror(errno));
return result;
}
typedef struct _sparcDomainRec {
unsigned long long io_addr, io_size;
unsigned long long mem_addr, mem_size;
pointer pci, io;
int bus_min, bus_max;
unsigned char dfn_mask[256 / 8];
} sparcDomainRec, *sparcDomainPtr;
#define SetBitInMap(bit, map) \
do { \
int _bit = (bit); \
(map)[_bit >> 3] |= 1 << (_bit & 7); \
} while (0)
#define IsBitSetInMap(bit, map) \
((map)[(bit) >> 3] & (1 << ((bit) & 7)))
#define MAX_DOMAINS (MAX_PCI_BUSES / 256)
static sparcDomainPtr xf86DomainInfo[MAX_DOMAINS];
static int pciNumDomains = 1;
#define PciReg(base, tag, off, type) \
*(volatile type *)(pointer)((char *)(base) + \
(PCI_TAG_NO_DOMAIN(tag) | (off)))
static CARD32
sparcPciCfgRead32(PCITAG tag, int off)
{
pciBusInfo_t *pBusInfo;
sparcDomainPtr pDomain;
volatile CARD32 result = (CARD32)(-1);
int bus;
if ((off >= 0) && (off <= 252) && !(off & 3) &&
((bus = PCI_BUS_FROM_TAG(tag)) < pciNumBuses) &&
(pBusInfo = pciBusInfo[bus]) && (pDomain = pBusInfo->pciBusPriv) &&
(bus >= pDomain->bus_min) && (bus < pDomain->bus_max) &&
((bus > pDomain->bus_min) ||
IsBitSetInMap(PCI_DFN_FROM_TAG(tag), pDomain->dfn_mask))) {
result = PciReg(pDomain->pci, tag, off, CARD32);
result = PCI_CPU(result);
}
return result;
}
static void
sparcPciCfgWrite32(PCITAG tag, int off, CARD32 val)
{
pciBusInfo_t *pBusInfo;
sparcDomainPtr pDomain;
int bus;
if ((off < 0) || (off > 252) || (off & 3) ||
((bus = PCI_BUS_FROM_TAG(tag)) >= pciNumBuses) ||
!(pBusInfo = pciBusInfo[bus]) || !(pDomain = pBusInfo->pciBusPriv) ||
(bus < pDomain->bus_min) || (bus >= pDomain->bus_max) ||
((bus == pDomain->bus_min) &&
!IsBitSetInMap(PCI_DFN_FROM_TAG(tag), pDomain->dfn_mask)))
return;
val = PCI_CPU(val);
PciReg(pDomain->pci, tag, off, CARD32) = val;
}
static void
sparcPciCfgSetBits32(PCITAG tag, int off, CARD32 mask, CARD32 bits)
{
CARD32 PciVal;
PciVal = sparcPciCfgRead32(tag, off);
PciVal &= ~mask;
PciVal |= bits;
sparcPciCfgWrite32(tag, off, PciVal);
}
static pciBusFuncs_t sparcPCIFunctions =
{
sparcPciCfgRead32,
sparcPciCfgWrite32,
sparcPciCfgSetBits32,
pciAddrNOOP,
pciAddrNOOP
};
static CARD32
sabrePciCfgRead32(PCITAG tag, int off)
{
pciBusInfo_t *pBusInfo;
sparcDomainPtr pDomain;
volatile CARD32 result;
int bus;
if (PCI_BDEV_FROM_TAG(tag))
return sparcPciCfgRead32(tag, off);
if (PCI_FUNC_FROM_TAG(tag) || (off < 0) || (off > 252) || (off & 3) ||
((bus = PCI_BUS_FROM_TAG(tag)) >= pciNumBuses) ||
!(pBusInfo = pciBusInfo[bus]) || !(pDomain = pBusInfo->pciBusPriv) ||
(bus != pDomain->bus_min))
return (CARD32)(-1);
if (off < 8) {
result = (PciReg(pDomain->pci, tag, off, CARD16) << 16) |
PciReg(pDomain->pci, tag, off + 2, CARD16);
return PCI_CPU(result);
}
result = (PciReg(pDomain->pci, tag, off + 3, CARD8) << 24) |
(PciReg(pDomain->pci, tag, off + 2, CARD8) << 16) |
(PciReg(pDomain->pci, tag, off + 1, CARD8) << 8) |
(PciReg(pDomain->pci, tag, off , CARD8) );
return result;
}
static void
sabrePciCfgWrite32(PCITAG tag, int off, CARD32 val)
{
pciBusInfo_t *pBusInfo;
sparcDomainPtr pDomain;
int bus;
if (PCI_BDEV_FROM_TAG(tag))
sparcPciCfgWrite32(tag, off, val);
else if (!PCI_FUNC_FROM_TAG(tag) &&
(off >= 0) && (off <= 252) && !(off & 3) &&
((bus = PCI_BUS_FROM_TAG(tag)) < pciNumBuses) &&
(pBusInfo = pciBusInfo[bus]) &&
(pDomain = pBusInfo->pciBusPriv) &&
(bus == pDomain->bus_min)) {
if (off < 8) {
val = PCI_CPU(val);
PciReg(pDomain->pci, tag, off , CARD16) = val >> 16;
PciReg(pDomain->pci, tag, off + 2, CARD16) = val;
} else {
PciReg(pDomain->pci, tag, off , CARD8) = val;
PciReg(pDomain->pci, tag, off + 1, CARD8) = val >> 8;
PciReg(pDomain->pci, tag, off + 2, CARD8) = val >> 16;
PciReg(pDomain->pci, tag, off + 3, CARD8) = val >> 24;
}
}
}
static void
sabrePciCfgSetBits32(PCITAG tag, int off, CARD32 mask, CARD32 bits)
{
CARD32 PciVal;
PciVal = sabrePciCfgRead32(tag, off);
PciVal &= ~mask;
PciVal |= bits;
sabrePciCfgWrite32(tag, off, PciVal);
}
static pciBusFuncs_t sabrePCIFunctions =
{
sabrePciCfgRead32,
sabrePciCfgWrite32,
sabrePciCfgSetBits32,
pciAddrNOOP,
pciAddrNOOP
};
static int pagemask;
void
sparcPciInit(void)
{
int node, node2;
if (!xf86LinearVidMem())
return;
apertureFd = open(apertureDevName, O_RDWR);
if (apertureFd < 0) {
xf86Msg(X_ERROR,
"sparcPciInit: open failure: %s\n", strerror(errno));
return;
}
sparcPromInit();
pagemask = xf86getpagesize() - 1;
for (node = promGetChild(promRootNode);
node;
node = promGetSibling(node)) {
unsigned long long pci_addr;
sparcDomainRec domain;
sparcDomainPtr pDomain;
pciBusFuncs_p pFunctions;
char *prop_val;
int prop_len, bus;
prop_val = promGetProperty("name", &prop_len);
if (!prop_val || (prop_len < 3) || (prop_len > 4) ||
strcmp(prop_val, "pci"))
continue;
prop_val = promGetProperty("model", &prop_len);
if (!prop_val || (prop_len <= 0)) {
prop_val = promGetProperty("compatible", &prop_len);
if (!prop_val || (prop_len <= 0))
continue;
}
pFunctions = &sparcPCIFunctions;
(void)memset(&domain, 0, sizeof(domain));
if (!strncmp("SUNW,sabre", prop_val, prop_len) ||
!strncmp("pci108e,a000", prop_val, prop_len) ||
!strncmp("pci108e,a001", prop_val, prop_len)) {
static Bool sabre_seen = FALSE;
xf86Msg(X_INFO,
"Sabre or Hummingbird PCI host bridge found (\"%s\")\n",
prop_val);
if (sabre_seen)
continue;
sabre_seen = TRUE;
prop_val = promGetProperty("bus-range", &prop_len);
if (!prop_val || (prop_len != 8) ||
(((unsigned int *)prop_val)[0]) ||
(((unsigned int *)prop_val)[1] >= 256))
continue;
pci_addr = 0x01fe01000000ull;
domain.io_addr = 0x01fe02000000ull;
domain.io_size = 0x000001000000ull;
domain.mem_addr = 0x01ff00000000ull;
domain.mem_size = 0x000100000000ull;
domain.bus_min = 0;
domain.bus_max = ((int *)prop_val)[1];
pFunctions = &sabrePCIFunctions;
} else
if (!strncmp("SUNW,psycho", prop_val, prop_len) ||
!strncmp("pci108e,8000", prop_val, prop_len)) {
xf86Msg(X_INFO,
"Psycho PCI host bridge found (\"%s\")\n", prop_val);
prop_val = promGetProperty("bus-range", &prop_len);
if (!prop_val || (prop_len != 8) ||
(((unsigned int *)prop_val)[1] >= 256) ||
(((unsigned int *)prop_val)[0] > ((unsigned int *)prop_val)[1]))
continue;
domain.bus_min = ((int *)prop_val)[0];
domain.bus_max = ((int *)prop_val)[1];
prop_val = promGetProperty("ranges", &prop_len);
if (!prop_val || (prop_len != 112) ||
prop_val[0] || (prop_val[28] != 0x01u) ||
(prop_val[56] != 0x02u) || (prop_val[84] != 0x03u) ||
(((unsigned int *)prop_val)[4] != 0x01000000u) ||
((unsigned int *)prop_val)[5] ||
((unsigned int *)prop_val)[12] ||
(((unsigned int *)prop_val)[13] != 0x00010000u) ||
((unsigned int *)prop_val)[19] ||
(((unsigned int *)prop_val)[20] != 0x80000000u) ||
((((unsigned int *)prop_val)[11] & ~0x00010000u) !=
0x02000000u) ||
(((unsigned int *)prop_val)[18] & ~0x80000000u) ||
(((unsigned int *)prop_val)[3] !=
((unsigned int *)prop_val)[10]) ||
(((unsigned int *)prop_val)[17] !=
((unsigned int *)prop_val)[24]) ||
(((unsigned int *)prop_val)[18] !=
((unsigned int *)prop_val)[25]) ||
(((unsigned int *)prop_val)[19] !=
((unsigned int *)prop_val)[26]) ||
(((unsigned int *)prop_val)[20] !=
((unsigned int *)prop_val)[27]))
continue;
(void)memcpy(&pci_addr, prop_val + 12,
sizeof(pci_addr));
(void)memcpy(&domain.io_addr, prop_val + 40,
sizeof(domain.io_addr));
(void)memcpy(&domain.mem_addr, prop_val + 68,
sizeof(domain.mem_addr));
domain.io_size = 0x000000010000ull;
domain.mem_size = 0x000080000000ull;
} else
if (!strncmp("SUNW,schizo", prop_val, prop_len) ||
!strncmp("pci108e,8001", prop_val, prop_len)) {
volatile unsigned long long mem_match, mem_mask, io_match, io_mask;
unsigned long Offset;
pointer pSchizo;
xf86Msg(X_INFO,
"Schizo PCI host bridge found (\"%s\")\n", prop_val);
prop_val = promGetProperty("bus-range", &prop_len);
if (!prop_val || (prop_len != 8) ||
(((unsigned int *)prop_val)[1] >= 256) ||
(((unsigned int *)prop_val)[0] > ((unsigned int *)prop_val)[1]))
continue;
domain.bus_min = ((int *)prop_val)[0];
domain.bus_max = ((int *)prop_val)[1];
prop_val = promGetProperty("reg", &prop_len);
if (!prop_val || (prop_len != 48))
continue;
pSchizo = sparcMapAperture(-1, VIDMEM_MMIO,
((unsigned long long *)prop_val)[2] - 0x000000010000ull,
0x00010000ul);
if ((((unsigned long long *)prop_val)[0] & 0x000000700000ull) ==
0x000000600000ull)
Offset = 0x0040;
else
Offset = 0x0060;
mem_match = PciReg(pSchizo, 0, Offset, unsigned long long);
mem_mask = PciReg(pSchizo, 0, Offset + 8, unsigned long long);
io_match = PciReg(pSchizo, 0, Offset + 16, unsigned long long);
io_mask = PciReg(pSchizo, 0, Offset + 24, unsigned long long);
xf86UnMapVidMem(-1, pSchizo, 0x00010000ul);
mem_mask = (((mem_mask - 1) ^ mem_mask) >> 1) + 1;
io_mask = (((io_mask - 1) ^ io_mask ) >> 1) + 1;
if (io_mask <= 0x000001000000ull)
continue;
domain.mem_addr = mem_match & ~0x8000000000000000ull;
domain.mem_size = mem_mask;
pci_addr = io_match & ~0x8000000000000000ull;
domain.io_addr = pci_addr + 0x0000000001000000ull;
domain.io_size = io_mask - 0x0000000001000000ull;
} else {
xf86Msg(X_WARNING, "Unknown PCI host bridge: \"%s\"\n", prop_val);
continue;
}
domain.pci = (char *)sparcMapAperture(-1, VIDMEM_MMIO,
pci_addr + PCI_MAKE_TAG(domain.bus_min, 0, 0),
PCI_MAKE_TAG(domain.bus_max - domain.bus_min + 1, 0, 0)) -
PCI_MAKE_TAG(domain.bus_min, 0, 0);
pDomain = xnfalloc(sizeof(sparcDomainRec));
*pDomain = domain;
bus = pDomain->bus_min =
PCI_MAKE_BUS(pciNumDomains, domain.bus_min);
pciNumBuses = pDomain->bus_max =
PCI_MAKE_BUS(pciNumDomains, domain.bus_max) + 1;
pciBusInfo[bus] = xnfcalloc(1, sizeof(pciBusInfo_t));
pciBusInfo[bus]->configMech = PCI_CFG_MECH_OTHER;
pciBusInfo[bus]->numDevices = 32;
pciBusInfo[bus]->funcs = pFunctions;
pciBusInfo[bus]->pciBusPriv = pDomain;
while (++bus < pciNumBuses) {
pciBusInfo[bus] = xnfalloc(sizeof(pciBusInfo_t));
*(pciBusInfo[bus]) = *(pciBusInfo[bus - 1]);
pciBusInfo[bus]->funcs = &sparcPCIFunctions;
}
xf86DomainInfo[pciNumDomains++] = pDomain;
for (node2 = promGetChild(node);
node2;
node2 = promGetSibling(node2)) {
prop_val = promGetProperty("reg", &prop_len);
if (!prop_val || (prop_len % 20))
continue;
prop_len /= 20;
for (; prop_len--; prop_val += 20)
SetBitInMap(PCI_DFN_FROM_TAG(*(PCITAG *)prop_val),
pDomain->dfn_mask);
}
SetBitInMap(0, pDomain->dfn_mask);
}
sparcPromClose();
close(apertureFd);
apertureFd = -1;
}
#ifndef INCLUDE_XF86_NO_DOMAIN
int
xf86GetPciDomain(PCITAG Tag)
{
return PCI_DOM_FROM_TAG(Tag);
}
pointer
xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag,
ADDRESS Base, unsigned long Size)
{
sparcDomainPtr pDomain;
pointer result;
int domain = PCI_DOM_FROM_TAG(Tag);
if ((domain <= 0) || (domain >= pciNumDomains) ||
!(pDomain = xf86DomainInfo[domain]) ||
(((unsigned long long)Base + (unsigned long long)Size) >
pDomain->mem_size))
FatalError("xf86MapDomainMemory() called with invalid parameters.\n");
result = sparcMapAperture(ScreenNum, Flags, pDomain->mem_addr + Base, Size);
if (apertureFd >= 0) {
close(apertureFd);
apertureFd = -1;
}
return result;
}
IOADDRESS
xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag,
IOADDRESS Base, unsigned long Size)
{
sparcDomainPtr pDomain;
int domain = PCI_DOM_FROM_TAG(Tag);
if ((domain <= 0) || (domain >= pciNumDomains) ||
!(pDomain = xf86DomainInfo[domain]) ||
(((unsigned long long)Base + (unsigned long long)Size) >
pDomain->io_size))
FatalError("xf86MapDomainIO() called with invalid parameters.\n");
if (!pDomain->io) {
pDomain->io = sparcMapAperture(ScreenNum, Flags,
pDomain->io_addr, pDomain->io_size);
if (apertureFd >= 0) {
close(apertureFd);
apertureFd = -1;
}
}
return (IOADDRESS)pDomain->io + Base;
}
int
xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf)
{
unsigned char *ptr, *src;
ADDRESS offset;
unsigned long size;
int len;
offset = Base & ~pagemask;
size = ((Base + Len + pagemask) & ~pagemask) - offset;
ptr = xf86MapDomainMemory(-1, VIDMEM_READONLY, Tag, offset, size);
src = ptr + (Base - offset);
for (len = Len; len-- > 0;)
*Buf++ = *src++;
xf86UnMapVidMem(-1, ptr, size);
return Len;
}
resPtr
xf86BusAccWindowsFromOS(void)
{
sparcDomainPtr pDomain;
resPtr pRes = NULL;
resRange range;
int domain;
for (domain = 1; domain < pciNumDomains; domain++) {
if (!(pDomain = xf86DomainInfo[domain]))
continue;
RANGE(range, 0, pDomain->mem_size - 1,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0, pDomain->io_size - 1,
RANGE_TYPE(ResExcIoBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
}
return pRes;
}
resPtr
xf86PciBusAccWindowsFromOS(void)
{
sparcDomainPtr pDomain;
resPtr pRes = NULL;
resRange range;
int domain;
for (domain = 1; domain < pciNumDomains; domain++) {
if (!(pDomain = xf86DomainInfo[domain]))
continue;
RANGE(range, 0, pDomain->mem_size - 1,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0, pDomain->io_size - 1,
RANGE_TYPE(ResExcIoBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
}
return pRes;
}
resPtr
xf86AccResFromOS(resPtr pRes)
{
sparcDomainPtr pDomain;
resRange range;
int domain;
for (domain = 1; domain < pciNumDomains; domain++) {
if (!(pDomain = xf86DomainInfo[domain]))
continue;
RANGE(range, 0x00000000u, 0x0009ffffu,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0x000c0000u, 0x000effffu,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0x000f0000u, 0x000fffffu,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, pDomain->mem_size - 1, pDomain->mem_size - 1,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0x00000000u, 0x00000000u,
RANGE_TYPE(ResExcIoBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, pDomain->io_size - 1, pDomain->io_size - 1,
RANGE_TYPE(ResExcIoBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
}
return pRes;
}
#endif
#endif
#if defined(ARCH_PCI_PCI_BRIDGE)
#define APB_IO_ADDRESS_MAP 0xDE
#define APB_MEM_ADDRESS_MAP 0xDF
static PCITAG simbavgaIOTag = 0, simbavgaMemTag = 0;
static Bool simbavgaRoutingAllow = TRUE;
static void
simbaCheckBus(CARD16 pcicommand, int bus)
{
pciConfigPtr pPCI, *ppPCI = xf86scanpci(0);
while ((pPCI = *ppPCI++)) {
if (pPCI->busnum < bus)
continue;
if (pPCI->busnum > bus)
break;
if (!(pcicommand & pPCI->pci_command))
continue;
switch (pPCI->pci_base_class) {
case PCI_CLASS_PREHISTORIC:
if (pPCI->pci_sub_class == PCI_SUBCLASS_PREHISTORIC_VGA)
continue;
break;
case PCI_CLASS_DISPLAY:
continue;
case PCI_CLASS_BRIDGE:
switch (pPCI->pci_sub_class) {
case PCI_SUBCLASS_BRIDGE_PCI:
case PCI_SUBCLASS_BRIDGE_CARDBUS:
simbaCheckBus(pcicommand & pPCI->pci_command,
PCI_SECONDARY_BUS_EXTRACT(pPCI->pci_pp_bus_register,
pPCI->tag));
if (!simbavgaRoutingAllow)
return;
default:
break;
}
default:
break;
}
simbavgaRoutingAllow = FALSE;
break;
}
}
static pciConfigPtr
simbaVerifyBus(int bus)
{
pciConfigPtr pPCI;
if ((bus < 0) || (bus >= pciNumBuses) ||
!pciBusInfo[bus] || !(pPCI = pciBusInfo[bus]->bridge) ||
(pPCI->pci_device_vendor != DEVID(VENDOR_SUN, CHIP_SIMBA)))
return NULL;
return pPCI;
}
static CARD16
simbaControlBridge(int bus, CARD16 mask, CARD16 value)
{
pciConfigPtr pPCI;
CARD16 current = 0, tmp;
CARD8 iomap, memmap;
if ((pPCI = simbaVerifyBus(bus))) {
iomap = pciReadByte(pPCI->tag, APB_IO_ADDRESS_MAP);
memmap = pciReadByte(pPCI->tag, APB_MEM_ADDRESS_MAP);
if (iomap & memmap & 0x01) {
current |= PCI_PCI_BRIDGE_VGA_EN;
if ((mask & PCI_PCI_BRIDGE_VGA_EN) &&
!(value & PCI_PCI_BRIDGE_VGA_EN)) {
if (!simbavgaRoutingAllow) {
xf86MsgVerb(X_WARNING, 3, "Attempt to disable VGA routing"
" through Simba at %x:%x:%x disallowed.\n",
pPCI->busnum, pPCI->devnum, pPCI->funcnum);
value |= PCI_PCI_BRIDGE_VGA_EN;
} else {
pciWriteByte(pPCI->tag, APB_IO_ADDRESS_MAP,
iomap & ~0x01);
pciWriteByte(pPCI->tag, APB_MEM_ADDRESS_MAP,
memmap & ~0x01);
simbavgaIOTag = simbavgaMemTag = 0;
}
}
} else {
if (mask & value & PCI_PCI_BRIDGE_VGA_EN) {
if (!simbavgaRoutingAllow) {
xf86MsgVerb(X_WARNING, 3, "Attempt to enable VGA routing"
" through Simba at %x:%x:%x disallowed.\n",
pPCI->busnum, pPCI->devnum, pPCI->funcnum);
value &= ~PCI_PCI_BRIDGE_VGA_EN;
} else {
if (pPCI->tag != simbavgaIOTag) {
if (simbavgaIOTag) {
tmp = pciReadByte(simbavgaIOTag,
APB_IO_ADDRESS_MAP);
pciWriteByte(simbavgaIOTag, APB_IO_ADDRESS_MAP,
tmp & ~0x01);
}
pciWriteByte(pPCI->tag, APB_IO_ADDRESS_MAP,
iomap | 0x01);
simbavgaIOTag = pPCI->tag;
}
if (pPCI->tag != simbavgaMemTag) {
if (simbavgaMemTag) {
tmp = pciReadByte(simbavgaMemTag,
APB_MEM_ADDRESS_MAP);
pciWriteByte(simbavgaMemTag, APB_MEM_ADDRESS_MAP,
tmp & ~0x01);
}
pciWriteByte(pPCI->tag, APB_MEM_ADDRESS_MAP,
memmap | 0x01);
simbavgaMemTag = pPCI->tag;
}
}
}
}
tmp = pciReadWord(pPCI->tag, PCI_PCI_BRIDGE_CONTROL_REG);
current |= tmp;
if (tmp & PCI_PCI_BRIDGE_MASTER_ABORT_EN) {
if ((mask & PCI_PCI_BRIDGE_MASTER_ABORT_EN) &&
!(value & PCI_PCI_BRIDGE_MASTER_ABORT_EN))
pciWriteWord(pPCI->tag, PCI_PCI_BRIDGE_CONTROL_REG,
tmp & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN);
} else {
if (mask & value & PCI_PCI_BRIDGE_MASTER_ABORT_EN)
pciWriteWord(pPCI->tag, PCI_PCI_BRIDGE_CONTROL_REG,
tmp | PCI_PCI_BRIDGE_MASTER_ABORT_EN);
}
}
return (current & ~mask) | (value & mask);
}
static void
simbaGetBridgeResources(int bus,
pointer *ppIoRes,
pointer *ppMemRes,
pointer *ppPmemRes)
{
pciConfigPtr pPCI = simbaVerifyBus(bus);
resRange range;
int i;
if (!pPCI)
return;
if (ppIoRes) {
xf86FreeResList(*ppIoRes);
*ppIoRes = NULL;
if (pPCI->pci_command & PCI_CMD_IO_ENABLE) {
unsigned char iomap = pciReadByte(pPCI->tag, APB_IO_ADDRESS_MAP);
if (simbavgaRoutingAllow)
iomap |= 0x01;
for (i = 0; i < 8; i++) {
if (iomap & (1 << i)) {
RANGE(range, i << 21, ((i + 1) << 21) - 1,
RANGE_TYPE(ResExcIoBlock,
xf86GetPciDomain(pPCI->tag)));
*ppIoRes = xf86AddResToList(*ppIoRes, &range, -1);
}
}
}
}
if (ppMemRes) {
xf86FreeResList(*ppMemRes);
*ppMemRes = NULL;
if (pPCI->pci_command & PCI_CMD_MEM_ENABLE) {
unsigned char memmap = pciReadByte(pPCI->tag, APB_MEM_ADDRESS_MAP);
if (simbavgaRoutingAllow)
memmap |= 0x01;
for (i = 0; i < 8; i++) {
if (memmap & (1 << i)) {
RANGE(range, i << 29, ((i + 1) << 29) - 1,
RANGE_TYPE(ResExcMemBlock,
xf86GetPciDomain(pPCI->tag)));
*ppMemRes = xf86AddResToList(*ppMemRes, &range, -1);
}
}
}
}
if (ppPmemRes) {
xf86FreeResList(*ppPmemRes);
*ppPmemRes = NULL;
}
}
void ARCH_PCI_PCI_BRIDGE(pciConfigPtr pPCI)
{
static pciBusFuncs_t simbaBusFuncs;
pciBusInfo_t *pBusInfo;
CARD16 pcicommand;
if (pPCI->pci_device_vendor != DEVID(VENDOR_SUN, CHIP_SIMBA))
return;
pBusInfo = pPCI->businfo;
simbaBusFuncs = *(pBusInfo->funcs);
simbaBusFuncs.pciControlBridge = simbaControlBridge;
simbaBusFuncs.pciGetBridgeResources = simbaGetBridgeResources;
pBusInfo->funcs = &simbaBusFuncs;
if (!simbavgaRoutingAllow)
return;
pcicommand = 0;
if (pciReadByte(pPCI->tag, APB_IO_ADDRESS_MAP) & 0x01) {
pcicommand |= PCI_CMD_IO_ENABLE;
simbavgaIOTag = pPCI->tag;
}
if (pciReadByte(pPCI->tag, APB_MEM_ADDRESS_MAP) & 0x01) {
pcicommand |= PCI_CMD_MEM_ENABLE;
simbavgaMemTag = pPCI->tag;
}
if (!pcicommand)
return;
simbaCheckBus(pcicommand,
PCI_SECONDARY_BUS_EXTRACT(pPCI->pci_pp_bus_register, pPCI->tag));
}
#endif