Parcourir la source

Merge pull request #387 from ZuluSCSI/plextor-d8h-vendor-cmd

Plextor d8h vendor cmd
Alex Perez il y a 1 an
Parent
commit
c90e69b886

+ 1 - 1
.github/workflows/firmware_build.yml

@@ -14,7 +14,7 @@ jobs:
     
     steps:
       - name: Check out code from GitHub
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           path: ZuluSCSI
           fetch-depth: "0"

+ 4 - 1
lib/SCSI2SD/include/scsi2sd.h

@@ -133,7 +133,10 @@ typedef struct __attribute__((packed))
 
 	uint16_t quirks; // S2S_CFG_QUIRKS
 
-	uint8_t reserved[64]; // Pad out to 128 bytes for main section.
+	// bit flags vendor extention for specific device types
+	uint32_t vendorExtensions;
+
+	uint8_t reserved[60]; // Pad out to 128 bytes for main section.
 } S2S_TargetCfg;
 
 typedef struct __attribute__((packed))

+ 11 - 0
lib/SCSI2SD/src/firmware/scsi.c

@@ -307,6 +307,17 @@ static void process_Command()
 
 	group = scsiDev.cdb[0] >> 5;
 	scsiDev.cdbLen = CmdGroupBytes[group];
+
+	if (scsiDev.target->cfg->deviceType == S2S_CFG_OPTICAL)
+	{
+		// Plextor CD-ROM vendor extensions 0xD8
+		if (unlikely(scsiDev.target->cfg->vendorExtensions & VENDOR_EXTENSION_OPTICAL_PLEXTOR))
+
+			if (scsiDev.cdb[0] == 0xD8)
+			{
+				scsiDev.cdbLen =  12;
+			}
+	}
 	if (parityError &&
 		(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))
 	{

+ 6 - 0
lib/SCSI2SD/src/firmware/scsi.h

@@ -183,6 +183,12 @@ typedef struct
 	int hostSpeedMeasured;
 } ScsiDevice;
 
+typedef enum
+{
+	VENDOR_EXTENSION_OPTICAL_PLEXTOR = 1 << 0,
+} VENDOR_EXTENSION_OPTICAL;
+
+
 extern ScsiDevice scsiDev;
 
 void process_Status(void);

+ 3 - 3
platformio.ini

@@ -153,8 +153,8 @@ debug_build_flags =
     -DLOGBUFSIZE=4096
     -DPREFETCH_BUFFER_SIZE=0
     -DSCSI2SD_BUFFER_SIZE=57344
-    ; This controls the depth of 2 x NETWORK_PACKET_MAX_SIZE (1520 bytes)
-    ; For example a queue size of 10 would be 10 x 2 x 1520 = 30400 bytes
+    ; This controls the depth NETWORK_PACKET_MAX_SIZE (1520 bytes)
+    ; For example a queue size of 10 would be 10 x 1520 = 30400 bytes
     -DNETWORK_PACKET_QUEUE_SIZE=10
 
 lib_deps =
@@ -176,7 +176,7 @@ build_flags =
     -DZULUSCSI_DAYNAPORT
 ; These take a large portion of the SRAM and can be adjusted
     -DLOGBUFSIZE=8192
-    -DPREFETCH_BUFFER_SIZE=5632
+    -DPREFETCH_BUFFER_SIZE=5120
     -DSCSI2SD_BUFFER_SIZE=57344
     ; This controls the depth of NETWORK_PACKET_MAX_SIZE (1520 bytes)
     ; For example a queue size of 10 would be 10 x 1520 = 15200 bytes

+ 84 - 5
src/ZuluSCSI_cdrom.cpp

@@ -31,8 +31,10 @@
 #include "ZuluSCSI_cdrom.h"
 #include "ZuluSCSI_log.h"
 #include "ZuluSCSI_config.h"
+#include "ZuluSCSI_settings.h"
 #include <CUEParser.h>
 #include <assert.h>
+#include <minIni.h>
 #ifdef ENABLE_AUDIO_OUTPUT
 #include "ZuluSCSI_audio.h"
 #endif
@@ -218,6 +220,11 @@ static const uint8_t TrackInformation[] =
     0x00,   // 27: track size (LSB)
 };
 
+enum sector_type_t
+{
+     SECTOR_TYPE_VENDOR_PLEXTOR = 100,
+};
+
 // Convert logical block address to CD-ROM time
 static void LBA2MSF(int32_t LBA, uint8_t* MSF, bool relative)
 {
@@ -1490,12 +1497,38 @@ static void doReadCD(uint32_t lba, uint32_t length, uint8_t sector_type,
     getTrackFromLBA(parser, lba, &trackinfo);
 
     // Figure out the data offset in the file
-    uint64_t offset = trackinfo.file_offset + trackinfo.sector_length * (lba - trackinfo.track_start);
-    dbgmsg("------ Read CD: ", (int)length, " sectors starting at ", (int)lba,
-           ", track number ", trackinfo.track_number, ", sector size ", (int)trackinfo.sector_length,
-           ", main channel ", main_channel, ", sub channel ", sub_channel,
-           ", data offset in file ", (int)offset);
+    uint64_t offset;
+    if (sector_type == SECTOR_TYPE_VENDOR_PLEXTOR &&
+         g_scsi_settings.getDevice(img.scsiId & 0x7)->vendorExtensions & VENDOR_EXTENSION_OPTICAL_PLEXTOR)
+    {
+        // This overrides values so doReadCD can be used with the
+        // Vendor specific Plextor 0xD8 command to read raw CD data
+        if (lba < 2)
+        {
+            logmsg("WARNING: Plextor CD-ROM vendor extension 0xd8 lba start below 2 is not implemented. LBA is ", lba);
+            scsiDev.status = CHECK_CONDITION;
+            scsiDev.target->sense.code = ILLEGAL_REQUEST;
+            scsiDev.target->sense.asc = LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+            scsiDev.phase = STATUS;
+            return;
+        }
 
+        const uint16_t PLEXTOR_D8_SECTOR_LENGTH =  2352;
+        trackinfo.sector_length = PLEXTOR_D8_SECTOR_LENGTH;
+        trackinfo.track_mode = CUETrack_AUDIO;
+        offset = (uint64_t)(lba - 2) * trackinfo.sector_length;
+        dbgmsg("------ Read CD Vendor Plextor (0xd8): ", (int)length, " sectors starting at ", (int)lba -2,
+               ", sector size ", (int) PLEXTOR_D8_SECTOR_LENGTH,
+               ", data offset in file ", (int)offset);
+    }
+    else
+    {
+        offset = trackinfo.file_offset + trackinfo.sector_length * (lba - trackinfo.track_start);
+        dbgmsg("------ Read CD: ", (int)length, " sectors starting at ", (int)lba,
+            ", track number ", trackinfo.track_number, ", sector size ", (int)trackinfo.sector_length,
+            ", main channel ", main_channel, ", sub channel ", sub_channel,
+            ", data offset in file ", (int)offset);
+    }
     // Ensure read is not out of range of the image
     uint64_t readend = offset + trackinfo.sector_length * length;
     if (readend > img.file.size())
@@ -1521,6 +1554,11 @@ static void doReadCD(uint32_t lba, uint32_t length, uint8_t sector_type,
         {
             sector_type_ok = true;
         }
+        else if (sector_type == SECTOR_TYPE_VENDOR_PLEXTOR && 
+            g_scsi_settings.getDevice(img.scsiId & 0x7)->vendorExtensions & VENDOR_EXTENSION_OPTICAL_PLEXTOR)
+        {
+            sector_type_ok = true;
+        }
 
         if (!sector_type_ok)
         {
@@ -1838,6 +1876,11 @@ static bool doReadCapacity(uint32_t lba, uint8_t pmi)
     return true;
 }
 
+static void doReadD8(uint32_t lba, uint32_t length)
+{
+    doReadCD(lba, length, SECTOR_TYPE_VENDOR_PLEXTOR, true, false, false );
+}
+
 /**************************************/
 /* CD-ROM command dispatching         */
 /**************************************/
@@ -2140,6 +2183,42 @@ extern "C" int scsiCDRomCommand()
 
         doReadCD(lba, blocks, 0, 0x10, 0, true);
     }
+    else if (unlikely(scsiDev.target->cfg->vendorExtensions & VENDOR_EXTENSION_OPTICAL_PLEXTOR) && 
+            command == 0xD8)
+    {
+        uint8_t lun = scsiDev.cdb[1] & 0x7;
+        uint8_t subcode = scsiDev.cdb[10];
+        if (lun != 0)
+        {
+            logmsg("ERROR: Plextor vendor 0xD8 command only supports LUN 0. Given ", (int)lun);
+            scsiDev.status = CHECK_CONDITION;
+            scsiDev.target->sense.code = ILLEGAL_REQUEST;
+            scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+            scsiDev.phase = STATUS;
+        }
+        else if (subcode != 0)
+        {
+            logmsg("ERROR: Plextor vendor 0xD8 command subcodes not supported. Given ", subcode);
+            scsiDev.status = CHECK_CONDITION;
+            scsiDev.target->sense.code = ILLEGAL_REQUEST;
+            scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+            scsiDev.phase = STATUS;
+        }
+        else
+        {
+            uint32_t lba =
+                (((uint32_t) scsiDev.cdb[2]) << 24) +
+                (((uint32_t) scsiDev.cdb[3]) << 16) +
+                (((uint32_t) scsiDev.cdb[4]) << 8) +
+                scsiDev.cdb[5];
+            uint32_t blocks =
+                (((uint32_t) scsiDev.cdb[6]) << 24) +
+                (((uint32_t) scsiDev.cdb[7]) << 16) +
+                (((uint32_t) scsiDev.cdb[8]) << 8) +
+                scsiDev.cdb[9];
+            doReadD8(lba, blocks);
+        }
+    }
     else if (command == 0x4E)
     {
         // STOP PLAY/SCAN

+ 2 - 0
src/ZuluSCSI_disk.cpp

@@ -250,6 +250,8 @@ static void scsiDiskSetImageConfig(uint8_t target_idx)
     img.reinsert_on_inquiry = devCfg->reinsertOnInquiry;
     img.reinsert_after_eject = devCfg->reinsertAfterEject;
     img.ejectButton = devCfg->ejectButton;
+    img.vendorExtensions = devCfg->vendorExtensions;
+
 #ifdef ENABLE_AUDIO_OUTPUT
     uint16_t vol = devCfg->vol;
     // Set volume on both channels

+ 1 - 0
src/ZuluSCSI_log_trace.cpp

@@ -100,6 +100,7 @@ static const char *getCommandName(uint8_t cmd)
         case 0xA8: return "Read12";
         case 0xC0: return "OMTI-5204 DefineFlexibleDiskFormat";
         case 0xC2: return "OMTI-5204 AssignDiskParameters";
+        case 0xD8: return "Plextor ReadCD";
         case 0xE0: return "Xebec RAM Diagnostic";
         case 0xE4: return "Xebec Drive Diagnostic";              
         default:   return "Unknown";

+ 4 - 0
src/ZuluSCSI_settings.cpp

@@ -226,6 +226,8 @@ static void readIniSCSIDeviceSetting(scsi_device_settings_t &cfg, const char *se
     cfg.sectorSDBegin = ini_getl(section, "SectorSDBegin", cfg.sectorSDBegin, CONFIGFILE);
     cfg.sectorSDEnd = ini_getl(section, "SectorSDEnd", cfg.sectorSDEnd, CONFIGFILE);
 
+    cfg.vendorExtensions = ini_getl(section, "VendorExtensions", cfg.vendorExtensions, CONFIGFILE);
+
     char tmp[32];
     ini_gets(section, "Vendor", "", tmp, sizeof(tmp), CONFIGFILE);
     if (tmp[0])
@@ -306,6 +308,8 @@ scsi_system_settings_t *ZuluSCSISettings::initSystem(const char *presetName)
     cfgDev.sectorSDBegin = 0;
     cfgDev.sectorSDEnd = 0;
 
+    cfgDev.vendorExtensions = 0;
+
     // System-specific defaults
 
     if (strequals(systemPresetName[SYS_PRESET_NONE], presetName))

+ 2 - 0
src/ZuluSCSI_settings.h

@@ -93,6 +93,8 @@ typedef struct __attribute__((__packed__)) scsi_device_settings_t
 
     uint32_t sectorSDBegin;
     uint32_t sectorSDEnd;
+
+    uint32_t vendorExtensions;
 } scsi_device_settings_t;
 
 

+ 2 - 0
zuluscsi.ini

@@ -48,6 +48,8 @@
 #Version = "1.0"
 #Serial = "0123456789ABCDEF"
 #Type = 0     # 0: Fixed, 1: Removable, 2: Optical, 3: Floppy, 4: Mag-optical, 5: Tape, 6: Network
+#VendorExtensions = 0 # Bit flags for specific extensions per device type
+#  CDROM - 1: Plextor's d8h vendor command
 #TypeModifier = 0  # Affects only INQUIRY response
 #SectorsPerTrack = 63
 #HeadsPerCylinder = 255