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 #include #include +#include //#include #include #endif @@ -51,6 +52,10 @@ #include #include #endif +#if defined(_BSD) && !defined(CONFIG_COCOA) +#include +#include +#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);