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 11 Oct 2006 16:11:13 -0000 @@ -26,6 +26,14 @@ here. */ #include +#include "block_int.h" + +#if defined(__linux__) +#include +#include +#endif + +extern BlockDriverState *bdrv_first; static void lba_to_msf(uint8_t *buf, int lba) { @@ -39,45 +47,125 @@ /* XXX: check this */ int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track) { - uint8_t *q; - int len; - - if (start_track > 1 && start_track != 0xaa) - return -1; - q = buf + 2; - *q++ = 1; /* first session */ - *q++ = 1; /* last session */ - if (start_track <= 1) { - *q++ = 0; /* reserved */ - *q++ = 0x14; /* ADR, control */ - *q++ = 1; /* track number */ - *q++ = 0; /* reserved */ - if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, 0); - q += 3; - } else { - /* sector 0 */ - cpu_to_be32wu((uint32_t *)q, 0); - q += 4; - } + uint8_t *q; + int len; + int i; + char * filename = NULL; + + /* Find the device filename */ + BlockDriverState *bs; + + for (bs = bdrv_first; bs != NULL; bs = bs->next) { + if(bs->type == BDRV_TYPE_CDROM) { + /* Looks like -snapshot also applies to CD */ + if(bs->backing_file[0]) { + filename = bs->backing_file; + } else { + filename = bs->filename; + } } - /* lead out track */ - *q++ = 0; /* reserved */ - *q++ = 0x16; /* ADR, control */ - *q++ = 0xaa; /* track number */ - *q++ = 0; /* reserved */ + } + + int fd = 0; +#if defined(__linux__) + fd = open(filename, O_RDONLY); + if(fd<0) { + return -1; + } +#endif + + struct cdrom_tochdr tochdr; +#if defined(__linux__) + if (ioctl(fd, CDROMREADTOCHDR, &tochdr)) { + /* If we have a file and not a real CD-ROM, revert to old behaviour */ + /*FIXME We should rather check bs->drv */ + close(fd); + fd = 0; +#else + { +#endif + tochdr.cdth_trk0 = 1; + tochdr.cdth_trk1 = 1; + + } + + if ((start_track > tochdr.cdth_trk1) && (start_track != 0xaa)) { + if (fd) + close(fd); + return -1; + } + + if (start_track < tochdr.cdth_trk0) + start_track = tochdr.cdth_trk0; + + q = buf + 2; + *q++ = tochdr.cdth_trk0; /* first session */ + *q++ = tochdr.cdth_trk1; /* last session */ + + for (i = start_track; i <= tochdr.cdth_trk1; i++) { + struct cdrom_tocentry tocentry; + +#if defined(__linux__) + tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA; + tocentry.cdte_track = i; + if (fd) { + if (ioctl(fd, CDROMREADTOCENTRY, &tocentry)) { + perror("cdrom: read_toc: READTOCENTRY lead-out failed"); + close(fd); + return -1; + } + } else { +#else + { +#endif + tocentry.cdte_adr = 0; + tocentry.cdte_ctrl = 0x14; + if (msf) { + tocentry.cdte_addr.msf.minute = 0; + tocentry.cdte_addr.msf.second = 2; + tocentry.cdte_addr.msf.frame = 0; + } else { + tocentry.cdte_addr.lba = 0; + } + } + + *q++ = 0; // Reserved + *q++ = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control + *q++ = i; // Track number + *q++ = 0; // Reserved + + // Start address if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, nb_sectors); - q += 3; + *q++ = 0; // reserved + *q++ = tocentry.cdte_addr.msf.minute; + *q++ = tocentry.cdte_addr.msf.second; + *q++ = tocentry.cdte_addr.msf.frame; } else { - cpu_to_be32wu((uint32_t *)q, nb_sectors); - q += 4; + *q++ = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff; + *q++ = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff; + *q++ = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff; + *q++ = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff; } - len = q - buf; - cpu_to_be16wu((uint16_t *)buf, len - 2); - return len; + } + + /* lead out track */ + *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); + q += 3; + } else { + cpu_to_be32wu((uint32_t *)q, nb_sectors); + q += 4; + } + len = q - buf; + cpu_to_be16wu((uint16_t *)buf, len - 2); + if (fd) + close(fd); + return len; } /* mostly same info as PearPc */ @@ -152,5 +240,3 @@ cpu_to_be16wu((uint16_t *)buf, len - 2); return len; } - - 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 11 Oct 2006 16:11:14 -0000 @@ -53,7 +53,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); -static BlockDriverState *bdrv_first; +BlockDriverState *bdrv_first; static BlockDriver *first_drv; #ifdef _WIN32