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 "qemu-common.h"
  30#include "hw/scsi/scsi.h"
  31
  32static 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 */
  42int 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 */
  86int 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