/[pearpc]/src/io/ide/cd.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/io/ide/cd.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 6 months ago) by dpavlin
File size: 22912 byte(s)
import upstream CVS
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 }

  ViewVC Help
Powered by ViewVC 1.1.26