mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-23 06:18:54 +00:00
First Impl.
This commit is contained in:
parent
8b63a80863
commit
f8dd90dc7c
6 changed files with 299 additions and 397 deletions
|
|
@ -33,10 +33,10 @@ namespace Cosmos.HAL.Drivers.PCI.Network
|
|||
}
|
||||
|
||||
this.pciCard = device;
|
||||
this.pciCard.Claimed = true;
|
||||
// this.pciCard.Claimed = true;
|
||||
this.pciCard.EnableDevice();
|
||||
|
||||
this.io = new AMDPCNetIIIOGroup((ushort) this.pciCard.BaseAddresses[0].BaseAddress());
|
||||
//this.io = new AMDPCNetIIIOGroup((ushort) this.pciCard.BaseAddresses[0].BaseAddress());
|
||||
this.io.RegisterData.DWord = 0;
|
||||
|
||||
// Get the EEPROM MAC Address and set it as the devices MAC
|
||||
|
|
@ -97,7 +97,7 @@ namespace Cosmos.HAL.Drivers.PCI.Network
|
|||
mTransmitBuffer = new Queue<byte[]>();
|
||||
mRecvBuffer = new Queue<byte[]>();
|
||||
|
||||
INTs.SetIrqHandler(device.InterruptLine, HandleNetworkInterrupt);
|
||||
//INTs.SetIrqHandler(device.InterruptLine, HandleNetworkInterrupt);
|
||||
}
|
||||
|
||||
protected void HandleNetworkInterrupt(ref INTs.IRQContext aContext)
|
||||
|
|
@ -134,17 +134,17 @@ namespace Cosmos.HAL.Drivers.PCI.Network
|
|||
/// </summary>
|
||||
public static void FindAll()
|
||||
{
|
||||
Console.WriteLine("Scanning for AMD PCNetII cards...");
|
||||
PCIDevice device = Cosmos.HAL.PCI.GetDevice(0x1022, 0x2000);
|
||||
if (device != null)
|
||||
{
|
||||
AMDPCNetII nic = new AMDPCNetII((PCIDeviceNormal) device);
|
||||
|
||||
Console.WriteLine("Found AMD PCNetII NIC on PCI " + device.bus + ":" + device.slot + ":" +
|
||||
device.function);
|
||||
Console.WriteLine("NIC IRQ: " + device.InterruptLine);
|
||||
Console.WriteLine("NIC MAC Address: " + nic.MACAddress.ToString());
|
||||
}
|
||||
Console.WriteLine("Scanning for AMD PCNetII cards...");
|
||||
// PCIDevice device = Cosmos.HAL.PCI.GetDevice(0x1022, 0x2000);
|
||||
// if (device != null)
|
||||
// {
|
||||
// AMDPCNetII nic = new AMDPCNetII((PCIDeviceNormal) device);
|
||||
//
|
||||
// Console.WriteLine("Found AMD PCNetII NIC on PCI " + device.bus + ":" + device.slot + ":" +
|
||||
// device.function);
|
||||
// Console.WriteLine("NIC IRQ: " + device.InterruptLine);
|
||||
// Console.WriteLine("NIC MAC Address: " + nic.MACAddress.ToString());
|
||||
// }
|
||||
}
|
||||
|
||||
#region Register Access Properties
|
||||
|
|
|
|||
|
|
@ -145,13 +145,13 @@ namespace Cosmos.HAL.Drivers.PCI.Video
|
|||
|
||||
public VMWareSVGAII()
|
||||
{
|
||||
device = (PCIDeviceNormal)(HAL.PCI.GetDevice(0x15AD, 0x0405));
|
||||
//device = (PCIDeviceNormal)(HAL.PCI.GetDevice(0x15AD, 0x0405));
|
||||
device.EnableMemory(true);
|
||||
uint basePort = device.BaseAddresses[0].BaseAddress();
|
||||
IndexPort = new IOPort((ushort)(basePort + (uint)IOPortOffset.Index));
|
||||
ValuePort = new IOPort((ushort)(basePort + (uint)IOPortOffset.Value));
|
||||
BiosPort = new IOPort((ushort)(basePort + (uint)IOPortOffset.Bios));
|
||||
IRQPort = new IOPort((ushort)(basePort + (uint)IOPortOffset.IRQ));
|
||||
//uint basePort = device.BaseAddresses[0].BaseAddress();
|
||||
//IndexPort = new IOPort((ushort)(basePort + (uint)IOPortOffset.Index));
|
||||
//ValuePort = new IOPort((ushort)(basePort + (uint)IOPortOffset.Value));
|
||||
//BiosPort = new IOPort((ushort)(basePort + (uint)IOPortOffset.Bios));
|
||||
// IRQPort = new IOPort((ushort)(basePort + (uint)IOPortOffset.IRQ));
|
||||
|
||||
WriteRegister(Register.ID, (uint)ID.V2);
|
||||
if (ReadRegister(Register.ID) != (uint)ID.V2)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,67 @@ namespace Cosmos.HAL
|
|||
|
||||
//static public PIT PIT = new PIT();
|
||||
// Must be static init, other static inits rely on it not being null
|
||||
public static TextScreenBase TextScreen = new TextScreen();
|
||||
|
||||
public static TextScreenBase TextScreen = new TextScreen();
|
||||
public static PCI Pci;
|
||||
public static int atamode;
|
||||
|
||||
static public void Init(TextScreenBase textScreen)
|
||||
{
|
||||
if (textScreen != null)
|
||||
{
|
||||
TextScreen = textScreen;
|
||||
}
|
||||
|
||||
mDebugger.Send("Before Core.Global.Init");
|
||||
Core.Global.Init();
|
||||
|
||||
//TODO Redo this - Global init should be other.
|
||||
// Move PCI detection to hardware? Or leave it in core? Is Core PC specific, or deeper?
|
||||
// If we let hardware do it, we need to protect it from being used by System.
|
||||
// Probably belongs in hardware, and core is more specific stuff like CPU, memory, etc.
|
||||
//Core.PCI.OnPCIDeviceFound = PCIDeviceFound;
|
||||
|
||||
//TODO: Since this is FCL, its "common". Otherwise it should be
|
||||
// system level and not accessible from Core. Need to think about this
|
||||
// for the future.
|
||||
|
||||
Console.WriteLine("Finding PCI Devices");
|
||||
mDebugger.Send("PCI Devices");
|
||||
PCI.Setup();
|
||||
|
||||
Console.WriteLine("Starting ACPI");
|
||||
mDebugger.Send("ACPI Init");
|
||||
ACPI.Start();
|
||||
|
||||
mDebugger.Send("Done initializing Cosmos.HAL.Global");
|
||||
|
||||
if (atamode == 1)
|
||||
{
|
||||
//TODO Implement an AHCI Driver
|
||||
}
|
||||
else if (atamode == 2)
|
||||
{
|
||||
//TODO Implement a RAID Driver
|
||||
}
|
||||
else if (atamode == 3)
|
||||
{
|
||||
mDebugger.Send("ATA Primary Master");
|
||||
InitAta(Ata.ControllerIdEnum.Primary, Ata.BusPositionEnum.Master);
|
||||
|
||||
//TODO Need to change code to detect if ATA controllers are present or not. How to do this? via PCI enum?
|
||||
// They do show up in PCI space as well as the fixed space.
|
||||
// Or is it always here, and was our compiler stack corruption issue?
|
||||
mDebugger.Send("ATA Secondary Master");
|
||||
InitAta(Ata.ControllerIdEnum.Secondary, Ata.BusPositionEnum.Master);
|
||||
//InitAta(BlockDevice.Ata.ControllerIdEnum.Secondary, BlockDevice.Ata.BusPositionEnum.Slave);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableInterrupts()
|
||||
{
|
||||
CPU.EnableInterrupts();
|
||||
}
|
||||
|
||||
private static void InitAta(Ata.ControllerIdEnum aControllerID,
|
||||
Ata.BusPositionEnum aBusPosition)
|
||||
|
|
@ -76,75 +134,6 @@ namespace Cosmos.HAL
|
|||
}
|
||||
}
|
||||
|
||||
// Init devices that are "static"/mostly static. These are devices
|
||||
// that all PCs are expected to have. Keyboards, screens, ATA hard drives etc.
|
||||
// Despite them being static, some discovery is required. For example, to see if
|
||||
// a hard drive is connected or not and if so what type.
|
||||
internal static void InitStaticDevices()
|
||||
{
|
||||
//TextScreen = new TextScreen();
|
||||
mDebugger.Send("CLS");
|
||||
//TODO: Since this is FCL, its "common". Otherwise it should be
|
||||
// system level and not accessible from Core. Need to think about this
|
||||
// for the future.
|
||||
mDebugger.Send("Finding PCI Devices");
|
||||
//PCI.Setup();
|
||||
}
|
||||
|
||||
static public void Init(TextScreenBase textScreen)
|
||||
{
|
||||
if (textScreen != null)
|
||||
{
|
||||
TextScreen = textScreen;
|
||||
}
|
||||
|
||||
mDebugger.Send("Before Core.Global.Init");
|
||||
Core.Global.Init();
|
||||
mDebugger.Send("Static Devices");
|
||||
InitStaticDevices();
|
||||
mDebugger.Send("PCI Devices");
|
||||
InitPciDevices();
|
||||
mDebugger.Send("ACPI Init");
|
||||
StartACPI();
|
||||
mDebugger.Send("Done initializing Cosmos.HAL.Global");
|
||||
|
||||
mDebugger.Send("ATA Primary Master");
|
||||
InitAta(Ata.ControllerIdEnum.Primary, Ata.BusPositionEnum.Master);
|
||||
|
||||
//TODO Need to change code to detect if ATA controllers are present or not. How to do this? via PCI enum?
|
||||
// They do show up in PCI space as well as the fixed space.
|
||||
// Or is it always here, and was our compiler stack corruption issue?
|
||||
mDebugger.Send("ATA Secondary Master");
|
||||
InitAta(Ata.ControllerIdEnum.Secondary, Ata.BusPositionEnum.Master);
|
||||
//InitAta(BlockDevice.Ata.ControllerIdEnum.Secondary, BlockDevice.Ata.BusPositionEnum.Slave);
|
||||
}
|
||||
|
||||
internal static void InitPciDevices()
|
||||
{
|
||||
//TODO Redo this - Global init should be other.
|
||||
// Move PCI detection to hardware? Or leave it in core? Is Core PC specific, or deeper?
|
||||
// If we let hardware do it, we need to protect it from being used by System.
|
||||
// Probably belongs in hardware, and core is more specific stuff like CPU, memory, etc.
|
||||
//Core.PCI.OnPCIDeviceFound = PCIDeviceFound;
|
||||
|
||||
//TODO: Since this is FCL, its "common". Otherwise it should be
|
||||
// system level and not accessible from Core. Need to think about this
|
||||
// for the future.
|
||||
Console.WriteLine("Finding PCI Devices");
|
||||
PCI.Setup();
|
||||
}
|
||||
|
||||
public static void StartACPI()
|
||||
{
|
||||
Console.WriteLine("Starting ACPI");
|
||||
ACPI.Start();
|
||||
}
|
||||
|
||||
public static void EnableInterrupts()
|
||||
{
|
||||
CPU.EnableInterrupts();
|
||||
}
|
||||
|
||||
public static bool InterruptsEnabled => CPU.mInterruptsEnabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,75 +8,104 @@ namespace Cosmos.HAL
|
|||
{
|
||||
public class PCI
|
||||
{
|
||||
private static List<PCIDevice> devices;
|
||||
internal static Debugger mDebugger = new Debugger("HAL", "PCI");
|
||||
private static List<PCIDevice> Devices;
|
||||
|
||||
public static uint Count
|
||||
{
|
||||
get { return (uint)Devices.Count; }
|
||||
}
|
||||
|
||||
public static void Setup()
|
||||
{
|
||||
EnumerateDevices();
|
||||
}
|
||||
Devices = new List<PCIDevice>();
|
||||
|
||||
public static PCIDevice GetDevice(ushort VendorID, ushort DeviceID)
|
||||
{
|
||||
for (int i = 0; i < devices.Count; i++)
|
||||
if ((PCIDevice.GetHeaderType(0x0, 0x0, 0x0) & 0x80) == 0)
|
||||
{
|
||||
if (devices[i].VendorID == VendorID && devices[i].DeviceID == DeviceID)
|
||||
return devices[i];
|
||||
CheckBus(0x0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void EnumerateDevices()
|
||||
{
|
||||
devices = new List<PCIDevice>();
|
||||
//EnumerateBus(0, 0);
|
||||
}
|
||||
|
||||
private static void EnumerateBus(uint xBus, uint step)
|
||||
{
|
||||
for (uint xDevice = 0; xDevice < 32; xDevice++)
|
||||
else
|
||||
{
|
||||
PCIDevice xPCIDevice = new PCIDevice(xBus, xDevice, 0x00);
|
||||
if (xPCIDevice.DeviceExists)
|
||||
for (ushort fn = 0; fn < 8; fn++)
|
||||
{
|
||||
if (xPCIDevice.HeaderType == PCIDevice.PCIHeaderType.Bridge)
|
||||
if (PCIDevice.GetVendorID(0x0, 0x0, fn) != 0xFFFF)
|
||||
break;
|
||||
|
||||
CheckBus(fn);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (PCIDevice device in Devices)
|
||||
{
|
||||
|
||||
if (device.ClassCode == 0x01 && device.Subclass == 0x06 && device.ProgIF == 0x01)
|
||||
{
|
||||
//Serial ATA (AHCI 1.0)
|
||||
Global.atamode = 1;
|
||||
}
|
||||
else if (device.ClassCode == 0x01 && device.Subclass == 0x04 && device.ProgIF == 0x00)
|
||||
{
|
||||
//RAID Controller
|
||||
Global.atamode = 2;
|
||||
}
|
||||
else if (device.ClassCode == 0x01 && device.Subclass == 0x01)
|
||||
{
|
||||
//IDE Controller
|
||||
Global.atamode = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckBus(ushort xBus)
|
||||
{
|
||||
for (ushort device = 0; device < 32; device++)
|
||||
{
|
||||
if (PCIDevice.GetVendorID(xBus, device, 0x0) == 0xFFFF)
|
||||
continue;
|
||||
|
||||
CheckFunction(new PCIDevice(xBus, device, 0x0));
|
||||
if ((PCIDevice.GetHeaderType(xBus, device, 0x0) & 0x80) != 0)
|
||||
{
|
||||
for (ushort fn = 1; fn < 8; fn++)
|
||||
{
|
||||
for (uint xFunction = 0; xFunction < 8; xFunction++)
|
||||
{
|
||||
xPCIDevice = new PCIDevice(xBus, xDevice, xFunction);
|
||||
if (xPCIDevice.DeviceExists)
|
||||
AddDevice(new PCIDeviceBridge(xBus, xDevice, xFunction), step);
|
||||
}
|
||||
}
|
||||
else if (xPCIDevice.HeaderType == PCIDevice.PCIHeaderType.Cardbus)
|
||||
{
|
||||
AddDevice(new PCIDeviceCardbus(xBus, xDevice, 0x00), step);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddDevice(new PCIDeviceNormal(xBus, xDevice, 0x00), step);
|
||||
if (PCIDevice.GetVendorID(xBus, device, fn) != 0xFFFF)
|
||||
CheckFunction(new PCIDevice(xBus, device, fn));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddDevice(PCIDevice device, uint step)
|
||||
private static void CheckFunction(PCIDevice xPCIDevice)
|
||||
{
|
||||
Console.WriteLine("Adding PCIDevice");
|
||||
string str = "";
|
||||
for (int i = 0; i < step; i++)
|
||||
Devices.Add(xPCIDevice);
|
||||
|
||||
if (xPCIDevice.ClassCode == 0x6 && xPCIDevice.Subclass == 0x4)
|
||||
CheckBus(xPCIDevice.SecondaryBusNumber);
|
||||
}
|
||||
|
||||
public static PCIDevice GetDeviceVendorID(ushort VendorID, ushort DeviceID)
|
||||
{
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
{
|
||||
str += " ";
|
||||
var xDevice = Devices[i];
|
||||
if (xDevice.VendorID == VendorID && xDevice.DeviceID == DeviceID)
|
||||
{
|
||||
return Devices[i];
|
||||
}
|
||||
}
|
||||
var xText = str + device.bus + ":" + device.slot + ":" + device.function + " " + PCIDevice.DeviceClass.GetString(device);
|
||||
mDebugger.Send(xText);
|
||||
Console.WriteLine(xText);
|
||||
devices.Add(device);
|
||||
if (device is PCIDeviceBridge)
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PCIDevice GetDeviceClass(ushort Class, ushort SubClass)
|
||||
{
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
{
|
||||
var xDevice = device as PCIDeviceBridge;
|
||||
EnumerateBus((xDevice).SecondaryBusNumber, step + 1);
|
||||
var xDevice = Devices[i];
|
||||
if (xDevice.ClassCode == Class && xDevice.Subclass == SubClass)
|
||||
{
|
||||
return Devices[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Cosmos.HAL
|
||||
{
|
||||
public class PCIBaseAddressBar
|
||||
{
|
||||
private uint baseAddress = 0;
|
||||
private ushort prefetchable = 0;
|
||||
private byte type = 0;
|
||||
private bool isIO = false;
|
||||
|
||||
internal PCIBaseAddressBar(uint raw)
|
||||
{
|
||||
isIO = (raw & 0x01) == 1;
|
||||
|
||||
if (isIO)
|
||||
{
|
||||
baseAddress = raw & 0xFFFFFFFC;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = (byte)((raw >> 1) & 0x03);
|
||||
prefetchable = (ushort)((raw >> 3) & 0x01);
|
||||
switch (type)
|
||||
{
|
||||
case 0x00:
|
||||
baseAddress = raw & 0xFFFFFFF0;
|
||||
break;
|
||||
case 0x01:
|
||||
baseAddress = raw & 0xFFFFFFF0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static int pci_size(int b, int mask)
|
||||
{
|
||||
int size = mask & b;
|
||||
size = size & ~(size - 1);
|
||||
return size;
|
||||
}
|
||||
|
||||
public uint BaseAddress()
|
||||
{
|
||||
return baseAddress;
|
||||
}
|
||||
|
||||
public bool IsIO()
|
||||
{
|
||||
return isIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,54 +10,21 @@ namespace Cosmos.HAL
|
|||
{
|
||||
public class PCIDevice
|
||||
{
|
||||
|
||||
#region Enums
|
||||
public enum PCIHeaderType : byte
|
||||
{
|
||||
Normal = 0x00,
|
||||
Bridge = 0x01,
|
||||
Cardbus = 0x02
|
||||
}
|
||||
};
|
||||
|
||||
[Flags]
|
||||
public enum PCIBist : byte
|
||||
{
|
||||
CocdMask = 0x0f, /* Return result */
|
||||
Start = 0x40, /* 1 to start BIST, 2 secs or less */
|
||||
Capable = 0x80 /* 1 if BIST capable */
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum PCICommand : short
|
||||
{
|
||||
IO = 0x1, /* Enable response in I/O space */
|
||||
Memory = 0x2, /* Enable response in Memory space */
|
||||
Master = 0x4, /* Enable bus mastering */
|
||||
Special = 0x8, /* Enable response to special cycles */
|
||||
Invalidate = 0x10, /* Use memory write and invalidate */
|
||||
VGA_Pallete = 0x20, /* Enable palette snooping */
|
||||
Parity = 0x40, /* Enable parity checking */
|
||||
Wait = 0x80, /* Enable address/data stepping */
|
||||
SERR = 0x100, /* Enable SERR */
|
||||
Fast_Back = 0x200, /* Enable back-to-back writes */
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum PCIStatus : int
|
||||
{
|
||||
CAP_LIST = 0x10, /* Support Capability List */
|
||||
SUPPORT_66MHZ = 0x20, /* Support 66 Mhz PCI 2.1 bus */
|
||||
UDF = 0x40, /* Support User Definable Features [obsolete] */
|
||||
FAST_BACK = 0x80, /* Accept fast-back to back */
|
||||
PARITY = 0x100, /* Detected parity error */
|
||||
DEVSEL_MASK = 0x600, /* DEVSEL timing */
|
||||
DEVSEL_FAST = 0x000,
|
||||
DEVSEL_MEDIUM = 0x200,
|
||||
DEVSEL_SLOW = 0x400,
|
||||
SIG_TARGET_ABORT = 0x800, /* Set on target abort */
|
||||
REC_TARGET_ABORT = 0x1000, /* Master ack of " */
|
||||
REC_MASTER_ABORT = 0x2000, /* Set on master abort */
|
||||
SIG_SYSTEM_ERROR = 0x4000, /* Set when we drive SERR */
|
||||
DETECTED_PARITY = 0x8000 /* Set on parity error */
|
||||
}
|
||||
CocdMask = 0x0f,
|
||||
Start = 0x40,
|
||||
Capable = 0x80
|
||||
};
|
||||
|
||||
public enum PCIInterruptPIN : byte
|
||||
{
|
||||
|
|
@ -66,95 +33,106 @@ namespace Cosmos.HAL
|
|||
INTB = 0x02,
|
||||
INTC = 0x03,
|
||||
INTD = 0x04
|
||||
}
|
||||
};
|
||||
|
||||
public ushort VendorID { get; private set; }
|
||||
public ushort DeviceID { get; private set; }
|
||||
public enum Config : byte
|
||||
{
|
||||
VendorID = 0, DeviceID = 2,
|
||||
Command = 4, Status = 6,
|
||||
RevisionID = 8, ProgIF = 9, SubClass = 10, Class = 11,
|
||||
CacheLineSize = 12, LatencyTimer = 13, HeaderType = 14, BIST = 15,
|
||||
BAR0 = 16,
|
||||
BAR1 = 20,
|
||||
PrimaryBusNo = 24, SecondaryBusNo = 25, SubBusNo = 26, SecondarLT = 27,
|
||||
IOBase = 28, IOLimit = 29, SecondaryStatus = 30,
|
||||
MemoryBase = 32, MemoryLimit = 34,
|
||||
PrefMemoryBase = 36, PrefMemoryLimit = 38,
|
||||
PrefBase32Upper = 40,
|
||||
PrefLimit32upper = 44,
|
||||
PrefBase16Upper = 48, PrefLimit16upper = 50,
|
||||
CapabilityPointer = 52, Reserved = 53,
|
||||
ExpROMBaseAddress = 56,
|
||||
InterruptLine = 60, InterruptPIN = 61, BridgeControl = 62
|
||||
};
|
||||
#endregion
|
||||
|
||||
//public PCICommand Command { get; private set; }
|
||||
//public PCIStatus Status { get; private set; }
|
||||
public PCICommand Command { get { return (PCICommand)ReadRegister16(0x04); } set { WriteRegister16(0x04, (ushort)value); } }
|
||||
public PCIStatus Status { get { return (PCIStatus)ReadRegister16(0x06); } set { WriteRegister16(0x06, (ushort)value); } }
|
||||
public readonly uint bus;
|
||||
public readonly uint slot;
|
||||
public readonly uint function;
|
||||
|
||||
public byte RevisionID { get; private set; }
|
||||
public byte ProgIF { get; private set; }
|
||||
public byte Subclass { get; private set; }
|
||||
public byte ClassCode { get; private set; }
|
||||
public readonly ushort VendorID;
|
||||
public readonly ushort DeviceID;
|
||||
|
||||
public byte CacheLineSize { get; private set; }
|
||||
public byte LatencyTimer { get; private set; }
|
||||
public PCIHeaderType HeaderType { get; private set; }
|
||||
public PCIBist BIST { get; private set; }
|
||||
public readonly ushort Command;
|
||||
public readonly ushort Status;
|
||||
|
||||
public byte InterruptLine { get; private set; }
|
||||
public PCIInterruptPIN InterruptPIN { get; private set; }
|
||||
public readonly byte RevisionID;
|
||||
public readonly byte ProgIF;
|
||||
public readonly byte Subclass;
|
||||
public readonly byte ClassCode;
|
||||
public readonly byte SecondaryBusNumber;
|
||||
|
||||
public bool DeviceExists { get; private set; }
|
||||
public readonly bool DeviceExists;
|
||||
|
||||
/// <summary>
|
||||
/// Has this device been claimed by a driver
|
||||
/// </summary>
|
||||
public bool Claimed { get; set; }
|
||||
public readonly PCIHeaderType HeaderType;
|
||||
public readonly PCIBist BIST;
|
||||
public readonly PCIInterruptPIN InterruptPIN;
|
||||
|
||||
public uint bus = 0;
|
||||
public uint slot = 0;
|
||||
public uint function = 0;
|
||||
public const ushort ConfigAddressPort = 0xCF8;
|
||||
public const ushort ConfigDataPort = 0xCFC;
|
||||
|
||||
public PCIBaseAddressBar[] BaseAddressBar;
|
||||
|
||||
protected static Core.IOGroup.PCI IO = new Core.IOGroup.PCI();
|
||||
|
||||
protected Core.IOGroup.PCI IO = new Core.IOGroup.PCI();
|
||||
public PCIDevice(uint bus, uint slot, uint function)
|
||||
{
|
||||
this.bus = bus;
|
||||
this.slot = slot;
|
||||
this.function = function;
|
||||
|
||||
VendorID = ReadRegister16(0x00);
|
||||
DeviceID = ReadRegister16(0x02);
|
||||
//Command = (PCICommand)ReadRegister16(0x04);
|
||||
//Status = (PCIStatus)ReadRegister16(0x06);
|
||||
VendorID = ReadRegister16((byte)Config.VendorID);
|
||||
DeviceID = ReadRegister16((byte)Config.DeviceID);
|
||||
|
||||
RevisionID = ReadRegister8(0x08);
|
||||
ProgIF = ReadRegister8(0x09);
|
||||
Subclass = ReadRegister8(0x0A);
|
||||
ClassCode = ReadRegister8(0x0B);
|
||||
Command = ReadRegister16((byte)Config.Command);
|
||||
Status = ReadRegister16((byte)Config.Status);
|
||||
|
||||
CacheLineSize = ReadRegister8(0x0C);
|
||||
LatencyTimer = ReadRegister8(0x0D);
|
||||
HeaderType = (PCIHeaderType)ReadRegister8(0x0E);
|
||||
BIST = (PCIBist)ReadRegister8(0x0F);
|
||||
|
||||
InterruptLine = ReadRegister8(0x3C);
|
||||
InterruptPIN = (PCIInterruptPIN)ReadRegister8(0x3D);
|
||||
RevisionID = ReadRegister8((byte)Config.RevisionID);
|
||||
ProgIF = ReadRegister8((byte)Config.ProgIF);
|
||||
Subclass = ReadRegister8((byte)Config.SubClass);
|
||||
ClassCode = ReadRegister8((byte)Config.Class);
|
||||
SecondaryBusNumber = ReadRegister8((byte)Config.SecondaryBusNo);
|
||||
|
||||
HeaderType = (PCIHeaderType)ReadRegister8((byte)Config.HeaderType);
|
||||
BIST = (PCIBist)ReadRegister8((byte)Config.BIST);
|
||||
InterruptPIN = (PCIInterruptPIN)ReadRegister8((byte)Config.InterruptPIN);
|
||||
|
||||
DeviceExists = (uint)VendorID != 0xFFFF && (uint)DeviceID != 0xFFFF;
|
||||
if (HeaderType == PCIHeaderType.Normal)
|
||||
{
|
||||
BaseAddressBar = new PCIBaseAddressBar[6];
|
||||
BaseAddressBar[0] = new PCIBaseAddressBar(ReadRegister32(0x10));
|
||||
BaseAddressBar[1] = new PCIBaseAddressBar(ReadRegister32(0x14));
|
||||
BaseAddressBar[2] = new PCIBaseAddressBar(ReadRegister32(0x18));
|
||||
BaseAddressBar[3] = new PCIBaseAddressBar(ReadRegister32(0x1C));
|
||||
BaseAddressBar[4] = new PCIBaseAddressBar(ReadRegister32(0x20));
|
||||
BaseAddressBar[5] = new PCIBaseAddressBar(ReadRegister32(0x24));
|
||||
}
|
||||
}
|
||||
|
||||
protected UInt32 GetAddressBase(uint aBus, uint aSlot, uint aFunction)
|
||||
public static ushort GetHeaderType(ushort Bus, ushort Slot, ushort Function)
|
||||
{
|
||||
// 31 30 - 24 23 - 16 15 - 11 10 - 8 7 - 2 1 - 0
|
||||
// Enable Bit Reserved Bus Number Device Number Function Number Register Number 00
|
||||
return (UInt32)(
|
||||
// Enable bit - must be set
|
||||
0x80000000
|
||||
// Bits 23-16
|
||||
| (aBus << 16)
|
||||
// Bits 15-11
|
||||
| ((aSlot & 0x1F) << 11)
|
||||
// Bits 10-8
|
||||
| ((aFunction & 0x07) << 8));
|
||||
UInt32 xAddr = GetAddressBase(Bus, Slot, Function) | 0xE & 0xFC;
|
||||
IO.ConfigAddressPort.DWord = xAddr;
|
||||
return (byte)(IO.ConfigDataPort.DWord >> ((0xE % 4) * 8) & 0xFF);
|
||||
}
|
||||
|
||||
public void EnableMemory(bool enable)
|
||||
public static UInt16 GetVendorID(ushort Bus, ushort Slot, ushort Function)
|
||||
{
|
||||
UInt16 command = ReadRegister16(0x04);
|
||||
|
||||
UInt16 flags = 0x0007;
|
||||
|
||||
if (enable)
|
||||
command |= flags;
|
||||
else
|
||||
command &= (ushort)~flags;
|
||||
|
||||
WriteRegister16(0x04, command);
|
||||
UInt32 xAddr = GetAddressBase(Bus, Slot, Function) | 0x0 & 0xFC;
|
||||
IO.ConfigAddressPort.DWord = xAddr;
|
||||
return (UInt16)(IO.ConfigDataPort.DWord >> ((0x0 % 4) * 8) & 0xFFFF);
|
||||
}
|
||||
|
||||
#region IOReadWrite
|
||||
|
|
@ -176,7 +154,7 @@ namespace Cosmos.HAL
|
|||
{
|
||||
UInt32 xAddr = GetAddressBase(bus, slot, function) | ((UInt32)(aRegister & 0xFC));
|
||||
IO.ConfigAddressPort.DWord = xAddr;
|
||||
return (UInt16)(IO.ConfigDataPort.DWord >> ((aRegister % 4) * 8) & 0xFFFF); ;
|
||||
return (UInt16)(IO.ConfigDataPort.DWord >> ((aRegister % 4) * 8) & 0xFFFF);
|
||||
}
|
||||
|
||||
protected void WriteRegister16(byte aRegister, ushort value)
|
||||
|
|
@ -201,104 +179,23 @@ namespace Cosmos.HAL
|
|||
}
|
||||
#endregion
|
||||
|
||||
public class DeviceClass
|
||||
protected static UInt32 GetAddressBase(uint aBus, uint aSlot, uint aFunction)
|
||||
{
|
||||
public static string GetString(PCIDevice device)
|
||||
{
|
||||
switch (device.VendorID)
|
||||
{
|
||||
case 0x1022: //AMD
|
||||
switch (device.DeviceID)
|
||||
{
|
||||
case 0x2000:
|
||||
return "AMD PCnet LANCE PCI Ethernet Controller";
|
||||
}
|
||||
break;
|
||||
case 0x104B: //Sony
|
||||
switch (device.DeviceID)
|
||||
{
|
||||
case 0x1040:
|
||||
return "Mylex BT958 SCSI Host Adaptor";
|
||||
}
|
||||
break;
|
||||
case 0x1274: //Ensoniq
|
||||
switch (device.DeviceID)
|
||||
{
|
||||
case 0x1371:
|
||||
return "Ensoniq AudioPCI";
|
||||
}
|
||||
break;
|
||||
case 0x15AD: //VMware
|
||||
switch (device.DeviceID)
|
||||
{
|
||||
case 0x0405:
|
||||
return "VMware NVIDIA 9500MGS";
|
||||
case 0x0770:
|
||||
return "VMware Standard Enhanced PCI to USB Host Controller";
|
||||
case 0x0790:
|
||||
return "VMware 6.0 Virtual USB 2.0 Host Controller";
|
||||
case 0x07A0:
|
||||
return "VMware PCI Express Root Port";
|
||||
}
|
||||
break;
|
||||
case 0x8086: //Intel
|
||||
switch (device.DeviceID)
|
||||
{
|
||||
case 0x7190:
|
||||
return "Intel 440BX/ZX AGPset Host Bridge";
|
||||
case 0x7191:
|
||||
return "Intel 440BX/ZX AGPset PCI-to-PCI bridge";
|
||||
case 0x7110:
|
||||
return "Intel PIIX4/4E/4M ISA Bridge";
|
||||
case 0x7112:
|
||||
return "Intel PIIX4/4E/4M USB Interface";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0x80000000 | (aBus << 16) | ((aSlot & 0x1F) << 11) | ((aFunction & 0x07) << 8);
|
||||
}
|
||||
|
||||
switch (device.ClassCode)
|
||||
{
|
||||
//case 0x00:
|
||||
// return "Any device";
|
||||
case 0x01:
|
||||
return "Mass Storage Controller";
|
||||
case 0x02:
|
||||
return "Network Controller";
|
||||
case 0x03:
|
||||
return "Display Controller";
|
||||
case 0x04:
|
||||
return "Multimedia Controller";
|
||||
case 0x05:
|
||||
return "Memory Controller";
|
||||
case 0x06:
|
||||
return "Bridge Device";
|
||||
case 0x07:
|
||||
return "Simple Communication Controller";
|
||||
case 0x08:
|
||||
return "Base System Peripheral";
|
||||
case 0x09:
|
||||
return "Input Device";
|
||||
case 0x0A:
|
||||
return "Docking Station";
|
||||
case 0x0B:
|
||||
return "Processor";
|
||||
case 0x0C:
|
||||
return "Serial Bus Controller";
|
||||
case 0x0D:
|
||||
return "Wireless Controller";
|
||||
case 0x0E:
|
||||
return "Intelligent I/O Controller";
|
||||
case 0x0F:
|
||||
return "Satellite Communication Controller";
|
||||
case 0x10:
|
||||
return "Encryption/Decryption Controller";
|
||||
case 0x11:
|
||||
return "Data Acquisition and Signal Processing Controller";
|
||||
//case 0xFF:
|
||||
// return "Unkown device";
|
||||
}
|
||||
return "ClassCode: " + device.ClassCode + " Subclass: " + device.Subclass + " ProgIF: " + device.ProgIF;
|
||||
}
|
||||
public void EnableMemory(bool enable)
|
||||
{
|
||||
UInt16 command = ReadRegister16(0x04);
|
||||
|
||||
UInt16 flags = 0x0007;
|
||||
|
||||
if (enable)
|
||||
command |= flags;
|
||||
else
|
||||
command &= (ushort)~flags;
|
||||
|
||||
WriteRegister16(0x04, command);
|
||||
}
|
||||
|
||||
private static string ToHex(uint aNumber, byte aBits)
|
||||
|
|
@ -306,4 +203,46 @@ namespace Cosmos.HAL
|
|||
return "0x" + aNumber.ToHex(aBits / 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PCIBaseAddressBar
|
||||
{
|
||||
private uint baseAddress = 0;
|
||||
private ushort prefetchable = 0;
|
||||
private ushort type = 0;
|
||||
private bool isIO = false;
|
||||
|
||||
public PCIBaseAddressBar(uint raw)
|
||||
{
|
||||
isIO = (raw & 0x01) == 1;
|
||||
|
||||
if (isIO)
|
||||
{
|
||||
baseAddress = raw & 0xFFFFFFFC;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = (ushort)((raw >> 1) & 0x03);
|
||||
prefetchable = (ushort)((raw >> 3) & 0x01);
|
||||
switch (type)
|
||||
{
|
||||
case 0x00:
|
||||
baseAddress = raw & 0xFFFFFFF0;
|
||||
break;
|
||||
case 0x01:
|
||||
baseAddress = raw & 0xFFFFFFF0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint BaseAddress
|
||||
{
|
||||
get { return baseAddress; }
|
||||
}
|
||||
|
||||
public bool IsIO
|
||||
{
|
||||
get { return isIO; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue