diff --git a/hw/atapi-pt.c b/hw/atapi-pt.c
-index 92f2934..343798d 100644
+index 92f2934..d38d536 100644
--- a/hw/atapi-pt.c
+++ b/hw/atapi-pt.c
-@@ -1,19 +1,23 @@
+@@ -1,19 +1,30 @@
+#include <scsi/sg.h>
#include <utime.h>
++#include <time.h>
++#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
++#include <unistd.h>
++#include "xen.h"
- #undef DEBUG_IDE_ATAPI_PT
+-#undef DEBUG_IDE_ATAPI_PT
++/* Even when defined debugging is only enabled if /etc/debugcdrom exists */
++#define DEBUG_IDE_ATAPI_PT
#define MSF_TO_FRAMES(M, S, F) (((M) * CD_SECS + (S)) * CD_FRAMES + (F))
+static int log_fd=-1;
++static int debug_fd=-1;
++static int debug_enabled=-1;
#ifdef DEBUG_IDE_ATAPI_PT
-# define DEBUG_PRINTF(Args...) printf(Args)
-+# define DEBUG_PRINTF(Args...) do { char buf[1024]; int len; if (log_fd==-1) log_fd=open("/tmp/cdrom.log",O_WRONLY | O_CREAT | O_APPEND,0666); len=sprintf(buf,Args); write(log_fd,buf,len); } while (1==0)
++# define DEBUG_PRINTF(Args...) atapi_dprintf(Args)
# define CHECK_SAME_VALUE(Val1, Val2) \
do { \
- if ((Val1) != (Val2)) \
- __PRETTY_FUNCTION__, __LINE__, #Val1, (Val1), \
- #Val2, (Val2)); \
+ if ((Val1) != (Val2)) \
-+ printf("[\e[1;32m!VALUE\e[m] %s:%d, %s=%d %s=%d\n", \
++ dprintf("[\e[1;32m!VALUE\e[m] %s:%d, %s=%d %s=%d\n", \
+ __PRETTY_FUNCTION__, __LINE__, #Val1, (Val1), \
+ #Val2, (Val2)); \
} while (0)
#else
# define DEBUG_PRINTF(Args...)
-@@ -676,14 +680,58 @@ static void ide_atapi_pt_error(IDEState *s)
+@@ -21,9 +32,10 @@
+ #endif /* DEBUG_IDE_ATAPI_PT */
+
+
++#define IDE_ATAPI_PT_DEBUG_ENABLE_FILE "/etc/debugcdrom"
+ #define IDE_ATAPI_PT_NEW_CD_FILE "/var/lock/xen-cd-new"
+ #define IDE_ATAPI_PT_EJECT_CD_FILE "/var/lock/xen-cd-eject"
+-
++#define IDE_ATAPI_PT_DEBUG_FILE_TEMPLATE "/var/log/cdrom-%d.log"
+
+ /* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+@@ -482,6 +494,40 @@ static const char *atapi_sense_to_str(int key, int asc, int ascq)
+ }
+
+
++static void atapi_dprintf(const char *fmt, ...)
++{
++ struct stat st;
++ char debugbuf[2048];
++ time_t t = time(NULL);
++ struct tm *tmp = localtime(&t);
++ struct timeval tv;
++ va_list args;
++ int l;
++ if (debug_enabled == 0)
++ return;
++ if (debug_enabled < 0) {
++ if (stat(IDE_ATAPI_PT_DEBUG_ENABLE_FILE, &st) == 0)
++ debug_enabled = 1;
++ else {
++ debug_enabled = 0;
++ return;
++ }
++ }
++ if (debug_fd<0) {
++ sprintf(debugbuf, IDE_ATAPI_PT_DEBUG_FILE_TEMPLATE, domid);
++ debug_fd=open(debugbuf, O_WRONLY | O_CREAT | O_APPEND, 0666);
++ }
++ gettimeofday(&tv, NULL);
++ l = snprintf(debugbuf, sizeof(debugbuf)-1, "[%02d:%02d:%02d.%03ld] ",
++ tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tv.tv_usec/1000);
++ va_start(args, fmt);
++ vsnprintf(debugbuf+l, sizeof(debugbuf)-1-l, fmt, args);
++ va_end(args);
++ debugbuf[sizeof(debugbuf)-1] = '\0';
++ write(debug_fd, debugbuf, strlen(debugbuf));
++}
++
++
+ /* For each SCSI command we need to know up to 3 data sizes. These are:
+ * 1. The amount of data to send to the LU.
+ * 2. The size of the buffer provided for data sent back from the LU.
+@@ -676,14 +722,58 @@ static void ide_atapi_pt_error(IDEState *s)
ide_set_irq(s);
}
assert(cmd->din_xfer_len != (__u32)-1);
s->atapi_pt.sense.error_code = 0;
-@@ -691,9 +739,27 @@ static void ide_atapi_pt_do_sg_io(IDEState *s)
+@@ -691,9 +781,27 @@ static void ide_atapi_pt_do_sg_io(IDEState *s)
s->atapi_pt.sense.asc = 0;
s->atapi_pt.sense.ascq = 0;
+ cmd->timeout = timeout ? timeout : 15000;
-
-- /* Send command and wait for reply, SG_IO ioctl*/
-- r = ioctl(raw_state->fd, 0x2285, cmd);
++
+ /* Poke worker thread to send command using SG_IO ioctl */
+ pthread_cond_signal(&s->atapi_pt.sgio_cv);
+ pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+
+ DEBUG_PRINTF("%s\n", __FUNCTION__);
+ assert(s);
-+
+
+- /* Send command and wait for reply, SG_IO ioctl*/
+- r = ioctl(raw_state->fd, 0x2285, cmd);
+ /* Get return code of ioctl from worker thread's fd */
+ read(s->atapi_pt.sgio_rfd, &r, sizeof(int));
if(s->atapi_pt.request[0] == GPCMD_GET_EVENT_STATUS_NOTIFICATION)
{
-@@ -832,16 +898,17 @@ static void ide_atapi_pt_do_sg_io(IDEState *s)
+@@ -746,16 +854,18 @@ static void ide_atapi_pt_do_sg_io(IDEState *s)
+
+ if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &file_stat) == 0)
+ {
+- /* 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;
+- }
++ if (s->atapi_pt.new_cd_time != file_stat.st_ctime) {
++ /* There's been a new media message that we haven't seen yet */
++ s->atapi_pt.new_cd_time = file_stat.st_ctime;
++ DEBUG_PRINTF("[ATAPI] new media message spotted\n");
++
++ 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)
+ {
+@@ -832,16 +942,17 @@ static void ide_atapi_pt_do_sg_io(IDEState *s)
if(din_desired == (__u32)-1)
din_desired = cmd->din_xfer_len;
static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret)
{
BMDMAState *bm = opaque;
-@@ -850,13 +917,15 @@ static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret)
+@@ -850,13 +961,15 @@ static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret)
if (ret < 0) {
ide_atapi_io_error(s, ret);
static void ide_atapi_pt_wcmd(IDEState *s)
{
if (s->atapi_dma)
-@@ -1005,11 +1074,20 @@ static int ide_atapi_pt_read_cd_block_size(const uint8_t *io_buffer)
+@@ -1005,11 +1118,20 @@ static int ide_atapi_pt_read_cd_block_size(const uint8_t *io_buffer)
return block_size;
}
memset(cmd, 0, sizeof(*cmd));
memcpy(s->atapi_pt.request, s->io_buffer, ATAPI_PACKET_SIZE);
cmd_code = s->atapi_pt.request[0];
-@@ -1021,6 +1099,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+@@ -1021,6 +1143,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
cmd->response = (__u64)&s->atapi_pt.sense;
cmd->max_response_len = sizeof(s->atapi_pt.sense);
cmd->timeout = 15000; // 15 seconds
s->status |= BUSY_STAT;
-@@ -1054,14 +1133,15 @@ static void ide_atapi_pt_cmd(IDEState *s)
+@@ -1054,14 +1177,15 @@ static void ide_atapi_pt_cmd(IDEState *s)
ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
ASC_INV_FIELD_IN_CMD_PACKET, 0x70);
break;
case GPCMD_WRITE_BUFFER:
-@@ -1072,6 +1152,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+@@ -1072,6 +1196,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
s->io_buffer[1] & 7);
ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
ASC_ILLEGAL_OPCODE, 0x70);
return;
}
-@@ -1091,6 +1172,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+@@ -1091,6 +1216,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
int size = 8 + s->atapi_pt.sense.add_sense_len;
memcpy(s->io_buffer, &s->atapi_pt.sense, sizeof (s->atapi_pt.sense));
ide_atapi_cmd_reply(s, size, max_size);
return;
}
-@@ -1152,6 +1234,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+@@ -1152,6 +1278,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
s->io_buffer[10]);
ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
ASC_ILLEGAL_OPCODE, 0x70);
return;
}
break;
-@@ -1169,5 +1252,5 @@ static void ide_atapi_pt_cmd(IDEState *s)
+@@ -1169,5 +1296,5 @@ static void ide_atapi_pt_cmd(IDEState *s)
return;
}