@@ -107,20 +107,24 @@
int fd_got_error;
int fd_media_changed;
#endif
uint8_t* aligned_buf;
} BDRVRawState;
static int posix_aio_init(void);
static int fd_open(BlockDriverState *bs);
+#if defined(__linux__)
+int cdrom_reopen(BlockDriverState *bs);
+#endif
+
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
int fd, open_flags, ret;
posix_aio_init();
s->lseek_err_cnt = 0;
open_flags = O_BINARY;
@@ -212,29 +216,32 @@
if (ret == count)
goto label__raw_read__success;
DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
"] read failed %d : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, ret, errno, strerror(errno));
/* Try harder for CDrom. */
if (bs->type == BDRV_TYPE_CDROM) {
- lseek(s->fd, offset, SEEK_SET);
- ret = read(s->fd, buf, count);
- if (ret == count)
- goto label__raw_read__success;
- lseek(s->fd, offset, SEEK_SET);
- ret = read(s->fd, buf, count);
- if (ret == count)
+ int i;
+ for (i = 0; i < 2; ++i) {
+#if defined(__linux__)
+ ret = cdrom_reopen(bs);
+ if (ret < 0)
goto label__raw_read__success;
-
+#endif
+ lseek(s->fd, offset, SEEK_SET);
+ ret = read(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_read__success;
+ }
DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
"] retry read failed %d : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, ret, errno, strerror(errno));
}
label__raw_read__success:
return ret;
}
@@ -1025,20 +1032,27 @@
printf("Floppy opened\n");
#endif
}
if (!last_media_present)
s->fd_media_changed = 1;
s->fd_open_time = qemu_get_clock(rt_clock);
s->fd_got_error = 0;
return 0;
}
+int cdrom_reopen(BlockDriverState *bs)
+{
+ /* mimics a 'change' monitor command - without the eject */
+ bdrv_close(bs);
+ return bdrv_open2(bs, bs->filename, 0, bs->drv);
+}
+
static int raw_is_inserted(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int ret;
switch(s->type) {
case FTYPE_CD:
ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
if (ret == CDS_DISC_OK)
return 1;
@@ -29,20 +29,24 @@
#include "pcmcia.h"
#include "block.h"
#include "block_int.h"
#include "qemu-timer.h"
#include "sysemu.h"
#include "ppc_mac.h"
#include "sh.h"
#include <console.h>
#include <syslog.h>
+#if defined(__linux__)
+int cdrom_reopen(BlockDriverState *bs);
+#endif
+
/* debug IDE devices */
//#define DEBUG_IDE
//#define DEBUG_IDE_ATAPI
//#define DEBUG_AIO
#define USE_DMA_CDROM
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define INDEX_STAT 0x02
#define ECC_STAT 0x04 /* Corrected error */
@@ -1363,20 +1367,25 @@
/* ATAPI DMA support */
/* XXX: handle read errors */
static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
{
BMDMAState *bm = opaque;
IDEState *s = bm->ide_if;
int data_offset, n;
if (ret < 0) {
+#if defined(__linux__)
+ /* on EIO failure try re-opening file */
+ if (ret == -EIO)
+ (void) cdrom_reopen(s->bs);
+#endif
ide_atapi_io_error(s, ret);
goto eot;
}
if (s->io_buffer_size > 0) {
/*
* For a cdrom read sector command (s->lba != -1),
* adjust the lba for the next s->io_buffer_size chunk
* and dma the current chunk.
* For a command != read (s->lba == -1), just transfer