]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
SCSI REQUEST SENSE lba-fields are now filled. SASI REQUEST SENSE improved.
authorToni Wilen <twilen@winuae.net>
Sun, 11 Sep 2016 15:41:40 +0000 (18:41 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 11 Sep 2016 15:41:40 +0000 (18:41 +0300)
blkdev.cpp
hardfile.cpp
scsi.cpp

index 06512efdc1003e0689cd53de703bbb75919860dc..3fb8f7d7996ad25344e3f1d90fb43237c148e885 100644 (file)
@@ -2057,7 +2057,8 @@ end:
        }
        if (ls) {
                //s[0] |= 0x80;
-               s[7] = ls - 7; // additional sense length
+               if (ls > 7)
+                       s[7] = ls - 8; // additional sense length
                if (log_scsiemu) {
                        write_log (_T("-> SENSE STATUS: KEY=%d ASC=%02X ASCQ=%02X\n"), s[2], s[12], s[13]);
                }
index 32c7f49f3c5779cd69e71f0ed45e84d13e9a1fe8..95f9f073ae0226f73016552fb93f69209239ff49 100644 (file)
@@ -1152,7 +1152,7 @@ static int checkbounds (struct hardfiledata *hfd, uae_u64 offset, uae_u64 len, i
                for (int i = 0; i < hfd->ci.badblock_num; i++) {
                        struct uaedev_badblock *bb = &hfd->ci.badblocks[i];
                        if (offset + len >= bb->first && offset < bb->last)
-                               return true;
+                               return 1;
                }
        }
        return 0;
@@ -1203,11 +1203,11 @@ static const uae_u8 sasi_commands2[] =
        0xff
 };
 
-static uae_u64 get_scsi_6_offset(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf)
+static uae_u64 get_scsi_6_offset(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, uae_u64 *lba)
 {
-       bool omti = hfd->ci.unit_feature_level == HD_LEVEL_SASI_CHS;
+       bool chs = hfd->ci.unit_feature_level == HD_LEVEL_SASI_CHS;
        uae_u64 offset;
-       if (omti) {
+       if (chs) {
                int cyl, cylsec, head, tracksec;
                if (hdhfd) {
                        cyl = hdhfd->cyls;
@@ -1221,6 +1221,7 @@ static uae_u64 get_scsi_6_offset(struct hardfiledata *hfd, struct hd_hardfiledat
                int d_cyl = cmdbuf[3] | ((cmdbuf[2] >> 6) << 8) | ((cmdbuf[1] >> 7) << 10);
                int d_sec = cmdbuf[2] & 63;
 
+               *lba = ((cmdbuf[1] & (0x1f | 0x80 | 0x40)) << 16) | (cmdbuf[2] << 8) || cmdbuf[3];
                if (d_cyl >= cyl || d_head >= head || d_sec >= tracksec)
                        return ~0;
                offset = d_cyl * head * tracksec + d_head * tracksec + d_sec;
@@ -1247,6 +1248,8 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        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_SASI_CHS;
+       uae_u8 sasi_sense = 0;
+       uae_u64 current_lba = ~0;
 
        cmd = cmdbuf[0];
 
@@ -1267,7 +1270,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        if (sasi || omti) {
                lun = lun & 1;
                if (lun)
-                       goto sasi_nodisk;
+                       goto nodisk;
        }
        if (cmd != 0x03 && cmd != 0x12 && lun) {
                status = 2; /* CHECK CONDITION */
@@ -1302,15 +1305,18 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        case 0x05: /* READ VERIFY */
                        if (nodisk(hfd))
                                goto nodisk;
-                       offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf);
+                       offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf, &current_lba);
                        if (offset == ~0) {
                                chkerr = 1;
                                goto checkfail;
                        }
+                       current_lba = offset;
                        offset *= hfd->ci.blocksize;
                        chkerr = checkbounds(hfd, offset, hfd->ci.blocksize, 1);
-                       if (chkerr)
+                       if (chkerr) {
+                               current_lba = offset;
                                goto checkfail;
+                       }
                        scsi_len = 0;
                        goto scsi_done;
                        case 0x0c: /* INITIALIZE DRIVE CHARACTERISTICS */
@@ -1420,25 +1426,29 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        case 0x09: /* READ VERIFY */
                if (nodisk(hfd))
                        goto nodisk;
-               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf);
+               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf, &current_lba);
                if (offset == ~0) {
                        chkerr = 1;
                        goto checkfail;
                }
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                chkerr = checkbounds(hfd, offset, hfd->ci.blocksize, 1);
-               if (chkerr)
+               if (chkerr) {
+                       current_lba = offset;
                        goto checkfail;
+               }
                scsi_len = 0;
                break;
        case 0x0b: /* SEEK (6) */
                if (nodisk (hfd))
                        goto nodisk;
-               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf);
+               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf, &current_lba);
                if (offset == ~0) {
                        chkerr = 1;
                        goto checkfail;
                }
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                chkerr = checkbounds(hfd, offset, hfd->ci.blocksize, 3);
                if (chkerr)
@@ -1448,11 +1458,12 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        case 0x08: /* READ (6) */
                if (nodisk (hfd))
                        goto nodisk;
-               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf);
+               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf, &current_lba);
                if (offset == ~0) {
                        chkerr = 1;
                        goto checkfail;
                }
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                len = cmdbuf[4];
                if (!len)
@@ -1471,11 +1482,12 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        goto nodisk;
                if (is_writeprotected(hfd))
                        goto readprot;
-               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf);
+               offset = get_scsi_6_offset(hfd, hdhfd, cmdbuf, &current_lba);
                if (offset == ~0) {
                        chkerr = 1;
                        goto checkfail;
                }
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                len = cmdbuf[4];
                if (!len)
@@ -1651,6 +1663,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                if (nodisk (hfd))
                        goto nodisk;
                offset = rl (cmdbuf + 2);
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                chkerr = checkbounds(hfd, offset, hfd->ci.blocksize, 3);
                if (chkerr)
@@ -1661,6 +1674,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                if (nodisk (hfd))
                        goto nodisk;
                offset = rl (cmdbuf + 2);
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                len = rl (cmdbuf + 7 - 2) & 0xffff;
                len *= hfd->ci.blocksize;
@@ -1675,6 +1689,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                if (is_writeprotected(hfd))
                        goto readprot;
                offset = rl (cmdbuf + 2);
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                len = rl (cmdbuf + 7 - 2) & 0xffff;
                len *= hfd->ci.blocksize;
@@ -1690,6 +1705,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                                goto nodisk;
                        if (bytchk) {
                                offset = rl (cmdbuf + 2);
+                               current_lba = offset;
                                offset *= hfd->ci.blocksize;
                                len = rl (cmdbuf + 7 - 2) & 0xffff;
                                len *= hfd->ci.blocksize;
@@ -1721,6 +1737,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                if (nodisk (hfd))
                        goto nodisk;
                offset = rl (cmdbuf + 2);
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                len = rl (cmdbuf + 6);
                len *= hfd->ci.blocksize;
@@ -1735,6 +1752,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                if (is_writeprotected(hfd))
                        goto readprot;
                offset = rl (cmdbuf + 2);
+               current_lba = offset;
                offset *= hfd->ci.blocksize;
                len = rl (cmdbuf + 6);
                len *= hfd->ci.blocksize;
@@ -1770,12 +1788,7 @@ readprot:
                s[2] = 7; /* DATA PROTECT */
                s[12] = 0x27; /* WRITE PROTECTED */
                ls = 0x12;
-               break;
-sasi_nodisk:
-               status = 2;
-               s[0] = 0x04; // Drive not ready
-               s[1] = lun << 5;
-               ls = 4;
+               sasi_sense = 0x03; // write fault
                break;
 nodisk:
                status = 2; /* CHECK CONDITION */
@@ -1783,6 +1796,7 @@ nodisk:
                s[2] = 2; /* NOT READY */
                s[12] = 0x3A; /* MEDIUM NOT PRESENT */
                ls = 0x12;
+               sasi_sense = 0x04; // drive not ready
                break;
 
        default:
@@ -1794,28 +1808,35 @@ errreq:
                s[2] = 5; /* ILLEGAL REQUEST */
                s[12] = 0x24; /* ILLEGAL FIELD IN CDB */
                ls = 0x12;
+               sasi_sense = 0x22; // invalid parameter
                break;
 checkfail:
                status = 2; /* CHECK CONDITION */
-               s[0] = 0x70;
+               s[0] = 0x70 | ((current_lba != ~0) ? 0x80 : 0x00);
                if (chkerr < 0) {
                        s[2] = 5; /* ILLEGAL REQUEST */
                        s[12] = 0x21; /* LOGICAL BLOCK OUT OF RANGE */
+                       sasi_sense = 0x21; // illegal disk address
                } else {
                        s[2] = 3; /* MEDIUM ERROR */
-                       if (chkerr == 1)
+                       if (chkerr == 1) {
                                s[12] = 0x11; /* Unrecovered Read Error */
-                       if (chkerr == 2)
+                               sasi_sense = 0x11; // uncorrectable data error
+                       }
+                       if (chkerr == 2) {
                                s[12] = 0x0c; /* Write Error */
+                               sasi_sense = 0x03; // write fault
+                       }
                }
                ls = 0x12;
                break;
 miscompare:
                status = 2; /* CHECK CONDITION */
-               s[0] = 0x70;
+               s[0] = 0x70 | ((current_lba != ~0) ? 0x80 : 0x00);
                s[2] = 5; /* ILLEGAL REQUEST */
                s[12] = 0x1d; /* MISCOMPARE DURING VERIFY OPERATION */
                ls = 0x12;
+               sasi_sense = 0x11; // uncorrectable data error
                break;
        }
 scsi_done:
@@ -1823,13 +1844,6 @@ scsi_done:
        if (ls > 7)
                s[7] = ls - 8;
 
-       if (log_scsiemu && ls) {
-               write_log (_T("-> SENSE STATUS: KEY=%d ASC=%02X ASCQ=%02X\n"), s[2], s[12], s[13]);
-               for (int i = 0; i < ls; i++)
-                       write_log (_T("%02X."), s[i]);
-               write_log (_T("\n"));   
-       }
-
        if (log_scsiemu)
                write_log (_T("-> DATAOUT=%d ST=%d SENSELEN=%d REPLYLEN=%d\n"), scsi_len, status, ls, lr);
 
@@ -1843,18 +1857,45 @@ scsi_done:
                        write_log (_T("\n"));   
                }
        }
-       *sense_len = ls;
        if (ls > 0) {
-               if (omti) {
-                       if (ls > 4) {
+               if (omti || sasi) {
+                       if (sasi_sense != 0) {
+                               bool islba = (s[0] & 0x80) != 0;
                                ls = 4;
-                               *sense_len = ls;
+                               s[0] = sasi_sense | (islba ? 0x80 : 0x00);
+                               s[1] = (lun & 1) << 5;
+                               s[2] = 0;
+                               s[3] = 0;
+                               if (islba) {
+                                       s[1] |= (current_lba >> 16) & 31;
+                                       s[2] = (current_lba >> 8) & 255;
+                                       s[3] = (current_lba >> 0) & 255;
+                               }
+                       }
+                       if (log_scsiemu && ls) {
+                               write_log(_T("-> SENSE STATUS:\n"));
+                               for (int i = 0; i < ls; i++)
+                                       write_log(_T("%02X."), s[i]);
+                               write_log(_T("\n"));
+                       }
+               } else {
+                       if (s[0] & 0x80) {
+                               s[3] = (current_lba >> 24) & 255;
+                               s[4] = (current_lba >> 16) & 255;
+                               s[5] = (current_lba >>  8) & 255;
+                               s[6] = (current_lba >>  0) & 255;
+                       }
+                       if (log_scsiemu && ls) {
+                               write_log(_T("-> SENSE STATUS: KEY=%d ASC=%02X ASCQ=%02X\n"), s[2], s[12], s[13]);
+                               for (int i = 0; i < ls; i++)
+                                       write_log(_T("%02X."), s[i]);
+                               write_log(_T("\n"));
                        }
-                       hfd->scsi_sense[1] = (lun & 1) << 5;
                }
                memset (hfd->scsi_sense, 0, MAX_SCSI_SENSE);
                memcpy (hfd->scsi_sense, s, ls);
        }
+       *sense_len = ls;
        return status;
 }
 
index d486d4ec4dcf71353c7c1826719b926f6a4e3752..527afedcc1936bb1940f7a5dc37befbfa1e50e68 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
@@ -255,18 +255,14 @@ static void copysense(struct scsi_data *sd)
 {
        bool sasi = sd->hfd && (sd->hfd->ci.unit_feature_level >= HD_LEVEL_SASI && sd->hfd->ci.unit_feature_level <= HD_LEVEL_SASI_ENHANCED);
        int len = sd->cmd[4];
-       if (log_scsiemu)
-               write_log (_T("REQUEST SENSE length %d (%d)\n"), len, sd->sense_len);
        if (len == 0 || sasi)
                len = 4;
        memset(sd->buffer, 0, len);
        int tlen = sd->sense_len > len ? len : sd->sense_len;
+       if (log_scsiemu)
+               write_log(_T("REQUEST SENSE %d (%d -> %d)\n"), sd->cmd[4], sd->sense_len, tlen);
        memcpy(sd->buffer, sd->sense, tlen);
-       if (len > 7 && sd->sense_len > 7)
-               sd->buffer[7] = sd->sense_len - 8;
-       if (sasi) {
-               sd->buffer[0] = sd->sense[12]; // 0 <- ASC
-       } else if (sd->sense_len == 0) {
+       if (!sasi && sd->sense_len == 0) {
                sd->buffer[0] = 0x70;
        }
        showsense (sd);