Example #1
0
        /// <summary>
        /// ATA transfer
        /// </summary>
        /// <param name="info">AHCI port info</param>
        /// <param name="offset">LBA</param>
        /// <param name="count">Num of sectors</param>
        /// <param name="buffer">Buffer ptr</param>
        /// <param name="write">Write action?</param>
        /// <returns></returns>
        public int AtaTransfer(AHCIPortInfo info, int offset, int count, byte *buffer, bool write)
        {
            AHCI_Port_registers *portReg = info.PortRegisters;



            portReg->IS = 0;

            int fullCount = count * 512;

            int headerNumber = findFreeCommandHeader(info);

            if (headerNumber == -1)
            {
                return(0);
            }

            AHCI_Command_header *header = info.CommandHeader + headerNumber;

            header->Options = (ushort)((sizeof(AHCI_REG_H2D) / 4) | ((write? CMD_HEAD_WRITE: CMD_HEAD_READ)));


            int prdtl = (fullCount / 2024) + 1;

            header->Prdtl = (ushort)prdtl;

            byte *curBuf    = buffer;
            int   curOffset = 0;
            AHCI_Command_table_entry *cmdTable = (AHCI_Command_table_entry *)Heap.AlignedAlloc(128, sizeof(AHCI_Command_table_entry) + (sizeof(AHCI_PRDT_Entry) * prdtl));

            Memory.Memclear(cmdTable, sizeof(AHCI_Command_table_entry) + (sizeof(AHCI_PRDT_Entry) * prdtl));

            header->CTBA = (uint)Paging.GetPhysicalFromVirtual(cmdTable);

            for (int i = 0; i < header->Prdtl - 1; i++)
            {
                AHCI_PRDT_Entry *entry = (AHCI_PRDT_Entry *)((int)cmdTable + sizeof(AHCI_Command_table_entry) + (sizeof(AHCI_PRDT_Entry) * i));

                entry->DBA  = (uint)Paging.GetPhysicalFromVirtual(curBuf);
                entry->DBAU = 0x00;
                entry->Misc = 2023;

                curBuf    += 2024;
                curOffset += 2024;
            }

            AHCI_PRDT_Entry *lastEntry = (AHCI_PRDT_Entry *)((int)cmdTable + sizeof(AHCI_Command_table_entry) + (sizeof(AHCI_PRDT_Entry) * (prdtl - 1)));

            lastEntry->DBA  = (uint)Paging.GetPhysicalFromVirtual(curBuf);
            lastEntry->DBAU = 0x00;
            lastEntry->Misc = (fullCount - curOffset) - 1;

            AHCI_REG_H2D *fis = (AHCI_REG_H2D *)cmdTable->CFIS;

            fis->FisType = (int)AHCI_FIS.REG_H2D;
            fis->Command = ATA_CMD_READ_DMA_EX;
            fis->Options = (1 << 7);

            fis->LBA0   = (byte)(offset & 0xFF);
            fis->LBA1   = (byte)((offset >> 8) & 0xFF);
            fis->LBA2   = (byte)((offset >> 16) & 0xFF);
            fis->Device = (1 << 6);

            fis->LBA3 = 0x00;
            fis->LBA4 = 0x00;
            fis->LBA5 = 0x00;

            fis->CountLo = (byte)(count & 0xFF);
            fis->CountHi = (byte)((count >> 8) & 0xFF);

            // Wait until port ready
            while ((info.PortRegisters->TFD & (ATA_DEV_BUSY | ATA_DEV_DRQ)) > 0)
            {
                Tasking.Yield();
            }

            info.PortRegisters->CI = (uint)(1 << headerNumber);


            while (true)
            {
                if ((info.PortRegisters->CI & (1 << headerNumber)) == 0)
                {
                    break;
                }

                Tasking.Yield();
            }

            if ((info.PortRegisters->IS & PxIS_TFES) > 0)
            {
                return(0);
            }

            return(0);
        }
Example #2
0
        /// <summary>
        /// Initalize port
        /// </summary>
        /// <param name="portInfo">Port info</param>
        private void initPort(AHCIPortInfo portInfo)
        {
            AHCI_Port_registers *portReg = mPorts + portInfo.PortNumber;

            portInfo.CommandHeader = (AHCI_Command_header *)Heap.AlignedAlloc(4048, sizeof(AHCI_Command_header) * NUM_CMD_HEADERS);
            Memory.Memset(portInfo.CommandHeader, 0xFF, sizeof(AHCI_Command_header) * NUM_CMD_HEADERS);

            portInfo.Type = GetPortType(portReg);

            // Port found?
            if (portInfo.Type == AHCI_PORT_TYPE.NO)
            {
                return;
            }

            // NOTE: We support only SATA for now..
            if (portInfo.Type != AHCI_PORT_TYPE.SATA)
            {
                switch (portInfo.Type)
                {
                case AHCI_PORT_TYPE.PM:
                    Console.Write("[AHCI] Unsupported type PM found on port ");
                    Console.WriteNum(portInfo.PortNumber);
                    Console.WriteLine("");
                    break;

                case AHCI_PORT_TYPE.SATAPI:
                    Console.Write("[AHCI] Unsupported type SATAPI found on port ");
                    Console.WriteNum(portInfo.PortNumber);
                    Console.WriteLine("");
                    break;


                case AHCI_PORT_TYPE.SEMB:
                    Console.Write("[AHCI] Unsupported type SEMB found on port ");
                    Console.WriteNum(portInfo.PortNumber);
                    Console.WriteLine("");
                    break;
                }

                return;
            }

            stopPort(portReg);

            AHCI_Received_FIS *Fises = (AHCI_Received_FIS *)Heap.AlignedAlloc(256, sizeof(AHCI_Received_FIS));

            Memory.Memclear(Fises, sizeof(AHCI_Received_FIS));

            portReg->CLB  = (uint)Paging.GetPhysicalFromVirtual(portInfo.CommandHeader);
            portReg->CLBU = 0x00;

            portReg->FB  = (uint)Paging.GetPhysicalFromVirtual(Fises);
            portReg->FBU = 0x00;

            AHCI_Command_table_entry *cmdTable = (AHCI_Command_table_entry *)Heap.AlignedAlloc(128, sizeof(AHCI_Command_table_entry));

            Memory.Memclear(cmdTable, sizeof(AHCI_Command_table_entry));

            for (int i = 0; i < NUM_CMD_HEADERS; i++)
            {
                portInfo.CommandHeader[i].Prdtl = 0;
                portInfo.CommandHeader[i].CTBA  = (uint)cmdTable;
                portInfo.CommandHeader[i].CTBAU = 0x00;
            }

            startPort(portReg);

            portInfo.PortRegisters = portReg;


            char *name = (char *)Heap.Alloc(5);

            name[0] = 'H';
            name[1] = 'D';
            name[2] = 'A';
            name[3] = (char)('0' + portInfo.PortNumber);
            name[4] = '\0';
            string nameStr = Util.CharPtrToString(name);

            Node node = new Node();

            node.Read = readImpl;
            //node.Write = writeImpl;

            AHCICookie cookie = new AHCICookie();

            cookie.AHCI     = this;
            cookie.PortInfo = portInfo;

            node.Cookie = cookie;

            Disk.InitalizeNode(node, nameStr);

            RootPoint dev = new RootPoint(nameStr, node);

            VFS.MountPointDevFS.AddEntry(dev);
        }