|
|
Sample Programs from NeXSTEP 3.3
/*
* 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);
*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;
}
/* 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 info on 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_all->lasttrack; 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(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;
}
/* 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_reply *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;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.