[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [patch] transparent CDROM eject/change for Linux hosts
From: |
Manu |
Subject: |
[Qemu-devel] [patch] transparent CDROM eject/change for Linux hosts |
Date: |
Sat, 24 Sep 2005 04:52:05 +0200 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050404 Thunderbird/1.0.2 Mnenhy/0.7.1 |
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);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [patch] transparent CDROM eject/change for Linux hosts,
Manu <=