xref: /openbmc/qemu/hw/block/cdrom.c (revision 59c58f96b270f5edd4ad10954c3a96556cb3a728)
149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini  * QEMU ATAPI CD-ROM Emulator
349ab747fSPaolo Bonzini  *
449ab747fSPaolo Bonzini  * Copyright (c) 2006 Fabrice Bellard
549ab747fSPaolo Bonzini  *
649ab747fSPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
749ab747fSPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
849ab747fSPaolo Bonzini  * in the Software without restriction, including without limitation the rights
949ab747fSPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1049ab747fSPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
1149ab747fSPaolo Bonzini  * furnished to do so, subject to the following conditions:
1249ab747fSPaolo Bonzini  *
1349ab747fSPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
1449ab747fSPaolo Bonzini  * all copies or substantial portions of the Software.
1549ab747fSPaolo Bonzini  *
1649ab747fSPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1749ab747fSPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1849ab747fSPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1949ab747fSPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2049ab747fSPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2149ab747fSPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2249ab747fSPaolo Bonzini  * THE SOFTWARE.
2349ab747fSPaolo Bonzini  */
2449ab747fSPaolo Bonzini 
2549ab747fSPaolo Bonzini /* ??? Most of the ATAPI emulation is still in ide.c.  It should be moved
2649ab747fSPaolo Bonzini    here.  */
2749ab747fSPaolo Bonzini 
28*80c71a24SPeter Maydell #include "qemu/osdep.h"
2949ab747fSPaolo Bonzini #include "hw/scsi/scsi.h"
3049ab747fSPaolo Bonzini 
lba_to_msf(uint8_t * buf,int lba)3149ab747fSPaolo Bonzini static void lba_to_msf(uint8_t *buf, int lba)
3249ab747fSPaolo Bonzini {
3349ab747fSPaolo Bonzini     lba += 150;
3449ab747fSPaolo Bonzini     buf[0] = (lba / 75) / 60;
3549ab747fSPaolo Bonzini     buf[1] = (lba / 75) % 60;
3649ab747fSPaolo Bonzini     buf[2] = lba % 75;
3749ab747fSPaolo Bonzini }
3849ab747fSPaolo Bonzini 
3949ab747fSPaolo Bonzini /* same toc as bochs. Return -1 if error or the toc length */
4049ab747fSPaolo Bonzini /* XXX: check this */
cdrom_read_toc(int nb_sectors,uint8_t * buf,int msf,int start_track)4149ab747fSPaolo Bonzini int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
4249ab747fSPaolo Bonzini {
4349ab747fSPaolo Bonzini     uint8_t *q;
4449ab747fSPaolo Bonzini     int len;
4549ab747fSPaolo Bonzini 
4649ab747fSPaolo Bonzini     if (start_track > 1 && start_track != 0xaa)
4749ab747fSPaolo Bonzini         return -1;
4849ab747fSPaolo Bonzini     q = buf + 2;
4949ab747fSPaolo Bonzini     *q++ = 1; /* first session */
5049ab747fSPaolo Bonzini     *q++ = 1; /* last session */
5149ab747fSPaolo Bonzini     if (start_track <= 1) {
5249ab747fSPaolo Bonzini         *q++ = 0; /* reserved */
5349ab747fSPaolo Bonzini         *q++ = 0x14; /* ADR, control */
5449ab747fSPaolo Bonzini         *q++ = 1;    /* track number */
5549ab747fSPaolo Bonzini         *q++ = 0; /* reserved */
5649ab747fSPaolo Bonzini         if (msf) {
5749ab747fSPaolo Bonzini             *q++ = 0; /* reserved */
5849ab747fSPaolo Bonzini             lba_to_msf(q, 0);
5949ab747fSPaolo Bonzini             q += 3;
6049ab747fSPaolo Bonzini         } else {
6149ab747fSPaolo Bonzini             /* sector 0 */
626bd194abSPeter Maydell             stl_be_p(q, 0);
6349ab747fSPaolo Bonzini             q += 4;
6449ab747fSPaolo Bonzini         }
6549ab747fSPaolo Bonzini     }
6649ab747fSPaolo Bonzini     /* lead out track */
6749ab747fSPaolo Bonzini     *q++ = 0; /* reserved */
6849ab747fSPaolo Bonzini     *q++ = 0x16; /* ADR, control */
6949ab747fSPaolo Bonzini     *q++ = 0xaa; /* track number */
7049ab747fSPaolo Bonzini     *q++ = 0; /* reserved */
7149ab747fSPaolo Bonzini     if (msf) {
7249ab747fSPaolo Bonzini         *q++ = 0; /* reserved */
7349ab747fSPaolo Bonzini         lba_to_msf(q, nb_sectors);
7449ab747fSPaolo Bonzini         q += 3;
7549ab747fSPaolo Bonzini     } else {
766bd194abSPeter Maydell         stl_be_p(q, nb_sectors);
7749ab747fSPaolo Bonzini         q += 4;
7849ab747fSPaolo Bonzini     }
7949ab747fSPaolo Bonzini     len = q - buf;
80d8ee2591SPeter Maydell     stw_be_p(buf, len - 2);
8149ab747fSPaolo Bonzini     return len;
8249ab747fSPaolo Bonzini }
8349ab747fSPaolo Bonzini 
8449ab747fSPaolo Bonzini /* mostly same info as PearPc */
cdrom_read_toc_raw(int nb_sectors,uint8_t * buf,int msf,int session_num)8549ab747fSPaolo Bonzini int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num)
8649ab747fSPaolo Bonzini {
8749ab747fSPaolo Bonzini     uint8_t *q;
8849ab747fSPaolo Bonzini     int len;
8949ab747fSPaolo Bonzini 
9049ab747fSPaolo Bonzini     q = buf + 2;
9149ab747fSPaolo Bonzini     *q++ = 1; /* first session */
9249ab747fSPaolo Bonzini     *q++ = 1; /* last session */
9349ab747fSPaolo Bonzini 
9449ab747fSPaolo Bonzini     *q++ = 1; /* session number */
9549ab747fSPaolo Bonzini     *q++ = 0x14; /* data track */
9649ab747fSPaolo Bonzini     *q++ = 0; /* track number */
9749ab747fSPaolo Bonzini     *q++ = 0xa0; /* lead-in */
9849ab747fSPaolo Bonzini     *q++ = 0; /* min */
9949ab747fSPaolo Bonzini     *q++ = 0; /* sec */
10049ab747fSPaolo Bonzini     *q++ = 0; /* frame */
10149ab747fSPaolo Bonzini     *q++ = 0;
10249ab747fSPaolo Bonzini     *q++ = 1; /* first track */
10349ab747fSPaolo Bonzini     *q++ = 0x00; /* disk type */
10449ab747fSPaolo Bonzini     *q++ = 0x00;
10549ab747fSPaolo Bonzini 
10649ab747fSPaolo Bonzini     *q++ = 1; /* session number */
10749ab747fSPaolo Bonzini     *q++ = 0x14; /* data track */
10849ab747fSPaolo Bonzini     *q++ = 0; /* track number */
10949ab747fSPaolo Bonzini     *q++ = 0xa1;
11049ab747fSPaolo Bonzini     *q++ = 0; /* min */
11149ab747fSPaolo Bonzini     *q++ = 0; /* sec */
11249ab747fSPaolo Bonzini     *q++ = 0; /* frame */
11349ab747fSPaolo Bonzini     *q++ = 0;
11449ab747fSPaolo Bonzini     *q++ = 1; /* last track */
11549ab747fSPaolo Bonzini     *q++ = 0x00;
11649ab747fSPaolo Bonzini     *q++ = 0x00;
11749ab747fSPaolo Bonzini 
11849ab747fSPaolo Bonzini     *q++ = 1; /* session number */
11949ab747fSPaolo Bonzini     *q++ = 0x14; /* data track */
12049ab747fSPaolo Bonzini     *q++ = 0; /* track number */
12149ab747fSPaolo Bonzini     *q++ = 0xa2; /* lead-out */
12249ab747fSPaolo Bonzini     *q++ = 0; /* min */
12349ab747fSPaolo Bonzini     *q++ = 0; /* sec */
12449ab747fSPaolo Bonzini     *q++ = 0; /* frame */
12549ab747fSPaolo Bonzini     if (msf) {
12649ab747fSPaolo Bonzini         *q++ = 0; /* reserved */
12749ab747fSPaolo Bonzini         lba_to_msf(q, nb_sectors);
12849ab747fSPaolo Bonzini         q += 3;
12949ab747fSPaolo Bonzini     } else {
1306bd194abSPeter Maydell         stl_be_p(q, nb_sectors);
13149ab747fSPaolo Bonzini         q += 4;
13249ab747fSPaolo Bonzini     }
13349ab747fSPaolo Bonzini 
13449ab747fSPaolo Bonzini     *q++ = 1; /* session number */
13549ab747fSPaolo Bonzini     *q++ = 0x14; /* ADR, control */
13649ab747fSPaolo Bonzini     *q++ = 0;    /* track number */
13749ab747fSPaolo Bonzini     *q++ = 1;    /* point */
13849ab747fSPaolo Bonzini     *q++ = 0; /* min */
13949ab747fSPaolo Bonzini     *q++ = 0; /* sec */
14049ab747fSPaolo Bonzini     *q++ = 0; /* frame */
14149ab747fSPaolo Bonzini     if (msf) {
14249ab747fSPaolo Bonzini         *q++ = 0;
14349ab747fSPaolo Bonzini         lba_to_msf(q, 0);
14449ab747fSPaolo Bonzini         q += 3;
14549ab747fSPaolo Bonzini     } else {
14649ab747fSPaolo Bonzini         *q++ = 0;
14749ab747fSPaolo Bonzini         *q++ = 0;
14849ab747fSPaolo Bonzini         *q++ = 0;
14949ab747fSPaolo Bonzini         *q++ = 0;
15049ab747fSPaolo Bonzini     }
15149ab747fSPaolo Bonzini 
15249ab747fSPaolo Bonzini     len = q - buf;
153d8ee2591SPeter Maydell     stw_be_p(buf, len - 2);
15449ab747fSPaolo Bonzini     return len;
15549ab747fSPaolo Bonzini }
156