]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
SCSI emulation updates, unit attention, wd33c93 select and transfer continuation.
authorToni Wilen <twilen@winuae.net>
Wed, 12 Aug 2015 16:16:22 +0000 (19:16 +0300)
committerToni Wilen <twilen@winuae.net>
Wed, 12 Aug 2015 16:16:22 +0000 (19:16 +0300)
a2091.cpp
blkdev.cpp
hardfile.cpp
include/filesys.h
include/scsi.h
scsi.cpp
scsitape.cpp

index 98e4ebc0e52bab363ef4234a2e1ced8780ef0153..0e6bef8d75d9a66ea49e9a142a066d3d052bd51f 100644 (file)
--- a/a2091.cpp
+++ b/a2091.cpp
@@ -1073,7 +1073,7 @@ static void wd_cmd_sel_xfer (struct wd_chip_state *wd, struct wd_state *wds, boo
                        if (scsi->direction != 0) {
                                // TC = 0 but we may have data
                                if (scsi->direction < 0) {
-                                       if (scsi->data_len == 0) {
+                                       if (scsi->data_len == 0 || scsi->offset >= scsi->data_len) {
                                                // no data, continue normally to status phase
                                                setphase (wd, 0x46);
                                                goto end;
index 5a15083dee3e210168e8c59205c6a6b3281fd141..630c8759fa6522bddc5cfe83d46bb429d6351057 100644 (file)
@@ -54,25 +54,6 @@ struct blkdevstate
 
 struct blkdevstate state[MAX_TOTAL_SCSI_DEVICES];
 
-#if 0
-static int scsiemu[MAX_TOTAL_SCSI_DEVICES];
-
-static struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES];
-static int openlist[MAX_TOTAL_SCSI_DEVICES];
-static int waspaused[MAX_TOTAL_SCSI_DEVICES];
-static int delayed[MAX_TOTAL_SCSI_DEVICES];
-static uae_sem_t unitsem[MAX_TOTAL_SCSI_DEVICES];
-static int unitsem_cnt[MAX_TOTAL_SCSI_DEVICES];
-
-static int play_end_pos[MAX_TOTAL_SCSI_DEVICES];
-static uae_u8 play_qcode[MAX_TOTAL_SCSI_DEVICES][SUBQ_SIZE];
-
-static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256];
-static int imagechangetime[MAX_TOTAL_SCSI_DEVICES];
-static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES];
-static int wasopen[MAX_TOTAL_SCSI_DEVICES];
-#endif
-
 static bool dev_init;
 
 /* convert minutes, seconds and frames -> logical sector number */
@@ -1307,11 +1288,20 @@ int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
        int v;
        int status = 0;
        struct device_info di;
-       uae_u8 cmd = cmdbuf[0];
+       uae_u8 cmd;
        int dlen, lun;
        
-       if (cmd == 0x03) { /* REQUEST SENSE */
-               st->mediawaschanged = false;
+       if (cmdbuf == NULL) {
+               if (st->mediawaschanged) {
+                       st->mediawaschanged = false;
+                       return (0x28 << 8) | (0x00);
+               }
+               return 0;
+       }
+
+       cmd = cmdbuf[0];
+
+       if (cmd == 0x03) {
                return 0;
        }
        
@@ -1336,22 +1326,6 @@ int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
                goto end;
        }
 
-       // media changed and not inquiry
-       if (st->mediawaschanged && cmd != 0x12) {
-               if (log_scsiemu) {
-                       write_log (_T("CD SCSIEMU %d: MEDIUM MAY HAVE CHANGED STATE\n"), unitnum);
-               }
-               lr = -1;
-               status = 2; /* CHECK CONDITION */
-               s[0] = 0x70;
-               s[2] = 6; /* UNIT ATTENTION */
-               s[12] = 0x28; /* MEDIUM MAY HAVE CHANGED */
-               ls = 0x12;
-               if (cmd == 0x00)
-                       st->mediawaschanged = false;
-               goto end;
-       }
-
        sys_command_info (unitnum, &di, 1);
 
        switch (cmdbuf[0])
index 43c93cbec0b4b71bf3914f6315a6ca97909844bf..b04a67c36b5e302a609a812d7f4dd6e9a60f552f 100644 (file)
@@ -1181,16 +1181,21 @@ static uae_u64 get_scsi_6_offset(struct hardfiledata *hfd, struct hd_hardfiledat
 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)
 {
+       if (cmdbuf == NULL)
+               return 0;
+
        uae_u64 len, offset;
        int lr = 0, ls = 0;
        int scsi_len = -1;
        int status = 0;
        int lun;
-       uae_u8 cmd = cmdbuf[0];
+       uae_u8 cmd;
        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;
 
+       cmd = cmdbuf[0];
+
        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,
                        cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], 
@@ -1198,14 +1203,8 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        scsi_cmd_len, scsi_data);
        }
 
-       if (cmd == 0x03) { /* REQUEST SENSE */
-               if (hfd->unit_attention) {
-                       s[0] = 0x70;
-                       s[2] = 6; /* UNIT ATTENTION */
-                       s[12] = (hfd->unit_attention >> 8) & 0xff;
-                       s[13] = (hfd->unit_attention >> 0) & 0xff;
-                       *sense_len = 0x12;
-               }
+       /* REQUEST SENSE */
+       if (cmd == 0x03) {
                return 0;
        }
 
@@ -1344,7 +1343,6 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        switch (cmdbuf[0])
        {
        case 0x00: /* TEST UNIT READY */
-               hfd->unit_attention = 0;
                if (nodisk (hfd))
                        goto nodisk;
                scsi_len = 0;
@@ -1683,6 +1681,9 @@ miscompare:
        }
 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++)
index 9efdf0c8f41e5fed76e2d084c3f80463e6ad3f02..31700a6a6181c3a7c51f9ebde2777e75214de481 100644 (file)
@@ -71,7 +71,6 @@ struct hardfiledata {
        int reinsertdelay;
        bool isreinsert;
        bool unit_stopped;
-       int unit_attention;
 };
 
 #define HFD_FLAGS_REALDRIVE 1
index 165faff4f802b629cb5e7b43e9f6028c35068223..b9665c89eea3309c9bc9120248d919a39cc4113e 100644 (file)
@@ -20,31 +20,32 @@ struct scsi_data_tape
 
 struct scsi_data
 {
-    int id;
+       int id;
        void *privdata;
-    int cmd_len;
-    uae_u8 *data;
-    int data_len;
-    int status;
-    uae_u8 sense[256];
-    int sense_len;
-    uae_u8 reply[256];
-    uae_u8 cmd[16];
+       int cmd_len;
+       uae_u8 *data;
+       int data_len;
+       int status;
+       uae_u8 sense[256];
+       int sense_len;
+       uae_u8 reply[256];
+       uae_u8 cmd[16];
        uae_u8 msgout[4];
-    int reply_len;
-    int direction;
+       int reply_len;
+       int direction;
        uae_u8 message[1];
        int blocksize;
 
-    int offset;
-    uae_u8 *buffer;
+       int offset;
+       uae_u8 *buffer;
        int buffer_size;
-    struct hd_hardfiledata *hfd;
+       struct hd_hardfiledata *hfd;
        struct scsi_data_tape *tape;
-    int device_type;
+       int device_type;
        int nativescsiunit;
        int cd_emu_unit;
        bool atapi;
+       uae_u32 unit_attention;
 };
 
 extern struct scsi_data *scsi_alloc_hd(int, struct hd_hardfiledata*);
index e83b7f25365fb9ce633bf77dff513f928f844324..d7a41bc6d0f89a95e9578236920ed7df77e46b1e 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
@@ -240,7 +240,7 @@ void scsi_clear_sense(struct scsi_data *sd)
 static void showsense(struct scsi_data *sd)
 {
        if (log_scsiemu) {
-               for (int i = 0; i < sd->data_len; i++) {
+               for (int i = 0; i < sd->sense_len; i++) {
                        if (i > 0)
                                write_log (_T("."));
                        write_log (_T("%02X"), sd->buffer[i]);
@@ -257,10 +257,12 @@ static void copysense(struct scsi_data *sd)
                len = 4;
        memset(sd->buffer, 0, len);
        memcpy(sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len);
+       if (len > 7 && sd->sense_len > 7)
+               sd->buffer[7] = sd->sense_len - 8;
        if (sd->sense_len == 0)
                sd->buffer[0] = 0x70;
-       sd->data_len = len;
        showsense (sd);
+       sd->data_len = len;
        scsi_clear_sense(sd);
 }
 static void copyreply(struct scsi_data *sd)
@@ -272,12 +274,69 @@ static void copyreply(struct scsi_data *sd)
        }
 }
 
+static void scsi_set_unit_attention(struct scsi_data *sd, uae_u8 v1, uae_u8 v2)
+{
+       sd->unit_attention = (v1 << 8) | v2;
+}
+
 void scsi_emulate_reset_device(struct scsi_data *sd)
 {
        if (!sd)
                return;
-       if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0)
-               sd->hfd->hfd.unit_attention = (0x29 << 8) | 0x02; //  SCSI bus reset occurred
+       if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0) {
+               scsi_clear_sense(sd);
+               //  SCSI bus reset occurred
+               scsi_set_unit_attention(sd, 0x29, 0x02);
+       }
+}
+
+static bool handle_ca(struct scsi_data *sd)
+{
+       bool cc = sd->sense_len > 2 && sd->sense[2] >= 2;
+       bool ua = sd->unit_attention != 0;
+       uae_u8 cmd = sd->cmd[0];
+
+       // INQUIRY
+       if (cmd == 0x12) {
+               if (ua && cc && sd->sense[2] == 6) {
+                       // INQUIRY clears UA only if previous
+                       // command was aborted due to UA
+                       sd->unit_attention = 0;
+               }
+               return true;
+       }
+
+       // REQUEST SENSE
+       if (cmd == 0x03) {
+               if (ua) {
+                       uae_u8 *s = sd->sense;
+                       scsi_clear_sense(sd);
+                       s[0] = 0x70;
+                       s[2] = 6; /* UNIT ATTENTION */
+                       s[12] = (sd->unit_attention >> 8) & 0xff;
+                       s[13] = (sd->unit_attention >> 0) & 0xff;
+                       sd->sense_len = 0x12;
+               }
+               sd->unit_attention = 0;
+               copysense(sd);
+               return true;
+       }
+
+       scsi_clear_sense(sd);
+
+       if (ua) {
+               uae_u8 *s = sd->sense;
+               s[0] = 0x70;
+               s[2] = 6; /* UNIT ATTENTION */
+               s[12] = (sd->unit_attention >> 8) & 0xff;
+               s[13] = (sd->unit_attention >> 0) & 0xff;
+               sd->sense_len = 0x12;
+               sd->unit_attention = 0;
+               sd->status = 2;
+               return false;
+       }
+
+       return true;
 }
 
 void scsi_emulate_cmd(struct scsi_data *sd)
@@ -295,33 +354,45 @@ void scsi_emulate_cmd(struct scsi_data *sd)
                sd->cmd[0], sd->cmd[1], sd->cmd[2], sd->cmd[3], sd->cmd[4], sd->cmd[5], sd->device_type, sd->nativescsiunit);
 #endif
        if (sd->device_type == UAEDEV_CD && sd->cd_emu_unit >= 0) {
-               if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
-                       scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, 0, 0, 0, 0, 0, 0, 0, sd->atapi); /* ack request sense */
-                       copysense(sd);
-               } else {
-                       scsi_clear_sense(sd);
-                       sd->status = scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len, sd->atapi);
-                       copyreply(sd);
+               uae_u32 ua = 0;
+               ua = scsi_cd_emulate(sd->cd_emu_unit, NULL, 0, 0, 0, 0, 0, 0, 0, sd->atapi);
+               if (ua)
+                       sd->unit_attention = ua;
+               if (handle_ca(sd)) {
+                       if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+                               scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, 0, 0, 0, 0, 0, 0, 0, sd->atapi); /* ack request sense */
+                       } else {
+                               sd->status = scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len, sd->atapi);
+                               copyreply(sd);
+                       }
                }
        } else if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0) {
-               if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
-                       scsi_hd_emulate(&sd->hfd->hfd, sd->hfd, sd->cmd, 0, 0, 0, 0, 0, sd->sense, &sd->sense_len);
-                       copysense(sd);
-               } else {
-                       scsi_clear_sense(sd);
-                       sd->status = scsi_hd_emulate(&sd->hfd->hfd, sd->hfd,
-                               sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
-                       copyreply(sd);
+               uae_u32 ua = 0;
+               ua = scsi_hd_emulate(&sd->hfd->hfd, sd->hfd, NULL, 0, 0, 0, 0, 0, 0, 0);
+               if (ua)
+                       sd->unit_attention = ua;
+               if (handle_ca(sd)) {
+                       if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+                               scsi_hd_emulate(&sd->hfd->hfd, sd->hfd, sd->cmd, 0, 0, 0, 0, 0, sd->sense, &sd->sense_len);
+                       } else {
+                               sd->status = scsi_hd_emulate(&sd->hfd->hfd, sd->hfd,
+                                       sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
+                               copyreply(sd);
+                       }
                }
        } else if (sd->device_type == UAEDEV_TAPE && sd->nativescsiunit < 0) {
-               if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
-                       scsi_tape_emulate(sd->tape, sd->cmd, 0, 0, 0, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len); /* get request sense extra bits */
-                       copysense(sd);
-               } else {
-                       scsi_clear_sense(sd);
-                       sd->status = scsi_tape_emulate(sd->tape,
-                               sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
-                       copyreply(sd);
+               uae_u32 ua = 0;
+               ua = scsi_tape_emulate(sd->tape, NULL, 0, 0, 0, 0, 0, 0, 0);
+               if (ua)
+                       sd->unit_attention = ua;
+               if (handle_ca(sd)) {
+                       if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+                               scsi_tape_emulate(sd->tape, sd->cmd, 0, 0, 0, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len); /* get request sense extra bits */
+                       } else {
+                               sd->status = scsi_tape_emulate(sd->tape,
+                                       sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
+                               copyreply(sd);
+                       }
                }
        } else if (sd->nativescsiunit >= 0) {
                struct amigascsi as;
@@ -861,10 +932,15 @@ static int countbits(uae_u8 v)
        return cnt;
 }
 
-static void raw_scsi_reset_bus(struct raw_scsi *rs)
+static void raw_scsi_reset_bus(struct soft_scsi *scsi)
 {
-       for (int i = 0; i < 8; i++)
-               scsi_emulate_reset_device(rs->device[i]);
+       struct raw_scsi *r = &scsi->rscsi;
+#if RAW_SCSI_DEBUG
+       write_log(_T("SCSI BUS reset\n"));
+#endif
+       for (int i = 0; i < 8; i++) {
+               scsi_emulate_reset_device(r->device[i]);
+       }
 }
 
 
@@ -1336,7 +1412,7 @@ static void ncr5380_reset(struct soft_scsi *scsi)
 
        scsi->irq = true;
        memset(scsi->regs, 0, sizeof scsi->regs);
-       raw_scsi_reset_bus(r);
+       raw_scsi_reset_bus(scsi);
        scsi->regs[1] = 0x80;
 }
 
index 271b9c306481b802913de7bdeddd2bbc8f47912f..7eb4a3db25bc8887c7873009eeeddf91ee006dc0 100644 (file)
@@ -271,6 +271,9 @@ int scsi_tape_emulate (struct scsi_data_tape *tape, uae_u8 *cmdbuf, int scsi_cmd
        int lun;
        bool eof;
 
+       if (cmdbuf == NULL)
+               return 0;
+
        if (log_tapeemu)
                write_log (_T("TAPEEMU: %02X.%02X.%02X.%02X.%02X.%02X\n"),
                cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5]);