Commit b9788fc4c4974a4871e0ee46b5c06fee105a6aff

Authored by bellard
1 parent 227671c9

cdrom_read_toc support (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1693 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 182 additions and 0 deletions
hw/esp.c
... ... @@ -75,6 +75,148 @@ typedef struct ESPState {
75 75 #define SEQ_0 0x0
76 76 #define SEQ_CD 0x4
77 77  
  78 +/* XXX: stolen from ide.c, move to common ATAPI/SCSI library */
  79 +static void lba_to_msf(uint8_t *buf, int lba)
  80 +{
  81 + lba += 150;
  82 + buf[0] = (lba / 75) / 60;
  83 + buf[1] = (lba / 75) % 60;
  84 + buf[2] = lba % 75;
  85 +}
  86 +
  87 +static inline void cpu_to_ube16(uint8_t *buf, int val)
  88 +{
  89 + buf[0] = val >> 8;
  90 + buf[1] = val;
  91 +}
  92 +
  93 +static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
  94 +{
  95 + buf[0] = val >> 24;
  96 + buf[1] = val >> 16;
  97 + buf[2] = val >> 8;
  98 + buf[3] = val;
  99 +}
  100 +
  101 +/* same toc as bochs. Return -1 if error or the toc length */
  102 +/* XXX: check this */
  103 +static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
  104 +{
  105 + uint8_t *q;
  106 + int len;
  107 +
  108 + if (start_track > 1 && start_track != 0xaa)
  109 + return -1;
  110 + q = buf + 2;
  111 + *q++ = 1; /* first session */
  112 + *q++ = 1; /* last session */
  113 + if (start_track <= 1) {
  114 + *q++ = 0; /* reserved */
  115 + *q++ = 0x14; /* ADR, control */
  116 + *q++ = 1; /* track number */
  117 + *q++ = 0; /* reserved */
  118 + if (msf) {
  119 + *q++ = 0; /* reserved */
  120 + lba_to_msf(q, 0);
  121 + q += 3;
  122 + } else {
  123 + /* sector 0 */
  124 + cpu_to_ube32(q, 0);
  125 + q += 4;
  126 + }
  127 + }
  128 + /* lead out track */
  129 + *q++ = 0; /* reserved */
  130 + *q++ = 0x16; /* ADR, control */
  131 + *q++ = 0xaa; /* track number */
  132 + *q++ = 0; /* reserved */
  133 + if (msf) {
  134 + *q++ = 0; /* reserved */
  135 + lba_to_msf(q, nb_sectors);
  136 + q += 3;
  137 + } else {
  138 + cpu_to_ube32(q, nb_sectors);
  139 + q += 4;
  140 + }
  141 + len = q - buf;
  142 + cpu_to_ube16(buf, len - 2);
  143 + return len;
  144 +}
  145 +
  146 +/* mostly same info as PearPc */
  147 +static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf,
  148 + int session_num)
  149 +{
  150 + uint8_t *q;
  151 + int len;
  152 +
  153 + q = buf + 2;
  154 + *q++ = 1; /* first session */
  155 + *q++ = 1; /* last session */
  156 +
  157 + *q++ = 1; /* session number */
  158 + *q++ = 0x14; /* data track */
  159 + *q++ = 0; /* track number */
  160 + *q++ = 0xa0; /* lead-in */
  161 + *q++ = 0; /* min */
  162 + *q++ = 0; /* sec */
  163 + *q++ = 0; /* frame */
  164 + *q++ = 0;
  165 + *q++ = 1; /* first track */
  166 + *q++ = 0x00; /* disk type */
  167 + *q++ = 0x00;
  168 +
  169 + *q++ = 1; /* session number */
  170 + *q++ = 0x14; /* data track */
  171 + *q++ = 0; /* track number */
  172 + *q++ = 0xa1;
  173 + *q++ = 0; /* min */
  174 + *q++ = 0; /* sec */
  175 + *q++ = 0; /* frame */
  176 + *q++ = 0;
  177 + *q++ = 1; /* last track */
  178 + *q++ = 0x00;
  179 + *q++ = 0x00;
  180 +
  181 + *q++ = 1; /* session number */
  182 + *q++ = 0x14; /* data track */
  183 + *q++ = 0; /* track number */
  184 + *q++ = 0xa2; /* lead-out */
  185 + *q++ = 0; /* min */
  186 + *q++ = 0; /* sec */
  187 + *q++ = 0; /* frame */
  188 + if (msf) {
  189 + *q++ = 0; /* reserved */
  190 + lba_to_msf(q, nb_sectors);
  191 + q += 3;
  192 + } else {
  193 + cpu_to_ube32(q, nb_sectors);
  194 + q += 4;
  195 + }
  196 +
  197 + *q++ = 1; /* session number */
  198 + *q++ = 0x14; /* ADR, control */
  199 + *q++ = 0; /* track number */
  200 + *q++ = 1; /* point */
  201 + *q++ = 0; /* min */
  202 + *q++ = 0; /* sec */
  203 + *q++ = 0; /* frame */
  204 + if (msf) {
  205 + *q++ = 0;
  206 + lba_to_msf(q, 0);
  207 + q += 3;
  208 + } else {
  209 + *q++ = 0;
  210 + *q++ = 0;
  211 + *q++ = 0;
  212 + *q++ = 0;
  213 + }
  214 +
  215 + len = q - buf;
  216 + cpu_to_ube16(buf, len - 2);
  217 + return len;
  218 +}
  219 +
78 220 static void handle_satn(ESPState *s)
79 221 {
80 222 uint8_t buf[32];
... ... @@ -128,6 +270,7 @@ static void handle_satn(ESPState *s)
128 270 memcpy(&s->ti_buf[8], "QEMU ", 8);
129 271 s->ti_buf[2] = 1;
130 272 s->ti_buf[3] = 2;
  273 + s->ti_buf[4] = 32;
131 274 s->ti_dir = 1;
132 275 s->ti_size = 36;
133 276 break;
... ... @@ -190,6 +333,45 @@ static void handle_satn(ESPState *s)
190 333 s->ti_dir = 0;
191 334 break;
192 335 }
  336 + case 0x43:
  337 + {
  338 + int start_track, format, msf, len;
  339 +
  340 + msf = buf[2] & 2;
  341 + format = buf[3] & 0xf;
  342 + start_track = buf[7];
  343 + bdrv_get_geometry(s->bd[target], &nb_sectors);
  344 + DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
  345 + switch(format) {
  346 + case 0:
  347 + len = cdrom_read_toc(nb_sectors, buf, msf, start_track);
  348 + if (len < 0)
  349 + goto error_cmd;
  350 + s->ti_size = len;
  351 + break;
  352 + case 1:
  353 + /* multi session : only a single session defined */
  354 + memset(buf, 0, 12);
  355 + buf[1] = 0x0a;
  356 + buf[2] = 0x01;
  357 + buf[3] = 0x01;
  358 + s->ti_size = 12;
  359 + break;
  360 + case 2:
  361 + len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track);
  362 + if (len < 0)
  363 + goto error_cmd;
  364 + s->ti_size = len;
  365 + break;
  366 + default:
  367 + error_cmd:
  368 + DPRINTF("Read TOC error\n");
  369 + // XXX error handling
  370 + break;
  371 + }
  372 + s->ti_dir = 1;
  373 + break;
  374 + }
193 375 default:
194 376 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
195 377 break;
... ...