cscope:
rm -f ./cscope.*
diff --git a/block-raw-posix.c b/block-raw-posix.c
-index 9a02d4f..775a1d1 100644
+index 9a02d4f..6898d6e 100644
--- a/block-raw-posix.c
+++ b/block-raw-posix.c
@@ -97,20 +97,7 @@
static int posix_aio_init(void);
+@@ -979,6 +966,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
+
+ s->type = FTYPE_FILE;
+ #if defined(__linux__)
++ printf("**** hdev_open(%s)\n", filename);
+ if (strstart(filename, "/dev/cd", NULL)) {
+ /* open will not fail even if no CD is inserted */
+ open_flags |= O_NONBLOCK;
diff --git a/block.c b/block.c
index 36f5eb9..ae71513 100644
--- a/block.c
+#endif /* !BLOCK_RAW_POSIX_H */
diff --git a/hw/atapi-pt.c b/hw/atapi-pt.c
new file mode 100644
-index 0000000..2f63492
+index 0000000..413cc47
--- /dev/null
+++ b/hw/atapi-pt.c
-@@ -0,0 +1,970 @@
+@@ -0,0 +1,1427 @@
++#include <sys/stat.h>
++
+#define DEBUG_IDE_ATAPI_PT
+
+#define MSF_TO_FRAMES(M, S, F) (((M) * CD_SECS + (S)) * CD_FRAMES + (F))
+# define CHECK_SAME_VALUE(Val1, Val2)
+#endif /* DEBUG_IDE_ATAPI_PT */
+
++
++#define IDE_ATAPI_PT_NEW_CD_FILE "/var/lock/xen-cd-new"
++#define IDE_ATAPI_PT_EJECT_CD_FILE "/var/lock/xen-cd-eject"
++
++
+/* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+static const struct {
+ "(reserved)",
+};
+
-+/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
++
++
++/* From Table 459 of the SFF8090 Ver. 4 (Mt. Fuji) draft standard.
++ * Code is (key << 16) | (asc << 8) | ascq
++ * Mask is a bit mask, since some codes span ranges of values.
++ */
+static const struct {
-+ unsigned long asc_ascq;
++ unsigned long code;
++ unsigned long mask;
+ const char * const text;
+} sense_data_texts[] = {
-+ { 0x000000, "No additional sense information" },
-+ { 0x000011, "Play operation in progress" },
-+ { 0x000012, "Play operation paused" },
-+ { 0x000013, "Play operation successfully completed" },
-+ { 0x000014, "Play operation stopped due to error" },
-+ { 0x000015, "No current audio status to return" },
-+ { 0x010c0a, "Write error - padding blocks added" },
-+ { 0x011700, "Recovered data with no error correction applied" },
-+ { 0x011701, "Recovered data with retries" },
-+ { 0x011702, "Recovered data with positive head offset" },
-+ { 0x011703, "Recovered data with negative head offset" },
-+ { 0x011704, "Recovered data with retries and/or CIRC applied" },
-+ { 0x011705, "Recovered data using previous sector ID" },
-+ { 0x011800, "Recovered data with error correction applied" },
-+ { 0x011801, "Recovered data with error correction and retries applied"},
-+ { 0x011802, "Recovered data - the data was auto-reallocated" },
-+ { 0x011803, "Recovered data with CIRC" },
-+ { 0x011804, "Recovered data with L-EC" },
-+ { 0x015d00, "Failure prediction threshold exceeded"
-+ " - Predicted logical unit failure" },
-+ { 0x015d01, "Failure prediction threshold exceeded"
-+ " - Predicted media failure" },
-+ { 0x015dff, "Failure prediction threshold exceeded - False" },
-+ { 0x017301, "Power calibration area almost full" },
-+ { 0x020400, "Logical unit not ready - cause not reportable" },
-+ /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
-+ { 0x020401, "Logical unit not ready"
-+ " - in progress [sic] of becoming ready" },
-+ { 0x020402, "Logical unit not ready - initializing command required" },
-+ { 0x020403, "Logical unit not ready - manual intervention required" },
-+ { 0x020404, "Logical unit not ready - format in progress" },
-+ { 0x020407, "Logical unit not ready - operation in progress" },
-+ { 0x020408, "Logical unit not ready - long write in progress" },
-+ { 0x020600, "No reference position found (media may be upside down)" },
-+ { 0x023000, "Incompatible medium installed" },
-+ { 0x023a00, "Medium not present" },
-+ { 0x025300, "Media load or eject failed" },
-+ { 0x025700, "Unable to recover table of contents" },
-+ { 0x030300, "Peripheral device write fault" },
-+ { 0x030301, "No write current" },
-+ { 0x030302, "Excessive write errors" },
-+ { 0x030c00, "Write error" },
-+ { 0x030c01, "Write error - Recovered with auto reallocation" },
-+ { 0x030c02, "Write error - auto reallocation failed" },
-+ { 0x030c03, "Write error - recommend reassignment" },
-+ { 0x030c04, "Compression check miscompare error" },
-+ { 0x030c05, "Data expansion occurred during compress" },
-+ { 0x030c06, "Block not compressible" },
-+ { 0x030c07, "Write error - recovery needed" },
-+ { 0x030c08, "Write error - recovery failed" },
-+ { 0x030c09, "Write error - loss of streaming" },
-+ { 0x031100, "Unrecovered read error" },
-+ { 0x031106, "CIRC unrecovered error" },
-+ { 0x033101, "Format command failed" },
-+ { 0x033200, "No defect spare location available" },
-+ { 0x033201, "Defect list update failure" },
-+ { 0x035100, "Erase failure" },
-+ { 0x037200, "Session fixation error" },
-+ { 0x037201, "Session fixation error writin lead-in" },
-+ { 0x037202, "Session fixation error writin lead-out" },
-+ { 0x037300, "CD control error" },
-+ { 0x037302, "Power calibration area is full" },
-+ { 0x037303, "Power calibration area error" },
-+ { 0x037304, "Program memory area / RMA update failure" },
-+ { 0x037305, "Program memory area / RMA is full" },
-+ { 0x037306, "Program memory area / RMA is (almost) full" },
-+ { 0x040200, "No seek complete" },
-+ { 0x040300, "Write fault" },
-+ { 0x040900, "Track following error" },
-+ { 0x040901, "Tracking servo failure" },
-+ { 0x040902, "Focus servo failure" },
-+ { 0x040903, "Spindle servo failure" },
-+ { 0x041500, "Random positioning error" },
-+ { 0x041501, "Mechanical positioning or changer error" },
-+ { 0x041502, "Positioning error detected by read of medium" },
-+ { 0x043c00, "Mechanical positioning or changer error" },
-+ { 0x044000, "Diagnostic failure on component (ASCQ)" },
-+ { 0x044400, "Internal CD/DVD logical unit failure" },
-+ { 0x04b600, "Media load mechanism failed" },
-+ { 0x051a00, "Parameter list length error" },
-+ { 0x052000, "Invalid command operation code" },
-+ { 0x052100, "Logical block address out of range" },
-+ { 0x052102, "Invalid address for write" },
-+ { 0x052400, "Invalid field in command packet" },
-+ { 0x052600, "Invalid field in parameter list" },
-+ { 0x052601, "Parameter not supported" },
-+ { 0x052602, "Parameter value invalid" },
-+ { 0x052700, "Write protected media" },
-+ { 0x052c00, "Command sequence error" },
-+ { 0x052c03, "Current program area is not empty" },
-+ { 0x052c04, "Current program area is empty" },
-+ { 0x053001, "Cannot read medium - unknown format" },
-+ { 0x053002, "Cannot read medium - incompatible format" },
-+ { 0x053900, "Saving parameters not supported" },
-+ { 0x054e00, "Overlapped commands attempted" },
-+ { 0x055302, "Medium removal prevented" },
-+ { 0x055500, "System resource failure" },
-+ { 0x056300, "End of user area encountered on this track" },
-+ { 0x056400, "Illegal mode for this track or incompatible medium" },
-+ { 0x056f00, "Copy protection key exchange failure"
-+ " - Authentication failure" },
-+ { 0x056f01, "Copy protection key exchange failure - Key not present" },
-+ { 0x056f02, "Copy protection key exchange failure"
-+ " - Key not established" },
-+ { 0x056f03, "Read of scrambled sector without authentication" },
-+ { 0x056f04, "Media region code is mismatched to logical unit" },
-+ { 0x056f05, "Drive region must be permanent"
-+ " / region reset count error" },
-+ { 0x057203, "Session fixation error - incomplete track in session" },
-+ { 0x057204, "Empty or partially written reserved track" },
-+ { 0x057205, "No more RZONE reservations are allowed" },
-+ { 0x05bf00, "Loss of streaming" },
-+ { 0x062800, "Not ready to ready transition, medium may have changed" },
-+ { 0x062900, "Power on, reset or hardware reset occurred" },
-+ { 0x062a00, "Parameters changed" },
-+ { 0x062a01, "Mode parameters changed" },
-+ { 0x062e00, "Insufficient time for operation" },
-+ { 0x063f00, "Logical unit operating conditions have changed" },
-+ { 0x063f01, "Microcode has been changed" },
-+ { 0x065a00, "Operator request or state change input (unspecified)" },
-+ { 0x065a01, "Operator medium removal request" },
-+ { 0x0bb900, "Play operation aborted" },
-+ /* Here we use 0xff for the key (not a valid key) to signify
-+ * that these can have _any_ key value associated with them... */
-+ { 0xff0401, "Logical unit is in process of becoming ready" },
-+ { 0xff0400, "Logical unit not ready, cause not reportable" },
-+ { 0xff0402, "Logical unit not ready, initializing command required" },
-+ { 0xff0403, "Logical unit not ready, manual intervention required" },
-+ { 0xff0500, "Logical unit does not respond to selection" },
-+ { 0xff0800, "Logical unit communication failure" },
-+ { 0xff0802, "Logical unit communication parity error" },
-+ { 0xff0801, "Logical unit communication time-out" },
-+ { 0xff2500, "Logical unit not supported" },
-+ { 0xff4c00, "Logical unit failed self-configuration" },
-+ { 0xff3e00, "Logical unit has not self-configured yet" },
++ { 0x080000, 0xFF0000, "BLANK CHECK"},
++ { 0x000000, 0xFFFFFF, "NO ADDITIONAL SENSE INFORMATION"},
++ { 0x000001, 0xFFFFFF, "FILEMARK DETECTED"},
++ { 0x000002, 0xFFFFFF, "END-OF-PARTITION/MEDIUM DETECTED"},
++ { 0x000003, 0xFFFFFF, "SETMARK DETECTED"},
++ { 0x000004, 0xFFFFFF, "BEGINNING-OF-PARTITION/MEDIUM DETECTED"},
++ { 0x000005, 0xFFFFFF, "END-OF-DATA DETECTED"},
++ { 0x0B0006, 0xFFFFFF, "I/O PROCESS TERMINATED, PLAY OPERATION ABORTED"},
++ { 0x000011, 0xFFFFFF, "AUDIO PLAY OPERATION IN PROGRESS"},
++ { 0x000012, 0xFFFFFF, "AUDIO PLAY OPERATION PAUSED"},
++ { 0x000013, 0xFFFFFF, "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED"},
++ { 0x000014, 0xFFFFFF, "AUDIO PLAY OPERATION STOPPED DUE TO ERROR"},
++ { 0x000015, 0xFFFFFF, "NO CURRENT AUDIO STATUS TO RETURN"},
++ { 0x000016, 0xFFFFFF, "OPERATION IN PROGRESS"},
++ { 0x040017, 0xFFFFFF, "CLEANING REQUESTED"},
++ { 0x040100, 0xFFFFFF, "NO INDEX/SECTOR SIGNAL"},
++ { 0x030200, 0xFFFFFF, "NO SEEK COMPLETE"},
++ { 0x030300, 0xFFFFFF, "PERIPHERAL DEVICE WRITE FAULT"},
++ { 0x030301, 0xFFFFFF, "NO WRITE CURRENT"},
++ { 0x030302, 0xFFFFFF, "EXCESSIVE WRITE ERRORS"},
++ { 0x020400, 0xFFFFFF, "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE"},
++ { 0x020401, 0xFFFFFF, "LOGICAL UNIT IS IN PROCESS OF BECOMING READY"},
++ { 0x020402, 0xFFFFFF, "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"},
++ { 0x020403, 0xFFFFFF, "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED"},
++ { 0x020404, 0xFFFFFF, "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS"},
++ { 0x020405, 0xFFFFFF, "LOGICAL UNIT NOT READY, REBUILD IN PROGRESS"},
++ { 0x020406, 0xFFFFFF, "LOGICAL UNIT NOT READY, RECALCULATION IN PROGRESS"},
++ { 0x020407, 0xFFFFFF, "LOGICAL UNIT NOT READY, OPERATION IN PROGRESS"},
++ { 0x020408, 0xFFFFFF, "LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS"},
++ { 0x020500, 0xFFFFFF, "LOGICAL UNIT DOES NOT RESPOND TO SELECTION"},
++ { 0x020600, 0xFFFFFF, "NO REFERENCE POSITION FOUND (medium may be upside down)"},
++ { 0x050700, 0xFFFFFF, "MULTIPLE PERIPHERAL DEVICES SELECTED"},
++ { 0x040800, 0xFFFFFF, "LOGICAL UNIT COMMUNICATION FAILURE"},
++ { 0x040801, 0xFFFFFF, "LOGICAL UNIT COMMUNICATION TIME-OUT"},
++ { 0x040802, 0xFFFFFF, "LOGICAL UNIT COMMUNICATION PARITY ERROR"},
++ { 0x040803, 0xFFFFFF, "LOGICAL UNIT COMMUNICATION CRC ERROR (ULTRA-DMA/32)"},
++ { 0x040900, 0xFFFFFF, "TRACK FOLLOWING ERROR"},
++ { 0x040901, 0xFFFFFF, "TRACKING SERVO FAILURE"},
++ { 0x040902, 0xFFFFFF, "FOCUS SERVO FAILURE"},
++ { 0x040903, 0xFFFFFF, "SPINDLE SERVO FAILURE"},
++ { 0x040904, 0xFFFFFF, "HEAD SELECT FAULT"},
++ { 0x060A00, 0xFFFFFF, "ERROR LOG OVERFLOW"},
++ { 0x010B00, 0xFFFFFF, "WARNING"},
++ { 0x010B01, 0xFFFFFF, "WARNING - SPECIFIED TEMPERATURE EXCEEDED"},
++ { 0x010B02, 0xFFFFFF, "WARNING - ENCLOSURE DEGRADED"},
++ { 0x030C00, 0xFFFFFF, "WRITE ERROR"},
++ { 0x030C01, 0xFFFFFF, "WRITE ERROR - RECOVERED WITH AUTO REALLOCATION"},
++ { 0x030C02, 0xFFFFFF, "WRITE ERROR - AUTO REALLOCATION FAILED"},
++ { 0x030C03, 0xFFFFFF, "WRITE ERROR - RECOMMEND REASSIGNMENT"},
++ { 0x030C04, 0xFFFFFF, "COMPRESSION CHECK MISCOMPARE ERROR"},
++ { 0x030C05, 0xFFFFFF, "DATA EXPANSION OCCURRED DURING COMPRESSION"},
++ { 0x030C06, 0xFFFFFF, "BLOCK NOT COMPRESSIBLE"},
++ { 0x030C07, 0xFFFFFF, "WRITE ERROR - RECOVERY NEEDED"},
++ { 0x030C08, 0xFFFFFF, "WRITE ERROR - RECOVERY FAILED"},
++ { 0x030C09, 0xFFFFFF, "WRITE ERROR - LOSS OF STREAMING"},
++ { 0x010C0A, 0xFFFFFF, "WRITE ERROR - PADDING BLOCKS ADDED"},
++ { 0x000D00, 0x00FFFF, "Reserved"},
++ { 0x000E00, 0x00FFFF, "Reserved"},
++ { 0x000F00, 0x00FFFF, "Reserved"},
++ { 0x031000, 0xFFFFFF, "ID CRC OR ECC ERROR"},
++ { 0x031100, 0xFFFFFF, "UNRECOVERED READ ERROR"},
++ { 0x031101, 0xFFFFFF, "READ RETRIES EXHAUSTED"},
++ { 0x031102, 0xFFFFFF, "ERROR TOO LONG TO CORRECT"},
++ { 0x031103, 0xFFFFFF, "MULTIPLE READ ERRORS"},
++ { 0x031104, 0xFFFFFF, "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED"},
++ { 0x031105, 0xFFFFFF, "L-EC UNCORRECTABLE ERROR"},
++ { 0x031106, 0xFFFFFF, "CIRC UNRECOVERED ERROR"},
++ { 0x031107, 0xFFFFFF, "RE-SYNCHRONIZATION ERROR"},
++ { 0x031108, 0xFFFFFF, "INCOMPLETE BLOCK READ"},
++ { 0x031109, 0xFFFFFF, "NO GAP FOUND"},
++ { 0x03110A, 0xFFFFFF, "MISCORRECTED ERROR"},
++ { 0x03110B, 0xFFFFFF, "UNRECOVERED READ ERROR - RECOMMEND REASSIGNMENT"},
++ { 0x03110C, 0xFFFFFF, "UNRECOVERED READ ERROR - RECOMMEND REWRITE THE DATA"},
++ { 0x03110D, 0xFFFFFF, "DE-COMPRESSION CRC ERROR"},
++ { 0x03110E, 0xFFFFFF, "CANNOT DECOMPRESS USING DECLARED ALGORITHM"},
++ { 0x03110F, 0xFFFFFF, "ERROR READING UPC/EAN NUMBER"},
++ { 0x031110, 0xFFFFFF, "ERROR READING ISRC NUMBER"},
++ { 0x0B1111, 0xFFFFFF, "READ ERROR - LOSS OF STREAMING"},
++ { 0x031200, 0xFFFFFF, "ADDRESS MARK NOT FOUND FOR ID FIELD"},
++ { 0x031300, 0xFFFFFF, "ADDRESS MARK NOT FOUND FOR DATA FIELD"},
++ { 0x031400, 0xFFFFFF, "RECORDED ENTITY NOT FOUND"},
++ { 0x031401, 0xFFFFFF, "RECORD NOT FOUND"},
++ { 0x031402, 0xFFFFFF, "FILEMARK OR SETMARK NOT FOUND"},
++ { 0x031403, 0xFFFFFF, "END-OF-DATA NOT FOUND"},
++ { 0x031404, 0xFFFFFF, "BLOCK SEQUENCE ERROR"},
++ { 0x031405, 0xFFFFFF, "RECORD NOT FOUND - RECOMMEND REASSIGNMENT"},
++ { 0x031406, 0xFFFFFF, "RECORD NOT FOUND - DATA AUTO-REALLOCATED"},
++ { 0x041500, 0xFFFFFF, "RANDOM POSITIONING ERROR"},
++ { 0x041501, 0xFFFFFF, "MECHANICAL POSITIONING ERROR"},
++ { 0x031502, 0xFFFFFF, "POSITIONING ERROR DETECTED BY READ OF MEDIUM"},
++ { 0x031600, 0xFFFFFF, "DATA SYNCHRONIZATION MARK ERROR"},
++ { 0x031601, 0xFFFFFF, "DATA SYNC ERROR - DATA REWRITTEN"},
++ { 0x031602, 0xFFFFFF, "DATA SYNC ERROR - RECOMMEND REWRITE"},
++ { 0x031603, 0xFFFFFF, "DATA SYNC ERROR - DATA AUTO-REALLOCATED"},
++ { 0x031604, 0xFFFFFF, "DATA SYNC ERROR - RECOMMEND REASSIGNMENT"},
++ { 0x011700, 0xFFFFFF, "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED"},
++ { 0x011701, 0xFFFFFF, "RECOVERED DATA WITH RETRIES"},
++ { 0x011702, 0xFFFFFF, "RECOVERED DATA WITH POSITIVE HEAD OFFSET"},
++ { 0x011703, 0xFFFFFF, "RECOVERED DATA WITH NEGATIVE HEAD OFFSET"},
++ { 0x011704, 0xFFFFFF, "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED"},
++ { 0x011705, 0xFFFFFF, "RECOVERED DATA USING PREVIOUS SECTOR ID"},
++ { 0x011706, 0xFFFFFF, "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED"},
++ { 0x011707, 0xFFFFFF, "RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT"},
++ { 0x011708, 0xFFFFFF, "RECOVERED DATA WITHOUT ECC - RECOMMEND REWRITE"},
++ { 0x011709, 0xFFFFFF, "RECOVERED DATA WITHOUT ECC - DATA REWRITTEN"},
++ { 0x011800, 0xFFFFFF, "RECOVERED DATA WITH ERROR CORRECTION APPLIED"},
++ { 0x011801, 0xFFFFFF, "RECOVERED DATA WITH ERROR CORR. & RETRIES APPLIED"},
++ { 0x011802, 0xFFFFFF, "RECOVERED DATA - DATA AUTO-REALLOCATED"},
++ { 0x011803, 0xFFFFFF, "RECOVERED DATA WITH CIRC"},
++ { 0x011804, 0xFFFFFF, "RECOVERED DATA WITH L-EC"},
++ { 0x011805, 0xFFFFFF, "RECOVERED DATA - RECOMMEND REASSIGNMENT"},
++ { 0x011806, 0xFFFFFF, "RECOVERED DATA - RECOMMEND REWRITE"},
++ { 0x011807, 0xFFFFFF, "RECOVERED DATA WITH ECC - DATA REWRITTEN"},
++ { 0x011808, 0xFFFFFF, "RECOVERED DATA WITH LINKING"},
++ { 0x031900, 0xFFFFFF, "DEFECT LIST ERROR"},
++ { 0x031901, 0xFFFFFF, "DEFECT LIST NOT AVAILABLE"},
++ { 0x031902, 0xFFFFFF, "DEFECT LIST ERROR IN PRIMARY LIST"},
++ { 0x031903, 0xFFFFFF, "DEFECT LIST ERROR IN GROWN LIST"},
++ { 0x051A00, 0xFFFFFF, "PARAMETER LIST LENGTH ERROR"},
++ { 0x041B00, 0xFFFFFF, "SYNCHRONOUS DATA TRANSFER ERROR"},
++ { 0x041C00, 0xFFFFFF, "DEFECT LIST NOT FOUND"},
++ { 0x041C01, 0xFFFFFF, "PRIMARY DEFECT LIST NOT FOUND"},
++ { 0x041C02, 0xFFFFFF, "GROWN DEFECT LIST NOT FOUND"},
++ { 0x0E1D00, 0xFFFFFF, "MISCOMPARE DURING VERIFY OPERATION"},
++ { 0x011E00, 0xFFFFFF, "RECOVERED ID WITH ECC CORRECTION"},
++ { 0x031F00, 0xFFFFFF, "PARTIAL DEFECT LIST TRANSFER"},
++ { 0x052000, 0xFFFFFF, "INVALID COMMAND OPERATION CODE"},
++ { 0x052100, 0xFFFFFF, "LOGICAL BLOCK ADDRESS OUT OF RANGE"},
++ { 0x052101, 0xFFFFFF, "INVALID ELEMENT ADDRESS"},
++ { 0x052102, 0xFFFFFF, "INVALID ADDRESS FOR WRITE"},
++ { 0x052200, 0xFFFFFF, "ILLEGAL FUNCTION (USE 20 00, 24 00, OR 26 00)"},
++ { 0x002300, 0x00FFFF, "Reserved"},
++ { 0x052400, 0xFFFFFF, "INVALID FIELD IN CDB"},
++ { 0x052500, 0xFFFFFF, "LOGICAL UNIT NOT SUPPORTED"},
++ { 0x052600, 0xFFFFFF, "INVALID FIELD IN PARAMETER LIST"},
++ { 0x052601, 0xFFFFFF, "PARAMETER NOT SUPPORTED"},
++ { 0x052602, 0xFFFFFF, "PARAMETER VALUE INVALID"},
++ { 0x052603, 0xFFFFFF, "THRESHOLD PARAMETERS NOT SUPPORTED"},
++ { 0x052604, 0xFFFFFF, "INVALID RELEASE OF ACTIVE PERSISTENT RESERVATION"},
++ { 0x072700, 0xFFFFFF, "WRITE PROTECTED"},
++ { 0x072701, 0xFFFFFF, "HARDWARE WRITE PROTECTED"},
++ { 0x072702, 0xFFFFFF, "LOGICAL UNIT SOFTWARE WRITE PROTECTED"},
++ { 0x072703, 0xFFFFFF, "ASSOCIATED WRITE PROTECT"},
++ { 0x072704, 0xFFFFFF, "PERSISTENT WRITE PROTECT"},
++ { 0x072705, 0xFFFFFF, "PERMANENT WRITE PROTECT"},
++ { 0x072706, 0xFFFFFF, "CONDITIONAL WRITE PROTECT"},
++ { 0x062800, 0xFFFFFF, "NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED"},
++ { 0x062801, 0xFFFFFF, "IMPORT OR EXPORT ELEMENT ACCESSED"},
++ { 0x062900, 0xFFFFFF, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"},
++ { 0x062901, 0xFFFFFF, "POWER ON OCCURRED"},
++ { 0x062902, 0xFFFFFF, "SCSI BUS RESET OCCURRED"},
++ { 0x062903, 0xFFFFFF, "BUS DEVICE RESET FUNCTION OCCURRED"},
++ { 0x062904, 0xFFFFFF, "DEVICE INTERNAL RESET"},
++ { 0x062A00, 0xFFFFFF, "PARAMETERS CHANGED"},
++ { 0x062A01, 0xFFFFFF, "MODE PARAMETERS CHANGED"},
++ { 0x062A02, 0xFFFFFF, "LOG PARAMETERS CHANGED"},
++ { 0x062A03, 0xFFFFFF, "RESERVATIONS PREEMPTED"},
++ { 0x052B00, 0xFFFFFF, "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT"},
++ { 0x052C00, 0xFFFFFF, "COMMAND SEQUENCE ERROR"},
++ { 0x052C01, 0xFFFFFF, "TOO MANY WINDOWS SPECIFIED"},
++ { 0x052C02, 0xFFFFFF, "INVALID COMBINATION OF WINDOWS SPECIFIED"},
++ { 0x052C03, 0xFFFFFF, "CURRENT PROGRAM AREA IS NOT EMPTY"},
++ { 0x052C04, 0xFFFFFF, "CURRENT PROGRAM AREA IS EMPTY"},
++ { 0x052C05, 0xFFFFFF, "PERSISTENT PREVENT CONFLICT"},
++ { 0x032D00, 0xFFFFFF, "OVERWRITE ERROR ON UPDATE IN PLACE"},
++ { 0x062E00, 0xFFFFFF, "INSUFFICIENT TIME FOR OPERATION"},
++ { 0x062F00, 0xFFFFFF, "COMMANDS CLEARED BY ANOTHER INITIATOR"},
++ { 0x023000, 0xFFFFFF, "INCOMPATIBLE MEDIUM INSTALLED"},
++ { 0x023001, 0xFFFFFF, "CANNOT READ MEDIUM - UNKNOWN FORMAT"},
++ { 0x023002, 0xFFFFFF, "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"},
++ { 0x053002, 0xFFFFFF, "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"},
++ { 0x023003, 0xFFFFFF, "CLEANING CARTRIDGE INSTALLED"},
++ { 0x053004, 0xFFFFFF, "CANNOT WRITE MEDIUM - UNKNOWN FORMAT"},
++ { 0x053005, 0xFFFFFF, "CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT"},
++ { 0x053006, 0xFFFFFF, "CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM"},
++ { 0x023007, 0xFFFFFF, "CLEANING FAILURE"},
++ { 0x053008, 0xFFFFFF, "CANNOT WRITE - APPLICATION CODE MISMATCH"},
++ { 0x053009, 0xFFFFFF, "CURRENT SESSION NOT FIXATED FOR APPEND"},
++ { 0x033100, 0xFFFFFF, "MEDIUM FORMAT CORRUPTED"},
++ { 0x033101, 0xFFFFFF, "FORMAT COMMAND FAILED"},
++ { 0x033102, 0xFFFFFF, "ZONED FORMATTING FAILED DUE TO SPARE LINKING"},
++ { 0x033200, 0xFFFFFF, "NO DEFECT SPARE LOCATION AVAILABLE"},
++ { 0x033201, 0xFFFFFF, "DEFECT LIST UPDATE FAILURE"},
++ { 0x033300, 0xFFFFFF, "TAPE LENGTH ERROR"},
++ { 0x043400, 0xFFFFFF, "ENCLOSURE FAILURE"},
++ { 0x043500, 0xFFFFFF, "ENCLOSURE SERVICES FAILURE"},
++ { 0x053501, 0xFFFFFF, "UNSUPPORTED ENCLOSURE FUNCTION"},
++ { 0x023502, 0xFFFFFF, "ENCLOSURE SERVICES UNAVAILABLE"},
++ { 0x043503, 0xFFFFFF, "ENCLOSURE SERVICES TRANSFER FAILURE"},
++ { 0x053504, 0xFFFFFF, "ENCLOSURE SERVICES TRANSFER REFUSED"},
++ { 0x033600, 0xFFFFFF, "RIBBON, INK, OR TONER FAILURE"},
++ { 0x013700, 0xFFFFFF, "ROUNDED PARAMETER"},
++ { 0x053800, 0xFFFFFF, "Reserved"},
++ { 0x053900, 0xFFFFFF, "SAVING PARAMETERS NOT SUPPORTED"},
++ { 0x023A00, 0xFFFFFF, "MEDIUM NOT PRESENT"},
++ { 0x023A01, 0xFFFFFF, "MEDIUM NOT PRESENT - TRAY CLOSED"},
++ { 0x023A02, 0xFFFFFF, "MEDIUM NOT PRESENT - TRAY OPEN"},
++ { 0x033B00, 0xFFFFFF, "SEQUENTIAL POSITIONING ERROR"},
++ { 0x033B01, 0xFFFFFF, "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM"},
++ { 0x033B02, 0xFFFFFF, "TAPE POSITION ERROR AT END-OF-MEDIUM"},
++ { 0x033B03, 0xFFFFFF, "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY"},
++ { 0x043B04, 0xFFFFFF, "SLEW FAILURE"},
++ { 0x043B05, 0xFFFFFF, "PAPER JAM"},
++ { 0x033B06, 0xFFFFFF, "FAILED TO SENSE TOP-OF-FORM"},
++ { 0x033B07, 0xFFFFFF, "FAILED TO SENSE BOTTOM-OF-FORM"},
++ { 0x033B08, 0xFFFFFF, "REPOSITION ERROR"},
++ { 0x033B09, 0xFFFFFF, "READ PAST END OF MEDIUM"},
++ { 0x033B0A, 0xFFFFFF, "READ PAST BEGINNING OF MEDIUM"},
++ { 0x033B0B, 0xFFFFFF, "POSITION PAST END OF MEDIUM"},
++ { 0x033B0C, 0xFFFFFF, "POSITION PAST BEGINNING OF MEDIUM"},
++ { 0x053B0D, 0xFFFFFF, "MEDIUM DESTINATION ELEMENT FULL"},
++ { 0x053B0E, 0xFFFFFF, "MEDIUM SOURCE ELEMENT EMPTY"},
++ { 0x063B0F, 0xFFFFFF, "END OF MEDIUM REACHED"},
++ { 0x023B11, 0xFFFFFF, "MEDIUM MAGAZINE NOT ACCESSIBLE"},
++ { 0x063B12, 0xFFFFFF, "MEDIUM MAGAZINE REMOVED"},
++ { 0x063B13, 0xFFFFFF, "MEDIUM MAGAZINE INSERTED"},
++ { 0x063B14, 0xFFFFFF, "MEDIUM MAGAZINE LOCKED"},
++ { 0x063B15, 0xFFFFFF, "MEDIUM MAGAZINE UNLOCKED"},
++ { 0x043B16, 0xFFFFFF, "MECHANICAL POSITIONING OR CHANGER ERROR"},
++ { 0x003C00, 0x00FFFF, "Reserved"},
++ { 0x053D00, 0xFFFFFF, "INVALID BITS IN IDENTIFY MESSAGE"},
++ { 0x023E00, 0xFFFFFF, "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET"},
++ { 0x043E01, 0xFFFFFF, "LOGICAL UNIT FAILURE"},
++ { 0x043E02, 0xFFFFFF, "TIMEOUT ON LOGICAL UNIT"},
++ { 0x063F00, 0xFFFFFF, "TARGET OPERATING CONDITIONS HAVE CHANGED"},
++ { 0x063F01, 0xFFFFFF, "MICROCODE HAS BEEN CHANGED"},
++ { 0x063F02, 0xFFFFFF, "CHANGED OPERATING DEFINITION"},
++ { 0x063F03, 0xFFFFFF, "INQUIRY DATA HAS CHANGED"},
++ { 0x044000, 0xFFFFFF, "RAM FAILURE (SHOULD USE 40 NN)"},
++ { 0x044000, 0xFFFF80, "DIAGNOSTIC FAILURE ON COMPONENT NN (80H-FFH)"},
++ { 0x044100, 0xFFFFFF, "DATA PATH FAILURE (SHOULD USE 40 NN)"},
++ { 0x044200, 0xFFFFFF, "POWER-ON OR SELF-TEST FAILURE (SHOULD USE 40 NN)"},
++ { 0x054300, 0xFFFFFF, "MESSAGE ERROR"},
++ { 0x044400, 0xFFFFFF, "INTERNAL TARGET FAILURE"},
++ { 0x0b4500, 0xFFFFFF, "SELECT OR RESELECT FAILURE"},
++ { 0x044600, 0xFFFFFF, "UNSUCCESSFUL SOFT RESET"},
++ { 0x044700, 0xFFFFFF, "SCSI PARITY ERROR"},
++ { 0x0b4800, 0xFFFFFF, "INITIATOR DETECTED ERROR MESSAGE RECEIVED"},
++ { 0x0b4900, 0xFFFFFF, "INVALID MESSAGE ERROR"},
++ { 0x044A00, 0xFFFFFF, "COMMAND PHASE ERROR"},
++ { 0x044B00, 0xFFFFFF, "DATA PHASE ERROR"},
++ { 0x044C00, 0xFFFFFF, "LOGICAL UNIT FAILED SELF-CONFIGURATION"},
++ { 0x0b4D00, 0xFFFF00, "TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG)"},
++ { 0x0B4E00, 0xFFFFFF, "OVERLAPPED COMMANDS ATTEMPTED"},
++ { 0x004F00, 0x00FFFF, "Reserved"},
++ { 0x005000, 0x00FFFF, "WRITE APPEND ERROR"},
++ { 0x005001, 0x00FFFF, "WRITE APPEND POSITION ERROR"},
++ { 0x005002, 0x00FFFF, "POSITION ERROR RELATED TO TIMING"},
++ { 0x035100, 0xFFFFFF, "ERASE FAILURE"},
++ { 0x035101, 0xFFFFFF, "ERASE FAILURE - Incomplete erase operation detected"},
++ { 0x035200, 0xFFFFFF, "CARTRIDGE FAULT"},
++ { 0x045300, 0xFFFFFF, "MEDIA LOAD OR EJECT FAILED"},
++ { 0x005301, 0x00FFFF, "UNLOAD TAPE FAILURE"},
++ { 0x025302, 0xFFFFFF, "MEDIUM REMOVAL PREVENTED"},
++ { 0x055302, 0xFFFFFF, "MEDIUM REMOVAL PREVENTED"},
++ { 0x005400, 0x00FFFF, "SCSI TO HOST SYSTEM INTERFACE FAILURE"},
++ { 0x055500, 0xFFFFFF, "SYSTEM RESOURCE FAILURE"},
++ { 0x005501, 0x00FFFF, "SYSTEM BUFFER FULL"},
++ { 0x005600, 0x00FFFF, "Reserved"},
++ { 0x035700, 0xFFFFFF, "UNABLE TO RECOVER TABLE-OF-CONTENTS"},
++ { 0x005800, 0x00FFFF, "GENERATION DOES NOT EXIST"},
++ { 0x005900, 0x00FFFF, "UPDATED BLOCK READ"},
++ { 0x065A00, 0xFFFFFF, "OPERATOR REQUEST OR STATE CHANGE INPUT"},
++ { 0x065A01, 0xFFFFFF, "OPERATOR MEDIUM REMOVAL REQUEST"},
++ { 0x065A02, 0xFFFFFF, "OPERATOR SELECTED WRITE PROTECT"},
++ { 0x065A03, 0xFFFFFF, "OPERATOR SELECTED WRITE PERMIT"},
++ { 0x065B00, 0xFFFFFF, "LOG EXCEPTION"},
++ { 0x065B01, 0xFFFFFF, "THRESHOLD CONDITION MET"},
++ { 0x065B02, 0xFFFFFF, "LOG COUNTER AT MAXIMUM"},
++ { 0x065B03, 0xFFFFFF, "LOG LIST CODES EXHAUSTED"},
++ { 0x065C00, 0xFFFFFF, "RPL STATUS CHANGE"},
++ { 0x065C01, 0xFFFFFF, "SPINDLES SYNCHRONIZED"},
++ { 0x035C02, 0xFFFFFF, "SPINDLES NOT SYNCHRONIZED"},
++ { 0x015D00, 0xFFFFFF, "FAILURE PREDICTION THRESHOLD EXCEEDED - Predicted Logical Unit Failure"},
++ { 0x015D01, 0xFFFFFF, "FAILURE PREDICTION THRESHOLD EXCEEDED - Predicted Media Failure"},
++ { 0x015D03, 0xFFFFFF, "FAILURE PREDICTION THRESHOLD EXCEEDED - Predicted Spare Area Exhaustion"},
++ { 0x015DFF, 0xFFFFFF, "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"},
++ { 0x065E00, 0xFFFFFF, "LOW POWER CONDITION ON"},
++ { 0x065E01, 0xFFFFFF, "IDLE CONDITION ACTIVATED BY TIMER"},
++ { 0x065E02, 0xFFFFFF, "STANDBY CONDITION ACTIVATED BY TIMER"},
++ { 0x065E03, 0xFFFFFF, "IDLE CONDITION ACTIVATED BY COMMAND"},
++ { 0x065E04, 0xFFFFFF, "STANDBY CONDITION ACTIVATED BY COMMAND"},
++ { 0x005F00, 0x00FFFF, "Reserved"},
++ { 0x046000, 0xFFFFFF, "LAMP FAILURE"},
++ { 0x036100, 0xFFFFFF, "VIDEO ACQUISITION ERROR"},
++ { 0x036101, 0xFFFFFF, "UNABLE TO ACQUIRE VIDEO"},
++ { 0x036102, 0xFFFFFF, "OUT OF FOCUS"},
++ { 0x046200, 0xFFFFFF, "SCAN HEAD POSITIONING ERROR"},
++ { 0x056300, 0xFFFFFF, "END OF USER AREA ENCOUNTERED ON THIS TRACK"},
++ { 0x056301, 0xFFFFFF, "PACKET DOES NOT FIT IN AVAILABLE SPACE"},
++ { 0x056400, 0xFFFFFF, "ILLEGAL MODE FOR THIS TRACK"},
++ { 0x056401, 0xFFFFFF, "INVALID PACKET SIZE"},
++ { 0x046500, 0xFFFFFF, "VOLTAGE FAULT"},
++ { 0x046600, 0xFFFFFF, "AUTOMATIC DOCUMENT FEEDER COVER UP"},
++ { 0x046601, 0xFFFFFF, "AUTOMATIC DOCUMENT FEEDER LIFT UP"},
++ { 0x046602, 0xFFFFFF, "DOCUMENT JAM IN AUTOMATIC DOCUMENT FEEDER"},
++ { 0x046603, 0xFFFFFF, "DOCUMENT MISS FEED AUTOMATIC IN DOCUMENT FEEDER"},
++ { 0x046700, 0xFFFFFF, "CONFIGURATION FAILURE"},
++ { 0x046701, 0xFFFFFF, "CONFIGURATION OF INCAPABLE LOGICAL UNITS FAILED"},
++ { 0x046702, 0xFFFFFF, "ADD LOGICAL UNIT FAILED"},
++ { 0x046703, 0xFFFFFF, "MODIFICATION OF LOGICAL UNIT FAILED"},
++ { 0x046704, 0xFFFFFF, "EXCHANGE OF LOGICAL UNIT FAILED"},
++ { 0x046705, 0xFFFFFF, "REMOVE OF LOGICAL UNIT FAILED"},
++ { 0x046706, 0xFFFFFF, "ATTACHMENT OF LOGICAL UNIT FAILED"},
++ { 0x046707, 0xFFFFFF, "CREATION OF LOGICAL UNIT FAILED"},
++ { 0x026800, 0xFFFFFF, "LOGICAL UNIT NOT CONFIGURED"},
++ { 0x046900, 0xFFFFFF, "DATA LOSS ON LOGICAL UNIT"},
++ { 0x046901, 0xFFFFFF, "MULTIPLE LOGICAL UNIT FAILURES"},
++ { 0x046902, 0xFFFFFF, "A PARITY/DATA MISMATCH"},
++ { 0x016A00, 0xFFFFFF, "INFORMATIONAL, REFER TO LOG"},
++ { 0x066B00, 0xFFFFFF, "STATE CHANGE HAS OCCURRED"},
++ { 0x066B01, 0xFFFFFF, "REDUNDANCY LEVEL GOT BETTER"},
++ { 0x066B02, 0xFFFFFF, "REDUNDANCY LEVEL GOT WORSE"},
++ { 0x036C00, 0xFFFFFF, "REBUILD FAILURE OCCURRED"},
++ { 0x036D00, 0xFFFFFF, "RECALCULATE FAILURE OCCURRED"},
++ { 0x046E00, 0xFFFFFF, "COMMAND TO LOGICAL UNIT FAILED"},
++ { 0x056F00, 0xFFFFFF, "COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE"},
++ { 0x056F01, 0xFFFFFF, "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT"},
++ { 0x056F02, 0xFFFFFF, "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED"},
++ { 0x056F03, 0xFFFFFF, "READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION"},
++ { 0x056F04, 0xFFFFFF, "MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION"},
++ { 0x056F05, 0xFFFFFF, "DRIVE REGION MUST BE PERMANENT/REGION RESET COUNT ERROR"},
++ { 0x037000, 0xFFFF00, "DECOMPRESSION EXCEPTION SHORT ALGORITHM ID OF NN"},
++ { 0x037100, 0xFFFFFF, "DECOMPRESSION EXCEPTION LONG ALGORITHM ID"},
++ { 0x037200, 0xFFFFFF, "SESSION FIXATION ERROR"},
++ { 0x037201, 0xFFFFFF, "SESSION FIXATION ERROR WRITING LEAD-IN"},
++ { 0x037202, 0xFFFFFF, "SESSION FIXATION ERROR WRITING LEAD-OUT"},
++ { 0x057203, 0xFFFFFF, "SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION"},
++ { 0x057204, 0xFFFFFF, "EMPTY OR PARTIALLY WRITTEN RESERVED TRACK"},
++ { 0x057205, 0xFFFFFF, "NO MORE RZONE RESERVATIONS ARE ALLOWED"},
++ { 0x037300, 0xFFFFFF, "CD CONTROL ERROR"},
++ { 0x017301, 0xFFFFFF, "POWER CALIBRATION AREA ALMOST FULL"},
++ { 0x037302, 0xFFFFFF, "POWER CALIBRATION AREA IS FULL"},
++ { 0x037303, 0xFFFFFF, "POWER CALIBRATION AREA ERROR"},
++ { 0x037304, 0xFFFFFF, "PROGRAM MEMORY AREA/RMA UPDATE FAILURE"},
++ { 0x037305, 0xFFFFFF, "PROGRAM MEMORY AREA/RMA IS FULL"},
++ { 0x017306, 0xFFFFFF, "PROGRAM MEMORY AREA/RMA IS (almost) FULL"},
++ { 0x008000, 0x008000, "VENDOR SPECIFIC"},
++ { 0x000000, 0x000000, "Unrecognised sense data"}
+};
+
-+static const char *atapi_ascq_to_str(int ascq)
++static const char *atapi_sense_to_str(int key, int asc, int ascq)
+{
+ int i;
++ unsigned long code;
++
++ code = ((key & 0xFF) << 16) | ((asc & 0xFF) << 8) | (ascq & 0xFF);
+
-+ for (i = 0; sense_data_texts[i].text; ++i)
-+ if (sense_data_texts[i].asc_ascq == ascq)
++ for (i = 0; 1; ++i)
++ if ((code & sense_data_texts[i].mask) == sense_data_texts[i].code)
+ return sense_data_texts[i].text;
-+ return 0;
+}
+
++
+static void ide_atapi_pt_set_error(IDEState *s, int sense_key, int asc, int error)
+{
+ s->atapi_pt.sense.sense_key = sense_key;
+ ide_set_irq(s);
+}
+
++#if 0
++static int cmd_count = 0;
++static int finish_count = 0;
++static int no_finish_count = 0;
++
+static void ide_atapi_pt_sg_io_finished(IDEState *s)
+{
+ BDRVRawState *raw_state = s->bs->opaque;
+ int read_bytes;
++ int i;
++
++ ++finish_count;
++ DEBUG_PRINTF("**** finish (%p, u=%p, raw=%p, fd=%d, %d-%d(%d))\n",
++ s, s->atapi_pt.cmd.usr_ptr,
++ raw_state, raw_state->fd, cmd_count,
++ finish_count + no_finish_count, no_finish_count);
++
++ DEBUG_PRINTF("Preread: 0x");
++ for(i = 0; i < sizeof(s->atapi_pt.cmd); ++i)
++ DEBUG_PRINTF("%02x", ((unsigned char *)&s->atapi_pt.cmd)[i]);
++ DEBUG_PRINTF("\n");
++
++#if 1
+ read_bytes = read(raw_state->fd, &s->atapi_pt.cmd, sizeof (s->atapi_pt.cmd));
+
++ DEBUG_PRINTF("Postread: 0x");
++ for(i = 0; i < sizeof(s->atapi_pt.cmd); ++i)
++ DEBUG_PRINTF("%02x", ((unsigned char *)&s->atapi_pt.cmd)[i]);
++ DEBUG_PRINTF("\n");
++#else
++ DEBUG_PRINTF("Postread: 0x");
++ for(i = 0; i < sizeof (s->atapi_pt.cmd); ++i) {
++ read(raw_state->fd, &((unsigned char *)&s->atapi_pt.cmd)[i], 1);
++ DEBUG_PRINTF("%02x", ((unsigned char *)&s->atapi_pt.cmd)[i]);
++ }
++ DEBUG_PRINTF("\n");
++ read_bytes = i;
++#endif
++
++ // DEBUG_PRINTF("finish read\n");
++
+ if (read_bytes != sizeof (s->atapi_pt.cmd))
+ {
+ ide_atapi_pt_error(s);
++ s->atapi_pt.cmd_sent = NULL;
+ return;
+ }
+
+ s->atapi_pt.sense.error_code,
+ s->atapi_pt.sense.asc,
+ s->atapi_pt.sense.ascq,
-+ atapi_ascq_to_str(s->atapi_pt.sense.ascq),
++ atapi_sense_to_str(s->atapi_pt.sense.sense_key,
++ s->atapi_pt.sense.asc,
++ s->atapi_pt.sense.ascq),
+ errno,
+ strerror(errno) ? : "(null)",
+ s->atapi_pt.cmd.driver_status,
+ s->atapi_pt.cmd.transport_status,
+ s->atapi_pt.cmd.device_status);
+ ide_atapi_pt_error(s);
++ s->atapi_pt.cmd_sent = NULL;
++ return;
++ }
++ if(s->atapi_pt.cmd_sent == NULL) {
++ static int null_count = 0;
++ ++null_count;
++ DEBUG_PRINTF("\e[1;31m%s called with cmd_sent = NULL %d time%c\e[m\n",
++ __FUNCTION__, null_count, (null_count == 1) ? ' ' : 's');
++ ide_atapi_cmd_ok(s);
++ s->atapi_pt.cmd_sent = NULL;
+ return;
+ }
++ // DEBUG_PRINTF("finish sent\n");
+ s->atapi_pt.cmd_sent(s);
++ s->atapi_pt.cmd_sent = NULL;
++ DEBUG_PRINTF("**** finished (%p)\n", s);
+}
+
+#define ATAPI_PT_SEND_PACKET \
+ i = dma_buf_rw(bm, 0);
+ ide_atapi_pt_read_finish(s);
+}
++#endif
+
++#if 0
+static void ide_atapi_pt_wcmd(IDEState *s)
+{
+ if (s->atapi_dma)
+ ide_set_irq(s);
+ return;
+}
++#endif
+
+static void ide_atapi_pt_read_format_capacities_sent(IDEState *s)
+{
+ assert(0);
+ break;
+ }
-+ printf("[reply] size: %d, din_resid: %d, max_in:%d, response_len: %d\n",
-+ size, s->atapi_pt.cmd.din_resid, s->atapi_pt.cmd.din_xfer_len,
-+ s->atapi_pt.cmd.response_len);
+ ide_atapi_cmd_reply(s, size, s->atapi_pt.cmd.din_xfer_len);
+}
+
+ return block_size;
+}
+
++
+static void ide_atapi_pt_cmd(IDEState *s)
+{
+ struct sg_io_v4 *cmd = &s->atapi_pt.cmd;
++ int r;
++ int command;
++ BDRVRawState *raw_state = s->bs->opaque;
+
+ memset(cmd, 0, sizeof (*cmd));
+ memcpy(s->atapi_pt.request, s->io_buffer, ATAPI_PACKET_SIZE);
+ s->atapi_pt.reply_size_offset = 0;
+ s->atapi_pt.reply_size_len = 0;
+
++ cmd->din_xferp = (__u64)s->io_buffer;
++ cmd->dout_xferp = (__u64)(s->io_buffer + ATAPI_PACKET_SIZE);
++ s->atapi_pt.cmd_sent = ide_atapi_cmd_ok;
++ command = s->io_buffer[0];
++
+ switch (s->io_buffer[0])
+ {
+ /*******************/
+ simple_cmd:
+ CHECK_SAME_VALUE(s->lcyl, 0);
+ CHECK_SAME_VALUE(s->hcyl, 0);
-+ s->atapi_pt.cmd_sent = ide_atapi_cmd_ok;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ break;
+
+ /******************/
+ /* WRITE COMMANDS */
+ case GPCMD_WRITE_10:
+ case GPCMD_WRITE_AND_VERIFY_10:
+ cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7) * CD_FRAMESIZE;
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
+ if (cmd->dout_xfer_len == 0)
+ goto simple_cmd;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++ break;
+
+ case GPCMD_WRITE_12:
+ cmd->dout_xfer_len = ube32_to_cpu(s->io_buffer + 6);
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
+ if (cmd->dout_xfer_len == 0)
+ goto simple_cmd;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+
+ case GPCMD_WRITE_BUFFER:
+ {
+ goto illegal_request;
+ }
+
-+ ide_atapi_pt_wcmd(s);
-+ return;
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+ }
+
+ case GPCMD_SEND_CUE_SHEET:
+ cmd->dout_xfer_len = ube24_to_cpu(s->io_buffer + 6);
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
+ if (cmd->dout_xfer_len == 0)
+ goto simple_cmd;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+
+ case GPCMD_MODE_SELECT_10:
+ cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7);
+ CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->dout_xfer_len);
++
++ DEBUG_PRINTF("Mode select 10 %d bytes\n", cmd->dout_xfer_len);
++ {
++ int i;
++ DEBUG_PRINTF("0x");
++ for(i = 0; i < 12; ++i)
++ DEBUG_PRINTF("%02x ", s->io_buffer[i]);
++ DEBUG_PRINTF("\n0x");
++ for(i = 0; i < cmd->dout_xfer_len; ++i)
++ DEBUG_PRINTF("%02x ", s->io_buffer[i + 12]);
++ DEBUG_PRINTF("\n");
++ }
++
+ if (cmd->dout_xfer_len == 0)
+ goto simple_cmd;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+
+ case GPCMD_SEND_KEY:
+ case GPCMD_SEND_EVENT:
+ cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 8);
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
+ if (cmd->dout_xfer_len == 0)
+ goto simple_cmd;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+
+ case GPCMD_SEND_OPC:
+ cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 7) << 3;
+ CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->dout_xfer_len);
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
+ if (cmd->dout_xfer_len == 0)
+ goto simple_cmd;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+
+ case GPCMD_SET_STREAMING:
+ cmd->dout_xfer_len = ube16_to_cpu(s->io_buffer + 9);
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
+ if (cmd->dout_xfer_len == 0)
+ goto simple_cmd;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+
+ case GPCMD_FORMAT_UNIT:
+ cmd->dout_xfer_len = 12;
-+ ide_atapi_pt_wcmd(s);
-+ return;
++
++ DEBUG_PRINTF("Write (%s) %d bytes\n", atapi_cmd_to_str(command),
++ cmd->dout_xfer_len);
++
++ // ide_atapi_pt_wcmd(s);
++ // return;
++ break;
+
+ /*****************/
+ /* READ COMMANDS */
+ /*****************/
+
+ case GPCMD_INQUIRY:
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ cmd->din_xfer_len = s->io_buffer[4];
+ s->atapi_pt.reply_size_init = 5;
+ s->atapi_pt.reply_size_offset = 4;
+ s->atapi_pt.reply_size_len = 1;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
-+ ATAPI_PT_SEND_PACKET;
++ // ATAPI_PT_SEND_PACKET;
+ break;
+
+ case GPCMD_REQUEST_SENSE:
+ {
+ // send the previous sense command
-+ DEBUG_PRINTF("=== REQUEST SENSE ===\n"
++ DEBUG_PRINTF("=== REQUEST SENSE === "
+ "atapi_cmd_error: sense=0x%x asc=0x%x error=0x%x\n",
+ s->atapi_pt.sense.sense_key,
+ s->atapi_pt.sense.asc,
+
+ int size = 8 + s->atapi_pt.sense.add_sense_len;
+
-+ printf("max_size: %d, add_sense_len: %d, sizeof: %lu\n",
-+ max_size, s->atapi_pt.sense.add_sense_len,
-+ sizeof (s->atapi_pt.sense));
++ // printf("max_size: %d, add_sense_len: %d, sizeof: %lu\n",
++ // max_size, s->atapi_pt.sense.add_sense_len,
++ // sizeof (s->atapi_pt.sense));
+ memcpy(s->io_buffer, &s->atapi_pt.sense, sizeof (s->atapi_pt.sense));
+ ide_atapi_cmd_reply(s, size, max_size);
+ return;
+ }
++
+ case GPCMD_READ_DVD_STRUCTURE:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
-+ s->atapi_pt.reply_size_len = 4;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ s->atapi_pt.reply_size_len = 2;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_READ_HEADER:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_MECHANISM_STATUS:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_offset = 6;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_REPORT_KEY:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_len = 2;
+ s->atapi_pt.reply_size_init = 2;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_READ_BUFFER_CAPACITY:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_len = 2;
+ s->atapi_pt.reply_size_init = 2;
-+ return;
++ // return;
++ break;
+
+ case GPCMD_GET_PERFORMANCE:
+ cmd->din_xfer_len = 8 + 8 * ube16_to_cpu(s->io_buffer + 8);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_len = 4;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_READ_10:
+ case GPCMD_READ_12:
+ default: assert(0);
+ }
+ cmd->din_xfer_len = nbblocks * blocksize;
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+ }
+
+ case GPCMD_READ_BUFFER:
+ // TODO check this one is correct
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ cmd->din_xfer_len = ube24_to_cpu(s->io_buffer + 6);
+
+ switch (s->io_buffer[1] & 0x7)
+ goto illegal_request;
+ }
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_READ_CDVD_CAPACITY:
+ cmd->din_xfer_len = 8;
+ CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->din_xfer_len);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_MODE_SENSE_10:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7);
+ CHECK_SAME_VALUE(s->lcyl | (s->hcyl << 8), cmd->din_xfer_len);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_len = 2;
+ s->atapi_pt.reply_size_init = 2;
+ //s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
+ case GPCMD_READ_DISC_INFO:
+ case GPCMD_READ_TOC_PMA_ATIP:
+ case GPCMD_READ_TRACK_RZONE_INFO:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_len = 2;
+ s->atapi_pt.reply_size_init = 2;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_READ_SUBCHANNEL:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_len = 2;
+ s->atapi_pt.reply_size_offset = 2;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_READ_CD:
+ {
+ int block_size = ide_atapi_pt_read_cd_block_size(s->io_buffer);
+
+ cmd->din_xfer_len = block_count * block_size;
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+ }
+
+ case GPCMD_READ_CD_MSF:
+ int block_size = ide_atapi_pt_read_cd_block_size(s->io_buffer);
+
+ cmd->din_xfer_len = block_count * block_size;
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+ }
+
+ case GPCMD_PLAY_AUDIO_10:
+ {
+ int block_count = ube16_to_cpu(s->io_buffer + 7);
+ cmd->din_xfer_len = block_count * CD_FRAMESIZE;
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+ }
+
+ case GPCMD_PLAY_AUDIO_MSF:
+ MSF_TO_FRAMES(s->io_buffer[6], s->io_buffer[7], s->io_buffer[8]);
+ int block_count = ending_frame - starting_frame;
+ cmd->din_xfer_len = block_count * CD_FRAMESIZE;
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = cmd->din_xfer_len;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+ }
+
+ case GPCMD_READ_FORMAT_CAPACITIES:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_read_format_capacities_sent;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_GET_CONFIGURATION:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 7);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = 4;
+ s->atapi_pt.reply_size_len = 4;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case GPCMD_SEND_DVD_STRUCTURE:
+ cmd->din_xfer_len = ube16_to_cpu(s->io_buffer + 8);
-+ cmd->din_xferp = (__u64)s->io_buffer;
++ // cmd->din_xferp = (__u64)s->io_buffer;
+ s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply;
+ s->atapi_pt.reply_size_init = 2;
+ s->atapi_pt.reply_size_len = 2;
-+ ATAPI_PT_SEND_PACKET;
-+ return;
++ // ATAPI_PT_SEND_PACKET;
++ // return;
++ break;
+
+ case 0x01: // GPMODE_R_W_ERROR_PAGE ?
+ case 0x1a: // GPMODE_POWER_PAGE ?
+ exit(1);
+ return;
+ }
++
++
++ s->atapi_pt.sense.error_code = 0;
++ s->atapi_pt.sense.sense_key = 0;
++ s->atapi_pt.sense.asc = 0;
++ s->atapi_pt.sense.ascq = 0;
++
++ /* Send command and wait for reply, SG_IO ioctl*/
++ r = ioctl(raw_state->fd, 0x2285, cmd);
++
++ if(command == GPCMD_GET_EVENT_STATUS_NOTIFICATION)
++ {
++ struct stat file_stat;
++
++ if(s->io_buffer[2] == 4 && s->io_buffer[4] == 2)
++ {
++ /* This is a "new media" message, tell any other VMs */
++ DEBUG_PRINTF("[ATAPI] new media\n");
++ system("touch " IDE_ATAPI_PT_NEW_CD_FILE);
++
++ if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &file_stat) != 0)
++ DEBUG_PRINTF("Error writing to new CD file\n");
++ else
++ s->atapi_pt.new_cd_time = file_stat.st_ctime;
++ }
++
++ if(s->io_buffer[2] == 4 && s->io_buffer[4] == 3)
++ {
++ /* This is a "media removed" message, tell any other VMs */
++ DEBUG_PRINTF("[ATAPI] media removed\n");
++ system("touch " IDE_ATAPI_PT_EJECT_CD_FILE);
++
++ if(stat(IDE_ATAPI_PT_EJECT_CD_FILE, &file_stat) != 0)
++ DEBUG_PRINTF("Error writing to eject CD file\n");
++ else
++ s->atapi_pt.eject_time = file_stat.st_ctime;
++ }
++
++ if((s->io_buffer[2] == 4 && s->io_buffer[4] == 0 && s->io_buffer[5] == 2) ||
++ (s->io_buffer[4] == 0 && s->io_buffer[5] == 0 &&
++ s->io_buffer[6] == 0 && s->io_buffer[7] == 0))
++ {
++ /* This is a no activity message we can hijack if we need to */
++
++ if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &file_stat) == 0 &&
++ s->atapi_pt.new_cd_time < file_stat.st_ctime)
++ {
++ /* There's been a new media message that we haven't seen yet */
++ DEBUG_PRINTF("[ATAPI] new media message spotted\n");
++ s->atapi_pt.new_cd_time = file_stat.st_ctime;
++
++ s->io_buffer[2] = 4;
++ s->io_buffer[4] = 2;
++ s->io_buffer[5] = 2;
++ s->io_buffer[6] = 0;
++ s->io_buffer[7] = 0;
++ }
++ else if(stat(IDE_ATAPI_PT_EJECT_CD_FILE, &file_stat) == 0 &&
++ s->atapi_pt.eject_time < file_stat.st_ctime)
++ {
++ /* There's been an eject message that we haven't seen yet */
++ DEBUG_PRINTF("[ATAPI] media removed message spotted\n");
++ s->atapi_pt.eject_time = file_stat.st_ctime;
++
++ s->io_buffer[2] = 4;
++ s->io_buffer[4] = 3;
++ s->io_buffer[5] = 1;
++ s->io_buffer[6] = 0;
++ s->io_buffer[7] = 0;
++ }
++ }
++ }
++
++ if(r || cmd->driver_status || cmd->transport_status ||
++ cmd->device_status) {
++ /*
++ DEBUG_PRINTF("[\e[1;31mERROR\e[m]\n"
++ "\tcommand 0x%02x (%s)\n"
++ "\terrno: %d (%s)\n"
++ "\tsense: 0x%02x,%02x,%02x (%s)\n"
++ "\tdriver: %d, transport: %d, device: %d\n",
++ command, atapi_cmd_to_str(command),
++ errno,
++ strerror(errno) ? : "(null)",
++ s->atapi_pt.sense.sense_key,
++ s->atapi_pt.sense.asc,
++ s->atapi_pt.sense.ascq,
++ atapi_sense_to_str(s->atapi_pt.sense.sense_key,
++ s->atapi_pt.sense.asc,
++ s->atapi_pt.sense.ascq),
++ cmd->driver_status,
++ cmd->transport_status,
++ cmd->device_status);
++ */
++ DEBUG_PRINTF("[\e[1;31mERROR\e[m] (%s) sense: 0x%02x,%02x,%02x (%s)\n",
++ atapi_cmd_to_str(command),
++ s->atapi_pt.sense.sense_key,
++ s->atapi_pt.sense.asc,
++ s->atapi_pt.sense.ascq,
++ atapi_sense_to_str(s->atapi_pt.sense.sense_key,
++ s->atapi_pt.sense.asc,
++ s->atapi_pt.sense.ascq));
++ ide_atapi_pt_error(s);
++ return;
++ }
++
++ s->atapi_pt.cmd_sent(s);
+}
diff --git a/hw/ide.c b/hw/ide.c
-index e8d676e..85a2813 100644
+index e8d676e..6c1d60a 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -22,6 +22,7 @@
#include "hw.h"
#include "pc.h"
#include "pci.h"
-@@ -36,6 +37,15 @@
+@@ -36,6 +37,16 @@
#include "sh.h"
#include "dma.h"
+
+# include <linux/cdrom.h>
+# include <linux/bsg.h>
++# include <linux/ioctl.h>
+#endif /* __linux__ */
+
+#include <assert.h>
/* debug IDE devices */
//#define DEBUG_IDE
//#define DEBUG_IDE_ATAPI
-@@ -221,83 +231,94 @@
+@@ -221,83 +232,94 @@
#define ATAPI_PACKET_SIZE 12
/*
* Based on values from <linux/cdrom.h> but extending CD_MINS
-@@ -309,10 +330,13 @@
+@@ -309,10 +331,13 @@
*/
/* Some generally useful CD-ROM information */
#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
#define CD_MAX_SECTORS (CD_MAX_BYTES / 512)
-@@ -351,12 +375,15 @@
+@@ -351,12 +376,15 @@
#define MMC_PROFILE_HDDVD_RW_DL 0x005A
#define MMC_PROFILE_INVALID 0xFFFF
#define ASC_ILLEGAL_OPCODE 0x20
#define ASC_LOGICAL_BLOCK_OOR 0x21
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
-@@ -371,15 +398,42 @@
+@@ -371,15 +399,45 @@
#define CFA_INVALID_ADDRESS 0x21
#define CFA_ADDRESS_OVERFLOW 0x2f
+ uint32_t reply_size_init; // initial value
+ uint32_t reply_size_offset; // offset in s->io_buffer
+ uint32_t reply_size_len; // length in byte (0, 1, 2, 3 or 4)
++
++ time_t new_cd_time;
++ time_t eject_time;
+} ATAPIPassThroughState;
+#endif /* __linux__ */
+
/* NOTE: IDEState represents in fact one drive */
typedef struct IDEState {
/* ide config */
-@@ -429,6 +483,10 @@ typedef struct IDEState {
+@@ -429,6 +487,10 @@ typedef struct IDEState {
int lba;
int cd_sector_size;
int atapi_dma; /* true if dma is requested for the packet cmd */
/* ATA DMA state */
int io_buffer_size;
QEMUSGList sg;
-@@ -1321,9 +1379,9 @@ static void ide_sector_write(IDEState *s)
+@@ -940,6 +1002,8 @@ static inline void ide_set_irq(IDEState *s)
+ if (bm) {
+ bm->status |= BM_STATUS_INT;
+ }
++ // if (s->is_cdrom)
++ // puts("@@@@@@@@ CDROM IRQ");
+ qemu_irq_raise(s->irq);
+ }
+ }
+@@ -1321,9 +1385,9 @@ static void ide_sector_write(IDEState *s)
that at the expense of slower write performances. Use this
option _only_ to install Windows 2000. You must disable it
for normal use. */
#endif
{
ide_set_irq(s);
-@@ -1499,6 +1557,13 @@ static inline int ube16_to_cpu(const uint8_t *buf)
+@@ -1499,6 +1563,13 @@ static inline int ube16_to_cpu(const uint8_t *buf)
return (buf[0] << 8) | buf[1];
}
static inline int ube32_to_cpu(const uint8_t *buf)
{
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-@@ -1567,12 +1632,14 @@ static void ide_atapi_io_error(IDEState *s, int ret)
+@@ -1567,12 +1638,14 @@ static void ide_atapi_io_error(IDEState *s, int ret)
static void ide_atapi_cmd_reply_end(IDEState *s)
{
int byte_count_limit, size, ret;
if (s->packet_transfer_size <= 0) {
/* end of transfer */
ide_transfer_stop(s);
-@@ -1582,63 +1649,65 @@ static void ide_atapi_cmd_reply_end(IDEState *s)
+@@ -1582,63 +1655,65 @@ static void ide_atapi_cmd_reply_end(IDEState *s)
#ifdef DEBUG_IDE_ATAPI
printf("status=0x%x\n", s->status);
#endif
}
}
-@@ -1882,6 +1951,10 @@ static int ide_dvd_read_structure(IDEState *s, int format,
+@@ -1882,6 +1957,10 @@ static int ide_dvd_read_structure(IDEState *s, int format,
}
}
static void ide_atapi_cmd(IDEState *s)
{
const uint8_t *packet;
-@@ -1922,7 +1995,6 @@ static void ide_atapi_cmd(IDEState *s)
+@@ -1922,7 +2001,6 @@ static void ide_atapi_cmd(IDEState *s)
ASC_MEDIUM_NOT_PRESENT);
}
break;
case GPCMD_MODE_SENSE_10:
{
int action, code;
-@@ -1935,9 +2007,9 @@ static void ide_atapi_cmd(IDEState *s)
+@@ -1935,9 +2013,9 @@ static void ide_atapi_cmd(IDEState *s)
switch(action) {
case 0: /* current values */
switch(code) {
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
-@@ -1954,17 +2026,17 @@ static void ide_atapi_cmd(IDEState *s)
+@@ -1954,17 +2032,17 @@ static void ide_atapi_cmd(IDEState *s)
buf[15] = 0x00;
ide_atapi_cmd_reply(s, 16, max_len);
break;
buf[10] = 0x00;
buf[11] = 0x00;
-@@ -1987,6 +2059,7 @@ static void ide_atapi_cmd(IDEState *s)
+@@ -1987,6 +2065,7 @@ static void ide_atapi_cmd(IDEState *s)
buf[27] = 0;
ide_atapi_cmd_reply(s, 28, max_len);
break;
default:
goto error_cmd;
}
-@@ -2110,7 +2183,7 @@ static void ide_atapi_cmd(IDEState *s)
+@@ -2110,7 +2189,7 @@ static void ide_atapi_cmd(IDEState *s)
break;
case GPCMD_MECHANISM_STATUS:
{
cpu_to_ube16(buf, 0);
/* no current LBA */
buf[2] = 0;
-@@ -2125,7 +2198,6 @@ static void ide_atapi_cmd(IDEState *s)
+@@ -2125,7 +2204,6 @@ static void ide_atapi_cmd(IDEState *s)
{
int format, msf, start_track, len;
uint64_t total_sectors;
bdrv_get_geometry(s->bs, &total_sectors);
total_sectors >>= 2;
if (total_sectors == 0) {
-@@ -2279,7 +2351,7 @@ static void ide_atapi_cmd(IDEState *s)
+@@ -2279,7 +2357,7 @@ static void ide_atapi_cmd(IDEState *s)
max_len = 512;
memset(buf, 0, max_len);
* the number of sectors from the media tells us which profile
* to use as current. 0 means there is no media
*/
-@@ -2484,7 +2556,11 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+@@ -2484,7 +2562,11 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
/* Only DEVICE RESET is allowed while BSY or/and DRQ are set */
if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET)
switch(val) {
case WIN_IDENTIFY:
-@@ -2727,7 +2803,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+@@ -2727,7 +2809,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
else
s->status = READY_STAT | SEEK_STAT;
s->error = 0x01; /* Device 0 passed, Device 1 passed or not
*/
ide_set_irq(s);
break;
-@@ -2748,7 +2824,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+@@ -2748,7 +2830,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
s->atapi_dma = s->feature & 1;
s->nsector = 1;
ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
break;
/* CF-ATA commands */
case CFA_REQ_EXT_ERROR_CODE:
-@@ -3133,8 +3209,20 @@ static void ide_init2(IDEState *ide_state,
+@@ -3133,8 +3215,20 @@ static void ide_init2(IDEState *ide_state,
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
s->is_cdrom = 1;
}
+#ifdef __linux__
+ else if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM_PT) {
-+ BDRVRawState *raw_state = s->bs->opaque;
++ // BDRVRawState *raw_state = s->bs->opaque;
+ s->is_cdrom = 1;
+ s->atapi_cmd = ide_atapi_pt_cmd;
+ bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
-+ qemu_set_fd_handler(raw_state->fd,
-+ (IOHandler *)ide_atapi_pt_sg_io_finished,
-+ NULL, s);
++ // qemu_set_fd_handler(raw_state->fd,
++ // (IOHandler *)ide_atapi_pt_sg_io_finished,
++ // NULL, s);
+ }
+#endif /* __linux__ */
}
s->drive_serial = drive_serial++;
strncpy(s->drive_serial_str, drive_get_serial(s->bs),
diff --git a/vl.c b/vl.c
-index f3b0dae..91fb696 100644
+index cd354de..b5dfbd5 100644
--- a/vl.c
+++ b/vl.c
@@ -2192,8 +2192,10 @@ static int bt_parse(const char *opt)
}
break;
case IF_SD:
-@@ -4244,6 +4251,7 @@ enum {
+@@ -2669,6 +2676,8 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ else if (cache == 3) /* not specified */
+ bdrv_flags |= BDRV_O_CACHE_DEF;
++
++ printf("**** vl open(%s)\n", file);
+ if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
+ fprintf(stderr, "qemu: could not open disk image %s\n",
+ file);
+@@ -4244,6 +4253,7 @@ enum {
QEMU_OPTION_hdc,
QEMU_OPTION_hdd,
QEMU_OPTION_cdrom,
QEMU_OPTION_drive,
QEMU_OPTION_mtdblock,
QEMU_OPTION_sd,
-@@ -4366,6 +4374,7 @@ static const QEMUOption qemu_options[] = {
+@@ -4366,6 +4376,7 @@ static const QEMUOption qemu_options[] = {
{ "hdc", HAS_ARG, QEMU_OPTION_hdc },
{ "hdd", HAS_ARG, QEMU_OPTION_hdd },
{ "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
{ "drive", HAS_ARG, QEMU_OPTION_drive },
{ "mtdblock", HAS_ARG, QEMU_OPTION_mtdblock },
{ "sd", HAS_ARG, QEMU_OPTION_sd },
-@@ -5035,13 +5044,16 @@ int main(int argc, char **argv, char **envp)
+@@ -5035,13 +5046,16 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_cdrom:
drive_add(optarg, CDROM_ALIAS);
break;