--- /dev/null
+diff --git a/hw/atapi-pt.c b/hw/atapi-pt.c
+index 2d26983..7f59aca 100644
+--- a/hw/atapi-pt.c
++++ b/hw/atapi-pt.c
+@@ -7,6 +7,8 @@
+ #include <pthread.h>
+ #include <sys/ioctl.h>
+ #include <unistd.h>
++#include <sys/types.h>
++#include <sys/socket.h>
+ #include "xen.h"
+
+ /* Even when defined debugging is only enabled if /etc/debugcdrom exists */
+@@ -395,6 +397,8 @@ static const struct {
+
+ static int we_have_lock = 0;
+
++static void ide_atapi_pt_ejected(void);
++
+ static int get_lock_fd(void)
+ {
+ static int lock_fd=-1;
+@@ -773,6 +777,9 @@ static uint32_t ide_atapi_pt_get_data_size(int size_select, uint8_t command, uin
+
+ static void ide_atapi_pt_set_error(IDEState *s, int sense_key, int asc, int ascq, int error)
+ {
++ static uint32_t serial=0;
++
++ DEBUG_PRINTF("ide_atapi_pt_set_error serial 0x%x\n",xerial++);
+ memset(&s->atapi_pt.sense, 0, 18);
+ s->atapi_pt.sense.sense_key = sense_key;
+ s->atapi_pt.sense.asc = asc;
+@@ -807,16 +814,11 @@ static void ide_atapi_pt_error(IDEState *s)
+ * send our command.
+ * This is the BSG SG_IO v4 implementation.
+ */
+-static void *ide_atapi_pt_sgio_worker_thread(void *arg)
++static int ide_atapi_pt_do_dispatch(volatile IDEState *s)
+ {
+- int r;
+ struct sg_io_v4 cmd;
+ BDRVRawState *raw_state;
+- volatile IDEState *s = (volatile IDEState *)arg;
+-
+- for(;;) {
+- pthread_mutex_lock(&s->atapi_pt.sgio_mutex);
+- pthread_cond_wait(&s->atapi_pt.sgio_cv, &s->atapi_pt.sgio_mutex);
++ int r;
+
+ /* Send command and wait for reply, SG_IO ioctl*/
+ memset(&cmd, 0, sizeof(cmd));
+@@ -869,11 +871,215 @@ static void *ide_atapi_pt_sgio_worker_thread(void *arg)
+ s->atapi_pt.sense.asc,
+ s->atapi_pt.sense.ascq));
+ }
++ return r;
++}
++
++static int status_file_touched(const char *fn,time_t *t)
++{
++ int fd;
++ struct stat buf;
++
++ if (!t) return 0;
++
++ if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &buf)) {
++ DEBUG_PRINTF("Error stating %s\n",fn);
++ return 0;
++ }
++
++ if (buf.st_ctime > *t) {
++ *t=buf.st_ctime;
++ return 1;
++ }
++
++ return 0;
++}
++
++static void touch_status_file(const char *fn,time_t *t)
++{
++ int fd;
++ struct stat buf;
++
++ fd = open(fn, O_WRONLY | O_TRUNC | O_CREAT, 0666);
++ if(fd < 0) {
++ DEBUG_PRINTF("Error touching %s\n",fn);
++ } else {
++ close(fd);
++ utime(fn, NULL);
++ }
++
++ if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &buf)) {
++ DEBUG_PRINTF("Error stating %s\n",fn);
++ return;
++ }
++
++ if (t)
++ *t = buf.st_ctime;
++}
++
++static void ide_atapi_pt_cmd_complete(void *arg) /* Mop up result*/
++{
++ IDEState *s = (IDEState *)arg;
++ uint8_t cmd_code = s->atapi_pt.request[0];
++ uint32_t din_desired;
++ static uint32_t serial = 0;
++
++ assert(s);
++
++
++ {
++ /* Get return code of ioctl from worker thread's fd */
++ int r;
++ recv(s->atapi_pt.sgio_dispatch_fd, &r, sizeof(int),0);
++
++ DEBUG_PRINTF("ide_atapi_pt_cmd_complete serial 0x%x - code %d\n",serial++,r);
++ }
++
++ if(s->atapi_pt.result)
++ {
++ if(s->atapi_pt.request[0] == GPCMD_TEST_UNIT_READY &&
++ s->atapi_pt.sense.sense_key == 2 && s->atapi_pt.sense.asc == 0x3A)
++ /* No media, remove exclusivity lock */
++ ide_atapi_pt_ejected();
++
++ ide_atapi_pt_error(s);
++ return;
++ }
++
++ if(s->atapi_pt.request[0] == GPCMD_GET_EVENT_STATUS_NOTIFICATION)
++ {
++
++ 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 detected\n");
++
++ touch_status_file(IDE_ATAPI_PT_NEW_CD_FILE,&s->atapi_pt.new_cd_time);
++ }
++
++ 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");
++
++ touch_status_file(IDE_ATAPI_PT_EJECT_CD_FILE,&s->atapi_pt.new_cd_time);
++
++ /* Remove exclusivity lock */
++ ide_atapi_pt_ejected();
++ }
++
++ 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(status_file_touched(IDE_ATAPI_PT_NEW_CD_FILE,&s->atapi_pt.new_cd_time)) {
++ 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(status_file_touched(IDE_ATAPI_PT_EJECT_CD_FILE,&s->atapi_pt.eject_time))
++ {
++ /* There's been an eject message that we haven't seen yet */
++ DEBUG_PRINTF("[ATAPI] media removed message spotted\n");
++
++ 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(s->atapi_pt.din_xfer_len == 0)
++ {
++ // Nothing else to do
++ ide_atapi_cmd_ok(s);
++ return;
++ }
++
++ din_desired = ide_atapi_pt_get_data_size(ide_atapi_pt_size_din, cmd_code, s->io_buffer);
++
++ /* din_xfer_len is the size of the buffer provided for the din data,
++ * din_desired in the size of the data the LU tried to send to us. Either one
++ * may be bigger. */
++
++ if(s->atapi_pt.request[0] == GPCMD_READ_BUFFER)
++ {
++ switch(s->atapi_pt.request[1] & 7)
++ {
++ case 0: // data with header, as specified in atapi_data_sizes table
++ break;
++
++ case 2: // data only
++ din_desired = s->atapi_pt.din_xfer_len;
++ break;
++
++ case 3: // header only
++ din_desired = 4;
++ break;
++
++ case 1: // vendor specific
++ default:
++ DEBUG_PRINTF("\e[3;31mIllegal read buffer mode %d\e[m\n",
++ s->io_buffer[1] & 7);
++ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
++ ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70);
++ return;
++ }
++ }
++
++ if(din_desired == (__u32)-1)
++ din_desired = s->atapi_pt.din_xfer_len;
++
++ DEBUG_PRINTF("Read %d bytes of data (buffer size %d)\n",
++ din_desired, s->atapi_pt.din_xfer_len);
++
++ if(s->atapi_pt.din_xfer_len >= 0x80 && din_desired >= 0x80)
++ DEBUG_HEXDUMP(s->io_buffer, 0x80);
++ else if(s->atapi_pt.din_xfer_len < din_desired)
++ DEBUG_HEXDUMP(s->io_buffer, s->atapi_pt.din_xfer_len);
++ else
++ DEBUG_HEXDUMP(s->io_buffer, din_desired);
++
++ ide_atapi_cmd_reply(s, din_desired, s->atapi_pt.din_xfer_len);
++}
++
++
++static void *ide_atapi_pt_sgio_worker_thread(void *arg)
++{
++ int r;
++ fd_set rfds;
++ sigset_t set;
++ static uint32_t serial=0;
++ volatile IDEState *s = (volatile IDEState *)arg;
+
+- /* Unlock _before_ signalling parent */
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- write(s->atapi_pt.sgio_wfd, &r, sizeof(int));
++ if (sigfillset(&set)) { DEBUG_PRINTF("sigfillset\n"); return NULL; }
++ if (pthread_sigmask(SIG_BLOCK, &set, NULL)) { DEBUG_PRINTF("sigprocmask"); return NULL; }
++
++ FD_ZERO(&rfds);
++
++ for(;;) {
++ struct timeval zero={0};
++ recv(s->atapi_pt.sgio_worker_fd,&r,sizeof(int),0);
++
++ FD_SET(s->atapi_pt.sgio_worker_fd,&rfds);
++
++ while (select(s->atapi_pt.sgio_worker_fd+1,&rfds,NULL,NULL,&zero)==1) {
++ recv(s->atapi_pt.sgio_worker_fd,&r,sizeof(int),MSG_DONTWAIT);
++ }
++
++ DEBUG_PRINTF("ide_atapi_pt_sgio_worker_thread: in serial 0x%x\n",serial++);
++ r=ide_atapi_pt_do_dispatch(s);
++ DEBUG_PRINTF("ide_atapi_pt_sgio_worker_thread: out serial 0x%x response %d\n",serial-1,r);
++
++ write(s->atapi_pt.sgio_worker_fd, &r, sizeof(int));
+ }
++return NULL;
+ }
+
+
+@@ -884,49 +1090,45 @@ static int ide_atapi_pt_aio_flush(void *unused)
+ return 0;
+ }
+
+-static void ide_atapi_pt_cmd_complete(void *arg);
+
+ static void ide_atapi_pt_setup_sgio_thread(IDEState *s)
+ {
+ int fds[2];
+
+- if(pipe(fds) < 0) {
+- DEBUG_PRINTF("atapi-pt failed to create pipe: %m\n");
++ if(socketpair(PF_UNIX,SOCK_DGRAM,0,fds) < 0) {
++ DEBUG_PRINTF("atapi-pt failed to create socketpair: %m\n");
+ exit(1);
+ }
+- s->atapi_pt.sgio_rfd = fds[0];
+- s->atapi_pt.sgio_wfd = fds[1];
+-
+- pthread_mutex_init(&s->atapi_pt.sgio_mutex, NULL);
+- pthread_cond_init (&s->atapi_pt.sgio_cv, NULL);
++ s->atapi_pt.sgio_dispatch_fd = fds[0];
++ s->atapi_pt.sgio_worker_fd = fds[1];
+
+ if (pthread_create(&s->atapi_pt.sgio_thread, NULL, ide_atapi_pt_sgio_worker_thread, (void *)s))
+ {
+ DEBUG_PRINTF("Create CD-ROM worker thread failed\n");
+ exit(1);
+ }
+- qemu_aio_set_fd_handler(s->atapi_pt.sgio_rfd, ide_atapi_pt_cmd_complete, NULL, ide_atapi_pt_aio_flush, (void *)s);
++ qemu_aio_set_fd_handler(s->atapi_pt.sgio_dispatch_fd, ide_atapi_pt_cmd_complete, NULL, ide_atapi_pt_aio_flush, (void *)s);
+ }
+
+-/* Call with ide_atapi_sgio_mutex held */
+ static void ide_atapi_pt_do_sg_io(IDEState *s)
+ {
++ static uint32_t serial=0;
++ int r='K';
++ DEBUG_PRINTF("ide_atapi_pt_do_sg_io 0x%x\n",serial++);
++
+ /* 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);
++ send(s->atapi_pt.sgio_dispatch_fd,&r,sizeof(int),MSG_NOSIGNAL);
+ }
+
+
+ /* Functions to fetch dout data from where-ever it comes from */
+
+-/* Call with ide_atapi_sgio_mutex held */
+ static void ide_atapi_pt_dout_fetch_pio_done(IDEState *s)
+ {
+ ide_transfer_stop(s);
+ ide_atapi_pt_do_sg_io(s);
+ }
+
+-/* Call with ide_atapi_sgio_mutex held */
+ static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret)
+ {
+ BMDMAState *bm = opaque;
+@@ -935,7 +1137,6 @@ static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret)
+
+ if (ret < 0) {
+ ide_atapi_io_error(s, ret);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+ return;
+ }
+
+@@ -943,7 +1144,6 @@ static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret)
+ ide_atapi_pt_do_sg_io(s);
+ }
+
+-/* Call with ide_atapi_sgio_mutex held */
+ static void ide_atapi_pt_wcmd(IDEState *s)
+ {
+ if (s->atapi_dma)
+@@ -1107,11 +1307,6 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ uint8_t cmd_code;
+ FILE *fp;
+
+- if(pthread_mutex_trylock(&s->atapi_pt.sgio_mutex)) {
+- DEBUG_PRINTF("ide_atapi_pt_cmd() called with existing request processing - ignored!\n");
+- return;
+- }
+-
+ memcpy(s->atapi_pt.request, s->io_buffer, ATAPI_PACKET_SIZE);
+ cmd_code = s->atapi_pt.request[0];
+ s->atapi_pt.timeout = 15000;
+@@ -1148,8 +1343,8 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ DEBUG_HEXDUMP(s->io_buffer, actual_size);
+
+ ide_atapi_cmd_reply(s, size, max_size);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
++
+ }
+
+ s->atapi_pt.dout_xfer_len = ide_atapi_pt_get_data_size(ide_atapi_pt_size_dout,
+@@ -1178,8 +1373,8 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ memcpy(s->io_buffer, inquiry_data, 96);
+ memset(&s->atapi_pt.sense, 0, sizeof(sense));
+ ide_atapi_cmd_reply(s, 96, s->atapi_pt.din_xfer_len);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
++
+ }
+
+ if(cmd_code == GPCMD_MODE_SENSE_10)
+@@ -1192,8 +1387,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ DEBUG_PRINTF("Blocking command due to exclusivity lock\n");
+ memcpy(&s->atapi_pt.sense, sense, sizeof(sense));
+ ide_atapi_pt_set_error(s, sense[2], sense[12], sense[13], 0x70);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
+ }
+
+ /* Claim exclusive use if we're doing any kind of writing */
+@@ -1210,8 +1404,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ // FIXME XXX - make this throw an error
+ memcpy(&s->atapi_pt.sense, sense, 18);
+ ide_atapi_pt_set_error(s, sense[2], sense[12], sense[13], 0x70);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
+ #endif
+ }
+ }
+@@ -1225,8 +1418,8 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ // we don't allow locking, to prevent a VM from hogging the drive
+ ide_atapi_cmd_ok(s);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
++
+
+ case GPCMD_FLUSH_CACHE: // bigger timeout while flushing write cache
+ s->atapi_pt.timeout = 1000 * 60;
+@@ -1256,8 +1449,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ s->io_buffer[1] & 7);
+ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
+ }
+
+ break;
+@@ -1328,8 +1520,8 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ s->io_buffer[10]);
+ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
++
+ }
+
+ s->atapi_pt.din_xfer_len += 8; // 8 bytes of header
+@@ -1352,8 +1544,7 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ DEBUG_HEXDUMP(s->atapi_pt.request, ATAPI_PACKET_SIZE);
+ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_ILLEGAL_OPCODE, 0, 0x70);
+- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex);
+- return;
++ return;
+ }
+
+ if(s->atapi_pt.dout_xfer_len > 0)
+@@ -1364,162 +1555,6 @@ static void ide_atapi_pt_cmd(IDEState *s)
+ }
+
+ ide_atapi_pt_do_sg_io(s);
+-}
+-
+-static void ide_atapi_pt_cmd_complete(void *arg)
+-{
+- IDEState *s = (IDEState *)arg;
+- int r;
+- uint8_t cmd_code = s->atapi_pt.request[0];
+- uint32_t din_desired;
+-
+- assert(s);
+-
+- /* Get return code of ioctl from worker thread's fd */
+- read(s->atapi_pt.sgio_rfd, &r, sizeof(int));
+-
+- if(s->atapi_pt.result)
+- {
+- if(s->atapi_pt.request[0] == GPCMD_TEST_UNIT_READY &&
+- s->atapi_pt.sense.sense_key == 2 && s->atapi_pt.sense.asc == 0x3A)
+- /* No media, remove exclusivity lock */
+- ide_atapi_pt_ejected();
+-
+- ide_atapi_pt_error(s);
+- return;
+- }
+-
+- if(s->atapi_pt.request[0] == GPCMD_GET_EVENT_STATUS_NOTIFICATION)
+- {
+- struct stat file_stat;
+- int fd;
+-
+- 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 detected\n");
+-
+- fd = open(IDE_ATAPI_PT_NEW_CD_FILE, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+- if(fd < 0) {
+- DEBUG_PRINTF("Error touching new CD file\n");
+- } else {
+- close(fd);
+- utime(IDE_ATAPI_PT_NEW_CD_FILE, NULL);
+- }
+-
+- 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");
+-
+- fd = open(IDE_ATAPI_PT_EJECT_CD_FILE, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+- if(fd < 0) {
+- DEBUG_PRINTF("Error touching eject CD file\n");
+- } else {
+- close(fd);
+- utime(IDE_ATAPI_PT_EJECT_CD_FILE, NULL);
+- }
+-
+- 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;
+-
+- /* Remove exclusivity lock */
+- ide_atapi_pt_ejected();
+- }
+-
+- 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 */
+- 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)
+- {
+- /* 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(s->atapi_pt.din_xfer_len == 0)
+- {
+- // Nothing else to do
+- ide_atapi_cmd_ok(s);
+- return;
+- }
+-
+- din_desired = ide_atapi_pt_get_data_size(ide_atapi_pt_size_din, cmd_code, s->io_buffer);
+-
+- /* din_xfer_len is the size of the buffer provided for the din data,
+- * din_desired in the size of the data the LU tried to send to us. Either one
+- * may be bigger. */
+-
+- if(s->atapi_pt.request[0] == GPCMD_READ_BUFFER)
+- {
+- switch(s->atapi_pt.request[1] & 7)
+- {
+- case 0: // data with header, as specified in atapi_data_sizes table
+- break;
+-
+- case 2: // data only
+- din_desired = s->atapi_pt.din_xfer_len;
+- break;
+
+- case 3: // header only
+- din_desired = 4;
+- break;
+-
+- case 1: // vendor specific
+- default:
+- DEBUG_PRINTF("\e[3;31mIllegal read buffer mode %d\e[m\n",
+- s->io_buffer[1] & 7);
+- ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST,
+- ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70);
+- return;
+- }
+- }
+-
+- if(din_desired == (__u32)-1)
+- din_desired = s->atapi_pt.din_xfer_len;
+-
+- DEBUG_PRINTF("Read %d bytes of data (buffer size %d)\n",
+- din_desired, s->atapi_pt.din_xfer_len);
+-
+- if(s->atapi_pt.din_xfer_len >= 0x80 && din_desired >= 0x80)
+- DEBUG_HEXDUMP(s->io_buffer, 0x80);
+- else if(s->atapi_pt.din_xfer_len < din_desired)
+- DEBUG_HEXDUMP(s->io_buffer, s->atapi_pt.din_xfer_len);
+- else
+- DEBUG_HEXDUMP(s->io_buffer, din_desired);
+-
+- ide_atapi_cmd_reply(s, din_desired, s->atapi_pt.din_xfer_len);
+ }
++
+diff --git a/hw/ide.c b/hw/ide.c
+index 37d0996..8a8c856 100644
+--- a/hw/ide.c
++++ b/hw/ide.c
+@@ -437,8 +437,8 @@ typedef struct ATAPIPassThroughState
+ pthread_t sgio_thread;
+ pthread_mutex_t sgio_mutex;
+ pthread_cond_t sgio_cv;
+- int sgio_rfd;
+- int sgio_wfd;
++ int sgio_worker_fd;
++ int sgio_dispatch_fd;
+ } ATAPIPassThroughState;
+ #endif /* __linux__ */
+