diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c')
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c | 168 |
1 files changed, 134 insertions, 34 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c b/xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c index a6c217cfd..9b44afe8f 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.21 2000/09/19 12:46:13 eich Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86pciBus.c,v 3.24 2000/10/26 11:47:45 tsi Exp $ */ /* * Copyright (c) 1997-1999 by The XFree86 Project, Inc. @@ -116,6 +116,8 @@ pciVendorDeviceInfo * xf86PCIVendorInfo; static void getPciClassFlags(pciConfigPtr *pcrpp); +static void +pciConvertListToHost(int bus, int dev, int func, resPtr list); static void FindPCIVideoInfo(void) @@ -227,8 +229,9 @@ FindPCIVideoInfo(void) mem64 = TRUE; #if defined LONG64 || defined WORD64 info->memBase[0] |= - (memType)PCIGETMEMORY64HIGH(pcrp->pci_base0) << 32; + (memType)PCIGETMEMORY64HIGH(pcrp->pci_base1) << 32; #else + if (pcrp->pci_base1) info->memBase[0] = 0; #endif } @@ -246,13 +249,14 @@ FindPCIVideoInfo(void) mem64 = TRUE; #if defined LONG64 || defined WORD64 info->memBase[1] |= - (memType)PCIGETMEMORY64HIGH(pcrp->pci_base1) << 32; + (memType)PCIGETMEMORY64HIGH(pcrp->pci_base2) << 32; #else + if (pcrp->pci_base2) info->memBase[1] = 0; #endif } } - } else if (mem64) + } else mem64 = FALSE; if (pcrp->pci_base2 && !mem64) { @@ -265,14 +269,15 @@ FindPCIVideoInfo(void) if (PCI_MAP_IS64BITMEM(pcrp->pci_base2)) { mem64 = TRUE; #if defined LONG64 || defined WORD64 - info->memBase[1] |= - (memType)PCIGETMEMORY64HIGH(pcrp->pci_base1) << 32; + info->memBase[2] |= + (memType)PCIGETMEMORY64HIGH(pcrp->pci_base3) << 32; #else - info->memBase[1] = 0; + if (pcrp->pci_base3) + info->memBase[2] = 0; #endif } } - } else if (mem64) + } else mem64 = FALSE; if (pcrp->pci_base3 && !mem64) { @@ -286,13 +291,14 @@ FindPCIVideoInfo(void) mem64 = TRUE; #if defined LONG64 || defined WORD64 info->memBase[3] |= - (memType)PCIGETMEMORY64HIGH(pcrp->pci_base3) << 32; + (memType)PCIGETMEMORY64HIGH(pcrp->pci_base4) << 32; #else + if (pcrp->pci_base4) info->memBase[3] = 0; #endif } } - } else if (mem64) + } else mem64 = FALSE; if (pcrp->pci_base4 && !mem64) { @@ -306,13 +312,14 @@ FindPCIVideoInfo(void) mem64 = TRUE; #if defined LONG64 || defined WORD64 info->memBase[4] |= - (memType)PCIGETMEMORY64HIGH(pcrp->pci_base4) << 32; + (memType)PCIGETMEMORY64HIGH(pcrp->pci_base5) << 32; #else + if (pcrp->pci_base5) info->memBase[4] = 0; #endif } } - } else if (mem64) + } else mem64 = FALSE; if (pcrp->pci_base5 && !mem64) { @@ -323,7 +330,8 @@ FindPCIVideoInfo(void) info->type[5] = pcrp->pci_base5 & PCI_MAP_MEMORY_ATTR_MASK; info->memBase[5] = (memType)PCIGETMEMORY(pcrp->pci_base5); } - } + } else + mem64 = FALSE; info->listed_class = pcrp->listed_class; } i++; @@ -992,11 +1000,14 @@ fixPciResource(int prt, memType alignment, pciVideoPtr pvp, long type) resRange range; resPtr resSize = NULL; resPtr w_tmp, w = NULL, w_2nd = NULL; - PCITAG tag = pciTag(pvp->bus,pvp->device,pvp->func); + PCITAG tag; PciBusPtr pbp = xf86PciBus, pbp1 = xf86PciBus; + pciConfigPtr pcp; resPtr tmp; if (!pvp) return FALSE; + tag = pciTag(pvp->bus,pvp->device,pvp->func); + pcp = pvp->thisCard; type &= ResAccMask; if (!type) type = ResShared; @@ -1090,8 +1101,7 @@ fixPciResource(int prt, memType alignment, pciVideoPtr pvp, long type) } /* convert bus based entries in avoid list to host base */ - xf86ConvertListToHost( - xf86GetPciEntity(pvp->bus,pvp->device,pvp->func), avoid); + pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid); if (!w) w = xf86DupResList(ResRange); @@ -1240,19 +1250,34 @@ fixPciResource(int prt, memType alignment, pciVideoPtr pvp, long type) (*p_base) = H2B(tag,range.rBegin,type); #ifdef DEBUG ErrorF("New PCI res %i base: 0x%lx, size: 0x%lx, type %s\n", - res_n,(*p_base),(1 << (*p_size)),type | ResMem ? "Mem" : "Io"); + res_n,(*p_base),(1 << (*p_size)), (type & ResMem) ? "Mem" : "Io"); #endif if (res_n != 0xff) { - pciWriteLong(tag,PCI_CMD_BASE_REG + res_n * sizeof(CARD32), - (CARD32)(*p_base) | (CARD32)(p_type)); + if (type & ResMem) + pvp->memBase[prt] = range.rBegin; + else + pvp->ioBase[prt] = range.rBegin; + ((CARD32 *)(&(pcp->pci_base0)))[res_n] = + (CARD32)(*p_base) | (CARD32)(p_type); + pciWriteLong(tag, PCI_CMD_BASE_REG + res_n * sizeof(CARD32), + ((CARD32 *)(&(pcp->pci_base0)))[res_n]); + if (PCI_MAP_IS64BITMEM(p_type)) { #if defined LONG64 || defined WORD64 - if (PCI_MAP_IS64BITMEM(p_type)) - pciWriteLong(tag,PCI_CMD_BASE_REG + (res_n + 1) * sizeof(CARD32), - (CARD32)(*p_base >> 32)); + ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1] = + (CARD32)(*p_base >> 32); + pciWriteLong(tag, PCI_CMD_BASE_REG + (res_n + 1) * sizeof(CARD32), + ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1]); +#else + ((CARD32 *)(&(pcp->pci_base0)))[res_n + 1] = 0; + pciWriteLong(tag, PCI_CMD_BASE_REG + (res_n + 1) * sizeof(CARD32), + 0); #endif + } } else { - CARD32 val = pciReadLong(tag,PCI_CMD_BIOS_REG) & 0x01; - pciWriteLong(tag,PCI_CMD_BIOS_REG,(CARD32)(*p_base) | val); + pvp->biosBase = range.rBegin; + pcp->pci_baserom = (pciReadLong(tag,PCI_CMD_BIOS_REG) & 0x01) | + (CARD32)(*p_base); + pciWriteLong(tag, PCI_CMD_BIOS_REG, pcp->pci_baserom); } /* @@@ fake BIOS allocated resource */ range.type |= ResBios; @@ -1384,8 +1409,7 @@ getValidBIOSBase(PCITAG tag, int num) } pbp = pbp->next; } - xf86ConvertListToHost( - xf86GetPciEntity(pvp->bus,pvp->device,pvp->func), avoid); + pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid); if (pvp->biosBase) { /* try biosBase first */ P_M_RANGE(range, TAG(pvp),pvp->biosBase,biosSize,ResExcMemBlock); @@ -1476,6 +1500,46 @@ printBridgeInfo(PciBusPtr PciBus) xf86PrintResList(3, PciBus->preferred_pmem); } +/* + * This Sun PCI-->PCI bridge must be handled specially since it does + * not report the decoded I/O and MEM ranges in the usual way. + */ +#define APB_IO_ADDRESS_MAP 0xde +#define APB_MEM_ADDRESS_MAP 0xdf + +static void +get_sun_apb_ranges(PciBusPtr PciBus, pciConfigPtr pcrp) +{ + unsigned char iomap, memmap; + resRange range; + int i; + + iomap = pciReadByte(pcrp->tag, APB_IO_ADDRESS_MAP); + memmap = pciReadByte(pcrp->tag, APB_MEM_ADDRESS_MAP); + + /* 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); + } + } + } + + /* 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); + } + } + } +} + PciBusPtr xf86GetPciBridgeInfo(const pciConfigPtr *pciInfo) { @@ -1519,7 +1583,14 @@ xf86GetPciBridgeInfo(const pciConfigPtr *pciInfo) PciBus->subclass = sub_class; PciBus->interface = pcrp->pci_prog_if; PciBus->brcontrol = pcrp->pci_bridge_control; - if (pcrp->pci_command & PCI_CMD_IO_ENABLE) { + if (pcrp->pci_vendor == PCI_VENDOR_SUN && + pcrp->pci_device == 0x5000) { + get_sun_apb_ranges(PciBus, pcrp); + break; + } + if ((pcrp->pci_command & PCI_CMD_IO_ENABLE) && + (pcrp->pci_upper_io_base || pcrp->pci_io_base || + pcrp->pci_upper_io_limit || pcrp->pci_io_limit)) { base = (pcrp->pci_upper_io_base << 16) | ((pcrp->pci_io_base & 0xf0u) << 8); limit = (pcrp->pci_upper_io_limit << 16) | @@ -1545,7 +1616,14 @@ xf86GetPciBridgeInfo(const pciConfigPtr *pciInfo) PciBus->preferred_io, &range, -1); } } - if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) { + if (pcrp->pci_command & PCI_CMD_MEM_ENABLE) { + /* + * The P2P spec requires these next two, but some bridges + * don't comply. Err on the side of caution, making the not + * so bold assumption that no bridge would ever re-route the + * bottom megabyte. + */ + if (pcrp->pci_mem_base || pcrp->pci_mem_limit) { base = pcrp->pci_mem_base & 0xfff0u; limit = pcrp->pci_mem_limit & 0xfff0u; if (base <= limit) { @@ -1555,6 +1633,12 @@ xf86GetPciBridgeInfo(const pciConfigPtr *pciInfo) PciBus->preferred_mem = xf86AddResToList(NULL, &range, -1); } + } + + if (pcrp->pci_prefetch_mem_base || + pcrp->pci_prefetch_mem_limit || + pcrp->pci_prefetch_upper_mem_base || + pcrp->pci_prefetch_upper_mem_limit) { base = pcrp->pci_prefetch_mem_base & 0xfff0u; limit = pcrp->pci_prefetch_mem_limit & 0xfff0u; #if defined(LONG64) || defined(WORD64) @@ -1568,6 +1652,7 @@ xf86GetPciBridgeInfo(const pciConfigPtr *pciInfo) PciBus->preferred_pmem = xf86AddResToList(NULL, &range, -1); } + } } break; case PCI_SUBCLASS_BRIDGE_ISA: @@ -1864,8 +1949,7 @@ ValidatePci(void) if (res_m_io == NULL) res_m_io = xf86DupResList(ResRange); - xf86ConvertListToHost( - xf86GetPciEntity(pvp->bus,pvp->device,pvp->func), avoid); + pciConvertListToHost(pvp->bus,pvp->device,pvp->func, avoid); #ifdef DEBUG xf86MsgVerb(X_INFO, 3,"avoid:\n"); @@ -2790,11 +2874,9 @@ pciTestMultiDeviceCard(int bus, int dev, int func, PCITAG** pTag) return j; } -void -pciConvertRange2Host(int entityIndex, resRange *pRange) +static void +pciTagConvertRange2Host(PCITAG tag, resRange *pRange) { - PCITAG tag = TAG(xf86GetPciInfoForEntity(entityIndex)); - switch(pRange->type & ResPhysMask) { case ResMem: switch(pRange->type & ResExtMask) { @@ -2827,3 +2909,21 @@ pciConvertRange2Host(int entityIndex, resRange *pRange) } } +static void +pciConvertListToHost(int bus, int dev, int func, resPtr list) +{ + PCITAG tag = pciTag(bus,dev,func); + while (list) { + pciTagConvertRange2Host(tag, &list->val); + list = list->next; + } +} + + +void +pciConvertRange2Host(int entityIndex, resRange *pRange) +{ + PCITAG tag = TAG(xf86GetPciInfoForEntity(entityIndex)); + pciTagConvertRange2Host(tag, pRange); +} + |