From 39ce971e2ee56cf404fd4f425c96b250fa32ac25 Mon Sep 17 00:00:00 2001 From: Matt Burke Date: Tue, 23 Apr 2019 18:06:15 -0700 Subject: [PATCH] SCSI: Added write support for tapes. Fixed set command for changing device type --- VAX/vax4xx_rz80.c | 3 + VAX/vax4xx_rz94.c | 14 ++++ sim_scsi.c | 172 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 186 insertions(+), 3 deletions(-) diff --git a/VAX/vax4xx_rz80.c b/VAX/vax4xx_rz80.c index 28a5a72c..1ddc49f6 100644 --- a/VAX/vax4xx_rz80.c +++ b/VAX/vax4xx_rz80.c @@ -809,6 +809,7 @@ return SCPE_OK; t_stat rz_set_type (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { +CTLR *rz = rz_ctxmap[uptr->cnum]; uint32 cap; uint32 max = sim_toffset_64? RZU_EMAXC: RZU_MAXC; t_stat r; @@ -827,6 +828,8 @@ if (cptr) { } uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE); uptr->capac = (t_addr)rzdev_tab[val].lbn; +scsi_set_unit (&rz->bus, uptr, &rzdev_tab[val]); +scsi_reset_unit (uptr); return SCPE_OK; } diff --git a/VAX/vax4xx_rz94.c b/VAX/vax4xx_rz94.c index 8dc280cb..ee68f09e 100644 --- a/VAX/vax4xx_rz94.c +++ b/VAX/vax4xx_rz94.c @@ -182,6 +182,18 @@ MTAB rz_mod[] = { &rz_set_type, NULL, NULL, "Set RRD40 Disk Type" }, { MTAB_XTD|MTAB_VUN, RRD42_DTYPE, NULL, "RRD42", &rz_set_type, NULL, NULL, "Set RRD42 Disk Type" }, + { MTAB_XTD|MTAB_VUN, RRD42_DTYPE, NULL, "RRW11", + &rz_set_type, NULL, NULL, "Set RRW11 Disk Type" }, + { MTAB_XTD|MTAB_VUN, RRW11_DTYPE, NULL, "RRW11", + &rz_set_type, NULL, NULL, "Set RRW11 Disk Type" }, + { MTAB_XTD|MTAB_VUN, CDW900_DTYPE, NULL, "CDW900", + &rz_set_type, NULL, NULL, "Set SONY CDW-900E Disk Type" }, + { MTAB_XTD|MTAB_VUN, XR1001_DTYPE, NULL, "XR1001", + &rz_set_type, NULL, NULL, "Set JVC XR-W1001 Disk Type" }, + { MTAB_XTD|MTAB_VUN, TZK50_DTYPE, NULL, "TZK50", + &rz_set_type, NULL, NULL, "Set DEC TZK50 Tape Type" }, + { MTAB_XTD|MTAB_VUN, TZ30_DTYPE, NULL, "TZ30", + &rz_set_type, NULL, NULL, "Set DEC TZ30 Tape Type" }, { MTAB_XTD|MTAB_VUN|MTAB_VALR, RZU_DTYPE, NULL, "RZUSER", &rz_set_type, NULL, NULL, "Set RZUSER=size Disk Type" }, { MTAB_XTD|MTAB_VUN, 0, "TYPE", NULL, @@ -823,6 +835,8 @@ if (cptr) { } uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE); uptr->capac = (t_addr)rzdev_tab[val].lbn; +scsi_set_unit (&rz_bus, uptr, &rzdev_tab[val]); +scsi_reset_unit (uptr); return SCPE_OK; } diff --git a/sim_scsi.c b/sim_scsi.c index 93963689..9319f710 100644 --- a/sim_scsi.c +++ b/sim_scsi.c @@ -33,11 +33,13 @@ #define CMD_TESTRDY 0x00 /* test unit ready */ #define CMD_INQUIRY 0x12 /* inquiry */ #define CMD_REQSENSE 0x03 /* request sense */ +#define CMD_RDBLKLIM 0x05 /* read block limits */ #define CMD_MODESEL6 0x15 /* mode select (6 bytes) */ #define CMD_MODESEL10 0x55 /* mode select (10 bytes) */ #define CMD_MODESENSE6 0x1A /* mode sense (6 bytes) */ #define CMD_MODESENSE10 0x5A /* mode sense (10 bytes) */ #define CMD_STARTSTOP 0x1B /* start/stop unit */ +#define CMD_LOADUNLOAD 0x1B /* load/unload unit */ #define CMD_PREVALLOW 0x1E /* prevent/allow medium removal */ #define CMD_RDCAP 0x25 /* read capacity */ #define CMD_READ6 0x08 /* read (6 bytes) */ @@ -931,6 +933,47 @@ else if (bus->phase == SCSI_DATO) { } } +/* Command - Write (6 byte command), tape version */ + +void scsi_write6_tape (SCSI_BUS *bus, uint8 *data, uint32 len) +{ +UNIT *uptr = bus->dev[bus->target]; +SCSI_DEV *dev = (SCSI_DEV *)uptr->up7; +t_seccnt sects; +t_stat r; + +if (bus->phase == SCSI_CMD) { + sim_debug (SCSI_DBG_CMD, bus->dptr, + "Write(6) - CMD\n"); + memcpy (&bus->cmd[0], &data[0], 6); /* save current cmd */ + sects = GETW (bus->cmd, 3) | (bus->cmd[2] << 16); + if (data[1] & 0x1) /* FIXED */ + sects = sects * dev->block_size; + bus->buf_b = sects; + scsi_set_phase (bus, SCSI_DATO); /* data out phase next */ + scsi_set_req (bus); /* request data */ + } +else if (bus->phase == SCSI_DATO) { + sects = GETW (bus->cmd, 3) | (bus->cmd[2] << 16); + if (data[1] & 0x1) /* FIXED */ + sects = sects * dev->block_size; + sim_debug (SCSI_DBG_CMD, bus->dptr, + "Write(6) - DATO, bytes %d\n", sects); + + if (uptr->flags & UNIT_ATT) { + r = sim_tape_wrrecf (uptr, &bus->buf[0], sects); + sim_debug (SCSI_DBG_CMD, bus->dptr, + "Write(6) - DATO, r = %d\n", r); + scsi_tape_status (bus, r); /* translate status */ + } + else + scsi_status_deferred (bus, STS_OK, KEY_OK, ASC_OK); + + memset (&bus->cmd[0], 0, 10); /* clear current cmd */ + scsi_status (bus, bus->status, bus->sense_key, bus->sense_code); + } +} + /* Command - Write (10 byte command), disk version */ void scsi_write10_disk (SCSI_BUS *bus, uint8 *data, uint32 len) @@ -1093,6 +1136,39 @@ scsi_set_phase (bus, SCSI_STS); /* status phase next */ scsi_set_req (bus); /* request to send data */ } +/* Command - Read Block Limits */ + +void scsi_read_blklim (SCSI_BUS *bus, uint8 *data, uint32 len) +{ +sim_debug (SCSI_DBG_CMD, bus->dptr, "Read Block Limits\n"); + +bus->buf[bus->buf_b++] = 0x00; /* reserved */ +bus->buf[bus->buf_b++] = (MTR_MAXLEN >> 16) & 0xFF; /* max block length (23:16) */ +bus->buf[bus->buf_b++] = (MTR_MAXLEN >> 8) & 0xFF; /* max block length (15:8) */ +bus->buf[bus->buf_b++] = MTR_MAXLEN & 0xFF; /* max block length (7:0) */ +bus->buf[bus->buf_b++] = 0x00; /* min block length (15:8) */ +bus->buf[bus->buf_b++] = 0x01; /* min block length (7:0) */ +scsi_set_phase (bus, SCSI_DATI); /* data in phase next */ +scsi_set_req (bus); /* request to send data */ +} + +/* Command Load/Unload Unit */ + +void scsi_load_unload (SCSI_BUS *bus, uint8 *data, uint32 len) +{ +UNIT *uptr = bus->dev[bus->target]; + +sim_debug (SCSI_DBG_CMD, bus->dptr, "Load/Unload\n"); + +if ((data[4] & 0x5) == 0x5) { /* EOT & Load? */ + scsi_status (bus, STS_CHK, KEY_ILLREQ, ASC_INVCDB); /* invalid combination */ + return; + } +if ((data[4] & 0x1) == 0) + sim_tape_detach (uptr); /* unload */ +scsi_status (bus, STS_OK, KEY_OK, ASC_OK); /* GOOD status */ +} + /* Process a SCSI command for a direct-access device */ void scsi_disk_command (SCSI_BUS *bus, uint8 *data, uint32 len) @@ -1218,7 +1294,9 @@ switch (data[0]) { scsi_read6_tape (bus, data, len); break; - /* FIXME: READ BLOCK LIMITS */ + case CMD_RDBLKLIM: /* mandatory */ + scsi_read_blklim (bus, data, len); + break; case CMD_RELEASE: /* mandatory */ scsi_release_unit (bus, data, len); @@ -1244,11 +1322,17 @@ switch (data[0]) { scsi_space (bus, data, len); break; + case CMD_LOADUNLOAD: /* optional */ + scsi_load_unload (bus, data, len); + break; + case CMD_TESTRDY: /* mandatory */ scsi_test_ready (bus, data, len); break; - /* FIXME: WRITE6 */ + case CMD_WRITE6: /* mandatory */ + scsi_write6_tape (bus, data, len); + break; case CMD_WRFMARK: /* mandatory */ scsi_wrfmark (bus, data, len); @@ -1261,6 +1345,83 @@ switch (data[0]) { } } +/* Process a SCSI command for a CD-ROM device */ + +void scsi_cdrom_command (SCSI_BUS *bus, uint8 *data, uint32 len) +{ +switch (data[0]) { + + case CMD_INQUIRY: /* mandatory */ + scsi_inquiry (bus, data, len); + break; + + case CMD_MODESEL6: /* optional */ + scsi_mode_sel6 (bus, data, len); + break; + + case CMD_MODESEL10: /* optional */ + scsi_mode_sel10 (bus, data, len); + break; + + case CMD_MODESENSE6: /* optional */ + scsi_mode_sense6 (bus, data, len); + break; + + case CMD_MODESENSE10: /* optional */ + scsi_mode_sense10 (bus, data, len); + break; + + case CMD_PREVALLOW: /* optional */ + scsi_prev_allow (bus, data, len); + break; + + case CMD_READ6: /* optional */ + scsi_read6_disk (bus, data, len); + break; + + case CMD_READ10: /* mandatory */ + scsi_read10_disk (bus, data, len); + break; + + case CMD_RDCAP: /* mandatory */ + scsi_read_capacity (bus, data, len); + break; + + case CMD_RDLONG: /* optional */ + scsi_read_long (bus, data, len); + break; + + case CMD_RELEASE: /* mandatory */ + scsi_release_unit (bus, data, len); + break; + + case CMD_REQSENSE: /* mandatory */ + scsi_req_sense (bus, data, len); + break; + + case CMD_RESERVE: /* mandatory */ + scsi_reserve_unit (bus, data, len); + break; + + case CMD_SNDDIAG: /* mandatory */ + scsi_send_diag (bus, data, len); + break; + + case CMD_STARTSTOP: /* optional */ + scsi_start_stop (bus, data, len); + break; + + case CMD_TESTRDY: /* mandatory */ + scsi_test_ready (bus, data, len); + break; + + default: + sim_printf ("SCSI: unknown CD-ROM command %02X\n", data[0]); + scsi_status (bus, STS_CHK, KEY_ILLREQ, ASC_INVCOM); + break; + } +} + /* Process data for CMD phase */ uint32 scsi_command (SCSI_BUS *bus, uint8 *data, uint32 len) @@ -1278,13 +1439,18 @@ bus->status = STS_OK; switch (dev->devtype) { case SCSI_DISK: + case SCSI_WORM: /* same as disk for now */ scsi_disk_command (bus, data, len); break; case SCSI_TAPE: scsi_tape_command (bus, data, len); break; - + + case SCSI_CDROM: + scsi_cdrom_command (bus, data, len); + break; + default: sim_printf ("SCSI: commands unimplemented for device type %d\n", dev->devtype); break;