6a309384b6a14553b30717c89e255dcda2d530d3
[SCSI2SD-V6.git] / software / SCSI2SD / src / cdrom.c
1 //      Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
2 //
3 //      This file is part of SCSI2SD.
4 //
5 //      SCSI2SD is free software: you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation, either version 3 of the License, or
8 //      (at your option) any later version.
9 //
10 //      SCSI2SD is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include "device.h"
19 #include "scsi.h"
20 #include "config.h"
21 #include "cdrom.h"
22
23 uint8_t SimpleTOC[] =
24 {
25         0x00, // toc length, MSB
26         0x0A, // toc length, LSB
27         0x01, // First track number
28         0x01, // Last track number,
29         // TRACK 1 Descriptor
30         0x00, // reservied
31         0x06, // Q sub-channel not supplied, Digital track
32         0x01, // Track 1,
33         0x00, // Reserved
34         0x00,0x00,0x00,0x00 // Track start sector (LBA)
35 };
36
37 void doReadTOC(int MSF, uint8_t track, uint16_t allocationLength)
38 {
39         // We only support track 1.
40         // track 0 means "return all tracks"
41         if (track > 1)
42         {
43                 scsiDev.status = CHECK_CONDITION;
44                 scsiDev.target->sense.code = ILLEGAL_REQUEST;
45                 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
46                 scsiDev.phase = STATUS;
47         }
48         else if (MSF)
49         {
50                 // MSF addressing not currently supported.
51                 scsiDev.status = CHECK_CONDITION;
52                 scsiDev.target->sense.code = ILLEGAL_REQUEST;
53                 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
54                 scsiDev.phase = STATUS;
55         }
56         else
57         {
58                 uint32_t len = sizeof(SimpleTOC);
59                 memcpy(scsiDev.data, SimpleTOC, len);
60                 if (len > allocationLength)
61                 {
62                         len = allocationLength;
63                 }
64                 scsiDev.dataLen = len;
65                 scsiDev.phase = DATA_IN;
66         }
67 }
68
69 uint8_t SimpleHeader[] =
70 {
71         0x01, // 2048byte user data, L-EC in 288 byte aux field.
72         0x00, // reserved
73         0x00, // reserved
74         0x00, // reserved
75         0x00,0x00,0x00,0x00 // Track start sector (LBA)
76 };
77
78 void doReadHeader(int MSF, uint32_t lba, uint16_t allocationLength)
79 {
80         if (MSF)
81         {
82                 // MSF addressing not currently supported.
83                 scsiDev.status = CHECK_CONDITION;
84                 scsiDev.target->sense.code = ILLEGAL_REQUEST;
85                 scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
86                 scsiDev.phase = STATUS;
87         }
88         else
89         {
90                 uint32_t len = sizeof(SimpleHeader);
91                 memcpy(scsiDev.data, SimpleHeader, len);
92                 if (len > allocationLength)
93                 {
94                         len = allocationLength;
95                 }
96                 scsiDev.dataLen = len;
97                 scsiDev.phase = DATA_IN;
98         }
99 }
100
101
102 // Handle direct-access scsi device commands
103 int scsiCDRomCommand()
104 {
105         int commandHandled = 1;
106
107         uint8 command = scsiDev.cdb[0];
108         if (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)
109         {
110                 if (command == 0x43)
111                 {
112                         // CD-ROM Read TOC
113                         int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
114                         uint8_t track = scsiDev.cdb[6];
115                         uint16_t allocationLength =
116                                 (((uint32_t) scsiDev.cdb[7]) << 8) +
117                                 scsiDev.cdb[8];
118
119                         doReadTOC(MSF, track, allocationLength);
120                 }
121                 else if (command == 0x44)
122                 {
123                         // CD-ROM Read Header
124                         int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
125                         uint32_t lba = 0; // IGNORED for now
126                         uint16_t allocationLength =
127                                 (((uint32_t) scsiDev.cdb[7]) << 8) +
128                                 scsiDev.cdb[8];
129                         doReadHeader(MSF, lba, allocationLength);
130                 }
131                 else
132                 {
133                         commandHandled = 0;
134                 }
135         }
136         else
137         {
138                 commandHandled = 0;
139         }
140
141         return commandHandled;
142 }