summaryrefslogtreecommitdiffstats
path: root/tools/ddcprobe/int10/i10_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ddcprobe/int10/i10_pci.c')
-rw-r--r--tools/ddcprobe/int10/i10_pci.c866
1 files changed, 866 insertions, 0 deletions
diff --git a/tools/ddcprobe/int10/i10_pci.c b/tools/ddcprobe/int10/i10_pci.c
new file mode 100644
index 000000000..387cebb65
--- /dev/null
+++ b/tools/ddcprobe/int10/i10_pci.c
@@ -0,0 +1,866 @@
+/*
+ * Copyright 1999 Egbert Eich
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <fcntl.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#if defined (__alpha__) || defined (__ia64__)
+#include <sys/io.h>
+#endif
+#include "AsmMacros.h"
+
+#include "pci.h"
+
+#define RESORT 1
+#define FIX_ROM 0
+
+/*
+ * I'm rather simple mindend - therefore I do a poor man's
+ * pci scan without all the fancy stuff that is done in
+ * scanpci. However that's all we need.
+ */
+
+PciStructPtr PciStruct = NULL;
+PciBusPtr PciBuses = NULL;
+PciStructPtr CurrentPci = NULL;
+PciStructPtr PciList = NULL;
+int pciMaxBus = 0;
+
+static CARD32 PciCfg1Addr;
+
+static void readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func,
+ CARD32 *reg);
+static int checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func);
+static int checkSlotCfg2(CARD32 bus, int dev);
+static void readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg);
+static CARD8 interpretConfigSpace(CARD32 *reg, int busidx,
+ CARD8 dev, CARD8 func);
+static CARD32 findBIOSMap(PciStructPtr pciP, CARD32 *biosSize);
+static void restoreMem(PciStructPtr pciP);
+
+
+#ifdef __alpha__
+#define PCI_BUS_FROM_TAG(tag) (((tag) & 0x00ff0000) >> 16)
+#define PCI_DFN_FROM_TAG(tag) (((tag) & 0x0000ff00) >> 8)
+
+#include <asm/unistd.h>
+
+CARD32
+axpPciCfgRead(CARD32 tag)
+{
+ int bus, dfn;
+ CARD32 val = 0xffffffff;
+
+ bus = PCI_BUS_FROM_TAG(tag);
+ dfn = PCI_DFN_FROM_TAG(tag);
+
+ syscall(__NR_pciconfig_read, bus, dfn, tag & 0xff, 4, &val);
+ return(val);
+}
+
+void
+axpPciCfgWrite(CARD32 tag, CARD32 val)
+{
+ int bus, dfn;
+
+ bus = PCI_BUS_FROM_TAG(tag);
+ dfn = PCI_DFN_FROM_TAG(tag);
+
+ syscall(__NR_pciconfig_write, bus, dfn, tag & 0xff, 4, &val);
+}
+
+static CARD32 (*readPci)(CARD32 reg) = axpPciCfgRead;
+static void (*writePci)(CARD32 reg, CARD32 val) = axpPciCfgWrite;
+#else
+static CARD32 readPciCfg1(CARD32 reg);
+static void writePciCfg1(CARD32 reg, CARD32 val);
+#ifndef __ia64__
+static CARD32 readPciCfg2(CARD32 reg);
+static void writePciCfg2(CARD32 reg, CARD32 val);
+#endif
+
+static CARD32 (*readPci)(CARD32 reg) = readPciCfg1;
+static void (*writePci)(CARD32 reg, CARD32 val) = writePciCfg1;
+#endif
+
+#if defined(__alpha__) || defined(__sparc__)
+#define PCI_EN 0x00000000
+#else
+#define PCI_EN 0x80000000
+#endif
+
+
+static int numbus;
+static int hostbridges = 1;
+static unsigned long pciMinMemReg = ~0;
+
+
+
+void
+scan_pci(int pci_cfg_method)
+{
+ unsigned short configtype;
+
+ CARD32 reg[64];
+ int busidx;
+ CARD8 cardnum;
+ CARD8 func;
+ int idx;
+
+ PciStructPtr pci1;
+ PciBusPtr pci_b1,pci_b2;
+
+ if(pci_cfg_method) {
+ configtype = pci_cfg_method;
+ }
+ else {
+#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__)
+ configtype = 1;
+#else
+ CARD8 tmp1, tmp2;
+ CARD32 tmp32_1, tmp32_2;
+ outb(PCI_MODE2_ENABLE_REG, 0x00);
+ outb(PCI_MODE2_FORWARD_REG, 0x00);
+ tmp1 = inb(PCI_MODE2_ENABLE_REG);
+ tmp2 = inb(PCI_MODE2_FORWARD_REG);
+ if ((tmp1 == 0x00) && (tmp2 == 0x00)) {
+ configtype = 2;
+ readPci = readPciCfg2;
+ writePci = writePciCfg2;
+ } else {
+ tmp32_1 = inl(PCI_MODE1_ADDRESS_REG);
+ outl(PCI_MODE1_ADDRESS_REG, PCI_EN);
+ tmp32_2 = inl(PCI_MODE1_ADDRESS_REG);
+ outl(PCI_MODE1_ADDRESS_REG, tmp32_1);
+ if (tmp32_2 == PCI_EN) {
+ configtype = 1;
+ } else {
+ return;
+ }
+ }
+#endif
+ }
+
+ if (configtype == 1) {
+ busidx = 0;
+ numbus = 1;
+ idx = 0;
+ do {
+ for (cardnum = 0; cardnum < MAX_DEV_PER_VENDOR_CFG1; cardnum++) {
+ func = 0;
+ do {
+ /* loop over the different functions, if present */
+ if (!checkSlotCfg1(busidx,cardnum,func)) {
+ if (!func)
+ break;
+ else {
+ func++;
+ continue;
+ }
+ }
+ readConfigSpaceCfg1(busidx,cardnum,func,reg);
+
+ func = interpretConfigSpace(reg,busidx,
+ cardnum,func);
+
+ if (++idx >= MAX_PCI_DEVICES)
+ break;
+ } while (func < 8);
+ if (idx >= MAX_PCI_DEVICES)
+ break;
+ }
+ if (idx >= MAX_PCI_DEVICES)
+ break;
+ } while (++busidx < PCI_MAXBUS);
+#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__)
+ /* don't use outl() ;-) */
+#else
+ outl(PCI_MODE1_ADDRESS_REG, 0);
+#endif
+ } else {
+ int slot;
+
+ busidx = 0;
+ numbus = 1;
+ idx = 0;
+ do {
+ for (slot=0xc0; slot<0xd0; slot++) {
+ if (!checkSlotCfg2(busidx,slot))
+ break;
+ readConfigSpaceCfg2(busidx,slot,reg);
+
+ interpretConfigSpace(reg,busidx,
+ slot,0);
+ if (++idx >= MAX_PCI_DEVICES)
+ break;
+ }
+ if (idx >= MAX_PCI_DEVICES)
+ break;
+ } while (++busidx < PCI_MAXBUS);
+ }
+
+
+ pciMaxBus = numbus - 1;
+
+ /* link buses */
+ pci_b1 = PciBuses;
+ while (pci_b1) {
+ pci_b2 = PciBuses;
+ pci_b1->pBus = NULL;
+ while (pci_b2) {
+ if (pci_b1->primary == pci_b2->secondary)
+ pci_b1->pBus = pci_b2;
+ pci_b2 = pci_b2->next;
+ }
+ pci_b1 = pci_b1->next;
+ }
+ pci1 = PciStruct;
+ while (pci1) {
+ pci_b2 = PciBuses;
+ pci1->pBus = NULL;
+ while (pci_b2) {
+ if (pci1->bus == pci_b2->secondary)
+ pci1->pBus = pci_b2;
+ pci_b2 = pci_b2->next;
+ }
+ pci1 = pci1->next;
+ }
+ if (RESORT) {
+ PciStructPtr tmp = PciStruct, tmp1;
+ PciStruct = NULL;
+ while (tmp) {
+ tmp1 = tmp->next;
+ tmp->next = PciStruct;
+ PciStruct = tmp;
+ tmp = tmp1;
+ }
+ }
+ PciList = CurrentPci = PciStruct;
+}
+
+#ifndef __alpha__
+static CARD32
+readPciCfg1(CARD32 reg)
+{
+ CARD32 val;
+
+ outl(PCI_MODE1_ADDRESS_REG, reg);
+ val = inl(PCI_MODE1_DATA_REG);
+ outl(PCI_MODE1_ADDRESS_REG, 0);
+ return val;
+}
+
+static void
+writePciCfg1(CARD32 reg, CARD32 val)
+{
+ outl(PCI_MODE1_ADDRESS_REG, reg);
+ outl(PCI_MODE1_DATA_REG,val);
+ outl(PCI_MODE1_ADDRESS_REG, 0);
+}
+
+#ifndef __ia64__
+static CARD32
+readPciCfg2(CARD32 reg)
+{
+ CARD32 val;
+ CARD8 bus = (reg >> 16) & 0xff;
+ CARD8 dev = (reg >> 11) & 0x1f;
+ CARD8 num = reg & 0xff;
+
+ outb(PCI_MODE2_ENABLE_REG, 0xF1);
+ outb(PCI_MODE2_FORWARD_REG, bus);
+ val = inl((dev << 8) + num);
+ outb(PCI_MODE2_ENABLE_REG, 0x00);
+ return val;
+}
+
+static void
+writePciCfg2(CARD32 reg, CARD32 val)
+{
+ CARD8 bus = (reg >> 16) & 0xff;
+ CARD8 dev = (reg >> 11) & 0x1f;
+ CARD8 num = reg & 0xff;
+
+ outb(PCI_MODE2_ENABLE_REG, 0xF1);
+ outb(PCI_MODE2_FORWARD_REG, bus);
+ outl((dev << 8) + num,val);
+ outb(PCI_MODE2_ENABLE_REG, 0x00);
+}
+#endif
+#endif
+
+void
+pciVideoDisable(void)
+{
+ /* disable VGA routing on bridges */
+ PciBusPtr pbp = PciBuses;
+ PciStructPtr pcp = PciStruct;
+
+ while (pbp) {
+ writePci(pbp->Slot.l | 0x3c, pbp->bctl & ~(CARD32)(8<<16));
+ pbp = pbp->next;
+ }
+ /* disable display devices */
+ while (pcp) {
+ writePci(pcp->Slot.l | 0x04, pcp->cmd_st & ~(CARD32)3);
+ writePci(pcp->Slot.l | 0x30, pcp->RomBase & ~(CARD32)1);
+ pcp = pcp->next;
+ }
+}
+
+void
+pciVideoRestore(void)
+{
+ /* disable VGA routing on bridges */
+ PciBusPtr pbp = PciBuses;
+ PciStructPtr pcp = PciStruct;
+
+ while (pbp) {
+ writePci(pbp->Slot.l | 0x3c, pbp->bctl);
+ pbp = pbp->next;
+ }
+ /* disable display devices */
+ while (pcp) {
+ writePci(pcp->Slot.l | 0x04, pcp->cmd_st);
+ writePci(pcp->Slot.l | 0x30, pcp->RomBase);
+ pcp = pcp->next;
+ }
+}
+
+void
+EnableCurrent()
+{
+ PciBusPtr pbp;
+ PciStructPtr pcp = CurrentPci;
+
+ pciVideoDisable();
+
+ pbp = pcp->pBus;
+ while (pbp) { /* enable bridges */
+ writePci(pbp->Slot.l | 0x3c, pbp->bctl | (CARD32)(8<<16));
+ pbp = pbp->pBus;
+ }
+ writePci(pcp->Slot.l | 0x04, pcp->cmd_st | (CARD32)3);
+ writePci(pcp->Slot.l | 0x30, pcp->RomBase | (CARD32)1);
+}
+
+CARD8
+PciRead8(int offset, CARD32 Slot)
+{
+ int shift = offset & 0x3;
+ offset = offset & 0xFC;
+ return ((readPci(Slot | offset) >> (shift << 3)) & 0xff);
+}
+
+CARD16
+PciRead16(int offset, CARD32 Slot)
+{
+ int shift = offset & 0x2;
+ offset = offset & 0xFC;
+ return ((readPci(Slot | offset) >> (shift << 3)) & 0xffff);
+}
+
+CARD32
+PciRead32(int offset, CARD32 Slot)
+{
+ offset = offset & 0xFC;
+ return (readPci(Slot | offset));
+}
+
+void
+PciWrite8(int offset, CARD8 byte, CARD32 Slot)
+{
+ CARD32 val;
+ int shift = offset & 0x3;
+ offset = offset & 0xFC;
+ val = readPci(Slot | offset);
+ val &= ~(CARD32)(0xff << (shift << 3));
+ val |= byte << (shift << 3);
+ writePci(Slot | offset, val);
+}
+
+void
+PciWrite16(int offset, CARD16 word, CARD32 Slot)
+{
+ CARD32 val;
+ int shift = offset & 0x2;
+ offset = offset & 0xFC;
+ val = readPci(Slot | offset);
+ val &= ~(CARD32)(0xffff << (shift << 3));
+ val |= word << (shift << 3);
+ writePci(Slot | offset, val);
+}
+
+void
+PciWrite32(int offset, CARD32 lg, CARD32 Slot)
+{
+ offset = offset & 0xFC;
+ writePci(Slot | offset, lg);
+}
+
+int
+mapPciRom(PciStructPtr pciP)
+{
+ unsigned long RomBase = 0;
+ int mem_fd;
+ unsigned char *mem, *ptr;
+ unsigned char *scratch = NULL;
+ int length = 0;
+ CARD32 biosSize = 0x1000000;
+ CARD32 enablePci = 0; /* to keep gcc happy */
+
+ if (!pciP)
+ pciP = CurrentPci;
+
+ if (FIX_ROM) {
+ RomBase = findBIOSMap(pciP, &biosSize);
+ if (!RomBase) {
+ RomBase = pciP->RomBase & ~(CARD32)0xFF;
+ }
+ } else {
+ RomBase = pciP->RomBase & ~(CARD32)0xFF;
+ if (~RomBase + 1 < biosSize || !RomBase)
+ RomBase = findBIOSMap(pciP, &biosSize);
+ }
+
+ if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
+ perror("opening memory");
+ restoreMem(pciP);
+ return (0);
+ }
+
+ PciWrite32(0x30,RomBase | 1,pciP->Slot.l);
+
+#ifdef __alpha__
+ mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
+ MAP_SHARED, mem_fd, RomBase | _bus_base());
+#else
+ mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
+ MAP_SHARED, mem_fd, RomBase);
+#endif
+ if (pciP != CurrentPci) {
+ enablePci = PciRead32(0x4,pciP->Slot.l);
+ PciWrite32(0x4,enablePci | 0x2,pciP->Slot.l);
+ }
+
+ while ( *ptr == 0x55 && *(ptr+1) == 0xAA) {
+ unsigned short data_off = *(ptr+0x18) | (*(ptr+0x19)<< 8);
+ unsigned char *data = ptr + data_off;
+ unsigned char type;
+ int i;
+
+ if (*data!='P' || *(data+1)!='C' || *(data+2)!='I' || *(data+3)!='R') {
+ break;
+ }
+ type = *(data + 0x14);
+
+ if (type != 0) { /* not PC-AT image: find next one */
+ unsigned int image_length;
+ unsigned char indicator = *(data + 0x15);
+ if (indicator & 0x80) /* last image */
+ break;
+ image_length = (*(data + 0x10)
+ | (*(data + 0x11) << 8)) << 9;
+ ptr = ptr + image_length;
+ continue;
+ }
+ /* OK, we have a PC Image */
+ length = (*(ptr + 2) << 9);
+ scratch = (unsigned char *)malloc(length);
+ /* don't use memcpy() here: Reading from bus! */
+ for (i=0;i<length;i++)
+ *(scratch + i)=*(ptr + i);
+ break;
+ }
+
+ if (pciP != CurrentPci)
+ PciWrite32(0x4,enablePci,pciP->Slot.l);
+
+ /* unmap/close/disable PCI bios mem */
+ munmap(mem, biosSize);
+ close(mem_fd);
+ /* disable and restore mapping */
+ writePci(pciP->Slot.l | 0x30, pciP->RomBase & ~(CARD32)1);
+
+ if (scratch && length) {
+ memcpy((unsigned char *)V_BIOS, scratch, length);
+ free(scratch);
+ }
+
+ restoreMem(pciP);
+ return length;
+}
+
+CARD32
+findPci(CARD16 slotBX)
+{
+ CARD32 slot = slotBX << 8;
+
+ if (slot == (CurrentPci->Slot.l & ~PCI_EN))
+ return (CurrentPci->Slot.l | PCI_EN);
+ else {
+#if !SHOW_ALL_DEV
+ PciBusPtr pBus = CurrentPci->pBus;
+ while (pBus) {
+ if (slot == (pBus->Slot.l & ~PCI_EN))
+ return pBus->Slot.l | PCI_EN;
+ pBus = pBus->next;
+ }
+#else
+ PciStructPtr pPci = PciStruct;
+ while (pPci) {
+ if (slot == (pPci->Slot.l & ~PCI_EN))
+ return pPci->Slot.l | PCI_EN;
+ pPci = pPci->next;
+ }
+#endif
+ }
+ return 0;
+}
+
+CARD16
+pciSlotBX(PciStructPtr pPci)
+{
+ return (CARD16)((pPci->Slot.l >> 8) & 0xFFFF);
+}
+
+PciStructPtr
+findPciDevice(CARD16 vendorID, CARD16 deviceID, char n)
+{
+ PciStructPtr pPci = CurrentPci;
+ n++;
+
+ while (pPci) {
+ if ((pPci->VendorID == vendorID) && (pPci->DeviceID == deviceID)) {
+ if (!(--n)) break;
+ }
+ pPci = pPci->next;
+ }
+ return pPci;
+}
+
+PciStructPtr
+findPciClass(CARD8 intf, CARD8 subClass, CARD16 class, char n)
+{
+ PciStructPtr pPci = CurrentPci;
+ n++;
+
+ while (pPci) {
+ if ((pPci->Interface == intf) && (pPci->SubClass == subClass)
+ && (pPci->BaseClass == class)) {
+ if (!(--n)) break;
+ }
+ pPci = pPci->next;
+ }
+ return pPci;
+}
+
+static void
+readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func, CARD32 *reg)
+{
+ CARD32 config_cmd = PCI_EN | (bus<<16) |
+ (dev<<11) | (func<<8);
+ int i;
+
+ for (i = 0; i<64;i+=4) {
+#ifdef __alpha__
+ reg[i] = axpPciCfgRead(config_cmd | i);
+#else
+ outl(PCI_MODE1_ADDRESS_REG, config_cmd | i);
+ reg[i] = inl(PCI_MODE1_DATA_REG);
+#endif
+
+ }
+}
+
+static int
+checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func)
+{
+ CARD32 config_cmd = PCI_EN | (bus<<16) |
+ (dev<<11) | (func<<8);
+ CARD32 reg;
+#ifdef __alpha__
+ reg = axpPciCfgRead(config_cmd);
+#else
+ outl(PCI_MODE1_ADDRESS_REG, config_cmd);
+ reg = inl(PCI_MODE1_DATA_REG);
+#endif
+ if (reg != 0xFFFFFFFF)
+ return 1;
+ else
+ return 0;
+}
+
+static int
+checkSlotCfg2(CARD32 bus, int dev)
+{
+ CARD32 val;
+
+ outb(PCI_MODE2_ENABLE_REG, 0xF1);
+ outb(PCI_MODE2_FORWARD_REG, bus);
+ val = inl(dev << 8);
+ outb(PCI_MODE2_FORWARD_REG, 0x00);
+ outb(PCI_MODE2_ENABLE_REG, 0x00);
+ if (val == 0xFFFFFFFF)
+ return 0;
+ if (val == 0xF0F0F0F0)
+ return 0;
+ return 1;
+}
+
+static void
+readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg)
+{
+ int i;
+
+ outb(PCI_MODE2_ENABLE_REG, 0xF1);
+ outb(PCI_MODE2_FORWARD_REG, bus);
+ for (i = 0; i<64;i+=4) {
+ reg[i] = inl((dev << 8) + i);
+ }
+ outb(PCI_MODE2_ENABLE_REG, 0x00);
+}
+
+static CARD8
+interpretConfigSpace(CARD32 *reg, int busidx, CARD8 dev, CARD8 func)
+{
+ CARD32 config_cmd;
+ CARD16 vendor, device;
+ CARD8 baseclass, subclass;
+ CARD8 primary, secondary;
+ CARD8 header, interface;
+ int i;
+
+ config_cmd = PCI_EN | busidx<<16 |
+ (dev<<11) | (func<<8);
+
+ for (i = 0x10; i < 0x28; i+=4) {
+ if (IS_MEM32(reg[i]))
+ if ((reg[i] & 0xFFFFFFF0) < pciMinMemReg)
+ pciMinMemReg = (reg[i] & 0xFFFFFFF0);
+#ifdef __alpha__
+ if (IS_MEM64(reg[i])) {
+ unsigned long addr = reg[i] |
+ (unsigned long)(reg[i+4]) << 32;
+ if ((addr & ~0xfL) < pciMinMemReg)
+ pciMinMemReg = (addr & ~0xfL);
+ i+=4;
+ }
+#endif
+ }
+ vendor = reg[0] & 0xFFFF;
+ device = reg[0] >> 16;
+ baseclass = reg[8] >> 24;
+ subclass = (reg[8] >> 16) & 0xFF;
+ interface = (reg[8] >> 8) & 0xFF;
+
+ header = (reg[0x0c] >> 16) & 0xff;
+ if (BRIDGE_CLASS(baseclass)) {
+ if (BRIDGE_PCI_CLASS(subclass)) {
+ PciBusPtr pbp = malloc(sizeof(PciBusRec));
+ primary = reg[0x18] & 0xFF;
+ secondary = (reg[0x18] >> 8) & 0xFF;
+ pbp->bctl = reg[0x3c];
+ pbp->primary = primary;
+ pbp->secondary = secondary;
+ pbp->Slot.l = config_cmd;
+ pbp->next = PciBuses;
+ PciBuses = pbp;
+ numbus++;
+ } else if (BRIDGE_HOST_CLASS(subclass)
+ && (hostbridges++ > 1)) {
+ numbus++;
+ }
+ } else if (VIDEO_CLASS(baseclass,subclass)) {
+ PciStructPtr pcp = malloc(sizeof(PciStructRec));
+ pcp->RomBase = reg[0x30];
+ pcp->cmd_st = reg[4];
+ pcp->active = (reg[4] & 0x03) == 3 ? 1 : 0;
+ pcp->VendorID = vendor;
+ pcp->DeviceID = device;
+ pcp->Interface = interface;
+ pcp->BaseClass = baseclass;
+ pcp->SubClass = subclass;
+ pcp->Slot.l = config_cmd;
+ pcp->bus = busidx;
+ pcp->dev = dev;
+ pcp->func = func;
+ pcp->next = PciStruct;
+ PciStruct = pcp;
+ }
+ if ((func == 0)
+ && ((header & PCI_MULTIFUNC_DEV) == 0))
+ func = 8;
+ else
+ func++;
+ return func;
+}
+
+static CARD32 remapMEM_val;
+static int remapMEM_num;
+
+static int /* map it on some other video device */
+remapMem(PciStructPtr pciP, int num, CARD32 size)
+{
+ PciStructPtr pciPtr = PciStruct;
+ int i;
+ CARD32 org;
+ CARD32 val;
+ CARD32 size_n;
+
+ org = PciRead32(num + 0x10,pciP->Slot.l);
+
+ while (pciPtr) {
+ for (i = 0; i < 20; i=i+4) {
+
+ val = PciRead32(i + 0x10,pciPtr->Slot.l);
+ /* don't map it on itself */
+ if ((org & 0xfffffff0) == (val & 0xfffffff0))
+ continue;
+ if (val && !(val & 1))
+ PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
+ else
+ continue;
+ size_n = PciRead32(i + 0x10,pciPtr->Slot.l);
+ PciWrite32(i + 0x10,val,pciPtr->Slot.l);
+ size_n = ~(CARD32)(size_n & 0xfffffff0) + 1;
+
+ if (size_n >= size) {
+ PciWrite32(num + 0x10,val,pciP->Slot.l);
+ return 1;
+ }
+ }
+ pciPtr = pciPtr->next;
+ }
+ /* last resort: try to go below lowest PCI mem address */
+ val = ((pciMinMemReg & ~(CARD32)(size - 1)) - size);
+ if (val > 0x7fffffff) {
+ PciWrite32(num + 0x10,val, pciP->Slot.l);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+restoreMem(PciStructPtr pciP)
+{
+ if (remapMEM_val == 0) return;
+ PciWrite32(remapMEM_num + 0x10,remapMEM_val,pciP->Slot.l);
+ return;
+}
+
+static CARD32
+findBIOSMap(PciStructPtr pciP, CARD32 *biosSize)
+{
+ PciStructPtr pciPtr = PciStruct;
+ int i;
+ CARD32 val;
+ CARD32 size = 4*1024; /* should be fixed: size seems _really_ to be undefined below */
+
+ PciWrite32(0x30,0xffffffff,pciP->Slot.l);
+ *biosSize = PciRead32(0x30,pciP->Slot.l);
+ PciWrite32(0x30,pciP->RomBase,pciP->Slot.l);
+ *biosSize = ~(*biosSize & 0xFFFFFF00) + 1;
+ if (*biosSize > (1024 * 1024 * 16)) {
+ *biosSize = 1024 * 1024 * 16;
+ }
+ while (pciPtr) {
+ if (pciPtr->bus != pciP->bus) {
+ pciPtr = pciPtr->next;
+ continue;
+ }
+ for (i = 0; i < 20; i=i+4) {
+
+ val = PciRead32(i + 0x10,pciPtr->Slot.l);
+ if (!(val & 1))
+
+ PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
+ else
+ continue;
+ size = PciRead32(i + 0x10,pciPtr->Slot.l);
+ PciWrite32(i + 0x10,val,pciPtr->Slot.l);
+ size = ~(CARD32)(size & 0xFFFFFFF0) + 1;
+ if (size >= *biosSize) {
+ if (pciP == pciPtr) { /* if same device remap ram*/
+ if (!(remapMem(pciP,i,size)))
+ continue;
+ remapMEM_val = val;
+ remapMEM_num = i;
+ } else {
+ remapMEM_val = 0;
+ }
+ return val & 0xFFFFFF00;
+ }
+ }
+ pciPtr = pciPtr->next;
+ }
+ remapMEM_val = 0;
+ /* very last resort */
+ if (pciP->bus == 0 && (pciMinMemReg > *biosSize))
+ return (pciMinMemReg - size) & ~(size - 1);
+
+ return 0;
+}
+
+int
+cfg1out(CARD16 addr, CARD32 val)
+{
+ if (addr == 0xCF8) {
+ PciCfg1Addr = val;
+ return 1;
+ } else if (addr == 0xCFC) {
+ writePci(PciCfg1Addr, val);
+ return 1;
+ }
+ return 0;
+}
+
+int
+cfg1in(CARD16 addr, CARD32 *val)
+{
+ if (addr == 0xCF8) {
+ *val = PciCfg1Addr;
+ return 1;
+ } else if (addr == 0xCFC) {
+ *val = readPci(PciCfg1Addr);
+ return 1;
+ }
+ return 0;
+}
+
+PciStructPtr
+findPciByIDs(int bus, int dev, int func)
+{
+ PciStructPtr pciP = PciList;
+
+ while (pciP) {
+ if (pciP->bus == (unsigned) bus && pciP->dev == (unsigned) dev && pciP->func == (unsigned) func)
+ return pciP;
+ pciP = pciP->next;
+ }
+ return NULL;
+}