2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)interface.c 1.40 06/02/19 Copyright 1998-2002 Heiko Eissfeldt, Copyright 2006 J. Schilling */
15 * CopyPolicy: GNU Public License 2 applies
16 * Copyright (C) 1994-1997 Heiko Eissfeldt heiko@colossus.escape.de
18 * Interface module for cdrom drive access
20 * Two interfaces are possible.
22 * 1. using 'cooked' ioctls() (Linux only)
23 * : available for atapi, sbpcd and cdu31a drives only.
25 * 2. using the generic scsi device (for details see SCSI Prog. HOWTO).
26 * NOTE: a bug/misfeature in the kernel requires blocking signal
27 * SIGINT during SCSI command handling. Once this flaw has
28 * been removed, the sigprocmask SIG_BLOCK and SIG_UNBLOCK calls
29 * should removed, thus saving context switches.
31 * For testing purposes I have added a third simulation interface.
33 * Version 0.8: used experiences of Jochen Karrer.
34 * SparcLinux port fixes
35 * AlphaLinux port fixes
55 #include <sys/ioctl.h>
61 /* some include file locations have changed with newer kernels */
62 #if defined (__linux__)
63 # if LINUX_VERSION_CODE > 0x10300 + 97
64 # if LINUX_VERSION_CODE < 0x200ff
65 # include <linux/sbpcd.h>
66 # include <linux/ucdrom.h>
68 # if !defined(CDROM_SELECT_SPEED)
69 # include <linux/ucdrom.h>
74 #include <usal/scsitransp.h>
77 #include "byteorder.h"
78 #include "interface.h"
86 #include "exitcodes.h"
87 #include "scsi_cmds.h"
91 #include "scsi_scan.h"
95 int trackindex_disp = 0;
101 void (*EnableCdda)(SCSI *, int Switch, unsigned uSectorsize);
102 unsigned (*doReadToc)(SCSI *usalp);
103 void (*ReadTocText)(SCSI *usalp);
104 unsigned (*ReadLastAudio)(SCSI *usalp);
105 int (*ReadCdRom)(SCSI *usalp, UINT4 *p, unsigned lSector,
106 unsigned SectorBurstVal);
107 int (*ReadCdRomData)(SCSI *usalp, unsigned char *p, unsigned lSector,
108 unsigned SectorBurstVal);
109 int (*ReadCdRomSub)(SCSI *usalp, UINT4 *p, unsigned lSector,
110 unsigned SectorBurstVal);
111 subq_chnl *(*ReadSubChannels)(SCSI *usalp, unsigned lSector);
112 subq_chnl *(*ReadSubQ)(SCSI *usalp, unsigned char sq_format,
113 unsigned char track);
114 void (*SelectSpeed)(SCSI *usalp, unsigned speed);
115 int (*Play_at)(SCSI *usalp, unsigned int from_sector, unsigned int sectors);
116 int (*StopPlay)(SCSI *usalp);
117 void (*trash_cache)(UINT4 *p, unsigned lSector, unsigned SectorBurstVal);
119 #if defined USE_PARANOIA
120 long cdda_read(void *d, void *buffer, long beginsector, long sectors);
122 long cdda_read(void *d, void *buffer, long beginsector, long sectors)
124 long ret = ReadCdRom(d, buffer, beginsector, sectors);
129 typedef struct string_len {
134 static mystring drv_is_not_mmc[] = {
135 {"DEC RRD47 (C) DEC ",24},
136 /* {"SONY CD-ROM CDU625 1.0",28}, */
137 {NULL,0} /* must be last entry */
140 static mystring drv_has_mmc_cdda[] = {
141 {"HITACHI CDR-7930",16},
142 /* {"TOSHIBA CD-ROM XM-5402TA3605",28}, */
143 {NULL,0} /* must be last entry */
146 static int Is_a_Toshiba3401;
148 int Toshiba3401(void);
152 return Is_a_Toshiba3401;
156 static void Dummy(void);
163 SCSI *get_scsi_p(void);
172 static void trash_cache_SCSI(UINT4 *p, unsigned lSector,
173 unsigned SectorBurstVal);
175 static void trash_cache_SCSI(UINT4 *p, unsigned lSector,
176 unsigned SectorBurstVal)
178 /* trash the cache */
179 ReadCdRom(get_scsi_p(), p, find_an_off_sector(lSector, SectorBurstVal), min(global.nsectors,6));
184 static void Check_interface_for_device(struct stat *statstruct,
186 static int OpenCdRom(char *pdev_name);
188 static void SetupSCSI(void);
190 static void SetupSCSI()
194 if (interface != GENERIC_SCSI) {
195 /* unfortunately we have the wrong interface and are
196 * not able to change on the fly */
197 fprintf(stderr, "The generic SCSI interface and devices are required\n");
201 /* do a test unit ready to 'init' the device. */
202 TestForMedium(usalp);
204 /* check for the correct type of unit. */
212 fprintf(stderr, "Inquiry command failed. Aborting...\n");
216 if ((*p != TYPE_ROM && *p != TYPE_WORM)) {
217 fprintf(stderr, "this is neither a scsi cdrom nor a worm device\n");
221 if (global.quiet == 0) {
223 "Type: %s, Vendor '%8.8s' Model '%16.16s' Revision '%4.4s' ",
224 *p == TYPE_ROM ? "ROM" : "WORM"
229 /* generic Sony type defaults */
231 accepts_fua_bit = -1;
232 EnableCdda = (void (*)(SCSI *, int, unsigned))Dummy;
233 ReadCdRom = ReadCdda12;
234 ReadCdRomSub = ReadCddaSubSony;
235 ReadCdRomData = (int (*)(SCSI *, unsigned char *, unsigned, unsigned))ReadStandardData;
236 ReadLastAudio = ReadFirstSessionTOCSony;
237 SelectSpeed = SpeedSelectSCSISony;
238 Play_at = Play_atSCSI;
239 StopPlay = StopPlaySCSI;
240 trash_cache = trash_cache_SCSI;
241 ReadTocText = ReadTocTextSCSIMMC;
242 doReadToc = ReadTocSCSI;
243 ReadSubQ = ReadSubQSCSI;
244 ReadSubChannels = NULL;
246 /* check for brands and adjust special peculiaritites */
248 /* If your drive is not treated correctly, you can adjust some things
251 global.in_lendian: should be to 1, if the CDROM drive or CD-Writer
252 delivers the samples in the native byteorder of the audio cd
254 HP CD-Writers need it set to 0.
255 NOTE: If you get correct wav files when using sox with the '-x' option,
256 the endianess is wrong. You can use the -C option to specify
257 the value of global.in_lendian.
265 allow_atapi(usalp, 1);
266 if (*p == TYPE_ROM) {
267 mmc_code = heiko_mmc(usalp);
273 /* Exceptions for drives that report incorrect MMC capability */
275 /* these drives are NOT capable of MMC commands */
276 mystring *pp = drv_is_not_mmc;
277 while (pp->str != NULL) {
278 if (!strncmp(pp->str, (char *)p+8,pp->sl)) {
286 /* these drives flag themselves as non-MMC, but offer CDDA reading
287 only with a MMC method. */
288 mystring *pp = drv_has_mmc_cdda;
289 while (pp->str != NULL) {
290 if (!strncmp(pp->str, (char *)p+8,pp->sl)) {
299 case 2: /* SCSI-3 cdrom drive with accurate audio stream */
301 case 1: /* SCSI-3 cdrom drive with no accurate audio stream */
304 global.in_lendian = 1;
309 ReadCdRom = ReadCddaFallbackMMC;
310 ReadCdRomSub = ReadCddaSubSony;
311 ReadLastAudio = ReadFirstSessionTOCMMC;
312 SelectSpeed = SpeedSelectSCSIMMC;
313 ReadTocText = ReadTocTextSCSIMMC;
314 doReadToc = ReadTocMMC;
315 ReadSubChannels = ReadSubChannelsFallbackMMC;
316 if (!memcmp(p+8,"SONY CD-RW CRX100E 1.0", 27)) ReadTocText = NULL;
317 if (!global.quiet) fprintf(stderr, "MMC+CDDA\n");
319 case -1: /* "MMC drive does not support cdda reading, sorry\n." */
320 doReadToc = ReadTocMMC;
321 if (!global.quiet) fprintf(stderr, "MMC-CDDA\n");
323 case 0: /* non SCSI-3 cdrom drive */
324 if (!global.quiet) fprintf(stderr, "no MMC\n");
325 ReadLastAudio = NULL;
326 if (!memcmp(p+8,"TOSHIBA", 7) ||
327 !memcmp(p+8,"IBM", 3) ||
328 !memcmp(p+8,"DEC", 3)) {
330 * older Toshiba ATAPI drives don't identify themselves as MMC.
331 * The last digit of the model number is '2' for ATAPI drives.
332 * These are treated as MMC.
334 if (!memcmp(p+15, " CD-ROM XM-", 11) && p[29] == '2') {
338 EnableCdda = EnableCddaModeSelect;
339 ReadSubChannels = ReadStandardSub;
340 ReadCdRom = ReadStandard;
341 SelectSpeed = SpeedSelectSCSIToshiba;
342 if (!memcmp(p+15, " CD-ROM XM-3401",15)) {
343 Is_a_Toshiba3401 = 1;
345 global.in_lendian = 1;
346 } else if (!memcmp(p+8,"IMS",3) ||
347 !memcmp(p+8,"KODAK",5) ||
348 !memcmp(p+8,"RICOH",5) ||
349 !memcmp(p+8,"HP",2) ||
350 !memcmp(p+8,"PHILIPS",7) ||
351 !memcmp(p+8,"PLASMON",7) ||
352 !memcmp(p+8,"GRUNDIG CDR100IPW",17) ||
353 !memcmp(p+8,"MITSUMI CD-R ",13)) {
354 EnableCdda = EnableCddaModeSelect;
355 ReadCdRom = ReadStandard;
356 SelectSpeed = SpeedSelectSCSIPhilipsCDD2600;
358 /* treat all of these as bigendian */
359 global.in_lendian = 0;
361 /* no overlap reading for cd-writers */
363 } else if (!memcmp(p+8,"NRC",3)) {
365 } else if (!memcmp(p+8,"YAMAHA",6)) {
366 EnableCdda = EnableCddaModeSelect;
367 SelectSpeed = SpeedSelectSCSIYamaha;
369 /* no overlap reading for cd-writers */
371 global.in_lendian = 1;
372 } else if (!memcmp(p+8,"PLEXTOR",7)) {
373 global.in_lendian = 1;
375 ReadLastAudio = ReadFirstSessionTOCSony;
376 ReadTocText = ReadTocTextSCSIMMC;
377 doReadToc = ReadTocSony;
378 ReadSubChannels = ReadSubChannelsSony;
379 } else if (!memcmp(p+8,"SONY",4)) {
380 global.in_lendian = 1;
381 if (!memcmp(p+16, "CD-ROM CDU55E",13)) {
382 ReadCdRom = ReadCddaMMC12;
384 ReadLastAudio = ReadFirstSessionTOCSony;
385 ReadTocText = ReadTocTextSCSIMMC;
386 doReadToc = ReadTocSony;
387 ReadSubChannels = ReadSubChannelsSony;
388 } else if (!memcmp(p+8,"NEC",3)) {
389 ReadCdRom = ReadCdda10;
391 SelectSpeed = SpeedSelectSCSINEC;
392 global.in_lendian = 1;
393 if (!memcmp(p+29,"5022.0r",3)) /* I assume all versions of the 502 require this? */
394 global.overlap = 0; /* no overlap reading for NEC CD-ROM 502 */
395 } else if (!memcmp(p+8,"MATSHITA",8)) {
396 ReadCdRom = ReadCdda12Matsushita;
397 global.in_lendian = 1;
399 } /* switch (get_mmc) */
403 /* look if caddy is loaded */
404 if (interface == GENERIC_SCSI) {
406 while (!wait_unit_ready(usalp, 60)) {
407 fprintf(stderr,"load cdrom please and press enter");
414 /* Check to see if the device will support SCSI generic commands. A
415 * better check than simply looking at the device name. Open the
416 * device, issue an inquiry. If they both succeed, there's a good
417 * chance that the device works... */
418 #if defined(__linux__)
419 static int check_linux_scsi_interface(char *pdev_name)
422 unsigned char *p = NULL;
425 dev = usal_open(pdev_name, errstr, sizeof(errstr), 0, 0);
439 /********************** General setup *******************************/
441 /* As the name implies, interfaces and devices are checked. We also
442 adjust nsectors, overlap, and interface for the first time here.
443 Any unnecessary privileges (setuid, setgid) are also dropped here.
445 static void Check_interface_for_device(struct stat *statstruct, char *pdev_name)
447 #if defined(__linux__)
450 #ifndef STAT_MACROS_BROKEN
451 if (!S_ISCHR(statstruct->st_mode) &&
452 !S_ISBLK(statstruct->st_mode)) {
453 fprintf(stderr, "%s is not a device\n",pdev_name);
458 /* Check what type of device we have */
459 #if defined (__linux__)
460 if (check_linux_scsi_interface(pdev_name))
462 if (interface == GENERIC_SCSI && !is_scsi)
464 fprintf(stderr, "device %s does not support generic_scsi; falling back to cooked_ioctl instead\n", pdev_name);
465 interface = COOKED_IOCTL;
467 if ((interface == COOKED_IOCTL) &&
469 (SCSI_GENERIC_MAJOR == major(statstruct->st_rdev)))
471 fprintf(stderr, "device %s is generic_scsi NOT cooked_ioctl\n", pdev_name);
472 interface = GENERIC_SCSI;
476 #if defined (HAVE_ST_RDEV)
477 switch (major(statstruct->st_rdev)) {
478 #if defined (__linux__)
479 case SCSI_GENERIC_MAJOR: /* generic */
481 default: /* ??? what is the proper value here */
483 #ifndef STAT_MACROS_BROKEN
484 #if defined (__linux__)
485 if (!S_ISCHR(statstruct->st_mode)) {
486 fprintf(stderr, "%s is not a char device\n",pdev_name);
490 if (interface != GENERIC_SCSI) {
491 fprintf(stderr, "wrong interface (cooked_ioctl) for this device (%s)\nset to generic_scsi\n", pdev_name);
492 interface = GENERIC_SCSI;
496 default: /* ??? what is the proper value here */
500 #if defined (__linux__) || defined (__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
501 #if defined (__linux__)
502 case SCSI_CDROM_MAJOR: /* scsi cd */
503 default: /* for example ATAPI cds */
505 #if defined (__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
506 #if __FreeBSD_version >= 600021
507 case 0: /* majors abandoned */
510 #if __FreeBSD_version >= 501113
514 case 117: /* pre-GEOM atapi cd */
515 if (!S_ISCHR(statstruct->st_mode)) {
516 fprintf(stderr, "%s is not a char device\n",pdev_name);
519 if (interface != COOKED_IOCTL) {
521 "cdrom device (%s) is not of type generic SCSI. \
522 Setting interface to cooked_ioctl.\n", pdev_name);
523 interface = COOKED_IOCTL;
526 case 19: /* first atapi cd */
529 if (!S_ISBLK(statstruct->st_mode)) {
530 fprintf(stderr, "%s is not a block device\n",pdev_name);
533 #if defined (__linux__)
534 #if LINUX_VERSION_CODE >= 0x20600
535 /* In Linux kernel 2.6 it is better to use the SCSI interface
541 if (interface != COOKED_IOCTL) {
543 "cdrom device (%s) is not of type generic SCSI. \
544 Setting interface to cooked_ioctl.\n", pdev_name);
545 interface = COOKED_IOCTL;
548 if (interface == COOKED_IOCTL) {
549 fprintf(stderr, "\nW: The cooked_ioctl interface is functionally very limited!!\n");
550 #if defined (__linux__)
551 fprintf(stderr, "\nW: For good sampling quality simply use the generic SCSI interface!\n"
552 "For example dev=ATA:1,0,0\n");
561 if (global.overlap >= global.nsectors)
562 global.overlap = global.nsectors-1;
565 /* open the cdrom device */
566 static int OpenCdRom(char *pdev_name)
569 struct stat fstatstruct;
571 /* The device (given by pdevname) can be:
572 a. an SCSI device specified with a /dev/xxx name,
573 b. an SCSI device specified with bus,target,lun numbers,
574 c. a non-SCSI device such as ATAPI or proprietary CDROM devices.
576 #ifdef HAVE_IOCTL_INTERFACE
577 struct stat statstruct;
578 int have_named_device = 0;
580 have_named_device = FALSE;
582 have_named_device = strchr(pdev_name, ':') == NULL
583 && memcmp(pdev_name, "/dev/", 5) == 0;
586 if (have_named_device) {
587 if (stat(pdev_name, &statstruct)) {
588 fprintf(stderr, "cannot stat device %s\n", pdev_name);
591 Check_interface_for_device( &statstruct, pdev_name );
596 if (interface == GENERIC_SCSI) {
603 * Call usal_remote() to force loading the remote SCSI transport library
604 * code that is located in librusal instead of the dummy remote routines
605 * that are located inside libusal.
608 if (pdev_name != NULL &&
609 ((strncmp(pdev_name, "HELP", 4) == 0) ||
610 (strncmp(pdev_name, "help", 4) == 0))) {
614 /* device name, debug, verboseopen */
615 usalp = usal_open(pdev_name, errstr, sizeof(errstr), 0, 0);
618 int err = geterrno();
620 errmsgno(err, "%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
621 errmsgno(EX_BAD, "For possible targets try 'wodim -scanbus'.%s\n",
622 geteuid() ? " Make sure you are root.":"");
626 #if defined(sun) || defined(__sun)
627 fprintf(stderr, "On SunOS/Solaris make sure you have Joerg Schillings usal SCSI driver installed.\n");
629 #if defined (__linux__)
630 fprintf(stderr, "Use the script scan_scsi.linux to find out more.\n");
632 fprintf(stderr, "Probably you did not define your SCSI device.\n");
633 fprintf(stderr, "Set the CDDA_DEVICE environment variable or use the -D option.\n");
634 fprintf(stderr, "You can also define the default device in the Makefile.\n");
635 fprintf(stderr, "For possible transport specifiers try 'wodim dev=help'.\n");
638 usal_settimeout(usalp, 300);
639 usal_settimeout(usalp, 60);
640 usalp->silent = global.scsi_silent;
641 usalp->verbose = global.scsi_verbose;
643 if (global.nsectors > (unsigned) usal_bufsize(usalp, 3*1024*1024)/CD_FRAMESIZE_RAW)
644 global.nsectors = usal_bufsize(usalp, 3*1024*1024)/CD_FRAMESIZE_RAW;
645 if (global.overlap >= global.nsectors)
646 global.overlap = global.nsectors-1;
649 * Newer versions of Linux seem to introduce an incompatible change
650 * and require root privileges or limit RLIMIT_MEMLOCK infinity
651 * in order to get a SCSI buffer in case we did call mlockall(MCL_FUTURE).
653 init_scsibuf(usalp, global.nsectors*CD_FRAMESIZE_RAW);
658 if (global.scandevs) {
659 list_devices(usalp, stdout, 0);
663 if (global.scanbus) {
664 select_target(usalp, stdout);
669 retval = open(pdev_name,O_RDONLY
677 fprintf(stderr, "while opening %s :", pdev_name);
679 exit(DEVICEOPEN_ERROR);
682 /* Do final security checks here */
683 if (fstat(retval, &fstatstruct)) {
684 fprintf(stderr, "Could not fstat %s (fd %d): ", pdev_name, retval);
688 Check_interface_for_device( &fstatstruct, pdev_name );
690 #if defined HAVE_IOCTL_INTERFACE
691 /* Watch for race conditions */
692 if (have_named_device
693 && (fstatstruct.st_dev != statstruct.st_dev ||
694 fstatstruct.st_ino != statstruct.st_ino)) {
695 fprintf(stderr,"Race condition attempted in OpenCdRom. Exiting now.\n");
700 * The structure looks like a desaster :-(
701 * We do this more than once as it is impossible to understand where
702 * the right place would be to do this....
705 usalp->verbose = global.scsi_verbose;
712 /******************* Simulation interface *****************/
715 static unsigned long sim_pos=0;
717 /* read 'SectorBurst' adjacent sectors of audio sectors
718 * to Buffer '*p' beginning at sector 'lSector'
720 static int ReadCdRom_sim(SCSI *x, UINT4 *p, unsigned lSector,
721 unsigned SectorBurstVal);
722 static int ReadCdRom_sim(SCSI *x, UINT4 *p, unsigned lSector,
723 unsigned SectorBurstVal)
726 Int16_t *q = (Int16_t *) p;
729 if (lSector > g_toc[cdtracks].dwStartSector || lSector + SectorBurstVal > g_toc[cdtracks].dwStartSector + 1) {
730 fprintf(stderr, "Read request out of bounds: %u - %u (%d - %d allowed)\n",
731 lSector, lSector + SectorBurstVal, 0, g_toc[cdtracks].dwStartSector);
734 /* jitter with a probability of jprob */
735 if (random() <= jprob) {
736 /* jitter up to jmax samples */
742 fprintf(stderr, ", last_b = %p\n", *last_buffer);
744 for (loop = lSector*CD_FRAMESAMPLES + joffset;
745 loop < (lSector+SectorBurstVal)*CD_FRAMESAMPLES + joffset;
751 fprintf(stderr, "sim wrote from %p upto %p - 4 (%d), last_b = %p\n",
752 p, q, SectorBurstVal*CD_FRAMESAMPLES, *last_buffer);
754 sim_pos = (lSector+SectorBurstVal)*CD_FRAMESAMPLES + joffset;
755 return SectorBurstVal;
758 static int Play_at_sim(SCSI *x, unsigned int from_sector, unsigned int sectors);
759 static int Play_at_sim(SCSI *x, unsigned int from_sector, unsigned int sectors)
761 sim_pos = from_sector*CD_FRAMESAMPLES;
765 static unsigned sim_indices;
768 /* read the table of contents (toc) via the ioctl interface */
769 static unsigned ReadToc_sim(SCSI *x, TOC *toc);
770 static unsigned ReadToc_sim(SCSI *x, TOC *toc)
772 unsigned int scenario;
790 fprintf(stderr, "select one of the following TOCs\n"
791 "0 : 1 track with 1 index\n"
792 "1 : 1 track with 2 indices\n"
793 "2 : 1 track with 99 indices\n"
794 "3 : 2 tracks with 1 index each\n"
795 "4 : 2 tracks with 2 indices each\n"
796 "5 : 2 tracks with 99 indices each\n"
797 "6 : 2 tracks (data and audio) with 1 index each\n"
798 "7 : 5 tracks with 2 indices each\n"
799 "8 : 5 tracks with 99 indices each\n"
800 "9 : 99 tracks with 1 index each\n"
801 "10: 99 tracks with 2 indices each\n"
802 "11: 99 tracks with 99 indices each\n"
806 scanf("%u", &scenario);
807 } while (scenario > sizeof(scen)/2/sizeof(int));
811 /* build table of contents */
814 trcks = scen[scenario][0] + 1;
815 sim_indices = scen[scenario][1];
817 for (i = 0; i < trcks; i++) {
818 toc[i].bFlags = (scenario == 6 && i == 0) ? 0x40 : 0xb1;
819 toc[i].bTrack = i + 1;
820 toc[i].dwStartSector = i * scen[scenario][2];
821 toc[i].mins = (toc[i].dwStartSector+150) / (60*75);
822 toc[i].secs = (toc[i].dwStartSector+150 / 75) % (60);
823 toc[i].frms = (toc[i].dwStartSector+150) % (75);
825 toc[i].bTrack = 0xaa;
826 toc[i].dwStartSector = i * scen[scenario][2];
827 toc[i].mins = (toc[i].dwStartSector+150) / (60*75);
828 toc[i].secs = (toc[i].dwStartSector+150 / 75) % (60);
829 toc[i].frms = (toc[i].dwStartSector+150) % (75);
832 int starts[15] = { 23625, 30115, 39050, 51777, 67507,
833 88612, 112962, 116840, 143387, 162662,
834 173990, 186427, 188077, 209757, 257120};
838 for (i = 0; i < trcks; i++) {
840 toc[i].bTrack = i + 1;
841 toc[i].dwStartSector = starts[i];
842 toc[i].mins = (starts[i]+150) / (60*75);
843 toc[i].secs = (starts[i]+150 / 75) % (60);
844 toc[i].frms = (starts[i]+150) % (75);
846 toc[i].bTrack = 0xaa;
847 toc[i].dwStartSector = starts[i];
848 toc[i].mins = (starts[i]) / (60*75);
849 toc[i].secs = (starts[i] / 75) % (60);
850 toc[i].frms = (starts[i]) % (75);
853 return --trcks; /* without lead-out */
857 static subq_chnl *ReadSubQ_sim(SCSI *usalp, unsigned char sq_format,
858 unsigned char track);
859 /* request sub-q-channel information. This function may cause confusion
860 * for a drive, when called in the sampling process.
862 static subq_chnl *ReadSubQ_sim(SCSI *usalp, unsigned char sq_format,
865 subq_chnl *SQp = (subq_chnl *) (SubQbuffer);
866 subq_position *SQPp = (subq_position *) &SQp->data;
867 unsigned long sim_pos1;
868 unsigned long sim_pos2;
870 if ( sq_format != GET_POSITIONDATA ) return NULL; /* not supported by sim */
872 /* simulate CDROMSUBCHNL ioctl */
874 /* copy to SubQbuffer */
875 SQp->audio_status = 0;
877 SQp->control_adr = 0xff;
878 sim_pos1 = sim_pos/CD_FRAMESAMPLES;
879 sim_pos2 = sim_pos1 % 150;
880 SQp->track = (sim_pos1 / 5000) + 1;
881 SQp->index = ((sim_pos1 / 150) % sim_indices) + 1;
883 SQPp->abs_min = sim_pos1 / (75*60);
884 SQPp->abs_sec = (sim_pos1 / 75) % 60;
885 SQPp->abs_frame = sim_pos1 % 75;
886 SQPp->trel_min = sim_pos2 / (75*60);
887 SQPp->trel_sec = (sim_pos2 / 75) % 60;
888 SQPp->trel_frame = sim_pos2 % 75;
890 return (subq_chnl *)(SubQbuffer);
893 static void SelectSpeed_sim(SCSI *x, unsigned sp);
895 static void SelectSpeed_sim(SCSI *x, unsigned sp)
899 static void trash_cache_sim(UINT4 *p, unsigned lSector,
900 unsigned SectorBurstVal);
903 static void trash_cache_sim(UINT4 *p, unsigned lSector,
904 unsigned SectorBurstVal)
908 static void SetupSimCd(void);
910 static void SetupSimCd()
912 EnableCdda = (void (*)(SCSI *, int, unsigned))Dummy;
913 ReadCdRom = ReadCdRom_sim;
914 ReadCdRomData = (int (*)(SCSI *, unsigned char *, unsigned, unsigned))ReadCdRom_sim;
915 doReadToc = ReadToc_sim;
917 ReadSubQ = ReadSubQ_sim;
918 ReadSubChannels = NULL;
919 ReadLastAudio = NULL;
920 SelectSpeed = SelectSpeed_sim;
921 Play_at = Play_at_sim;
922 StopPlay = (int (*)(SCSI *))Dummy;
923 trash_cache = trash_cache_sim;
927 #endif /* def SIM_CD */
929 /* perform initialization depending on the interface used. */
930 void SetupInterface()
933 fprintf( stderr, "SIMULATION MODE !!!!!!!!!!!\n");
935 /* ensure interface is setup correctly */
936 global.cooked_fd = OpenCdRom ( global.dev_name );
939 global.pagesize = getpagesize();
941 /* request one sector for table of contents */
942 bufferTOC = malloc( CD_FRAMESIZE_RAW + 96 ); /* assumes sufficient aligned addresses */
943 /* SubQchannel buffer */
944 SubQbuffer = malloc( 48 ); /* assumes sufficient aligned addresses */
945 cmd = malloc( 18 ); /* assumes sufficient aligned addresses */
946 if ( !bufferTOC || !SubQbuffer || !cmd ) {
947 fprintf( stderr, "Too low on memory. Giving up.\n");
952 usalp = malloc(sizeof(* usalp));
954 FatalError("No memory for SCSI structure.\n");
959 /* if drive is of type scsi, get vendor name */
960 if (interface == GENERIC_SCSI) {
961 unsigned sector_size;
964 sector_size = get_orig_sectorsize(usalp, &orgmode4, &orgmode10, &orgmode11);
965 if (!SCSI_emulated_ATAPI_on(usalp)) {
966 if ( sector_size != 2048 && set_sectorsize(usalp, 2048) ) {
967 fprintf( stderr, "Could not change sector size from %d to 2048\n", sector_size );
973 /* get cache setting */
975 /* set cache to zero */
978 #if defined (HAVE_IOCTL_INTERFACE)
979 usalp = malloc(sizeof(* usalp));
981 FatalError("No memory for SCSI structure.\n");
984 SetupCookedIoctl( global.dev_name );
986 FatalError("Sorry, there is no known method to access the device.\n");
989 #endif /* if def SIM_CD */
991 * The structure looks like a desaster :-(
992 * We do this more than once as it is impossible to understand where
993 * the right place would be to do this....
996 usalp->verbose = global.scsi_verbose;
1007 #ifdef HAVE_PRIV_SET
1009 * Give up privs we do not need anymore.
1010 * We no longer need:
1011 * file_dac_read,sys_devices,proc_priocntl,net_privaddr
1013 priv_set(PRIV_OFF, PRIV_EFFECTIVE,
1014 PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
1015 PRIV_NET_PRIVADDR, NULL);
1016 priv_set(PRIV_OFF, PRIV_INHERITABLE,
1017 PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
1018 PRIV_NET_PRIVADDR, PRIV_SYS_DEVICES, NULL);
1025 #ifdef HAVE_PRIV_SET
1027 * Get back privs we may need now.
1029 * file_dac_read,sys_devices,proc_priocntl,net_privaddr
1031 priv_set(PRIV_ON, PRIV_EFFECTIVE,
1032 PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
1033 PRIV_NET_PRIVADDR, NULL);
1040 #ifdef HAVE_PRIV_SET
1042 * Give up privs we do not need anymore.
1043 * We no longer need:
1044 * file_dac_read,sys_devices,proc_priocntl,net_privaddr
1046 priv_set(PRIV_OFF, PRIV_EFFECTIVE,
1047 PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
1048 PRIV_NET_PRIVADDR, NULL);