? programs/Xserver/hw/xfree86/dummylib/getemptypci.c Index: programs/Xserver/hw/xfree86/common/xf86Priv.h =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/common/xf86Priv.h,v retrieving revision 1.6 diff -u -r1.6 xf86Priv.h --- programs/Xserver/hw/xfree86/common/xf86Priv.h 24 Aug 2005 11:18:32 -0000 1.6 +++ programs/Xserver/hw/xfree86/common/xf86Priv.h 29 Nov 2005 17:49:47 -0000 @@ -154,6 +154,7 @@ extern void xf86PostPreInit(void); extern void xf86PostScreenInit(void); extern memType getValidBIOSBase(PCITAG tag, int num); +extern memType getEmptyPciRange(PCITAG tag, int base_reg); extern int pciTestMultiDeviceCard(int bus, int dev, int func, PCITAG** pTag); /* xf86Config.c */ Index: programs/Xserver/hw/xfree86/common/xf86pciBus.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c,v retrieving revision 1.15 diff -u -r1.15 xf86pciBus.c --- programs/Xserver/hw/xfree86/common/xf86pciBus.c 4 Jul 2005 18:41:02 -0000 1.15 +++ programs/Xserver/hw/xfree86/common/xf86pciBus.c 29 Nov 2005 17:49:50 -0000 @@ -1516,29 +1516,117 @@ /* * BIOS releated */ -memType -getValidBIOSBase(PCITAG tag, int num) +static resPtr +getOwnResources(pciVideoPtr pvp, resPtr mem) +{ + resRange range; + int i; + /* Make sure we don't conflict with our own mem resources */ + for (i = 0; i < 6; i++) { + if (!pvp->memBase[i]) + continue; + P_M_RANGE(range,TAG(pvp),pvp->memBase[i],pvp->size[i], + ResExcMemBlock); + mem = xf86AddResToList(mem,&range,-1); + } + return mem; +} + +static void +getPciRangesForMapping(pciVideoPtr pvp, resPtr *map, resPtr *avoid) { - pciVideoPtr pvp = NULL; PciBusPtr pbp; - resPtr m = NULL; - resPtr tmp, avoid, mem = NULL; + resPtr tmp; + + *avoid = xf86DupResList(pciAvoidRes); + + pbp = xf86PciBus; + while (pbp) { + if (pbp->secondary == pvp->bus) { + if (pbp->preferred_pmem) + tmp = xf86DupResList(pbp->preferred_pmem); + else + tmp = xf86DupResList(pbp->pmem); + *map = xf86JoinResLists(*map,tmp); + if (pbp->preferred_mem) + tmp = xf86DupResList(pbp->preferred_mem); + else + tmp = xf86DupResList(pbp->mem); + *map = xf86JoinResLists(*map,tmp); + tmp = *map; + while (tmp) { + tmp->block_end = min(tmp->block_end,PCI_MEM32_LENGTH_MAX); + tmp = tmp->next; + } + } else if ((pbp->primary == pvp->bus) && + (pbp->secondary >= 0) && + (pbp->primary != pbp->secondary)) { + tmp = xf86DupResList(pbp->preferred_pmem); + *avoid = xf86JoinResLists(*avoid, tmp); + tmp = xf86DupResList(pbp->pmem); + *avoid = xf86JoinResLists(*avoid, tmp); + tmp = xf86DupResList(pbp->preferred_mem); + *avoid = xf86JoinResLists(*avoid, tmp); + tmp = xf86DupResList(pbp->mem); + *avoid = xf86JoinResLists(*avoid, tmp); + } + pbp = pbp->next; + } + pciConvertListToHost(pvp->bus,pvp->device,pvp->func, *avoid); + pciConvertListToHost(pvp->bus,pvp->device,pvp->func, *map); +} + +static memType +findPciRange(PCITAG tag, resPtr m, resPtr avoid, CARD32 size) +{ resRange range; - memType ret; + CARD32 alignment = (1 << size) - 1; + + while (m) { + range = xf86GetBlock(RANGE_TYPE(ResExcMemBlock, xf86GetPciDomain(tag)), + PCI_SIZE(ResMem, tag, 1 << size), + m->block_begin, m->block_end, + PCI_SIZE(ResMem, tag, alignment), + avoid); + if (range.type != ResEnd) { + return M2B(tag, range.rBase); + } + m = m->next; + } + return 0; +} + +pciVideoPtr +getPciVideoPtr(tag) +{ int n = 0; - int i; - CARD32 biosSize, alignment; + pciVideoPtr pvp = NULL; if (!xf86PciVideoInfo) return 0; while ((pvp = xf86PciVideoInfo[n++])) { if (pciTag(pvp->bus,pvp->device,pvp->func) == tag) - break; + return pvp; } if (!pvp) return 0; +} + +memType +getValidBIOSBase(PCITAG tag, int num) +{ + pciVideoPtr pvp = NULL; + memType ret; + CARD32 biosSize; + resPtr mem = NULL; + resPtr avoid = NULL, m = NULL; + resRange range; + + pvp = getPciVideoPtr(tag); + + if (!pvp) return 0; biosSize = pvp->biosSize; - alignment = (1 << biosSize) - 1; + if (biosSize > 24) biosSize = 24; @@ -1549,15 +1637,8 @@ /* In some cases the BIOS base register contains the size mask */ if ((memType)(-1 << biosSize) == PCIGETROM(pvp->biosBase)) return 0; - /* Make sure we don't conflict with our own mem resources */ - for (i = 0; i < 6; i++) { - if (!pvp->memBase[i]) - continue; - P_M_RANGE(range,TAG(pvp),pvp->memBase[i],pvp->size[i], - ResExcMemBlock); - mem = xf86AddResToList(mem,&range,-1); - } - P_M_RANGE(range, TAG(pvp),pvp->biosBase,biosSize,ResExcMemBlock); + mem = getOwnResources(pvp,mem); + P_M_RANGE(range, tag, pvp->biosBase,biosSize,ResExcMemBlock); ret = pvp->biosBase; break; case ROM_BASE_MEM0: @@ -1568,7 +1649,7 @@ case ROM_BASE_MEM5: if (!pvp->memBase[num] || (pvp->size[num] < biosSize)) return 0; - P_M_RANGE(range, TAG(pvp),pvp->memBase[num],biosSize, + P_M_RANGE(range, tag ,pvp->memBase[num],biosSize, ResExcMemBlock); ret = pvp->memBase[num]; break; @@ -1580,59 +1661,15 @@ } /* Now find the ranges for validation */ - avoid = xf86DupResList(pciAvoidRes); - pbp = 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; - } - } else if ((pbp->primary == pvp->bus) && - (pbp->secondary >= 0) && - (pbp->primary != pbp->secondary)) { - tmp = xf86DupResList(pbp->preferred_pmem); - avoid = xf86JoinResLists(avoid, tmp); - tmp = xf86DupResList(pbp->pmem); - avoid = xf86JoinResLists(avoid, tmp); - tmp = xf86DupResList(pbp->preferred_mem); - avoid = xf86JoinResLists(avoid, tmp); - tmp = xf86DupResList(pbp->mem); - avoid = xf86JoinResLists(avoid, tmp); - } - pbp = pbp->next; - } - pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid); - if (mem) - pciConvertListToHost(pvp->bus,pvp->device,pvp->func, mem); - + getPciRangesForMapping(pvp,&m,&avoid); + if (!ret) { /* Return a possible window */ - while (m) { - range = xf86GetBlock(RANGE_TYPE(ResExcMemBlock, xf86GetPciDomain(tag)), - 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; - } + ret = findPciRange(tag,m,avoid,biosSize); } else { #if !defined(__ia64__) /* on ia64, trust the kernel, don't look for overlaps */ + if (mem) + pciConvertListToHost(pvp->bus,pvp->device,pvp->func, mem); if (!xf86IsSubsetOf(range, m) || ChkConflict(&range, avoid, SETUP) || (mem && ChkConflict(&range, mem, SETUP))) @@ -1645,6 +1682,22 @@ return ret; } +memType +getEmptyPciRange(PCITAG tag, int base_reg) +{ + resPtr avoid = NULL, m = NULL; + memType ret; + + pciVideoPtr pvp = getPciVideoPtr(tag); + if (!pvp) return 0; + getPciRangesForMapping(pvp,&m,&avoid); + ret = findPciRange(tag,m,avoid,pvp->size[base_reg]); + xf86FreeResList(avoid); + xf86FreeResList(m); + + return ret; +} + /* * xf86Bus.c interface */ Index: programs/Xserver/hw/xfree86/dummylib/Imakefile =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/dummylib/Imakefile,v retrieving revision 1.4 diff -u -r1.4 Imakefile --- programs/Xserver/hw/xfree86/dummylib/Imakefile 23 Aug 2005 04:03:54 -0000 1.4 +++ programs/Xserver/hw/xfree86/dummylib/Imakefile 29 Nov 2005 17:49:50 -0000 @@ -8,6 +8,7 @@ SRCS = \ fatalerror.c \ getvalidbios.c \ + getemptypci.c \ logvwrite.c \ pcitestmulti.c \ verrorf.c \ @@ -32,6 +33,7 @@ OBJS = \ fatalerror.o \ getvalidbios.o \ + getemptypci.o \ logvwrite.o \ pcitestmulti.o \ verrorf.o \ Index: programs/Xserver/hw/xfree86/os-support/bus/Pci.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c,v retrieving revision 1.9 diff -u -r1.9 Pci.c --- programs/Xserver/hw/xfree86/os-support/bus/Pci.c 26 Aug 2005 05:47:36 -0000 1.9 +++ programs/Xserver/hw/xfree86/os-support/bus/Pci.c 29 Nov 2005 17:49:54 -0000 @@ -1123,13 +1123,18 @@ /* if we use a mem base save it and move it out of the way */ if (b_reg >= 0 && b_reg <= 5) { + memType emptybase; savebase = pciReadLong(Tag, PCI_MAP_REG_START+(b_reg<<2)); xf86MsgVerb(X_INFO,5,"xf86ReadPciBios: modifying membase[%i]" " for device %i:%i:%i\n", basereg, (int)PCI_BUS_FROM_TAG(Tag), (int)PCI_DEV_FROM_TAG(Tag), (int)PCI_FUNC_FROM_TAG(Tag)); + if (!(emptybase = getEmptyPciRange(Tag,b_reg))) { + xf86Msg(X_ERROR,"Cannot find empty range to map base to\n"); + return NULL; + } pciWriteLong(Tag, PCI_MAP_REG_START + (b_reg << 2), - (CARD32)~0); + emptybase); } /* Set ROM base address and enable ROM address decoding */ pciWriteLong(Tag, PCI_MAP_ROM_REG, romaddr