Cucumber/Kernel/src/Alentours/PCI.cpp

203 lines
4.7 KiB
C++

#include "Alentours/PCI.h"
#include "Alentours/PCIDB.h"
extern "C" {
#include "Tier0/kstdio.h"
}
using namespace Alentours;
u32 CPCIManager::ConfigRead(u16 Bus, u16 Device, u16 Function, u16 Offset)
{
TPCIConfigAddress Address;
Address.Fields.Zero = 0;
Address.Fields.Register = Offset >> 2;
Address.Fields.Function = Function;
Address.Fields.Device = Device;
Address.Fields.Bus = Bus;
Address.Fields.Reserved = 0;
Address.Fields.Enable = 1;
koutl(PCI_CONFIG_ADDRESS, Address.Value);
return kinl(PCI_CONFIG_DATA);
}
u8 CPCIManager::DevicePresent(u16 Bus, u16 Device)
{
// try to get the VID & PID pair - if all 1's, then no device is present
u32 Value = CPCIManager::ConfigRead(Bus, Device, 0, 0);
return (Value != 0xFFFFFFFF);
}
void CPCIManager::Initialize(void)
{
for (u16 BusID = 0; BusID < 256; BusID++)
{
for (u8 DeviceID = 0; DeviceID < 32; DeviceID++)
{
u8 Present = DevicePresent(BusID, DeviceID);
if (Present)
{
CPCIDevice Device(BusID, DeviceID);
m_Devices.Push(Device);
}
}
}
}
u8 CPCIManager::DBGetVendor(u16 VID, const s8 **VendorNameOut)
{
u32 TableLength = PCI_VENTABLE_LEN;
for (u32 i = 0; i < TableLength; i++)
{
PCI_VENTABLE *Vendor = &PciVenTable[i];
if (Vendor->VenId == VID)
{
// try to use the short name, if not null
bool Empty = true;
const s8 *Character = Vendor->VenShort;
while (*Character != 0)
{
if (*Character != 0)
{
Empty = false;
break;
}
Character++;
}
if (!Empty)
*VendorNameOut = Vendor->VenShort;
else
*VendorNameOut = Vendor->VenFull;
return 1;
}
}
return 0;
}
u8 CPCIManager::DBGetProduct(u16 VID, u16 PID, const s8 **ProductNameOut, const s8 **ProductDescriptionOut)
{
u32 TableLength = PCI_DEVTABLE_LEN;
for (u32 i = 0; i < TableLength; i++)
{
PCI_DEVTABLE *Product = &PciDevTable[i];
if (Product->VenId == VID && Product->DevId == PID)
{
*ProductNameOut = Product->Chip;
*ProductDescriptionOut = Product->ChipDesc;
return 1;
}
}
return 0;
}
u32 CPCIDevice::ConfigRead(u16 Function, u16 Offset)
{
TPCIConfigAddress Address;
Address.Fields.Zero = 0;
Address.Fields.Register = Offset >> 2;
Address.Fields.Function = Function;
Address.Fields.Device = m_Device;
Address.Fields.Bus = m_Bus;
Address.Fields.Reserved = 0;
Address.Fields.Enable = 1;
koutl(PCI_CONFIG_ADDRESS, Address.Value);
return kinl(PCI_CONFIG_DATA);
}
void CPCIDevice::ConfigWrite(u16 Function, u16 Offset, u32 Data)
{
TPCIConfigAddress Address;
Address.Fields.Zero = 0;
Address.Fields.Register = Offset >> 2;
Address.Fields.Function = Function;
Address.Fields.Device = m_Device;
Address.Fields.Bus = m_Bus;
Address.Fields.Reserved = 0;
Address.Fields.Enable = 1;
koutl(PCI_CONFIG_ADDRESS, Address.Value);
koutl(PCI_CONFIG_DATA, Data);
}
CPCIDevice::CPCIDevice(u16 Bus, u16 Device)
{
m_Bus = Bus;
m_Device = Device;
m_DeviceHeader = 0;
kprintf("PCI device [%i:%i]\n", Bus, Device);
for (u8 i = 0; i < sizeof(m_Header); i += 4)
{
u32 Value = ConfigRead(0, i);
((u32 *)&m_Header)[i/4] = Value;
}
kprintf(" VID: %h, PID: %h\n", m_Header.VendorID, m_Header.ProductID);
kprintf(" Type: ");
switch (m_Header.HeaderType)
{
case 0x00:
kprintf("Generic Device\n");
break;
case 0x01:
kprintf("PCI-PCI Bridge\n");
break;
case 0x02:
kprintf("CardBus Bridge\n");
break;
default:
kprintf("Unknown.\n");
break;
}
kprintf(" Info: ");
const s8 *VendorName, *ProductName, *ProductDescription;
if (CPCIManager::DBGetVendor(m_Header.VendorID, &VendorName))
kprintf("%s", VendorName);
if (CPCIManager::DBGetProduct(m_Header.VendorID, m_Header.ProductID, &ProductName, &ProductDescription))
kprintf(" %s %s", ProductName, ProductDescription);
kprintf("\n");
switch (m_Header.HeaderType)
{
case 0x00:
{
m_DeviceHeader = new TPCIHeaderDevice;
for (u8 i = 0; i < sizeof(TPCIHeaderDevice); i += 4)
((u32 *)m_DeviceHeader)[i/4] = ConfigRead(0, 0x10 + i);
for (u8 i = 0; i < 6; i++)
{
TPCIBAR *BAR = &m_DeviceHeader->BAR[i];
u32 Value = BAR->Value;
if (Value == 0)
continue;
// kprintf(" BAR%i: ", i);
if (Value & 1)
{
// kprintf("I/O ");
// kprintf("Value: %x\n", Value);
}
else
{
if (BAR->MemoryBAR.Type != 0x00)
{
kprintf(" non 32-bit, ignoring.\n");
continue;
}
// kprintf("Memory ");
// kprintf("Value: %x ", Value);
ConfigWrite(0, 0x10 + (i * 4), 0xFFFFFFFF);
// u32 NewValue = ConfigRead(0, 0x10 + (i * 4));
ConfigWrite(0, 0x10 + (i * 4), Value);
// u32 Size = ~(NewValue & ~(0b1111)) + 1;
// kprintf("Size: %x (%ik)\n", Size, Size/1024);
}
}
break;
}
}
}
cb::CVector<CPCIDevice> CPCIManager::m_Devices;