pci.c

来自「适合KS8695X」· C语言 代码 · 共 903 行 · 第 1/2 页

C
903
字号
/*
 * 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>

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);
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
#endif


static int numbus;
static int hostbridges = 1;
static unsigned long pciMinMemReg = ~0;


void
scan_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 CARD32
readPciCfg1(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 void
writePciCfg1(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 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);
    P_printf("reading: 0x%x from 0x%x\n",val,reg);
    return val;
}

static void
writePciCfg2(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);
}
#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;

    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 + =
减小字号Ctrl + -
显示快捷键?