1 |
dpavlin |
1 |
/* |
2 |
|
|
* PearPC |
3 |
|
|
* cd.cc |
4 |
|
|
* |
5 |
|
|
* Copyright (C) 2003 Sebastian Biallas (sb@biallas.net) |
6 |
|
|
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License version 2 as |
9 |
|
|
* published by the Free Software Foundation. |
10 |
|
|
* |
11 |
|
|
* This program is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with this program; if not, write to the Free Software |
18 |
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#include <cstdio> |
22 |
|
|
#include <cstring> |
23 |
|
|
#include "errno.h" |
24 |
|
|
|
25 |
|
|
#include "debug/tracers.h" |
26 |
|
|
#include "tools/data.h" |
27 |
|
|
#include "cd.h" |
28 |
|
|
#include "scsicmds.h" |
29 |
|
|
|
30 |
|
|
#define MM_DEVICE_PROFILE_CDROM 0x0008 // .242 |
31 |
|
|
#define MM_DEVICE_PROFILE_DVDROM 0x0010 // d.375 |
32 |
|
|
|
33 |
|
|
#define MM_DEVICE_FEATURE_PROFILE 0x0000 |
34 |
|
|
#define MM_DEVICE_FEATURE_CORE 0x0001 |
35 |
|
|
#define MM_DEVICE_FEATURE_MORPHING 0x0002 |
36 |
|
|
#define MM_DEVICE_FEATURE_REMOVABLE 0x0003 |
37 |
|
|
#define MM_DEVICE_FEATURE_RANDOM_READ 0x0010 |
38 |
|
|
#define MM_DEVICE_FEATURE_CD_READ 0x001e |
39 |
|
|
#define MM_DEVICE_FEATURE_DVD_READ 0x001f |
40 |
|
|
#define MM_DEVICE_FEATURE_INC_WRITE 0x0021 // .192 |
41 |
|
|
#define MM_DEVICE_FEATURE_xx 0x002d |
42 |
|
|
#define MM_DEVICE_FEATURE_xx2 0x002e |
43 |
|
|
#define MM_DEVICE_FEATURE_POWER 0x0100 |
44 |
|
|
#define MM_DEVICE_FEATURE_CD_AUDIO 0x0103 // .224 |
45 |
|
|
#define MM_DEVICE_FEATURE_TIMEOUT 0x0105 |
46 |
|
|
#define MM_DEVICE_FEATURE_DVD_CSS 0x0106 // .228 |
47 |
|
|
#define MM_DEVICE_FEATURE_RT_STREAM 0x0107 |
48 |
|
|
|
49 |
|
|
|
50 |
|
|
CDROMDevice::CDROMDevice(const char *name) |
51 |
|
|
: IDEDevice(name) |
52 |
|
|
{ |
53 |
|
|
mFeatures = new AVLTree(true); |
54 |
|
|
mProfiles = new AVLTree(true); |
55 |
|
|
addProfile(MM_DEVICE_PROFILE_DVDROM); |
56 |
|
|
curProfile = MM_DEVICE_PROFILE_DVDROM; |
57 |
|
|
// Profile DVDROM implies these features: |
58 |
|
|
addFeature(MM_DEVICE_FEATURE_PROFILE); |
59 |
|
|
addFeature(MM_DEVICE_FEATURE_CORE); |
60 |
|
|
addFeature(MM_DEVICE_FEATURE_MORPHING); |
61 |
|
|
addFeature(MM_DEVICE_FEATURE_REMOVABLE); |
62 |
|
|
addFeature(MM_DEVICE_FEATURE_RANDOM_READ); |
63 |
|
|
addFeature(MM_DEVICE_FEATURE_CD_READ); |
64 |
|
|
addFeature(MM_DEVICE_FEATURE_DVD_READ); |
65 |
|
|
addFeature(MM_DEVICE_FEATURE_POWER); |
66 |
|
|
addFeature(MM_DEVICE_FEATURE_TIMEOUT); |
67 |
|
|
addFeature(MM_DEVICE_FEATURE_RT_STREAM); |
68 |
|
|
|
69 |
|
|
mReady = false; |
70 |
|
|
mLocked = false; |
71 |
|
|
is_dvd = false; |
72 |
|
|
} |
73 |
|
|
|
74 |
|
|
CDROMDevice::~CDROMDevice() |
75 |
|
|
{ |
76 |
|
|
delete mFeatures; |
77 |
|
|
delete mProfiles; |
78 |
|
|
} |
79 |
|
|
|
80 |
|
|
bool CDROMDevice::isReady() |
81 |
|
|
{ |
82 |
|
|
return mReady; |
83 |
|
|
} |
84 |
|
|
|
85 |
|
|
bool CDROMDevice::setReady(bool aReady) |
86 |
|
|
{ |
87 |
|
|
if (isLocked()) return false; |
88 |
|
|
mReady = aReady; |
89 |
|
|
return true; |
90 |
|
|
} |
91 |
|
|
|
92 |
|
|
bool CDROMDevice::isLocked() |
93 |
|
|
{ |
94 |
|
|
return mLocked; |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
bool CDROMDevice::setLock(bool aLocked) |
98 |
|
|
{ |
99 |
|
|
if (!isReady()) return false; |
100 |
|
|
mLocked = aLocked; |
101 |
|
|
return true; |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
bool CDROMDevice::toggleLock() |
105 |
|
|
{ |
106 |
|
|
return setLock(!isLocked()); |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
void CDROMDevice::MSFfromLBA(MSF &msf, LBA lba) |
110 |
|
|
{ |
111 |
|
|
lba += 150; |
112 |
|
|
msf.m = lba / 4500; |
113 |
|
|
msf.s = (lba % 4500) / 75; |
114 |
|
|
msf.f = lba % 75; |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
void CDROMDevice::LBAfromMSF(LBA &lba, MSF msf) |
118 |
|
|
{ |
119 |
|
|
lba = (((msf.m*60) + msf.s) * 75) + msf.f - 150; |
120 |
|
|
} |
121 |
|
|
|
122 |
|
|
bool CDROMDevice::validLBA(LBA lba) |
123 |
|
|
{ |
124 |
|
|
return true; |
125 |
|
|
} |
126 |
|
|
|
127 |
|
|
uint CDROMDevice::getBlockSize() |
128 |
|
|
{ |
129 |
|
|
return 2048; |
130 |
|
|
} |
131 |
|
|
|
132 |
|
|
uint CDROMDevice::getBlockCount() |
133 |
|
|
{ |
134 |
|
|
return getCapacity(); |
135 |
|
|
} |
136 |
|
|
|
137 |
|
|
int CDROMDevice::getConfig(byte *buf, int aLen, byte RT, int first) |
138 |
|
|
{ |
139 |
|
|
// .284 |
140 |
|
|
byte header[] = { |
141 |
|
|
0x00, 0x00, 0x00, 0x00, // length, filled later |
142 |
|
|
0x00, 0x00, // res |
143 |
|
|
curProfile >> 8, curProfile, |
144 |
|
|
}; |
145 |
|
|
int len = sizeof header - 4; |
146 |
|
|
switch (RT) { |
147 |
|
|
case 0x00: |
148 |
|
|
// return all |
149 |
|
|
foreach(UInt, f, *mFeatures, { |
150 |
|
|
int v = f->value; |
151 |
|
|
if (v >= first) |
152 |
|
|
len += getFeature(buf+len, aLen-len, v); |
153 |
|
|
}); |
154 |
|
|
break; |
155 |
|
|
case 0x01: |
156 |
|
|
// return all with current bit |
157 |
|
|
foreach(UInt, f, *mFeatures, { |
158 |
|
|
int v = f->value; |
159 |
|
|
if (v >= first /* FIXME: && (current bit) */) |
160 |
|
|
len += getFeature(buf+len, aLen-len, v); |
161 |
|
|
}); |
162 |
|
|
break; |
163 |
|
|
case 0x02: |
164 |
|
|
// return specific |
165 |
|
|
len += getFeature(buf+len, aLen-len, first); |
166 |
|
|
break; |
167 |
|
|
default: |
168 |
|
|
IO_IDE_ERR("unknown RT in CDROMDevice::getConfig()\n"); |
169 |
|
|
return -1; |
170 |
|
|
} |
171 |
|
|
header[0] = len >> 24; header[1] = len >> 16; header[2] = len >> 8; header[3] = len; |
172 |
|
|
put(buf, aLen, header, sizeof header); |
173 |
|
|
return len; |
174 |
|
|
} |
175 |
|
|
|
176 |
|
|
int CDROMDevice::modeSense(byte *buf, int aLen, int pc, int page) |
177 |
|
|
{ |
178 |
|
|
return 0; |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
void CDROMDevice::addFeature(int feature) |
182 |
|
|
{ |
183 |
|
|
mFeatures->insert(new UInt(feature)); |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
void CDROMDevice::addProfile(int profile) |
187 |
|
|
{ |
188 |
|
|
mProfiles->insert(new UInt(profile)); |
189 |
|
|
} |
190 |
|
|
|
191 |
|
|
int CDROMDevice::getFeature(byte *buf, int aLen, int feature) |
192 |
|
|
{ |
193 |
|
|
if (aLen <= 0) return 0; |
194 |
|
|
switch (feature) { |
195 |
|
|
case MM_DEVICE_FEATURE_PROFILE: { |
196 |
|
|
int count = mProfiles->count(); |
197 |
|
|
byte list[count*4]; |
198 |
|
|
int idx = 0; |
199 |
|
|
// FIXME: foreachbwd ?? |
200 |
|
|
foreach(UInt, p, *mProfiles, { |
201 |
|
|
int v = p->value; |
202 |
|
|
list[idx++] = v>>8; |
203 |
|
|
list[idx++] = v; |
204 |
|
|
list[idx++] = (v == curProfile) ? 0x01 : 0x00; |
205 |
|
|
list[idx++] = 0x00; |
206 |
|
|
}); |
207 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_PROFILE, 0, true, true, list, count*4); |
208 |
|
|
} |
209 |
|
|
case MM_DEVICE_FEATURE_CORE: { |
210 |
|
|
byte core[] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; // 02=ATAPI, DBEvent=0 |
211 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_CORE, 0, true, true, core, sizeof core); |
212 |
|
|
} |
213 |
|
|
case MM_DEVICE_FEATURE_MORPHING: { |
214 |
|
|
byte morph[] = {0x00, 0x00, 0x00, 0x00}; // 1. ASYNC=0 (ATAPI) |
215 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_MORPHING, 1, true, true, morph, sizeof morph); |
216 |
|
|
} |
217 |
|
|
case MM_DEVICE_FEATURE_REMOVABLE: { |
218 |
|
|
byte remove[] = {0x19, 0x00, 0x00, 0x00}; // Tray-Type-Loading, Eject=1, Jmpr=0, LockAllow=1 |
219 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_REMOVABLE, 0, true, true, remove, sizeof remove); |
220 |
|
|
} |
221 |
|
|
case MM_DEVICE_FEATURE_RANDOM_READ: { |
222 |
|
|
byte randomread[] = { |
223 |
|
|
0x00, 0x00, 0x08, 0x00, // Logical Block Size |
224 |
|
|
0x00, 0x10, // Blocking |
225 |
|
|
0x00, |
226 |
|
|
0x00, // PP=0 |
227 |
|
|
}; |
228 |
|
|
// FIXME: persistent, current? |
229 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_RANDOM_READ, 0, true, true, randomread, sizeof randomread); |
230 |
|
|
} |
231 |
|
|
case MM_DEVICE_FEATURE_CD_READ: { |
232 |
|
|
byte cdread[] = {0x00, 0x00, 0x00, 0x00}; // DAP=0, C2=0, CD-Text=0 |
233 |
|
|
// FIXME: persistent, current? |
234 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_CD_READ, 2, true, true, cdread, sizeof cdread); |
235 |
|
|
} |
236 |
|
|
case MM_DEVICE_FEATURE_DVD_READ: { |
237 |
|
|
byte dvdread[] = {0x00, 0x00, 0x00, 0x00}; //MULTI110=0, Dual-R=0 |
238 |
|
|
|
239 |
|
|
// FIXME: persistent, current? |
240 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_DVD_READ, 2, true, true, dvdread, sizeof dvdread); |
241 |
|
|
} |
242 |
|
|
case MM_DEVICE_FEATURE_POWER: |
243 |
|
|
// FIXME: persistent, current? |
244 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_POWER, 0, true, true, NULL, 0); |
245 |
|
|
case MM_DEVICE_FEATURE_TIMEOUT: { |
246 |
|
|
byte timeout[] = {0x00, 0x00, 0x00, 0x00}; // Group 3=0 |
247 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_TIMEOUT, 0, true, true, timeout, sizeof timeout); |
248 |
|
|
} |
249 |
|
|
case MM_DEVICE_FEATURE_RT_STREAM: { |
250 |
|
|
byte rt_stream[] = { 0x00, 0x00, 0x00, 0x00 }; // RBCD=0 SCS=0 MP2A=0 WSPD=0 SW=0 |
251 |
|
|
|
252 |
|
|
return createFeature(buf, aLen, MM_DEVICE_FEATURE_RT_STREAM, 0, true, true, rt_stream, sizeof rt_stream); |
253 |
|
|
} |
254 |
|
|
default: |
255 |
|
|
// return size==0 for unimplemented / unsupported features |
256 |
|
|
return 0; |
257 |
|
|
} |
258 |
|
|
} |
259 |
|
|
|
260 |
|
|
int CDROMDevice::createFeature(byte *buf, int len, int feature, int version, bool pp, bool cur, byte *add, int size) |
261 |
|
|
{ |
262 |
|
|
byte header[] = { |
263 |
|
|
feature>>8, feature, |
264 |
|
|
version<<2|(pp?0x2:0)|(cur?0x1:0), |
265 |
|
|
size, |
266 |
|
|
}; |
267 |
|
|
int l = put(buf, len, header, sizeof header); |
268 |
|
|
return l+put(buf+l, len-l, add, size); |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
int CDROMDevice::put(byte *buf, int aLen, byte *src, int size) |
272 |
|
|
{ |
273 |
|
|
int len = 0; |
274 |
|
|
while (size > 0) { |
275 |
|
|
if (aLen > 0) { |
276 |
|
|
*(buf++) = *(src++); |
277 |
|
|
} else { |
278 |
|
|
len += size; |
279 |
|
|
break; |
280 |
|
|
} |
281 |
|
|
size--; |
282 |
|
|
aLen--; |
283 |
|
|
len++; |
284 |
|
|
|
285 |
|
|
} |
286 |
|
|
return len; |
287 |
|
|
} |
288 |
|
|
|
289 |
|
|
int CDROMDevice::writeBlock(byte *buf) |
290 |
|
|
{ |
291 |
|
|
IO_IDE_ERR("attempt to write to CDROM\n"); |
292 |
|
|
return 0; |
293 |
|
|
} |
294 |
|
|
|
295 |
|
|
int CDROMDevice::readDVDStructure(byte *buf, int len, uint8 subcommand, uint32 address, uint8 layer, uint8 format, uint8 AGID, uint8 control) |
296 |
|
|
{ |
297 |
|
|
uint32 capacity = getCapacity(); |
298 |
|
|
|
299 |
|
|
if (!is_dvd) { |
300 |
|
|
return 0; |
301 |
|
|
} |
302 |
|
|
|
303 |
|
|
if (subcommand == 0x0000) { |
304 |
|
|
switch (format) { |
305 |
|
|
case 0x00: //Physical format information |
306 |
|
|
buf[0] = 0; |
307 |
|
|
buf[1] = 21; |
308 |
|
|
|
309 |
|
|
buf[2] = 0x00; // reserved |
310 |
|
|
buf[3] = 0x00; // reserved |
311 |
|
|
|
312 |
|
|
buf[4] = 0x01; //DVD-ROM + Version 1.0x |
313 |
|
|
buf[5] = 0x0f; //120mm + No max rate specified |
314 |
|
|
buf[6] = 0x00; //1 layer + PTP + embossed data |
315 |
|
|
buf[7] = 0x00; //0.267um/bit + 0.74um/track |
316 |
|
|
|
317 |
|
|
buf[8] = 0x00; //pad |
318 |
|
|
buf[9] = 0x03; //start of physical data |
319 |
|
|
buf[10] = 0x00; //start of physical data |
320 |
|
|
buf[11] = 0x00; //start of physical data |
321 |
|
|
|
322 |
|
|
buf[12] = 0x00; //pad |
323 |
|
|
buf[13] = capacity >> 16; //end of physical data |
324 |
|
|
buf[14] = capacity >> 8; //end of physical data |
325 |
|
|
buf[15] = capacity; //end of physical data |
326 |
|
|
|
327 |
|
|
buf[16] = 0x00; //pad |
328 |
|
|
buf[17] = 0x00; //end sector number in layer 0 |
329 |
|
|
buf[18] = 0x00; //end sector number in layer 0 |
330 |
|
|
buf[19] = 0x00; //end sector number in layer 0 |
331 |
|
|
|
332 |
|
|
buf[20] = 0x00; //BCA + reserved |
333 |
|
|
|
334 |
|
|
// 21-n : defined as reserved for DVD-ROMs |
335 |
|
|
|
336 |
|
|
return 21; |
337 |
|
|
|
338 |
|
|
case 0x01: // Copyright Information |
339 |
|
|
buf[0] = 0; |
340 |
|
|
buf[1] = 8; |
341 |
|
|
|
342 |
|
|
buf[2] = 0; |
343 |
|
|
buf[3] = 0; |
344 |
|
|
|
345 |
|
|
buf[4] = 0x00; // no copyright information |
346 |
|
|
buf[5] = 0x00; // all regions allowed |
347 |
|
|
buf[6] = 0x00; // reserved |
348 |
|
|
buf[7] = 0x00; // reserved |
349 |
|
|
|
350 |
|
|
return 8; |
351 |
|
|
|
352 |
|
|
default: |
353 |
|
|
ht_printf("readDVDStructure with Unsupported Format (%i)\n", format); |
354 |
|
|
return 0; |
355 |
|
|
} |
356 |
|
|
} else { |
357 |
|
|
ht_printf("readDVDStructure on Unsupported Media (%i)\n", subcommand); |
358 |
|
|
return 0; |
359 |
|
|
} |
360 |
|
|
} |
361 |
|
|
|
362 |
|
|
void CDROMDevice::activateDVD(bool onoff) |
363 |
|
|
{ |
364 |
|
|
is_dvd = onoff; |
365 |
|
|
} |
366 |
|
|
|
367 |
|
|
bool CDROMDevice::isDVD(void) |
368 |
|
|
{ |
369 |
|
|
return is_dvd; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
// ----------------------------- File based CDROM device ------------------------------------ |
373 |
|
|
|
374 |
|
|
/* |
375 |
|
|
* |
376 |
|
|
*/ |
377 |
|
|
CDROMDeviceFile::CDROMDeviceFile(const char *name) |
378 |
|
|
: CDROMDevice(name) |
379 |
|
|
{ |
380 |
|
|
mFile = NULL; |
381 |
|
|
} |
382 |
|
|
|
383 |
|
|
CDROMDeviceFile::~CDROMDeviceFile() |
384 |
|
|
{ |
385 |
|
|
if (mFile) sys_fclose(mFile); |
386 |
|
|
} |
387 |
|
|
|
388 |
|
|
uint32 CDROMDeviceFile::getCapacity() |
389 |
|
|
{ |
390 |
|
|
return mCapacity; |
391 |
|
|
} |
392 |
|
|
|
393 |
|
|
bool CDROMDeviceFile::seek(uint64 blockno) |
394 |
|
|
{ |
395 |
|
|
curLBA = blockno; |
396 |
|
|
sys_fseek(mFile, (uint64)blockno * 2048); |
397 |
|
|
return true; |
398 |
|
|
} |
399 |
|
|
|
400 |
|
|
void CDROMDeviceFile::flush() |
401 |
|
|
{ |
402 |
|
|
sys_flush(mFile); |
403 |
|
|
} |
404 |
|
|
|
405 |
|
|
int CDROMDeviceFile::readBlock(byte *buf) |
406 |
|
|
{ |
407 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_HDR_SYNC) { |
408 |
|
|
// .95 |
409 |
|
|
byte sync[]={0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0}; |
410 |
|
|
memcpy(buf, sync, 12); |
411 |
|
|
buf+=12; |
412 |
|
|
} |
413 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_HDR_SECTOR) { |
414 |
|
|
// .95 |
415 |
|
|
MSF msf; |
416 |
|
|
MSFfromLBA(msf, curLBA); |
417 |
|
|
*(buf++) = msf.m; |
418 |
|
|
*(buf++) = msf.s; |
419 |
|
|
*(buf++) = msf.f; |
420 |
|
|
*(buf++) = 0x01; // mode 1 data |
421 |
|
|
} |
422 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_DATA) { |
423 |
|
|
sys_fread(mFile, buf, 2048); |
424 |
|
|
buf += 2048; |
425 |
|
|
} |
426 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_ECC) { |
427 |
|
|
// .96 |
428 |
|
|
// blablablablabla ;) |
429 |
|
|
memset(buf, 0, 288); |
430 |
|
|
} |
431 |
|
|
curLBA++; |
432 |
|
|
return 0; |
433 |
|
|
} |
434 |
|
|
|
435 |
|
|
bool CDROMDeviceFile::promSeek(uint64 pos) |
436 |
|
|
{ |
437 |
|
|
return sys_fseek(mFile, pos) == 0; |
438 |
|
|
} |
439 |
|
|
|
440 |
|
|
uint CDROMDeviceFile::promRead(byte *buf, uint size) |
441 |
|
|
{ |
442 |
|
|
return sys_fread(mFile, buf, size); |
443 |
|
|
} |
444 |
|
|
|
445 |
|
|
bool CDROMDeviceFile::changeDataSource(const char *file) |
446 |
|
|
{ |
447 |
|
|
if (mFile) sys_fclose(mFile); |
448 |
|
|
mFile = sys_fopen(file, SYS_OPEN_READ); |
449 |
|
|
if (!mFile) { |
450 |
|
|
char buf[256]; |
451 |
|
|
ht_snprintf(buf, sizeof buf, "%s: could not open file (%s)", file, strerror(errno)); |
452 |
|
|
setError(buf); |
453 |
|
|
return false; |
454 |
|
|
} |
455 |
|
|
sys_fseek(mFile, 0, SYS_SEEK_END); |
456 |
|
|
FileOfs fsize = sys_ftell(mFile); |
457 |
|
|
mCapacity = fsize / 2048 + !!(fsize % 2048); |
458 |
|
|
|
459 |
|
|
if (!is_dvd && (mCapacity > 1151850)) { |
460 |
|
|
/* In case the image just can't be a CD-ROM */ |
461 |
|
|
this->activateDVD(true); |
462 |
|
|
} |
463 |
|
|
|
464 |
|
|
return true; |
465 |
|
|
} |
466 |
|
|
|
467 |
|
|
int CDROMDeviceFile::readTOC(byte *buf, bool msf, uint8 starttrack, int len, int format) |
468 |
|
|
{ |
469 |
|
|
switch (format) { |
470 |
|
|
case 0: { |
471 |
|
|
// .415 |
472 |
|
|
// start_track == track |
473 |
|
|
byte sector[12] = { |
474 |
|
|
0, |
475 |
|
|
10, |
476 |
|
|
|
477 |
|
|
1, // first track |
478 |
|
|
1, // last track |
479 |
|
|
0x00, // res |
480 |
|
|
0x16, // .408 (Data track, copy allowed :) ) |
481 |
|
|
1, // track number |
482 |
|
|
0x00, // res |
483 |
|
|
0x00, // LBA |
484 |
|
|
0x00, |
485 |
|
|
0x00, |
486 |
|
|
0x00, // LBA |
487 |
|
|
}; |
488 |
|
|
if (msf) { |
489 |
|
|
MSF m; |
490 |
|
|
MSFfromLBA(m, 0); |
491 |
|
|
sector[8] = 0x00; |
492 |
|
|
sector[9] = m.m; |
493 |
|
|
sector[10] = m.s; |
494 |
|
|
sector[11] = m.f; |
495 |
|
|
} |
496 |
|
|
return put(buf, len, sector, sizeof sector); |
497 |
|
|
} |
498 |
|
|
case 1: { |
499 |
|
|
// .418 Multisession information |
500 |
|
|
// start_track == 0 |
501 |
|
|
byte sector[12] = { |
502 |
|
|
0, |
503 |
|
|
10, |
504 |
|
|
|
505 |
|
|
1, // first session |
506 |
|
|
1, // last session |
507 |
|
|
0x00, // res |
508 |
|
|
0x16, // .408 (Data track, copy allowed :) ) |
509 |
|
|
1, // first track number in last complete session |
510 |
|
|
0x00, // res |
511 |
|
|
0x00, // LBA |
512 |
|
|
0x00, |
513 |
|
|
0x00, |
514 |
|
|
0x00, // LBA |
515 |
|
|
}; |
516 |
|
|
if (msf) { |
517 |
|
|
MSF m; |
518 |
|
|
MSFfromLBA(m, 0); |
519 |
|
|
sector[8] = 0x00; |
520 |
|
|
sector[9] = m.m; |
521 |
|
|
sector[10] = m.s; |
522 |
|
|
sector[11] = m.f; |
523 |
|
|
} |
524 |
|
|
return put(buf, len, sector, sizeof sector); |
525 |
|
|
} |
526 |
|
|
case 2: { |
527 |
|
|
// .420 Raw TOC |
528 |
|
|
// start_track == session number |
529 |
|
|
|
530 |
|
|
MSF msf_cap, msf_zero; |
531 |
|
|
// FIXME: only when (msf)? |
532 |
|
|
MSFfromLBA(msf_cap, getCapacity()); |
533 |
|
|
MSFfromLBA(msf_zero, 0); |
534 |
|
|
|
535 |
|
|
byte sector[48] = { |
536 |
|
|
0, |
537 |
|
|
sizeof sector - 2, |
538 |
|
|
1, // first session |
539 |
|
|
1, // last session |
540 |
|
|
|
541 |
|
|
// points a0-af tracks b0-bf |
542 |
|
|
|
543 |
|
|
1, // session number |
544 |
|
|
0x16, // .408 (Data track, copy allowed :) ) |
545 |
|
|
0, // track number |
546 |
|
|
0xa0, // point (lead-in) |
547 |
|
|
0x00, // min |
548 |
|
|
0x00, // sec |
549 |
|
|
0x00, // frame |
550 |
|
|
0x00, // zero |
551 |
|
|
0x01, // first track |
552 |
|
|
0x00, // disk type |
553 |
|
|
0x00, // |
554 |
|
|
|
555 |
|
|
1, // session number |
556 |
|
|
0x16, // .408 (Data track, copy allowed :) ) |
557 |
|
|
0, // track number |
558 |
|
|
0xa1, // point |
559 |
|
|
0x00, // min |
560 |
|
|
0x00, // sec |
561 |
|
|
0x00, // frame |
562 |
|
|
0x00, // zero |
563 |
|
|
0x01, // last track |
564 |
|
|
0x00, // |
565 |
|
|
0x00, // |
566 |
|
|
|
567 |
|
|
1, // session number |
568 |
|
|
0x16, // .408 (Data track, copy allowed :) ) |
569 |
|
|
0, // track number |
570 |
|
|
0xa2, // point (lead-out) |
571 |
|
|
0x00, // min |
572 |
|
|
0x00, // sec |
573 |
|
|
0x00, // frame |
574 |
|
|
0x00, // zero |
575 |
|
|
msf_cap.m, // start |
576 |
|
|
msf_cap.s, // of |
577 |
|
|
msf_cap.f, // leadout |
578 |
|
|
|
579 |
|
|
1, // session number |
580 |
|
|
0x16, // .408 (Data track, copy allowed :) ) |
581 |
|
|
0, // track number |
582 |
|
|
1, // point (real track) |
583 |
|
|
0x00, // min |
584 |
|
|
0x00, // sec |
585 |
|
|
0x00, // frame |
586 |
|
|
0x00, // zero |
587 |
|
|
msf_zero.m, // start |
588 |
|
|
msf_zero.s, // of |
589 |
|
|
msf_zero.f, // track |
590 |
|
|
}; |
591 |
|
|
return put(buf, len, sector, sizeof sector); |
592 |
|
|
} |
593 |
|
|
case 3: |
594 |
|
|
// PMA |
595 |
|
|
case 4: |
596 |
|
|
// ATIP |
597 |
|
|
case 5: |
598 |
|
|
// CDTEXT |
599 |
|
|
default: { |
600 |
|
|
IO_IDE_WARN("read toc: format %d not supported.\n", format); |
601 |
|
|
byte sector[2] = {0, 0}; |
602 |
|
|
return put(buf, len, sector, sizeof sector); |
603 |
|
|
} |
604 |
|
|
} |
605 |
|
|
} |
606 |
|
|
|
607 |
|
|
void CDROMDeviceFile::eject() |
608 |
|
|
{ |
609 |
|
|
} |
610 |
|
|
|
611 |
|
|
|
612 |
|
|
//---------------------- SCSI based CDROM drive ----------------------- |
613 |
|
|
|
614 |
|
|
#define CD_FRAMESIZE 2048 |
615 |
|
|
|
616 |
|
|
// For me values up to 32 worked, 0 disables caching |
617 |
|
|
#define SCSI_BUFFER_SECTORS 32 |
618 |
|
|
|
619 |
|
|
|
620 |
|
|
/// @author Alexander Stockinger |
621 |
|
|
/// @date 07/17/2004 |
622 |
|
|
/// @param name The name of the CDROM device |
623 |
|
|
CDROMDeviceSCSI::CDROMDeviceSCSI(const char *name) |
624 |
|
|
:CDROMDevice(name) |
625 |
|
|
{ |
626 |
|
|
buffer_size = SCSI_BUFFER_SECTORS; |
627 |
|
|
buffer_base = (LBA) - SCSI_BUFFER_SECTORS; |
628 |
|
|
data_buffer = NULL; |
629 |
|
|
// Alloc read ahead buffer |
630 |
|
|
if (buffer_size) |
631 |
|
|
data_buffer = new byte[buffer_size * CD_FRAMESIZE]; |
632 |
|
|
|
633 |
|
|
} |
634 |
|
|
|
635 |
|
|
/// @author Alexander Stockinger |
636 |
|
|
/// @date 07/17/2004 |
637 |
|
|
CDROMDeviceSCSI::~CDROMDeviceSCSI() |
638 |
|
|
{ |
639 |
|
|
delete[]data_buffer; |
640 |
|
|
} |
641 |
|
|
|
642 |
|
|
/// @author Alexander Stockinger |
643 |
|
|
/// @date 07/17/2004 |
644 |
|
|
/// @return true if drive is ready, else false |
645 |
|
|
bool CDROMDeviceSCSI::isReady() |
646 |
|
|
{ |
647 |
|
|
byte params[8] = {0, 0, 0, 0, 0, 0, 0, 0}; |
648 |
|
|
byte res = SCSI_ExecCmd(SCSI_UNITREADY, SCSI_CMD_DIR_OUT, params); |
649 |
|
|
mReady = res == SCSI_STATUS_GOOD; |
650 |
|
|
return mReady; |
651 |
|
|
} |
652 |
|
|
|
653 |
|
|
/// @author Alexander Stockinger |
654 |
|
|
/// @date 07/17/2004 |
655 |
|
|
/// @param lock true for locking the tray, false for unlocking |
656 |
|
|
/// @return true on successful execution, else false |
657 |
|
|
bool CDROMDeviceSCSI::setLock(bool lock) |
658 |
|
|
{ |
659 |
|
|
bool ret = CDROMDevice::setLock(lock); |
660 |
|
|
if (ret) { |
661 |
|
|
byte params[8] = {0, 0, 0, 0, 0, 0, 0, 0}; |
662 |
|
|
params[3] = lock ? SCSI_TRAYLOCK_LOCKED : SCSI_TRAYLOCK_UNLOCKED; |
663 |
|
|
ret = SCSI_ExecCmd(SCSI_TRAYLOCK, SCSI_CMD_DIR_OUT, params) == SCSI_STATUS_GOOD; |
664 |
|
|
} |
665 |
|
|
return ret; |
666 |
|
|
} |
667 |
|
|
|
668 |
|
|
/// @author Alexander Stockinger |
669 |
|
|
/// @date 07/17/2004 |
670 |
|
|
/// @return The number of sectors on the inserted media |
671 |
|
|
uint32 CDROMDeviceSCSI::getCapacity() |
672 |
|
|
{ |
673 |
|
|
if (!isReady()) { |
674 |
|
|
IO_IDE_ERR("CDROMDeviceSCSI::getCapacity() failed: not ready.\n"); |
675 |
|
|
} else { |
676 |
|
|
byte buf[8]; |
677 |
|
|
|
678 |
|
|
byte params[8] = {0, 0, 0, 0, 0, 0, 0, 0}; |
679 |
|
|
byte res = SCSI_ExecCmd(SCSI_READCDCAP, SCSI_CMD_DIR_IN, params, buf, 8); |
680 |
|
|
if (res != SCSI_STATUS_GOOD) return 0; |
681 |
|
|
|
682 |
|
|
return (buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + buf[3]; |
683 |
|
|
} |
684 |
|
|
} |
685 |
|
|
|
686 |
|
|
/// @author Alexander Stockinger |
687 |
|
|
/// @date 07/17/2004 |
688 |
|
|
/// @param blockno The sector to seek to |
689 |
|
|
/// @return true on successful execution, else false |
690 |
|
|
bool CDROMDeviceSCSI::seek(uint64 blockno) |
691 |
|
|
{ |
692 |
|
|
curLBA = blockno; |
693 |
|
|
return true; |
694 |
|
|
} |
695 |
|
|
|
696 |
|
|
/// @author Alexander Stockinger |
697 |
|
|
/// @date 07/17/2004 |
698 |
|
|
void CDROMDeviceSCSI::flush() |
699 |
|
|
{ |
700 |
|
|
} |
701 |
|
|
|
702 |
|
|
/// @author Alexander Stockinger |
703 |
|
|
/// @date 07/17/2004 |
704 |
|
|
/// @param sector The sector to read |
705 |
|
|
/// @param buf The buffer to read into (size is expected to be CD_FRAMESIZE bytes) |
706 |
|
|
/// @return true on successful execution, else false |
707 |
|
|
bool CDROMDeviceSCSI::readBufferedData(byte *buf, uint sector) |
708 |
|
|
{ |
709 |
|
|
if (buffer_size) { |
710 |
|
|
// If we have the requested data buffered, return it |
711 |
|
|
int buffer_delta = (int) sector - (int) buffer_base; |
712 |
|
|
if (buffer_delta >= 0 && buffer_delta < (int) buffer_size) { |
713 |
|
|
uint offset = CD_FRAMESIZE * buffer_delta; |
714 |
|
|
memcpy(buf, data_buffer + offset, CD_FRAMESIZE); |
715 |
|
|
return true; |
716 |
|
|
} |
717 |
|
|
|
718 |
|
|
// If not, buffer some more and return the requested one |
719 |
|
|
buffer_base = sector; |
720 |
|
|
bool ret = SCSI_ReadSectors(sector, data_buffer, CD_FRAMESIZE * buffer_size, buffer_size); |
721 |
|
|
memcpy(buf, data_buffer, CD_FRAMESIZE); |
722 |
|
|
return ret; |
723 |
|
|
} else |
724 |
|
|
return SCSI_ReadSectors(sector, buf, CD_FRAMESIZE, 1); |
725 |
|
|
} |
726 |
|
|
|
727 |
|
|
/// @author Alexander Stockinger |
728 |
|
|
/// @date 07/17/2004 |
729 |
|
|
/// @param buf The buffer to read into (size is expected to be CD_FRAMESIZE bytes) |
730 |
|
|
/// @return Always 0 at the moment |
731 |
|
|
int CDROMDeviceSCSI::readBlock(byte *buf) |
732 |
|
|
{ |
733 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_HDR_SYNC) { |
734 |
|
|
// .95 |
735 |
|
|
byte sync[] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0}; |
736 |
|
|
memcpy(buf, sync, 12); |
737 |
|
|
buf += 12; |
738 |
|
|
} |
739 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_HDR_SECTOR) { |
740 |
|
|
// .95 |
741 |
|
|
MSF msf; |
742 |
|
|
MSFfromLBA(msf, curLBA); |
743 |
|
|
*(buf++) = msf.m; |
744 |
|
|
*(buf++) = msf.s; |
745 |
|
|
*(buf++) = msf.f; |
746 |
|
|
*(buf++) = 0x01; // mode 1 data |
747 |
|
|
} |
748 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_DATA) { |
749 |
|
|
//bool ret = ASPI_ReadSector(a, t, l, curLBA, buf, CD_FRAMESIZE); |
750 |
|
|
bool ret = readBufferedData(buf, curLBA); |
751 |
|
|
if (!ret) |
752 |
|
|
IO_IDE_WARN("Error reading from SCSI CD drive (sector %d)\n", curLBA); |
753 |
|
|
buf += CD_FRAMESIZE; |
754 |
|
|
} |
755 |
|
|
if (mMode & IDE_ATAPI_TRANSFER_ECC) { |
756 |
|
|
// .96 |
757 |
|
|
// blablablablabla ;) |
758 |
|
|
memset(buf, 0, 288); |
759 |
|
|
} |
760 |
|
|
curLBA++; |
761 |
|
|
return 0; |
762 |
|
|
} |
763 |
|
|
|
764 |
|
|
|
765 |
|
|
/** |
766 |
|
|
* @param buffer result buffer |
767 |
|
|
* @param msf if true use MSF encoding otherwise LBA |
768 |
|
|
* @param starttrack start track |
769 |
|
|
* @param len maximum length of buffer |
770 |
|
|
* @param format see CDROMDeviceFile::readTOC |
771 |
|
|
*/ |
772 |
|
|
int CDROMDeviceSCSI::readTOC(byte *buf, bool msf, uint8 starttrack, int len, int format) |
773 |
|
|
{ |
774 |
|
|
byte params[9] = { |
775 |
|
|
msf ? 2 : 0, |
776 |
|
|
0, |
777 |
|
|
0, |
778 |
|
|
0, |
779 |
|
|
0, |
780 |
|
|
starttrack, |
781 |
|
|
len >> 8, |
782 |
|
|
len >> 0, |
783 |
|
|
format << 6, |
784 |
|
|
}; |
785 |
|
|
if (SCSI_ExecCmd(SCSI_READ_TOC, SCSI_CMD_DIR_IN, |
786 |
|
|
params, buf, len) == SCSI_STATUS_GOOD) { |
787 |
|
|
ht_printf("readtoc: %d\n", (buf[0] << 8) | (buf[1] << 0)); |
788 |
|
|
return (buf[0] << 8) | (buf[1] << 0); |
789 |
|
|
} else { |
790 |
|
|
ht_printf("readtoc failed\n"); |
791 |
|
|
return 0; |
792 |
|
|
} |
793 |
|
|
} |
794 |
|
|
|
795 |
|
|
int CDROMDeviceSCSI::getConfig(byte *buf, int len, byte RT, int first) |
796 |
|
|
{ |
797 |
|
|
static byte rt[] = { |
798 |
|
|
0x00, 0x01, 0x02, 0x03, 0x43, 0x6f, 0x6e, 0x74, |
799 |
|
|
0x61, 0x69, 0x6e, 0x73, 0x00, 0x50, 0x00, 0x45, |
800 |
|
|
0x00, 0x41, 0x00, 0x52, 0x00, 0x50, 0x00, 0x43, |
801 |
|
|
0x20, 0x43, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x50, |
802 |
|
|
0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, |
803 |
|
|
0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, |
804 |
|
|
0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x53, 0x65, |
805 |
|
|
0x62, 0x61, 0x73, 0x74, 0x69, 0x61, 0x6e, 0x20, |
806 |
|
|
0x42, 0x69, 0x61, 0x6c, 0x6c, 0x61, 0x73, 0x20, |
807 |
|
|
0x32, 0x30, 0x30, 0x34, 0x00, 0x46, 0x00, 0x00 |
808 |
|
|
}; |
809 |
|
|
|
810 |
|
|
byte params[9] = { |
811 |
|
|
rt[RT], |
812 |
|
|
first >> 8, |
813 |
|
|
first >> 0, |
814 |
|
|
0, |
815 |
|
|
0, |
816 |
|
|
0, |
817 |
|
|
len >> 8, |
818 |
|
|
len >> 0, |
819 |
|
|
0, |
820 |
|
|
}; |
821 |
|
|
if (SCSI_ExecCmd(rt[(4<<4)+13], SCSI_CMD_DIR_IN, |
822 |
|
|
params, buf, len) == SCSI_STATUS_GOOD) { |
823 |
|
|
uint32 reslen = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0) + 4; |
824 |
|
|
return reslen; |
825 |
|
|
} else { |
826 |
|
|
ht_printf("getconfig failed\n"); |
827 |
|
|
return 0; |
828 |
|
|
} |
829 |
|
|
} |
830 |
|
|
|
831 |
|
|
int CDROMDeviceSCSI::readDVDStructure(byte *buf, int len, uint8 subcommand, uint32 address, uint8 layer, uint8 format, uint8 AGID, uint8 control) |
832 |
|
|
{ |
833 |
|
|
byte params[11] = { |
834 |
|
|
subcommand, |
835 |
|
|
address >> 24, |
836 |
|
|
address >> 16, |
837 |
|
|
address >> 8, |
838 |
|
|
address >> 0, |
839 |
|
|
layer, |
840 |
|
|
format, |
841 |
|
|
len >> 8, |
842 |
|
|
len >> 0, |
843 |
|
|
AGID << 6, |
844 |
|
|
control, |
845 |
|
|
}; |
846 |
|
|
if (SCSI_ExecCmd(0xad, SCSI_CMD_DIR_IN, |
847 |
|
|
params, buf, len) == SCSI_STATUS_GOOD) { |
848 |
|
|
uint32 reslen = (buf[0] << 8) | (buf[1] << 0) + 2; |
849 |
|
|
return reslen; |
850 |
|
|
} else { |
851 |
|
|
ht_printf("readDVDStructure failed\n"); |
852 |
|
|
return 0; |
853 |
|
|
} |
854 |
|
|
} |
855 |
|
|
|
856 |
|
|
/// @author Alexander Stockinger |
857 |
|
|
/// @date 07/17/2004 |
858 |
|
|
void CDROMDeviceSCSI::eject() |
859 |
|
|
{ |
860 |
|
|
if (!isLocked()) { |
861 |
|
|
byte params[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; |
862 |
|
|
params[3] = true ? SCSI_EJECTTRAY_UNLOAD : SCSI_EJECTTRAY_LOAD; |
863 |
|
|
SCSI_ExecCmd(SCSI_EJECTTRAY, SCSI_CMD_DIR_OUT, params); |
864 |
|
|
buffer_base = (LBA) - buffer_size; |
865 |
|
|
} |
866 |
|
|
} |
867 |
|
|
|
868 |
|
|
/// @date 07/17/2004 |
869 |
|
|
/// @param pos The new seek position (byte address) |
870 |
|
|
/// @return true on successful execution, else false |
871 |
|
|
bool CDROMDeviceSCSI::promSeek(uint64 pos) |
872 |
|
|
{ |
873 |
|
|
prompos = pos; |
874 |
|
|
return true; |
875 |
|
|
} |
876 |
|
|
|
877 |
|
|
/// @author Alexander Stockinger |
878 |
|
|
/// @date 07/17/2004 |
879 |
|
|
/// @param buf The buffer to read into (expected to be at least count bytes) |
880 |
|
|
/// @param pos The first byte to read |
881 |
|
|
/// @param count The number of bytes to read |
882 |
|
|
/// @return The number of bytes actually read |
883 |
|
|
uint CDROMDeviceSCSI::readData(byte *buf, uint64 pos, uint count) |
884 |
|
|
{ |
885 |
|
|
uint res = 0; |
886 |
|
|
while (count) { |
887 |
|
|
uint sector = pos / CD_FRAMESIZE; |
888 |
|
|
uint offset = pos % CD_FRAMESIZE; |
889 |
|
|
uint read = CD_FRAMESIZE - offset; |
890 |
|
|
read = MIN(read, count); |
891 |
|
|
|
892 |
|
|
byte buffer[CD_FRAMESIZE]; |
893 |
|
|
bool ret = readBufferedData(buffer, sector); |
894 |
|
|
if (!ret) return res; |
895 |
|
|
|
896 |
|
|
memcpy(buf, buffer + offset, read); |
897 |
|
|
|
898 |
|
|
count -= read; |
899 |
|
|
res += read; |
900 |
|
|
buf += read; |
901 |
|
|
pos += read; |
902 |
|
|
} |
903 |
|
|
return res; |
904 |
|
|
} |
905 |
|
|
|
906 |
|
|
/// @author Alexander Stockinger |
907 |
|
|
/// @date 07/17/2004 |
908 |
|
|
/// @param buf The buffer to read into (expected to be at least size bytes) |
909 |
|
|
/// @param size The number of bytes to read |
910 |
|
|
/// @return The number of bytes read |
911 |
|
|
uint CDROMDeviceSCSI::promRead(byte *buf, uint size) |
912 |
|
|
{ |
913 |
|
|
if (!isReady()) { |
914 |
|
|
IO_IDE_WARN("CDROMDeviceSCSI::promRead(): not ready.\n"); |
915 |
|
|
return 0; |
916 |
|
|
} |
917 |
|
|
return readData(buf, prompos, size); |
918 |
|
|
} |
919 |
|
|
|
920 |
|
|
/// @author Alexander Stockinger |
921 |
|
|
/// @date 07/17/2004 |
922 |
|
|
/// @param start The first sector to read |
923 |
|
|
/// @param buffer The data buffer to read into |
924 |
|
|
/// @param buffer_bytes The size of the data buffer in bytes |
925 |
|
|
/// @param sectors The number of consecutive sectors to read |
926 |
|
|
/// @return true on successful execution, else false |
927 |
|
|
bool CDROMDeviceSCSI::SCSI_ReadSectors(uint32 start, byte *buffer, |
928 |
|
|
uint buffer_bytes, |
929 |
|
|
uint sectors) |
930 |
|
|
{ |
931 |
|
|
byte params[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; |
932 |
|
|
|
933 |
|
|
params[1] = (byte) (start >> 24); |
934 |
|
|
params[2] = (byte) (start >> 16); |
935 |
|
|
params[3] = (byte) (start >> 8); |
936 |
|
|
params[4] = (byte) (start >> 0); |
937 |
|
|
|
938 |
|
|
params[6] = sectors >> 8; // Number of sectors to read |
939 |
|
|
params[7] = sectors; // Number of sectors to read |
940 |
|
|
|
941 |
|
|
byte ret = SCSI_ExecCmd(SCSI_READ10, SCSI_CMD_DIR_IN, params, buffer, buffer_bytes); |
942 |
|
|
return ret == SCSI_STATUS_GOOD; |
943 |
|
|
} |