From a75508c93da2d0ca1290a83be1580aec5bfefeb3 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Mon, 22 May 2023 19:13:36 +0300 Subject: [PATCH] More tape command implementations: Erase, Seek and ReadPosition --- src/BlueSCSI_log_trace.cpp | 5 +-- src/BlueSCSI_tape.cpp | 72 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/BlueSCSI_log_trace.cpp b/src/BlueSCSI_log_trace.cpp index ba308342..b1255aea 100644 --- a/src/BlueSCSI_log_trace.cpp +++ b/src/BlueSCSI_log_trace.cpp @@ -20,7 +20,7 @@ static const char *getCommandName(uint8_t cmd) switch (cmd) { case 0x00: return "TestUnitReady"; - case 0x01: return "RezeroUnit"; + case 0x01: return "RezeroUnit/Rewind"; case 0x03: return "RequestSense"; case 0x04: return "FormatUnit"; case 0x05: return "ReadBlockLimits"; @@ -35,6 +35,7 @@ static const char *getCommandName(uint8_t cmd) case 0x15: return "ModeSelect6"; case 0x16: return "Reserve"; case 0x17: return "Release"; + case 0x19: return "Erase"; case 0x1A: return "ModeSense"; case 0x1B: return "StartStopUnit"; case 0x1C: return "ReceiveDiagnostic"; @@ -47,7 +48,7 @@ static const char *getCommandName(uint8_t cmd) case 0x2C: return "Erase10"; case 0x2E: return "WriteVerify"; case 0x2F: return "Verify"; - case 0x34: return "PreFetch"; + case 0x34: return "PreFetch/ReadPosition"; case 0x35: return "SynchronizeCache"; case 0x36: return "LockUnlockCache"; case 0x37: return "ReadDefectData"; diff --git a/src/BlueSCSI_tape.cpp b/src/BlueSCSI_tape.cpp index b68f1fd5..7c0bde43 100644 --- a/src/BlueSCSI_tape.cpp +++ b/src/BlueSCSI_tape.cpp @@ -31,6 +31,31 @@ extern "C" { #include } +static void doSeek(uint32_t lba) +{ + image_config_t &img = *(image_config_t*)scsiDev.target->cfg; + uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector; + uint32_t capacity = img.file.size() / bytesPerSector; + + debuglog("------ Locate tape to LBA ", (int)lba); + + if (lba >= capacity) + { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + scsiDev.phase = STATUS; + } + else + { + delay(10); + img.tape_pos = lba; + + scsiDev.status = GOOD; + scsiDev.phase = STATUS; + } +} + extern "C" int scsiTapeCommand() { image_config_t &img = *(image_config_t*)scsiDev.target->cfg; @@ -158,6 +183,12 @@ extern "C" int scsiTapeCommand() img.tape_pos += length; } } + else if (command == 0x19) + { + // Erase + // Just a stub implementation, fake erase to end of tape + img.tape_pos = img.scsiSectors; + } else if (command == 0x01) { // REWIND @@ -230,6 +261,47 @@ extern "C" int scsiTapeCommand() scsiDev.phase = STATUS; } } + else if (command == 0x2B) + { + // Seek/Locate 10 + uint32_t lba = + (((uint32_t) scsiDev.cdb[3]) << 24) + + (((uint32_t) scsiDev.cdb[4]) << 16) + + (((uint32_t) scsiDev.cdb[5]) << 8) + + scsiDev.cdb[6]; + + doSeek(lba); + } + else if (command == 0x34) + { + // ReadPosition + uint32_t lba = img.tape_pos; + scsiDev.data[0] = 0x00; + if (lba == 0) scsiDev.data[0] |= 0x80; + if (lba >= img.scsiSectors) scsiDev.data[0] |= 0x40; + scsiDev.data[1] = 0x00; + scsiDev.data[2] = 0x00; + scsiDev.data[3] = 0x00; + scsiDev.data[4] = (lba >> 24) & 0xFF; // Next block on tape + scsiDev.data[5] = (lba >> 16) & 0xFF; + scsiDev.data[6] = (lba >> 8) & 0xFF; + scsiDev.data[7] = (lba >> 0) & 0xFF; + scsiDev.data[8] = (lba >> 24) & 0xFF; // Last block in buffer + scsiDev.data[9] = (lba >> 16) & 0xFF; + scsiDev.data[10] = (lba >> 8) & 0xFF; + scsiDev.data[11] = (lba >> 0) & 0xFF; + scsiDev.data[12] = 0x00; + scsiDev.data[13] = 0x00; + scsiDev.data[14] = 0x00; + scsiDev.data[15] = 0x00; + scsiDev.data[16] = 0x00; + scsiDev.data[17] = 0x00; + scsiDev.data[18] = 0x00; + scsiDev.data[19] = 0x00; + + scsiDev.phase = DATA_IN; + scsiDev.dataLen = 20; + } else { commandHandled = 0;