forked from KolibriOS/kolibrios
160 lines
3.5 KiB
C
160 lines
3.5 KiB
C
|
|
||
|
#include "common.h"
|
||
|
#include "pci.h"
|
||
|
|
||
|
|
||
|
int
|
||
|
pciGetBaseSize(int bus, int devfn, int index, Bool destructive, Bool *min)
|
||
|
{
|
||
|
int offset;
|
||
|
CARD32 addr1;
|
||
|
CARD32 addr2;
|
||
|
CARD32 mask1;
|
||
|
CARD32 mask2;
|
||
|
int bits = 0;
|
||
|
|
||
|
/*
|
||
|
* silently ignore bogus index values. Valid values are 0-6. 0-5 are
|
||
|
* the 6 base address registers, and 6 is the ROM base address register.
|
||
|
*/
|
||
|
if (index < 0 || index > 6)
|
||
|
return 0;
|
||
|
|
||
|
if (min)
|
||
|
*min = destructive;
|
||
|
|
||
|
/* Get the PCI offset */
|
||
|
if (index == 6)
|
||
|
offset = PCI_MAP_ROM_REG;
|
||
|
else
|
||
|
offset = PCI_MAP_REG_START + (index << 2);
|
||
|
|
||
|
addr1 = PciRead32(bus, devfn, offset);
|
||
|
/*
|
||
|
* Check if this is the second part of a 64 bit address.
|
||
|
* XXX need to check how endianness affects 64 bit addresses.
|
||
|
*/
|
||
|
if (index > 0 && index < 6) {
|
||
|
addr2 = PciRead32(bus, devfn, offset - 4);
|
||
|
if (PCI_MAP_IS_MEM(addr2) && PCI_MAP_IS64BITMEM(addr2))
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (destructive) {
|
||
|
PciWrite32(bus, devfn, offset, 0xffffffff);
|
||
|
mask1 = PciRead32(bus, devfn, offset);
|
||
|
PciWrite32(bus, devfn, offset, addr1);
|
||
|
} else {
|
||
|
mask1 = addr1;
|
||
|
}
|
||
|
|
||
|
/* Check if this is the first part of a 64 bit address. */
|
||
|
if (index < 5 && PCI_MAP_IS_MEM(mask1) && PCI_MAP_IS64BITMEM(mask1))
|
||
|
{
|
||
|
if (PCIGETMEMORY(mask1) == 0)
|
||
|
{
|
||
|
addr2 = PciRead32(bus, devfn, offset + 4);
|
||
|
if (destructive)
|
||
|
{
|
||
|
PciWrite32(bus, devfn, offset + 4, 0xffffffff);
|
||
|
mask2 = PciRead32(bus, devfn, offset + 4);
|
||
|
PciWrite32(bus, devfn, offset + 4, addr2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mask2 = addr2;
|
||
|
}
|
||
|
if (mask2 == 0)
|
||
|
return 0;
|
||
|
bits = 32;
|
||
|
while ((mask2 & 1) == 0)
|
||
|
{
|
||
|
bits++;
|
||
|
mask2 >>= 1;
|
||
|
}
|
||
|
if (bits > 32)
|
||
|
return bits;
|
||
|
}
|
||
|
}
|
||
|
if (index < 6)
|
||
|
if (PCI_MAP_IS_MEM(mask1))
|
||
|
mask1 = PCIGETMEMORY(mask1);
|
||
|
else
|
||
|
mask1 = PCIGETIO(mask1);
|
||
|
else
|
||
|
mask1 = PCIGETROM(mask1);
|
||
|
if (mask1 == 0)
|
||
|
return 0;
|
||
|
bits = 0;
|
||
|
while ((mask1 & 1) == 0) {
|
||
|
bits++;
|
||
|
mask1 >>= 1;
|
||
|
}
|
||
|
/* I/O maps can be no larger than 8 bits */
|
||
|
|
||
|
if ((index < 6) && PCI_MAP_IS_IO(addr1) && bits > 8)
|
||
|
bits = 8;
|
||
|
/* ROM maps can be no larger than 24 bits */
|
||
|
if (index == 6 && bits > 24)
|
||
|
bits = 24;
|
||
|
return bits;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
int chipRev;
|
||
|
int subsysVendor;
|
||
|
int subsysCard;
|
||
|
int bus;
|
||
|
int devfn;
|
||
|
// int func;
|
||
|
int class;
|
||
|
int subclass;
|
||
|
int interface;
|
||
|
memType memBase[6];
|
||
|
memType ioBase[6];
|
||
|
int size[6];
|
||
|
unsigned char type[6];
|
||
|
memType biosBase;
|
||
|
int biosSize;
|
||
|
*/
|
||
|
|
||
|
int pciGetInfo(pciVideoPtr pci)
|
||
|
{
|
||
|
CARD32 reg0,reg2C;
|
||
|
int i;
|
||
|
|
||
|
reg0 = PciRead32(pci->bus,pci->devfn, 0);
|
||
|
reg2C = PciRead32(pci->bus,pci->devfn, 0x2C);
|
||
|
|
||
|
pci->vendor = reg0 & 0xFFFF;
|
||
|
pci->devtype = reg0 >> 16;
|
||
|
|
||
|
pci->subsysVendor = reg2C & 0xFFFF;
|
||
|
pci->subsysCard = reg2C >> 16;
|
||
|
|
||
|
for (i = 0; i < 6; i++)
|
||
|
{
|
||
|
CARD32 base;
|
||
|
|
||
|
base = PciRead32(pci->bus,pci->devfn, PCI_MAP_REG_START + (i << 2));
|
||
|
if(base)
|
||
|
{
|
||
|
if (base & PCI_MAP_IO)
|
||
|
{
|
||
|
pci->ioBase[i] = (memType)PCIGETIO(base);
|
||
|
pci->type[i] = base & PCI_MAP_IO_ATTR_MASK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pci->type[i] = base & PCI_MAP_MEMORY_ATTR_MASK;
|
||
|
pci->memBase[i] = (memType)PCIGETMEMORY(base);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pci->size[i] =
|
||
|
pciGetBaseSize(pci->bus,pci->devfn, i, TRUE, &pci->validSize);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|