Browse Source

Simulate CD-ROM eject (#21)

Petteri Aimonen 3 years ago
parent
commit
576f07b738
2 changed files with 70 additions and 7 deletions
  1. 69 7
      src/AzulSCSI_disk.cpp
  2. 1 0
      src/AzulSCSI_log_trace.cpp

+ 69 - 7
src/AzulSCSI_disk.cpp

@@ -27,6 +27,10 @@ SdDevice sdDev = {2, 256 * 1024 * 1024 * 2}; /* For SCSI2SD */
 struct image_config_t: public S2S_TargetCfg
 {
     FsFile file;
+
+    // For CD-ROM drive ejection
+    bool ejected;
+    uint8_t cdrom_events;
 };
 
 static image_config_t g_DiskImages[S2S_MAX_TARGETS];
@@ -370,17 +374,21 @@ static void doReadCapacity()
 static int doTestUnitReady()
 {
     int ready = 1;
-    if (likely(blockDev.state == (DISK_PRESENT | DISK_INITIALISED) &&
-		scsiDev.target->started))
+    image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
+    if (unlikely(!scsiDev.target->started || !img.file.isOpen()))
     {
-        // nothing to do.
+        ready = 0;
+        scsiDev.status = CHECK_CONDITION;
+        scsiDev.target->sense.code = NOT_READY;
+        scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
+        scsiDev.phase = STATUS;
     }
-    else if (unlikely(!scsiDev.target->started))
+    else if (img.ejected)
     {
         ready = 0;
         scsiDev.status = CHECK_CONDITION;
         scsiDev.target->sense.code = NOT_READY;
-        scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED;
+        scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
         scsiDev.phase = STATUS;
     }
     else if (unlikely(!(blockDev.state & DISK_PRESENT)))
@@ -402,6 +410,43 @@ static int doTestUnitReady()
     return ready;
 }
 
+static void doGetEventStatusNotification(bool immed)
+{
+    image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
+
+    if (!immed)
+    {
+        // Asynchronous notification not supported
+        scsiDev.status = CHECK_CONDITION;
+        scsiDev.target->sense.code = ILLEGAL_REQUEST;
+        scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+        scsiDev.phase = STATUS;
+    }
+    else if (img.cdrom_events)
+    {
+        scsiDev.data[0] = 0;
+        scsiDev.data[1] = 6; // EventDataLength
+        scsiDev.data[2] = 0x04; // Media status events
+        scsiDev.data[3] = 0x04; // Supported events
+        scsiDev.data[4] = img.cdrom_events;
+        scsiDev.data[5] = 0x01; // Power status
+        scsiDev.data[6] = 0; // Start slot
+        scsiDev.data[7] = 0; // End slot
+        scsiDev.dataLen = 8;
+        scsiDev.phase = DATA_IN;
+        img.cdrom_events = 0;
+    }
+    else
+    {
+        scsiDev.data[0] = 0;
+        scsiDev.data[1] = 2; // EventDataLength
+        scsiDev.data[2] = 0x00; // Media status events
+        scsiDev.data[3] = 0x04; // Supported events
+        scsiDev.dataLen = 4;
+        scsiDev.phase = DATA_IN;
+    }
+}
+
 /****************/
 /* Seek command */
 /****************/
@@ -794,6 +839,7 @@ extern "C"
 int scsiDiskCommand()
 {
     int commandHandled = 1;
+    image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
 
     uint8_t command = scsiDev.cdb[0];
     if (unlikely(command == 0x1B))
@@ -804,9 +850,20 @@ int scsiDiskCommand()
         int start = scsiDev.cdb[4] & 1;
 	    int loadEject = scsiDev.cdb[4] & 2;
 	
-        if (loadEject)
+        if (loadEject && img.deviceType == S2S_CFG_OPTICAL)
         {
-            // Ignore load/eject requests. We can't do that.
+            if (start)
+            {
+                azdbg("------ CDROM close tray");
+                img.ejected = false;
+                img.cdrom_events = 2; // New media
+            }
+            else
+            {
+                azdbg("------ CDROM open tray");
+                img.ejected = true;
+                img.cdrom_events = 3; // Media removal
+            }
         }
         else if (start)
         {
@@ -822,6 +879,11 @@ int scsiDiskCommand()
         // TEST UNIT READY
         doTestUnitReady();
     }
+    else if (command == 0x4A)
+    {
+        bool immed = scsiDev.cdb[1] & 1;
+        doGetEventStatusNotification(immed);
+    }
     else if (unlikely(!doTestUnitReady()))
     {
         // Status and sense codes already set by doTestUnitReady

+ 1 - 0
src/AzulSCSI_log_trace.cpp

@@ -42,6 +42,7 @@ static const char *getCommandName(uint8_t cmd)
         case 0x3C: return "ReadBuffer";
         case 0xC0: return "OMTI-5204 DefineFlexibleDiskFormat";
         case 0xC2: return "OMTI-5204 AssignDiskParameters";
+        case 0x4A: return "GetEventStatusNotification";
         default:   return "Unknown";
     }
 }