* [Qemu-devel] Re: [patch] TOC support for raw cdrom block devices
2006-10-23 19:30 [Qemu-devel] [patch] TOC support for raw cdrom block devices Josh Elsasser
@ 2006-10-23 19:34 ` Josh Elsasser
0 siblings, 0 replies; 2+ messages in thread
From: Josh Elsasser @ 2006-10-23 19:34 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1.1: Type: text/plain, Size: 56 bytes --]
How about I actually attach the patch this time?
-jre
[-- Attachment #1.2: multitrack2.diff --]
[-- Type: text/plain, Size: 10468 bytes --]
Index: block-raw.c
===================================================================
RCS file: /sources/qemu/qemu/block-raw.c,v
retrieving revision 1.10
diff -u -r1.10 block-raw.c
--- block-raw.c 3 Sep 2006 12:08:37 -0000 1.10
+++ block-raw.c 18 Oct 2006 23:17:33 -0000
@@ -39,6 +39,7 @@
#include <IOKit/storage/IOMediaBSDClient.h>
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IOCDMedia.h>
+#include <IOKit/storage/IOCDMediaBSDClient.h>
//#include <IOKit/storage/IOCDTypes.h>
#include <CoreFoundation/CoreFoundation.h>
#endif
@@ -51,6 +52,10 @@
#include <linux/cdrom.h>
#include <linux/fd.h>
#endif
+#if defined(_BSD) && !defined(CONFIG_COCOA)
+#include <sys/cdio.h>
+#include <arpa/inet.h>
+#endif
//#define DEBUG_FLOPPY
@@ -675,6 +680,114 @@
}
#endif
+static void raw_gettracks(BlockDriverState *bs, int *start, int *end)
+{
+ BDRVRawState *s = bs->opaque;
+ int fd = s->fd;
+#ifdef CDROMREADTOCHDR
+ struct cdrom_tochdr hdr;
+#endif
+#ifdef CDIOREADTOCHEADER
+ struct ioc_toc_header hdr;
+#endif
+#ifdef DKIOCCDREADTOC
+ dk_cd_read_toc_t hdr;
+ uint8_t buf[4];
+#endif
+ int ret;
+
+ *start = -1;
+ *end = -1;
+ ret = fd_open(bs);
+ if (ret < 0)
+ return;
+
+#if defined(CDROMREADTOCHDR)
+ if (!ioctl(fd, CDROMREADTOCHDR, &hdr)) {
+ *start = hdr.cdth_trk0;
+ *end = hdr.cdth_trk1;
+ }
+#endif
+#ifdef CDIOREADTOCHEADER
+ if (!ioctl(fd, CDIOREADTOCHEADER, &hdr)) {
+ *start = hdr.starting_track;
+ *end = hdr.ending_track;
+ }
+#endif
+#if defined(DKIOCCDREADTOC)
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.bufferLength = sizeof(buf);
+ hdr.buffer = &buf;
+ if (!ioctl(fd, DKIOCCDREADTOC, &hdr) && sizeof(buf) == hdr.bufferLength) {
+ /* buf is the same format as an ATAPI READ TOC/PMA/ATIP response */
+ *start = buf[2];
+ *end = buf[3];
+ }
+#endif
+
+ return;
+}
+
+static int64_t raw_gettrackoff(BlockDriverState *bs, int track)
+{
+ BDRVRawState *s = bs->opaque;
+ int fd = s->fd;
+ int64_t off;
+#if defined(CDIOREADTOCENTRY)
+ struct ioc_read_toc_single_entry entry;
+#elif defined(CDIOREADTOCENTRIES)
+ struct ioc_read_toc_entry entry;
+ struct cd_toc_entry buf;
+#elif defined(CDROMREADTOCENTRY)
+ struct cdrom_tocentry entry;
+#elif defined(DKIOCCDREADTOC)
+ dk_cd_read_toc_t hdr;
+ uint8_t buf[804];
+ int skip, max;
+#endif
+ int ret;
+
+ off = -1;
+ ret = fd_open(bs);
+ if (ret < 0)
+ return off;
+
+#if defined(CDIOREADTOCENTRY)
+ entry.address_format = CD_LBA_FORMAT;
+ entry.track = track;
+ if (!ioctl(fd, CDIOREADTOCENTRY, &entry))
+ off = ntohl(entry.entry.addr.lba);
+#elif defined(CDIOREADTOCENTRIES)
+ entry.address_format = CD_LBA_FORMAT;
+ entry.starting_track = track;
+ entry.data_len = sizeof(buf);
+ entry.data = &buf;
+ if (!ioctl(fd, CDIOREADTOCENTRIES, &entry))
+ off = buf.addr.lba;
+#elif defined(CDROMREADTOCENTRY)
+ entry.cdte_track = track;
+ entry.cdte_format = CDROM_LBA;
+ if (!ioctl(fd, CDROMREADTOCENTRY, &entry))
+ off = entry.cdte_addr.lba;
+#elif defined(DKIOCCDREADTOC)
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.address.track = track;
+ hdr.bufferLength = sizeof(buf);
+ hdr.buffer = &buf;
+ if (!ioctl(fd, DKIOCCDREADTOC, &hdr) && 4 <= hdr.bufferLength) {
+ /* buf is the same format as an ATAPI READ TOC/PMA/ATIP response */
+ max = OSReadBigInt16(buf, 0) + 2;
+ if (sizeof(buf) < max)
+ max = sizeof(buf);
+ for (skip = 4; 0 > off && skip + 8 <= max; skip += 8)
+ if(track == buf[skip + 2])
+ off = OSReadBigInt32(buf, skip + 4);
+ }
+#endif
+
+ return off;
+}
+
#if defined(__linux__)
static int raw_is_inserted(BlockDriverState *bs)
@@ -818,6 +931,8 @@
.bdrv_pread = raw_pread,
.bdrv_pwrite = raw_pwrite,
.bdrv_getlength = raw_getlength,
+ .bdrv_gettracks = raw_gettracks,
+ .bdrv_gettrackoff = raw_gettrackoff,
/* removable device support */
.bdrv_is_inserted = raw_is_inserted,
Index: block.c
===================================================================
RCS file: /sources/qemu/qemu/block.c,v
retrieving revision 1.37
diff -u -r1.37 block.c
--- block.c 24 Aug 2006 19:53:37 -0000 1.37
+++ block.c 18 Oct 2006 23:17:34 -0000
@@ -705,6 +705,38 @@
*nb_sectors_ptr = length;
}
+void bdrv_get_track_count(BlockDriverState *bs, int *start, int *end)
+{
+ BlockDriver *drv = bs->drv;
+ if (!drv)
+ *start = *end = 0;
+ else if (!drv->bdrv_gettracks)
+ *start = *end = 1;
+ else
+ drv->bdrv_gettracks(bs, start, end);
+}
+
+int64_t bdrv_get_track_offset(BlockDriverState *bs, int track)
+{
+ BlockDriver *drv = bs->drv;
+ int64_t ret;
+
+ if (!drv)
+ ret = -1;
+ else if (!drv->bdrv_gettrackoff) {
+ if (1 == track)
+ ret = 0;
+ else if(0xaa == track)
+ bdrv_get_geometry(bs, &ret);
+ else
+ ret = -1;
+ }
+ else
+ ret = drv->bdrv_gettrackoff(bs, track);
+
+ return ret;
+}
+
/* force a given boot sector. */
void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
{
Index: block_int.h
===================================================================
RCS file: /sources/qemu/qemu/block_int.h,v
retrieving revision 1.10
diff -u -r1.10 block_int.h
--- block_int.h 19 Aug 2006 11:45:59 -0000 1.10
+++ block_int.h 18 Oct 2006 23:17:34 -0000
@@ -58,6 +58,8 @@
const uint8_t *buf, int count);
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
int64_t (*bdrv_getlength)(BlockDriverState *bs);
+ void (*bdrv_gettracks)(BlockDriverState *bs, int *start, int *end);
+ int64_t (*bdrv_gettrackoff)(BlockDriverState *bs, int track);
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
Index: vl.h
===================================================================
RCS file: /sources/qemu/qemu/vl.h,v
retrieving revision 1.154
diff -u -r1.154 vl.h
--- vl.h 24 Sep 2006 18:49:43 -0000 1.154
+++ vl.h 18 Oct 2006 23:17:35 -0000
@@ -564,6 +564,8 @@
int bdrv_truncate(BlockDriverState *bs, int64_t offset);
int64_t bdrv_getlength(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
+void bdrv_get_track_count(BlockDriverState *bs, int *start, int *end);
+int64_t bdrv_get_track_offset(BlockDriverState *bs, int track);
int bdrv_commit(BlockDriverState *bs);
void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
/* async block I/O */
@@ -882,7 +884,7 @@
SetIRQFunc *set_irq, void *irq_opaque, int irq);
/* cdrom.c */
-int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
+int cdrom_read_toc(BlockDriverState *bs, uint8_t *buf, int msf, int start_track);
int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
/* es1370.c */
Index: hw/cdrom.c
===================================================================
RCS file: /sources/qemu/qemu/hw/cdrom.c,v
retrieving revision 1.1
diff -u -r1.1 cdrom.c
--- hw/cdrom.c 25 May 2006 23:58:51 -0000 1.1
+++ hw/cdrom.c 18 Oct 2006 23:17:35 -0000
@@ -37,42 +37,55 @@
/* same toc as bochs. Return -1 if error or the toc length */
/* XXX: check this */
-int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
+int cdrom_read_toc(BlockDriverState *bs, uint8_t *buf, int msf, int start_track)
{
uint8_t *q;
- int len;
-
- if (start_track > 1 && start_track != 0xaa)
+ int start, end, len;
+ int64_t off;
+
+ bdrv_get_track_count(bs, &start, &end);
+ if (0 > start || 0 > end)
+ return -1;
+ if (0 == start_track)
+ start_track = start;
+ if (start_track < start || (start_track > end && start_track != 0xaa))
return -1;
q = buf + 2;
- *q++ = 1; /* first session */
- *q++ = 1; /* last session */
- if (start_track <= 1) {
+ *q++ = start; /* first session */
+ *q++ = end; /* last session */
+ while (start_track <= end) {
+ off = bdrv_get_track_offset(bs, start_track);
+ if (0 > off)
+ return -1;
*q++ = 0; /* reserved */
- *q++ = 0x14; /* ADR, control */
- *q++ = 1; /* track number */
+ *q++ = 0x14; /* ADR, control XXX audio tracks are not supported */
+ *q++ = start_track; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
- lba_to_msf(q, 0);
+ lba_to_msf(q, off);
q += 3;
} else {
- /* sector 0 */
- cpu_to_be32wu((uint32_t *)q, 0);
+ /* start sector */
+ cpu_to_be32wu((uint32_t *)q, off);
q += 4;
}
+ start_track++;
}
/* lead out track */
+ off = bdrv_get_track_offset(bs, 0xaa);
+ if (0 > off)
+ return -1;
*q++ = 0; /* reserved */
*q++ = 0x16; /* ADR, control */
*q++ = 0xaa; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
- lba_to_msf(q, nb_sectors);
+ lba_to_msf(q, off);
q += 3;
} else {
- cpu_to_be32wu((uint32_t *)q, nb_sectors);
+ cpu_to_be32wu((uint32_t *)q, off);
q += 4;
}
len = q - buf;
Index: hw/ide.c
===================================================================
RCS file: /sources/qemu/qemu/hw/ide.c,v
retrieving revision 1.48
diff -u -r1.48 ide.c
--- hw/ide.c 19 Aug 2006 11:44:21 -0000 1.48
+++ hw/ide.c 18 Oct 2006 23:17:37 -0000
@@ -1415,7 +1415,7 @@
start_track = packet[6];
switch(format) {
case 0:
- len = cdrom_read_toc(total_sectors, buf, msf, start_track);
+ len = cdrom_read_toc(s->bs, buf, msf, start_track);
if (len < 0)
goto error_cmd;
ide_atapi_cmd_reply(s, len, max_len);
[-- Attachment #2: Type: application/pgp-signature, Size: 187 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread