public void command_ok() { state = HD_STATE.S_IDLE; transptr = 0xFFFFFFFF; reg.err = 0; reg.status = HD_STATUS.STATUS_DRDY | HD_STATUS.STATUS_DSC; }
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); */ }
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; }
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); }
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; }
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; }
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); }
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; }
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; }
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); */ }
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; }
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; }
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; }