Hi, Please found attached a patch to allow easier transparent eject/change of CDROM when the source of the emulated drive is a physical drive. It still needs improvement ().
diff -ruN qemu-0.7.1/Makefile qemu-0.7.1-cdrom/Makefile --- qemu-0.7.1/Makefile 2005-07-24 20:52:08.000000000 +0200 +++ qemu-0.7.1-cdrom/Makefile 2005-09-23 18:14:05.000000000 +0200 @@ -25,7 +25,7 @@ endif endif -qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c +qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-cdrom-dev.c $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS) dyngen$(EXESUF): dyngen.c diff -ruN qemu-0.7.1/Makefile.target qemu-0.7.1-cdrom/Makefile.target --- qemu-0.7.1/Makefile.target 2005-07-24 20:52:08.000000000 +0200 +++ qemu-0.7.1-cdrom/Makefile.target 2005-09-23 18:22:04.000000000 +0200 @@ -260,7 +260,7 @@ # must use static linking to avoid leaving stuff in virtual address space VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o -VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o +VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-cdrom-dev.o SOUND_HW = sb16.o AUDIODRV = audio.o noaudio.o wavaudio.o diff -ruN qemu-0.7.1/block-cdrom-dev.c qemu-0.7.1-cdrom/block-cdrom-dev.c --- qemu-0.7.1/block-cdrom-dev.c 1970-01-01 01:00:00.000000000 +0100 +++ qemu-0.7.1-cdrom/block-cdrom-dev.c 2005-09-23 18:28:59.000000000 +0200 @@ -0,0 +1,278 @@ +/* + * QEMU Block driver for real CDROM device + * + * Copyright (c) 2005 Emmanuel Varagnat + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * Only works for Linux + */ + + +#if defined(LINUX) || defined(__LINUX__) || defined(__linux__) + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include <linux/cdrom.h> + +#include "vl.h" +#include "block_int.h" + +static int cdrom_dev_open(BlockDriverState *bs, const char *filename); +static void cdrom_dev_close(BlockDriverState *bs); + +typedef struct BDRVCDROMDevState { + int fd; + int cap; +} BDRVCDROMDevState; + +static int cdrom_dev_get_cap(const char *filename) { + /* struct stat fst;*/ + int fd, cap = 0; + + fd = open(filename, O_RDONLY | O_NONBLOCK); + if(fd < 0) { + return -1; + } + + /* + bzero(&fst, sizeof(fst)); + if( fstat(fd, &fst) < 0 ) { + perror("stat"); + close(fd); + return 0; + } + + if( 0 && S_ISBLK(fst.st_mode) != S_IFBLK ) { + close(fd); + return 0; + } + */ + + errno = 0; /* errno can be non zero due to a previous call */ + cap = ioctl(fd, CDROM_GET_CAPABILITY, 0); + if( cap == -1 || ( errno != ENOMEDIUM && errno != 0 ) ) { + return -1; + } + + close(fd); + + return cap; +} + +static int cdrom_dev_is_inserted(BlockDriverState *bs) { + /* BDRVCDROMDevState *s = bs->opaque;*/ + int fd, status; + + fd = open(bs->filename, O_RDONLY | O_NONBLOCK | O_NOCTTY); + if(fd == -1) + return 0; + + errno = 0; + status = ioctl(fd, CDROM_DRIVE_STATUS, 0); + close(fd); + + if( status == CDS_DISC_OK ) { + if( ! bs->inserted ) + bdrv_open(bs, bs->filename, 0); + + return 1; + } + else { + if( bs->inserted ) + bdrv_close(bs); + + return 0; + } +} + +static int cdrom_dev_is_locked(BlockDriverState *bs) { + + return 0; +} + +static void cdrom_dev_change_cb(void *opaque) { +} + +static int cdrom_dev_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + if( cdrom_dev_get_cap(filename) == -1) + return -1; + else + return 100; +} + +static int cdrom_dev_open(BlockDriverState *bs, const char *filename) +{ + BDRVCDROMDevState *s = bs->opaque; + int fd; + int64_t size; +#ifdef _BSD + struct stat sb; +#endif + int cap; + int mask; + + cap = cdrom_dev_get_cap(filename); + if( cap == -1) + return -1; + + s->cap = cap; + /* + for( mask = 0x1; cap && mask <= (1 << (__WORDSIZE-1)); mask = mask<<1 ) { + switch(cap & mask) { + case CDC_CLOSE_TRAY: + break; + case CDC_OPEN_TRAY: + break; + case CDC_LOCK: + break; + case CDC_SELECT_SPEED: + break; + case CDC_SELECT_DISC: + break; + case CDC_MULTI_SESSION: + break; + case CDC_MCN: + break; + case CDC_MEDIA_CHANGED: + break; + case CDC_PLAY_AUDIO: + break; + case CDC_RESET: + break; + case CDC_IOCTLS: + break; + case CDC_DRIVE_STATUS: + break; + case CDC_GENERIC_PACKET: + break; + case CDC_CD_R: + break; + case CDC_CD_RW: + break; + case CDC_DVD: + break; + case CDC_DVD_R: + break; + case CDC_DVD_RAM: + break; + case CDC_MO_DRIVE: + break; + case CDC_MRW: + break; + case CDC_MRW_W: + break; + case CDC_RAM: + break; + default: + break; + } + } + */ + /* By default */ + bs->read_only = 1; + + bs->change_cb = cdrom_dev_change_cb; + bs->is_inserted = cdrom_dev_is_inserted; + bs->is_locked = cdrom_dev_is_locked; + + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) { + s->fd = -1; + bs->inserted = 0; + } + else { + s->fd = fd; + bs->inserted = 1; + +#ifdef _BSD + if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { +#ifdef DIOCGMEDIASIZE + if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) +#endif + size = lseek(fd, 0LL, SEEK_END); + } else +#endif + { + size = lseek(fd, 0, SEEK_END); + } +#ifdef _WIN32 + /* On Windows hosts it can happen that we're unable to get file size + for CD-ROM raw device (it's inherent limitation of the CDFS driver). */ + if (size == -1) + size = LONG_LONG_MAX; +#endif + bs->total_sectors = size / 512; + s->fd = fd; + } + + return 0; +} + +static int cdrom_dev_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVCDROMDevState *s = bs->opaque; + int ret; + + if(s->fd == -1) + return -1; + + lseek(s->fd, sector_num * 512, SEEK_SET); + ret = read(s->fd, buf, nb_sectors * 512); + if (ret != nb_sectors * 512) + return -1; + return 0; +} + +static void cdrom_dev_close(BlockDriverState *bs) +{ + BDRVCDROMDevState *s = bs->opaque; + + if(s->fd != -1) + close(s->fd); +} + +static int cdrom_dev_create(const char *filename, int64_t total_size, + const char *backing_file, int flags) +{ + return -ENOTSUP; +} + +BlockDriver bdrv_cdrom_dev = { + "cdrom-dev", + sizeof(BDRVCDROMDevState), + cdrom_dev_probe, + cdrom_dev_open, + cdrom_dev_read, + NULL, /* write */ + + cdrom_dev_close, + cdrom_dev_create, +}; + +#endif diff -ruN qemu-0.7.1/block.c qemu-0.7.1-cdrom/block.c --- qemu-0.7.1/block.c 2005-07-24 20:52:08.000000000 +0200 +++ qemu-0.7.1-cdrom/block.c 2005-09-23 18:12:52.000000000 +0200 @@ -410,17 +410,28 @@ int bdrv_is_inserted(BlockDriverState *bs) { + if(bs->is_inserted) + bs->inserted = bs->is_inserted(bs); + return bs->inserted; } int bdrv_is_locked(BlockDriverState *bs) { + if(bs->is_locked) + bs->locked = bs->is_locked(bs); + return bs->locked; } void bdrv_set_locked(BlockDriverState *bs, int locked) { - bs->locked = locked; + printf("set_locked\n"); + + if(bs->lock) + bs->locked = bs->lock(locked); + else + bs->locked = locked; } void bdrv_set_change_cb(BlockDriverState *bs, @@ -589,7 +600,7 @@ { BDRVRawState *s = bs->opaque; int ret; - + lseek(s->fd, sector_num * 512, SEEK_SET); ret = read(s->fd, buf, nb_sectors * 512); if (ret != nb_sectors * 512) @@ -640,6 +651,7 @@ raw_open, raw_read, raw_write, + raw_close, raw_create, }; @@ -647,6 +659,9 @@ void bdrv_init(void) { bdrv_register(&bdrv_raw); +#if defined(LINUX) || defined(__LINUX__) || defined(__linux__) + bdrv_register(&bdrv_cdrom_dev); +#endif #ifndef _WIN32 bdrv_register(&bdrv_cow); #endif diff -ruN qemu-0.7.1/block_int.h qemu-0.7.1-cdrom/block_int.h --- qemu-0.7.1/block_int.h 2005-07-24 20:52:08.000000000 +0200 +++ qemu-0.7.1-cdrom/block_int.h 2005-09-23 16:30:34.000000000 +0200 @@ -51,6 +51,9 @@ int encrypted; /* if true, the media is encrypted */ /* event callback when inserting/removing */ void (*change_cb)(void *opaque); + int (*lock)(int); + int (*is_inserted)(BlockDriverState *bs); + int (*is_locked)(BlockDriverState *bs); void *change_opaque; BlockDriver *drv; diff -ruN qemu-0.7.1/vl.h qemu-0.7.1-cdrom/vl.h --- qemu-0.7.1/vl.h 2005-07-24 20:52:08.000000000 +0200 +++ qemu-0.7.1-cdrom/vl.h 2005-09-23 18:14:55.000000000 +0200 @@ -395,6 +395,7 @@ extern BlockDriver bdrv_bochs; extern BlockDriver bdrv_vpc; extern BlockDriver bdrv_vvfat; +extern BlockDriver bdrv_cdrom_dev; void bdrv_init(void); BlockDriver *bdrv_find_format(const char *format_name);
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel