예제 #1
0
파일: PATAPI.cs 프로젝트: zrbruce/FlingOS
        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
        }
예제 #2
0
        protected override void _IssueTransfer(USBTransfer transfer)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Issue Transfer");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction firstTransaction = (UHCITransaction)((USBTransaction)transfer.transactions[0]).underlyingTz;
            UHCITransaction lastTransaction  = (UHCITransaction)((USBTransaction)transfer.transactions[transfer.transactions.Count - 1]).underlyingTz;
            UHCI_qTD.SetIntOnComplete(lastTransaction.qTD, true);  // We want an interrupt after complete transfer
            CreateQH((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint)transfer.underlyingTransferData, firstTransaction.qTD);

#if UHCI_TRACE
            BasicConsole.WriteLine("    Queue head data:");
            BasicConsole.DumpMemory(transfer.underlyingTransferData, sizeof(UHCI_QueueHead_Struct));
            BasicConsole.WriteLine("    Transactions data:");
            for (int i = 0; i < transfer.transactions.Count; i++)
            {
                BasicConsole.Write(" ");
                BasicConsole.Write(i);
                BasicConsole.WriteLine(" : ");
                BasicConsole.WriteLine("  - qTD:");
                BasicConsole.DumpMemory(
                    ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTD, sizeof(UHCI_qTD_Struct));
                BasicConsole.WriteLine("  - qTDBuffer:");
                BasicConsole.DumpMemory(
                    ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTDBuffer, 16);
            }
            BasicConsole.DelayOutput(60);

            BasicConsole.WriteLine("UHCI: Issuing transfer...");
#endif

            for (byte i = 0; i < UHCI_Consts.NUMBER_OF_UHCI_RETRIES && !transfer.success; i++)
            {
                TransactionsCompleted = 0;
                for (int j = 0; j < transfer.transactions.Count; j++)
                {
                    USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                    UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                    uT.qTD->u1 = uT.qTD->u1 & 0xFF00FFFF;
                    UHCI_qTD.SetActive(uT.qTD, true);
                }

                // stop scheduler
                USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
                USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() & ~UHCI_Consts.CMD_RS));
                while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) == 0)
                {
                    Hardware.Devices.Timer.Default.Wait(10);
                }

                // update scheduler
                uint qhPhysAddr = ((uint)VirtMemManager.GetPhysicalAddress(transfer.underlyingTransferData) | UHCI_Consts.BIT_QH);
                FrameList[0] = qhPhysAddr;
                FRBASEADD.Write_UInt32((uint)VirtMemManager.GetPhysicalAddress(FrameList));
                FRNUM.Write_UInt16(0);
                // start scheduler
                USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
                USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() | UHCI_Consts.CMD_RS));
                while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) != 0)
                {
                    Hardware.Devices.Timer.Default.Wait(10);
                }

#if UHCI_TRACE
                BasicConsole.WriteLine(((FOS_System.String) "USBINT val: ") + USBINTR.Read_UInt16());
#endif

                // run transactions
                bool active  = true;
                int  timeout = 100; //5 seconds
                while (active && timeout > 0)
                {
                    active = false;
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                        active = active || ((uT.qTD->u1 & 0x00FF0000) == 0x00800000);
                    }

                    Hardware.Devices.Timer.Default.Wait(50);
                    timeout--;
                }

#if UHCI_TRACE
                BasicConsole.WriteLine("Finished waiting.");
#endif

                FrameList[0] = UHCI_Consts.BIT_T;

                if (timeout == 0 ||
                    TransactionsCompleted != transfer.transactions.Count)
                {
#if UHCI_TRACE
                    BasicConsole.SetTextColour(BasicConsole.error_colour);
                    BasicConsole.WriteLine("UHCI: Error! Transactions wait timed out or wrong number of transactions completed.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);

                    BasicConsole.WriteLine(((FOS_System.String) "Transactions completed: ") + TransactionsCompleted);

                    if (timeout == 0)
                    {
                        BasicConsole.SetTextColour(BasicConsole.error_colour);
                        BasicConsole.WriteLine("UHCI: Error! Transfer timed out.");
                        BasicConsole.SetTextColour(BasicConsole.default_colour);
                    }
#endif

                    transfer.success = false;

                    bool completeDespiteNoInterrupt = true;
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);

#if UHCI_TRACE
                        BasicConsole.WriteLine(((FOS_System.String) "u1=") + uT.qTD->u1 + ", u2=" + uT.qTD->u2);
                        BasicConsole.WriteLine(((FOS_System.String) "Status=") + (byte)(uT.qTD->u1 >> 16));
#endif
                        completeDespiteNoInterrupt = completeDespiteNoInterrupt && isTransactionSuccessful(uT);
                    }

                    transfer.success = completeDespiteNoInterrupt;

#if UHCI_TRACE
                    BasicConsole.SetTextColour(BasicConsole.warning_colour);
                    BasicConsole.WriteLine(((FOS_System.String) "Complete despite no interrupts: ") + completeDespiteNoInterrupt);
                    BasicConsole.SetTextColour(BasicConsole.default_colour);

                    BasicConsole.DelayOutput(5);
#endif
                }
                else
                {
                    transfer.success = true;
                }

                if (transfer.success)
                {
                    // check conditions and save data
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                        transfer.success = transfer.success && isTransactionSuccessful(uT); // executed w/o error

                        if (uT.inBuffer != null && uT.inLength != 0)
                        {
                            MemoryUtils.MemCpy_32((byte *)uT.inBuffer, (byte *)uT.qTDBuffer, uT.inLength);
                        }
                    }
                }

#if UHCI_TRACE
                if (!transfer.success)
                {
                    BasicConsole.SetTextColour(BasicConsole.error_colour);
                    BasicConsole.WriteLine("UHCI: Transfer failed.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);
                }
                else
                {
                    BasicConsole.SetTextColour((char)0x0200);
                    BasicConsole.WriteLine("Transfer succeeded.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);
                }
#endif
            }
        }
예제 #3
0
        /// <summary>
        /// Reads the specified number of bytes from the stream from the current position into the buffer at the
        /// specified offset or as many bytes as are available before the end of the stream is met.
        /// </summary>
        /// <param name="buffer">The byte array to read into.</param>
        /// <param name="offset">The offset within the buffer to start storing read data at.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>The actual number of bytes read.</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            //Don't attempt to read a file of 0 size.
            if (TheFile.Size > 0)
            {
                ISO9660FileSystem TheFS = TheISO9660FileSystem;

#if ISO9660FileStream_TRACE
                BasicConsole.WriteLine("Checking params...");
#endif

                //Conditions for being able to read from the stream.
                if (count < 0)
                {
                    ExceptionMethods.Throw(new Exceptions.ArgumentException("ISO9660FileStream.Read: aCount must be > 0"));
                }
                else if (offset < 0)
                {
                    ExceptionMethods.Throw(new Exceptions.ArgumentException("ISO9660FileStream.Read: anOffset must be > 0"));
                }
                else if (buffer == null)
                {
                    ExceptionMethods.Throw(new Exceptions.ArgumentException("ISO9660FileStream.Read: aBuffer must not be null!"));
                }
                else if (buffer.Length - offset < count)
                {
                    ExceptionMethods.Throw(new Exceptions.ArgumentException("ISO9660FileStream.Read: Invalid offset / length values!"));
                }
                else if (position == TheFile.Size)
                {
                    // EOF
                    return(0);
                }

#if ISO9660FileStream_TRACE
                BasicConsole.WriteLine("Params OK.");
#endif

                // Clamp the count value so that no out of bounds exceptions occur
                ulong FileSize         = TheFile.Size;
                ulong MaxReadableBytes = FileSize - position;
                ulong ActualCount      = (ulong)count;
                if (ActualCount > MaxReadableBytes)
                {
                    ActualCount = MaxReadableBytes;
                }

#if ISO9660FileStream_TRACE
                BasicConsole.WriteLine("Creating new sector array...");
#endif

                //Temporary store of cluster data since we can only
                //  read entire clusters at a time.
                if (ReadSectorBuffer == null)
                {
                    ReadSectorBuffer = TheFS.ThePartition.NewBlockArray(1);
                    ReadSectorSize   = (uint)TheFS.ThePartition.BlockSize;

#if ISO9660FileStream_TRACE
                    BasicConsole.WriteLine(((FOS_System.String) "ReadSectorSize: ") + ReadSectorSize);
#endif
                }

                int read = 0;

#if ISO9660FileStream_TRACE
                BasicConsole.WriteLine("Reading data...");
#endif
                //Loop reading in the data
                while (ActualCount > 0)
                {
                    UInt32 SectorIdx   = ((UInt32)position / ReadSectorSize) + TheISO9660File.TheDirectoryRecord.LBALocation;
                    UInt32 PosInSector = (UInt32)position % ReadSectorSize;
#if ISO9660FileStream_TRACE
                    BasicConsole.WriteLine(((FOS_System.String) "Reading sector ") + SectorIdx);
#endif
                    TheFS.ThePartition.ReadBlock(SectorIdx, 1, ReadSectorBuffer);
#if ISO9660FileStream_TRACE
                    BasicConsole.WriteLine("Read sector.");
#endif
                    uint ReadSize;
                    if (PosInSector + ActualCount > ReadSectorSize)
                    {
                        ReadSize = ReadSectorSize - PosInSector;
                    }
                    else
                    {
                        ReadSize = (uint)ActualCount;
                    }

#if ISO9660FileStream_TRACE
                    BasicConsole.WriteLine("Read sector buffer: ");
                    unsafe
                    {
                        BasicConsole.DumpMemory((byte *)Utilities.ObjectUtilities.GetHandle(ReadSectorBuffer) + FOS_System.Array.FieldsBytesSize, ReadSectorBuffer.Length);
                    }
#endif
                    // TODO: Should we do an argument check here just in case?
                    FOS_System.Array.Copy(ReadSectorBuffer, (int)PosInSector, buffer, offset, (int)ReadSize);
                    offset      += (int)ReadSize;
                    ActualCount -= (ulong)ReadSize;
                    read        += (int)ReadSize;
                    position    += ReadSize;
                }

#if ISO9660FileStream_TRACE
                BasicConsole.WriteLine("Read data.");
#endif

                return(read);
            }
            else
            {
                return(0);
            }
        }