From: Toni Wilen Date: Wed, 12 Aug 2015 16:16:22 +0000 (+0300) Subject: SCSI emulation updates, unit attention, wd33c93 select and transfer continuation. X-Git-Tag: 3200~110 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=87e9c2cc9d5115a791f1928af79f3c0fa688b3de;p=francis%2Fwinuae.git SCSI emulation updates, unit attention, wd33c93 select and transfer continuation. --- diff --git a/a2091.cpp b/a2091.cpp index 98e4ebc0..0e6bef8d 100644 --- 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; diff --git a/blkdev.cpp b/blkdev.cpp index 5a15083d..630c8759 100644 --- a/blkdev.cpp +++ b/blkdev.cpp @@ -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]) diff --git a/hardfile.cpp b/hardfile.cpp index 43c93cbe..b04a67c3 100644 --- a/hardfile.cpp +++ b/hardfile.cpp @@ -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++) diff --git a/include/filesys.h b/include/filesys.h index 9efdf0c8..31700a6a 100644 --- a/include/filesys.h +++ b/include/filesys.h @@ -71,7 +71,6 @@ struct hardfiledata { int reinsertdelay; bool isreinsert; bool unit_stopped; - int unit_attention; }; #define HFD_FLAGS_REALDRIVE 1 diff --git a/include/scsi.h b/include/scsi.h index 165faff4..b9665c89 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -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*); diff --git a/scsi.cpp b/scsi.cpp index e83b7f25..d7a41bc6 100644 --- 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; } diff --git a/scsitape.cpp b/scsitape.cpp index 271b9c30..7eb4a3db 100644 --- a/scsitape.cpp +++ b/scsitape.cpp @@ -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]);