1 /* @(#)ioctl.c 1.39 10/12/19 Copyright 1998,1999,2000 Heiko Eissfeldt, Copyright 2006-2010 J. Schilling */
2 #include "config.h"
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)ioctl.c 1.39 10/12/19 Copyright 1998,1999,2000 Heiko Eissfeldt, Copyright 2006-2010 J. Schilling";
6
7 #endif
8 /*
9 * Copyright (C) 1999 Heiko Eissfeldt heiko@colossus.escape.de
10 * Copyright (c) 2006-2010 J. Schilling
11 *
12 * Ioctl interface module for cdrom drive access
13 *
14 * Solaris ATAPI cdrom drives are untested!
15 *
16 */
17 /*
18 * The contents of this file are subject to the terms of the
19 * Common Development and Distribution License, Version 1.0 only
20 * (the "License"). You may not use this file except in compliance
21 * with the License.
22 *
23 * See the file CDDL.Schily.txt in this distribution for details.
24 * A copy of the CDDL is also available via the Internet at
25 * http://www.opensource.org/licenses/cddl1.txt
26 *
27 * When distributing Covered Code, include this CDDL HEADER in each
28 * file and include the License file CDDL.Schily.txt from this distribution.
29 */
30
31 #include "config.h"
32 #include <schily/stdio.h>
33 #include <schily/standard.h>
34 #include <schily/stdlib.h>
35 #include <schily/unistd.h>
36 #include <schily/string.h>
37 #include <schily/errno.h>
38 #include <schily/signal.h>
39 #include <schily/fcntl.h>
40 #include <schily/assert.h>
41 #include <schily/ioctl.h>
42 #include <schily/stat.h>
43 #include <schily/schily.h>
44 #include <schily/nlsdefs.h>
45 #include <schily/device.h>
46
47 #include <scg/scsitransp.h>
48
49 #include "mycdrom.h"
50 #include "lowlevel.h"
51 /* some include file locations have changed with newer kernels */
52 #if defined(__linux__)
53 # if LINUX_VERSION_CODE > 0x10300 + 97
54 # if LINUX_VERSION_CODE < 0x200ff
55 # include <linux/sbpcd.h>
56 # include <linux/ucdrom.h>
57 # endif
58 # if !defined(CDROM_SELECT_SPEED)
59 # include <linux/ucdrom.h>
60 # endif
61 # endif
62 #endif
63
64 #include "mytype.h"
65 #include "byteorder.h"
66 #include "interface.h"
67 #include "toc.h"
68 #include "cdda2wav.h"
69 #include "ioctl.h"
70 #include "global.h"
71 #include "exitcodes.h"
72
73 #include <schily/utypes.h>
74 #include <cdrecord.h>
75
76 #if defined(HAVE_IOCTL_INTERFACE)
77 #if !defined(sun) && !defined(__sun) && \
78 !((defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && \
79 (__FreeBSD_version >= 501112))
80 static struct cdrom_read_audio arg;
81 #endif
82
83 #if ((defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && \
84 __FreeBSD_version >= 400014) || \
85 defined(__DragonFly__)
86 static unsigned sector_size;
87 #endif
88
89 static int err;
90
91 static void EnableCdda_cooked __PR((SCSI *scgp, int fAudioMode,
92 unsigned uSectorsize));
93 /* ARGSUSED */
94 static void
EnableCdda_cooked(scgp,fAudioMode,uSectorsize)95 EnableCdda_cooked(scgp, fAudioMode, uSectorsize)
96 SCSI *scgp;
97 int fAudioMode;
98 unsigned uSectorsize;
99 {
100 #if ((defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && \
101 __FreeBSD_version >= 400014) || \
102 defined(__DragonFly__)
103 if (scgp && scgp->verbose)
104 fprintf(stderr, _("EnableCdda_cooked (CDRIOCSETBLOCKSIZE)...\n"));
105
106 if (fAudioMode) {
107 if (ioctl(global.cooked_fd, CDRIOCGETBLOCKSIZE,
108 §or_size) == -1)
109 sector_size = CD_FRAMESIZE;
110 ioctl(global.cooked_fd, CDRIOCSETBLOCKSIZE, &uSectorsize);
111 } else
112 ioctl(global.cooked_fd, CDRIOCSETBLOCKSIZE, §or_size);
113 #else
114 #if defined CDIOCSETCDDA
115 if (scgp && scgp->verbose) {
116 fprintf(stderr, _("EnableCdda_cooked (CDIOCSETCDDA)...\n"));
117 if (uSectorsize != CD_FRAMESIZE_RAW)
118 fprintf(stderr, _("non audio sector size is ignored.\n"));
119 }
120
121 ioctl(global.cooked_fd, CDIOCSETCDDA, &fAudioMode);
122 #else
123 fprintf(stderr,
124 _("EnableCdda_cooked (CDIOCSETCDDA) is not available...\n"));
125 #endif
126 #endif
127
128 }
129
130
131 static unsigned ReadToc_cooked __PR((SCSI *x));
132
133 /* read the table of contents (toc) via the ioctl interface */
134 static unsigned
ReadToc_cooked(x)135 ReadToc_cooked(x)
136 SCSI *x;
137 {
138 unsigned i;
139 unsigned tracks;
140 struct cdrom_tochdr hdr;
141 struct cdrom_tocentry entry[100];
142 struct cdrom_tocentry entryMSF[100];
143
144 if (x && x->verbose) {
145 fprintf(stderr, _("ReadToc_cooked (CDROMREADTOCHDR)...\n"));
146 }
147
148 /*
149 * get TocHeader to find out how many entries there are
150 */
151 err = ioctl(global.cooked_fd, CDROMREADTOCHDR, &hdr);
152 if (err != 0) {
153 /*
154 * error handling
155 */
156 if (err == -1) {
157 if (errno == EPERM) {
158 fprintf(stderr,
159 _("Please run this program setuid root.\n"));
160 }
161 errmsg(_("Cooked: Error in read TOC.\n"));
162 exit(DEVICE_ERROR);
163 } else {
164 errmsgno(EX_BAD,
165 _("Can't get TocHeader (error %d).\n"), err);
166 exit(MEDIA_ERROR);
167 }
168 }
169 /*
170 * get all TocEntries
171 */
172 for (i = 0; i < hdr.cdth_trk1; i++) {
173 entryMSF[i].cdte_track = 1+i;
174 entryMSF[i].cdte_format = CDROM_MSF;
175 err = ioctl(global.cooked_fd, CDROMREADTOCENTRY, &entryMSF[i]);
176 if (err != 0) {
177 /*
178 * error handling
179 */
180 errmsg(("Can't get TocEntry #%d msf (error %d).\n"),
181 i+1, err);
182 exit(MEDIA_ERROR);
183 }
184 }
185 entryMSF[i].cdte_track = CDROM_LEADOUT;
186 entryMSF[i].cdte_format = CDROM_MSF;
187 err = ioctl(global.cooked_fd, CDROMREADTOCENTRY, &entryMSF[i]);
188 if (err != 0) {
189 /*
190 * error handling
191 */
192 errmsg(_("Can't get TocEntry LEADOUT msf (error %d).\n"),
193 err);
194 exit(MEDIA_ERROR);
195 }
196 tracks = hdr.cdth_trk1+1;
197 #ifdef nonono
198 for (i = 0; i < tracks; i++) {
199 toc[i].bFlags = (entry[i].cdte_adr << 4) | (entry[i].cdte_ctrl & 0x0f);
200 toc[i].bTrack = entry[i].cdte_track;
201 toc[i].mins = entry[i].cdte_addr.msf.minute;
202 toc[i].secs = entry[i].cdte_addr.msf.second;
203 toc[i].frms = entry[i].cdte_addr.msf.frame;
204 }
205 #endif
206 /*
207 * get all TocEntries now in lba format
208 */
209 for (i = 0; i < hdr.cdth_trk1; i++) {
210 entry[i].cdte_track = 1+i;
211 entry[i].cdte_format = CDROM_LBA;
212 err = ioctl(global.cooked_fd, CDROMREADTOCENTRY, &entry[i]);
213 if (err != 0) {
214 /*
215 * error handling
216 */
217 errmsg(_("Can't get TocEntry #%d lba (error %d).\n"),
218 i+1, err);
219 exit(MEDIA_ERROR);
220 }
221 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
222 entry[i].cdte_addr.lba = be32_to_cpu(entry[i].cdte_addr.lba);
223 #endif
224 }
225 entry[i].cdte_track = CDROM_LEADOUT;
226 entry[i].cdte_format = CDROM_LBA;
227 err = ioctl(global.cooked_fd, CDROMREADTOCENTRY, &entry[i]);
228 if (err != 0) {
229 /*
230 * error handling
231 */
232 errmsg(_("Can't get TocEntry LEADOUT lba (error %d).\n"),
233 err);
234 exit(MEDIA_ERROR);
235 }
236 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
237 entry[i].cdte_addr.lba = be32_to_cpu(entry[i].cdte_addr.lba);
238 #endif
239
240 for (i = 0; i < tracks; i++) {
241 toc_entry(i+1,
242 (entry[i].cdte_adr << 4) | (entry[i].cdte_ctrl & 0x0f),
243 entry[i].cdte_track,
244 NULL /* ISRC */,
245 entry[i].cdte_addr.lba,
246 entryMSF[i].cdte_addr.msf.minute,
247 entryMSF[i].cdte_addr.msf.second,
248 entryMSF[i].cdte_addr.msf.frame);
249 }
250 bufferTOC[0] = '\0';
251 bufferTOC[1] = '\0';
252 return (--tracks); /* without lead-out */
253 }
254
255 static void trash_cache_cooked __PR((UINT4 *p, unsigned lSector,
256 unsigned SectorBurstVal));
257
258 static void
trash_cache_cooked(p,lSector,SectorBurstVal)259 trash_cache_cooked(p, lSector, SectorBurstVal)
260 UINT4 *p;
261 unsigned lSector;
262 unsigned SectorBurstVal;
263 {
264 /*
265 * trash the cache
266 */
267
268 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
269 defined(__DragonFly__)
270 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && \
271 __FreeBSD_version >= 501112
272 pread(global.cooked_fd, (void *) &p[0], 3*CD_FRAMESIZE_RAW,
273 find_an_off_sector(lSector, SectorBurstVal)*CD_FRAMESIZE_RAW);
274 #else
275 static struct cdrom_read_audio arg2;
276
277 arg2.address.lba = find_an_off_sector(lSector, SectorBurstVal);
278 arg2.addr_format = CDROM_LBA;
279 arg2.nframes = 3;
280 arg2.buffer = (unsigned char *) &p[0];
281
282 ioctl(global.cooked_fd, CDROMREADAUDIO, &arg2);
283 #endif
284 #endif
285 #if defined __linux__
286 static struct cdrom_read_audio arg2;
287
288 arg2.addr.lba = find_an_off_sector(lSector, SectorBurstVal);
289 arg2.addr_format = CDROM_LBA;
290 arg2.nframes = 3;
291 arg2.buf = (unsigned char *) &p[0];
292
293 ioctl(global.cooked_fd, CDROMREADAUDIO, &arg2);
294 #endif
295 #if defined __sun || \
296 (defined HAVE_SYS_CDIO_H && defined CDROM_DA_NO_SUBCODE)
297 struct cdrom_cdda suncdda;
298
299 suncdda.cdda_addr = lSector;
300 suncdda.cdda_length = SectorBurstVal*CD_FRAMESIZE_RAW;
301 suncdda.cdda_data = (char *) &p[0];
302 suncdda.cdda_subcode = CDROM_DA_NO_SUBCODE;
303
304 ioctl(global.cooked_fd, CDROMCDDA, &suncdda);
305 #endif
306 }
307
308 static void ReadCdRomData_cooked __PR((SCSI *x, UINT4 *p, unsigned lSector,
309 unsigned SectorBurstVal));
310 /*
311 * read 'SectorBurst' adjacent sectors of data sectors
312 * to Buffer '*p' beginning at sector 'lSector'
313 */
314 static void
ReadCdRomData_cooked(x,p,lSector,SectorBurstVal)315 ReadCdRomData_cooked(x, p, lSector, SectorBurstVal)
316 SCSI *x;
317 UINT4 *p;
318 unsigned lSector;
319 unsigned SectorBurstVal;
320 {
321 int retval;
322
323 if (x && x->verbose) {
324 fprintf(stderr, _("ReadCdRomData_cooked (lseek & read)...\n"));
325 }
326
327 if ((retval = lseek(global.cooked_fd, lSector*CD_FRAMESIZE, SEEK_SET))
328 != (int)lSector*CD_FRAMESIZE) {
329 errmsg(_("Cannot seek sector.\n"));
330 }
331 if ((retval = read(global.cooked_fd, p, SectorBurstVal*CD_FRAMESIZE))
332 != (int)SectorBurstVal*CD_FRAMESIZE) {
333 errmsg(_("Cannot read sector.\n"));
334 }
335 }
336
337 static int ReadCdRom_cooked __PR((SCSI *x, UINT4 *p, unsigned lSector,
338 unsigned SectorBurstVal));
339 /*
340 * read 'SectorBurst' adjacent sectors of audio sectors
341 * to Buffer '*p' beginning at sector 'lSector'
342 */
343 static int
ReadCdRom_cooked(x,p,lSector,SectorBurstVal)344 ReadCdRom_cooked(x, p, lSector, SectorBurstVal)
345 SCSI *x;
346 UINT4 *p;
347 unsigned lSector;
348 unsigned SectorBurstVal;
349 {
350 int retry_count = 0;
351 static int nothing_read = 1;
352
353 /* read 2352 bytes audio data */
354 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
355 defined(__DragonFly__)
356 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && \
357 __FreeBSD_version >= 501112
358 if (x && x->verbose) {
359 fprintf(stderr, _("ReadCdRom_cooked (pread)...\n"));
360 }
361
362 do {
363 err = 0;
364 if (pread(global.cooked_fd, (void *) &p[0],
365 SectorBurstVal*CD_FRAMESIZE_RAW,
366 lSector*CD_FRAMESIZE_RAW) == -1) {
367 err = -1;
368 }
369 #else
370 arg.address.lba = lSector;
371 arg.addr_format = CDROM_LBA;
372 arg.nframes = SectorBurstVal;
373 arg.buffer = (unsigned char *) &p[0];
374
375 if (x && x->verbose) {
376 fprintf(stderr, _("ReadCdRom_cooked (CDROMREADAUDIO)...\n"));
377 }
378
379 do {
380 err = ioctl(global.cooked_fd, CDROMREADAUDIO, &arg);
381 #endif
382 #endif
383 #if defined __linux__
384 arg.addr.lba = lSector;
385 arg.addr_format = CDROM_LBA;
386 arg.nframes = SectorBurstVal;
387 arg.buf = (unsigned char *) &p[0];
388
389 if (x && x->verbose) {
390 fprintf(stderr, _("ReadCdRom_cooked (CDROMREADAUDIO)...\n"));
391 }
392
393 do {
394 err = ioctl(global.cooked_fd, CDROMREADAUDIO, &arg);
395 #endif
396 #if defined __sun || \
397 (defined HAVE_SYS_CDIO_H && defined CDROM_DA_NO_SUBCODE)
398 struct cdrom_cdda suncdda;
399
400 suncdda.cdda_addr = lSector;
401 suncdda.cdda_length = SectorBurstVal*CD_FRAMESIZE_RAW;
402 suncdda.cdda_data = (char *) &p[0];
403 suncdda.cdda_subcode = CDROM_DA_NO_SUBCODE;
404
405 if (x && x->verbose) {
406 fprintf(stderr, _("ReadCdRom_cooked (CDROMCDDA)...\n"));
407 }
408
409 do {
410 err = ioctl(global.cooked_fd, CDROMCDDA, &suncdda);
411 #endif
412 retry_count++;
413
414 if (err) {
415 trash_cache_cooked(p, lSector, SectorBurstVal);
416 }
417
418 } while ((err) && (retry_count < 30));
419
420 if (err != 0) {
421 if (x->silent == 0) {
422 /*
423 * error handling
424 */
425 if (err == -1) {
426 if (nothing_read &&
427 (errno == EINVAL || errno == EIO)) {
428 fprintf(stderr,
429 _("Sorry, this driver and/or drive does not support cdda reading.\n"));
430 }
431 errmsg(_("Cooked: Error read cdda sector %u + %u, buffer %p + %x\n"),
432 lSector, SectorBurstVal, p,
433 global.shmsize);
434 } else {
435 errmsgno(EX_BAD,
436 _("Can't read frame #%u (error %d).\n"),
437 lSector, err);
438 }
439 }
440 return (SectorBurstVal - 1);
441 } else {
442 nothing_read = 0;
443 }
444
445 return (SectorBurstVal);
446 }
447
448 static int StopPlay_cooked __PR((SCSI *x));
449 static int
450 StopPlay_cooked(x)
451 SCSI *x;
452 {
453 if (x && x->verbose) {
454 fprintf(stderr, _("StopPlay_cooked (CDROMSTOP)...\n"));
455 }
456
457 return (ioctl(global.cooked_fd, CDROMSTOP, 0) ? 0 : -1);
458 }
459
460 static int Play_at_cooked __PR((SCSI *x, unsigned int from_sector,
461 unsigned int sectors));
462 static int
463 Play_at_cooked(x, from_sector, sectors)
464 SCSI *x;
465 unsigned int from_sector;
466 unsigned int sectors;
467 {
468 struct cdrom_msf cmsf;
469 int retval;
470
471 if (x && x->verbose) {
472 fprintf(stderr,
473 _("Play_at_cooked (CDROMSTART & CDROMPLAYMSF)... (%u-%u)"),
474 from_sector, from_sector+sectors-1);
475 fprintf(stderr, "\n");
476 }
477
478 cmsf.cdmsf_min0 = (from_sector + 150) / (60*75);
479 cmsf.cdmsf_sec0 = ((from_sector + 150) / 75) % 60;
480 cmsf.cdmsf_frame0 = (from_sector + 150) % 75;
481 cmsf.cdmsf_min1 = (from_sector + 150 + sectors) / (60*75);
482 cmsf.cdmsf_sec1 = ((from_sector + 150 + sectors) / 75) % 60;
483 cmsf.cdmsf_frame1 = (from_sector + 150 + sectors) % 75;
484
485 #if 0
486 /*
487 * makes index scanning under FreeBSD too slow
488 */
489 if ((retval = ioctl(global.cooked_fd, CDROMSTART, 0)) != 0) {
490 errmsg(_("Cannot do ioctl(%d, CDROMSTART, 0).\n"),
491 global.cooked_fd);
492 }
493 #endif
494 if ((retval = ioctl(global.cooked_fd, CDROMPLAYMSF, &cmsf)) != 0) {
495 errmsg(_("Cannot do ioctl(%d, CDROMPLAYMSF, ...).\n"),
496 global.cooked_fd);
497 }
498 return (retval);
499 }
500
501 #if defined PROTOTYPES
502 static subq_chnl *ReadSubQ_cooked __PR((SCSI *x,
503 unsigned char sq_format,
504 unsigned char track))
505 #else
506 /*
507 * request sub-q-channel information. This function may cause confusion
508 * for a drive, when called in the sampling process.
509 */
510 static subq_chnl *
511 ReadSubQ_cooked(x, sq_format, track)
512 SCSI *x;
513 unsigned char sq_format;
514 unsigned char track;
515 #endif
516 {
517 struct cdrom_subchnl sub_ch;
518
519 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
520 struct cd_sub_channel_info sub_ch_info;
521
522 if (x && x->verbose) {
523 fprintf(stderr,
524 _("ReadSubQ_cooked (CDROM_GET_MCN or CDROMSUBCHNL)...\n"));
525 }
526
527 sub_ch.address_format = CD_MSF_FORMAT;
528 sub_ch.track = track;
529 sub_ch.data_len = sizeof (struct cd_sub_channel_info);
530 sub_ch.data = &sub_ch_info;
531
532 switch (sq_format) {
533
534 case GET_CATALOGNUMBER:
535 sub_ch.data_format = CD_MEDIA_CATALOG;
536 #else
537 if (x && x->verbose) {
538 fprintf(stderr,
539 _("ReadSubQ_cooked (CDROM_GET_MCN or CDROMSUBCHNL)...\n"));
540 }
541
542 switch (sq_format) {
543
544 case GET_CATALOGNUMBER:
545 #endif
546 #if defined CDROM_GET_MCN
547 if (!(err = ioctl(global.cooked_fd, CDROM_GET_MCN,
548 (struct cdrom_mcn *) SubQbuffer))) {
549 subq_chnl *SQp = (subq_chnl *) SubQbuffer;
550 subq_catalog *SQPp = (subq_catalog *) &SQp->data;
551
552 memmove(SQPp->media_catalog_number, SQp,
553 sizeof (SQPp->media_catalog_number));
554 SQPp->zero = 0;
555 SQPp->mc_valid = 0x80;
556 break;
557 } else
558 #endif
559 {
560 return (NULL);
561 }
562
563 case GET_POSITIONDATA:
564 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
565 sub_ch.data_format = CD_CURRENT_POSITION;
566 #endif
567 #if defined(__linux__)
568 sub_ch.cdsc_format = CDROM_MSF;
569 #endif
570 if (!(err = ioctl(global.cooked_fd, CDROMSUBCHNL, &sub_ch))) {
571 /*
572 * copy to SubQbuffer
573 */
574 subq_chnl *SQp = (subq_chnl *) (SubQbuffer);
575 subq_position *SQPp = (subq_position *) SQp->data;
576 SQp->audio_status = sub_ch.cdsc_audiostatus;
577 SQp->format = sub_ch.cdsc_format;
578 SQp->control_adr = (sub_ch.cdsc_adr << 4) |
579 (sub_ch.cdsc_ctrl & 0x0f);
580 SQp->track = sub_ch.cdsc_trk;
581 SQp->index = sub_ch.cdsc_ind;
582 SQPp->abs_min = sub_ch.cdsc_absaddr.msf.minute;
583 SQPp->abs_sec = sub_ch.cdsc_absaddr.msf.second;
584 SQPp->abs_frame = sub_ch.cdsc_absaddr.msf.frame;
585 SQPp->trel_min = sub_ch.cdsc_reladdr.msf.minute;
586 SQPp->trel_sec = sub_ch.cdsc_reladdr.msf.second;
587 SQPp->trel_frame = sub_ch.cdsc_reladdr.msf.frame;
588 } else {
589 if (err == -1) {
590 if (errno == EPERM)
591 fprintf(stderr,
592 _("Please run this program setuid root.\n"));
593 errmsg(_("Cooked: Error in read subq.\n"));
594 exit(DEVICE_ERROR);
595 } else {
596 errmsgno(EX_BAD,
597 _("Can't read sub q channel (error %d).\n"),
598 err);
599 exit(DEVICE_ERROR);
600 }
601 }
602 break;
603
604 default:
605 return (NULL);
606 } /* switch */
607
608 return ((subq_chnl *)(SubQbuffer));
609 }
610
611 /*
612 * Speed control
613 */
614 static void SpeedSelect_cooked __PR((SCSI *x, unsigned speed));
615 /* ARGSUSED */
616 static void
617 SpeedSelect_cooked(x, speed)
618 SCSI *x;
619 unsigned speed;
620 {
621 if (x && x->verbose) {
622 fprintf(stderr,
623 _("SpeedSelect_cooked (CDROM_SELECT_SPEED)...\n"));
624 }
625
626 #ifdef CDROM_SELECT_SPEED
627 /*
628 * CAUTION!!!!! Non standard ioctl parameter types here!!!!
629 */
630 if ((err = ioctl(global.cooked_fd, CDROM_SELECT_SPEED, speed))) {
631 if (err == -1) {
632 if (errno == EPERM) {
633 fprintf(stderr,
634 _("Please run this program setuid root.\n"));
635 }
636 errmsg(_("Cooked: Error in speed select.\n"));
637 /* exit(err); */
638 } else {
639 errmsgno(EX_BAD,
640 _("Can't set speed %d (error %d).\n"),
641 speed, err);
642 exit(DEVICE_ERROR);
643 }
644 }
645 #endif
646 }
647
648 /*
649 * set function pointers to use the ioctl routines
650 */
651 void
652 SetupCookedIoctl(pdev_name)
653 char *pdev_name;
654 {
655 #if (HAVE_ST_RDEV == 1)
656 struct stat statstruct;
657
658 if (fstat(global.cooked_fd, &statstruct)) {
659 errmsg(_("Cannot stat cd %d (%s).\n"),
660 global.cooked_fd, pdev_name);
661 exit(STAT_ERROR);
662 }
663 #if defined __linux__
664 switch (major(statstruct.st_rdev)) {
665
666 case CDU31A_CDROM_MAJOR: /* sony cdu-31a/33a */
667 global.nsectors = 13;
668 if (global.nsectors >= 14) {
669 global.overlap = 10;
670 }
671 break;
672
673 case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */
674 case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */
675 case MATSUSHITA_CDROM3_MAJOR: /* sbpcd 3 */
676 case MATSUSHITA_CDROM4_MAJOR: /* sbpcd 4 */
677 /*
678 * some are more compatible than others
679 */
680 global.nsectors = 13;
681 break;
682
683 default:
684 global.nsectors = 8;
685 break;
686 }
687
688 err = ioctl(global.cooked_fd, CDROMAUDIOBUFSIZ, global.nsectors);
689
690 switch (major(statstruct.st_rdev)) {
691
692 case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */
693 case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */
694 case MATSUSHITA_CDROM3_MAJOR: /* sbpcd 3 */
695 case MATSUSHITA_CDROM4_MAJOR: /* sbpcd 4 */
696
697 if (err == -1) {
698 errmsg(_("Error doing ioctl(CDROMAUDIOBUFSIZ).\n"));
699 }
700 }
701 #endif
702 #endif
703 EnableCdda = EnableCdda_cooked;
704 ReadCdRom = ReadCdRom_cooked;
705 ReadCdRomData = (int (*) __PR((SCSI *,
706 unsigned char *,
707 unsigned, unsigned))) ReadCdRomData_cooked;
708 doReadToc = ReadToc_cooked;
709 ReadTocText = (void (*) __PR((SCSI *)))NULL;
710 ReadSubQ = ReadSubQ_cooked;
711 ReadSubChannels = (subq_chnl * (*) __PR((SCSI *, unsigned)))NULL;
712 SelectSpeed = SpeedSelect_cooked;
713 Play_at = Play_at_cooked;
714 StopPlay = StopPlay_cooked;
715 trash_cache = trash_cache_cooked;
716 ReadLastAudio = (unsigned (*) __PR((SCSI *)))NULL;
717 }
718 #endif
719