ports/x11-servers/xorg-server/files/patch-freebsdPci.c
Marius Strobl 5be6d0491c Teach xorg-server that FreeBSD >= 700053 supports PCI domains and
how to deal with it. This affects !386 only and is based on the
respective Linux support code.

Approved by:	flz
2007-09-30 11:01:41 +00:00

306 lines
7.6 KiB
C

--- hw/xfree86/os-support/bus/freebsdPci.c.orig Thu Sep 6 02:48:26 2007
+++ hw/xfree86/os-support/bus/freebsdPci.c Sat Sep 29 12:22:56 2007
@@ -109,10 +109,6 @@
#define PCI_CPU(val) (val)
#endif
-
-#define BUS(tag) (((tag)>>16)&0xff)
-#define DFN(tag) (((tag)>>8)&0xff)
-
static int pciFd = -1;
void
@@ -133,9 +129,12 @@
{
struct pci_io io;
int error;
- io.pi_sel.pc_bus = BUS(tag);
- io.pi_sel.pc_dev = DFN(tag) >> 3;
- io.pi_sel.pc_func = DFN(tag) & 7;
+#ifndef INCLUDE_XF86_NO_DOMAIN
+ io.pi_sel.pc_domain = PCI_DOM_FROM_TAG(tag);
+#endif
+ io.pi_sel.pc_bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag));
+ io.pi_sel.pc_dev = PCI_DEV_FROM_TAG(tag);
+ io.pi_sel.pc_func = PCI_FUNC_FROM_TAG(tag);
io.pi_reg = off;
io.pi_width = 4;
error = ioctl(pciFd, PCIOCREAD, &io);
@@ -148,9 +147,12 @@
freebsdPciCfgWrite(PCITAG tag, int off, CARD32 val)
{
struct pci_io io;
- io.pi_sel.pc_bus = BUS(tag);
- io.pi_sel.pc_dev = DFN(tag) >> 3;
- io.pi_sel.pc_func = DFN(tag) & 7;
+#ifndef INCLUDE_XF86_NO_DOMAIN
+ io.pi_sel.pc_domain = PCI_DOM_FROM_TAG(tag);
+#endif
+ io.pi_sel.pc_bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag));
+ io.pi_sel.pc_dev = PCI_DEV_FROM_TAG(tag);
+ io.pi_sel.pc_func = PCI_FUNC_FROM_TAG(tag);
io.pi_reg = off;
io.pi_width = 4;
io.pi_data = PCI_CPU(val);
@@ -164,3 +166,260 @@
val = (val & ~mask) | (bits & mask);
freebsdPciCfgWrite(tag, off, val);
}
+
+#ifndef INCLUDE_XF86_NO_DOMAIN
+
+/* This probably shouldn't be FreeBSD-specific. */
+static pciConfigPtr
+xf86GetPciHostConfigFromTag(PCITAG Tag)
+{
+ int bus = PCI_BUS_FROM_TAG(Tag);
+ pciBusInfo_t *pBusInfo;
+
+ while ((bus < pciNumBuses) && (pBusInfo = pciBusInfo[bus])) {
+ if (bus == pBusInfo->primary_bus)
+ return pBusInfo->bridge;
+ bus = pBusInfo->primary_bus;
+ }
+
+ return NULL; /* Bad data */
+}
+
+/*
+ * This is ugly, but until I can extract this information from the kernel,
+ * it'll have to do. The default I/O space size is 64K, and 4G for memory.
+ * Anything else needs to go in this table. (PowerPC folk take note.)
+ *
+ * Please keep this table in ascending vendor/device order.
+ */
+static const struct pciSizes {
+ unsigned short vendor, device;
+ unsigned long io_size, mem_size;
+} pciControllerSizes[] = {
+ {
+ PCI_VENDOR_SUN, PCI_CHIP_PSYCHO,
+ 1U << 16, 1U << 31
+ },
+ {
+ PCI_VENDOR_SUN, PCI_CHIP_SCHIZO,
+ 1U << 24, 1U << 31 /* ??? */
+ },
+ {
+ PCI_VENDOR_SUN, PCI_CHIP_SABRE,
+ 1U << 24, (unsigned long)(1ULL << 32)
+ },
+ {
+ PCI_VENDOR_SUN, PCI_CHIP_HUMMINGBIRD,
+ 1U << 24, (unsigned long)(1ULL << 32)
+ }
+};
+#define NUM_SIZES (sizeof(pciControllerSizes) / sizeof(pciControllerSizes[0]))
+
+static const struct pciSizes *
+freebsdGetSizesStruct(PCITAG Tag)
+{
+ static const struct pciSizes default_size = {
+ 0, 0, 1U << 16, (unsigned long)(1ULL << 32)
+ };
+ pciConfigPtr pPCI;
+ int i;
+
+ /* Find host bridge */
+ if ((pPCI = xf86GetPciHostConfigFromTag(Tag))) {
+ /* Look up vendor/device */
+ for (i = 0; i < NUM_SIZES; i++) {
+ if ((pPCI->pci_vendor ==
+ pciControllerSizes[i].vendor) &&
+ (pPCI->pci_device ==
+ pciControllerSizes[i].device)) {
+ return & pciControllerSizes[i];
+ }
+ }
+ }
+
+ /* Default to 64KB I/O and 4GB memory. */
+ return & default_size;
+}
+
+static __inline__ unsigned long
+freebsdGetIOSize(PCITAG Tag)
+{
+ const struct pciSizes * const sizes = freebsdGetSizesStruct(Tag);
+ return sizes->io_size;
+}
+
+static __inline__ void
+freebsdGetSizes(PCITAG Tag, unsigned long *io_size, unsigned long *mem_size)
+{
+ const struct pciSizes * const sizes = freebsdGetSizesStruct(Tag);
+
+ *io_size = sizes->io_size;
+ *mem_size = sizes->mem_size;
+}
+
+_X_EXPORT int
+xf86GetPciDomain(PCITAG Tag)
+{
+ return PCI_DOM_FROM_TAG(Tag);
+}
+
+_X_EXPORT pointer
+xf86MapDomainMemory(int ScreenNum, int Flags, PCITAG Tag, ADDRESS Base,
+ unsigned long Size)
+{
+ return xf86MapVidMem(ScreenNum, Flags, Base, Size);
+}
+
+_X_EXPORT IOADDRESS
+xf86MapDomainIO(int ScreenNum, int Flags, PCITAG Tag, IOADDRESS Base,
+ unsigned long Size)
+{
+ return Base;
+}
+
+_X_EXPORT int
+xf86ReadDomainMemory(PCITAG Tag, ADDRESS Base, int Len, unsigned char *Buf)
+{
+ int ret, length, rlength;
+
+ /* Read in 64kB chunks. */
+ ret = 0;
+ while ((length = Len) > 0) {
+ if (length > 0x010000) length = 0x010000;
+ rlength = xf86ReadBIOS(Base, 0, Buf, length);
+ if (rlength < 0) {
+ ret = rlength;
+ break;
+ }
+ ret += rlength;
+ if (rlength < length) break;
+ Base += rlength;
+ Buf += rlength;
+ Len -= rlength;
+ }
+
+ return ret;
+}
+
+resPtr
+xf86BusAccWindowsFromOS(void)
+{
+ pciConfigPtr *ppPCI, pPCI;
+ resPtr pRes = NULL;
+ resRange range;
+ unsigned long io_size, mem_size;
+ int domain;
+
+ if ((ppPCI = xf86scanpci(0))) {
+ for (; (pPCI = *ppPCI); ppPCI++) {
+ if ((pPCI->pci_base_class != PCI_CLASS_BRIDGE) ||
+ (pPCI->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST))
+ continue;
+
+ domain = xf86GetPciDomain(pPCI->tag);
+ freebsdGetSizes(pPCI->tag, &io_size, &mem_size);
+
+ RANGE(range, 0, (ADDRESS)(mem_size - 1),
+ RANGE_TYPE(ResExcMemBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+
+ RANGE(range, 0, (IOADDRESS)(io_size - 1),
+ RANGE_TYPE(ResExcIoBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+
+ if (domain <= 0)
+ break;
+ }
+ }
+
+ return pRes;
+}
+
+resPtr
+xf86PciBusAccWindowsFromOS(void)
+{
+ pciConfigPtr *ppPCI, pPCI;
+ resPtr pRes = NULL;
+ resRange range;
+ unsigned long io_size, mem_size;
+ int domain;
+
+ if ((ppPCI = xf86scanpci(0))) {
+ for (; (pPCI = *ppPCI); ppPCI++) {
+ if ((pPCI->pci_base_class != PCI_CLASS_BRIDGE) ||
+ (pPCI->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST))
+ continue;
+
+ domain = xf86GetPciDomain(pPCI->tag);
+ freebsdGetSizes(pPCI->tag, &io_size, &mem_size);
+
+ RANGE(range, 0, (ADDRESS)(mem_size - 1),
+ RANGE_TYPE(ResExcMemBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+
+ RANGE(range, 0, (IOADDRESS)(io_size - 1),
+ RANGE_TYPE(ResExcIoBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+
+ if (domain <= 0)
+ break;
+ }
+ }
+
+ return pRes;
+}
+
+resPtr
+xf86AccResFromOS(resPtr pRes)
+{
+ pciConfigPtr *ppPCI, pPCI;
+ resRange range;
+ unsigned long io_size, mem_size;
+ int domain;
+
+ if ((ppPCI = xf86scanpci(0))) {
+ for (; (pPCI = *ppPCI); ppPCI++) {
+ if ((pPCI->pci_base_class != PCI_CLASS_BRIDGE) ||
+ (pPCI->pci_sub_class != PCI_SUBCLASS_BRIDGE_HOST))
+ continue;
+
+ domain = xf86GetPciDomain(pPCI->tag);
+ freebsdGetSizes(pPCI->tag, &io_size, &mem_size);
+
+ /*
+ * At minimum, the top and bottom resources must be
+ * claimed, so that resources that are (or appear to
+ * be) unallocated can be relocated.
+ */
+ RANGE(range, 0x00000000u, 0x0009ffffu,
+ RANGE_TYPE(ResExcMemBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+ RANGE(range, 0x000c0000u, 0x000effffu,
+ RANGE_TYPE(ResExcMemBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+ RANGE(range, 0x000f0000u, 0x000fffffu,
+ RANGE_TYPE(ResExcMemBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+
+ RANGE(range, (ADDRESS)(mem_size - 1),
+ (ADDRESS)(mem_size - 1),
+ RANGE_TYPE(ResExcMemBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+
+ RANGE(range, 0x00000000u, 0x00000000u,
+ RANGE_TYPE(ResExcIoBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+ RANGE(range, (IOADDRESS)(io_size - 1),
+ (IOADDRESS)(io_size - 1),
+ RANGE_TYPE(ResExcIoBlock, domain));
+ pRes = xf86AddResToList(pRes, &range, -1);
+
+ if (domain <= 0)
+ break;
+ }
+ }
+
+ return pRes;
+}
+
+#endif /* !INCLUDE_XF86_NO_DOMAIN */