/// <summary> /// Reads contiguous blocks from the drive. /// </summary> /// <param name="aBlockNo">The number of the first block to read.</param> /// <param name="aBlockCount">The number of contiguous blocks to read.</param> /// <param name="aData">The data array to read into.</param> public override void ReadBlock(UInt64 aBlockNo, UInt32 aBlockCount, byte[] aData) { if (!BaseDevice.initialised) { return; } SelectSector(aBlockNo, aBlockCount); BaseDevice.SendCmd(PATABase.Cmd.ReadPio); BaseDevice.IO.Data.Read_Bytes(aData); }
private void _ReadBlock(ulong aBlockNo, byte[] aData, uint DataOffset) { // Setup the packet #if PATAPI_TRACE BasicConsole.WriteLine("Setup ATAPI packet"); #endif byte[] atapi_packet = new byte[12]; atapi_packet[0] = 0xA8; atapi_packet[1] = 0x0; atapi_packet[2] = (byte)(aBlockNo >> 24); atapi_packet[3] = (byte)(aBlockNo >> 16); atapi_packet[4] = (byte)(aBlockNo >> 8); atapi_packet[5] = (byte)(aBlockNo >> 0); atapi_packet[6] = 0x0; atapi_packet[7] = 0x0; atapi_packet[8] = 0x0; atapi_packet[9] = 1; atapi_packet[10] = 0x0; atapi_packet[11] = 0x0; // Inform the controller we are using PIO mode #if PATAPI_TRACE BasicConsole.WriteLine("Tell controller we are using PIO mode"); #endif BaseDevice.IO.Features.Write_Byte(0); // Tell the drive the buffer size #if PATAPI_TRACE BasicConsole.WriteLine("Tell drive the buffer size"); #endif BaseDevice.IO.LBA1.Write_Byte((byte)BlockSize); // Low byte BaseDevice.IO.LBA1.Write_Byte((byte)(BlockSize >> 8)); // High byte // Send the packet command (includes the wait) #if PATAPI_TRACE BasicConsole.WriteLine("Send Packet command"); #endif PATABase.Status xStatus = BaseDevice.SendCmd(PATABase.Cmd.Packet); // Error occurred #if PATAPI_TRACE BasicConsole.WriteLine("Check for error"); #endif if ((xStatus & PATABase.Status.Error) != 0) { #if PATAPI_TRACE BasicConsole.WriteLine("Error detected"); #endif ExceptionMethods.Throw(new Exceptions.NoDiskException("ATAPI read error! Status bits incorrect in first check.")); } // Check if that invoked an IRQ - it shouldn't have #if PATAPI_TRACE BasicConsole.WriteLine("Check if IRQ invoked"); #endif if (IRQInvoked) { #if PATAPI_TRACE BasicConsole.WriteLine("IRQ had been invoked"); #endif // Allow future IRQs by reading Status register BaseDevice.IO.Status.Read_Byte(); IRQInvoked = false; } // Send the data #if PATAPI_TRACE BasicConsole.WriteLine("Write packet data"); #endif BaseDevice.IO.Data.Write_UInt16s(atapi_packet); // Wait a bit #if PATAPI_TRACE BasicConsole.WriteLine("Brief wait"); #endif BaseDevice.Wait(); // Wait for the IRQ #if PATAPI_TRACE BasicConsole.WriteLine("Wait for IRQ"); #endif if (WaitForIRQ()) { #if PATAPI_TRACE BasicConsole.WriteLine("Error! Wait for IRQ timed out."); BasicConsole.DelayOutput(5); #endif } // Wait for Busy to clear and check alternate status #if PATAPI_TRACE BasicConsole.WriteLine("Wait till not busy"); #endif uint timeout = 0xF0000000; do { BaseDevice.Wait(); xStatus = (PATABase.Status)BaseDevice.IO.Control.Read_Byte(); } while ((xStatus & PATABase.Status.Busy) != 0 && (xStatus & PATABase.Status.Error) == 0 && timeout-- > 0); // Read status reg to clear IRQ #if PATAPI_TRACE BasicConsole.WriteLine("Read status"); #endif xStatus = (PATABase.Status)BaseDevice.IO.Status.Read_Byte(); IRQInvoked = false; // Error occurred #if PATAPI_TRACE BasicConsole.WriteLine("Check for error"); #endif if ((xStatus & (PATABase.Status.Error | PATABase.Status.ATA_SR_DF)) != 0 || (xStatus & PATABase.Status.DRQ) == 0) { #if PATAPI_TRACE BasicConsole.WriteLine("Error detected"); #endif ExceptionMethods.Throw(new Exceptions.NoDiskException("ATAPI read error! Status bits incorrect in second check.")); } // Read the data #if PATAPI_TRACE BasicConsole.WriteLine("Read the data"); BasicConsole.WriteLine("Length: " + (FOS_System.String)aData.Length); #endif uint offset = DataOffset + 1; uint i = 0; for (; i < BlockSize && offset < aData.Length; i += 2, offset += 2) { UInt16 val = BaseDevice.IO.Data.Read_UInt16(); aData[offset - 1] = (byte)(val); aData[offset] = (byte)(val >> 8); } // Clear out any remaining data for (; i < BlockSize; i++) { BaseDevice.IO.Data.Read_UInt16(); } #if PATAPI_TRACE unsafe { BasicConsole.DumpMemory((byte *)Utilities.ObjectUtilities.GetHandle(aData) + FOS_System.Array.FieldsBytesSize, aData.Length); } BasicConsole.WriteLine("Wait for IRQ"); #endif // Wait for IRQ if (WaitForIRQ()) { #if PATAPI_TRACE BasicConsole.WriteLine("Error! Wait for IRQ timed out. (1)"); BasicConsole.DelayOutput(5); #endif } // Wait for Busy and DRQ to clear and check status #if PATAPI_TRACE BasicConsole.WriteLine("Wait till not busy"); #endif timeout = 0xF0000000; do { BaseDevice.Wait(); xStatus = (PATABase.Status)BaseDevice.IO.Control.Read_Byte(); } while ((xStatus & (PATABase.Status.Busy | PATABase.Status.DRQ)) != 0 && (xStatus & PATABase.Status.Error) == 0 && timeout-- > 0); // Error occurred #if PATAPI_TRACE BasicConsole.WriteLine("Check for error"); #endif if ((xStatus & (PATABase.Status.Error | PATABase.Status.ATA_SR_DF)) != 0 || (xStatus & (PATABase.Status.DRQ)) != 0) { #if PATAPI_TRACE BasicConsole.WriteLine("Error detected"); #endif ExceptionMethods.Throw(new FOS_System.Exception("ATAPI read error! Status bits incorrect in third check.")); } #if PATAPI_TRACE BasicConsole.WriteLine("Complete"); BasicConsole.DelayOutput(10); #endif }