| 
					
				 | 
			
			
				@@ -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 
			 |