singrdk/base/Kernel/Singularity.Drivers/IdeBus.cs

192 lines
7.2 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: IdeBus.cs
//
// Creates IDE Bus device
// Creates IDE controller devices as sub devices and registers with with the system
// Creates two instances of the controller
#define DONT_DISABLE_LEGACY_NFORCE_TO_HIDE_DVD //
using System;
using System.Collections;
using System.Threading;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Configuration;
using Microsoft.Singularity.Drivers.IDE;
namespace Microsoft.Singularity.Drivers.IDE
{
// create the resource objects for CTR to fill in
// CTR will have to figure out which class to use...
[DriverCategory]
[Signature("pci/cc_0101")]
#if DONT_DISABLE_LEGACY_NFORCE_TO_HIDE_DVD //
[Signature("pci/ven_10de&dev_0053&cc_0101")] // nForce4
[Signature("pci/ven_10de&dev_0035&cc_0101")] // nForce4 Intel Edition
#endif
[EnumeratesDevice("/ata/controller")]
internal class LegacyIdeBus : DriverCategoryDeclaration
{
[IoPortRange(4, Default = 0xffa0, Length = 0x10, Shared = true)]
IoPortRange port1;
[IoFixedIrqRange(Base = 14, Shared = true)]
IoIrqRange primaryIrq;
[IoFixedIrqRange(Base = 15, Shared = true)]
IoIrqRange secondaryIrq;
// Provide to unify creation.
public static IDevice! DeviceCreate(IoConfig! config, String! instanceName)
{
return new IdeBus((PciDeviceConfig)config);
}
}
[DriverCategory]
[Signature("pci/ven_10de&dev_0054&cc_0101")] // nForce4
[Signature("pci/ven_10de&dev_0055&cc_0101")] // nForce4
[Signature("pci/ven_10de&dev_0036&cc_0101")] // nForce4 Intel Edition
[Signature("pci/ven_10d3&dev_003e&cc_0101")] // nForce4 Intel Edition
[EnumeratesDevice("/ata/controller")]
internal class NvIdeBus : DriverCategoryDeclaration
{
// [TODO] Should all of these be shared?
[IoPortRange(0, Default = 0x09f0, Length = 0x08, Shared = true)]
IoPortRange port1;
[IoPortRange(1, Default = 0x0bf0, Length = 0x04, Shared = true)]
IoPortRange port2;
[IoPortRange(2, Default = 0x0970, Length = 0x08, Shared = true)]
IoPortRange port3;
[IoPortRange(3, Default = 0x0b70, Length = 0x04, Shared = true)]
IoPortRange port4;
[IoPortRange(4, Default = 0xf600, Length = 0x10, Shared = true)]
IoPortRange port5;
[IoMemoryRange(5, Default = 0, Length = 0x1000)]
IoMemoryRange mem1;
[IoIrqRange(6, Default = 0x0b, Shared = true)]
IoIrqRange irq1;
// Provide to unify creation.
public static IDevice! DeviceCreate(IoConfig! config, String! name)
{
return new IdeBus((PciDeviceConfig)config);
}
}
[CLSCompliant(false)]
public class IdeBus : IBusDevice
{
private PciDeviceConfig! config;
private PnpConfig primaryConfig;
private PnpConfig secondaryConfig;
const uint PCI_CONFIG_Command_IOE = 0x1;
const uint PCI_CONFIG_PI_PrimaryMode = 0x1; // NATIVE, ~compatible
const uint PCI_CONFIG_PI_PrimaryFixed = 0x2; // DYNAMIC, ~fixed
const uint PCI_CONFIG_PI_SecondaryMode = 0x4; // NATIVE, ~compatible
const uint PCI_CONFIG_PI_SecondaryFixed = 0x8; // DYNAMIC, ~fixed
public IdeBus(PciDeviceConfig! config)
{
//DebugStub.Print("IdeBus: Device instantiated.\n");
this.config = config;
}
public void Initialize()
{
// 0: irq, 1: command, 2: control, 3: dma
IoRange[] primary = new IoRange[4];
IoRange[] secondary = new IoRange[4];
DebugStub.Print("IdeBus: Initializing device {0:x8}, vendor {1:x8}, config: {2}\n",
__arglist(
(ulong)config.DeviceId,
(ulong)config.VendorId,
config.ToString()));
// First, Check to see if the IDE controller is active by checking the
// IO enable bit in the PCI configspace Command Register.
// For the moment we are assuming that Read32() is handling endian issues
// for us.
config.EnableIoSpace(true);
// Read the Programming Interface (PI) Register from the PCI configuration space
byte programmingInterfaceValue = config.Read8(0x9);
// The high bit in the PI indicates the presence of bus-master DMA.
assert config.DynamicRanges != null;
if ((programmingInterfaceValue & 0x80) > 0 &&
config.DynamicRanges[4] as IoPortRange != null) {
IoPortRange! range = (IoPortRange!)(config.DynamicRanges[4]);
primary[3] = range.RangeAtOffset(0, 8, true, true);
secondary[3] = range.RangeAtOffset(8, 8, true, true);
DebugStub.Print("IdeBus: Interface supports BusMaster DMA, at {0}\n",
__arglist(range.ToString()));
}
// Next we decode the Native/Compat bits from the PI register
if ((programmingInterfaceValue & PCI_CONFIG_PI_PrimaryMode) > 0) {
//DebugStub.Print("Using Native mode PI={0:x2}\n",__arglist(programmingInterfaceValue));
primary[0] = config.GetIrq();
secondary[0] = config.GetIrq();
primary[1] = config.DynamicRanges[0];
primary[2] = config.DynamicRanges[1];
secondary[1] = config.DynamicRanges[2];
secondary[2] = config.DynamicRanges[3];
uint ideChannelConfig = config.Read32(0x50);
Tracing.Log(Tracing.Debug,"Channel Config= {0:x8}\n",
(UIntPtr)ideChannelConfig);
}
else {
//compat mode
primary[0] = new IoIrqRange(14, 1);
secondary[0] = new IoIrqRange(15, 1);
primary[1] = new IoPortRange(0x1F0, 8, Access.ReadWrite);
primary[2] = new IoPortRange(0x3F4, 4, Access.ReadWrite);
secondary[1] = new IoPortRange(0x170, 8, Access.ReadWrite);
secondary[2] = new IoPortRange(0x374, 4, Access.ReadWrite);
}
primaryConfig = new PnpConfig(new string[] { "/ata/controller" }, primary);
secondaryConfig = new PnpConfig(new string[] { "/ata/controller" }, secondary);
}
public void Finalize()
{
DebugStub.Print("IdeBus: Finalized.\n");
}
public SortedList Enumerate()
{
SortedList found = new SortedList();
found.Add("/controller0", primaryConfig);
found.Add("/controller1", secondaryConfig);
//FIXFIX: need to figure out why shared interrupt is not working. Post SOSP
//found.Add("/secondary",secondaryConfig);
return found;
}
}
}