Initial tape and magneto-optical support
authorMichael McMaster <michael@codesrc.com>
Sun, 6 Sep 2015 05:15:41 +0000 (15:15 +1000)
committerMichael McMaster <michael@codesrc.com>
Sun, 6 Sep 2015 05:15:41 +0000 (15:15 +1000)
software/SCSI2SD/src/cdrom.c
software/SCSI2SD/src/inquiry.c
software/SCSI2SD/src/mo.c [new file with mode: 0644]
software/SCSI2SD/src/mo.h [new file with mode: 0644]
software/SCSI2SD/src/mode.c
software/SCSI2SD/src/scsi.c
software/SCSI2SD/src/tape.c [new file with mode: 0644]
software/SCSI2SD/src/tape.h [new file with mode: 0644]
software/include/scsi2sd.h
software/scsi2sd-util/TargetPanel.cc

index 18ed321..1c9305f 100755 (executable)
@@ -277,50 +277,43 @@ int scsiCDRomCommand()
        int commandHandled = 1;
 
        uint8 command = scsiDev.cdb[0];
-       if (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)
+       if (command == 0x43)
        {
-               if (command == 0x43)
-               {
-                       // CD-ROM Read TOC
-                       int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
-                       uint8_t track = scsiDev.cdb[6];
-                       uint16_t allocationLength =
-                               (((uint32_t) scsiDev.cdb[7]) << 8) +
-                               scsiDev.cdb[8];
+               // CD-ROM Read TOC
+               int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
+               uint8_t track = scsiDev.cdb[6];
+               uint16_t allocationLength =
+                       (((uint32_t) scsiDev.cdb[7]) << 8) +
+                       scsiDev.cdb[8];
 
-                       // Reject MMC commands for now, otherwise the TOC data format
-                       // won't be understood.
-                       // The "format" field is reserved for SCSI-2
-                       uint8_t format = scsiDev.cdb[2] & 0x0F;
-                       switch (format)
+               // Reject MMC commands for now, otherwise the TOC data format
+               // won't be understood.
+               // The "format" field is reserved for SCSI-2
+               uint8_t format = scsiDev.cdb[2] & 0x0F;
+               switch (format)
+               {
+                       case 0: doReadTOC(MSF, track, allocationLength); break; // SCSI-2
+                       case 1: doReadSessionInfo(MSF, allocationLength); break; // MMC2
+                       case 2: doReadFullTOC(0, track, allocationLength); break; // MMC2
+                       case 3: doReadFullTOC(1, track, allocationLength); break; // MMC2
+                       default:
                        {
-                               case 0: doReadTOC(MSF, track, allocationLength); break; // SCSI-2
-                               case 1: doReadSessionInfo(MSF, allocationLength); break; // MMC2
-                               case 2: doReadFullTOC(0, track, allocationLength); break; // MMC2
-                               case 3: doReadFullTOC(1, track, allocationLength); break; // MMC2
-                               default:
-                               {
-                                       scsiDev.status = CHECK_CONDITION;
-                                       scsiDev.target->sense.code = ILLEGAL_REQUEST;
-                                       scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
-                                       scsiDev.phase = STATUS;
-                               }
+                               scsiDev.status = CHECK_CONDITION;
+                               scsiDev.target->sense.code = ILLEGAL_REQUEST;
+                               scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+                               scsiDev.phase = STATUS;
                        }
                }
-               else if (command == 0x44)
-               {
-                       // CD-ROM Read Header
-                       int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
-                       uint32_t lba = 0; // IGNORED for now
-                       uint16_t allocationLength =
-                               (((uint32_t) scsiDev.cdb[7]) << 8) +
-                               scsiDev.cdb[8];
-                       doReadHeader(MSF, lba, allocationLength);
-               }
-               else
-               {
-                       commandHandled = 0;
-               }
+       }
+       else if (command == 0x44)
+       {
+               // CD-ROM Read Header
+               int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
+               uint32_t lba = 0; // IGNORED for now
+               uint16_t allocationLength =
+                       (((uint32_t) scsiDev.cdb[7]) << 8) +
+                       scsiDev.cdb[8];
+               doReadHeader(MSF, lba, allocationLength);
        }
        else
        {
index cf9bab7..1a88f5c 100755 (executable)
@@ -203,6 +203,16 @@ void scsiInquiry()
                        scsiDev.data[1] |= 0x80; // Removable bit.\r
                        break;\r
 \r
+               case CONFIG_SEQUENTIAL:\r
+                       scsiDev.data[0] = 0x01; // device type\r
+                       scsiDev.data[1] |= 0x80; // Removable bit.\r
+                       break;\r
+                       \r
+               case CONFIG_MO:\r
+                       scsiDev.data[0] = 0x07; // device type\r
+                       scsiDev.data[1] |= 0x80; // Removable bit.\r
+                       break;\r
+\r
                case CONFIG_FLOPPY_14MB:\r
                case CONFIG_REMOVEABLE:\r
                        scsiDev.data[1] |= 0x80; // Removable bit.\r
diff --git a/software/SCSI2SD/src/mo.c b/software/SCSI2SD/src/mo.c
new file mode 100644 (file)
index 0000000..e13acc5
--- /dev/null
@@ -0,0 +1,43 @@
+//     Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
+//
+//     This file is part of SCSI2SD.
+//
+//     SCSI2SD is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+//
+//     SCSI2SD is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+//
+//     You should have received a copy of the GNU General Public License
+//     along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
+#pragma GCC push_options
+#pragma GCC optimize("-flto")
+
+#include "device.h"
+#include "scsi.h"
+#include "config.h"
+#include "mo.h"
+
+
+// Handle magneto-optical scsi device commands
+int scsiMOCommand()
+{
+       int commandHandled = 0;
+
+       uint8 command = scsiDev.cdb[0];
+       if ((command == 0x2C) || // ERASE(10)
+               (command == 0xAC)) // ERASE(12)
+       {
+               // TODO consider sending an erase command to the SD card.
+
+               commandHandled = 1;
+       }
+
+       return commandHandled;
+}
+
+#pragma GCC pop_options
diff --git a/software/SCSI2SD/src/mo.h b/software/SCSI2SD/src/mo.h
new file mode 100644 (file)
index 0000000..fe996d2
--- /dev/null
@@ -0,0 +1,22 @@
+//     Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
+//
+//     This file is part of SCSI2SD.
+//
+//     SCSI2SD is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+//
+//     SCSI2SD is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+//
+//     You should have received a copy of the GNU General Public License
+//     along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
+#ifndef MO_H
+#define MO_H
+
+int scsiMOCommand(void);
+
+#endif
index 2eb3c50..b7bd9c0 100755 (executable)
@@ -161,6 +161,22 @@ static const uint8 ControlModePage[] =
 0x00, 0x00 // AEN holdoff period.\r
 };\r
 \r
+static const uint8_t SequentialDeviceConfigPage[] =\r
+{\r
+0x10, // page code\r
+0x0E, // Page length\r
+0x00, // CAP, CAF, Active Format\r
+0x00, // Active partition\r
+0x00, // Write buffer full ratio\r
+0x00, // Read buffer empty ratio\r
+0x00,0x01, // Write delay time, in 100ms units\r
+0x00, // Default gap size\r
+0x10, // auto-generation of default eod (end of data)\r
+0x00,0x00,0x00 // buffer-size at early warning\r
+0x00, // No data compression\r
+0x00 // reserved\r
+};\r
+\r
 // Allow Apple 68k Drive Setup to format this drive.\r
 // Code\r
 static const uint8 AppleVendorPage[] =\r
@@ -218,6 +234,17 @@ static void doModeSense(
                density = 0x01; // User data only, 2048bytes per sector.\r
                break;\r
 \r
+       case CONFIG_SEQUENTIAL:\r
+               mediumType = 0; // reserved\r
+               deviceSpecificParam =\r
+                       (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+               density = 0x13; // DAT Data Storage, X3B5/88-185A \r
+               break;\r
+\r
+       case CONFIG_MO:\r
+               TODO\r
+               break;\r
+\r
        };\r
 \r
        scsiDev.data[idx++] = mediumType;\r
@@ -400,6 +427,18 @@ static void doModeSense(
                idx += sizeof(ControlModePage);\r
        }\r
 \r
+       if ((scsiDev.target->cfg->deviceType == CONFIG_SEQUENTIAL) &&\r
+               (pageCode == 0x10 || pageCode == 0x3F))\r
+       {\r
+               pageFound = 1;\r
+               pageIn(\r
+                       pc,\r
+                       idx,\r
+                       SequentialDeviceConfigPage,\r
+                       sizeof(SequentialDeviceConfigPage));\r
+               idx += sizeof(SequentialDeviceConfigPage);\r
+       }\r
+\r
        if ((\r
                        (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) ||\r
                        (idx + sizeof(AppleVendorPage) <= allocLength)\r
index d8f5d7c..48b4c6d 100755 (executable)
@@ -264,6 +264,7 @@ static void process_Command()
        control = scsiDev.cdb[scsiDev.cdbLen - 1];\r
 \r
        scsiDev.cmdCount++;\r
+       TargetConfig* cfg = scsiDev.target->cfg;\r
 \r
        if (unlikely(scsiDev.resetFlag))\r
        {\r
@@ -273,7 +274,7 @@ static void process_Command()
                return;\r
        }\r
        else if (scsiDev.parityError &&\r
-               (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
+               (cfg->flags & CONFIG_ENABLE_PARITY) &&\r
                (scsiDev.compatMode >= COMPAT_SCSI2))\r
        {\r
                scsiDev.target->sense.code = ABORTED_COMMAND;\r
@@ -326,7 +327,7 @@ static void process_Command()
        // on receiving the unit attention response on boot, thus\r
        // triggering another unit attention condition.\r
        else if (scsiDev.target->unitAttention &&\r
-               (scsiDev.target->cfg->flags & CONFIG_ENABLE_UNIT_ATTENTION))\r
+               (cfg->flags & CONFIG_ENABLE_UNIT_ATTENTION))\r
        {\r
                scsiDev.target->sense.code = UNIT_ATTENTION;\r
                scsiDev.target->sense.asc = scsiDev.target->unitAttention;\r
@@ -352,6 +353,14 @@ static void process_Command()
        {\r
                enter_Status(CONFLICT);\r
        }\r
+       // Handle odd device types first that may override basic read and\r
+       // write commands. Will fall-through to generic disk handling.\r
+       else if (((cfg->deviceType == CONFIG_OPTICAL) && scsiCDRomCommand()) ||\r
+               ((cfg->deviceType == CONFIG_SEQUENTIAL) && scsiTapeCommand()) ||\r
+               ((cfg->deviceType == CONFIG_MO) && scsiMOCommand()))\r
+       {\r
+               // Already handled.\r
+       }\r
        else if (scsiDiskCommand())\r
        {\r
                // Already handled.\r
@@ -374,9 +383,7 @@ static void process_Command()
        {\r
                scsiReadBuffer();\r
        }\r
-       else if (\r
-               !scsiCDRomCommand() &&\r
-               !scsiModeCommand())\r
+       else if (!scsiModeCommand())\r
        {\r
                scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
                scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;\r
diff --git a/software/SCSI2SD/src/tape.c b/software/SCSI2SD/src/tape.c
new file mode 100644 (file)
index 0000000..9416a95
--- /dev/null
@@ -0,0 +1,33 @@
+//     Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
+//
+//     This file is part of SCSI2SD.
+//
+//     SCSI2SD is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+//
+//     SCSI2SD is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+//
+//     You should have received a copy of the GNU General Public License
+//     along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
+#pragma GCC push_options
+#pragma GCC optimize("-flto")
+
+#include "device.h"
+#include "scsi.h"
+#include "config.h"
+#include "tape.h"
+
+// Handle sequential scsi device commands
+int scsiTapeCommand()
+{
+       // TODO handle tape-specific read/write commands and return 1
+
+       return 0;
+}
+
+#pragma GCC pop_options
diff --git a/software/SCSI2SD/src/tape.h b/software/SCSI2SD/src/tape.h
new file mode 100644 (file)
index 0000000..1249731
--- /dev/null
@@ -0,0 +1,22 @@
+//     Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
+//
+//     This file is part of SCSI2SD.
+//
+//     SCSI2SD is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+//
+//     SCSI2SD is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+//
+//     You should have received a copy of the GNU General Public License
+//     along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
+#ifndef TAPE_H
+#define TAPE_H
+
+int scsiTapeCommand(void);
+
+#endif
index 22202cf..71d50f6 100755 (executable)
@@ -93,7 +93,10 @@ typedef enum
        CONFIG_FIXED,
        CONFIG_REMOVEABLE,
        CONFIG_OPTICAL,
-       CONFIG_FLOPPY_14MB
+       CONFIG_FLOPPY_14MB,
+       CONFIG_MO,
+       CONFIG_SEQUENTIAL
+
 } CONFIG_TYPE;
 
 typedef enum
index ecbdf51..afd9480 100644 (file)
@@ -109,7 +109,8 @@ TargetPanel::TargetPanel(wxWindow* parent, const TargetConfig& initialConfig) :
                wxT("Hard Drive"),
                wxT("Removable"),
                wxT("CDROM"),
-               wxT("3.5\" Floppy")
+               wxT("3.5\" Floppy"),
+               wxT("Magneto optical")
        };
        myDeviceTypeCtrl =
                new wxChoice(