home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / UNIX / SCSI_CD / cd_commands.c < prev    next >
Text File  |  1992-07-24  |  12KB  |  437 lines

  1. /*
  2.  * cd_commands.c: CD-ROM drive specific commands
  3.  * NOTE: this version is taylored for audio. Basically it uses msf address
  4.  *       format
  5.  *
  6.  * History
  7.  * -------
  8.  * Mon Sep 16 15:57:35 PDT 1991 James C. Lee at NeXT
  9.  *  Created
  10.  */
  11.  
  12. #import "cd_commands.h"
  13. #import "scsi_commands.h"
  14. #import "myflags.h"
  15. #import <libc.h>
  16. #import <objc/objc.h>
  17. #import <c.h>
  18.  
  19. int    do_eject(int fd, struct timeval *tvp, struct esense_reply *erp)
  20. {
  21.     struct scsi_req sr;
  22.     struct start_stop_cmd *sscp;
  23.     int err;
  24.  
  25.     bzero((char *)&sr, sizeof(sr));
  26.  
  27.     sscp = (struct start_stop_cmd *)&sr.sr_cdb;
  28.     sscp->ssc_opcode = C6OP_STARTSTOP;
  29.     sscp->ssc_imm = 0;    /* status will be returned after the operation is
  30.                            completed */
  31.     sscp->ssc_loej = 1;    /* eject when spin down (scc_start=0) */
  32.     sscp->ssc_start = 0;    /* spin down */
  33.  
  34.     sr.sr_addr = NULL;
  35.     sr.sr_dma_max = 0;    /* don't really do I/O to memory */
  36.     sr.sr_ioto = 10;    /* time out in 10 seconds */
  37.     sr.sr_dma_dir = SR_DMA_RD;
  38.  
  39.     err = ioctl(fd, SDIOCSRQ, &sr);
  40.  
  41. $    p = sr.sr_exec_time;
  42.  
  43.     if (sr.sr_dma_xfr != 0)
  44.         fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
  45.  
  46.     *erp = sr.sr_esense;
  47.     return err | sr.sr_io_status;
  48. }
  49.  
  50. /* same command as do_eject except that sscp->ssc_start=1, and
  51.    sscp->ssc_loej=0 */
  52. int    do_spinup(int fd, struct timeval *tvp, struct esense_reply *erp)
  53. {
  54.     struct scsi_req sr;
  55.     struct start_stop_cmd *sscp;
  56.     int err;
  57.  
  58.     bzero((char *)&sr, sizeof(sr));
  59.  
  60.     sscp = (struct start_stop_cmd *)&sr.sr_cdb;
  61.     sscp->ssc_opcode = C6OP_STARTSTOP;
  62.     sscp->ssc_imm = 0;    /* status will be returned after the operation is
  63.                            completed */
  64.     sscp->ssc_loej = 0;
  65.     sscp->ssc_start = 1;    /* spin up */
  66.  
  67.     sr.sr_addr = NULL;
  68.     sr.sr_dma_max = 0;    /* don't really do I/O to memory */
  69.     sr.sr_ioto = 10;    /* time out in 10 seconds */
  70.     sr.sr_dma_dir = SR_DMA_RD;
  71.  
  72.     err = ioctl(fd, SDIOCSRQ, &sr);
  73.  
  74.     *tvp = sr.sr_exec_time;
  75.  
  76.     if (sr.sr_dma_xfr != 0)
  77.         fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
  78.  
  79.     *erp = sr.sr_esense;
  80.     return err | sr.sr_io_status;
  81. }
  82.  
  83. /* read table of content */
  84. int do_readtoc(int fd, int track, struct toc10_reply *tocrp,
  85.     struct esense_reply *erp)
  86. {
  87.     struct scsi_req sr;
  88.     struct readtoc10_cmd *rt10cp;
  89.     int err;
  90.  
  91.     bzero((char *)&sr, sizeof(sr));
  92.  
  93.     rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
  94.     rt10cp->rt10_op_code = C10OP_READTOC;
  95.     rt10cp->rt10_msf = 0;    /* don't use msf format */
  96.     rt10cp->rt10_starttrack = track;
  97.     /* read only info on one track */
  98.     rt10cp->rt10_length = sizeof(struct toc10_reply);
  99.     
  100.     sr.sr_addr = (char *) tocrp;
  101.     sr.sr_dma_max = sizeof(*tocrp);
  102.     sr.sr_ioto = 5;        /* time out in 5 seconds */
  103.     sr.sr_dma_dir = SR_DMA_RD;
  104.  
  105.     err = ioctl(fd, SDIOCSRQ, &sr);
  106.  
  107.     *erp = sr.sr_esense;
  108.     return err | sr.sr_io_status;
  109. }
  110.  
  111. /* read entire table of contents */
  112. int do_readtoc_all(int fd, struct toc_all *toc_all, struct esense_reply *erp)
  113. {
  114.     struct scsi_req sr;
  115.     struct readtoc10_cmd *rt10cp;
  116.     struct toc10_reply tocr;
  117.     int        err;
  118.     char    *toc_reply;    /* toc reply from scsi bus, need to be allocated */
  119.     u_int    toc_data_length;
  120.     struct rtr10_desc    *desc;    /* pointer to trverse through *toc_reply */
  121.     int        nrecords,    /* number of desc blocks info in toc */
  122.             i, track;
  123.  
  124.     bzero((char *)&sr, sizeof(sr));
  125.  
  126.     rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
  127.     rt10cp->rt10_op_code = C10OP_READTOC;
  128.     rt10cp->rt10_msf = 0;    /* don't use msf format */
  129.     rt10cp->rt10_starttrack = 0;
  130.     /* read only in$    n track 0 to find out TOC data length */
  131.     rt10cp->rt10_length = sizeof(struct toc10_reply);
  132.     
  133.     sr.sr_addr = (char *) &tocr;
  134.     sr.sr_dma_max = sizeof(tocr);
  135.     sr.sr_ioto = 5;        /* time out in 5 seconds */
  136.     sr.sr_dma_dir = SR_DMA_RD;
  137.  
  138.     err = ioctl(fd, SDIOCSRQ, &sr);
  139.     *erp = sr.sr_esense;
  140.     if (err | sr.sr_io_status) {    /* problem reading TOC, return */
  141.         return err | sr.sr_io_status;
  142.     }
  143.     
  144.     /* record first & last track, and toc data length */
  145.     toc_all->firsttrack = tocr.h.rtr_firsttrack;
  146.     toc_all->lasttrack = tocr.h.rtr_lasttrack;
  147.     toc_data_length = tocr.h.rtr_datalength;
  148.     nrecords = toc_data_length / sizeof(struct rtr10_desc);
  149.  
  150.     /* prepare for second read toc for the whole thing */
  151.     bzero((char *)&sr, sizeof(sr));
  152.  
  153.     rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
  154.     rt10cp->rt10_op_code = C10OP_READTOC;
  155.     rt10cp->rt10_msf = 1;    /* want msf format */
  156.     rt10cp->rt10_starttrack = 0;
  157.     /* read only info on track 0 to find out TOC data length */
  158.     rt10cp->rt10_length = toc_data_length + sizeof(struct rtr_header);
  159.  
  160.     toc_reply = (char *) malloc(toc_data_length + sizeof(struct rtr_header));
  161.     sr.sr_addr = toc_reply;
  162.     sr.sr_dma_max = toc_data_length + sizeof(struct rtr_header);
  163.     sr.sr_ioto = 5;        /* time out in 5 seconds */
  164.     sr.sr_dma_dir = SR_DMA_RD;
  165.     
  166.     err = ioctl(fd, SDIOCSRQ, &sr);
  167.     *erp = sr.sr_esense;
  168.     if (err | sr.sr_io_status) {    /* problem reading TOC, return */
  169.         return err | sr.sr_io_status;
  170.     }
  171.     
  172.     /* successfully read the whole thing, now process it */
  173.     toc_all->naudio = toc_all->ndata = 0;    /* zero counts */
  174.     for (i=0; i<=100; i++) {    /* first initialize addr to be invalid */
  175.         toc_all->info[i].hour = -1;
  176.         toc_all->info[i].min = -1;
  177.         toc_all->info[i].sec = -1;
  178.         toc_all->info[i].frame = -1;
  179.     }
  180.     desc = (struct rtr10_desc *) &(toc_reply[4]);    /* skip the header */
  181.     for (i=0; i<nrecords; i++) {
  182.         track = desc->t10d_track;
  183.         if (track == 0xaa) track = 100;    /* transition area */
  184.         if (desc->t10d_control & DATA_TRACK)
  185.             toc_all->ndata++;
  186.         else if (track != 100)
  187.             toc_all->naudio++;
  188.         toc_all->info[track].control = desc->t10d_control;
  189.         toc_all->info[track].hour = desc->t10d_hour;
  190.         toc_all->info[track].min = desc->t10d_min;
  191.         toc_all->info[track].sec = desc->t10d_sec;
  192.         toc_all->info[track].frame = desc->t10d_frame;
  193.         desc++;
  194.     }
  195. #ifdef CD_DEBUG
  196.     /* print the table of contents to stderr */
  197.     for (i=toc_all->firsttrack; i<=toc_al$    asttrack; i++) {
  198.         printf("Track %2d: %d:%d:%d:%d %c\n", i,
  199.             toc_all->info[i].hour, toc_all->info[i].min, toc_all->info[i].sec,
  200.             toc_all->info[i].frame,
  201.             toc_all->info[i].control&DATA_TRACK? 'D' : 'A');
  202.     }
  203.         printf("Track LO: %d:%d:%d:%d %c\n",
  204.             toc_all->info[100].hour, toc_all->info[100].min,
  205.             toc_all->info[100].sec, toc_all->info[100].frame,
  206.         toc_all->info[100].control&DATA_TRACK? 'D' : 'A');
  207. #endif
  208.     return err | sr.sr_io_status;
  209. }
  210.  
  211. /* play audio (C6OP_PLAYAUDIO = c8h) */
  212. int do_playaudio(int fd, int lba, int length, struct esense_reply *erp)
  213. {
  214.     struct scsi_req sr;
  215.     struct playaudio_cmd *pap;
  216.     int err;
  217.  
  218.     bzero((char *)&sr, sizeof(sr));
  219.  
  220.     pap = (struct playaudio_cmd *)&sr.sr_cdb;
  221.     pap->pa_op_code = C6OP_PLAYAUDIO;
  222.     pap->pa_lba = lba;    /* block to play audio from */
  223.     pap->pa_length = length;
  224.     
  225.     sr.sr_addr = NULL;
  226.     sr.sr_dma_max = 0;
  227.     sr.sr_ioto = 10;        /* time out in 10 seconds */
  228.     sr.sr_dma_dir = SR_DMA_RD;
  229.  
  230.     err = ioctl(fd, SDIOCSRQ, &sr);
  231.  
  232.     if (sr.sr_dma_xfr != 0)
  233.         fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
  234.  
  235.     *erp = sr.sr_esense;
  236.     return err | sr.sr_io_status;
  237. }
  238.  
  239. /* pause audio (C10OP_PAUSE = c5h) */
  240. int do_pauseaudio(int fd, int pause, struct esense_reply *erp)
  241. {
  242.     struct scsi_req sr;
  243.     struct pause_cmd *pp;
  244.     int err;
  245.  
  246.     bzero((char *)&sr, sizeof(sr));
  247.  
  248.     pp = (struct pause_cmd *)&sr.sr_cdb;
  249.     pp->p_op_code = C10OP_PAUSE;
  250.     pp->p_pause = pause;
  251.     
  252.     sr.sr_addr = NULL;
  253.     sr.sr_dma_max = 0;
  254.     sr.sr_ioto = 5;        /* time out in 5 seconds */
  255.     sr.sr_dma_dir = SR_DMA_RD;
  256.  
  257.     err = ioctl(fd, SDIOCSRQ, &sr);
  258.  
  259.     if (sr.sr_dma_xfr != 0)
  260.         fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
  261.  
  262.     *erp = sr.sr_esense;
  263.     return err | sr.sr_io_status;
  264. }
  265.  
  266. /* play audio (C10OP_PLAYAUDIO_MSF = 47h) */
  267. int do_playaudio_msf(int fd, struct msf startmsf, struct msf endmsf,
  268.     struct esense_reply *erp)
  269. {
  270.     struct scsi_req sr;
  271.     struct playaudio_msf_cmd *pap;
  272.     int err;
  273.  
  274.     bzero((char *)&sr, sizeof(sr));
  275.  
  276.     pap = (struct playaudio_msf_cmd *)&sr.sr_cdb;
  277.     pap->pam_op_code = C10OP_PLAYAUDIO_MSF;
  278.     pap->pam_start_min = startmsf.min;
  279.     pap->pam_start_sec = startmsf.sec;
  280.     pap->pam_start_frame = startmsf.frame;
  281.     pap->pam_end_min = endmsf.min;
  282.     pap->pam_end_sec = endmsf.sec;
  283.     pap->pam_end_frame = endmsf.frame;
  284.     
  285.     sr.sr_addr = NULL;
  286.     sr.sr_dma_max = 0;
  287.     sr.sr_ioto = 10;        /* time out in 10 seconds */
  288.     sr.sr_dma_dir = SR_DMA_RD;
  289.  
  290.     err = ioctl($    SDIOCSRQ, &sr);
  291.  
  292.     if (sr.sr_dma_xfr != 0)
  293.         fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
  294.  
  295.     *erp = sr.sr_esense;
  296.     return err | sr.sr_io_status;
  297. }
  298.  
  299. /* read sub-channel data (C10OP_READSUBHCANNEL = 42h) */
  300. int    do_readsubchannel(int fd, int msf, int subq, int page, int track,
  301.     struct sc_reply *scrp, struct esense_reply *erp)
  302. {
  303.     struct scsi_req sr;
  304.     struct readsc_cmd *rscp;
  305.     int err;
  306.     int    i;
  307.     char *cptr;
  308.  
  309.     bzero((char *)&sr, sizeof(sr));
  310.     
  311.     rscp = (struct readsc_cmd *) &sr.sr_cdb;
  312.     rscp->rsc_op_code = C10OP_READSUBHCANNEL;
  313.     rscp->rsc_msf = msf;
  314.     rscp->rsc_subq = subq;
  315.     rscp->rsc_dformat = page;
  316.     rscp->rsc_track = track;
  317.     rscp->rsc_length = sizeof(struct sc_reply);
  318.     
  319.     cptr = (char *) rscp;
  320. /*    printf("Cmd: ");
  321.     for (i=0; i<10; i++) {
  322.         printf("%.2x ", *cptr++);
  323.     }
  324.     printf("\n");*/
  325.     
  326.     sr.sr_addr = (char *) scrp;
  327.     sr.sr_dma_max = sizeof(struct sc_reply);
  328.     sr.sr_ioto = 5;        /* time out in 5 seconds */
  329.     sr.sr_dma_dir = SR_DMA_RD;
  330.  
  331.     err = ioctl(fd, SDIOCSRQ, &sr);
  332.     *erp = sr.sr_esense;
  333.     return err | sr.sr_io_status;
  334. }
  335.  
  336. /* get playback status data (C10OP_PLAYBACKSTATUS = c4h) */
  337. int    do_playbackstatus(int fd, struct playback_data *pbdatap,
  338.     struct esense_reply *erp)
  339. {
  340.     struct scsi_req sr;
  341.     struct playback_cmd *pbcp;
  342.     int err;
  343.  
  344.     bzero((char *)&sr, sizeof(sr));
  345.     
  346.     pbcp = (struct playback_cmd *) &sr.sr_cdb;
  347.     pbcp->pb_opcode = C10OP_PLAYBACKSTATUS;
  348.     pbcp->pb_length = sizeof(struct playback_data);
  349.         
  350.     sr.sr_addr = (char *) pbdatap;
  351.     sr.sr_dma_max = sizeof(struct playback_data);
  352.     sr.sr_ioto = 1;        /* time out in 1 second */
  353.     sr.sr_dma_dir = SR_DMA_RD;
  354.  
  355.     err = ioctl(fd, SDIOCSRQ, &sr);
  356.     *erp = sr.sr_esense;
  357.     return err | sr.sr_io_status;
  358. }
  359.  
  360.  
  361. /* playback status control (C10OP_PLAYBACKCONTROL = c9h) */
  362. int    do_playbackcontrol(int fd, struct playback_data *pbdatap,
  363.     struct esense_reply *erp)
  364. {
  365.     struct scsi_req sr;
  366.     struct playback_cmd *pbcp;
  367.     int err;
  368.  
  369.     bzero((char *)&sr, sizeof(sr));
  370.     
  371.     pbcp = (struct playback_cmd *) &sr.sr_cdb;
  372.     pbcp->pb_opcode = C10OP_PLAYBACKCONTROL;
  373.     pbcp->pb_length = sizeof(struct playback_data);
  374.         
  375.     sr.sr_addr = (char *) pbdatap;
  376.     sr.sr_dma_max = sizeof(struct playback_data);
  377.     sr.sr_ioto = 1;        /* time out in 1 second */
  378.     sr.sr_dma_dir = SR_DMA_WR;
  379.  
  380.     err = ioctl(fd, SDIOCSRQ, &sr);
  381.     *erp = sr.sr_esense;
  382.     return err | sr.sr_io_status;
  383. }
  384.  
  385. /* print sub-channel data */
  386. void printf_sc(int page, struct sc_re$    *scrp)
  387. {
  388.     struct msf    *msfp;    /* msf structure */
  389.     int            i;
  390.     
  391.     printf("Audio status: %.2x, Page %d\n", scrp->scr_header.sch_astatus,
  392.         page);
  393.     switch (page) {
  394.         case 1:    /* page 1 */
  395.             printf("Track       : %d\n", scrp->u.u_scr_cur_pos.sc1_track);
  396.             printf("Index       : %d\n", scrp->u.u_scr_cur_pos.sc1_index);
  397.             msfp = (struct msf *) &(scrp->u.u_scr_cur_pos.sc1_abs_addr);
  398.             printf("Abs Address : %d:%d:%d:%d\n", msfp->hour, msfp->min,
  399.                 msfp->sec, msfp->frame);
  400.             msfp = (struct msf *) &(scrp->u.u_scr_cur_pos.sc1_rel_addr);
  401.             printf("Rel Address : %d:%d:%d:%d\n", msfp->hour, msfp->min,
  402.                 msfp->sec, msfp->frame);
  403.             break;
  404.         case 2:    /* page 2 */
  405.             printf("MCVal       : %d\n", scrp->u.u_scr_med_cat.sc2_mcval);
  406.             printf("MCatalog    : ");
  407.             for (i=0; i<15; i++) {
  408.                 printf("%.2x", scrp->u.u_scr_med_cat.sc2_med_cat[i]);
  409.             }
  410.             printf("\n");
  411.             break;
  412.         case 3:    /* page 3 */
  413.             /* don't need to use it now */
  414.             printf("Page 3 not currently implemented\n");
  415.             break;
  416.         default:
  417.             printf("Unknown page number %d\n", page);
  418.             break;
  419.     }
  420.     return;
  421. }
  422.  
  423.  
  424. /* print playback status data */
  425. void printf_pb(struct playback_data *pbdatap)
  426. {
  427.     printf("pbd_ch0_sel: 0x%x\n", pbdatap->pbd_ch0_sel);
  428.     printf("pbd_ch0_vol: 0x%x\n", pbdatap->pbd_ch0_vol);
  429.     printf("pbd_ch1_sel: 0x%x\n", pbdatap->pbd_ch1_sel);
  430.     printf("pbd_ch1_vol: 0x%x\n", pbdatap->pbd_ch1_vol);
  431.     printf("pbd_ch2_sel: 0x%x\n", pbdatap->pbd_ch2_sel);
  432.     printf("pbd_ch2_vol: 0x%x\n", pbdatap->pbd_ch2_vol);
  433.     printf("pbd_ch3_sel: 0x%x\n", pbdatap->pbd_ch3_sel);
  434.     printf("pbd_ch3_vol: 0x%x\n", pbdatap->pbd_ch3_vol);
  435.     return;
  436. }
  437.