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 * Copyright (c) 2003 Fabrice Bellard 4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2006 Openedhand Ltd. 5 * Copyright (c) 2006 Openedhand Ltd.
@@ -284,6 +284,58 @@ @@ -284,6 +284,58 @@
284 * of MODE_SENSE_POWER_PAGE */ 284 * of MODE_SENSE_POWER_PAGE */
285 #define GPMODE_CDROM_PAGE 0x0d 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 #define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ 339 #define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
288 #define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ 340 #define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
289 #define ATAPI_INT_REASON_REL 0x04 341 #define ATAPI_INT_REASON_REL 0x04
@@ -540,7 +592,7 @@ static void ide_atapi_identify(IDEState *s) @@ -540,7 +592,7 @@ static void ide_atapi_identify(IDEState *s)
540 put_le16(p + 21, 512); /* cache size in sectors */ 592 put_le16(p + 21, 512); /* cache size in sectors */
541 put_le16(p + 22, 4); /* ecc bytes */ 593 put_le16(p + 22, 4); /* ecc bytes */
542 padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */ 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 put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */ 596 put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
545 #ifdef USE_DMA_CDROM 597 #ifdef USE_DMA_CDROM
546 put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */ 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,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 static void ide_atapi_cmd(IDEState *s) 1361 static void ide_atapi_cmd(IDEState *s)
1294 { 1362 {
1295 const uint8_t *packet; 1363 const uint8_t *packet;
@@ -1634,13 +1702,13 @@ static void ide_atapi_cmd(IDEState *s) @@ -1634,13 +1702,13 @@ static void ide_atapi_cmd(IDEState *s)
1634 buf[6] = 0; /* reserved */ 1702 buf[6] = 0; /* reserved */
1635 buf[7] = 0; /* reserved */ 1703 buf[7] = 0; /* reserved */
1636 padstr8(buf + 8, 8, "QEMU"); 1704 padstr8(buf + 8, 8, "QEMU");
1637 - padstr8(buf + 16, 16, "QEMU CD-ROM"); 1705 + padstr8(buf + 16, 16, "QEMU DVD-ROM");
1638 padstr8(buf + 32, 4, QEMU_VERSION); 1706 padstr8(buf + 32, 4, QEMU_VERSION);
1639 ide_atapi_cmd_reply(s, 36, max_len); 1707 ide_atapi_cmd_reply(s, 36, max_len);
1640 break; 1708 break;
1641 case GPCMD_GET_CONFIGURATION: 1709 case GPCMD_GET_CONFIGURATION:
1642 { 1710 {
1643 - uint64_t total_sectors; 1711 + uint32_t len;
1644 1712
1645 /* only feature 0 is supported */ 1713 /* only feature 0 is supported */
1646 if (packet[2] != 0 || packet[3] != 0) { 1714 if (packet[2] != 0 || packet[3] != 0) {
@@ -1648,17 +1716,46 @@ static void ide_atapi_cmd(IDEState *s) @@ -1648,17 +1716,46 @@ static void ide_atapi_cmd(IDEState *s)
1648 ASC_INV_FIELD_IN_CMD_PACKET); 1716 ASC_INV_FIELD_IN_CMD_PACKET);
1649 break; 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 break; 1759 break;
1663 } 1760 }
1664 default: 1761 default: