1 /******************************************************************
2 * CopyPolicy: GNU Lesser General Public License 2.1 applies
3 * Copyright (C) Monty xiphmont@mit.edu
5 * CDROM code specific to the cooked ioctl interface
7 ******************************************************************/
9 #include "low_interface.h"
10 #include "common_interface.h"
13 static int timed_ioctl(cdrom_drive
*d
, int fd
, int command
, void *arg
){
16 int ret1
=clock_gettime(d
->private->clock
,&tv1
);
17 int ret2
=ioctl(fd
, command
,arg
);
18 int ret3
=clock_gettime(d
->private->clock
,&tv2
);
20 d
->private->last_milliseconds
=-1;
22 d
->private->last_milliseconds
= (tv2
.tv_sec
-tv1
.tv_sec
)*1000. + (tv2
.tv_nsec
-tv1
.tv_nsec
)/1000000.;
27 static int cooked_readtoc (cdrom_drive
*d
){
30 struct cdrom_tochdr hdr
;
31 struct cdrom_tocentry entry
;
33 /* get TocHeader to find out how many entries there are */
34 if(ioctl(d
->ioctl_fd
, CDROMREADTOCHDR
, &hdr
))
37 cderror(d
,"102: Permision denied on cdrom (ioctl) device\n");
40 cderror(d
,"004: Unable to read table of contents header\n");
44 /* get all TocEntries */
45 for(i
=0;i
<hdr
.cdth_trk1
;i
++){
46 entry
.cdte_track
= i
+1;
47 entry
.cdte_format
= CDROM_LBA
;
48 if(ioctl(d
->ioctl_fd
,CDROMREADTOCENTRY
,&entry
)){
49 cderror(d
,"005: Unable to read table of contents entry\n");
53 d
->disc_toc
[i
].bFlags
= (entry
.cdte_adr
<< 4) | (entry
.cdte_ctrl
& 0x0f);
54 d
->disc_toc
[i
].bTrack
= i
+1;
55 d
->disc_toc
[i
].dwStartSector
= entry
.cdte_addr
.lba
;
58 entry
.cdte_track
= CDROM_LEADOUT
;
59 entry
.cdte_format
= CDROM_LBA
;
60 if(ioctl(d
->ioctl_fd
, CDROMREADTOCENTRY
, &entry
)){
61 cderror(d
,"005: Unable to read table of contents entry\n");
64 d
->disc_toc
[i
].bFlags
= (entry
.cdte_adr
<< 4) | (entry
.cdte_ctrl
& 0x0f);
65 d
->disc_toc
[i
].bTrack
= entry
.cdte_track
;
66 d
->disc_toc
[i
].dwStartSector
= entry
.cdte_addr
.lba
;
68 tracks
=hdr
.cdth_trk1
+1;
69 d
->cd_extra
=FixupTOC(d
,tracks
);
70 return(--tracks
); /* without lead-out */
73 /* Set operating speed */
74 static int cooked_setspeed(cdrom_drive
*d
, int speed
)
77 return ioctl(d
->ioctl_fd
, CDROM_SELECT_SPEED
, speed
);
82 /* read 'SectorBurst' adjacent sectors of audio sectors
83 * to Buffer '*p' beginning at sector 'lSector'
86 static long cooked_read (cdrom_drive
*d
, void *p
, long begin
, long sectors
){
87 int retry_count
,err
,ret
=0;
88 struct cdrom_read_audio arg
;
89 char *buffer
=(char *)p
;
91 /* read d->nsectors at a time, max. */
92 sectors
=(sectors
>d
->nsectors
?d
->nsectors
:sectors
);
93 if(p
==NULL
)buffer
= malloc(sectors
*CD_FRAMESIZE_RAW
);
96 arg
.addr_format
= CDROM_LBA
;
97 arg
.nframes
= sectors
;
102 if((err
=timed_ioctl(d
,d
->ioctl_fd
, CDROMREADAUDIO
, &arg
))){
109 /* D'oh. Possible kernel error. Keep limping */
111 /* Nope, can't continue */
112 cderror(d
,"300: Kernel memory error\n");
126 /* *Could* be I/O or media error. I think. If we're at
127 30 retries, we better skip this unhappy little
129 if(retry_count
>MAX_RETRIES
-1){
131 sprintf(b
,"010: Unable to access sector %ld: skipping...\n",
144 if(retry_count
>MAX_RETRIES
){
145 cderror(d
,"007: Unknown, unrecoverable error reading data\n");
156 if(p
==NULL
&& buffer
)free(buffer
);
161 static int Dummy (cdrom_drive
*d
,int Switch
){
165 static int verify_read_command(cdrom_drive
*d
){
167 int16_t *buff
=malloc(CD_FRAMESIZE_RAW
);
170 cdmessage(d
,"Verifying drive can read CDDA...\n");
174 for(i
=1;i
<=d
->tracks
;i
++){
175 if(cdda_track_audiop(d
,i
)==1){
176 long firstsector
=cdda_track_firstsector(d
,i
);
177 long lastsector
=cdda_track_lastsector(d
,i
);
178 long sector
=(firstsector
+lastsector
)>>1;
181 if(d
->read_audio(d
,buff
,sector
,1)>0){
182 cdmessage(d
,"\tExpected command set reads OK.\n");
193 cdmessage(d
,"\tCould not find any audio tracks on this disk.\n");
197 cdmessage(d
,"\n\tUnable to read any data; "
198 "drive probably not CDDA capable.\n");
200 cderror(d
,"006: Could not read any data from drive\n");
206 #include "drive_exceptions.h"
208 static void check_exceptions(cdrom_drive
*d
,exception
*list
){
211 while(list
[i
].model
){
212 if(!strncmp(list
[i
].model
,d
->drive_model
,strlen(list
[i
].model
))){
213 if(list
[i
].bigendianp
!=-1)d
->bigendianp
=list
[i
].bigendianp
;
220 /* set function pointers to use the ioctl routines */
221 int cooked_init_drive (cdrom_drive
*d
){
224 switch(d
->drive_type
){
225 case MATSUSHITA_CDROM_MAJOR
: /* sbpcd 1 */
226 case MATSUSHITA_CDROM2_MAJOR
: /* sbpcd 2 */
227 case MATSUSHITA_CDROM3_MAJOR
: /* sbpcd 3 */
228 case MATSUSHITA_CDROM4_MAJOR
: /* sbpcd 4 */
229 /* don't make the buffer too big; this sucker don't preempt */
231 cdmessage(d
,"Attempting to set sbpcd buffer size...\n");
236 /* this ioctl returns zero on error; exactly wrong, but that's
239 if(ioctl(d
->ioctl_fd
, CDROMAUDIOBUFSIZ
, d
->nsectors
)==0){
244 sprintf(buffer
,"\tTrouble setting buffer size. Defaulting to %d sectors.\n",
247 break; /* Oh, well. Try to read anyway.*/
251 sprintf(buffer
,"\tSetting read block size at %d sectors (%ld bytes).\n",
252 d
->nsectors
,(long)d
->nsectors
*CD_FRAMESIZE_RAW
);
263 d
->nsectors
=8; /* it's a define in the linux kernel; we have no
264 way of determining other than this guess tho */
268 check_exceptions(d
,atapi_list
);
274 d
->enable_cdda
= Dummy
;
275 d
->read_audio
= cooked_read
;
276 d
->read_toc
= cooked_readtoc
;
277 d
->set_speed
= cooked_setspeed
;
278 ret
=d
->tracks
=d
->read_toc(d
);
283 if((ret
=verify_read_command(d
)))return(ret
);