Commit 38cdea7ccf34ad81a9129b46db914ca3291ad193

Authored by balrog
1 parent 609497ab

Multi-profile DVD-ROM support (Carlo Marcelo Arenas Belon).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3910 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 112 additions and 15 deletions
hw/ide.c
1 1 /*
2   - * QEMU IDE disk and CD-ROM Emulator
  2 + * QEMU IDE disk and CD/DVD-ROM Emulator
3 3 *
4 4 * Copyright (c) 2003 Fabrice Bellard
5 5 * Copyright (c) 2006 Openedhand Ltd.
... ... @@ -284,6 +284,58 @@
284 284 * of MODE_SENSE_POWER_PAGE */
285 285 #define GPMODE_CDROM_PAGE 0x0d
286 286  
  287 +/*
  288 + * Based on values from <linux/cdrom.h> but extending CD_MINS
  289 + * to the maximum common size allowed by the Orange's Book ATIP
  290 + *
  291 + * 90 and 99 min CDs are also available but using them as the
  292 + * upper limit reduces the effectiveness of the heuristic to
  293 + * detect DVDs burned to less than 25% of their maximum capacity
  294 + */
  295 +
  296 +/* Some generally useful CD-ROM information */
  297 +#define CD_MINS 80 /* max. minutes per CD */
  298 +#define CD_SECS 60 /* seconds per minute */
  299 +#define CD_FRAMES 75 /* frames per second */
  300 +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
  301 +#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
  302 +#define CD_MAX_SECTORS (CD_MAX_BYTES / 512)
  303 +
  304 +/*
  305 + * The MMC values are not IDE specific and might need to be moved
  306 + * to a common header if they are also needed for the SCSI emulation
  307 + */
  308 +
  309 +/* Profile list from MMC-6 revision 1 table 91 */
  310 +#define MMC_PROFILE_NONE 0x0000
  311 +#define MMC_PROFILE_CD_ROM 0x0008
  312 +#define MMC_PROFILE_CD_R 0x0009
  313 +#define MMC_PROFILE_CD_RW 0x000A
  314 +#define MMC_PROFILE_DVD_ROM 0x0010
  315 +#define MMC_PROFILE_DVD_R_SR 0x0011
  316 +#define MMC_PROFILE_DVD_RAM 0x0012
  317 +#define MMC_PROFILE_DVD_RW_RO 0x0013
  318 +#define MMC_PROFILE_DVD_RW_SR 0x0014
  319 +#define MMC_PROFILE_DVD_R_DL_SR 0x0015
  320 +#define MMC_PROFILE_DVD_R_DL_JR 0x0016
  321 +#define MMC_PROFILE_DVD_RW_DL 0x0017
  322 +#define MMC_PROFILE_DVD_DDR 0x0018
  323 +#define MMC_PROFILE_DVD_PLUS_RW 0x001A
  324 +#define MMC_PROFILE_DVD_PLUS_R 0x001B
  325 +#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A
  326 +#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B
  327 +#define MMC_PROFILE_BD_ROM 0x0040
  328 +#define MMC_PROFILE_BD_R_SRM 0x0041
  329 +#define MMC_PROFILE_BD_R_RRM 0x0042
  330 +#define MMC_PROFILE_BD_RE 0x0043
  331 +#define MMC_PROFILE_HDDVD_ROM 0x0050
  332 +#define MMC_PROFILE_HDDVD_R 0x0051
  333 +#define MMC_PROFILE_HDDVD_RAM 0x0052
  334 +#define MMC_PROFILE_HDDVD_RW 0x0053
  335 +#define MMC_PROFILE_HDDVD_R_DL 0x0058
  336 +#define MMC_PROFILE_HDDVD_RW_DL 0x005A
  337 +#define MMC_PROFILE_INVALID 0xFFFF
  338 +
287 339 #define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
288 340 #define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
289 341 #define ATAPI_INT_REASON_REL 0x04
... ... @@ -540,7 +592,7 @@ static void ide_atapi_identify(IDEState *s)
540 592 put_le16(p + 21, 512); /* cache size in sectors */
541 593 put_le16(p + 22, 4); /* ecc bytes */
542 594 padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */
543   - padstr((char *)(p + 27), "QEMU CD-ROM", 40); /* model */
  595 + padstr((char *)(p + 27), "QEMU DVD-ROM", 40); /* model */
544 596 put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
545 597 #ifdef USE_DMA_CDROM
546 598 put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
... ... @@ -1290,6 +1342,22 @@ static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
1290 1342 }
1291 1343 }
1292 1344  
  1345 +static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index,
  1346 + uint16_t profile)
  1347 +{
  1348 + uint8_t *buf_profile = buf + 12; /* start of profiles */
  1349 +
  1350 + buf_profile += ((*index) * 4); /* start of indexed profile */
  1351 + cpu_to_ube16 (buf_profile, profile);
  1352 + buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7]));
  1353 +
  1354 + /* each profile adds 4 bytes to the response */
  1355 + (*index)++;
  1356 + buf[11] += 4; /* Additional Length */
  1357 +
  1358 + return 4;
  1359 +}
  1360 +
1293 1361 static void ide_atapi_cmd(IDEState *s)
1294 1362 {
1295 1363 const uint8_t *packet;
... ... @@ -1634,13 +1702,13 @@ static void ide_atapi_cmd(IDEState *s)
1634 1702 buf[6] = 0; /* reserved */
1635 1703 buf[7] = 0; /* reserved */
1636 1704 padstr8(buf + 8, 8, "QEMU");
1637   - padstr8(buf + 16, 16, "QEMU CD-ROM");
  1705 + padstr8(buf + 16, 16, "QEMU DVD-ROM");
1638 1706 padstr8(buf + 32, 4, QEMU_VERSION);
1639 1707 ide_atapi_cmd_reply(s, 36, max_len);
1640 1708 break;
1641 1709 case GPCMD_GET_CONFIGURATION:
1642 1710 {
1643   - uint64_t total_sectors;
  1711 + uint32_t len;
1644 1712  
1645 1713 /* only feature 0 is supported */
1646 1714 if (packet[2] != 0 || packet[3] != 0) {
... ... @@ -1648,17 +1716,46 @@ static void ide_atapi_cmd(IDEState *s)
1648 1716 ASC_INV_FIELD_IN_CMD_PACKET);
1649 1717 break;
1650 1718 }
1651   - memset(buf, 0, 32);
1652   - bdrv_get_geometry(s->bs, &total_sectors);
1653   - buf[3] = 16;
1654   - buf[7] = total_sectors <= 1433600 ? 0x08 : 0x10; /* current profile */
1655   - buf[10] = 0x10 | 0x1;
1656   - buf[11] = 0x08; /* size of profile list */
1657   - buf[13] = 0x10; /* DVD-ROM profile */
1658   - buf[14] = buf[7] == 0x10; /* (in)active */
1659   - buf[17] = 0x08; /* CD-ROM profile */
1660   - buf[18] = buf[7] == 0x08; /* (in)active */
1661   - ide_atapi_cmd_reply(s, 32, 32);
  1719 +
  1720 + /* XXX: could result in alignment problems in some architectures */
  1721 + max_len = ube16_to_cpu(packet + 7);
  1722 + /*
  1723 + * XXX: avoid overflow for io_buffer if max_len is bigger than the
  1724 + * size of that buffer (dimensioned to max number of sectors
  1725 + * to transfer at once)
  1726 + *
  1727 + * Only a problem if the feature/profiles grow exponentially.
  1728 + */
  1729 + if (max_len > 512) /* XXX: assume 1 sector */
  1730 + max_len = 512;
  1731 +
  1732 + memset(buf, 0, max_len);
  1733 + /*
  1734 + * the number of sectors from the media tells us which profile
  1735 + * to use as current. 0 means there is no media
  1736 + *
  1737 + * XXX: fails to detect correctly DVDs with less data burned
  1738 + * than what a CD can hold
  1739 + */
  1740 + if ((s -> nb_sectors)) {
  1741 + if ((s -> nb_sectors > CD_MAX_SECTORS))
  1742 + cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
  1743 + else
  1744 + cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
  1745 + }
  1746 +
  1747 + len = 8; /* header completed */
  1748 + if (max_len > len) {
  1749 + uint8_t index = 0;
  1750 +
  1751 + buf[10] = 0x02 | 0x01; /* persistent and current */
  1752 + len += 4; /* header */
  1753 + len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM);
  1754 + len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM);
  1755 + }
  1756 + cpu_to_ube32(buf, len - 4); /* data length */
  1757 +
  1758 + ide_atapi_cmd_reply(s, len, max_len);
1662 1759 break;
1663 1760 }
1664 1761 default:
... ...