home *** CD-ROM | disk | FTP | other *** search
- /*
- * cd_commands.c: CD-ROM drive specific commands
- * NOTE: this version is taylored for audio. Basically it uses msf address
- * format
- *
- * History
- * -------
- * Mon Sep 16 15:57:35 PDT 1991 James C. Lee at NeXT
- * Created
- */
-
- #import "cd_commands.h"
- #import "scsi_commands.h"
- #import "myflags.h"
- #import <libc.h>
- #import <objc/objc.h>
- #import <c.h>
-
- int do_eject(int fd, struct timeval *tvp, struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct start_stop_cmd *sscp;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- sscp = (struct start_stop_cmd *)&sr.sr_cdb;
- sscp->ssc_opcode = C6OP_STARTSTOP;
- sscp->ssc_imm = 0; /* status will be returned after the operation is
- completed */
- sscp->ssc_loej = 1; /* eject when spin down (scc_start=0) */
- sscp->ssc_start = 0; /* spin down */
-
- sr.sr_addr = NULL;
- sr.sr_dma_max = 0; /* don't really do I/O to memory */
- sr.sr_ioto = 10; /* time out in 10 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
-
- $ p = sr.sr_exec_time;
-
- if (sr.sr_dma_xfr != 0)
- fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
-
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* same command as do_eject except that sscp->ssc_start=1, and
- sscp->ssc_loej=0 */
- int do_spinup(int fd, struct timeval *tvp, struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct start_stop_cmd *sscp;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- sscp = (struct start_stop_cmd *)&sr.sr_cdb;
- sscp->ssc_opcode = C6OP_STARTSTOP;
- sscp->ssc_imm = 0; /* status will be returned after the operation is
- completed */
- sscp->ssc_loej = 0;
- sscp->ssc_start = 1; /* spin up */
-
- sr.sr_addr = NULL;
- sr.sr_dma_max = 0; /* don't really do I/O to memory */
- sr.sr_ioto = 10; /* time out in 10 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
-
- *tvp = sr.sr_exec_time;
-
- if (sr.sr_dma_xfr != 0)
- fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
-
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* read table of content */
- int do_readtoc(int fd, int track, struct toc10_reply *tocrp,
- struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct readtoc10_cmd *rt10cp;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
- rt10cp->rt10_op_code = C10OP_READTOC;
- rt10cp->rt10_msf = 0; /* don't use msf format */
- rt10cp->rt10_starttrack = track;
- /* read only info on one track */
- rt10cp->rt10_length = sizeof(struct toc10_reply);
-
- sr.sr_addr = (char *) tocrp;
- sr.sr_dma_max = sizeof(*tocrp);
- sr.sr_ioto = 5; /* time out in 5 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
-
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* read entire table of contents */
- int do_readtoc_all(int fd, struct toc_all *toc_all, struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct readtoc10_cmd *rt10cp;
- struct toc10_reply tocr;
- int err;
- char *toc_reply; /* toc reply from scsi bus, need to be allocated */
- u_int toc_data_length;
- struct rtr10_desc *desc; /* pointer to trverse through *toc_reply */
- int nrecords, /* number of desc blocks info in toc */
- i, track;
-
- bzero((char *)&sr, sizeof(sr));
-
- rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
- rt10cp->rt10_op_code = C10OP_READTOC;
- rt10cp->rt10_msf = 0; /* don't use msf format */
- rt10cp->rt10_starttrack = 0;
- /* read only in$ n track 0 to find out TOC data length */
- rt10cp->rt10_length = sizeof(struct toc10_reply);
-
- sr.sr_addr = (char *) &tocr;
- sr.sr_dma_max = sizeof(tocr);
- sr.sr_ioto = 5; /* time out in 5 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
- *erp = sr.sr_esense;
- if (err | sr.sr_io_status) { /* problem reading TOC, return */
- return err | sr.sr_io_status;
- }
-
- /* record first & last track, and toc data length */
- toc_all->firsttrack = tocr.h.rtr_firsttrack;
- toc_all->lasttrack = tocr.h.rtr_lasttrack;
- toc_data_length = tocr.h.rtr_datalength;
- nrecords = toc_data_length / sizeof(struct rtr10_desc);
-
- /* prepare for second read toc for the whole thing */
- bzero((char *)&sr, sizeof(sr));
-
- rt10cp = (struct readtoc10_cmd *)&sr.sr_cdb;
- rt10cp->rt10_op_code = C10OP_READTOC;
- rt10cp->rt10_msf = 1; /* want msf format */
- rt10cp->rt10_starttrack = 0;
- /* read only info on track 0 to find out TOC data length */
- rt10cp->rt10_length = toc_data_length + sizeof(struct rtr_header);
-
- toc_reply = (char *) malloc(toc_data_length + sizeof(struct rtr_header));
- sr.sr_addr = toc_reply;
- sr.sr_dma_max = toc_data_length + sizeof(struct rtr_header);
- sr.sr_ioto = 5; /* time out in 5 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
- *erp = sr.sr_esense;
- if (err | sr.sr_io_status) { /* problem reading TOC, return */
- return err | sr.sr_io_status;
- }
-
- /* successfully read the whole thing, now process it */
- toc_all->naudio = toc_all->ndata = 0; /* zero counts */
- for (i=0; i<=100; i++) { /* first initialize addr to be invalid */
- toc_all->info[i].hour = -1;
- toc_all->info[i].min = -1;
- toc_all->info[i].sec = -1;
- toc_all->info[i].frame = -1;
- }
- desc = (struct rtr10_desc *) &(toc_reply[4]); /* skip the header */
- for (i=0; i<nrecords; i++) {
- track = desc->t10d_track;
- if (track == 0xaa) track = 100; /* transition area */
- if (desc->t10d_control & DATA_TRACK)
- toc_all->ndata++;
- else if (track != 100)
- toc_all->naudio++;
- toc_all->info[track].control = desc->t10d_control;
- toc_all->info[track].hour = desc->t10d_hour;
- toc_all->info[track].min = desc->t10d_min;
- toc_all->info[track].sec = desc->t10d_sec;
- toc_all->info[track].frame = desc->t10d_frame;
- desc++;
- }
- #ifdef CD_DEBUG
- /* print the table of contents to stderr */
- for (i=toc_all->firsttrack; i<=toc_al$ asttrack; i++) {
- printf("Track %2d: %d:%d:%d:%d %c\n", i,
- toc_all->info[i].hour, toc_all->info[i].min, toc_all->info[i].sec,
- toc_all->info[i].frame,
- toc_all->info[i].control&DATA_TRACK? 'D' : 'A');
- }
- printf("Track LO: %d:%d:%d:%d %c\n",
- toc_all->info[100].hour, toc_all->info[100].min,
- toc_all->info[100].sec, toc_all->info[100].frame,
- toc_all->info[100].control&DATA_TRACK? 'D' : 'A');
- #endif
- return err | sr.sr_io_status;
- }
-
- /* play audio (C6OP_PLAYAUDIO = c8h) */
- int do_playaudio(int fd, int lba, int length, struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct playaudio_cmd *pap;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- pap = (struct playaudio_cmd *)&sr.sr_cdb;
- pap->pa_op_code = C6OP_PLAYAUDIO;
- pap->pa_lba = lba; /* block to play audio from */
- pap->pa_length = length;
-
- sr.sr_addr = NULL;
- sr.sr_dma_max = 0;
- sr.sr_ioto = 10; /* time out in 10 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
-
- if (sr.sr_dma_xfr != 0)
- fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
-
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* pause audio (C10OP_PAUSE = c5h) */
- int do_pauseaudio(int fd, int pause, struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct pause_cmd *pp;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- pp = (struct pause_cmd *)&sr.sr_cdb;
- pp->p_op_code = C10OP_PAUSE;
- pp->p_pause = pause;
-
- sr.sr_addr = NULL;
- sr.sr_dma_max = 0;
- sr.sr_ioto = 5; /* time out in 5 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
-
- if (sr.sr_dma_xfr != 0)
- fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
-
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* play audio (C10OP_PLAYAUDIO_MSF = 47h) */
- int do_playaudio_msf(int fd, struct msf startmsf, struct msf endmsf,
- struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct playaudio_msf_cmd *pap;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- pap = (struct playaudio_msf_cmd *)&sr.sr_cdb;
- pap->pam_op_code = C10OP_PLAYAUDIO_MSF;
- pap->pam_start_min = startmsf.min;
- pap->pam_start_sec = startmsf.sec;
- pap->pam_start_frame = startmsf.frame;
- pap->pam_end_min = endmsf.min;
- pap->pam_end_sec = endmsf.sec;
- pap->pam_end_frame = endmsf.frame;
-
- sr.sr_addr = NULL;
- sr.sr_dma_max = 0;
- sr.sr_ioto = 10; /* time out in 10 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl($ SDIOCSRQ, &sr);
-
- if (sr.sr_dma_xfr != 0)
- fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
-
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* read sub-channel data (C10OP_READSUBHCANNEL = 42h) */
- int do_readsubchannel(int fd, int msf, int subq, int page, int track,
- struct sc_reply *scrp, struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct readsc_cmd *rscp;
- int err;
- int i;
- char *cptr;
-
- bzero((char *)&sr, sizeof(sr));
-
- rscp = (struct readsc_cmd *) &sr.sr_cdb;
- rscp->rsc_op_code = C10OP_READSUBHCANNEL;
- rscp->rsc_msf = msf;
- rscp->rsc_subq = subq;
- rscp->rsc_dformat = page;
- rscp->rsc_track = track;
- rscp->rsc_length = sizeof(struct sc_reply);
-
- cptr = (char *) rscp;
- /* printf("Cmd: ");
- for (i=0; i<10; i++) {
- printf("%.2x ", *cptr++);
- }
- printf("\n");*/
-
- sr.sr_addr = (char *) scrp;
- sr.sr_dma_max = sizeof(struct sc_reply);
- sr.sr_ioto = 5; /* time out in 5 seconds */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* get playback status data (C10OP_PLAYBACKSTATUS = c4h) */
- int do_playbackstatus(int fd, struct playback_data *pbdatap,
- struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct playback_cmd *pbcp;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- pbcp = (struct playback_cmd *) &sr.sr_cdb;
- pbcp->pb_opcode = C10OP_PLAYBACKSTATUS;
- pbcp->pb_length = sizeof(struct playback_data);
-
- sr.sr_addr = (char *) pbdatap;
- sr.sr_dma_max = sizeof(struct playback_data);
- sr.sr_ioto = 1; /* time out in 1 second */
- sr.sr_dma_dir = SR_DMA_RD;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
-
- /* playback status control (C10OP_PLAYBACKCONTROL = c9h) */
- int do_playbackcontrol(int fd, struct playback_data *pbdatap,
- struct esense_reply *erp)
- {
- struct scsi_req sr;
- struct playback_cmd *pbcp;
- int err;
-
- bzero((char *)&sr, sizeof(sr));
-
- pbcp = (struct playback_cmd *) &sr.sr_cdb;
- pbcp->pb_opcode = C10OP_PLAYBACKCONTROL;
- pbcp->pb_length = sizeof(struct playback_data);
-
- sr.sr_addr = (char *) pbdatap;
- sr.sr_dma_max = sizeof(struct playback_data);
- sr.sr_ioto = 1; /* time out in 1 second */
- sr.sr_dma_dir = SR_DMA_WR;
-
- err = ioctl(fd, SDIOCSRQ, &sr);
- *erp = sr.sr_esense;
- return err | sr.sr_io_status;
- }
-
- /* print sub-channel data */
- void printf_sc(int page, struct sc_re$ *scrp)
- {
- struct msf *msfp; /* msf structure */
- int i;
-
- printf("Audio status: %.2x, Page %d\n", scrp->scr_header.sch_astatus,
- page);
- switch (page) {
- case 1: /* page 1 */
- printf("Track : %d\n", scrp->u.u_scr_cur_pos.sc1_track);
- printf("Index : %d\n", scrp->u.u_scr_cur_pos.sc1_index);
- msfp = (struct msf *) &(scrp->u.u_scr_cur_pos.sc1_abs_addr);
- printf("Abs Address : %d:%d:%d:%d\n", msfp->hour, msfp->min,
- msfp->sec, msfp->frame);
- msfp = (struct msf *) &(scrp->u.u_scr_cur_pos.sc1_rel_addr);
- printf("Rel Address : %d:%d:%d:%d\n", msfp->hour, msfp->min,
- msfp->sec, msfp->frame);
- break;
- case 2: /* page 2 */
- printf("MCVal : %d\n", scrp->u.u_scr_med_cat.sc2_mcval);
- printf("MCatalog : ");
- for (i=0; i<15; i++) {
- printf("%.2x", scrp->u.u_scr_med_cat.sc2_med_cat[i]);
- }
- printf("\n");
- break;
- case 3: /* page 3 */
- /* don't need to use it now */
- printf("Page 3 not currently implemented\n");
- break;
- default:
- printf("Unknown page number %d\n", page);
- break;
- }
- return;
- }
-
-
- /* print playback status data */
- void printf_pb(struct playback_data *pbdatap)
- {
- printf("pbd_ch0_sel: 0x%x\n", pbdatap->pbd_ch0_sel);
- printf("pbd_ch0_vol: 0x%x\n", pbdatap->pbd_ch0_vol);
- printf("pbd_ch1_sel: 0x%x\n", pbdatap->pbd_ch1_sel);
- printf("pbd_ch1_vol: 0x%x\n", pbdatap->pbd_ch1_vol);
- printf("pbd_ch2_sel: 0x%x\n", pbdatap->pbd_ch2_sel);
- printf("pbd_ch2_vol: 0x%x\n", pbdatap->pbd_ch2_vol);
- printf("pbd_ch3_sel: 0x%x\n", pbdatap->pbd_ch3_sel);
- printf("pbd_ch3_vol: 0x%x\n", pbdatap->pbd_ch3_vol);
- return;
- }
-