diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c')
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c | 167 |
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 |