#include <stdio.h>
#include "compiler.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "Pci.h"
#include <asm/unistd.h>
#include "../linux/lnx.h"
static CARD32 axpPciCfgRead(PCITAG tag, int off);
static void axpPciCfgWrite(PCITAG, int off, CARD32 val);
static void axpPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits);
static pciBusFuncs_t axpFuncs0 = {
axpPciCfgRead,
axpPciCfgWrite,
axpPciCfgSetBits,
pciAddrNOOP,
pciAddrNOOP
};
typedef struct _axpDomainRec {
int domain, hose;
int root_bus;
unsigned long dense_io, sparse_io;
unsigned long dense_mem, sparse_mem;
IOADDRESS mapped_io;
} axpDomainRec, *axpDomainPtr;
#define MAX_DOMAINS (MAX_PCI_BUSES / 256)
static axpDomainPtr xf86DomainInfo[MAX_DOMAINS] = { NULL, };
static int pciNumDomains = 0;
#if 0
# define FORCE_HIGH_DOMAINS MAX_DOMAINS
#endif
#if defined(FORCE_HIGH_DOMAINS) && (FORCE_HIGH_DOMAINS > MAX_DOMAINS)
# undef FORCE_HIGH_DOMAINS
# define FORCE_HIGH_DOMAINS MAX_DOMAINS
#endif
static int
axpSetupDomains(void)
{
axpDomainRec axpDomain;
int numDomains = 0;
int hose;
#ifndef INCLUDE_XF86_NO_DOMAIN
#ifdef FORCE_HIGH_DOMAINS
xf86Msg(X_WARNING,
"DEBUG OPTION FORCE_HIGH_DOMAINS in use - DRI will *NOT* work\n");
numDomains = FORCE_HIGH_DOMAINS;
#endif
for(hose = 0; hose < MAX_DOMAINS; hose++) {
axpDomain.root_bus = _iobase(IOBASE_ROOT_BUS, hose, -1, -1);
if (axpDomain.root_bus < 0) continue;
axpDomain.hose = hose;
#ifndef FORCE_HIGH_DOMAINS
axpDomain.domain = axpDomain.hose = hose;
numDomains = axpDomain.domain + 1;
#else
axpDomain.domain = numDomains - hose - 1;
xf86Msg(X_WARNING,
"FORCE_HIGH_DOMAINS - assigned hose %d to domain %d\n",
axpDomain.hose, axpDomain.domain);
#endif
axpDomain.dense_io = _iobase(IOBASE_DENSE_IO, hose, -1, -1);
axpDomain.sparse_io = _iobase(IOBASE_SPARSE_IO, hose, -1, -1);
axpDomain.mapped_io = 0;
axpDomain.dense_mem = _iobase(IOBASE_DENSE_MEM, hose, -1, -1);
axpDomain.sparse_mem = _iobase(IOBASE_SPARSE_MEM, hose, -1, -1);
xf86DomainInfo[axpDomain.domain] = xnfalloc(sizeof(axpDomainRec));
*(xf86DomainInfo[axpDomain.domain]) = axpDomain;
if (axpDomain.sparse_io) {
if (_iobase(IOBASE_ROOT_BUS, hose + 1, -1, -1) >= 0) {
xf86Msg(X_INFO,
"Sparse I/O system - constraining video to hose 0\n");
}
break;
}
}
#else
xf86DomainInfo[0] = xnfalloc(sizeof(axpDomainRec));
*(xf86DomainInfo[0]) = axpDomain;
numDomains = 1;
#endif
return numDomains;
}
void
axpPciInit()
{
axpDomainPtr pDomain;
int domain, bus;
pciNumDomains = axpSetupDomains();
for(domain = 0; domain < pciNumDomains; domain++) {
if (!(pDomain = xf86DomainInfo[domain])) continue;
bus = PCI_MAKE_BUS(domain, 0);
pciBusInfo[bus] = xnfalloc(sizeof(pciBusInfo_t));
(void)memset(pciBusInfo[bus], 0, sizeof(pciBusInfo_t));
pciBusInfo[bus]->configMech = PCI_CFG_MECH_OTHER;
pciBusInfo[bus]->numDevices = 32;
pciBusInfo[bus]->funcs = &axpFuncs0;
pciBusInfo[bus]->pciBusPriv = pDomain;
pciNumBuses = bus + 1;
}
pciFindFirstFP = pciGenFindFirst;
pciFindNextFP = pciGenFindNext;
}
static int
axpPciBusFromTag(PCITAG tag)
{
pciBusInfo_t *pBusInfo;
axpDomainPtr pDomain;
int bus, dfn;
bus = PCI_BUS_FROM_TAG(tag);
if ((bus >= pciNumBuses)
|| !(pBusInfo = pciBusInfo[bus])
|| !(pDomain = pBusInfo->pciBusPriv)
|| (pDomain->domain != PCI_DOM_FROM_TAG(tag))) return -1;
bus = PCI_BUS_NO_DOMAIN(bus) + pDomain->root_bus;
dfn = PCI_DFN_FROM_TAG(tag);
if (_iobase(IOBASE_HOSE, -1, bus, dfn) != pDomain->hose) return -1;
return bus;
}
static CARD32
axpPciCfgRead(PCITAG tag, int off)
{
int bus, dfn;
CARD32 val = 0xffffffff;
if ((bus = axpPciBusFromTag(tag)) >= 0) {
dfn = PCI_DFN_FROM_TAG(tag);
syscall(__NR_pciconfig_read, bus, dfn, off, 4, &val);
}
return(val);
}
static void
axpPciCfgWrite(PCITAG tag, int off, CARD32 val)
{
int bus, dfn;
if ((bus = axpPciBusFromTag(tag)) >= 0) {
dfn = PCI_DFN_FROM_TAG(tag);
syscall(__NR_pciconfig_write, bus, dfn, off, 4, &val);
}
}
static void
axpPciCfgSetBits(PCITAG tag, int off, CARD32 mask, CARD32 bits)
{
int bus, dfn;
CARD32 val = 0xffffffff;
if ((bus = axpPciBusFromTag(tag)) >= 0) {
dfn = PCI_DFN_FROM_TAG(tag);
syscall(__NR_pciconfig_read, bus, dfn, off, 4, &val);
val = (val & ~mask) | (bits & mask);
syscall(__NR_pciconfig_write, bus, dfn, off, 4, &val);
}
}
#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)
{
axpDomainPtr pDomain;
int domain = PCI_DOM_FROM_TAG(Tag);
if ((domain < 0) || (domain >= pciNumDomains) ||
!(pDomain = xf86DomainInfo[domain]))
FatalError("%s called with invalid parameters\n", __FUNCTION__);
return xf86MapVidMem(ScreenNum, Flags,
pDomain->dense_mem + Base - _bus_base(), Size);
}
IOADDRESS
xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag,
IOADDRESS Base, unsigned long Size)
{
axpDomainPtr pDomain;
int domain = PCI_DOM_FROM_TAG(Tag);
if ((domain < 0) || (domain >= pciNumDomains) ||
!(pDomain = xf86DomainInfo[domain]))
FatalError("%s called with invalid parameters\n", __FUNCTION__);
if (pDomain->sparse_io) return Base;
if (!pDomain->mapped_io)
pDomain->mapped_io = (IOADDRESS)xf86MapVidMem(ScreenNum, Flags,
pDomain->dense_io - _bus_base(),
0x10000);
return pDomain->mapped_io + Base;
}
int
xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf)
{
static unsigned long pagemask = 0;
unsigned char *MappedAddr;
unsigned long MapSize;
ADDRESS MapBase;
int i;
if (!pagemask) pagemask = xf86getpagesize() - 1;
MapBase = Base & ~pagemask;
MapSize = ((Base + Len + pagemask) & ~pagemask) - MapBase;
MappedAddr = xf86MapDomainMemory(-1, VIDMEM_READONLY | VIDMEM_MMIO,
Tag, MapBase, MapSize);
for (i = 0; i < Len; i++) {
*Buf++ = xf86ReadMmio8(MappedAddr, Base - MapBase + i);
}
xf86UnMapVidMem(-1, MappedAddr, MapSize);
return Len;
}
resPtr
xf86PciBusAccWindowsFromOS(void)
{
resPtr pRes = NULL;
resRange range;
int domain;
for(domain = 0; domain < pciNumDomains; domain++) {
if (!xf86DomainInfo[domain]) continue;
RANGE(range, 0, 0xffffffffUL,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0, 0x0000ffffUL,
RANGE_TYPE(ResExcIoBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
}
return pRes;
}
resPtr
xf86BusAccWindowsFromOS(void)
{
return xf86PciBusAccWindowsFromOS();
}
resPtr
xf86AccResFromOS(resPtr pRes)
{
resRange range;
int domain;
for(domain = 0; domain < pciNumDomains; domain++) {
if (!xf86DomainInfo[domain]) continue;
RANGE(range, 0x000c0000, 0x000effff,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0x00000000, 0x000000ff,
RANGE_TYPE(ResExcIoBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0x00000000, 0x00000000,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0xffffffff, 0xffffffff,
RANGE_TYPE(ResExcMemBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
RANGE(range, 0xffffffff, 0xffffffff,
RANGE_TYPE(ResExcIoBlock, domain));
pRes = xf86AddResToList(pRes, &range, -1);
}
return pRes;
}
#endif