summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c')
-rw-r--r--xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c167
1 files changed, 151 insertions, 16 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c b/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c
index f74d0d8b3..9b1e3f000 100644
--- a/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c
+++ b/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c,v 3.39 2001/04/01 14:00:08 tsi Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c,v 3.42 2001/05/16 07:56:06 alanh Exp $ */
/*
* Copyright (c) 1997-1999 by The XFree86 Project, Inc.
@@ -406,7 +406,8 @@ FindPCIVideoInfo(void)
xf86ErrorF("unknown chipset (0x%04x) ", info->chipType);
xf86ErrorF("rev %d", info->chipRev);
for (i = 0; i < 6; i++) {
- if (info->memBase[i]) {
+ if (info->memBase[i] &&
+ (info->memBase[i] < (memType)(-1 << info->size[i]))) {
if (!memdone) {
xf86ErrorF(", Mem @ ");
memdone = TRUE;
@@ -416,7 +417,8 @@ FindPCIVideoInfo(void)
}
}
for (i = 0; i < 6; i++) {
- if (info->ioBase[i]) {
+ if (info->ioBase[i] &&
+ (info->ioBase[i] < (memType)(-1 << info->size[i]))) {
if (!iodone) {
xf86ErrorF(", I/O @ ");
iodone = TRUE;
@@ -425,6 +427,10 @@ FindPCIVideoInfo(void)
xf86ErrorF("0x%04x/%d", info->ioBase[i], info->size[i]);
}
}
+ if (info->biosBase &&
+ (info->biosBase < (memType)(-1 << info->biosSize)))
+ xf86ErrorF(", BIOS @ 0x%08x/%d",
+ info->biosBase, info->biosSize);
xf86ErrorF("\n");
}
}
@@ -819,12 +825,14 @@ xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes)
resMisc |= ResEstimated;
for (i = 0; i < 6; i++) {
- if (pvp->ioBase[i]) {
+ if (pvp->ioBase[i] &&
+ (pvp->ioBase[i] < (memType)(-1 << pvp->size[i]))) {
PV_I_RANGE(range,pvp,i,ResExcIoBlock | resMisc);
tmp = xf86AddResToList(NULL, &range, -1);
removeOverlapsWithBridges(pvp->bus,tmp);
*res = xf86JoinResLists(tmp,*res);
- } else if (pvp->memBase[i]) {
+ } else if (pvp->memBase[i] &&
+ (pvp->memBase[i] < (memType)(-1 << pvp->size[i]))) {
PV_M_RANGE(range, pvp,i, ResExcMemBlock | resMisc);
tmp = xf86AddResToList(NULL, &range, -1);
removeOverlapsWithBridges(pvp->bus,tmp);
@@ -834,7 +842,8 @@ xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes)
/* FIXME!!!: Don't use BIOS resources for overlap
* checking but reserve them!
*/
- if (pvp->biosBase) {
+ if (pvp->biosBase &&
+ (pvp->biosBase < (memType)(-1 << pvp->biosSize))) {
PV_B_RANGE(range, pvp, ResExcMemBlock | resMisc);
tmp = xf86AddResToList(NULL, &range, -1);
removeOverlapsWithBridges(pvp->bus,tmp);
@@ -1185,13 +1194,12 @@ fixPciResource(int prt, memType alignment, pciVideoPtr pvp, long type)
xf86FreeResList(w_2nd);
xf86FreeResList(avoid);
return TRUE;
- } else {
+ }
#ifdef DEBUG
- ErrorF("removing old resource\n");
+ ErrorF("removing old resource\n");
#endif
- orgAcc = Acc;
- Acc = AccTmp;
- }
+ orgAcc = Acc;
+ Acc = AccTmp;
#else
orgAcc = xf86DupResList(Acc);
pAcc = &Acc;
@@ -1374,7 +1382,127 @@ xf86ReallocatePciResources(int entityIndex, resPtr pRes)
/*
* BIOS releated
*/
+memType
+getValidBIOSBase(PCITAG tag, int num)
+{
+ pciVideoPtr pvp = NULL;
+ PciBusPtr pbp, pbp1;
+ resPtr m = NULL;
+ resPtr tmp, avoid;
+ resRange range;
+ memType ret;
+ int n = 0;
+ CARD32 biosSize, alignment;
+
+ if (!xf86PciVideoInfo) return 0;
+
+ while ((pvp = xf86PciVideoInfo[n++])) {
+ if (pciTag(pvp->bus,pvp->device,pvp->func) == tag)
+ break;
+ }
+ if (!pvp) return 0;
+
+ biosSize = pvp->biosSize;
+ alignment = (1 << biosSize) - 1;
+ if (biosSize > 24)
+ biosSize = 24;
+
+ switch ((romBaseSource)num) {
+ case ROM_BASE_PRESET:
+ return 0; /* This should not happen */
+ case ROM_BASE_BIOS:
+ /* In some cases the BIOS base register contains the size mask */
+ if ((memType)(-1 << biosSize) == PCIGETROM(pvp->biosBase))
+ return 0;
+ P_M_RANGE(range, TAG(pvp),pvp->biosBase,biosSize,ResExcMemBlock);
+ ret = pvp->biosBase;
+ break;
+ case ROM_BASE_MEM0:
+ case ROM_BASE_MEM1:
+ case ROM_BASE_MEM2:
+ case ROM_BASE_MEM3:
+ case ROM_BASE_MEM4:
+ case ROM_BASE_MEM5:
+ if (!pvp->memBase[num] || (pvp->size[n] < biosSize))
+ return 0;
+ P_M_RANGE(range, TAG(pvp),pvp->memBase[num],biosSize,
+ ResExcMemBlock);
+ ret = pvp->memBase[num];
+ break;
+ case ROM_BASE_FIND:
+ ret = 0;
+ break;
+ default:
+ return 0; /* This should not happen */
+ }
+
+ /* Now find the ranges for validation */
+ avoid = xf86DupResList(pciAvoidRes);
+ pbp = pbp1 = xf86PciBus;
+ while (pbp) {
+ if (pbp->secondary == pvp->bus) {
+ if (pbp->preferred_pmem)
+ tmp = xf86DupResList(pbp->preferred_pmem);
+ else
+ tmp = xf86DupResList(pbp->pmem);
+ m = xf86JoinResLists(m,tmp);
+ if (pbp->preferred_mem)
+ tmp = xf86DupResList(pbp->preferred_mem);
+ else
+ tmp = xf86DupResList(pbp->mem);
+ m = xf86JoinResLists(m,tmp);
+ tmp = m;
+ while (tmp) {
+ tmp->block_end = MIN(tmp->block_end,PCI_MEM32_LENGTH_MAX);
+ tmp = tmp->next;
+ }
+ }
+ while (pbp1) {
+ if (pbp1->primary == pvp->bus) {
+ tmp = xf86DupResList(pbp1->preferred_pmem);
+ avoid = xf86JoinResLists(avoid,tmp);
+ tmp = xf86DupResList(pbp1->pmem);
+ avoid = xf86JoinResLists(avoid,tmp);
+ tmp = xf86DupResList(pbp1->preferred_mem);
+ avoid = xf86JoinResLists(avoid,tmp);
+ tmp = xf86DupResList(pbp1->mem);
+ avoid = xf86JoinResLists(avoid,tmp);
+ }
+ pbp1 = pbp1->next;
+ }
+ pbp = pbp->next;
+ }
+ pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid);
+
+ if (!ret) {
+ /*
+ * Return a possible window. Note that this doesn't deal with
+ * host bridges yet. But the fix for that belongs elsewhere.
+ */
+ while (m) {
+ range = xf86GetBlock(ResExcMemBlock,
+ PCI_SIZE(ResMem, TAG(pvp), 1 << biosSize),
+ m->block_begin, m->block_end,
+ PCI_SIZE(ResMem, TAG(pvp), alignment),
+ avoid);
+ if (range.type != ResEnd) {
+ ret = M2B(TAG(pvp), range.rBase);
+ break;
+ }
+ m = m->next;
+ }
+ } else {
+ if (!xf86IsSubsetOf(range, m) ||
+ ChkConflict(&range, avoid, SETUP))
+ ret = 0;
+ }
+
+ xf86FreeResList(avoid);
+ xf86FreeResList(m);
+ return ret;
+}
+#if 0
memType
getValidBIOSBase(PCITAG tag, int *num)
{
@@ -1436,7 +1564,9 @@ getValidBIOSBase(PCITAG tag, int *num)
}
pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid);
- if (pvp->biosBase) { /* try biosBase first */
+ if (pvp->biosBase &&
+ (pvp->biosBase < (memType)(-1 << pvp->biosSize))) {
+ /* try biosBase first */
P_M_RANGE(range, TAG(pvp),pvp->biosBase,biosSize,ResExcMemBlock);
if (xf86IsSubsetOf(range,m) && ! ChkConflict(&range,avoid,SETUP)) {
xf86FreeResList(avoid);
@@ -1498,6 +1628,7 @@ getValidBIOSBase(PCITAG tag, int *num)
return 0;
}
+#endif
/*
* xf86Bus.c interface
@@ -1566,24 +1697,24 @@ get_sun_apb_ranges(PciBusPtr PciBus, pciConfigPtr pcrp)
iomap = pciReadByte(pcrp->tag, APB_IO_ADDRESS_MAP);
memmap = pciReadByte(pcrp->tag, APB_MEM_ADDRESS_MAP);
- /* if (pcrp->pci_command & PCI_CMD_IO_ENABLE) */ { /* ??? */
+ if (pcrp->pci_command & PCI_CMD_IO_ENABLE) {
for (i = 0; i < 8; i++) {
if ((iomap & (1 << i)) != 0) {
PCI_I_RANGE(range, pcrp->tag,
(i << 21), (i << 21) + ((1 << 21) - 1),
ResIo | ResBlock | ResExclusive);
- PciBus->io = xf86AddResToList(PciBus->io, &range, -1);
+ PciBus->preferred_io = xf86AddResToList(PciBus->preferred_io, &range, -1);
}
}
}
- /* if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) */ { /* ??? */
+ if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) {
for (i = 0; i < 8; i++) {
if ((memmap & (1 << i)) != 0) {
PCI_M_RANGE(range, pcrp->tag,
(i << 29), (i << 29) + ((1 << 29) - 1),
ResMem | ResBlock | ResExclusive);
- PciBus->mem = xf86AddResToList(PciBus->mem, &range, -1);
+ PciBus->preferred_mem = xf86AddResToList(PciBus->preferred_mem, &range, -1);
}
}
}
@@ -1923,6 +2054,10 @@ ValidatePci(void)
Sys = xf86AddResToList(Sys, &range, -1);
}
}
+#ifdef DEBUG
+ xf86MsgVerb(X_INFO, 3,"Sys:\n");
+ xf86PrintResList(3,Sys);
+#endif
/*
* The order the video devices are listed in is