浏览代码

Merge pull request #27 from ZuluSCSI/release-1.0.5

Prepare for firmware release 1.0.5
Alex Perez 3 年之前
父节点
当前提交
3aefe7ef0f
共有 5 个文件被更改,包括 209 次插入13 次删除
  1. 20 5
      src/ZuluSCSI.cpp
  2. 7 1
      src/ZuluSCSI_config.h
  3. 173 5
      src/ZuluSCSI_disk.cpp
  4. 1 1
      src/ZuluSCSI_disk.h
  5. 8 1
      zuluscsi.ini

+ 20 - 5
src/ZuluSCSI.cpp

@@ -58,6 +58,7 @@ FsFile g_logfile;
 /* Status reporting by blinking led */
 /************************************/
 
+#define BLINK_STATUS_OK 1
 #define BLINK_ERROR_NO_IMAGES  3 
 #define BLINK_ERROR_NO_SD_CARD 5
 
@@ -210,8 +211,9 @@ bool findHDDImages()
       file.close();
       bool is_hd = (tolower(name[0]) == 'h' && tolower(name[1]) == 'd');
       bool is_cd = (tolower(name[0]) == 'c' && tolower(name[1]) == 'd');
+      bool is_fd = (tolower(name[0]) == 'f' && tolower(name[1]) == 'd');
 
-      if (is_hd || is_cd)
+      if (is_hd || is_cd || is_fd)
       {
         // Check file extension
         // We accept anything except known compressed files
@@ -306,7 +308,7 @@ bool findHDDImages()
         // Open the image file
         if(id < NUM_SCSIID && lun < NUM_SCSILUN) {
           azlog("-- Opening ", fullname, " for id:", id, " lun:", lun);
-          imageReady = scsiDiskOpenHDDImage(id, fullname, id, lun, blk, is_cd);
+          imageReady = scsiDiskOpenHDDImage(id, fullname, id, lun, blk, is_cd, is_fd);
           if(imageReady)
           {
             foundImage = true;
@@ -384,7 +386,15 @@ static void reinitSCSI()
   if (foundImage)
   {
     // Ok, there is an image
-    blinkStatus(1);
+    blinkStatus(BLINK_STATUS_OK);
+  }
+  else
+  {
+#if RAW_FALLBACK_ENABLE
+    azlog("No images found, enabling RAW fallback partition");
+    scsiDiskOpenHDDImage(RAW_FALLBACK_SCSI_ID, "RAW:0:0xFFFFFFFF", RAW_FALLBACK_SCSI_ID, 0,
+                         RAW_FALLBACK_BLOCKSIZE, false, false);
+#endif
   }
 
   scsiPhyReset();
@@ -398,7 +408,7 @@ extern "C" int zuluscsi_main(void)
   azplatform_init();
   azplatform_late_init();
 
-  if(!SD.begin(SD_CONFIG))
+  if(!SD.begin(SD_CONFIG) && (!SD.card() || SD.sdErrorCode() != 0))
   {
     azlog("SD card init failed, sdErrorCode: ", (int)SD.sdErrorCode(),
            " sdErrorData: ", (int)SD.sdErrorData());
@@ -408,10 +418,15 @@ extern "C" int zuluscsi_main(void)
       blinkStatus(BLINK_ERROR_NO_SD_CARD);
       delay(1000);
       azplatform_reset_watchdog();
-    } while (!SD.begin(SD_CONFIG));
+    } while (!SD.begin(SD_CONFIG) && (!SD.card() || SD.sdErrorCode() != 0));
     azlog("SD card init succeeded after retry");
   }
 
+  if (SD.clusterCount() == 0)
+  {
+    azlog("SD card without filesystem!");
+  }
+
   print_sd_info();
   
   reinitSCSI();

+ 7 - 1
src/ZuluSCSI_config.h

@@ -4,7 +4,7 @@
 #pragma once
 
 // Use variables for version number
-#define FW_VER_NUM      "1.0.4"
+#define FW_VER_NUM      "1.0.5"
 #define FW_VER_SUFFIX   "release"
 #define ZULU_FW_VERSION FW_VER_NUM "-" FW_VER_SUFFIX
 
@@ -35,6 +35,12 @@
 #define NUM_SCSILUN 1          // Maximum number of LUNs supported     (Currently has to be 1)
 #define READ_PARITY_CHECK 0    // Perform read parity check (unverified)
 
+// SCSI raw fallback configuration when no image files are detected
+// Presents the whole SD card as an SCSI drive
+#define RAW_FALLBACK_ENABLE 1
+#define RAW_FALLBACK_SCSI_ID 1
+#define RAW_FALLBACK_BLOCKSIZE 512
+
 // Default SCSI drive information (can be overridden in INI file)
 // Selected based on device type (fixed, removable, optical, floppy, mag-optical, tape)
 // Each entry has {vendor, product, version, serial}

+ 173 - 5
src/ZuluSCSI_disk.cpp

@@ -11,6 +11,8 @@
 #include "ZuluSCSI_config.h"
 #include <minIni.h>
 #include <string.h>
+#include <strings.h>
+#include <assert.h>
 #include <SdFat.h>
 
 extern "C" {
@@ -41,6 +43,8 @@ extern "C" {
 #define PLATFORM_OPTIMAL_LAST_SD_WRITE_SIZE 512
 #endif
 
+// SD card sector size is always 512 bytes
+#define SD_SECTOR_SIZE 512
 
 /***********************/
 /* Backing image files */
@@ -49,9 +53,168 @@ extern "C" {
 extern SdFs SD;
 SdDevice sdDev = {2, 256 * 1024 * 1024 * 2}; /* For SCSI2SD */
 
+// This class wraps SdFat library FsFile to allow access
+// through either FAT filesystem or as a raw sector range.
+//
+// Raw access is activated by using filename like "RAW:0:12345"
+// where the numbers are the first and last sector.
+class ImageBackingStore
+{
+public:
+    ImageBackingStore()
+    {
+        m_israw = false;
+        m_blockdev = nullptr;
+        m_bgnsector = m_endsector = m_cursector = 0;
+    }
+
+    ImageBackingStore(const char *filename): ImageBackingStore()
+    {
+        if (strncasecmp(filename, "RAW:", 4) == 0)
+        {
+            char *endptr, *endptr2;
+            m_bgnsector = strtoul(filename + 4, &endptr, 0);
+            m_endsector = strtoul(endptr + 1, &endptr2, 0);
+
+            if (*endptr != ':' || *endptr2 != '\0')
+            {
+                azlog("Invalid format for raw filename: ", filename);
+                return;
+            }
+
+            m_israw = true;
+            m_blockdev = SD.card();
+
+            if (m_endsector >= SD.card()->sectorCount())
+            {
+                m_endsector = SD.card()->sectorCount() - 1;
+            }
+        }
+        else
+        {
+            m_fsfile = SD.open(filename, O_RDWR);
+        }
+    }
+
+    bool isOpen() { return m_israw ? !!m_blockdev : m_fsfile.isOpen(); }
+    bool close()
+    {
+        if (m_israw)
+        {
+            m_blockdev = nullptr;
+            return true;
+        }
+        else
+        {
+            return m_fsfile.close();
+        }
+    }
+
+    uint64_t size()
+    {
+        if (m_israw && m_blockdev)
+        {
+            return (uint64_t)(m_endsector - m_bgnsector + 1) * SD_SECTOR_SIZE;
+        }
+        else
+        {
+            return m_fsfile.size();
+        }
+    }
+
+    bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector)
+    {
+        if (m_israw && m_blockdev)
+        {
+            *bgnSector = m_bgnsector;
+            *endSector = m_endsector;
+            return true;
+        }
+        else
+        {
+            return m_fsfile.contiguousRange(bgnSector, endSector);
+        }
+    }
+
+    bool seek(uint64_t pos)
+    {
+        if (m_israw && m_blockdev)
+        {
+            uint32_t sectornum = pos / SD_SECTOR_SIZE;
+            assert((uint64_t)sectornum * SD_SECTOR_SIZE == pos);
+            m_cursector = m_bgnsector + sectornum;
+            return (m_cursector <= m_endsector);
+        }
+        else
+        {
+            return m_fsfile.seek(pos);
+        }
+    }
+
+    int read(void* buf, size_t count)
+    {
+        if (m_israw && m_blockdev)
+        {
+            uint32_t sectorcount = count / SD_SECTOR_SIZE;
+            assert((uint64_t)sectorcount * SD_SECTOR_SIZE == count);
+            if (m_blockdev->readSectors(m_cursector, (uint8_t*)buf, sectorcount))
+            {
+                m_cursector += sectorcount;
+                return count;
+            }
+            else
+            {
+                return -1;
+            }
+        }
+        else
+        {
+            return m_fsfile.read(buf, count);
+        }
+    }
+
+    size_t write(const void* buf, size_t count)
+    {
+        if (m_israw && m_blockdev)
+        {
+            uint32_t sectorcount = count / SD_SECTOR_SIZE;
+            assert((uint64_t)sectorcount * SD_SECTOR_SIZE == count);
+            if (m_blockdev->writeSectors(m_cursector, (const uint8_t*)buf, sectorcount))
+            {
+                m_cursector += sectorcount;
+                return count;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+        else
+        {
+            return m_fsfile.write(buf, count);
+        }
+    }
+
+    void flush()
+    {
+        if (!m_israw)
+        {
+            m_fsfile.flush();
+        }
+    }
+
+private:
+    bool m_israw;
+    FsFile m_fsfile;
+    SdCard *m_blockdev;
+    uint32_t m_bgnsector;
+    uint32_t m_endsector;
+    uint32_t m_cursector;
+};
+
 struct image_config_t: public S2S_TargetCfg
 {
-    FsFile file;
+    ImageBackingStore file;
 
     // For CD-ROM drive ejection
     bool ejected;
@@ -201,10 +364,10 @@ static void setDefaultDriveInfo(int target_idx)
     formatDriveInfoField(img.serial, sizeof(img.serial), true);
 }
 
-bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int scsi_lun, int blocksize, bool is_cd)
+bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int scsi_lun, int blocksize, bool is_cd, bool is_fd)
 {
     image_config_t &img = g_DiskImages[target_idx];
-    img.file = SD.open(filename, O_RDWR);
+    img.file = ImageBackingStore(filename);
 
     if (img.file.isOpen())
     {
@@ -243,6 +406,11 @@ bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int
             azlog("---- Configuring as CD-ROM drive based on image name");
             img.deviceType = S2S_CFG_OPTICAL;
         }
+        else if (is_fd)
+        {
+            azlog("---- Configuring as floppy drive based on image name");
+            img.deviceType = S2S_CFG_FLOPPY_14MB;
+        }
 
 #ifdef AZPLATFORM_CONFIG_HOOK
         AZPLATFORM_CONFIG_HOOK(&img);
@@ -348,7 +516,7 @@ void scsiDiskLoadConfig(int target_idx)
         image_config_t &img = g_DiskImages[target_idx];
         int blocksize = (img.deviceType == S2S_CFG_OPTICAL) ? 2048 : 512;
         azlog("-- Opening ", filename, " for id:", target_idx, ", specified in " CONFIGFILE);
-        scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, blocksize, false);
+        scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, blocksize, false, false);
     }
 }
 
@@ -600,7 +768,7 @@ static bool checkNextCDImage()
         azlog("Switching to next CD-ROM image for ", target_idx, ": ", filename);
         image_config_t &img = g_DiskImages[target_idx];
         img.file.close();
-        bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048, false);
+        bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048, false, false);
 
         if (status)
         {

+ 1 - 1
src/ZuluSCSI_disk.h

@@ -14,5 +14,5 @@ extern "C" {
 }
 
 void scsiDiskResetImages();
-bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int scsi_lun, int blocksize, bool is_cd);
+bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int scsi_lun, int blocksize, bool is_cd, bool is_fd);
 void scsiDiskLoadConfig(int target_idx);

+ 8 - 1
zuluscsi.ini

@@ -35,4 +35,11 @@ Product = "CD-ROM Drive"
 Type = 2
 # If IMG0..IMG9 are specified, they are cycled after each CD eject command.
 #IMG0 = FirstCD.iso
-#IMG1 = SecondCD.iso
+#IMG1 = SecondCD.iso
+
+
+# Raw sector range from SD card can be passed through
+# Format is RAW:first_sector:last_sector where sector numbers can be decimal or hex.
+# If end sector is beyond end of SD card, it will be adjusted automatically.
+# [SCSI4]
+# IMG0 = RAW:0x00000000:0xFFFFFFFF # Whole SD card