File:  [NeXTSTEP 3.3 examples] / Examples / UNIX / SCSI_CD / cd_commands.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:48:25 2018 UTC (8 years, 1 month ago) by root
Branches: NeXT, MAIN
CVS tags: NeXTSTEP33, HEAD
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;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.