Example #1
0
        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
        }