📄 pci.c
字号:
/* * 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 "debug.h"#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"/* * 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;PciStructPtr BootBios = 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>CARD32axpPciCfgRead(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);}voidaxpPciCfgWrite(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;#elsestatic CARD32 readPciCfg1(CARD32 reg);static void writePciCfg1(CARD32 reg, CARD32 val);static CARD32 readPciCfg2(CARD32 reg);static void writePciCfg2(CARD32 reg, CARD32 val);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#endifstatic int numbus;static int hostbridges = 1;static unsigned long pciMinMemReg = ~0;voidscan_pci(void){ unsigned short configtype; CARD32 reg[64]; int busidx; CARD8 cardnum; CARD8 func; int idx; int i; PciStructPtr pci1; PciBusPtr pci_b1,pci_b2;#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; P_printf("PCI says configuration type 2\n"); } 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; P_printf("PCI says configuration type 1\n"); } else { P_printf("No PCI !\n"); return; } }#endif if (configtype == 1) { P_printf("PCI probing configuration type 1\n"); busidx = 0; numbus = 1; idx = 0; do { P_printf("\nProbing for devices on PCI bus %d:\n", busidx); 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)) break; readConfigSpaceCfg1(busidx,cardnum,func,reg); func = interpretConfigSpace(reg,busidx, cardnum,func); if (idx++ > MAX_PCI_DEVICES) continue; } while (func < 8); } } 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; P_printf("PCI probing configuration type 2\n"); busidx = 0; numbus = 1; idx = 0; do { for (slot=0xc0; slot<0xd0; i++) { if (!checkSlotCfg2(busidx,slot)) break; readConfigSpaceCfg2(busidx,slot,reg); interpretConfigSpace(reg,busidx, slot,0); if (idx++ > MAX_PCI_DEVICES) continue; } } while (++busidx < PCI_MAXBUS); } pciMaxBus = numbus - 1; P_printf("Number of buses in system: %i\n",pciMaxBus + 1); P_printf("Min PCI mem address: 0x%lx\n",pciMinMemReg); /* 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 CARD32readPciCfg1(CARD32 reg){ CARD32 val; outl(PCI_MODE1_ADDRESS_REG, reg); val = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, 0); P_printf("reading: 0x%x from 0x%x\n",val,reg); return val;}static voidwritePciCfg1(CARD32 reg, CARD32 val){ P_printf("writing: 0x%x to 0x%x\n",val,reg); outl(PCI_MODE1_ADDRESS_REG, reg); outl(PCI_MODE1_DATA_REG,val); outl(PCI_MODE1_ADDRESS_REG, 0);}static CARD32readPciCfg2(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); P_printf("reading: 0x%x from 0x%x\n",val,reg); return val;}static voidwritePciCfg2(CARD32 reg, CARD32 val){ CARD8 bus = (reg >> 16) & 0xff; CARD8 dev = (reg >> 11) & 0x1f; CARD8 num = reg & 0xff; P_printf("writing: 0x%x to 0x%x\n",val,reg); outb(PCI_MODE2_ENABLE_REG, 0xF1); outb(PCI_MODE2_FORWARD_REG, bus); outl((dev << 8) + num,val); outb(PCI_MODE2_ENABLE_REG, 0x00);}#endifvoidpciVideoDisable(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; }}voidpciVideoRestore(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; }}voidEnableCurrent(){ 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);}CARD8PciRead8(int offset, CARD32 Slot){ int shift = offset & 0x3; offset = offset & 0xFC; return ((readPci(Slot | offset) >> (shift << 3)) & 0xff);}CARD16PciRead16(int offset, CARD32 Slot){ int shift = offset & 0x2; offset = offset & 0xFC; return ((readPci(Slot | offset) >> (shift << 3)) & 0xffff);}CARD32PciRead32(int offset, CARD32 Slot){ offset = offset & 0xFC; return (readPci(Slot | offset));}voidPciWrite8(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);}voidPciWrite16(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);}voidPciWrite32(int offset, CARD32 lg, CARD32 Slot){ offset = offset & 0xFC; writePci(Slot | offset, lg);}intmapPciRom(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; if (!pciP) pciP = CurrentPci; if (FIX_ROM) { RomBase = findBIOSMap(pciP, &biosSize); if (!RomBase) { fprintf(stderr,"Cannot remap BIOS of %i:%i:%i " "- trying preset address\n",pciP->bus,pciP->dev, pciP->func); RomBase = pciP->RomBase & ~(CARD32)0xFF; } } else { RomBase = pciP->RomBase & ~(CARD32)0xFF; if (~RomBase + 1 < biosSize || !RomBase) RomBase = findBIOSMap(pciP, &biosSize); } P_printf("RomBase: 0x%lx\n",RomBase); 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__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -