/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26