refinements/compat fixes to fisrt-stage cache/timing tests
[xiph/unicode.git] / cdparanoia / interface / cooked_interface.c
blobde290551ff4bd432833c07d044f9e5fad1f99467
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"
11 #include "utils.h"
12 #include <time.h>
13 static int timed_ioctl(cdrom_drive *d, int fd, int command, void *arg){
14 struct timespec tv1;
15 struct timespec tv2;
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);
19 if(ret1<0 || ret3<0){
20 d->private->last_milliseconds=-1;
21 }else{
22 d->private->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000. + (tv2.tv_nsec-tv1.tv_nsec)/1000000.;
24 return ret2;
27 static int cooked_readtoc (cdrom_drive *d){
28 int i;
29 int tracks;
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 ))
35 switch(errno){
36 case EPERM:
37 cderror(d,"102: Permision denied on cdrom (ioctl) device\n");
38 return(-102);
39 default:
40 cderror(d,"004: Unable to read table of contents header\n");
41 return(-4);
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");
50 return(-5);
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");
62 return(-5);
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)
76 if(d->ioctl_fd!=-1)
77 return ioctl(d->ioctl_fd, CDROM_SELECT_SPEED, speed);
78 else
79 return 0;
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);
95 arg.addr.lba = begin;
96 arg.addr_format = CDROM_LBA;
97 arg.nframes = sectors;
98 arg.buf=buffer;
99 retry_count=0;
101 do {
102 if((err=timed_ioctl(d,d->ioctl_fd, CDROMREADAUDIO, &arg))){
103 if(!d->error_retry){
104 ret=-7;
105 goto done;
107 switch(errno){
108 case ENOMEM:
109 /* D'oh. Possible kernel error. Keep limping */
110 if(sectors==1){
111 /* Nope, can't continue */
112 cderror(d,"300: Kernel memory error\n");
113 ret=-300;
114 goto done;
116 case ENXIO:
117 case EBADF:
118 case ENOMEDIUM:
119 errno=ENOMEDIUM;
120 ret=0;
121 goto done;
122 default:
123 if(sectors==1){
126 /* *Could* be I/O or media error. I think. If we're at
127 30 retries, we better skip this unhappy little
128 sector. */
129 if(retry_count>MAX_RETRIES-1){
130 char b[256];
131 sprintf(b,"010: Unable to access sector %ld: skipping...\n",
132 begin);
133 cderror(d,b);
134 ret=-10;
135 goto done;
137 break;
140 if(retry_count>4)
141 if(sectors>1)
142 sectors=sectors*3/4;
143 retry_count++;
144 if(retry_count>MAX_RETRIES){
145 cderror(d,"007: Unknown, unrecoverable error reading data\n");
146 ret=-7;
147 goto done;
149 }else
150 break;
151 } while (err);
153 ret=sectors;
155 done:
156 if(p==NULL && buffer)free(buffer);
157 return ret;
160 /* hook */
161 static int Dummy (cdrom_drive *d,int Switch){
162 return(0);
165 static int verify_read_command(cdrom_drive *d){
166 int i;
167 int16_t *buff=malloc(CD_FRAMESIZE_RAW);
168 int audioflag=0;
170 cdmessage(d,"Verifying drive can read CDDA...\n");
172 d->enable_cdda(d,1);
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;
179 audioflag=1;
181 if(d->read_audio(d,buff,sector,1)>0){
182 cdmessage(d,"\tExpected command set reads OK.\n");
183 d->enable_cdda(d,0);
184 free(buff);
185 return(0);
190 d->enable_cdda(d,0);
192 if(!audioflag){
193 cdmessage(d,"\tCould not find any audio tracks on this disk.\n");
194 return(-403);
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");
202 free(buff);
203 return(-6);
206 #include "drive_exceptions.h"
208 static void check_exceptions(cdrom_drive *d,exception *list){
210 int i=0;
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;
214 return;
216 i++;
220 /* set function pointers to use the ioctl routines */
221 int cooked_init_drive (cdrom_drive *d){
222 int ret;
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");
233 d->nsectors=8;
234 while(1){
236 /* this ioctl returns zero on error; exactly wrong, but that's
237 what it does. */
239 if(ioctl(d->ioctl_fd, CDROMAUDIOBUFSIZ, d->nsectors)==0){
240 d->nsectors>>=1;
241 if(d->nsectors==0){
242 char buffer[256];
243 d->nsectors=8;
244 sprintf(buffer,"\tTrouble setting buffer size. Defaulting to %d sectors.\n",
245 d->nsectors);
246 cdmessage(d,buffer);
247 break; /* Oh, well. Try to read anyway.*/
249 }else{
250 char buffer[256];
251 sprintf(buffer,"\tSetting read block size at %d sectors (%ld bytes).\n",
252 d->nsectors,(long)d->nsectors*CD_FRAMESIZE_RAW);
253 cdmessage(d,buffer);
254 break;
258 break;
259 case IDE0_MAJOR:
260 case IDE1_MAJOR:
261 case IDE2_MAJOR:
262 case IDE3_MAJOR:
263 d->nsectors=8; /* it's a define in the linux kernel; we have no
264 way of determining other than this guess tho */
265 d->bigendianp=0;
266 d->is_atapi=1;
268 check_exceptions(d,atapi_list);
270 break;
271 default:
272 d->nsectors=40;
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);
279 if(d->tracks<1)
280 return(ret);
282 d->opened=1;
283 if((ret=verify_read_command(d)))return(ret);
284 d->error_retry=1;
285 return(0);