- remove trailing white space, trailing empty lines, C++ comments, etc.
- split cmd_boot.c (separate cmd_bdinfo.c and cmd_load.c)
* Patches by Kenneth Johansson, 25 Jun 2003:
- major rework of command structure
(work done mostly by Michal Cendrowski and Joakim Kristiansen)
903 lines
21 KiB
C
903 lines
21 KiB
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>
|
|
|
|
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__
|
|
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);
|
|
}
|
|
|
|
#ifdef PRINT_PCI
|
|
dprint((unsigned long)ptr,0x30);
|
|
#endif
|
|
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);
|
|
P_printf("data segment in BIOS: 0x%x, type: 0x%x ",data_off,type);
|
|
|
|
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;
|
|
P_printf("data image length: 0x%x, ind: 0x%x\n",
|
|
image_length,indicator);
|
|
ptr = ptr + image_length;
|
|
continue;
|
|
}
|
|
/* OK, we have a PC Image */
|
|
length = (*(ptr + 2) << 9);
|
|
P_printf("BIOS length: 0x%x\n",length);
|
|
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) {
|
|
/* fprintf(stderr,"slot: 0x%x bridge: 0x%x\n",slot, pBus->Slot.l); */
|
|
if (slot == (pBus->Slot.l & ~PCI_EN))
|
|
return pBus->Slot.l | PCI_EN;
|
|
pBus = pBus->next;
|
|
}
|
|
#else
|
|
PciStructPtr pPci = PciStruct;
|
|
while (pPci) {
|
|
/*fprintf(stderr,"slot: 0x%x bridge: 0x%x\n",slot, pPci->Slot.l); */
|
|
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
|
|
|
|
#ifdef V86BIOS_DEBUG
|
|
P_printf("0x%lx\n",reg[i]);
|
|
#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);
|
|
#ifdef V86BIOS_DEBUG
|
|
P_printf("0x%lx\n",reg[i]);
|
|
#endif
|
|
}
|
|
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;
|
|
P_printf("bus: %i card: %i func %i reg0: 0x%x ", busidx,dev,func,reg[0]);
|
|
baseclass = reg[8] >> 24;
|
|
subclass = (reg[8] >> 16) & 0xFF;
|
|
interface = (reg[8] >> 8) & 0xFF;
|
|
|
|
header = (reg[0x0c] >> 16) & 0xff;
|
|
P_printf("bc 0x%x, sub 0x%x, if 0x%x, hdr 0x%x\n",
|
|
baseclass,subclass,interface,header);
|
|
if (BRIDGE_CLASS(baseclass)) {
|
|
if (BRIDGE_PCI_CLASS(subclass)) {
|
|
PciBusPtr pbp = malloc(sizeof(PciBusRec));
|
|
P_printf("Pci-Pci Bridge found; ");
|
|
primary = reg[0x18] & 0xFF;
|
|
secondary = (reg[0x18] >> 8) & 0xFF;
|
|
P_printf("primary: 0x%x secondary: 0x%x\n",
|
|
primary,secondary);
|
|
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));
|
|
P_printf("Display adapter found\n");
|
|
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;
|
|
|
|
PciWrite32(0x30,0xffffffff,pciP->Slot.l);
|
|
*biosSize = PciRead32(0x30,pciP->Slot.l);
|
|
P_printf("bios size: 0x%x\n",*biosSize);
|
|
PciWrite32(0x30,pciP->RomBase,pciP->Slot.l);
|
|
*biosSize = ~(*biosSize & 0xFFFFFF00) + 1;
|
|
P_printf("bios size masked: 0x%x\n",*biosSize);
|
|
if (*biosSize > (1024 * 1024 * 16)) {
|
|
*biosSize = 1024 * 1024 * 16;
|
|
P_printf("fixing broken BIOS size: 0x%x\n",*biosSize);
|
|
}
|
|
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;
|
|
#ifdef V86_BIOS_DEBUG
|
|
P_printf("size: 0x%x\n",size);
|
|
#endif
|
|
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;
|
|
}
|
|
|
|
void
|
|
list_pci(void)
|
|
{
|
|
PciStructPtr pci = PciList;
|
|
|
|
while (pci) {
|
|
printf("[0x%x:0x%x:0x%x] vendor: 0x%4.4x dev: 0x%4.4x class: 0x%4.4x"
|
|
" subclass: 0x%4.4x\n",pci->bus,pci->dev,pci->func,
|
|
pci->VendorID,pci->DeviceID,pci->BaseClass,pci->SubClass);
|
|
pci = pci->next;
|
|
}
|
|
}
|
|
|
|
PciStructPtr
|
|
findPciByIDs(int bus, int dev, int func)
|
|
{
|
|
PciStructPtr pciP = PciList;
|
|
|
|
while (pciP) {
|
|
if (pciP->bus == bus && pciP->dev == dev && pciP->func == func)
|
|
return pciP;
|
|
pciP = pciP->next;
|
|
}
|
|
return NULL;
|
|
}
|