From: Andrew McNeil Date: Fri, 28 Aug 2009 19:42:48 +0000 (+0100) Subject: Atapi pass through using SG_IO to allow concurrent access by multiple VMs. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=0f31287c561c399deaf7d8128f3cda830ced709b;p=xenclient%2Fioemu-pq.git Atapi pass through using SG_IO to allow concurrent access by multiple VMs. All VMS get notifications on CD insertion and extraction. CD writing is currently broken. --- diff --git a/master/atapi-pass-through b/master/atapi-pass-through index 9acc7b4..c79f08a 100644 --- a/master/atapi-pass-through +++ b/master/atapi-pass-through @@ -14,7 +14,7 @@ index 5f4f4cf..42da5b6 100644 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 @@ @@ -39,6 +39,14 @@ index 9a02d4f..775a1d1 100644 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 @@ -97,10 +105,12 @@ index 0000000..f9bdee9 +#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 ++ +#define DEBUG_IDE_ATAPI_PT + +#define MSF_TO_FRAMES(M, S, F) (((M) * CD_SECS + (S)) * CD_FRAMES + (F)) @@ -119,6 +129,11 @@ index 0000000..2f63492 +# 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 { @@ -211,158 +226,371 @@ index 0000000..2f63492 + "(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; @@ -380,15 +608,51 @@ index 0000000..2f63492 + 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; + } + @@ -407,16 +671,31 @@ index 0000000..2f63492 + 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 \ @@ -460,7 +739,9 @@ index 0000000..2f63492 + 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) @@ -487,6 +768,7 @@ index 0000000..2f63492 + ide_set_irq(s); + return; +} ++#endif + +static void ide_atapi_pt_read_format_capacities_sent(IDEState *s) +{ @@ -518,9 +800,6 @@ index 0000000..2f63492 + 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); +} + @@ -645,9 +924,13 @@ index 0000000..2f63492 + 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); @@ -665,6 +948,11 @@ index 0000000..2f63492 + 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]) + { + /*******************/ @@ -694,9 +982,7 @@ index 0000000..2f63492 + 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 */ @@ -705,17 +991,25 @@ index 0000000..2f63492 + 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: + { @@ -742,71 +1036,115 @@ index 0000000..2f63492 + 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, @@ -816,61 +1154,68 @@ index 0000000..2f63492 + + 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: @@ -889,16 +1234,17 @@ index 0000000..2f63492 + 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) @@ -922,49 +1268,54 @@ index 0000000..2f63492 + 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: + { @@ -974,11 +1325,12 @@ index 0000000..2f63492 + 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: @@ -992,22 +1344,24 @@ index 0000000..2f63492 + 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: @@ -1018,37 +1372,41 @@ index 0000000..2f63492 + 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 ? @@ -1070,9 +1428,116 @@ index 0000000..2f63492 + 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 @@ @@ -1083,7 +1548,7 @@ index e8d676e..85a2813 100644 #include "hw.h" #include "pc.h" #include "pci.h" -@@ -36,6 +37,15 @@ +@@ -36,6 +37,16 @@ #include "sh.h" #include "dma.h" @@ -1092,6 +1557,7 @@ index e8d676e..85a2813 100644 + +# include +# include ++# include +#endif /* __linux__ */ + +#include @@ -1099,7 +1565,7 @@ index e8d676e..85a2813 100644 /* debug IDE devices */ //#define DEBUG_IDE //#define DEBUG_IDE_ATAPI -@@ -221,83 +231,94 @@ +@@ -221,83 +232,94 @@ #define ATAPI_PACKET_SIZE 12 @@ -1258,7 +1724,7 @@ index e8d676e..85a2813 100644 /* * Based on values from but extending CD_MINS -@@ -309,10 +330,13 @@ +@@ -309,10 +331,13 @@ */ /* Some generally useful CD-ROM information */ @@ -1276,7 +1742,7 @@ index e8d676e..85a2813 100644 #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 @@ -1292,7 +1758,7 @@ index e8d676e..85a2813 100644 #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 @@ -1333,13 +1799,16 @@ index e8d676e..85a2813 100644 + 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 */ @@ -1350,7 +1819,16 @@ index e8d676e..85a2813 100644 /* 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. */ @@ -1362,7 +1840,7 @@ index e8d676e..85a2813 100644 #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]; } @@ -1376,7 +1854,7 @@ index e8d676e..85a2813 100644 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; @@ -1391,7 +1869,7 @@ index e8d676e..85a2813 100644 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 @@ -1508,7 +1986,7 @@ index e8d676e..85a2813 100644 } } -@@ -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, } } @@ -1519,7 +1997,7 @@ index e8d676e..85a2813 100644 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; @@ -1527,7 +2005,7 @@ index e8d676e..85a2813 100644 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) { @@ -1539,7 +2017,7 @@ index e8d676e..85a2813 100644 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; @@ -1561,7 +2039,7 @@ index e8d676e..85a2813 100644 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; @@ -1569,7 +2047,7 @@ index e8d676e..85a2813 100644 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: { @@ -1578,7 +2056,7 @@ index e8d676e..85a2813 100644 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; @@ -1586,7 +2064,7 @@ index e8d676e..85a2813 100644 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); @@ -1595,7 +2073,7 @@ index e8d676e..85a2813 100644 * 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) @@ -1607,7 +2085,7 @@ index e8d676e..85a2813 100644 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 @@ -1616,7 +2094,7 @@ index e8d676e..85a2813 100644 */ 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, @@ -1625,7 +2103,7 @@ index e8d676e..85a2813 100644 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; @@ -1634,20 +2112,20 @@ index e8d676e..85a2813 100644 } +#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) @@ -1689,7 +2167,16 @@ index f3b0dae..91fb696 100644 } 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, @@ -1697,7 +2184,7 @@ index f3b0dae..91fb696 100644 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 }, @@ -1705,7 +2192,7 @@ index f3b0dae..91fb696 100644 { "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;