drv_mmc.c

来自「刻录光盘的程序」· C语言 代码 · 共 1,299 行 · 第 1/3 页

C
1,299
字号
 #ifdef	DEBUG	scsiprbytes("CD write parameter:", (u_char *)mode, len);#endif	if (!set_mode_params(scgp, "CD write parameter", mode, len, 0, trackp->secsize))		return (-1);	return (0);}LOCAL intclose_track_mmc(scgp, track, trackp)	SCSI	*scgp;	int	track;	track_t	*trackp;{	int	ret;	if (!is_tao(trackp))		return (0);	if (scsi_flush_cache(scgp) < 0) {		printf("Trouble flushing the cache\n");		return -1;	}	wait_unit_ready(scgp, 300);		/* XXX Wait for ATAPI */	if (is_packet(trackp) && !is_noclose(trackp)) {			/* close the incomplete track */		ret = scsi_close_tr_session(scgp, 1, 0xFF);		wait_unit_ready(scgp, 300);	/* XXX Wait for ATAPI */		return (ret);	}	return (0);}int	toc2sess[] = {	SES_DA_ROM,	/* CD-DA		 */	SES_DA_ROM,	/* CD-ROM		 */	SES_XA,		/* CD-ROM XA mode 1	 */	SES_XA,		/* CD-ROM XA MODE 2	 */	SES_CDI,	/* CDI			 */	SES_DA_ROM,	/* Invalid - use default */	SES_DA_ROM,	/* Invalid - use default */};LOCAL intopen_session_mmc(scgp, tracks, trackp, toctype, multi)	SCSI	*scgp;	int	tracks;	track_t	*trackp;	int	toctype;	int	multi;{	u_char	mode[0x100];	int	len;	struct	cd_mode_page_05 *mp;	fillbytes((caddr_t)mode, sizeof(mode), '\0');	if (!get_mode_params(scgp, 0x05, "CD write parameter",			mode, (u_char *)0, (u_char *)0, (u_char *)0, &len))		return (-1);	if (len == 0)		return (-1);	mp = (struct cd_mode_page_05 *)		(mode + sizeof(struct scsi_mode_header) +		((struct scsi_mode_header *)mode)->blockdesc_len);	mp->write_type = WT_TAO; /* fix to allow DAO later */	if (!is_tao(trackp)) {		mp->write_type = WT_SAO;		mp->track_mode = 0;		mp->dbtype = DB_RAW;	}	mp->multi_session = (multi != 0) ? MS_MULTI : MS_NONE;	mp->session_format = toc2sess[toctype & TOC_MASK];	if (trackp->isrc) {		mp->media_cat_number[0] = 0x80;	/* Set MCN valid */		strncpy((char *)&mp->media_cat_number[1], trackp->isrc, 13);	} else {		fillbytes(&mp->media_cat_number[0], sizeof(mp->media_cat_number), '\0');	}#ifdef	DEBUG	scsiprbytes("CD write parameter:", (u_char *)mode, len);#endif	if (!set_mode_params(scgp, "CD write parameter", mode, len, 0, -1))		return (-1);	return (0);}LOCAL intwaitfix_mmc(scgp, secs)	SCSI	*scgp;	int	secs;{	char	dibuf[16];	int	i;	int	key;#define	W_SLEEP	2	scgp->silent++;	for (i = 0; i < secs/W_SLEEP; i++) {		if (read_disk_info(scgp, dibuf, sizeof(dibuf)) >= 0) {			scgp->silent--;			return (0);		}		key = scsi_sense_key(scgp);		if (key != SC_UNIT_ATTENTION && key != SC_NOT_READY)			break;		sleep(W_SLEEP);	}	scgp->silent--;	return (-1);#undef	W_SLEEP}LOCAL intfixate_mmc(scgp, onp, dummy, toctype, tracks, trackp)	SCSI	*scgp;	int	onp;	int	dummy;	int	toctype;	int	tracks;	track_t	*trackp;{	int	ret = 0;	int	key = 0;	int	code = 0;	struct timeval starttime;	struct timeval stoptime;	starttime.tv_sec = 0;	starttime.tv_usec = 0;	stoptime = starttime;	gettimeofday(&starttime, (struct timezone *)0);	if (dummy && lverbose)		printf("WARNING: Some drives don't like fixation in dummy mode.\n");	if (is_tao(trackp)) {	scgp->silent++;	ret = scsi_close_tr_session(scgp, 2, 0);	scgp->silent--;	key = scsi_sense_key(scgp);	code = scsi_sense_code(scgp);	} else {		if (scsi_flush_cache(scgp) < 0)			printf("Trouble flushing the cache\n");	}	if (ret >= 0) {		wait_unit_ready(scgp, 420/curspeed);	/* XXX Wait for ATAPI */		waitfix_mmc(scgp, 420/curspeed);	/* XXX Wait for ATAPI */		return (ret);	}	if ((dummy != 0 && (key != SC_ILLEGAL_REQUEST)) ||		/*		 * Try to suppress messages from drives that don't like fixation		 * in -dummy mode.		 */	    ((dummy == 0) &&	     ( ((key != SC_UNIT_ATTENTION) && (key != SC_NOT_READY)) ||				((code != 0x2E) && (code != 0x04)) ||				(strncmp(scgp->inq->vendor_info, "MITSUMI", 7) != 0)))) {		/*		 * UNIT ATTENTION/2E seems to be a magic for old Mitsumi ATAPI drives		 * NOT READY/ code 4 qual 7 (logical unit not ready, operation in progress)		 * seems to be a magic for newer Mitsumi ATAPI drives		 * when returning early from fixating.		 * Try to supress the error message in this case to make		 * simple minded users less confused.		 */		scsiprinterr(scgp);		scsiprintresult(scgp);	/* XXX restore key/code in future */	}	wait_unit_ready(scgp, 420);	/* XXX Wait for ATAPI */	waitfix_mmc(scgp, 420/curspeed);/* XXX Wait for ATAPI */	if (!dummy &&		(ret >= 0 || (key == SC_UNIT_ATTENTION && code == 0x2E))) {		/*		 * Some ATAPI drives (e.g. Mitsumi) imply the		 * IMMED bit in the SCSI cdb. As there seems to be no		 * way to properly check for the real end of the		 * fixating process we wait for the expected time.		 */		gettimeofday(&stoptime, (struct timezone *)0);		timevaldiff(&starttime, &stoptime);		if (stoptime.tv_sec < (220 / curspeed)) {			unsigned secs;			if (lverbose) {				printf("Actual fixating time: %ld seconds\n",							(long)stoptime.tv_sec);			}			secs = (280 / curspeed) - stoptime.tv_sec;			if (lverbose) {				printf("ATAPI early return: sleeping %d seconds.\n",								secs);			}			sleep(secs);		}	}	return (ret);}char	*blank_types[] = {	"entire disk",	"PMA, TOC, pregap",	"incomplete track",	"reserved track",	"tail of track",	"closing of last session",	"last session",	"reserved blanking type",};LOCAL intblank_mmc(scgp, addr, blanktype)	SCSI	*scgp;	long	addr;	int	blanktype;{	BOOL	cdrr	 = FALSE;	/* Read CD-R	*/	BOOL	cdwr	 = FALSE;	/* Write CD-R	*/	BOOL	cdrrw	 = FALSE;	/* Read CD-RW	*/	BOOL	cdwrw	 = FALSE;	/* Write CD-RW	*/	mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL);	if (!cdwrw)		return (blank_dummy(scgp, addr, blanktype));	if (lverbose) {		printf("Blanking %s\n", blank_types[blanktype & 0x07]);		flush();	}	return (scsi_blank(scgp, addr, blanktype));}LOCAL intscsi_sony_write(scgp, bp, sectaddr, size, blocks, islast)	SCSI	*scgp;	caddr_t	bp;		/* address of buffer */	long	sectaddr;	/* disk address (sector) to put */	long	size;		/* number of bytes to transfer */	int	blocks;		/* sector count */	BOOL	islast;		/* last write for track */{	return (write_xg5(scgp, bp, sectaddr, size, blocks));}Uchar	db2df[] = {	0x00,			/*  0 2352 bytes of raw data			*/	0xFF,			/*  1 2368 bytes (raw data + P/Q Subchannel)	*/	0xFF,			/*  2 2448 bytes (raw data + P-W Subchannel)	*/	0xFF,			/*  3 2448 bytes (raw data + P-W raw Subchannel)*/	0xFF,			/*  4 -    Reserved				*/	0xFF,			/*  5 -    Reserved				*/	0xFF,			/*  6 -    Reserved				*/	0xFF,			/*  7 -    Vendor specific			*/	0x10,			/*  8 2048 bytes Mode 1 (ISO/IEC 10149)		*/	0xFF,			/*  9 2336 bytes Mode 2 (ISO/IEC 10149)		*/	0xFF,			/* 10 2048 bytes Mode 2! (CD-ROM XA form 1)	*/	0xFF,			/* 11 2056 bytes Mode 2 (CD-ROM XA form 1)	*/	0xFF,			/* 12 2324 bytes Mode 2 (CD-ROM XA form 2)	*/	0xFF,			/* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr)	*/	0xFF,			/* 14 -    Reserved				*/	0xFF,			/* 15 -    Vendor specific			*/};#include <stdxlib.h>LOCAL	void	fillcue		__PR((struct mmc_cue *cp, int ca, int tno, int idx, int dataform, int scms, msf_t *mp));EXPORT	int	do_cue		__PR((int tracks, track_t *trackp, struct mmc_cue **cuep));EXPORT	int	send_cue	__PR((SCSI *scgp, int tracks, track_t *trackp));EXPORT intdo_cue(tracks, trackp, cuep)	int	tracks;	track_t	*trackp;	struct mmc_cue	**cuep;{	int	i;	struct mmc_cue	*cue;	struct mmc_cue	*cp;	int	ncue = 0;	int	icue = 0;	int	pgsize;	msf_t	m;	int	ctl;	int	df;	int	scms;	cue = (struct mmc_cue *)malloc(1);	for (i = 0; i <= tracks; i++) {		ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;		if (is_copy(&trackp[i]))			ctl |= TM_ALLOW_COPY << 4;		df = db2df[trackp[i].dbtype & 0x0F];		if (trackp[i].isrc) {	/* MCN or ISRC */			ncue += 2;			cue = (struct mmc_cue *)realloc(cue, ncue * sizeof(*cue));			cp = &cue[icue++];			if (i == 0) {				cp->cs_ctladr = 0x02;				movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);				cp = &cue[icue++];				cp->cs_ctladr = 0x02;				movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);			} else {				cp->cs_ctladr = 0x03;				cp->cs_tno = i;				movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);				cp = &cue[icue++];				cp->cs_ctladr = 0x03;				cp->cs_tno = i;				movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);			}		}		if (i == 0) {	/* Lead in */			if (df < 0x10)				df |= 1;			else				df |= 4;			lba_to_msf(-150, &m);			cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue));			cp = &cue[icue++];			fillcue(cp, ctl|0x01, i, 0, df, 0, &m);		} else {			scms = 0;			if (is_scms(&trackp[i]))				scms = 0x80;			pgsize = trackp[i].pregapsize;/*			if (pgsize == 0)*//*				pgsize = 150;*/			lba_to_msf(trackp[i].trackstart-pgsize, &m);			cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue));			cp = &cue[icue++];			fillcue(cp, ctl|0x01, i, 0, df, scms, &m);			if (trackp[i].nindex == 1) {				lba_to_msf(trackp[i].trackstart, &m);				cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue));				cp = &cue[icue++];				fillcue(cp, ctl|0x01, i, 1, df, scms, &m);			} else {				int	idx;				long	*idxlist;				ncue += trackp[i].nindex;				idxlist = trackp[i].tindex;				cue = (struct mmc_cue *)realloc(cue, ncue * sizeof(*cue));				for(idx = 1; idx <=trackp[i].nindex; idx++) {					lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);					cp = &cue[icue++];					fillcue(cp, ctl|0x01, i, idx, df, scms, &m);				}			}		}	}	/* Lead out */	ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;	df = db2df[trackp[tracks+1].dbtype & 0x0F];	if (df < 0x10)		df |= 1;	else		df |= 4;	lba_to_msf(trackp[tracks+1].trackstart, &m);	cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue));	cp = &cue[icue++];	fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);	if (lverbose > 1) for (i = 0; i < ncue; i++) {		scsiprbytes("", (Uchar *)&cue[i], 8);	}	if (cuep)		*cuep = cue;	return (ncue);}LOCAL voidfillcue(cp, ca, tno, idx, dataform, scms, mp)	struct mmc_cue	*cp;	/* The target cue entry		*/	int	ca;		/* Control/adr for this entry	*/	int	tno;		/* Track number for this entry	*/	int	idx;		/* Index for this entry		*/	int	dataform;	/* Data format for this entry	*/	int	scms;		/* Serial copy management	*/	msf_t	*mp;		/* MSF value for this entry	*/{	cp->cs_ctladr = ca;	/* XXX wie lead in */	cp->cs_tno = tno;	cp->cs_index = idx;	cp->cs_dataform = dataform;/* XXX wie lead in */	cp->cs_scms = scms;	cp->cs_min = mp->msf_min;	cp->cs_sec = mp->msf_sec;	cp->cs_frame = mp->msf_frame;}EXPORT intsend_cue(scgp, tracks, trackp)	SCSI	*scgp;	int	tracks;	track_t	*trackp;{	struct mmc_cue	*cp;	int		ncue;	int		ret;	int		i;	ncue = do_cue(tracks, trackp, &cp);	for (i = 1; i <= tracks; i++) {		if (trackp[i].tracksize < 0) {			errmsgno(EX_BAD, "Track %d has unknown length.\n", i);			return (-1);		}	}	ret = send_cue_sheet(scgp, (caddr_t)cp, ncue*8);	free(cp);	return (ret);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?