Example #1
0
 public void command_ok()
 {
     state      = HD_STATE.S_IDLE;
     transptr   = 0xFFFFFFFF;
     reg.err    = 0;
     reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC;
 }
Example #2
0
        public void read_sectors()
        {
            //   __debugbreak();
            intrq = true;
            if (!seek())
            {
                return;
            }

            if (LogIo)
            {
                Logger.Info("ATA{0:X2}: IDE HDD READ SECTOR", Id);
            }
            if (!ata_p.ReadSector(transbf, 0))
            {
                reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR;
                reg.err    = HD_ERROR.ERR_UNC | HD_ERROR.ERR_IDNF;
                state      = HD_STATE.S_IDLE;
                return;
            }
            transptr   = 0;
            transcount = 0x100;
            state      = HD_STATE.S_READ_SECTORS;
            reg.err    = HD_ERROR.ERR_NONE;
            reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;

            /*
             * if(reg.devhead & 0x40)
             *     printf("dev=%d lba=%d\n", device_id, *(unsigned*)(regs+3) & 0x0FFFFFFF);
             * else
             *     printf("dev=%d c/h/s=%d/%d/%d\n", device_id, reg.cyl, (reg.devhead & 0xF), reg.sec);
             */
        }
Example #3
0
        public void write(AtaReg n_reg, byte data)
        {
            //   printf("dev=%d, reg=%d, data=%02X\n", device_id, n_reg, data);
            if (!loaded())
            {
                return;
            }
            if (n_reg == AtaReg.FeatureError)
            {
                reg.feat = data;
                return;
            }

            if (n_reg != AtaReg.CommandStatus)
            {
                regs[(int)n_reg] = data;
                if ((reg.control & HD_CONTROL.CONTROL_SRST) != 0)
                {
                    //          printf("dev=%d, reset\n", device_id);
                    reset(RESET_TYPE.RESET_SRST);
                }
                return;
            }

            // execute command!
            if (((reg.devhead ^ device_id) & 0x10) != 0 &&
                data != 0x90)
            {
                return;
            }
            if ((reg.status & HD_STATUS.STATUS_DRDY) == 0 && !atapi)
            {
                Logger.Warn("ATA{0:X2}: hdd not ready cmd = #{1:X2} (ignored)", Id, data);
                return;
            }

            reg.err = HD_ERROR.ERR_NONE;
            intrq   = false;

            //{printf(" [");for (int q=1;q<9;q++) printf("-%02X",regs[q]);printf("]\n");}
            if (exec_atapi_cmd(data))
            {
                return;
            }
            if (exec_ata_cmd(data))
            {
                return;
            }
            reg.status = HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_ERR;
            reg.err    = HD_ERROR.ERR_ABRT;
            state      = HD_STATE.S_IDLE;
            intrq      = true;
        }
Example #4
0
        public bool exec_atapi_cmd(byte cmd)
        {
            if (!atapi)
            {
                return(false);
            }

            // soft reset
            if (cmd == 0x08)
            {
                reset(RESET_TYPE.RESET_SOFT);
                return(true);
            }
            if (cmd == 0xA1) // IDENTIFY PACKET DEVICE
            {
                prepare_id();
                return(true);
            }

            if (cmd == 0xA0)
            { // packet
                state         = HD_STATE.S_RECV_PACKET;
                reg.status    = HD_STATUS.STATUS_DRQ;
                reg.intreason = ATAPI_INT_REASON.INT_COD;
                transptr      = 0;
                transcount    = 6;
                return(true);
            }

            if (cmd == 0xEC)
            {
                reg.count = 1;
                reg.sec   = 1;
                reg.cyl   = 0xEB14;

                reg.status = HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_ERR;
                reg.err    = HD_ERROR.ERR_ABRT;
                state      = HD_STATE.S_IDLE;
                intrq      = true;
                return(true);
            }

            Logger.Error("ATA{0:X2}: Unknown ATAPI command #{1:X2}", Id, cmd);
            // "command aborted" with ATAPI signature
            reg.count = 1;
            reg.sec   = 1;
            reg.cyl   = 0xEB14;
            return(false);
        }
Example #5
0
        public void prepare_id()
        {
            if (phys_dev == -1)
            {
                for (int i = 0; i < 512; i++)
                {
                    transbf[i] = 0;
                }
                make_ata_string(transbf, 10 * 2, 10, _deviceInfo.SerialNumber);    // Serial number
                make_ata_string(transbf, 23 * 2, 4, _deviceInfo.FirmwareRevision); // Firmware revision
                make_ata_string(transbf, 27 * 2, 20, _deviceInfo.ModelNumber);     // Model number

                setUInt16(transbf, 0 * 2, 0x045A);                                 // [General configuration]
                setUInt16(transbf, 1 * 2, (UInt16)c);
                setUInt16(transbf, 3 * 2, (UInt16)h);
                setUInt16(transbf, 6 * 2, (UInt16)s);
                setUInt16(transbf, 20 * 2, 3);                  // a dual ported multi-sector buffer capable of simultaneous transfers with a read caching capability
                setUInt16(transbf, 21 * 2, 512);                // cache size=256k
                setUInt16(transbf, 22 * 2, 4);                  // ECC bytes
                setUInt16(transbf, 49 * 2, 0x200);              // LBA supported
                setUInt32(transbf, 60 * 2, lba);                // [Total number of user addressable logical sectors]
                setUInt16(transbf, 80 * 2, 0x3E);               // support specifications up to ATA-5
                setUInt16(transbf, 81 * 2, 0x13);               // ATA/ATAPI-5 T13 1321D revision 3
                setUInt16(transbf, 82 * 2, 0x60);               // supported look-ahead and write cache

                // make checksum
                transbf[510] = 0xA5;
                byte cs = 0;
                for (int i = 0; i < 511; i++)
                {
                    cs += transbf[i];
                }
                transbf[511] = (byte)(0 - cs);
            }
            else
            { // copy as is...
              //for(int i=0; i < 512; i++)
              //	transbf[i] = phys[phys_dev].idsector[i];
            }

            state      = HD_STATE.S_READ_ID;
            transptr   = 0;
            transcount = 0x100;
            intrq      = true;
            reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
            reg.err    = HD_ERROR.ERR_NONE;
        }
Example #6
0
        public void write_sectors()
        {
            intrq = true;
            //printf(" [write] ");
            if (!seek())
            {
                return;
            }

            if (LogIo)
            {
                Logger.Info("ATA{0:X2}: IDE HDD WRITE SECTOR", Id);
            }
            if (!ata_p.WriteSector(transbf, 0))
            {
                reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR;
                reg.err    = HD_ERROR.ERR_UNC;
                state      = HD_STATE.S_IDLE;
                return;
            }

            if (--reg.count == 0)
            {
                command_ok();
                return;
            }
            next_sector();

            transptr   = 0;
            transcount = 0x100;
            state      = HD_STATE.S_WRITE_SECTORS;
            reg.err    = HD_ERROR.ERR_NONE;
            // Alex: DRDY added for SPRINTER
            ///Missing DRDY produce not ready error on write operation
            reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
        }
Example #7
0
        public bool exec_ata_cmd(byte cmd)
        {
            //   printf(__FUNCTION__" cmd=%02X\n", cmd);
            // EXECUTE DEVICE DIAGNOSTIC for both ATA and ATAPI
            if (cmd == 0x90)
            {
                reset_signature(RESET_TYPE.RESET_SOFT);
                return(true);
            }

            if (atapi)
            {
                return(false);
            }

            // [DEVICE RESET]
            if (cmd == 0x08)
            {
                reset(RESET_TYPE.RESET_SOFT);
                return(true);
            }
            // INITIALIZE DEVICE PARAMETERS
            if (cmd == 0x91)
            {
                // pos = (reg.cyl * h + (reg.devhead & 0x0F)) * s + reg.sec - 1;
                h = (uint)((reg.devhead & 0xF) + 1);
                s = reg.count;
                if (s == 0)
                {
                    reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DF | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR;
                    return(true);
                }

                c = lba / s / h;

                reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC;
                return(true);
            }

            if ((cmd & 0xFE) == 0x20) // ATA-3 (mandatory), read sectors
            {                         // cmd #21 obsolette, rqd for is-dos
                //       printf(__FUNCTION__" sec_cnt=%d\n", reg.count);
                read_sectors();
                return(true);
            }

            if ((cmd & 0xFE) == 0x40) // ATA-3 (mandatory),  verify sectors
            {                         //rqd for is-dos
                verify_sectors();
                return(true);
            }

            if ((cmd & 0xFE) == 0x30) // ATA-3 (mandatory), write sectors
            {
                if (seek())
                {
                    state      = HD_STATE.S_WRITE_SECTORS;
                    reg.status = HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
                    transptr   = 0;
                    transcount = 0x100;
                }
                return(true);
            }

            if (cmd == 0x50) // format track (данная реализация - ничего не делает)
            {
                reg.sec = 1;
                if (seek())
                {
                    state      = HD_STATE.S_FORMAT_TRACK;
                    reg.status = HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
                    transptr   = 0;
                    transcount = 0x100;
                }
                return(true);
            }

            if (cmd == 0xEC)
            {
                prepare_id();
                return(true);
            }

            if (cmd == 0xE7)
            { // FLUSH CACHE
                if (ata_p.Flush())
                {
                    command_ok();
                    intrq = true;
                }
                else
                {
                    reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DF | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR; // 0x71
                }
                return(true);
            }

            if (cmd == 0x10)
            {
                recalibrate();
                command_ok();
                intrq = true;
                return(true);
            }

            if (cmd == 0x70)
            { // seek
                if (!seek())
                {
                    return(true);
                }
                command_ok();
                intrq = true;
                return(true);
            }

            Logger.Error("ATA{0:X2}: Unknown ATA command #{1:X2}", Id, cmd);
            return(false);
        }
Example #8
0
        public void write(int n_reg, byte data)
        {
            //   printf("dev=%d, reg=%d, data=%02X\n", device_id, n_reg, data);
            if (!loaded())
                return;
            if (n_reg == 1)
            {
                reg.feat = data;
                return;
            }

            if (n_reg != 7)
            {
                regs[n_reg] = data;
                if ((reg.control & HD_CONTROL.CONTROL_SRST) != 0)
                {
                    //          printf("dev=%d, reset\n", device_id);
                    reset(RESET_TYPE.RESET_SRST);
                }
                return;
            }

            // execute command!
            if (((reg.devhead ^ device_id) & 0x10) != 0 && data != 0x90)
                return;
            if ((reg.status & HD_STATUS.STATUS_DRDY) == 0 && !atapi)
            {
                LogAgent.Warn("hdd not ready cmd = #{0:X2} (ignored)", data);
                return;
            }

            reg.err = HD_ERROR.ERR_NONE;
            intrq = false;

            //{printf(" [");for (int q=1;q<9;q++) printf("-%02X",regs[q]);printf("]\n");}
            if (exec_atapi_cmd(data))
                return;
            if (exec_ata_cmd(data))
                return;
            reg.status = HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_ERR;
            reg.err = HD_ERROR.ERR_ABRT;
            state = HD_STATE.S_IDLE;
            intrq = true;
        }
Example #9
0
        public void write_sectors()
        {
            intrq = true;
            //printf(" [write] ");
            if (!seek())
                return;

            if (!ata_p.write_sector(transbf, 0))
            {
                reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR;
                reg.err = HD_ERROR.ERR_UNC;
                state = HD_STATE.S_IDLE;
                return;
            }

            if (--reg.count == 0)
            {
                command_ok();
                return;
            }
            next_sector();

            transptr = 0;
            transcount = 0x100;
            state = HD_STATE.S_WRITE_SECTORS;
            reg.err = HD_ERROR.ERR_NONE;
            reg.status = HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
        }
Example #10
0
        public void read_sectors()
        {
            //   __debugbreak();
            intrq = true;
            if (!seek())
                return;

            if (!ata_p.read_sector(transbf, 0))
            {
                reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR;
                reg.err = HD_ERROR.ERR_UNC | HD_ERROR.ERR_IDNF;
                state = HD_STATE.S_IDLE;
                return;
            }
            transptr = 0;
            transcount = 0x100;
            state = HD_STATE.S_READ_SECTORS;
            reg.err = HD_ERROR.ERR_NONE;
            reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;

            /*
               if(reg.devhead & 0x40)
                   printf("dev=%d lba=%d\n", device_id, *(unsigned*)(regs+3) & 0x0FFFFFFF);
               else
                   printf("dev=%d c/h/s=%d/%d/%d\n", device_id, reg.cyl, (reg.devhead & 0xF), reg.sec);
            */
        }
Example #11
0
        public void prepare_id()
        {
            if (phys_dev == -1)
            {
                for (int i = 0; i < 512; i++)
                    transbf[i] = 0;
                string firmwareVersion = System.Windows.Forms.Application.ProductVersion;

                make_ata_string(transbf, 10 * 2, 10, "00000000001234567890");	// Serial number
                make_ata_string(transbf, 23 * 2, 4, firmwareVersion);			// Firmware revision
                make_ata_string(transbf, 27 * 2, 20, "ZXMAK2 HDD IMAGE");		// Model number

                setUInt16(transbf, 0 * 2, 0x045A);		// [General configuration]
                setUInt16(transbf, 1 * 2, (UInt16)c);
                setUInt16(transbf, 3 * 2, (UInt16)h);
                setUInt16(transbf, 6 * 2, (UInt16)s);
                setUInt16(transbf, 20 * 2, 3);			// a dual ported multi-sector buffer capable of simultaneous transfers with a read caching capability
                setUInt16(transbf, 21 * 2, 512);		// cache size=256k
                setUInt16(transbf, 22 * 2, 4);			// ECC bytes
                setUInt16(transbf, 49 * 2, 0x200);		// LBA supported
                setUInt32(transbf, 60 * 2, lba);		// [Total number of user addressable logical sectors]
                setUInt16(transbf, 80 * 2, 0x3E);		// support specifications up to ATA-5
                setUInt16(transbf, 81 * 2, 0x13);		// ATA/ATAPI-5 T13 1321D revision 3
                setUInt16(transbf, 82 * 2, 0x60);		// supported look-ahead and write cache

                // make checksum
                transbf[510] = 0xA5;
                byte cs = 0;
                for (int i = 0; i < 511; i++)
                    cs += transbf[i];
                transbf[511] = (byte)(0 - cs);
            }
            else
            { // copy as is...
                //for(int i=0; i < 512; i++)
                //	transbf[i] = phys[phys_dev].idsector[i];
            }

            state = HD_STATE.S_READ_ID;
            transptr = 0;
            transcount = 0x100;
            intrq = true;
            reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
            reg.err = HD_ERROR.ERR_NONE;
        }
Example #12
0
        public bool exec_ata_cmd(byte cmd)
        {
            //   printf(__FUNCTION__" cmd=%02X\n", cmd);
            // EXECUTE DEVICE DIAGNOSTIC for both ATA and ATAPI
            if (cmd == 0x90)
            {
                reset_signature(RESET_TYPE.RESET_SOFT);
                return true;
            }

            if (atapi)
                return false;

            // [DEVICE RESET]
            if (cmd == 0x08)
            {
                reset(RESET_TYPE.RESET_SOFT);
                return true;
            }
            // INITIALIZE DEVICE PARAMETERS
            if (cmd == 0x91)
            {
                // pos = (reg.cyl * h + (reg.devhead & 0x0F)) * s + reg.sec - 1;
                h = (uint)((reg.devhead & 0xF) + 1);
                s = reg.count;
                if (s == 0)
                {
                    reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DF | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR;
                    return true;
                }

                c = lba / s / h;

                reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC;
                return true;
            }

            if ((cmd & 0xFE) == 0x20) // ATA-3 (mandatory), read sectors
            { // cmd #21 obsolette, rqd for is-dos
                //       printf(__FUNCTION__" sec_cnt=%d\n", reg.count);
                read_sectors();
                return true;
            }

            if ((cmd & 0xFE) == 0x40) // ATA-3 (mandatory),  verify sectors
            { //rqd for is-dos
                verify_sectors();
                return true;
            }

            if ((cmd & 0xFE) == 0x30) // ATA-3 (mandatory), write sectors
            {
                if (readOnly)
                    return false;
                if (seek())
                {
                    state = HD_STATE.S_WRITE_SECTORS;
                    reg.status = HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
                    transptr = 0;
                    transcount = 0x100;
                }
                return true;
            }

            if (cmd == 0x50) // format track (данная реализация - ничего не делает)
            {
                reg.sec = 1;
                if (seek())
                {
                    state = HD_STATE.S_FORMAT_TRACK;
                    reg.status = HD_STATUS.STATUS_DRQ | HD_STATUS.STATUS_DSC;
                    transptr = 0;
                    transcount = 0x100;
                }
                return true;
            }

            if (cmd == 0xEC)
            {
                prepare_id();
                return true;
            }

            if (cmd == 0xE7)
            { // FLUSH CACHE
                if (ata_p.flush())
                {
                    command_ok();
                    intrq = true;
                }
                else
                {
                    reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DF | HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_ERR; // 0x71
                }
                return true;
            }

            if (cmd == 0x10)
            {
                recalibrate();
                command_ok();
                intrq = true;
                return true;
            }

            if (cmd == 0x70)
            { // seek
                if (!seek())
                    return true;
                command_ok();
                intrq = true;
                return true;
            }

            LogAgent.Error("*** unknown ATA cmd #{0:X2} ***", cmd);
            return false;
        }
Example #13
0
        public bool exec_atapi_cmd(byte cmd)
        {
            if (!atapi)
                return false;

            // soft reset
            if (cmd == 0x08)
            {
                reset(RESET_TYPE.RESET_SOFT);
                return true;
            }
            if (cmd == 0xA1) // IDENTIFY PACKET DEVICE
            {
                prepare_id();
                return true;
            }

            if (cmd == 0xA0)
            { // packet
                state = HD_STATE.S_RECV_PACKET;
                reg.status = HD_STATUS.STATUS_DRQ;
                reg.intreason = ATAPI_INT_REASON.INT_COD;
                transptr = 0;
                transcount = 6;
                return true;
            }

            if (cmd == 0xEC)
            {
                reg.count = 1;
                reg.sec = 1;
                reg.cyl = 0xEB14;

                reg.status = HD_STATUS.STATUS_DSC | HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_ERR;
                reg.err = HD_ERROR.ERR_ABRT;
                state = HD_STATE.S_IDLE;
                intrq = true;
                return true;
            }

            LogAgent.Error("*** unknown ATAPI cmd #{0:X2} ***\n", cmd);
            // "command aborted" with ATAPI signature
            reg.count = 1;
            reg.sec = 1;
            reg.cyl = 0xEB14;
            return false;
        }
Example #14
0
 public void command_ok()
 {
     state = HD_STATE.S_IDLE;
     transptr = 0xFFFFFFFF;
     reg.err = 0;
     reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC;
 }