diff options
Diffstat (limited to 'hw/xfree86/common/xf86pciBus.c')
-rw-r--r-- | hw/xfree86/common/xf86pciBus.c | 185 |
1 files changed, 122 insertions, 63 deletions
diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index c40fc1016..641d1c919 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1,6 +1,29 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c,v 3.68.2.1 2003/05/06 17:00:43 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c,v 3.77 2003/11/03 05:11:03 tsi Exp $ */ /* - * Copyright (c) 1997-2002 by The XFree86 Project, Inc. + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). */ /* @@ -270,8 +293,8 @@ FindPCIVideoInfo(void) } /* - * 64-bit base addresses are checked for and avoided. - * XXX Should deal with them on platforms that support them. + * 64-bit base addresses are checked for and avoided on 32-bit + * platforms. */ if (pcrp->pci_base0) { if (pcrp->pci_base0 & PCI_MAP_IO) { @@ -454,7 +477,7 @@ FindPCIVideoInfo(void) memdone = TRUE; } else xf86ErrorF(", "); - xf86ErrorF("0x%08x/%d", info->memBase[i], info->size[i]); + xf86ErrorF("0x%08lx/%d", info->memBase[i], info->size[i]); } } for (i = 0; i < 6; i++) { @@ -465,12 +488,12 @@ FindPCIVideoInfo(void) iodone = TRUE; } else xf86ErrorF(", "); - xf86ErrorF("0x%04x/%d", info->ioBase[i], info->size[i]); + xf86ErrorF("0x%04lx/%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(", BIOS @ 0x%08lx/%d", info->biosBase, info->biosSize); xf86ErrorF("\n"); } } @@ -567,7 +590,7 @@ pciIoAccessEnable(void* arg) ErrorF("pciIoAccessEnable: 0x%05lx\n", *(PCITAG *)arg); #endif pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE; - (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); + pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); } static void @@ -577,7 +600,7 @@ pciIoAccessDisable(void* arg) ErrorF("pciIoAccessDisable: 0x%05lx\n", *(PCITAG *)arg); #endif pArg->ctrl &= ~SETBITS; - (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); + pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); } #undef SETBITS @@ -589,7 +612,7 @@ pciIo_MemAccessEnable(void* arg) ErrorF("pciIo_MemAccessEnable: 0x%05lx\n", *(PCITAG *)arg); #endif pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE; - (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); + pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); } static void @@ -599,7 +622,7 @@ pciIo_MemAccessDisable(void* arg) ErrorF("pciIo_MemAccessDisable: 0x%05lx\n", *(PCITAG *)arg); #endif pArg->ctrl &= ~SETBITS; - (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); + pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); } #undef SETBITS @@ -611,7 +634,7 @@ pciMemAccessEnable(void* arg) ErrorF("pciMemAccessEnable: 0x%05lx\n", *(PCITAG *)arg); #endif pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE; - (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); + pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); } static void @@ -621,38 +644,48 @@ pciMemAccessDisable(void* arg) ErrorF("pciMemAccessDisable: 0x%05lx\n", *(PCITAG *)arg); #endif pArg->ctrl &= ~SETBITS; - (*pArg->func)(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); + pciWriteLong(pArg->tag, PCI_CMD_STAT_REG, pArg->ctrl); } #undef SETBITS #undef pArg /* move to OS layer */ -#define PCI_PCI_BRDG_CTRL_BASE (PCI_PCI_BRIDGE_CONTROL_REG & 0xFC) -#define SHIFT_BITS ((PCI_PCI_BRIDGE_CONTROL_REG & 0x3) << 3) -#define SETBITS (CARD32)((PCI_PCI_BRIDGE_VGA_EN) << SHIFT_BITS) +#define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN) static void pciBusAccessEnable(BusAccPtr ptr) { + PCITAG tag = ptr->busdep.pci.acc; + CARD16 ctrl; + #ifdef DEBUG ErrorF("pciBusAccessEnable: bus=%d\n", ptr->busdep.pci.bus); #endif - (*ptr->busdep.pci.func)(ptr->busdep.pci.acc, PCI_PCI_BRDG_CTRL_BASE, - SETBITS, SETBITS); + ctrl = pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG); + if ((ctrl & MASKBITS) != PCI_PCI_BRIDGE_VGA_EN) { + ctrl = (ctrl | PCI_PCI_BRIDGE_VGA_EN) & + ~(PCI_PCI_BRIDGE_MASTER_ABORT_EN | PCI_PCI_BRIDGE_SECONDARY_RESET); + pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG, ctrl); + } } /* move to OS layer */ static void pciBusAccessDisable(BusAccPtr ptr) { + PCITAG tag = ptr->busdep.pci.acc; + CARD16 ctrl; + #ifdef DEBUG ErrorF("pciBusAccessDisable: bus=%d\n", ptr->busdep.pci.bus); #endif - (*ptr->busdep.pci.func)(ptr->busdep.pci.acc, PCI_PCI_BRDG_CTRL_BASE, - SETBITS, 0); + ctrl = pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG); + if (ctrl & MASKBITS) { + ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET); + pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG, ctrl); + } } -#undef SETBITS -#undef SHIFT_BITS +#undef MASKBITS /* move to OS layer */ static void @@ -740,23 +773,34 @@ restorePciState(PCITAG tag, pciSavePtr ptr) static void savePciBusState(BusAccPtr ptr) { + PCITAG tag = ptr->busdep.pci.acc; + ptr->busdep.pci.save.control = - pciReadWord(ptr->busdep.pci.acc, PCI_PCI_BRIDGE_CONTROL_REG) & + pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG) & ~PCI_PCI_BRIDGE_SECONDARY_RESET; /* Allow master aborts to complete normally on non-root buses */ if (ptr->busdep.pci.save.control & PCI_PCI_BRIDGE_MASTER_ABORT_EN) - pciWriteWord(ptr->busdep.pci.acc, PCI_PCI_BRIDGE_CONTROL_REG, - ptr->busdep.pci.save.control - & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN); + pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG, + ptr->busdep.pci.save.control & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN); } /* move to OS layer */ +#define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN) static void restorePciBusState(BusAccPtr ptr) { - pciWriteWord(ptr->busdep.pci.acc, PCI_PCI_BRIDGE_CONTROL_REG, - ptr->busdep.pci.save.control); + PCITAG tag = ptr->busdep.pci.acc; + CARD16 ctrl; + + /* Only restore the bits we've changed (and don't cause resets) */ + ctrl = pciReadWord(tag, PCI_PCI_BRIDGE_CONTROL_REG); + if ((ctrl ^ ptr->busdep.pci.save.control) & MASKBITS) { + ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET); + ctrl |= ptr->busdep.pci.save.control & MASKBITS; + pciWriteWord(tag, PCI_PCI_BRIDGE_CONTROL_REG, ctrl); + } } +#undef MASKBITS /* move to OS layer */ static void @@ -828,12 +872,17 @@ correctPciSize(memType base, memType oldsize, memType newsize, #if defined(LONG64) || defined(WORD64) || (B2M(pcrp->tag,PCIGETMEMORY64(basep[i])) == base) +#else + || + (!basep[i+1] + && (B2M(pcrp->tag,PCIGETMEMORY(basep[i])) == base)) #endif ))) { pcrp->basesize[i] = new_bits; break; /* to next device */ } } + if (PCI_MAP_IS64BITMEM(basep[i])) i++; } } @@ -883,7 +932,7 @@ removeOverlapsWithBridges(int busIndex, resPtr target) target->block_end - target->block_begin, target->res_type); xf86MsgVerb(X_INFO, 3, - "PCI %s resource overlap reduced 0x%08x from 0x%08x to 0x%08x\n", + "PCI %s resource overlap reduced 0x%08lx from 0x%08lx to 0x%08lx\n", ((target->res_type & ResPhysMask) == ResMem) ? "Memory" : "I/O", range.rBegin, range.rEnd, target->block_end); } @@ -988,28 +1037,38 @@ xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes) (subclass == PCI_SUBCLASS_BRIDGE_HOST)) resMisc |= ResOverlap; - if ((pcrp->pci_command & (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE))) - res = activeRes; - else - res = inactiveRes; - basep = &pcrp->pci_base0; for (i = 0; i < 6; i++) { if (basep[i]) { - if (PCI_MAP_IS_IO(basep[i])) - P_I_RANGE(range,pcrp->tag,PCIGETIO(basep[i]), + if (PCI_MAP_IS_IO(basep[i])) { + if (pcrp->pci_command & PCI_CMD_IO_ENABLE) + res = activeRes; + else + res = inactiveRes; + P_I_RANGE(range, pcrp->tag, PCIGETIO(basep[i]), pcrp->basesize[i], ResExcIoBlock | resMisc) - else if (!PCI_MAP_IS64BITMEM(basep[i])) - P_M_RANGE(range,pcrp->tag,PCIGETMEMORY(basep[i]), - pcrp->basesize[i], ResExcMemBlock | resMisc) - else { + } else if (!PCI_MAP_IS64BITMEM(basep[i])) { + if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) + res = activeRes; + else + res = inactiveRes; + P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i]), + pcrp->basesize[i], ResExcMemBlock | resMisc) + } else { i++; #if defined(LONG64) || defined(WORD64) - P_M_RANGE(range,pcrp->tag,PCIGETMEMORY64(basep[i-1]), - pcrp->basesize[i-1], ResExcMemBlock | resMisc) + P_M_RANGE(range,pcrp->tag,PCIGETMEMORY64(basep[i - 1]), + pcrp->basesize[i - 1], ResExcMemBlock | resMisc) #else + if (basep[i]) continue; + P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i - 1]), + pcrp->basesize[i - 1], ResExcMemBlock | resMisc) #endif + if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) + res = activeRes; + else + res = inactiveRes; } if (range.rBegin) { /* catch cases where PCI base is unset */ tmp = xf86AddResToList(NULL, &range, -1); @@ -1018,15 +1077,16 @@ xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes) } } } + /* Ignore disabled non-video ROMs */ - if ((res == activeRes) && + if ((pcrp->pci_command & PCI_CMD_MEM_ENABLE) && (pcrp->pci_baserom & PCI_MAP_ROM_DECODE_ENABLE)) { P_M_RANGE(range,pcrp->tag,PCIGETROM(pcrp->pci_baserom), pcrp->basesize[6], ResExcMemBlock | resMisc); if (range.rBegin) { tmp = xf86AddResToList(NULL, &range, -1); - removeOverlapsWithBridges(pcrp->busnum,tmp); - *res = xf86JoinResLists(tmp,*res); + removeOverlapsWithBridges(pcrp->busnum, tmp); + *activeRes = xf86JoinResLists(tmp, *activeRes); } } } @@ -1063,8 +1123,8 @@ xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes) pRes->block_end - pRes->block_begin, pRes->res_type); xf86MsgVerb(X_INFO, 3, - "PCI %s resource overlap reduced 0x%08x" - " from 0x%08x to 0x%08x\n", + "PCI %s resource overlap reduced 0x%08lx" + " from 0x%08lx to 0x%08lx\n", ((pRes->res_type & ResPhysMask) == ResMem) ? "Memory" : "I/O", range.rBegin, range.rEnd, pRes->block_end); @@ -1092,8 +1152,8 @@ xf86GetPciRes(resPtr *activeRes, resPtr *inactiveRes) pRes->block_end - pRes->block_begin, pRes->res_type); xf86MsgVerb(X_INFO, 3, - "PCI %s resource overlap reduced 0x%08x" - " from 0x%08x to 0x%08x\n", + "PCI %s resource overlap reduced 0x%08lx" + " from 0x%08lx to 0x%08lx\n", ((pRes->res_type & ResPhysMask) == ResMem) ? "Memory" : "I/O", range.rBegin, range.rEnd, pRes->block_end); @@ -1760,8 +1820,8 @@ xf86GetPciBridgeInfo(void) break; } - if (pBusInfo && pBusInfo->funcs->pciGetBridgeBusses) - (*pBusInfo->funcs->pciGetBridgeBusses)(secondary, + if (pBusInfo && pBusInfo->funcs->pciGetBridgeBuses) + (*pBusInfo->funcs->pciGetBridgeBuses)(secondary, &primary, &secondary, &subordinate); @@ -1899,8 +1959,8 @@ xf86GetPciBridgeInfo(void) break; } - if (pBusInfo && pBusInfo->funcs->pciGetBridgeBusses) - (*pBusInfo->funcs->pciGetBridgeBusses)(secondary, + if (pBusInfo && pBusInfo->funcs->pciGetBridgeBuses) + (*pBusInfo->funcs->pciGetBridgeBuses)(secondary, &primary, &secondary, &subordinate); @@ -2087,8 +2147,8 @@ xf86GetPciBridgeInfo(void) if (pBusInfo) { PciBus->primary = PciBus->secondary = secondary; - if (pBusInfo->funcs->pciGetBridgeBusses) - (*pBusInfo->funcs->pciGetBridgeBusses) + if (pBusInfo->funcs->pciGetBridgeBuses) + (*pBusInfo->funcs->pciGetBridgeBuses) (secondary, &PciBus->primary, &PciBus->secondary, @@ -2275,7 +2335,6 @@ ValidatePci(void) pciConfigPtr pcrp, *pcrpp; CARD32 *basep; resPtr Sys; - resPtr Fix; resRange range; int n = 0, m, i; @@ -2286,6 +2345,7 @@ ValidatePci(void) * the ones which have been assigned to a screen. */ Sys = xf86DupResList(osRes); + /* Only validate graphics devices in use */ for (i=0; i<xf86NumScreens; i++) { for (m = 0; m < xf86Screens[i]->numEntities; m++) if ((pvp = xf86GetPciInfoForEntity(xf86Screens[i]->entityList[m]))) @@ -2328,6 +2388,7 @@ ValidatePci(void) } for (pcrpp = xf86PciInfo, pcrp = *pcrpp; pcrp; pcrp = *++(pcrpp)) { + /* These were handled above */ if (PCIINFOCLASSES(pcrp->pci_base_class, pcrp->pci_sub_class)) continue; @@ -2350,13 +2411,16 @@ ValidatePci(void) pcrp->basesize[i], ResExcMemBlock) } else { i++; -#if defined(LONG64) || defined(WORD64) if (!(pcrp->pci_command & PCI_CMD_MEM_ENABLE)) continue; +#if defined(LONG64) || defined(WORD64) P_M_RANGE(range, pcrp->tag, PCIGETMEMORY64(basep[i-1]), pcrp->basesize[i-1], ResExcMemBlock) #else - continue; + if (basep[i]) + continue; + P_M_RANGE(range, pcrp->tag, PCIGETMEMORY(basep[i-1]), + pcrp->basesize[i-1], ResExcMemBlock) #endif } Sys = xf86AddResToList(Sys, &range, -1); @@ -2458,7 +2522,6 @@ ValidatePci(void) xf86MsgVerb(X_INFO, 3,"MEM/IO:\n"); xf86PrintResList(3,res_m_io); #endif - Fix = NULL; for (i = 0; i < 6; i++) { int j; resPtr own = NULL; @@ -2596,8 +2659,6 @@ initPciState(void) pcaccp->devnum = pvp->device; pcaccp->funcnum = pvp->func; pcaccp->arg.tag = pciTag(pvp->bus, pvp->device, pvp->func); - pcaccp->arg.func = - (WriteProcPtr)pciLongFunc(pcaccp->arg.tag,WRITE); pcaccp->ioAccess.AccessDisable = pciIoAccessDisable; pcaccp->ioAccess.AccessEnable = pciIoAccessEnable; pcaccp->ioAccess.arg = &pcaccp->arg; @@ -2674,8 +2735,6 @@ initPciBusState(void) pbap->enable_f = pciBusAccessEnable; pbap->disable_f = pciBusAccessDisable; pbap->busdep.pci.acc = pciTag(pbp->brbus,pbp->brdev,pbp->brfunc); - pbap->busdep.pci.func = - (SetBitsProcPtr)pciLongFunc(pbap->busdep.pci.acc,SET_BITS); savePciBusState(pbap); break; case PCI_SUBCLASS_BRIDGE_ISA: |