interface.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:23k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)interface.c 1.3 00/01/25 Copyright 1998,1999 Heiko Eissfeldt */
  2. #ifndef lint
  3. static char     sccsid[] =
  4. "@(#)interface.c 1.3 00/01/25 Copyright 1998,1999 Heiko Eissfeldt";
  5. #endif
  6. /***
  7.  * CopyPolicy: GNU Public License 2 applies
  8.  * Copyright (C) 1994-1997 Heiko Eissfeldt heiko@colossus.escape.de
  9.  *
  10.  * Interface module for cdrom drive access
  11.  *
  12.  * Two interfaces are possible.
  13.  *
  14.  * 1. using 'cooked' ioctls() (Linux only)
  15.  *    : available for atapi, sbpcd and cdu31a drives only.
  16.  *
  17.  * 2. using the generic scsi device (for details see SCSI Prog. HOWTO).
  18.  *    NOTE: a bug/misfeature in the kernel requires blocking signal
  19.  *          SIGINT during SCSI command handling. Once this flaw has
  20.  *          been removed, the sigprocmask SIG_BLOCK and SIG_UNBLOCK calls
  21.  *          should removed, thus saving context switches.
  22.  *
  23.  * For testing purposes I have added a third simulation interface.
  24.  *
  25.  * Version 0.8: used experiences of Jochen Karrer.
  26.  *              SparcLinux port fixes
  27.  *              AlphaLinux port fixes
  28.  *
  29.  */
  30. #if 0
  31. #define SIM_CD
  32. #endif
  33. #include "config.h"
  34. #include <stdio.h>
  35. #include <standard.h>
  36. #include <stdlib.h>
  37. #include <unixstd.h>
  38. #include <strdefs.h>
  39. #include <errno.h>
  40. #include <signal.h>
  41. #include <fcntl.h>
  42. #include <assert.h>
  43. #include <sys/ioctl.h>
  44. #include <sys/stat.h>
  45. #include <statdefs.h>
  46. #include "mycdrom.h"
  47. #include "lowlevel.h"
  48. /* some include file locations have changed with newer kernels */
  49. #if defined (__linux__)
  50. # if LINUX_VERSION_CODE > 0x10300 + 97
  51. #  if LINUX_VERSION_CODE < 0x200ff
  52. #   include <linux/sbpcd.h>
  53. #   include <linux/ucdrom.h>
  54. #  endif
  55. #  if !defined(CDROM_SELECT_SPEED)
  56. #   include <linux/ucdrom.h>
  57. #  endif
  58. # endif
  59. #endif
  60. #include <scg/scsitransp.h>
  61. #include "mytype.h"
  62. #include "byteorder.h"
  63. #include "interface.h"
  64. #include "cdda2wav.h"
  65. #include "semshm.h"
  66. #include "setuid.h"
  67. #include "ringbuff.h"
  68. #include "toc.h"
  69. #include "global.h"
  70. #include "ioctl.h"
  71. #include "scsi_cmds.h"
  72. #include <utypes.h>
  73. #include <cdrecord.h>
  74. unsigned interface;
  75. int trackindex_disp = 0;
  76. TOC g_toc [MAXTRK]; /* 100 */
  77. unsigned char MCN[14];  /* including a zero string terminator */
  78. void     (*EnableCdda) __PR((SCSI *, int Switch));
  79. unsigned (*ReadToc) __PR(( SCSI *scgp, TOC *ptoc ));
  80. void  (*ReadTocText) __PR(( SCSI *scgp ));
  81. unsigned (*ReadLastAudio) __PR(( SCSI *scgp, unsigned tracks ));
  82. void     (*ReadCdRom) __PR((SCSI *scgp, UINT4 *p, unsigned lSector, unsigned SectorBurstVal ));
  83. void     (*ReadCdRomData) __PR((SCSI *scgp, unsigned char *p, unsigned lSector, unsigned SectorBurstVal ));
  84. subq_chnl *(*ReadSubQ) __PR(( SCSI *scgp, unsigned char sq_format, unsigned char track ));
  85. void     (*SelectSpeed) __PR(( SCSI *scgp, unsigned speed ));
  86. int (*Play_at) __PR(( SCSI *scgp, unsigned int from_sector, unsigned int sectors));
  87. int (*StopPlay) __PR(( SCSI *scgp));
  88. void (*trash_cache) __PR((UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
  89. typedef struct string_len {
  90.   char *str;
  91.   unsigned int sl;
  92. } mystring;
  93. static mystring drv_is_not_mmc[] = {
  94. {"SONY    CD-ROM CDU625    1.0",28},
  95. {NULL,0} /* must be last entry */
  96. };
  97. static mystring drv_has_mmc_cdda[] = {
  98. {NULL,0} /* must be last entry */
  99. };
  100. static int Is_a_Toshiba3401;
  101. int Toshiba3401 __PR((void));
  102. int Toshiba3401 ( ) {
  103.   return Is_a_Toshiba3401;
  104. }
  105. /* hook */
  106. static void Dummy __PR(( void ));
  107. static void Dummy ( )
  108. {
  109. }
  110. static SCSI    *scgp;
  111. SCSI * get_scsi_p __PR((void));
  112. SCSI * get_scsi_p( )
  113. {
  114.     return scgp;
  115. }
  116. #if !defined(SIM_CD)
  117. static void trash_cache_SCSI __PR((UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
  118. static void trash_cache_SCSI(p, lSector, SectorBurstVal)
  119. UINT4 *p;
  120. unsigned lSector;
  121. unsigned SectorBurstVal;
  122. {
  123.       /* trash the cache */
  124.       ReadCdRom(get_scsi_p(), p, find_an_off_sector(lSector, SectorBurstVal), min(global.nsectors,6));
  125. }
  126. static void Check_interface_for_device __PR((struct stat *statstruct, char *pdev_name));
  127. static int OpenCdRom __PR((char *pdev_name));
  128. static void SetupSCSI __PR((void));
  129. static void SetupSCSI( )
  130. {
  131.     unsigned char *p;
  132.     if (interface != GENERIC_SCSI) {
  133. /* unfortunately we have the wrong interface and are
  134.  * not able to change on the fly */
  135. fprintf(stderr, "The generic SCSI interface and devices are requiredn");
  136. exit(1);
  137.     }
  138.     /* do a test unit ready to 'init' the device. */
  139.     TestForMedium(scgp);
  140.     /* check for the correct type of unit. */
  141.     p = Inquiry(scgp);
  142. #undef TYPE_ROM
  143. #define TYPE_ROM 5
  144. #undef TYPE_WORM
  145. #define TYPE_WORM  4
  146.     if (p == NULL) {
  147. fprintf(stderr, "Inquiry command failed. Aborting...n");
  148. exit(1);
  149.     }
  150.     if ((*p != TYPE_ROM && *p != TYPE_WORM)) {
  151. fprintf(stderr, "this is neither a scsi cdrom nor a worm devicen");
  152. exit(1);
  153.     }
  154.     /* generic Sony type defaults */
  155.     density = 0x0;
  156.     accepts_fua_bit = -1;
  157.     accepts_fua_bit = -1;
  158.     EnableCdda = (void (*) __PR((SCSI *, int)))Dummy;
  159.     ReadCdRom = ReadCdda12;
  160.     ReadCdRomData = (void (*) __PR((SCSI *, unsigned char *, unsigned, unsigned ))) ReadStandard;
  161.     ReadLastAudio = ReadFirstSessionTOCSony;
  162.     SelectSpeed = SpeedSelectSCSISony;
  163.     Play_at = Play_atSCSI;
  164.     StopPlay = StopPlaySCSI;
  165.     trash_cache = trash_cache_SCSI;
  166.     ReadTocText = ReadTocTextSCSIMMC;
  167.     /* check for brands and adjust special peculiaritites */
  168.     /* If your drive is not treated correctly, you can adjust some things
  169.        here:
  170.        *in_leendian: should be to 1, if the CDROM drive or CD-Writer
  171.   delivers the samples in the native byteorder of the audio cd
  172.   (LSB first).
  173.   HP CD-Writers need it set to 0.
  174.        NOTE: If you get correct wav files when using sox with the '-x' option,
  175.              the endianess is wrong. You can use the -C option to specify
  176.      the value of (*in_lendian).
  177.      */
  178.     {
  179.       int mmc_code;
  180.       allow_atapi(scgp, 1);
  181.       if (*p == TYPE_ROM) {
  182.         mmc_code = heiko_mmc(scgp);
  183.       } else {
  184.         mmc_code = 0;
  185.       }
  186.       /* Exceptions for drives that report incorrect MMC capability */
  187.       if (mmc_code != 0) {
  188. /* these drives are NOT capable of MMC commands */
  189.         mystring *pp = drv_is_not_mmc;
  190. while (pp->str != NULL) {
  191.   if (!strncmp(pp->str, (char *)p+8,pp->sl)) {
  192.     mmc_code = 0;
  193.     break;
  194.   }
  195.   pp++;
  196.         }
  197.       }
  198.       {
  199. /* these drives flag themselves as non-MMC, but offer CDDA reading
  200.    only with a MMC method. */
  201.         mystring *pp = drv_has_mmc_cdda;
  202. while (pp->str != NULL) {
  203.   if (!strncmp(pp->str, (char *)p+8,pp->sl)) {
  204.     mmc_code = 1;
  205.     break;
  206.   }
  207.   pp++;
  208.         }
  209.       }
  210.       switch (mmc_code) {
  211.        case 2:      /* SCSI-3 cdrom drive with accurate audio stream */
  212.          if ( (*in_lendian) == -1 )
  213.    (*in_lendian) = 1;
  214.          global.overlap = 0;
  215.          ReadCdRom = ReadCddaMMC12;
  216.          ReadLastAudio = ReadFirstSessionTOCMMC;
  217.          global.speed = 0xffff;
  218.          SelectSpeed = SpeedSelectSCSIMMC;
  219.       ReadTocText = ReadTocTextSCSIMMC;
  220.        break;
  221.        case 1:      /* SCSI-3 cdrom drive with no accurate audio stream */
  222.          if ( (*in_lendian) == -1 )
  223.    (*in_lendian) = 1;
  224.          global.overlap = 1;
  225.          ReadCdRom = ReadCddaMMC12;
  226.          ReadLastAudio = ReadFirstSessionTOCMMC;
  227.          global.speed = 0xffff;
  228.          SelectSpeed = SpeedSelectSCSIMMC;
  229.          break;
  230.        case -1: /* "MMC drive does not support cdda reading, sorryn." */
  231. /* fall through */
  232.        case 0:      /* non SCSI-3 cdrom drive */
  233.          ReadLastAudio = NULL;
  234.     if (!memcmp(p+8,"TOSHIBA", 7) ||
  235.         !memcmp(p+8,"IBM", 3) ||
  236.         !memcmp(p+8,"DEC", 3)) {
  237. density = 0x82;
  238. EnableCdda = EnableCddaModeSelect;
  239.   ReadCdRom = ReadStandard;
  240.         SelectSpeed = SpeedSelectSCSIToshiba;
  241.         if (!memcmp(p+16, "CD-ROM XM-3401",14)) {
  242.    Is_a_Toshiba3401 = 1;
  243. }
  244. if ( (*in_lendian) == -1 )
  245. (*in_lendian) = 1;
  246.     } else if (!memcmp(p+8,"IMS",3) ||
  247.                !memcmp(p+8,"KODAK",5) ||
  248.                !memcmp(p+8,"RICOH",5) ||
  249.                !memcmp(p+8,"HP",2) ||
  250.                !memcmp(p+8,"PHILIPS",7) ||
  251.                !memcmp(p+8,"PLASMON",7) ||
  252.                !memcmp(p+8,"GRUNDIG CDR100IPW",17) ||
  253.                !memcmp(p+8,"MITSUMI CD-R ",13)) {
  254. EnableCdda = EnableCddaModeSelect;
  255. ReadCdRom = ReadStandard;
  256.         SelectSpeed = SpeedSelectSCSIPhilipsCDD2600;
  257. /* treat all of these as bigendian */
  258. if ( (*in_lendian) == -1 )
  259. (*in_lendian) = 0;
  260. /* no overlap reading for cd-writers */
  261. global.overlap = 0;
  262.     } else if (!memcmp(p+8,"NRC",3)) {
  263.         SelectSpeed = NULL;
  264.     } else if (!memcmp(p+8,"YAMAHA",6)) {
  265. EnableCdda = EnableCddaModeSelect;
  266.         SelectSpeed = SpeedSelectSCSIYamaha;
  267. /* no overlap reading for cd-writers */
  268. global.overlap = 0;
  269. if ( (*in_lendian) == -1 )
  270. (*in_lendian) = 1;
  271.     } else if (!memcmp(p+8,"PLEXTOR",7)) {
  272. if ( (*in_lendian) == -1 )
  273. (*in_lendian) = 1;
  274. global.overlap = 0;
  275.         ReadLastAudio = ReadFirstSessionTOCSony;
  276.      ReadTocText = ReadTocTextSCSIMMC;
  277.     } else if (!memcmp(p+8,"SONY",4)) {
  278. if ( (*in_lendian) == -1 )
  279. (*in_lendian) = 1;
  280.         if (!memcmp(p+16, "CD-ROM CDU55E",13)) {
  281.    ReadCdRom = ReadCddaMMC12;
  282. }
  283.         ReadLastAudio = ReadFirstSessionTOCSony;
  284.      ReadTocText = ReadTocTextSCSIMMC;
  285.     } else if (!memcmp(p+8,"NEC",3)) {
  286. ReadCdRom = ReadCdda10;
  287.         ReadTocText = NULL;
  288.         SelectSpeed = SpeedSelectSCSINEC;
  289. if ( (*in_lendian) == -1 )
  290. (*in_lendian) = 1;
  291.         if (!memcmp(p+29,"5022.0r",3)) /* I assume all versions of the 502 require this? */
  292.                global.overlap = 0;           /* no overlap reading for NEC CD-ROM 502 */
  293.     } else if (!memcmp(p+8,"MATSHITA",8)) {
  294. ReadCdRom = ReadCdda12Matsushita;
  295. if ( (*in_lendian) == -1 )
  296. (*in_lendian) = 1;
  297.     }
  298.     } /* switch (get_mmc) */
  299.     }
  300.     ReadToc = ReadTocSCSI;
  301.     ReadSubQ = ReadSubQSCSI;
  302.     /* look if caddy is loaded */
  303.     if (interface == GENERIC_SCSI) while (!wait_unit_ready(scgp, 60)) {
  304. fprintf(stderr,"load cdrom please and press enter");
  305. getchar();
  306.     }
  307. }
  308. /********************** General setup *******************************/
  309. /* As the name implies, interfaces and devices are checked.  We also
  310.    adjust nsectors, overlap, and interface for the first time here.
  311.    Any unnecessary privileges (setuid, setgid) are also dropped here.
  312. */
  313. static void Check_interface_for_device( statstruct, pdev_name)
  314. struct stat *statstruct;
  315. char *pdev_name;
  316. {
  317. #if !defined (STAT_MACROS_BROKEN) || (STAT_MACROS_BROKEN != 1)
  318.     if (!S_ISCHR(statstruct->st_mode) &&
  319. !S_ISBLK(statstruct->st_mode)) {
  320.       fprintf(stderr, "%s is not a devicen",pdev_name);
  321.       exit(1);
  322.     }
  323. #endif
  324. #if defined (HAVE_ST_RDEV) && (HAVE_ST_RDEV == 1)
  325.     switch ((int) (statstruct->st_rdev >> 8L)) {
  326. #if defined (__linux__)
  327.     case SCSI_GENERIC_MAJOR: /* generic */
  328. #else
  329.     default: /* ??? what is the proper value here */
  330. #endif
  331. #if !defined (STAT_MACROS_BROKEN) || (STAT_MACROS_BROKEN != 1)
  332. #if defined (__linux__)
  333.        if (!S_ISCHR(statstruct->st_mode)) {
  334.  fprintf(stderr, "%s is not a char devicen",pdev_name);
  335.  exit(1);
  336.        }
  337.        if (interface != GENERIC_SCSI) {
  338.  fprintf(stderr, "wrong interface (cooked_ioctl) for this device (%s)nset to generic_scsin", pdev_name);
  339.  interface = GENERIC_SCSI;
  340.        }
  341. #endif
  342. #endif
  343.        break;
  344. #if defined (__linux__) || defined (__FreeBSD__)
  345. #if defined (__linux__)
  346.     case SCSI_CDROM_MAJOR:     /* scsi cd */
  347.     default: /* for example ATAPI cds */
  348. #else
  349. #if defined (__FreeBSD__)
  350.     case 117:
  351. if (!S_ISCHR(statstruct->st_mode)) {
  352.     fprintf(stderr, "%s is not a char devicen",pdev_name);
  353.     exit(1);
  354. }
  355. if (interface != COOKED_IOCTL) {
  356.     fprintf(stderr, "cdrom device (%s) is not of type generic SCSI. "
  357.     "Setting interface to cooked_ioctl.n", pdev_name);
  358.     interface = COOKED_IOCTL;
  359. }
  360. break;
  361.     case 19:     /* first atapi cd */
  362. #endif
  363. #endif
  364. if (!S_ISBLK(statstruct->st_mode)) {
  365.     fprintf(stderr, "%s is not a block devicen",pdev_name);
  366.     exit(1);
  367. }
  368. if (interface != COOKED_IOCTL) {
  369.     fprintf(stderr, "cdrom device (%s) is not of type generic SCSI. "
  370.     "Setting interface to cooked_ioctl.n", pdev_name);
  371.     interface = COOKED_IOCTL;
  372. }
  373. break;
  374. #endif
  375.     }
  376. #endif
  377.     if (global.overlap >= global.nsectors)
  378.       global.overlap = global.nsectors-1;
  379. }
  380. /* open the cdrom device */
  381. static int OpenCdRom ( pdev_name )
  382. char *pdev_name;
  383. {
  384.   int retval = 0;
  385.   struct stat fstatstruct;
  386.   /*  The device (given by pdevname) can be:
  387.       a. an SCSI device specified with a /dev/xxx name,
  388.       b. an SCSI device specified with bus,target,lun numbers,
  389.       c. a non-SCSI device such as ATAPI or proprietary CDROM devices.
  390.    */
  391. #ifdef HAVE_IOCTL_INTERFACE
  392.   struct stat statstruct;
  393.   int have_named_device = 0;
  394.   have_named_device = strchr(pdev_name, ':') == NULL
  395.  && memcmp(pdev_name, "/dev/", 5) == 0;
  396.   if (have_named_device) {
  397.     if (stat(pdev_name, &statstruct)) {
  398.       fprintf(stderr, "cannot stat device %sn", pdev_name);
  399.       exit(1);
  400.     } else {
  401.       Check_interface_for_device( &statstruct, pdev_name );
  402.     }
  403.   }
  404. #endif
  405.   if (interface == GENERIC_SCSI) {
  406. char errstr[80];
  407.       needroot(0);
  408.       needgroup(0);
  409. /* device name, debug, verboseopen */
  410.       scgp = open_scsi(pdev_name, errstr, sizeof(errstr), 0, 0);
  411.       if (scgp == NULL) {
  412. errmsg("%s%sCannot open SCSI driver.n", errstr, errstr[0]?". ":"");
  413.         fprintf(stderr, "open(%s) in file %s, line %dn",pdev_name, __FILE__, __LINE__);
  414.         dontneedgroup();
  415.         dontneedroot();
  416. #if defined(sun) || defined(__sun)
  417.         fprintf(stderr, "On SunOS/Solaris make sure you have Joerg Schillings scg SCSI driver installed.n");
  418. #endif
  419. #if defined (__linux__)
  420.         fprintf(stderr, "Use the script scan_scsi.linux to find out more.n");
  421. #endif
  422.         fprintf(stderr, "Probably you did not define your SCSI device.n");
  423. fprintf(stderr, "You can scan the SCSI bus(es) with 'cdrecord -scanbus'.n");
  424.         fprintf(stderr, "Set the CDDA_DEVICE environment variable or use the -D option.n");
  425.         fprintf(stderr, "You can also define the default device in the Makefile.n");
  426.         exit(1);
  427.       }
  428. scsi_settimeout(scgp, 100);
  429. if (scgp) {
  430. scgp->silent = global.scsi_silent;
  431. scgp->verbose = global.scsi_verbose;
  432. }
  433.       dontneedgroup();
  434.       dontneedroot();
  435.       if (global.nsectors > (unsigned) scsi_bufsize(scgp, 100*1024*1024)/CD_FRAMESIZE_RAW)
  436.         global.nsectors = scsi_bufsize(scgp, 100*1024*1024)/CD_FRAMESIZE_RAW;
  437.       if (global.overlap >= global.nsectors)
  438.         global.overlap = global.nsectors-1;
  439. init_scsibuf(scgp, global.nsectors*CD_FRAMESIZE_RAW);
  440.   } else {
  441.       needgroup(0);
  442.       retval = open(pdev_name,O_RDONLY);
  443.       dontneedgroup();
  444.       if (retval < 0) {
  445.         fprintf(stderr, "while opening %s :", pdev_name);
  446.         perror("");
  447.         exit(1);
  448.       }
  449.       /* Do final security checks here */
  450.       if (fstat(retval, &fstatstruct)) {
  451.         fprintf(stderr, "Could not fstat %s (fd %d): ", pdev_name, retval);
  452.         perror("");
  453.         exit(1);
  454.       }
  455.       Check_interface_for_device( &fstatstruct, pdev_name );
  456. #if defined HAVE_IOCTL_INTERFACE
  457.       /* Watch for race conditions */
  458.       if (have_named_device 
  459.           && (fstatstruct.st_dev != statstruct.st_dev ||
  460.               fstatstruct.st_ino != statstruct.st_ino)) {
  461.          fprintf(stderr,"Race condition attempted in OpenCdRom.  Exiting now.n");
  462.          exit(1);
  463.       }
  464. #endif
  465.   }
  466.   return retval;
  467. }
  468. #endif /* SIM_CD */
  469. /******************* Simulation interface *****************/
  470. #if defined SIM_CD
  471. #include "toc.h"
  472. static unsigned long sim_pos=0;
  473. /* read 'SectorBurst' adjacent sectors of audio sectors 
  474.  * to Buffer '*p' beginning at sector 'lSector'
  475.  */
  476. static void ReadCdRom_sim __PR(( SCSI *x, UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
  477. static void ReadCdRom_sim (x, p, lSector, SectorBurstVal )
  478. SCSI *x;
  479. UINT4 *p;
  480. unsigned lSector;
  481. unsigned SectorBurstVal;
  482. {
  483.   unsigned int loop=0;
  484.   short *q = (short *) p;
  485.   int joffset = 0;
  486.   if (lSector > g_toc[cdtracks].dwStartSector || lSector + SectorBurstVal > g_toc[cdtracks].dwStartSector + 1) {
  487.     fprintf(stderr, "Read request out of bounds: %u - %u (%d - %d allowed)n",
  488. lSector, lSector + SectorBurstVal, 0, g_toc[cdtracks].dwStartSector);
  489.   }
  490. #if 0
  491.   /* jitter with a probability of jprob */
  492.   if (random() <= jprob) {
  493.     /* jitter up to jmax samples */
  494.     joffset = random();
  495.   }
  496. #endif
  497. #ifdef DEBUG_SHM
  498.   fprintf(stderr, ", last_b = %pn", *last_buffer);
  499. #endif
  500.   for (loop = lSector*CD_FRAMESAMPLES + joffset; 
  501.        loop < (lSector+SectorBurstVal)*CD_FRAMESAMPLES + joffset; 
  502.        loop++) {
  503.     *q++ = loop;
  504.     *q++ = ~loop;
  505.   }
  506. #ifdef DEBUG_SHM
  507.   fprintf(stderr, "sim wrote from %p upto %p - 4 (%d), last_b = %pn",
  508.           p, q, SectorBurstVal*CD_FRAMESAMPLES, *last_buffer);
  509. #endif
  510.   sim_pos = (lSector+SectorBurstVal)*CD_FRAMESAMPLES + joffset; 
  511. }
  512. static int Play_at_sim __PR(( SCSI *x, unsigned int from_sector, unsigned int sectors));
  513. static int Play_at_sim( x, from_sector, sectors)
  514. SCSI *x;
  515. unsigned int from_sector;
  516. unsigned int sectors;
  517. {
  518.   sim_pos = from_sector*CD_FRAMESAMPLES; 
  519.   return 0;
  520. }
  521. static unsigned sim_indices;
  522. /* read the table of contents (toc) via the ioctl interface */
  523. static unsigned ReadToc_sim __PR(( SCSI *x, TOC *toc));
  524. static unsigned ReadToc_sim ( x, toc )
  525. SCSI *x;
  526. TOC *toc;
  527. {
  528.     unsigned int scenario;
  529.     int scen[12][3] = { 
  530.       {1,1,500}, 
  531.       {1,2,500}, 
  532.       {1,99,150*99}, 
  533.       {2,1,500}, 
  534.       {2,2,500}, 
  535.       {2,99,150*99},
  536.       {5,1,500}, 
  537.       {5,2,500}, 
  538.       {5,99,150*99}, 
  539.       {99,1,1000}, 
  540.       {99,2,1000}, 
  541.       {99,99,150*99}, 
  542.     };
  543.     unsigned int i;
  544.     unsigned trcks;
  545. #if 0
  546.     fprintf(stderr, "select one of the following TOCsn"
  547.     "0 :  1 track  with  1 indexn"
  548.     "1 :  1 track  with  2 indicesn"
  549.     "2 :  1 track  with 99 indicesn"
  550.     "3 :  2 tracks with  1 index eachn"
  551.     "4 :  2 tracks with  2 indices eachn"
  552.     "5 :  2 tracks with 99 indices eachn"
  553.     "6 :  5 tracks with  1 index eachn"
  554.     "7 :  5 tracks with  2 indices eachn"
  555.     "8 :  5 tracks with 99 indices eachn"
  556.     "9 : 99 tracks with  1 index eachn"
  557.     "10: 99 tracks with  2 indices eachn"
  558.     "11: 99 tracks with 99 indices eachn"
  559.     );
  560.     do {
  561.       scanf("%u", &scenario);
  562.     } while (scenario > sizeof(scen)/2/sizeof(int));
  563. #else
  564.     scenario = 6;
  565. #endif
  566.     /* build table of contents */
  567.     trcks = scen[scenario][0] + 1;
  568.     sim_indices = scen[scenario][1];
  569.     for (i = 0; i < trcks; i++) {
  570.         toc[i].bFlags = 0x1b;
  571.         toc[i].bTrack = i + 1;
  572.         toc[i].dwStartSector = i * scen[scenario][2];
  573.     }
  574.     toc[i].bTrack = 0xaa;
  575.     return --trcks;           /* without lead-out */
  576. }
  577. static subq_chnl *ReadSubQ_sim __PR(( SCSI *scgp, unsigned char sq_format, unsigned char track ));
  578. /* request sub-q-channel information. This function may cause confusion
  579.  * for a drive, when called in the sampling process.
  580.  */
  581. static subq_chnl *ReadSubQ_sim ( scgp, sq_format, track )
  582. SCSI *scgp;
  583. unsigned char sq_format;
  584. unsigned char track;
  585. {
  586.     subq_chnl *SQp = (subq_chnl *) (SubQbuffer);
  587.     subq_position *SQPp = (subq_position *) &SQp->data;
  588.     unsigned long sim_pos1;
  589.     unsigned long sim_pos2;
  590.     if ( sq_format != GET_POSITIONDATA ) return NULL;  /* not supported by sim */
  591.     /* simulate CDROMSUBCHNL ioctl */
  592.     /* copy to SubQbuffer */
  593.     SQp->audio_status  = 0;
  594.     SQp->format  = 0xff;
  595.     SQp->control_adr = 0xff;
  596.     sim_pos1 = sim_pos/CD_FRAMESAMPLES;
  597.     sim_pos2 = sim_pos1 % 150;
  598.     SQp->track  = (sim_pos1 / 5000) + 1;
  599.     SQp->index  = ((sim_pos1 / 150) % sim_indices) + 1;
  600.     sim_pos1 += 150;
  601.     SQPp->abs_min  = sim_pos1 / (75*60);
  602.     SQPp->abs_sec  = (sim_pos1 / 75) % 60;
  603.     SQPp->abs_frame  = sim_pos1 % 75;
  604.     SQPp->trel_min  = sim_pos2 / (75*60);
  605.     SQPp->trel_sec  = (sim_pos2 / 75) % 60;
  606.     SQPp->trel_frame  = sim_pos2 % 75;
  607.     return (subq_chnl *)(SubQbuffer);
  608. }
  609. static void SelectSpeed_sim __PR(( SCSI *x, unsigned sp));
  610. static void SelectSpeed_sim(x, sp)
  611. SCSI *x;
  612. unsigned sp;
  613. {
  614. PRETEND_TO_USE(x);
  615. PRETEND_TO_USE(sp);
  616. }
  617. static void trash_cache_sim __PR((UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
  618. static void trash_cache_sim(p, lSector, SectorBurstVal)
  619. UINT4 *p;
  620. unsigned lSector;
  621. unsigned SectorBurstVal;
  622. {
  623. PRETEND_TO_USE(p);
  624. PRETEND_TO_USE(lSector);
  625. PRETEND_TO_USE(SectorBurstVal);
  626. }
  627. static void SetupSimCd __PR((void));
  628. static void SetupSimCd()
  629. {
  630.     EnableCdda = (void (*) __PR((SCSI *, int)))Dummy;
  631.     ReadCdRom = ReadCdRom_sim;
  632.     ReadCdRomData = (void (*) __PR((SCSI *, unsigned char *, unsigned, unsigned ))) ReadCdRom_sim;
  633.     ReadToc = ReadToc_sim;
  634.     ReadTocText = NULL;
  635.     ReadSubQ = ReadSubQ_sim;
  636.     ReadLastAudio = NULL;
  637.     SelectSpeed = SelectSpeed_sim;
  638.     Play_at = Play_at_sim;
  639.     StopPlay = (int (*) __PR((SCSI *)))Dummy;
  640.     trash_cache = trash_cache_sim;
  641.  
  642. }
  643. #endif /* def SIM_CD */
  644. /* perform initialization depending on the interface used. */
  645. void SetupInterface( )
  646. {
  647. #if defined SIM_CD
  648.     global.nsectors = 75;
  649.     fprintf( stderr, "SIMULATION MODE !!!!!!!!!!!n");
  650. #else
  651.     /* ensure interface is setup correctly */
  652.     global.cooked_fd = OpenCdRom ( global.dev_name );
  653. #endif
  654. #ifdef  _SC_PAGESIZE
  655.     global.pagesize = sysconf(_SC_PAGESIZE);
  656. #else
  657.     global.pagesize = getpagesize();
  658. #endif
  659.     /* Value of 'nsectors' must be defined here */
  660.     assert(global.nsectors > 0);
  661.     assert(global.buffers > 0);
  662.     global.shmsize = HEADER_SIZE + ENTRY_SIZE_PAGE_AL * global.buffers;
  663. #if defined (HAVE_FORK_AND_SHAREDMEM)
  664. #if defined(HAVE_SMMAP) || defined(HAVE_USGSHM) || defined(HAVE_DOSALLOCSHAREDMEM)
  665.     fill_buffer = request_shm_sem(global.shmsize, (unsigned char **)&fill_buffer);
  666.     if (fill_buffer == NULL) {
  667. #else /* have shared memory */
  668.     if (1) {
  669. #endif
  670. fprintf( stderr, "no shared memory available!n");
  671. exit(2);
  672.     }
  673. #else /* do not have fork() and shared memory */
  674.     fill_buffer = malloc(global.shmsize);
  675.     if (fill_buffer == NULL) {
  676. fprintf( stderr, "no buffer memory available!n");
  677. exit(2);
  678.     }
  679. #endif
  680.     if (global.verbose != 0)
  681.      fprintf(stderr,
  682.      "%u bytes buffer memory requested, %d buffers, %d sectorsn",
  683.      global.shmsize, global.buffers, global.nsectors);
  684.     /* initialize pointer into shared memory segment */
  685.     last_buffer = fill_buffer + 1;
  686.     total_segments_read = (unsigned long *) (last_buffer + 1);
  687.     total_segments_written = total_segments_read + 1;
  688.     child_waits = (int *) (total_segments_written + 1);
  689.     parent_waits = child_waits + 1;
  690.     in_lendian = parent_waits + 1;
  691.     *in_lendian = -1;
  692.     set_total_buffers(global.buffers, sem_id);
  693.     /* request one sector for table of contents */
  694.     bufferTOC = (unsigned char *) malloc( CD_FRAMESIZE );      /* assumes sufficient aligned addresses */
  695.     /* SubQchannel buffer */
  696.     SubQbuffer = (subq_chnl *) malloc( 48 );               /* assumes sufficient aligned addresses */
  697.     cmd = (unsigned char *) malloc( 18 );                      /* assumes sufficient aligned addresses */
  698.     if ( !bufferTOC || !SubQbuffer || !cmd ) {
  699.        fprintf( stderr, "Too low on memory. Giving up.n");
  700.        exit(2);
  701.     }
  702. #if defined SIM_CD
  703.     SetupSimCd();
  704. #else
  705.     /* if drive is of type scsi, get vendor name */
  706.     if (interface == GENERIC_SCSI) {
  707.         unsigned sector_size;
  708. SetupSCSI();
  709.         sector_size = get_orig_sectorsize(scgp, &orgmode4, &orgmode10, &orgmode11);
  710. if (!SCSI_emulated_ATAPI_on(scgp)) {
  711.           if ( sector_size != 2048 && set_sectorsize(scgp, 2048) ) {
  712.     fprintf( stderr, "Could not change sector size from %d to 2048n", sector_size );
  713.           }
  714.         } else {
  715.           sector_size = 2048;
  716.         }
  717. /* get cache setting */
  718. /* set cache to zero */
  719. #if defined (HAVE_IOCTL_INTERFACE)
  720.     } else {
  721. SetupCookedIoctl( global.dev_name );
  722. #endif
  723.     }
  724. #endif /* if def SIM_CD */
  725. }