1 /* 2 * QEMU ATAPI CD-ROM Emulator 3 * 4 * Copyright (c) 2006 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 /* ??? Most of the ATAPI emulation is still in ide.c. It should be moved 26 here. */ 27 28 #include "qemu-common.h" 29 #include "hw/scsi/scsi.h" 30 31 static void lba_to_msf(uint8_t *buf, int lba) 32 { 33 lba += 150; 34 buf[0] = (lba / 75) / 60; 35 buf[1] = (lba / 75) % 60; 36 buf[2] = lba % 75; 37 } 38 39 /* same toc as bochs. Return -1 if error or the toc length */ 40 /* XXX: check this */ 41 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track) 42 { 43 uint8_t *q; 44 int len; 45 46 if (start_track > 1 && start_track != 0xaa) 47 return -1; 48 q = buf + 2; 49 *q++ = 1; /* first session */ 50 *q++ = 1; /* last session */ 51 if (start_track <= 1) { 52 *q++ = 0; /* reserved */ 53 *q++ = 0x14; /* ADR, control */ 54 *q++ = 1; /* track number */ 55 *q++ = 0; /* reserved */ 56 if (msf) { 57 *q++ = 0; /* reserved */ 58 lba_to_msf(q, 0); 59 q += 3; 60 } else { 61 /* sector 0 */ 62 cpu_to_be32wu((uint32_t *)q, 0); 63 q += 4; 64 } 65 } 66 /* lead out track */ 67 *q++ = 0; /* reserved */ 68 *q++ = 0x16; /* ADR, control */ 69 *q++ = 0xaa; /* track number */ 70 *q++ = 0; /* reserved */ 71 if (msf) { 72 *q++ = 0; /* reserved */ 73 lba_to_msf(q, nb_sectors); 74 q += 3; 75 } else { 76 cpu_to_be32wu((uint32_t *)q, nb_sectors); 77 q += 4; 78 } 79 len = q - buf; 80 cpu_to_be16wu((uint16_t *)buf, len - 2); 81 return len; 82 } 83 84 /* mostly same info as PearPc */ 85 int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num) 86 { 87 uint8_t *q; 88 int len; 89 90 q = buf + 2; 91 *q++ = 1; /* first session */ 92 *q++ = 1; /* last session */ 93 94 *q++ = 1; /* session number */ 95 *q++ = 0x14; /* data track */ 96 *q++ = 0; /* track number */ 97 *q++ = 0xa0; /* lead-in */ 98 *q++ = 0; /* min */ 99 *q++ = 0; /* sec */ 100 *q++ = 0; /* frame */ 101 *q++ = 0; 102 *q++ = 1; /* first track */ 103 *q++ = 0x00; /* disk type */ 104 *q++ = 0x00; 105 106 *q++ = 1; /* session number */ 107 *q++ = 0x14; /* data track */ 108 *q++ = 0; /* track number */ 109 *q++ = 0xa1; 110 *q++ = 0; /* min */ 111 *q++ = 0; /* sec */ 112 *q++ = 0; /* frame */ 113 *q++ = 0; 114 *q++ = 1; /* last track */ 115 *q++ = 0x00; 116 *q++ = 0x00; 117 118 *q++ = 1; /* session number */ 119 *q++ = 0x14; /* data track */ 120 *q++ = 0; /* track number */ 121 *q++ = 0xa2; /* lead-out */ 122 *q++ = 0; /* min */ 123 *q++ = 0; /* sec */ 124 *q++ = 0; /* frame */ 125 if (msf) { 126 *q++ = 0; /* reserved */ 127 lba_to_msf(q, nb_sectors); 128 q += 3; 129 } else { 130 cpu_to_be32wu((uint32_t *)q, nb_sectors); 131 q += 4; 132 } 133 134 *q++ = 1; /* session number */ 135 *q++ = 0x14; /* ADR, control */ 136 *q++ = 0; /* track number */ 137 *q++ = 1; /* point */ 138 *q++ = 0; /* min */ 139 *q++ = 0; /* sec */ 140 *q++ = 0; /* frame */ 141 if (msf) { 142 *q++ = 0; 143 lba_to_msf(q, 0); 144 q += 3; 145 } else { 146 *q++ = 0; 147 *q++ = 0; 148 *q++ = 0; 149 *q++ = 0; 150 } 151 152 len = q - buf; 153 cpu_to_be16wu((uint16_t *)buf, len - 2); 154 return len; 155 } 156