From: Manu <qemu-devel@guzu.net>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [patch] transparent CDROM eject/change for Linux hosts
Date: Sat, 24 Sep 2005 04:52:05 +0200 [thread overview]
Message-ID: <4334BF55.6090908@guzu.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 177 bytes --]
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 ().
[-- Attachment #2: qemu-0.7.1-cdrom-r1.patch --]
[-- Type: text/x-patch, Size: 10019 bytes --]
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);
reply other threads:[~2005-09-24 0:03 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4334BF55.6090908@guzu.net \
--to=qemu-devel@guzu.net \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.