Esempio n. 1
0
        /// <summary>
        /// Get AHCI port type
        /// </summary>
        /// <param name="portReg">Port registers</param>
        /// <returns>Port type</returns>
        private AHCI_PORT_TYPE GetPortType(AHCI_Port_registers *portReg)
        {
            // Check if there is a device attached on the port.
            if ((portReg->SSTS & SSTS_DET_MASK) == SSTS_DET_NO)
            {
                return(AHCI_PORT_TYPE.NO);
            }

            // Check if port is active.
            if ((portReg->SSTS & SSTS_IPM_MASK) != SSTS_IPM_ACTIVE)
            {
                return(AHCI_PORT_TYPE.NO);
            }


            switch (portReg->SIG)
            {
            case SIG_SATA:
                return(AHCI_PORT_TYPE.SATA);

            case SIG_SATAPI:
                return(AHCI_PORT_TYPE.SATAPI);

            case SIG_SEMB:
                return(AHCI_PORT_TYPE.SEMB);

            case SIG_PM:
                return(AHCI_PORT_TYPE.PM);

            default:
                return(AHCI_PORT_TYPE.SATA);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Initalize device
        /// </summary>
        public unsafe void InitDevice()
        {
            // Check if its a memory bar
            if ((mPciDevice.BAR5.flags & Pci.BAR_IO) > 0)
            {
                Console.WriteLine("[AHCI] Device not MMIO!");
                return;
            }

            // Enable bus mastering
            Pci.EnableBusMastering(mPciDevice);


            int size = sizeof(AHCI_Generic_registers) + (sizeof(AHCI_Port_registers) * 32);

            mAddress        = (int)mPciDevice.BAR5.Address;
            mAddressVirtual = (int)Paging.MapToVirtual(Paging.CurrentDirectory, mAddress, size, Paging.PageFlags.Writable | Paging.PageFlags.Present);

            mGenericRegs = (AHCI_Generic_registers *)mAddressVirtual;
            mPorts       = (AHCI_Port_registers *)(mAddressVirtual + 0x100);

            ReadCapabilties();
            initPorts();

            Console.Write("[AHCI] Initalized at 0x");
            Console.WriteHex(mAddress & 0xFFFFFFFF);
            Console.WriteLine("");
        }
Esempio n. 3
0
        /// <summary>
        /// Start port
        /// </summary>
        /// <param name="portReg">Port register</param>
        private void startPort(AHCI_Port_registers *portReg)
        {
            // Wait till device ready
            while ((portReg->CMD & PxCMD_CR) > 0)
            {
                CPU.HLT();
            }

            portReg->CMD |= (PxCMD_ST) | (PxCMD_FRE);
        }
Esempio n. 4
0
        /// <summary>
        /// Stop port
        /// </summary>
        /// <param name="portReg">Port register</param>
        private void stopPort(AHCI_Port_registers *portReg)
        {
            portReg->CMD &= ~(uint)(PxCMD_ST);

            // Wait till device ready
            while ((portReg->CMD & PxCMD_CR) > 0)
            {
                CPU.HLT();
            }

            portReg->CMD &= ~(uint)(PxCMD_FRE);
        }
Esempio n. 5
0
        /// <summary>
        /// Find free command header on port
        /// </summary>
        /// <param name="port">Port info</param>
        /// <returns>Command header number</returns>
        private int findFreeCommandHeader(AHCIPortInfo port)
        {
            AHCI_Port_registers *portReg = port.PortRegisters;

            uint slotValues = (portReg->CI | portReg->SACT);

            // Find free slot.
            for (int i = 0; i < NUM_CMD_HEADERS; i++)
            {
                if ((slotValues & (1 << i)) == 0)
                {
                    return(i);
                }
            }

            // No free slot found.
            return(-1);
        }
Esempio n. 6
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);
        }
Esempio n. 7
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);
        }