qemu/hw/block/cdrom.c
<<
>>
Prefs
   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 "hw/scsi/scsi.h"
  30
  31static 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 */
  41int 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            stl_be_p(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        stl_be_p(q, nb_sectors);
  77        q += 4;
  78    }
  79    len = q - buf;
  80    stw_be_p(buf, len - 2);
  81    return len;
  82}
  83
  84/* mostly same info as PearPc */
  85int 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        stl_be_p(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    stw_be_p(buf, len - 2);
 154    return len;
 155}
 156