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 */
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;
}
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])
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],
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;
}
switch (cmdbuf[0])
{
case 0x00: /* TEST UNIT READY */
- hfd->unit_attention = 0;
if (nodisk (hfd))
goto nodisk;
scsi_len = 0;
}
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++)
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]);
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)
}
}
+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)
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;
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]);
+ }
}
scsi->irq = true;
memset(scsi->regs, 0, sizeof scsi->regs);
- raw_scsi_reset_bus(r);
+ raw_scsi_reset_bus(scsi);
scsi->regs[1] = 0x80;
}