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/osdep.h" 29 #include "qemu-common.h" 30 #include "hw/scsi/scsi.h" 31 32 static void lba_to_msf(uint8_t *buf, int lba) 33 { 34 lba += 150; 35 buf[0] = (lba / 75) / 60; 36 buf[1] = (lba / 75) % 60; 37 buf[2] = lba % 75; 38 } 39 40 /* same toc as bochs. Return -1 if error or the toc length */ 41 /* XXX: check this */ 42 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track) 43 { 44 uint8_t *q; 45 int len; 46 47 if (start_track > 1 && start_track != 0xaa) 48 return -1; 49 q = buf + 2; 50 *q++ = 1; /* first session */ 51 *q++ = 1; /* last session */ 52 if (start_track <= 1) { 53 *q++ = 0; /* reserved */ 54 *q++ = 0x14; /* ADR, control */ 55 *q++ = 1; /* track number */ 56 *q++ = 0; /* reserved */ 57 if (msf) { 58 *q++ = 0; /* reserved */ 59 lba_to_msf(q, 0); 60 q += 3; 61 } else { 62 /* sector 0 */ 63 stl_be_p(q, 0); 64 q += 4; 65 } 66 } 67 /* lead out track */ 68 *q++ = 0; /* reserved */ 69 *q++ = 0x16; /* ADR, control */ 70 *q++ = 0xaa; /* track number */ 71 *q++ = 0; /* reserved */ 72 if (msf) { 73 *q++ = 0; /* reserved */ 74 lba_to_msf(q, nb_sectors); 75 q += 3; 76 } else { 77 stl_be_p(q, nb_sectors); 78 q += 4; 79 } 80 len = q - buf; 81 stw_be_p(buf, len - 2); 82 return len; 83 } 84 85 /* mostly same info as PearPc */ 86 int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num) 87 { 88 uint8_t *q; 89 int len; 90 91 q = buf + 2; 92 *q++ = 1; /* first session */ 93 *q++ = 1; /* last session */ 94 95 *q++ = 1; /* session number */ 96 *q++ = 0x14; /* data track */ 97 *q++ = 0; /* track number */ 98 *q++ = 0xa0; /* lead-in */ 99 *q++ = 0; /* min */ 100 *q++ = 0; /* sec */ 101 *q++ = 0; /* frame */ 102 *q++ = 0; 103 *q++ = 1; /* first track */ 104 *q++ = 0x00; /* disk type */ 105 *q++ = 0x00; 106 107 *q++ = 1; /* session number */ 108 *q++ = 0x14; /* data track */ 109 *q++ = 0; /* track number */ 110 *q++ = 0xa1; 111 *q++ = 0; /* min */ 112 *q++ = 0; /* sec */ 113 *q++ = 0; /* frame */ 114 *q++ = 0; 115 *q++ = 1; /* last track */ 116 *q++ = 0x00; 117 *q++ = 0x00; 118 119 *q++ = 1; /* session number */ 120 *q++ = 0x14; /* data track */ 121 *q++ = 0; /* track number */ 122 *q++ = 0xa2; /* lead-out */ 123 *q++ = 0; /* min */ 124 *q++ = 0; /* sec */ 125 *q++ = 0; /* frame */ 126 if (msf) { 127 *q++ = 0; /* reserved */ 128 lba_to_msf(q, nb_sectors); 129 q += 3; 130 } else { 131 stl_be_p(q, nb_sectors); 132 q += 4; 133 } 134 135 *q++ = 1; /* session number */ 136 *q++ = 0x14; /* ADR, control */ 137 *q++ = 0; /* track number */ 138 *q++ = 1; /* point */ 139 *q++ = 0; /* min */ 140 *q++ = 0; /* sec */ 141 *q++ = 0; /* frame */ 142 if (msf) { 143 *q++ = 0; 144 lba_to_msf(q, 0); 145 q += 3; 146 } else { 147 *q++ = 0; 148 *q++ = 0; 149 *q++ = 0; 150 *q++ = 0; 151 } 152 153 len = q - buf; 154 stw_be_p(buf, len - 2); 155 return len; 156 } 157