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.c168
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);
+}
+