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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)ioctl.c 1.4 00/01/25 Copyright 1998,1999 Heiko Eissfeldt */
  2. #ifndef lint
  3. static char     sccsid[] =
  4. "@(#)ioctl.c 1.4 00/01/25 Copyright 1998,1999 Heiko Eissfeldt";
  5. #endif
  6. /***
  7.  * CopyPolicy: GNU Public License 2 applies
  8.  * Copyright (C) 1999 Heiko Eissfeldt heiko@colossus.escape.de
  9.  *
  10.  * Ioctl interface module for cdrom drive access
  11.  *
  12.  * Solaris ATAPI cdrom drives are untested!
  13.  *
  14.  */
  15. #include "config.h"
  16. #include <stdio.h>
  17. #include <standard.h>
  18. #include <stdlib.h>
  19. #if defined (HAVE_UNISTD_H) && (HAVE_UNISTD_H == 1)
  20. #include <sys/types.h>
  21. #include <unistd.h>
  22. #endif
  23. #include <strdefs.h>
  24. #include <errno.h>
  25. #include <signal.h>
  26. #include <fcntl.h>
  27. #include <assert.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/stat.h>
  30. #include <statdefs.h>
  31. #include <scg/scsitransp.h>
  32. #include "mycdrom.h"
  33. #include "lowlevel.h"
  34. /* some include file locations have changed with newer kernels */
  35. #if defined (__linux__)
  36. # if LINUX_VERSION_CODE > 0x10300 + 97
  37. #  if LINUX_VERSION_CODE < 0x200ff
  38. #   include <linux/sbpcd.h>
  39. #   include <linux/ucdrom.h>
  40. #  endif
  41. #  if !defined(CDROM_SELECT_SPEED)
  42. #   include <linux/ucdrom.h>
  43. #  endif
  44. # endif
  45. #endif
  46. #include "mytype.h"
  47. #include "byteorder.h"
  48. #include "interface.h"
  49. #include "toc.h"
  50. #include "cdda2wav.h"
  51. #include "ioctl.h"
  52. #include "global.h"
  53. #include <utypes.h>
  54. #include <cdrecord.h>
  55. #if defined (HAVE_IOCTL_INTERFACE)
  56. #if !defined sun && !defined __sun
  57. static struct cdrom_read_audio arg;
  58. #endif
  59. static struct cdrom_tochdr hdr;
  60. static struct cdrom_tocentry entry[100];
  61. static int err;
  62. static void EnableCdda_cooked __PR((SCSI *scgp, int fAudioMode));
  63. static void EnableCdda_cooked (scgp, fAudioMode)
  64. SCSI *scgp;
  65. int fAudioMode;
  66. {
  67. #if defined CDIOCSETCDDA
  68. ioctl(global.cooked_fd, CDIOCSETCDDA, &fAudioMode);
  69. #else
  70. PRETEND_TO_USE(fAudioMode);
  71. #endif
  72. PRETEND_TO_USE(scgp);
  73. }
  74. static unsigned ReadToc_cooked __PR(( SCSI *x, TOC *toc ));
  75. /* read the table of contents (toc) via the ioctl interface */
  76. static unsigned ReadToc_cooked ( x, toc )
  77. SCSI *x;
  78. TOC *toc;
  79. {
  80.     unsigned i;
  81.     unsigned tracks;
  82.     PRETEND_TO_USE(x);
  83.     /* get TocHeader to find out how many entries there are */
  84.     err = ioctl( global.cooked_fd, CDROMREADTOCHDR, &hdr );
  85.     if ( err != 0 ) {
  86. /* error handling */
  87. if (err == -1) {
  88.     if (errno == EPERM)
  89. fprintf( stderr, "Please run this program setuid root.n");
  90.     perror("cooked: Read TOC ");
  91.     exit( err );
  92. } else {
  93.     fprintf( stderr, "can't get TocHeader (error %d).n", err );
  94.     exit( -1 );
  95. }
  96.     }
  97.     /* get all TocEntries */
  98.     for ( i = 0; i < hdr.cdth_trk1; i++ ) {
  99. entry[i].cdte_track = 1+i;
  100. entry[i].cdte_format = CDROM_MSF;
  101. err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
  102. if ( err != 0 ) {
  103.     /* error handling */
  104.     fprintf( stderr, "can't get TocEntry #%d (error %d).n", i+1, err );
  105.     exit( -1 );
  106. }
  107.     }
  108.     entry[i].cdte_track = CDROM_LEADOUT;
  109.     entry[i].cdte_format = CDROM_MSF;
  110.     err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
  111.     if ( err != 0 ) {
  112. /* error handling */
  113. fprintf( stderr, "can't get TocEntry LEADOUT (error %d).n", err );
  114. exit( -1 );
  115.     }
  116.     tracks = hdr.cdth_trk1+1;
  117.     for (i = 0; i < tracks; i++) {
  118.         toc[i].bFlags = (entry[i].cdte_adr << 4) | (entry[i].cdte_ctrl & 0x0f);
  119.         toc[i].bTrack = entry[i].cdte_track;
  120.         toc[i].dwStartSector = -150 + 75*60*entry[i].cdte_addr.msf.minute+
  121.       75*   entry[i].cdte_addr.msf.second+
  122.             entry[i].cdte_addr.msf.frame;
  123.     }
  124.     bufferTOC[0] = '';
  125.     bufferTOC[1] = '';
  126.     return --tracks;           /* without lead-out */
  127. }
  128. static void trash_cache_cooked __PR((UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
  129. static void trash_cache_cooked(p, lSector, SectorBurstVal)
  130. UINT4 *p;
  131. unsigned lSector;
  132. unsigned SectorBurstVal;
  133. {
  134.       /* trash the cache */
  135. #if defined __FreeBSD__
  136.       static struct cdrom_read_audio arg2;
  137.       arg2.address.lba = find_an_off_sector(lSector, SectorBurstVal);
  138.       arg2.addr_format = CDROM_LBA;
  139.       arg2.nframes = 3;
  140.       arg2.buffer = (unsigned char *) &p[0];
  141.       ioctl(global.cooked_fd, CDROMREADAUDIO, &arg2);
  142. #endif
  143. #if defined __linux__
  144.       static struct cdrom_read_audio arg2;
  145.       arg2.addr.lba = find_an_off_sector(lSector, SectorBurstVal);
  146.       arg2.addr_format = CDROM_LBA;
  147.       arg2.nframes = 3;
  148.       arg2.buf = (unsigned char *) &p[0];
  149.       ioctl(global.cooked_fd, CDROMREADAUDIO, &arg2);
  150. #endif
  151. #if defined __sun
  152.       struct cdrom_cdda suncdda;
  153.       suncdda.cdda_addr = lSector;
  154.       suncdda.cdda_length = SectorBurstVal*CD_FRAMESIZE_RAW;
  155.       suncdda.cdda_data = (char *) &p[0];
  156.       suncdda.cdda_subcode = CDROM_DA_NO_SUBCODE;
  157.  
  158.       ioctl(global.cooked_fd, CDROMCDDA, &suncdda);
  159. #endif
  160. }
  161. static void ReadCdRomData_cooked __PR(( SCSI *x, UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
  162. /* read 'SectorBurst' adjacent sectors of data sectors 
  163.  * to Buffer '*p' beginning at sector 'lSector'
  164.  */
  165. static void ReadCdRomData_cooked (x, p, lSector, SectorBurstVal )
  166. SCSI *x;
  167. UINT4 *p;
  168. unsigned lSector;
  169. unsigned SectorBurstVal;
  170. {
  171. int retval;
  172. if ((retval = lseek(global.cooked_fd, lSector*CD_FRAMESIZE, SEEK_SET))
  173. != lSector*CD_FRAMESIZE) { perror("cannot seek sector"); }
  174. if ((retval = read(global.cooked_fd, p, SectorBurstVal*CD_FRAMESIZE))
  175. != SectorBurstVal*CD_FRAMESIZE) { perror("cannot read sector"); }
  176. PRETEND_TO_USE(x);
  177. return;
  178. }
  179. static void ReadCdRom_cooked __PR(( SCSI *x, UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
  180. /* read 'SectorBurst' adjacent sectors of audio sectors 
  181.  * to Buffer '*p' beginning at sector 'lSector'
  182.  */
  183. static void ReadCdRom_cooked (x, p, lSector, SectorBurstVal )
  184. SCSI *x;
  185. UINT4 *p;
  186. unsigned lSector;
  187. unsigned SectorBurstVal;
  188. {
  189.   int retry_count=0;
  190.   static int nothing_read = 1;
  191. /* read 2352 bytes audio data */
  192. #if defined __FreeBSD__
  193.   arg.address.lba = lSector;
  194.   arg.addr_format = CDROM_LBA;
  195.   arg.nframes = SectorBurstVal;
  196.   arg.buffer = (unsigned char *) &p[0];
  197.   do {
  198.     err = ioctl(global.cooked_fd, CDROMREADAUDIO, &arg);
  199. #endif
  200. #if defined __linux__
  201.   arg.addr.lba = lSector;
  202.   arg.addr_format = CDROM_LBA;
  203.   arg.nframes = SectorBurstVal;
  204.   arg.buf = (unsigned char *) &p[0];
  205.   do {
  206.     err = ioctl(global.cooked_fd, CDROMREADAUDIO, &arg);
  207. #endif
  208. #if defined sun || defined __sun
  209.   struct cdrom_cdda suncdda;
  210.   suncdda.cdda_addr = lSector;
  211.   suncdda.cdda_length = SectorBurstVal*CD_FRAMESIZE_RAW;
  212.   suncdda.cdda_data = (char *) &p[0];
  213.   suncdda.cdda_subcode = CDROM_DA_NO_SUBCODE;
  214.  
  215.   do {
  216.     err = ioctl(global.cooked_fd, CDROMCDDA, &suncdda);
  217. #endif
  218.     retry_count++;
  219.     if (err) { 
  220.       trash_cache_cooked(p, lSector, SectorBurstVal);
  221.     }
  222.   } while ((err) && (retry_count < 30));
  223.   if (err != 0) {
  224.       /* error handling */
  225.       if (err == -1) {
  226.   if (nothing_read && (errno == EINVAL || errno == EIO))
  227.       fprintf( stderr, "Sorry, this driver and/or drive does not support cdda reading.n");
  228.   perror("cooked: Read cdda ");
  229.           fprintf(stderr, " sector %u + %u, buffer %p + %xn", lSector, SectorBurstVal, p, global.shmsize);
  230.       } else {
  231.   fprintf(stderr, "can't read frame #%u (error %d).n", 
  232.   lSector, err);
  233.       }
  234.   } else {
  235.     nothing_read = 0;
  236.   }
  237.   PRETEND_TO_USE(x);
  238. }
  239. static int StopPlay_cooked __PR(( SCSI *x));
  240. static int StopPlay_cooked( x )
  241. SCSI *x;
  242. {
  243. PRETEND_TO_USE(x);
  244. return ioctl( global.cooked_fd, CDROMSTOP, 0 ) ? 0 : -1; 
  245. }
  246. static int Play_at_cooked __PR(( SCSI *x, unsigned int from_sector, unsigned int sectors));
  247. static int Play_at_cooked( x, from_sector, sectors)
  248. SCSI *x;
  249. unsigned int from_sector;
  250. unsigned int sectors;
  251. {
  252. struct cdrom_msf cmsf;
  253. PRETEND_TO_USE(x);
  254. cmsf.cdmsf_min0 = (from_sector + 150) / (60*75);
  255. cmsf.cdmsf_sec0 = ((from_sector + 150) / 75) % 60;
  256. cmsf.cdmsf_frame0 = (from_sector + 150) % 75;
  257. cmsf.cdmsf_min1 = (from_sector + 150 + sectors) / (60*75);
  258. cmsf.cdmsf_sec1 = ((from_sector + 150 + sectors) / 75) % 60;
  259. cmsf.cdmsf_frame1 = (from_sector + 150 + sectors) % 75;
  260. ioctl( global.cooked_fd, CDROMSTART, 0 );
  261. return ioctl( global.cooked_fd, CDROMPLAYMSF, &cmsf ) ? 0 : -1; 
  262. }
  263. #if defined PROTOTYPES
  264. static subq_chnl *ReadSubQ_cooked __PR(( SCSI *x, unsigned char sq_format, unsigned char track ))
  265. #else
  266. /* request sub-q-channel information. This function may cause confusion
  267.  * for a drive, when called in the sampling process.
  268.  */
  269. static subq_chnl *ReadSubQ_cooked ( x, sq_format, track )
  270. SCSI *x;
  271. unsigned char sq_format;
  272. unsigned char track;
  273. #endif
  274. {
  275.     struct cdrom_subchnl sub_ch;
  276. #if defined __FreeBSD__
  277.     struct cd_sub_channel_info sub_ch_info;
  278.     PRETEND_TO_USE(x);
  279.     sub_ch.address_format = CD_MSF_FORMAT;
  280.     sub_ch.track = track;
  281.     sub_ch.data_len = sizeof(struct cd_sub_channel_info);
  282.     sub_ch.data = &sub_ch_info;
  283.     switch (sq_format) {
  284.       case GET_CATALOGNUMBER:
  285.       sub_ch.data_format = CD_MEDIA_CATALOG;
  286. #else
  287.     PRETEND_TO_USE(x);
  288.     switch (sq_format) {
  289.       case GET_CATALOGNUMBER:
  290. #endif
  291. #if defined CDROM_GET_MCN
  292.       if (!(err = ioctl(global.cooked_fd, CDROM_GET_MCN, (struct cdrom_mcn *) SubQbuffer))) {
  293.           subq_chnl *SQp = (subq_chnl *) SubQbuffer;
  294.   subq_catalog *SQPp = (subq_catalog *) &SQp->data;
  295.           movebytes(SQp, SQPp->media_catalog_number, sizeof (SQPp->media_catalog_number));
  296.           SQPp->zero = 0;
  297.           SQPp->mc_valid = 0x80;
  298.           break;
  299.       } else
  300. #endif
  301.       {
  302.           return NULL;
  303.       }
  304.       case GET_POSITIONDATA:
  305. #if defined __FreeBSD__
  306.       sub_ch.data_format = CD_CURRENT_POSITION;
  307. #endif
  308.       if (!(err = ioctl(global.cooked_fd, CDROMSUBCHNL, &sub_ch))) {
  309.   /* copy to SubQbuffer */
  310.   subq_chnl *SQp = (subq_chnl *) (SubQbuffer);
  311.   subq_position *SQPp = (subq_position *) SQp->data;
  312.   SQp->audio_status  = sub_ch.cdsc_audiostatus;
  313.   SQp->format  = sub_ch.cdsc_format;
  314.   SQp->control_adr = (sub_ch.cdsc_adr << 4) | (sub_ch.cdsc_ctrl & 0x0f);
  315.   SQp->track  = sub_ch.cdsc_trk;
  316.   SQp->index  = sub_ch.cdsc_ind;
  317.   SQPp->abs_min  = sub_ch.cdsc_absaddr.msf.minute;
  318.   SQPp->abs_sec  = sub_ch.cdsc_absaddr.msf.second;
  319.   SQPp->abs_frame  = sub_ch.cdsc_absaddr.msf.frame;
  320.   SQPp->trel_min  = sub_ch.cdsc_reladdr.msf.minute;
  321.   SQPp->trel_sec  = sub_ch.cdsc_reladdr.msf.second;
  322.   SQPp->trel_frame  = sub_ch.cdsc_reladdr.msf.frame;
  323.       } else {
  324.   if (err == -1) {
  325.       if (errno == EPERM)
  326.   fprintf( stderr, "Please run this program setuid root.n");
  327.       perror("cooked: Read subq ");
  328.       exit( err );
  329.   } else {
  330.       fprintf(stderr, "can't read sub q channel (error %d).n", err);
  331.       exit( -1 );
  332.   }
  333.       }
  334.       break;
  335.       default:
  336.           return NULL;
  337.     } /* switch */
  338.   return (subq_chnl *)(SubQbuffer);
  339. }
  340. /* Speed control */
  341. static void SpeedSelect_cooked __PR(( SCSI *x, unsigned speed));
  342. static void SpeedSelect_cooked( x, speed )
  343. SCSI *x;
  344. unsigned speed;
  345. {
  346.     PRETEND_TO_USE(x);
  347. #ifdef CDROM_SELECT_SPEED
  348.     /* CAUTION!!!!! Non standard ioctl parameter types here!!!! */
  349.     if (!(err = ioctl(global.cooked_fd, CDROM_SELECT_SPEED, speed))) {
  350.     } else {
  351. if (err == -1) {
  352.     if (errno == EPERM)
  353. fprintf( stderr, "Please run this program setuid root.n");
  354.     perror("cooked: Speed select ");
  355.     /*exit( err ); */
  356. } else {
  357.     fprintf(stderr, "can't set speed %d (error %d).n", speed, err);
  358.     exit( -1 );
  359. }
  360.     }
  361. #else
  362.     PRETEND_TO_USE(speed);
  363. #endif
  364. }
  365. /* set function pointers to use the ioctl routines */
  366. void SetupCookedIoctl( pdev_name )
  367. char *pdev_name;
  368. {
  369. #if (HAVE_ST_RDEV == 1)
  370.     struct stat statstruct;
  371.     if (fstat(global.cooked_fd, &statstruct)) {
  372.       fprintf(stderr, "cannot stat cd %d (%s)n",global.cooked_fd, pdev_name);
  373.       exit(1);
  374.     }
  375. #if defined __linux__
  376.     switch ((int)(statstruct.st_rdev >> 8L)) {
  377.     case CDU31A_CDROM_MAJOR: /* sony cdu-31a/33a */
  378.         global.nsectors = 13;
  379.         if (global.nsectors >= 14) {
  380.   global.overlap = 10;
  381. }
  382.         break;
  383.     case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */
  384.     case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */
  385.     case MATSUSHITA_CDROM3_MAJOR: /* sbpcd 3 */
  386.     case MATSUSHITA_CDROM4_MAJOR: /* sbpcd 4 */
  387.         /* some are more compatible than others */
  388.         global.nsectors = 13;
  389. break;
  390. default:
  391.     }
  392.     err = ioctl(global.cooked_fd, CDROMAUDIOBUFSIZ, global.nsectors);
  393.     switch ((int)(statstruct.st_rdev >> 8L)) {
  394.     case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */
  395.     case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */
  396.     case MATSUSHITA_CDROM3_MAJOR: /* sbpcd 3 */
  397.     case MATSUSHITA_CDROM4_MAJOR: /* sbpcd 4 */
  398.       if (err == -1) {
  399.         perror("ioctl(CDROMAUDIOBUFSIZ)");
  400.       }
  401.     }
  402. #endif
  403. #endif
  404.     EnableCdda = EnableCdda_cooked;
  405.     ReadCdRom = ReadCdRom_cooked;
  406.     ReadCdRomData = (void (*) __PR((SCSI *, unsigned char *, unsigned, unsigned ))) ReadCdRomData_cooked;
  407.     ReadToc = ReadToc_cooked;
  408.     ReadTocText = NULL;
  409.     ReadSubQ = ReadSubQ_cooked;
  410.     SelectSpeed = SpeedSelect_cooked;
  411.     Play_at = Play_at_cooked;
  412.     StopPlay = StopPlay_cooked;
  413.     trash_cache = trash_cache_cooked;
  414.     ReadLastAudio = NULL;
  415. }
  416. #endif