192 lines
7.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
|