2008-03-05 09:52:00 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Microsoft Research Singularity
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
|
|
|
// File: ATA6.cs
|
|
|
|
//
|
|
|
|
// Base Classes and Interfaces for interacting with ATA
|
|
|
|
//
|
|
|
|
// References used:
|
|
|
|
// "AT Attachment with Packet Interface with Extension 6 (ATA/ATAPI-6-)",
|
|
|
|
// ISO Working Group T13, http://www.t13.org/
|
|
|
|
//
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading;
|
|
|
|
using Microsoft.SingSharp;
|
|
|
|
using Microsoft.Singularity;
|
|
|
|
using Microsoft.Singularity.Io;
|
|
|
|
using Microsoft.Singularity.Drivers.IDE;
|
|
|
|
using Microsoft.Singularity.V1.Services;
|
|
|
|
using Microsoft.Contracts;
|
|
|
|
|
|
|
|
namespace Microsoft.Singularity.Drivers.IDE
|
|
|
|
{
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public class IdeDiskConfig
|
|
|
|
{
|
|
|
|
public IdeConfig ControllerConfig;
|
|
|
|
public byte DiskNumber;
|
|
|
|
public bool Atapi;
|
|
|
|
public String! DeviceName;
|
|
|
|
public String! Id;
|
|
|
|
|
|
|
|
public IdeDiskConfig(IdeConfig config, byte num, String! deviceName, bool atapi)
|
|
|
|
{
|
|
|
|
ControllerConfig = config;
|
|
|
|
DiskNumber = num;
|
|
|
|
Atapi = atapi;
|
|
|
|
Id = "/ata/disk";
|
|
|
|
DeviceName = deviceName;
|
|
|
|
// Used to be "/dev/disk0", but now we use the instance name.
|
|
|
|
|
|
|
|
base();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class IdeConfig
|
|
|
|
{
|
|
|
|
public IoIrqRange Interrupt;
|
|
|
|
public bool UseDma;
|
|
|
|
public IoPortRange DmaBase;
|
|
|
|
public IoPortRange CommandBase;
|
|
|
|
public IoPortRange ControlBase;
|
|
|
|
public IdeController! IdeController;
|
|
|
|
public BusMasterDma BusMasterDma;
|
|
|
|
public IoIrq/*[!]*/ Irq;
|
|
|
|
public AutoResetEvent/*[!]*/ CommandEndEvent;
|
|
|
|
public AutoResetEvent/*[!]*/ IdentifyEndEvent;
|
|
|
|
public String Id;
|
|
|
|
|
|
|
|
public IdeConfig(IoIrqRange! interrupt,
|
|
|
|
IoPortRange! command,
|
|
|
|
IoPortRange! control,
|
|
|
|
bool useDma,
|
|
|
|
IoPortRange! bmBaseAddr,
|
|
|
|
[Delayed]
|
|
|
|
IdeController! ideController
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Interrupt = interrupt;
|
|
|
|
CommandBase = command;
|
|
|
|
ControlBase = control;
|
|
|
|
UseDma = useDma;
|
|
|
|
DmaBase = bmBaseAddr;
|
|
|
|
IdeController = ideController;
|
|
|
|
|
|
|
|
Id = "/ata/controller";
|
|
|
|
Tracing.Log(Tracing.Debug,"IdeConfig: INT={1} cmd={2:x4}, ctrl={3:x4}, DMA@{4:x4}\n",
|
|
|
|
(UIntPtr)interrupt.Irq,
|
|
|
|
(UIntPtr)command.Port,
|
|
|
|
(UIntPtr)control.Port,
|
|
|
|
(UIntPtr)bmBaseAddr.Port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public struct IdentifyDeviceInformation
|
|
|
|
// Information Returned to host via the IdentifyDeviceInformation command
|
|
|
|
{
|
|
|
|
public bool RemovableMediaDevice; // Word 0, Bit 7
|
|
|
|
public bool RemovableController; // Word 0, Bit 6
|
|
|
|
public ushort CylinderCount; // word 1
|
|
|
|
public ushort HeadCount; // word 3
|
|
|
|
public ushort SectorCountPerTrack; // Word 6
|
|
|
|
public string SerialNumber; // Words 10 to 19
|
|
|
|
public ushort NumberOfBytesAvailInVendorCommand; // Word 22
|
|
|
|
public string FirmwareRevision; // Words 23 to 26
|
|
|
|
public string ModelNumber; // Words 27 to 47
|
|
|
|
public bool SupportsMultiple; // Word 47, bits 7 to 0 == 0
|
|
|
|
public ushort MaximumMultipleSectorCount; // Word 47, bits 7 to 0
|
|
|
|
|
|
|
|
public bool StandbyTimer; // Word 49, bit 13
|
|
|
|
|
|
|
|
public bool IORDYSupported; // Word 49, bit 11
|
|
|
|
public bool IORDYDisableable; // Word 49, bit 10
|
|
|
|
public bool LBASupported; // Word 49, bit 9
|
|
|
|
public bool DMASupported; // Word 49, bit 8
|
|
|
|
|
|
|
|
public bool Word88Valid; // Word 53, bit 2
|
|
|
|
public bool UltraDmaSupported; // Word 53, bit 2 (same)
|
|
|
|
public bool Words64to70Valid; // Word 53, bit 1
|
|
|
|
public bool Words54to58Valid; // Word 53, bit 0
|
|
|
|
|
|
|
|
// Words 54-58 are valid if word 53, bit 0 is set.
|
|
|
|
|
|
|
|
public ushort CurrentLogicalCylinderCount; // Word 54
|
|
|
|
public ushort CurrentLogicalHeadCount; // Word 55
|
|
|
|
public ushort CurrentLogicalSectorCount; // Word 56
|
|
|
|
public uint CurrentCapacityInSectors; // Word 57-58
|
|
|
|
public bool MultipleSectorSettingValid; // Word 59, bits 8
|
|
|
|
public ushort CurrentSectorCountPerInterrupt; // Word 59
|
|
|
|
public uint TotalAddressableSectors; // Word 60-61
|
|
|
|
public ushort MultiwordDMATransferMode; // Word 63, 15-8
|
|
|
|
public ushort MultiwordDMATransferModes; // Word 63, 7-0
|
|
|
|
|
|
|
|
// Words 64-70 are valid if word 53, bit 1 is set.
|
|
|
|
|
|
|
|
public ushort PIODMATransferModes; // Word 64, bits 7-0
|
|
|
|
public ushort MinimumMultiwordDMACycleTime; // in nanoseconds Word 65
|
|
|
|
public ushort RecommendedMultiwordDMACycleTime; // in nanoseconds Word 66
|
|
|
|
public ushort MinimumPIOCycleTimeWithFlowControl; // in nanoseconds Word 67
|
|
|
|
public ushort MinimumPIOCycleTimeWithIORDY; // in nanoseconds Word 68
|
|
|
|
|
|
|
|
public ushort QueueDepth; // word 75, value == depth-1
|
|
|
|
public ushort MajorVersion; //word 80
|
|
|
|
public ushort MinorVersion; //word 81
|
|
|
|
|
|
|
|
public ushort FeatureSet1Supported;
|
|
|
|
public bool NOPSupported; // word 82, bit 14
|
|
|
|
public bool ReadBufferSupported; // word 82, bit 13
|
|
|
|
public bool WriteBufferSupported; // word 82, bit 12
|
|
|
|
public bool HostProtectedAreaSupported; // word 82, bit 10
|
|
|
|
public bool DeviceResetSupported; // word 82, bit 9
|
|
|
|
public bool ServiceInterruptSupported; // word 82, bit 8
|
|
|
|
public bool ReleaseInterruptSupported; // word 82, bit 7
|
|
|
|
public bool LookAheadSupported; // word 82, bit 6
|
|
|
|
public bool WriteCacheSupported; // word 82, bit 5
|
|
|
|
public bool PacketSupported; // word 82, bit 4
|
|
|
|
public bool PowerManagementSupported; // word 82, bit 3
|
|
|
|
public bool RemovableMediaSupported; // word 82, bit 2
|
|
|
|
public bool SecurityModeSupported; // word 82, bit 1
|
|
|
|
public bool SmartSupported; // word 82, bit 0
|
|
|
|
|
|
|
|
public ushort FeatureSet2Supported;
|
|
|
|
public bool FlushCacheExtSupported; // word 83, bit 13
|
|
|
|
public bool FlushCacheSupported; // word 83, bit 12
|
|
|
|
public bool DeviceConfigurationOverlaySupported; // word 83, bit 11
|
|
|
|
public bool LBA48Supported; // word 83, bit 10
|
|
|
|
public bool AutomaticAcousticManagementSupported; // word 83, bit 9
|
|
|
|
public bool SetMaxSecuritySupported; // word 83, bit 8
|
|
|
|
public bool AddressOffsetrAreaBootSupported; // word 83, bit 7
|
|
|
|
public bool SetFeaturesSupported; // word 83, bit 6
|
|
|
|
public bool PowerUpInStandbySupported; // word 83, bit 5
|
|
|
|
public bool RemovableMediaStatusNotificationSupported; // word 83, bit 4
|
|
|
|
public bool APMSupported; // word 83, bit 3
|
|
|
|
public bool CFASupported; // word 83, bit 2
|
|
|
|
public bool QueuedDMASupported; // word 83, bit 1
|
|
|
|
public bool DownloadMicrocodeSupported; // word 83, bit 0
|
|
|
|
|
|
|
|
public ushort FeatureSet3Supported;
|
|
|
|
public bool GeneralPurposeLoggingSupported; // word 83, bit 5
|
|
|
|
public bool MediaCardPssThroughSupported; // word 83, bit 3
|
|
|
|
public bool MediaSerialNumberSupported; // word 83, bit 2
|
|
|
|
public bool SmartSelfTestSupported; // word 83, bit 1
|
|
|
|
public bool SmartErrorLogSupported; // word 83, bit 0
|
|
|
|
|
|
|
|
public bool EnabledDataValid; // word 87, bits 15,14 (0x8000)
|
|
|
|
|
|
|
|
public ushort FeatureSet1Enabled;
|
|
|
|
public bool NOPEnabled; // word 85, bit 14
|
|
|
|
public bool ReadBufferEnabled; // word 85, bit 13
|
|
|
|
public bool WriteBufferEnabled; // word 85, bit 12
|
|
|
|
public bool HostProtectedAreaEnabled; // word 85, bit 10
|
|
|
|
public bool DeviceResetEnabled; // word 85, bit 9
|
|
|
|
public bool ServiceInterruptEnabled; // word 85, bit 8
|
|
|
|
public bool ReleaseInterruptEnabled; // word 85, bit 7
|
|
|
|
public bool LookAheadEnabled; // word 85, bit 6
|
|
|
|
public bool WriteCacheEnabled; // word 85, bit 5
|
|
|
|
public bool PacketEnabled; // word 85, bit 4
|
|
|
|
public bool PowerManagementEnabled; // word 85, bit 3
|
|
|
|
public bool RemovableMediaEnabled; // word 85, bit 2
|
|
|
|
public bool SecurityModeEnabled; // word 85, bit 1
|
|
|
|
public bool SmartEnabled; // word 85, bit 0
|
|
|
|
|
|
|
|
public ushort FeatureSet2Enabled;
|
|
|
|
public bool FlushCacheExtEnabled; // word 86, bit 13
|
|
|
|
public bool FlushCacheEnabled; // word 86, bit 12
|
|
|
|
public bool DeviceConfigurationOverlayEnabled; // word 86, bit 11
|
|
|
|
public bool LBA48Enabled; // word 86, bit 10
|
|
|
|
public bool AutomaticAcousticManagementEnabled; // word 86, bit 9
|
|
|
|
public bool SetMaxSecurityEnabled; // word 86, bit 8
|
|
|
|
public bool AddressOffsetrAreaBootEnabled; // word 86, bit 7
|
|
|
|
public bool SetFeaturesEnabled; // word 86, bit 6
|
|
|
|
public bool PowerUpInStandbyEnabled; // word 86, bit 5
|
|
|
|
public bool RemovableMediaStatusNotificationEnabled; // word 86, bit 4
|
|
|
|
public bool APMEnabled; // word 86, bit 3
|
|
|
|
public bool CFAEnabled; // word 86, bit 2
|
|
|
|
public bool QueuedDMAEnabled; // word 86, bit 1
|
|
|
|
public bool DownloadMicrocodeEnabled; // word 86, bit 0
|
|
|
|
|
|
|
|
public ushort FeatureSet3Enabled;
|
|
|
|
public bool GeneralPurposeLoggingEnabled; // word 87, bit 5
|
|
|
|
public bool MediaCardPssThroughEnabled; // word 87, bit 3
|
|
|
|
public bool MediaSerialNumberEnabled; // word 87, bit 2
|
|
|
|
public bool SmartSelfTestEnabled; // word 87, bit 1
|
|
|
|
public bool SmartErrorLogEnabled; // word 87, bit 0
|
|
|
|
|
|
|
|
|
|
|
|
//word 88 UltraDMA
|
|
|
|
public ushort UltraDmaModes; //word 88
|
|
|
|
public byte HighestUltraDmaMode; // Highest UDMA mode supported;
|
|
|
|
public bool UltraDmaMode5Selected; //word 88. bit 13
|
|
|
|
public bool UltraDmaMode4Selected; //word 88. bit 12
|
|
|
|
public bool UltraDmaMode3Selected; //word 88. bit 11
|
|
|
|
public bool UltraDmaMode2Selected; //word 88. bit 10
|
|
|
|
public bool UltraDmaMode1Selected; //word 88. bit 9
|
|
|
|
public bool UltraDmaMode0Selected; //word 88. bit 8
|
|
|
|
|
|
|
|
public bool UltraDmaMode5Supported; //word 88. bit 5
|
|
|
|
public bool UltraDmaMode4Supported; //word 88. bit 4
|
|
|
|
public bool UltraDmaMode3Supported; //word 88. bit 3
|
|
|
|
public bool UltraDmaMode2Supported; //word 88. bit 2
|
|
|
|
public bool UltraDmaMode1Supported; //word 88. bit 1
|
|
|
|
public bool UltraDmaMode0Supported; //word 88. bit 0
|
|
|
|
|
|
|
|
public ulong MaxLBASectors; //words 100-103
|
|
|
|
}
|
|
|
|
|
|
|
|
#region ATA6
|
|
|
|
public class ATA6
|
|
|
|
{
|
|
|
|
internal static string WordsToString(ushort[]! DriveData, int Start, int End)
|
|
|
|
{
|
|
|
|
int iter;
|
|
|
|
int length = End - Start;
|
|
|
|
ASCIIEncoding xlate = new ASCIIEncoding();
|
|
|
|
byte[] tempBuffer = new byte[(End - Start) * 2];
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
for (iter = 0; iter < length; iter++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
tempBuffer[iter * 2 + 1] = (byte)(DriveData[Start + iter] & (ushort)0xFF);
|
|
|
|
tempBuffer[iter * 2] = (byte)((DriveData[Start + iter] >> 8) & (ushort)0xFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
string ret = xlate.GetString(tempBuffer);
|
|
|
|
|
|
|
|
if (ret != null) {
|
|
|
|
ret = ret.Trim();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static byte HighestBitSet(ushort uiBits)
|
|
|
|
{
|
|
|
|
ushort uiMask = 0x80;
|
|
|
|
for (ushort nBit = 8; nBit > 0; nBit--, uiMask >>= 1) {
|
2008-11-17 18:29:00 -05:00
|
|
|
if ((uiBits & uiMask) > 0) {
|
2008-03-05 09:52:00 -05:00
|
|
|
return (byte)nBit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//public static uint MAX_SUPPORTED_SECTORS = 2048 * 128;
|
|
|
|
//public static uint MAX_SUPPORTED_SECTORS = 16383 * 16 * 63;
|
|
|
|
|
|
|
|
public static IdentifyDeviceInformation ParseIdentifyInformation(ushort[]! DriveData)
|
|
|
|
{
|
|
|
|
IdentifyDeviceInformation temp = new IdentifyDeviceInformation();
|
|
|
|
temp.RemovableMediaDevice = (DriveData[0] & (1<<7)) > 0;
|
|
|
|
temp.CylinderCount = DriveData[1];
|
|
|
|
temp.HeadCount = DriveData[3];
|
|
|
|
temp.SectorCountPerTrack = DriveData[6];
|
|
|
|
temp.SerialNumber = WordsToString(DriveData, 10, 19);
|
|
|
|
temp.NumberOfBytesAvailInVendorCommand = DriveData[22];
|
|
|
|
temp.FirmwareRevision = WordsToString(DriveData, 23, 26);
|
|
|
|
temp.ModelNumber = WordsToString(DriveData, 27, 46);
|
|
|
|
if ((DriveData[47] & (0xFF)) == 0) {
|
|
|
|
temp.SupportsMultiple = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
temp.SupportsMultiple = true;
|
|
|
|
temp.MaximumMultipleSectorCount = (ushort)(DriveData[47] & 0xFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
temp.StandbyTimer = ((DriveData[49] & (1 << 13))) > 0;
|
|
|
|
temp.IORDYSupported = ((DriveData[49] & (1 << 11))) > 0;
|
|
|
|
temp.IORDYDisableable = ((DriveData[49] & (1 << 10))) > 0;
|
|
|
|
temp.LBASupported = ((DriveData[49] & (1 << 9))) > 0;
|
|
|
|
temp.DMASupported = ((DriveData[49] & (1 << 8))) > 0;
|
|
|
|
//UltraDMA supported
|
|
|
|
temp.Word88Valid = ((DriveData[53] & (1 << 2))) > 0;
|
|
|
|
temp.UltraDmaSupported = temp.Word88Valid;
|
|
|
|
//this bit should always be true unless device is CFA or PCMCIA
|
|
|
|
temp.Words64to70Valid = ((DriveData[53] & (1 << 1))) > 0;
|
|
|
|
//obsolete
|
|
|
|
temp.Words54to58Valid = ((DriveData[53] & (1 << 0))) > 0;
|
|
|
|
|
|
|
|
// word 59: multiple sector setting
|
|
|
|
temp.MultipleSectorSettingValid = (DriveData[59] & (1 << 8)) > 0;
|
|
|
|
temp.CurrentSectorCountPerInterrupt = (ushort)(DriveData[59] & 0xFF);
|
|
|
|
|
|
|
|
// words 60,61: Total # of addressable sectors (+1)
|
|
|
|
temp.TotalAddressableSectors = ((uint)DriveData[61] << 16) | (uint)DriveData[60];
|
|
|
|
#if obsolete
|
|
|
|
if (temp.TotalAddressableSectors > MAX_SUPPORTED_SECTORS) {
|
|
|
|
temp.TotalAddressableSectors = MAX_SUPPORTED_SECTORS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// word 63: should be 0 if UltraDMA is supported
|
|
|
|
// bit 10: MDMA mode 2 selected
|
|
|
|
// bit 09: MDMA mode 1 selected
|
|
|
|
// bit 08: MDMA mode 0 selected
|
|
|
|
|
|
|
|
// bit 02: MDMA mode 2 supported
|
|
|
|
// bit 01: MDMA mode 1 supported
|
|
|
|
// bit 00: MDMA mode 0 supported
|
|
|
|
|
|
|
|
temp.MultiwordDMATransferMode = (ushort)((DriveData[63] & 0xFF00) >> 8);
|
|
|
|
temp.MultiwordDMATransferModes = (ushort)(DriveData[63] & 0xFF);
|
|
|
|
|
|
|
|
temp.PIODMATransferModes = (ushort)(DriveData[64] & 0xFF);
|
|
|
|
temp.MinimumMultiwordDMACycleTime = DriveData[65];
|
|
|
|
temp.RecommendedMultiwordDMACycleTime = DriveData[66];
|
|
|
|
temp.MinimumPIOCycleTimeWithFlowControl = DriveData[67];
|
|
|
|
temp.MinimumPIOCycleTimeWithIORDY = DriveData[68];
|
|
|
|
|
|
|
|
// value == maximum queue depth -1 (max = 31 +1)
|
|
|
|
temp.QueueDepth = (ushort)(DriveData[75] & 0x1F);
|
|
|
|
|
|
|
|
temp.MajorVersion = DriveData[80];
|
|
|
|
temp.MinorVersion = DriveData[81];
|
|
|
|
|
|
|
|
//Feature sets
|
|
|
|
temp.FeatureSet1Supported = DriveData[82];
|
|
|
|
temp.FeatureSet2Supported = DriveData[83];
|
|
|
|
temp.FeatureSet3Supported = DriveData[84];
|
|
|
|
temp.FeatureSet1Enabled = DriveData[85];
|
|
|
|
temp.FeatureSet2Enabled = DriveData[86];
|
|
|
|
temp.FeatureSet3Enabled = DriveData[87];
|
|
|
|
|
|
|
|
temp.LBA48Supported = ((DriveData[83] & (1 << 10))) > 0;
|
|
|
|
temp.LBA48Enabled = ((DriveData[86] & (1 << 10))) > 0;
|
|
|
|
|
|
|
|
temp.QueuedDMASupported = ((DriveData[83] & (1 << 1))) > 0;
|
|
|
|
temp.QueuedDMAEnabled = ((DriveData[86] & (1 << 1))) > 0;
|
|
|
|
|
|
|
|
if (temp.UltraDmaSupported) {
|
|
|
|
temp.UltraDmaModes = DriveData[88];
|
|
|
|
temp.HighestUltraDmaMode =
|
|
|
|
(byte) (HighestBitSet((ushort)(temp.UltraDmaModes & 0x3f)) - (byte) 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (temp.LBA48Supported) {
|
|
|
|
temp.MaxLBASectors = ((ulong)DriveData[103] << 48)
|
|
|
|
| ((ulong)DriveData[102] << 32)
|
|
|
|
| ((ulong)DriveData[101] << 16)
|
|
|
|
| (ulong)DriveData[100];
|
|
|
|
DebugStub.WriteLine("Disk Device supports LBA 48\n");
|
|
|
|
DebugStub.WriteLine("Total LBA sectors ={0}",__arglist(temp.MaxLBASectors));
|
|
|
|
//controller.WriteCommandPort( (byte) ATA6.IdeCommand.ReadNativeMaxAddressExt);
|
|
|
|
//controller.Delay400ns();
|
|
|
|
//DebugStub.WriteLine("ReadNativeMaxAddressExt:");
|
|
|
|
//ShowOffsetAndCount();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
temp.MaxLBASectors = temp.TotalAddressableSectors;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (temp.UltraDmaSupported) {
|
|
|
|
DebugStub.WriteLine("Disk Device supports Ultra DMA modes={0:x4},highest={1}",
|
|
|
|
__arglist(temp.UltraDmaModes,temp.HighestUltraDmaMode));
|
|
|
|
}
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static
|
|
|
|
IdentifyDeviceInformation GetDeviceIdentification(IdeController! controller,
|
|
|
|
int devsel, bool atapi)
|
|
|
|
{
|
|
|
|
ushort[] identifyData = new ushort[256];
|
|
|
|
|
|
|
|
if (!controller.PollBSY(false)) {
|
|
|
|
// should fail here.
|
|
|
|
}
|
|
|
|
controller.SelectDevice(devsel, atapi);
|
|
|
|
|
|
|
|
//DebugStub.Print(" IDE GetDeviceIdentification starting\n");
|
2008-11-17 18:29:00 -05:00
|
|
|
bool iflag = PrivilegedGate.DisableInterrupts();
|
2008-03-05 09:52:00 -05:00
|
|
|
try {
|
|
|
|
controller.SetIdentifyInProgress(true);
|
|
|
|
controller.PollDRDY(true);
|
|
|
|
byte cmd = (atapi)? (byte)IdeCommand.IdentifyPacketDevice:
|
|
|
|
(byte)IdeCommand.IdentifyDevice;
|
|
|
|
controller.WriteCommandPort(cmd); //will post interrupt
|
|
|
|
controller.Delay400ns();
|
|
|
|
Tracing.Log(Tracing.Debug,"status={0}",(UIntPtr) controller.ReadFullStatus());
|
|
|
|
controller.PollDRDY(true); // Device indicates ready.
|
|
|
|
}
|
|
|
|
finally {
|
2008-11-17 18:29:00 -05:00
|
|
|
PrivilegedGate.RestoreInterrupts(iflag);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
IdeConfig config = controller.GetConfig();
|
|
|
|
bool success = (config != null) && config.IdentifyEndEvent.WaitOne(TimeSpan.FromMilliseconds(250));
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
//DebugStub.Break();
|
|
|
|
Tracing.Log(Tracing.Debug," IDE GetDeviceIdentification did NOT receive interrupt\n");
|
|
|
|
controller.SetIdentifyInProgress(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//DebugStub.Print(" IDE GetDeviceIdentification received interrupt\n");
|
|
|
|
|
|
|
|
// XXX: We should check for an Error condition here.
|
|
|
|
// XXX: We should check for the ATAPI signature here.
|
|
|
|
|
|
|
|
byte statusBits = controller.ReadAlternateStatusPort();
|
|
|
|
if ((statusBits & (byte)ATA6.IdeStatus.ERR) > 0) {
|
|
|
|
Tracing.Log(Tracing.Debug,"ERR reported in status after IdentifyDevice!\n");
|
|
|
|
DebugStub.Break();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
|
|
identifyData[i] = controller.ReadDataPort();
|
|
|
|
}
|
|
|
|
|
|
|
|
IdentifyDeviceInformation ident = ParseIdentifyInformation(identifyData);
|
|
|
|
|
|
|
|
//// if (atapi)
|
|
|
|
if (ident.ModelNumber == "Virtual CD") // SECTOR_SIZE is actually 2048
|
|
|
|
ident.MaxLBASectors = 650 * 1024 * 1024 / IdeRequest.SECTOR_SIZE;
|
|
|
|
// for IdeDisk::ReadWrite tests
|
|
|
|
return ident;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void DebugQueryStatus(IdeController! controller)
|
|
|
|
{
|
|
|
|
byte statusBits = controller.ReadAlternateStatusPort();
|
|
|
|
byte errorBits = controller.ReadErrorPort();
|
|
|
|
|
|
|
|
Tracing.Log(Tracing.Debug,"ATAcontroller: Status Register({0:x2}): ",statusBits);
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte) ATA6.IdeStatus.BSY) > 0)
|
|
|
|
? "BSY " : "!bsy ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte)ATA6.IdeStatus.DRDY) > 0)
|
|
|
|
? "DRDY " : "!drdy ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte)ATA6.IdeStatus.DWF) > 0)
|
|
|
|
? "DWF " : "!dwf ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte)ATA6.IdeStatus.DSC) > 0)
|
|
|
|
? "DSC " : "!dsc ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte)ATA6.IdeStatus.DRQ) > 0)
|
|
|
|
? "DRQ " : "!drq ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte)ATA6.IdeStatus.CORR) > 0)
|
|
|
|
? "CORR " : "!corr ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte)ATA6.IdeStatus.IDX) > 0)
|
|
|
|
? "IDX " : "!idx");
|
|
|
|
Tracing.Log(Tracing.Debug, ((statusBits & (byte)ATA6.IdeStatus.ERR) > 0)
|
|
|
|
? "ERR " : "!err ");
|
|
|
|
Tracing.Log(Tracing.Debug,"\n");
|
|
|
|
|
|
|
|
Tracing.Log(Tracing.Debug,"ATAcontroller: Error Register:({0:x2}): ",errorBits);
|
|
|
|
Tracing.Log(Tracing.Debug, ((errorBits & (byte)ATA6.IdeError.UNC) > 0)
|
|
|
|
? "UNC " : "!unc ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((errorBits & (byte)ATA6.IdeError.MC) > 0)
|
|
|
|
? "MC " : "!mc ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((errorBits & (byte)ATA6.IdeError.IDNF) > 0)
|
|
|
|
? "IDNF " : "!idnf ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((errorBits & (byte)ATA6.IdeError.ABRT) > 0)
|
|
|
|
? "ABRT " : "!abrt ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((errorBits & (byte)ATA6.IdeError.MCR) > 0)
|
|
|
|
? "MCR " : "!mcr ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((errorBits & (byte)ATA6.IdeError.TK0NF) > 0)
|
|
|
|
? "TK0NF " : "!tk0nf ");
|
|
|
|
Tracing.Log(Tracing.Debug, ((errorBits & (byte)ATA6.IdeError.AMNF) > 0)
|
|
|
|
? "AMNF " : "!amnf ");
|
|
|
|
Tracing.Log(Tracing.Debug,"\n");
|
|
|
|
|
|
|
|
ushort lbaLow = controller.ReadLBALowPort();
|
|
|
|
ushort lbaMid = controller.ReadLBAMidPort();
|
|
|
|
ushort lbaHigh = controller.ReadLBAHighPort();
|
|
|
|
Tracing.Log(Tracing.Debug,"LBA={0:x2},{1:x2},{2:x2}\n",
|
|
|
|
(UIntPtr)lbaHigh, (UIntPtr)lbaMid, (UIntPtr)lbaLow);
|
|
|
|
}
|
|
|
|
|
|
|
|
public enum IdeCommand
|
|
|
|
{
|
|
|
|
Nop = 0x00,
|
|
|
|
Read = 0x20,
|
|
|
|
ReadNoRetry = 0x21,
|
|
|
|
ReadLong = 0x22,
|
|
|
|
ReadLongNoRetry = 0x23,
|
|
|
|
ReadDmaExt = 0x25,
|
|
|
|
ReadDmaQueuedExt = 0x26,
|
|
|
|
ReadNativeMaxAddressExt = 0x27,
|
|
|
|
Write = 0x30,
|
|
|
|
WriteNoRetry = 0x31,
|
|
|
|
WriteLong = 0x32,
|
|
|
|
WriteLongNoRetry = 0x33,
|
|
|
|
WriteDmaExt = 0x35,
|
|
|
|
WriteDmaQueuedExt = 0x36,
|
|
|
|
WriteVerify = 0x3C,
|
|
|
|
ReadVerify = 0x40,
|
|
|
|
ReadVerifyNoRetry = 0x41,
|
|
|
|
FormatTrack = 0x50,
|
|
|
|
Seek = 0x70,
|
|
|
|
ExecuteDeviceDiagnostic = 0x90,
|
|
|
|
InitializeDeviceParameters = 0x91,
|
|
|
|
DownloadMicrocode = 0x92,
|
|
|
|
AtapiPacket = 0xA0,
|
|
|
|
IdentifyPacketDevice = 0xA1,
|
|
|
|
ReadMultiple = 0xC4,
|
|
|
|
WriteMultiple = 0xC5,
|
|
|
|
SetMultipleMode = 0xC6,
|
|
|
|
ReadDmaQueued = 0xC7,
|
|
|
|
ReadDmaRetry = 0xC8,
|
|
|
|
ReadDmaNoRetry = 0xC9,
|
|
|
|
WriteDmaRetry = 0xCA,
|
|
|
|
WriteDmaNoRetry = 0xCB,
|
|
|
|
WriteDmaQueued = 0xCC,
|
|
|
|
AcknowledgeMediaChange = 0xDB,
|
|
|
|
BootPostBoot = 0xDC,
|
|
|
|
BootPreBoot = 0xDD,
|
|
|
|
DoorLock = 0xDE,
|
|
|
|
DoorUnLock = 0xDF,
|
|
|
|
ReadBuffer = 0xE4,
|
|
|
|
WriteBuffer = 0xE8,
|
|
|
|
WriteSame = 0xE9,
|
|
|
|
IdentifyDevice = 0xEC,
|
|
|
|
MediaEject = 0xED,
|
|
|
|
SetFeature = 0xEF,
|
|
|
|
}
|
|
|
|
|
|
|
|
public enum Atapi : byte
|
|
|
|
{
|
|
|
|
DMA = 0x01,
|
|
|
|
Read = 0x28,
|
|
|
|
}
|
|
|
|
|
|
|
|
public enum IdeStatus : byte
|
|
|
|
{
|
|
|
|
BSY = 0x80,
|
|
|
|
DRDY = 0x40,
|
|
|
|
DWF = 0x20,
|
|
|
|
DSC = 0x10,
|
|
|
|
DRQ = 0x08,
|
|
|
|
CORR = 0x04,
|
|
|
|
IDX = 0x02,
|
|
|
|
ERR = 0x01,
|
|
|
|
}
|
|
|
|
public enum IdeError
|
|
|
|
{
|
|
|
|
UNC = 0x40,
|
|
|
|
MC = 0x20,
|
|
|
|
IDNF = 0x10,
|
|
|
|
ABRT = 0x08,
|
|
|
|
MCR = 0x04,
|
|
|
|
TK0NF = 0x02,
|
|
|
|
AMNF = 0x01,
|
|
|
|
}
|
|
|
|
public const byte DriveSelect = 0x10; // Low = Master, High = Slave
|
|
|
|
|
|
|
|
public const bool High = true;
|
|
|
|
public const bool Low = false;
|
|
|
|
|
|
|
|
public const byte DeviceControlSRST = 0x04;
|
|
|
|
public const byte DeviceControlnIEN = 0x02; // note active low
|
|
|
|
|
|
|
|
// High Order Bit, used to read LBA 48 "previous" values in low,mid,and high port queues
|
|
|
|
public const byte DeviceControlHOB = 0x80;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|