From: Toni Wilen Date: Mon, 6 Jul 2015 15:59:49 +0000 (+0300) Subject: SASI and CHD addressing support code for old HD controllers. X-Git-Tag: 3200~158 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=426b42b81ef9443f05c4a75504c9093633a2bf91;p=francis%2Fwinuae.git SASI and CHD addressing support code for old HD controllers. --- diff --git a/hardfile.cpp b/hardfile.cpp index afc8d739..93b42ad6 100644 --- a/hardfile.cpp +++ b/hardfile.cpp @@ -1151,6 +1151,33 @@ static const uae_u8 sasi_commands2[] = 0xff }; +static uae_u64 get_scsi_6_offset(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf) +{ + bool omti = hfd->ci.unit_feature_level == HD_LEVEL_OMTI; + uae_u64 offset; + if (omti) { + int cyl, cylsec, head, tracksec; + if (hdhfd) { + cyl = hdhfd->cyls; + head = hdhfd->heads; + tracksec = hdhfd->secspertrack; + cylsec = 0; + } else { + getchsx(hfd, &cyl, &cylsec, &head, &tracksec); + } + int d_head = cmdbuf[1] & 31; + int d_cyl = cmdbuf[3] | ((cmdbuf[2] >> 6) << 8) | ((cmdbuf[1] >> 7) << 10); + int d_sec = cmdbuf[2] & 63; + + if (d_cyl >= cyl || d_head >= head || d_sec >= tracksec) + return ~0; + offset = d_cyl * head * tracksec + d_head * tracksec + d_sec; + } else { + offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; + } + return offset; +} + int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len, uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len) { @@ -1160,8 +1187,9 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua int status = 0; int lun; uae_u8 cmd = cmdbuf[0]; - bool sasi = hfd->ci.unit_feature_level >= HD_LEVEL_SASI; + bool sasi = hfd->ci.unit_feature_level >= HD_LEVEL_SASI && hfd->ci.unit_feature_level <= HD_LEVEL_SASI_ENHANCED; bool sasie = hfd->ci.unit_feature_level == HD_LEVEL_SASI_ENHANCED; + bool omti = hfd->ci.unit_feature_level == HD_LEVEL_OMTI; if (log_scsiemu) { write_log (_T("SCSIEMU HD %d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X CMDLEN=%d DATA=%p\n"), hfd->unitnum, @@ -1183,8 +1211,11 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua *reply_len = *sense_len = 0; lun = cmdbuf[1] >> 5; - if (sasi) - lun = 0; + if (sasi || omti) { + lun = lun & 1; + if (lun) + goto sasi_nodisk; + } if (cmd != 0x03 && cmd != 0x12 && lun) { status = 2; /* CHECK CONDITION */ s[0] = 0x70; @@ -1195,7 +1226,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua goto scsi_done; } - if (sasi) { + if (sasi || omti) { int i; for (i = 0; sasi_commands[i] != 0xff; i++) { if (sasi_commands[i] == cmdbuf[0]) @@ -1215,7 +1246,18 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua } switch (cmdbuf[0]) { - case 0x0c: /* INITIALIZE DRIVE CHARACTERICS */ + case 0x05: /* READ VERIFY */ + if (nodisk(hfd)) + goto nodisk; + offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf); + if (offset == ~0) + goto outofbounds; + offset *= hfd->ci.blocksize; + if (!checkbounds(hfd, offset, hfd->ci.blocksize)) + goto outofbounds; + scsi_len = 0; + goto scsi_done; + case 0x0c: /* INITIALIZE DRIVE CHARACTERISTICS */ scsi_len = 8; goto scsi_done; case 0x12: /* INQUIRY */ @@ -1314,7 +1356,9 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua case 0x09: /* READ VERIFY */ if (nodisk(hfd)) goto nodisk; - offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; + offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf); + if (offset == ~0) + goto outofbounds; offset *= hfd->ci.blocksize; if (!checkbounds(hfd, offset, hfd->ci.blocksize)) goto outofbounds; @@ -1323,7 +1367,9 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua case 0x0b: /* SEEK (6) */ if (nodisk (hfd)) goto nodisk; - offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; + offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf); + if (offset == ~0) + goto outofbounds; offset *= hfd->ci.blocksize; if (!checkbounds(hfd, offset, hfd->ci.blocksize)) goto outofbounds; @@ -1332,7 +1378,9 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua case 0x08: /* READ (6) */ if (nodisk (hfd)) goto nodisk; - offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; + offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf); + if (offset == ~0) + goto outofbounds; offset *= hfd->ci.blocksize; len = cmdbuf[4]; if (!len) @@ -1350,7 +1398,9 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua goto nodisk; if (hfd->ci.readonly || hfd->dangerous) goto readprot; - offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3]; + offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf); + if (offset == ~0) + goto outofbounds; offset *= hfd->ci.blocksize; len = cmdbuf[4]; if (!len) @@ -1583,6 +1633,12 @@ readprot: s[12] = 0x27; /* WRITE PROTECTED */ ls = 0x12; break; +sasi_nodisk: + status = 2; + s[0] = 0x04; // Drive not ready + s[1] = lun << 5; + ls = 4; + break; nodisk: status = 2; /* CHECK CONDITION */ s[0] = 0x70; @@ -1640,6 +1696,13 @@ scsi_done: } *sense_len = ls; if (ls > 0) { + if (omti) { + if (ls > 4) { + ls = 4; + *sense_len = ls; + } + hfd->scsi_sense[1] = (lun & 1) << 5; + } memset (hfd->scsi_sense, 0, MAX_SCSI_SENSE); memcpy (hfd->scsi_sense, s, ls); }