From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1GcTmM-00026i-LQ for qemu-devel@nongnu.org; Tue, 24 Oct 2006 17:25:46 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1GcTmG-00020R-Km for qemu-devel@nongnu.org; Tue, 24 Oct 2006 17:25:45 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GcTmF-0001zh-O9 for qemu-devel@nongnu.org; Tue, 24 Oct 2006 17:25:39 -0400 Received: from [216.99.193.136] (helo=jade.aracnet.com) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA:32) (Exim 4.52) id 1GcTmE-0008Tp-4O for qemu-devel@nongnu.org; Tue, 24 Oct 2006 17:25:39 -0400 Received: from mail.elsasser.org (jade.elsasser.org [216.99.208.138]) (authenticated bits=0) by jade.aracnet.com (8.13.6/8.12.8) with ESMTP id k9OLPVfu002687 for ; Tue, 24 Oct 2006 14:25:32 -0700 Date: Tue, 24 Oct 2006 14:25:31 -0700 From: Josh Elsasser Message-ID: <20061024212531.GA79722@jade.elsasser.org> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="neYutvxvOLaeuPCA" Content-Disposition: inline Subject: [Qemu-devel] [patch] TOC support for raw cdrom block devices Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --neYutvxvOLaeuPCA Content-Type: multipart/mixed; boundary="x+6KMIRAuhnl3hBn" Content-Disposition: inline --x+6KMIRAuhnl3hBn Content-Type: text/plain; charset=us-ascii Content-Disposition: inline The current raw block drvice code fakes a TOC with one track covering the entire disc. With this patch it attempts to read the TOC from a cdrom device and make that information available to the ide driver when the guest issues an ATAPI READ TOC/PMA/ATIP type 0 (read TOC) command. There is only support for reading the TOC on the BSDs, MacOS X, and Linux, Win32 and other OSes will still fake one large data track. All tracks are reported as data, no attempt was made to support audio tracks. The ATAPI READ TOC/PMA/ATIP type 2 (read full TOC) command is unchanged, I did not have a way of testing it. The purpose of this patch, in case anyone was wondering, was to get the BeOS R5 CD booting in qemu. -jre --x+6KMIRAuhnl3hBn Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="multitrack2.diff" Content-Transfer-Encoding: quoted-printable Index: block-raw.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 =20 //#define DEBUG_FLOPPY =20 @@ -675,6 +680,114 @@ } #endif =20 +static void raw_gettracks(BlockDriverState *bs, int *start, int *end) +{ + BDRVRawState *s =3D bs->opaque; + int fd =3D 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 =3D -1; + *end =3D -1; + ret =3D fd_open(bs); + if (ret < 0) + return; + +#if defined(CDROMREADTOCHDR) + if (!ioctl(fd, CDROMREADTOCHDR, &hdr)) { + *start =3D hdr.cdth_trk0; + *end =3D hdr.cdth_trk1; + } +#endif +#ifdef CDIOREADTOCHEADER + if (!ioctl(fd, CDIOREADTOCHEADER, &hdr)) { + *start =3D hdr.starting_track; + *end =3D hdr.ending_track; + } +#endif +#if defined(DKIOCCDREADTOC) + memset(&hdr, 0, sizeof(hdr)); + hdr.bufferLength =3D sizeof(buf); + hdr.buffer =3D &buf; + if (!ioctl(fd, DKIOCCDREADTOC, &hdr) && sizeof(buf) =3D=3D hdr.bufferL= ength) { + /* buf is the same format as an ATAPI READ TOC/PMA/ATIP response */ + *start =3D buf[2]; + *end =3D buf[3]; + } +#endif + + return; +} + +static int64_t raw_gettrackoff(BlockDriverState *bs, int track) +{ + BDRVRawState *s =3D bs->opaque; + int fd =3D 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 =3D -1; + ret =3D fd_open(bs); + if (ret < 0) + return off; + +#if defined(CDIOREADTOCENTRY) + entry.address_format =3D CD_LBA_FORMAT; + entry.track =3D track; + if (!ioctl(fd, CDIOREADTOCENTRY, &entry)) + off =3D ntohl(entry.entry.addr.lba); +#elif defined(CDIOREADTOCENTRIES) + entry.address_format =3D CD_LBA_FORMAT; + entry.starting_track =3D track; + entry.data_len =3D sizeof(buf); + entry.data =3D &buf; + if (!ioctl(fd, CDIOREADTOCENTRIES, &entry)) + off =3D buf.addr.lba; +#elif defined(CDROMREADTOCENTRY) + entry.cdte_track =3D track; + entry.cdte_format =3D CDROM_LBA; + if (!ioctl(fd, CDROMREADTOCENTRY, &entry)) + off =3D entry.cdte_addr.lba; +#elif defined(DKIOCCDREADTOC) + memset(&hdr, 0, sizeof(hdr)); + hdr.address.track =3D track; + hdr.bufferLength =3D sizeof(buf); + hdr.buffer =3D &buf; + if (!ioctl(fd, DKIOCCDREADTOC, &hdr) && 4 <=3D hdr.bufferLength) { + /* buf is the same format as an ATAPI READ TOC/PMA/ATIP response */ + max =3D OSReadBigInt16(buf, 0) + 2; + if (sizeof(buf) < max) + max =3D sizeof(buf); + for (skip =3D 4; 0 > off && skip + 8 <=3D max; skip +=3D 8) + if(track =3D=3D buf[skip + 2]) + off =3D OSReadBigInt32(buf, skip + 4); + } +#endif + + return off; +} + #if defined(__linux__) =20 static int raw_is_inserted(BlockDriverState *bs) @@ -818,6 +931,8 @@ .bdrv_pread =3D raw_pread, .bdrv_pwrite =3D raw_pwrite, .bdrv_getlength =3D raw_getlength, + .bdrv_gettracks =3D raw_gettracks, + .bdrv_gettrackoff =3D raw_gettrackoff, =20 /* removable device support */ .bdrv_is_inserted =3D raw_is_inserted, Index: block.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 =3D length; } =20 +void bdrv_get_track_count(BlockDriverState *bs, int *start, int *end) +{ + BlockDriver *drv =3D bs->drv; + if (!drv) + *start =3D *end =3D 0; + else if (!drv->bdrv_gettracks) + *start =3D *end =3D 1; + else + drv->bdrv_gettracks(bs, start, end); +} + +int64_t bdrv_get_track_offset(BlockDriverState *bs, int track) +{ + BlockDriver *drv =3D bs->drv; + int64_t ret; + + if (!drv) + ret =3D -1; + else if (!drv->bdrv_gettrackoff) { + if (1 =3D=3D track) + ret =3D 0; + else if(0xaa =3D=3D track) + bdrv_get_geometry(bs, &ret); + else + ret =3D -1; + } + else + ret =3D drv->bdrv_gettrackoff(bs, track); + + return ret; +} + /* force a given boot sector. */ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int s= ize) { Index: block_int.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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,= =20 const uint8_t *buf, int nb_sectors); =20 Index: vl.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 s= ize); /* async block I/O */ @@ -882,7 +884,7 @@ SetIRQFunc *set_irq, void *irq_opaque, int irq); =20 /* 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); =20 /* es1370.c */ Index: hw/cdrom.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 @@ =20 /* 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; - =20 - if (start_track > 1 && start_track !=3D 0xaa) + int start, end, len; + int64_t off; + + bdrv_get_track_count(bs, &start, &end); + if (0 > start || 0 > end) + return -1; + if (0 =3D=3D start_track) + start_track =3D start; + if (start_track < start || (start_track > end && start_track !=3D 0xaa= )) return -1; q =3D buf + 2; - *q++ =3D 1; /* first session */ - *q++ =3D 1; /* last session */ - if (start_track <=3D 1) { + *q++ =3D start; /* first session */ + *q++ =3D end; /* last session */ + while (start_track <=3D end) { + off =3D bdrv_get_track_offset(bs, start_track); + if (0 > off) + return -1; *q++ =3D 0; /* reserved */ - *q++ =3D 0x14; /* ADR, control */ - *q++ =3D 1; /* track number */ + *q++ =3D 0x14; /* ADR, control XXX audio tracks are not supported = */ + *q++ =3D start_track; /* track number */ *q++ =3D 0; /* reserved */ if (msf) { *q++ =3D 0; /* reserved */ - lba_to_msf(q, 0); + lba_to_msf(q, off); q +=3D 3; } else { - /* sector 0 */ - cpu_to_be32wu((uint32_t *)q, 0); + /* start sector */ + cpu_to_be32wu((uint32_t *)q, off); q +=3D 4; } + start_track++; } /* lead out track */ + off =3D bdrv_get_track_offset(bs, 0xaa); + if (0 > off) + return -1; *q++ =3D 0; /* reserved */ *q++ =3D 0x16; /* ADR, control */ *q++ =3D 0xaa; /* track number */ *q++ =3D 0; /* reserved */ if (msf) { *q++ =3D 0; /* reserved */ - lba_to_msf(q, nb_sectors); + lba_to_msf(q, off); q +=3D 3; } else { - cpu_to_be32wu((uint32_t *)q, nb_sectors); + cpu_to_be32wu((uint32_t *)q, off); q +=3D 4; } len =3D q - buf; Index: hw/ide.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 =3D packet[6]; switch(format) { case 0: - len =3D cdrom_read_toc(total_sectors, buf, msf, start_trac= k); + len =3D cdrom_read_toc(s->bs, buf, msf, start_track); if (len < 0) goto error_cmd; ide_atapi_cmd_reply(s, len, max_len); --x+6KMIRAuhnl3hBn-- --neYutvxvOLaeuPCA Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (FreeBSD) iD8DBQFFPoTLz9XqP7gz/VARAhPAAJ473Rt/ZbgsdHcS1+f/DnschvuNXACfftt5 mF7yxQMAwlxrpH+hvvq5Moc= =GsA3 -----END PGP SIGNATURE----- --neYutvxvOLaeuPCA--