[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#181028: cdrecord: promotes non-free software



Since I am a strong believer in put-up or shut-up, I've forward ported
the DVD-R support patch to cdrtools-2.0. This small simple patch applies
to the cdrtools in unstable. It also removes the offending message about
using dvdpro. I just wasted 5 DVD-R's testing burns (all worked) of
random files on my harddrive, aswell as 1 DVD-R for burning a home
movie mpeg2 converted with dvdauthor to correct DVD-video format (piped
through mkisofs --dvd-video). So I've got around $10 invested in this.

I honestly don't care if this patch is accepted upstream. I really
expect that it wont be, for whatever reason. I do expect it to be
applied to the Debian source though. The cdrtools author has been kind
enough to give a mechanism for creating a binary that is known to be
modified from the original source which might contain bugs, and even
supply an email address for where to send bug reports.

Because of that mechanism, it completely alleviates most fears regarding
the author having to support our patches, so I don't want to hear such
complaints.

-- 
Debian     - http://www.debian.org/
Linux 1394 - http://www.linux1394.org/
Subversion - http://subversion.tigris.org/
Deqo       - http://www.deqo.com/
--- cdrtools-2.0.orig/cdda2wav/scsi_cdr.c	2002-11-03 10:32:56.000000000 -0500
+++ cdrtools-2.0/cdda2wav/scsi_cdr.c	2003-02-23 01:12:27.000000000 -0500
@@ -753,6 +753,37 @@
 	return (scg_cmd(scgp));
 }
 
+
+EXPORT int
+read_rzone_info(scgp, bp, track, cnt)
+	SCSI    *scgp;
+	caddr_t bp;
+	int     track;
+	int     cnt;
+
+{
+	register struct scg_cmd *scmd = scgp->scmd;
+
+	fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+	scmd->addr = bp;
+	scmd->size = cnt;
+	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+	scmd->cdb_len = SC_G1_CDBLEN;
+	scmd->sense_len = CCS_SENSE_LEN;
+	scmd->timeout = 4 * 60;         /* Needs up to 2 minutes */
+	scmd->cdb.g1_cdb.cmd = 0x52;
+	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
+	scmd->cdb.g1_cdb.reladr = 1;
+	g1_cdbaddr(&scmd->cdb.g1_cdb, track);
+	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+	scgp->cmdname = "read rzone info";
+
+	if (scg_cmd(scgp) < 0)
+		return (-1);
+	return (0);
+}
+
 EXPORT int
 read_subchannel(scgp, bp, track, cnt, msf, subq, fmt)
 	SCSI	*scgp;
@@ -948,6 +979,30 @@
 }
 
 EXPORT int
+reserve_track(scgp, size)
+	SCSI    *scgp;
+	Ulong   size;
+
+{
+	register struct scg_cmd *scmd = scgp->scmd;
+
+	fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+	scmd->flags = SCG_DISRE_ENA;
+	scmd->cdb_len = SC_G1_CDBLEN;
+	scmd->sense_len = CCS_SENSE_LEN;
+	scmd->cdb.g1_cdb.cmd = 0x53;
+	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
+	i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], size);
+
+	scgp->cmdname = "reserve track";
+
+	if (scg_cmd(scgp) < 0)
+		return (-1);
+
+	return (0);
+}
+
+EXPORT int
 read_dvd_structure(scgp, bp, cnt, fmt)
 	SCSI	*scgp;
 	caddr_t	bp;
--- cdrtools-2.0.orig/cdrecord/cdr_drv.c	2002-09-25 07:22:30.000000000 -0400
+++ cdrtools-2.0/cdrecord/cdr_drv.c	2003-02-22 21:06:16.000000000 -0500
@@ -42,6 +42,7 @@
 extern	cdr_t	cdr_oldcd;
 extern	cdr_t	cdr_cd;
 extern	cdr_t	cdr_mmc;
+extern	cdr_t	cdr_dvd;
 extern	cdr_t	cdr_mmc_sony;
 extern	cdr_t	cdr_cd_dvd;
 extern	cdr_t	cdr_philips_cdd521O;
@@ -78,6 +79,7 @@
 cdr_t	*drivers[] = {
 	&cdr_cd_dvd,
 	&cdr_mmc,
+	&cdr_dvd,
 	&cdr_mmc_sony,
 	&cdr_cd,
 	&cdr_oldcd,
--- cdrtools-2.0.orig/cdrecord/cdrecord.c	2002-12-24 08:16:39.000000000 -0500
+++ cdrtools-2.0/cdrecord/cdrecord.c	2003-02-23 02:06:13.000000000 -0500
@@ -4,7 +4,7 @@
 	"@(#)cdrecord.c	1.216 02/12/24 Copyright 1995-2002 J. Schilling";
 #endif
 /*
- *	Record data on a CD/CVD-Recorder
+ *	Record data on a CD/DVD-Recorder
  *
  *	Copyright (c) 1995-2002 J. Schilling
  */
@@ -542,12 +542,6 @@
 		if (!is_mmc(scgp, &is_cdwr, &is_dvdwr))
 			is_cdwr = TRUE;			/* If it is not MMC, it must be a CD writer */
 
-		if (is_dvdwr && !set_cdrcmds("mmc_dvd", (cdr_t **)NULL)) {
-			errmsgno(EX_BAD,
-			"This version of cdrecord does not include DVD-R/DVD-RW support code.\n");
-			errmsgno(EX_BAD,
-			"If you need DVD-R/DVD-RW support, ask the Author for cdrecord-ProDVD.\n");
-		}
 		/*
 		 * Only exit if this is not the ProDVD test binary.
 		 */
@@ -620,6 +614,21 @@
 	}
 	scgp->silent--;
 
+	/* If it is DVD, the information in TOC is fabricated :)
+	 * The real information is from read disk info command.  */
+	if (dp->cdr_dstat->ds_flags & DSF_DVD) {
+		/* If it is DVD, the information in TOC is fabricated :)
+		 * The real information is from read disk info command. */
+		if (dp->cdr_dstat->ds_trlast > 0) {
+			trackno = dp->cdr_dstat->ds_trlast - 1;
+			printf("Track Number   : %d\n", trackno);
+		}
+
+		/* Disable TAO. DVD's don't need this in order to support
+		 * packet writing. XXX */
+		//track[1].flags &= ~TI_TAO;
+	}
+
 	if (tracks > 0 && (debug || lverbose))
 		printf("FIFO size      : %lu = %lu KB\n", fs, fs >> 10);
 
@@ -3061,7 +3070,7 @@
 			flags &= ~TI_SHORT_TRACK;
 		if (bswab)
 			flags |= TI_SWAB;
-		if (ispacket) 
+		if (ispacket)
 			flags |= TI_PACKET;
 		if (noclose) 
 			flags |= TI_NOCLOSE;
--- cdrtools-2.0.orig/cdrecord/cdrecord.h	2002-11-03 10:32:55.000000000 -0500
+++ cdrtools-2.0/cdrecord/cdrecord.h	2003-02-22 22:42:11.000000000 -0500
@@ -819,6 +819,9 @@
 					BOOL *cdrrwp, BOOL *cdwrwp,
 					BOOL *dvdp, BOOL *dvdwp));
 extern	void	print_capabilities	__PR((SCSI *scgp));
+
+extern int read_rzone_info __PR((SCSI *scgp, caddr_t bp, int track, int cnt));
+extern int reserve_track __PR((SCSI *scgp, Ulong size));
 #endif
 
 /*
--- cdrtools-2.0.orig/cdrecord/drv_mmc.c	2002-11-30 07:01:30.000000000 -0500
+++ cdrtools-2.0/cdrecord/drv_mmc.c	2003-02-23 03:50:48.000000000 -0500
@@ -82,6 +82,7 @@
 EXPORT	char	*hasdrvopt		__PR((char *optstr, char *optname));
 LOCAL	cdr_t	*identify_mmc		__PR((SCSI *scgp, cdr_t *, struct scsi_inquiry *));
 LOCAL	int	attach_mmc		__PR((SCSI *scgp, cdr_t *));
+LOCAL	int	attach_dvd		__PR((SCSI *scgp, cdr_t *));
 EXPORT	int	check_writemodes_mmc	__PR((SCSI *scgp, cdr_t *dp));
 LOCAL	int	deflt_writemodes_mmc	__PR((SCSI *scgp, BOOL reset_dummy));
 LOCAL	int	get_diskinfo		__PR((SCSI *scgp, struct disk_info *dip));
@@ -91,15 +92,22 @@
 LOCAL	int	get_pma			__PR((SCSI *scgp));
 #endif
 LOCAL	int	getdisktype_mmc		__PR((SCSI *scgp, cdr_t *dp));
+LOCAL	int	getdisktype_dvd		__PR((SCSI *scgp, cdr_t *dp));
 LOCAL	int	speed_select_mmc	__PR((SCSI *scgp, cdr_t *dp, int *speedp, int dummy));
+LOCAL	int	speed_select_dvd	__PR((SCSI *scgp, cdr_t *dp, int *speedp, int dummy));
 LOCAL	int	mmc_set_speed		__PR((SCSI *scgp, int readspeed, int writespeed, int rotctl));
 LOCAL	int	next_wr_addr_mmc	__PR((SCSI *scgp, track_t *trackp, long *ap));
+LOCAL	int	next_wr_addr_dvd	__PR((SCSI *scgp, track_t *trackp, long *ap));
 LOCAL	int	write_leadin_mmc	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
 LOCAL	int	open_track_mmc		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
+LOCAL	int	open_track_dvd		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
 LOCAL	int	close_track_mmc		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
+LOCAL	int	close_track_dvd		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
 LOCAL	int	open_session_mmc	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp, int toctype, int multi));
+LOCAL	int	open_session_dvd	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp, int toctype, int multi));
 LOCAL	int	waitfix_mmc		__PR((SCSI *scgp, int secs));
 LOCAL	int	fixate_mmc		__PR((SCSI *scgp, cdr_t *dp, int onp, int dummy, int toctype, track_t *trackp));
+LOCAL	int	fixate_dvd		__PR((SCSI *scgp, cdr_t *dp, int onp, int dummy, int toctype, track_t *trackp));
 LOCAL	int	blank_mmc		__PR((SCSI *scgp, cdr_t *dp, long addr, int blanktype));
 LOCAL	int	send_opc_mmc		__PR((SCSI *scgp, caddr_t, int cnt, int doopc));
 LOCAL	int	opt1_mmc		__PR((SCSI *scgp, cdr_t *dp));
@@ -174,6 +182,41 @@
 	opt1_mmc,
 };
 
+cdr_t   cdr_dvd = {
+	0, 0,
+	CDR_SWABAUDIO|CDR_DVD,
+	372, 372,
+	"mmc_dvd",
+	"generic SCSI-3/mmc DVD-R driver",
+	0,
+	(dstat_t *)0,
+	identify_mmc,
+	attach_dvd,
+	getdisktype_dvd,
+	scsi_load,
+	scsi_unload,
+	read_buff_cap,
+	(int(*)__PR((SCSI *)))cmd_dummy,        /* recovery_needed      */
+	(int(*)__PR((SCSI *, int)))cmd_dummy,   /* recover              */
+	speed_select_dvd,
+	select_secsize,
+	next_wr_addr_dvd,
+	(int(*)__PR((SCSI *, Ulong)))cmd_ill,   /* reserve_track        */
+	scsi_cdr_write,
+	(int(*)__PR((SCSI *scgp, track_t *trackp)))cmd_dummy, /* send_cue */
+	(int(*)__PR((SCSI *scgp, cdr_t *dp, track_t *trackp)))cmd_dummy, /* write_leadin_mmc */
+	open_track_dvd,
+	close_track_dvd,
+	open_session_dvd,
+	cmd_dummy,
+	read_session_offset,
+	fixate_dvd,
+	(int(*)__PR((SCSI *, cdr_t *)))cmd_dummy,/* stats               */
+	blank_mmc,
+	send_opc_mmc,
+	(int(*)__PR((SCSI *, cdr_t *)))cmd_dummy,/* opt1                */
+};
+
 cdr_t	cdr_mmc_sony = {
 	0, 0,
 /*	CDR_TAO|CDR_SAO|CDR_PACKET|CDR_SWABAUDIO,*/
@@ -494,7 +537,7 @@
 #ifndef	DVD_DEBUG
 		scgp->silent++;
 #else
-		error("identify_dvd: checking for DVD media\n");
+		error("identify_mmc: checking for DVD media\n");
 #endif
 		if (read_dvd_structure(scgp, (caddr_t)xb, 32, 0) >= 0) {
 			/*
@@ -521,13 +564,12 @@
 #ifndef	DVD_DEBUG
 		scgp->silent--;
 #else
-		error("identify_dvd: is_dvd: %d\n", is_dvd);
+		error("identify_mmc: is_dvd: %d\n", is_dvd);
 #endif
 	}
-	if (is_dvd) {
-		errmsgno(EX_BAD,
-		"Found DVD media but DVD-R/DVD-RW support code is missing.\n");
-	}
+	if (is_dvd)
+		dp = &cdr_dvd;
+
 	return (dp);
 }
 
@@ -684,6 +726,44 @@
 }
 
 
+LOCAL int
+attach_dvd(scgp, dp)
+	SCSI	*scgp;
+	cdr_t	*dp;
+{
+	struct  cd_mode_page_2A *mp;
+
+	allow_atapi(scgp, TRUE);/* Try to switch to 10 byte mode cmds */
+
+	scgp->silent++;
+	mp = mmc_cap(scgp, NULL);/* Get MMC capabilities in allocated mp */
+	scgp->silent--;
+	if (mp == NULL)
+		return (-1);    /* Pre SCSI-3/mmc drive         */
+
+	dp->cdr_cdcap = mp;     /* Store MMC cap pointer        */
+
+	if (mp->loading_type == LT_TRAY)
+		dp->cdr_flags |= CDR_TRAYLOAD;
+	else if (mp->loading_type == LT_CADDY)
+		dp->cdr_flags |= CDR_CADDYLOAD;
+
+	if (mp->BUF != 0)
+		dp->cdr_flags |= CDR_BURNFREE;
+
+	check_writemodes_mmc(scgp, dp);
+	dp->cdr_dstat->ds_flags |= DSF_DVD;
+
+	if (driveropts != NULL) {
+		if (strcmp(driveropts, "help") == 0) {
+			mmc_opthelp(dp, 0);
+		}
+	}
+
+	return (0);
+}
+
+
 EXPORT int
 check_writemodes_mmc(scgp, dp)
 	SCSI	*scgp;
@@ -974,6 +1054,10 @@
 
 	if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0)
 		dsp->ds_last_leadout = dsp->ds_maxblocks;
+
+	dsp->ds_trfirst=dip->first_track;
+	dsp->ds_trlast=dip->last_track_ls;
+	dsp->ds_trfirst_ls=dip->first_track_ls;
 }
 
 LOCAL int
@@ -1076,6 +1160,27 @@
 #endif	/* PRINT_ATIP */
 
 LOCAL int
+getdisktype_dvd(scgp, dp)
+	SCSI    *scgp;
+	cdr_t   *dp;
+{
+	struct track_info track_info;
+
+	if (getdisktype_mmc(scgp, dp) < 0)
+		return -1;
+
+	/* Read rzone info to get the space left on disk. ds_trlast is the last
+	 * rzone on disk, can be invisible */
+	if (read_rzone_info(scgp, (caddr_t)&track_info, dp->cdr_dstat->ds_trlast,
+			    sizeof(track_info)) >= 0)
+		dp->cdr_dstat->ds_maxblocks = a_to_u_4_byte(track_info.free_blocks) +
+				    a_to_4_byte(track_info.next_writable_addr);
+
+	return 0;
+}
+
+
+LOCAL int
 getdisktype_mmc(scgp, dp)
 	SCSI	*scgp;
 	cdr_t	*dp;
@@ -1565,6 +1670,29 @@
 	return (ret);
 }
 
+
+LOCAL int
+speed_select_dvd(scgp, dp, speedp, dummy)
+	SCSI    *scgp;
+	cdr_t	*dp;
+	int     *speedp;
+	int     dummy;
+{
+	int retcode;
+	/* For the moment we just divide the CD speed by 7*/
+
+	if (speedp != NULL)
+		(*speedp) = (*speedp) * 8;
+
+	retcode = speed_select_mmc(scgp,dp,speedp,dummy);
+
+	if (speedp != NULL)
+		(*speedp) = (*speedp) / 7;
+
+	return retcode;
+}
+
+
 LOCAL int
 next_wr_addr_mmc(scgp, trackp, ap)
 	SCSI	*scgp;
@@ -1604,6 +1732,47 @@
 	return (0);
 }
 
+
+LOCAL int
+next_wr_addr_dvd(scgp, trackp, ap)
+	SCSI    *scgp;
+	track_t *trackp;
+	long    *ap;
+{
+	struct  track_info      track_info;
+	long    next_addr;
+	int     result = -1;
+	struct  disk_info disk_info;
+
+	if (trackp != 0 && trackp->track > 0 && is_packet(trackp)) {
+		scgp->silent++;
+		result = read_rzone_info(scgp, (caddr_t)&track_info,
+					 trackp->track, sizeof(track_info));
+		scgp->silent--;
+		if (scsi_in_progress(scgp)){
+			return -1;
+		}
+	}
+
+	if (result < 0) {
+		/* Get the last rzone*/
+		if(read_disk_info(scgp,(caddr_t)&disk_info,8) < 0)
+			return (-1);
+
+		if (read_rzone_info(scgp, (caddr_t)&track_info,
+				    disk_info.last_track_ls, sizeof(track_info)) < 0)
+			return (-1);
+	}
+	if (scgp->verbose)
+		scg_prbytes("track info:", (Uchar *)&track_info,
+			    sizeof(track_info)-scg_getresid(scgp));
+	next_addr = a_to_4_byte(track_info.next_writable_addr);
+	if (ap)
+		*ap = next_addr;
+	return (0);
+}
+
+
 LOCAL int
 write_leadin_mmc(scgp, dp, trackp)
 	SCSI	*scgp;
@@ -1773,6 +1942,50 @@
 	return (0);
 }
 
+
+LOCAL int
+open_track_dvd(scgp, dp, trackp)
+	SCSI    *scgp;
+	cdr_t   *dp;
+	track_t *trackp;
+{
+	Uchar   mode[0x100];
+	int     len;
+	struct  cd_mode_page_05 *mp;
+
+	if (is_packet(trackp)) {
+		fillbytes((caddr_t)mode, sizeof(mode), '\0');
+
+		trackp[0].flags &= ~TI_TAO;
+
+		if (!get_mode_params(scgp, 0x05, "DVD write parameter",
+				     mode, (Uchar *)0, (Uchar *)0, (Uchar *)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_PACKET;
+		mp->LS_V = 1;
+		/* For now we set the link size to 0x10(32k) because
+		 * Pioneer-A03 only support this */
+		mp->link_size=0x10;
+		mp->fp = 1;
+		i_to_4_byte(mp->packet_size, trackp->pktsize);
+	} else {
+		return 0;
+	}
+
+	if (!set_mode_params(scgp, "DVD write parameter", mode, len, 0, trackp->secsize))
+		return (-1);
+
+	return (0);
+}
+
+
 LOCAL int
 close_track_mmc(scgp, dp, trackp)
 	SCSI	*scgp;
@@ -1808,6 +2021,31 @@
 	SES_DA_ROM,	/* Invalid - use default */
 };
 
+
+LOCAL int
+close_track_dvd(scgp, dp, trackp)
+	SCSI    *scgp;
+	cdr_t	*dp;
+	track_t *trackp;
+{
+	int     ret;
+
+	if (!is_packet(trackp))
+		return (0);
+
+	if (scsi_flush_cache(scgp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
+		printf("Trouble flushing the cache\n");
+		return (-1);
+	}
+	if (!is_noclose(trackp)) {
+		ret = scsi_close_tr_session(scgp, 1, trackp->track, FALSE);
+		wait_unit_ready(scgp, 300);
+		return (ret);
+	}
+	return (0);
+}
+
+
 LOCAL int
 open_session_mmc(scgp, dp, trackp, toctype, multi)
 	SCSI	*scgp;
@@ -1923,6 +2161,81 @@
 	return (0);
 }
 
+
+LOCAL int
+open_session_dvd(scgp, dp, trackp, toctype, multi)
+	SCSI    *scgp;
+	cdr_t   *dp;
+	track_t *trackp;
+	int     toctype;
+	int     multi;
+{
+	Uchar   mode[0x100];
+	int     len;
+	struct  cd_mode_page_05 *mp;
+	Ulong totalsize;
+	int i;
+	struct  track_info      track_info;
+
+	fillbytes((caddr_t)mode, sizeof(mode), '\0');
+
+	if (!get_mode_params(scgp, 0x05, "DVD write parameter",
+			     mode, (Uchar *)0, (Uchar *)0, (Uchar *)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);
+	if (is_packet(trackp)){
+		mp->write_type=WT_PACKET;
+		mp->multi_session = (multi != 0) ? MS_MULTI : MS_NONE;
+		mp->fp=0;
+		mp->BUFE=1;
+		mp->track_mode=1;
+	} else {
+		mp->write_type = WT_SAO;
+	}
+
+	if (lverbose && dp->cdr_cdcap->BUF != 0)
+		printf("BURN-Free is %s.\n", mp->BUFE?"ON":"OFF");
+	if (driveropts != NULL) {
+		if ((strcmp(driveropts, "burnproof") == 0 ||
+		     strcmp(driveropts, "burnfree") == 0) && dp->cdr_cdcap->BUF != 0) {
+			errmsgno(EX_BAD, "Turning BURN-Free on\n");
+			mp->BUFE = 1;
+		} else if ((strcmp(driveropts, "noburnproof") == 0 ||
+			    strcmp(driveropts, "noburnfree") == 0)) {
+			errmsgno(EX_BAD, "Turning BURN-Free off\n");
+			mp->BUFE = 0;
+		} else if (strcmp(driveropts, "help") == 0) {
+			mmc_opthelp(dp, 0);
+		} else {
+			errmsgno(EX_BAD, "Bad driver opts '%s'.\n", driveropts);
+			mmc_opthelp(dp, EX_BAD);
+		}
+	}
+
+
+	if (!set_mode_params(scgp, "DVD write parameter", mode, len, 0, -1))
+		return (-1);
+
+	totalsize = 0;
+	for (i = 1; i <= trackp->tracks; i++) {
+		totalsize += trackp[i].tracksecs;
+	}
+
+	if (!is_packet(trackp)) {
+		/* in DAO mode we need to reserve space for the track*/
+		if (reserve_track(scgp, totalsize)<0)
+			return (-1);
+	}
+
+	return (0);
+}
+
+
 LOCAL int
 waitfix_mmc(scgp, secs)
 	SCSI	*scgp;
@@ -1949,6 +2262,33 @@
 #undef	W_SLEEP
 }
 
+
+LOCAL int
+fixate_dvd(scgp, dp, onp, dummy, toctype, trackp)
+	SCSI    *scgp;
+	cdr_t	*dp;
+	int     onp;
+	int     dummy;
+	int     toctype;
+	track_t *trackp;
+{
+	int ret;
+
+	/* Set a really BIG timeout and call fixate_mmc. The BIG
+	 * timeout is needed in case there was a very short rzone to
+	 * write at the beginning of the disk, because lead-out needs
+	 * to be at some distance. */
+	scg_settimeout(scgp, 1000);
+	if (is_packet(trackp)) {
+		scsi_close_tr_session(scgp, 2, 0, FALSE);
+	}
+	ret = fixate_mmc(scgp, dp, onp, dummy, toctype, trackp);
+	scg_settimeout(scgp, 200);
+
+	return ret;
+}
+
+
 LOCAL int
 fixate_mmc(scgp, dp, onp, dummy, toctype, trackp)
 	SCSI	*scgp;
--- cdrtools-2.0.orig/cdrecord/scsi_cdr.c	2002-11-03 10:32:56.000000000 -0500
+++ cdrtools-2.0/cdrecord/scsi_cdr.c	2003-02-23 01:12:27.000000000 -0500
@@ -753,6 +753,37 @@
 	return (scg_cmd(scgp));
 }
 
+
+EXPORT int
+read_rzone_info(scgp, bp, track, cnt)
+	SCSI    *scgp;
+	caddr_t bp;
+	int     track;
+	int     cnt;
+
+{
+	register struct scg_cmd *scmd = scgp->scmd;
+
+	fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+	scmd->addr = bp;
+	scmd->size = cnt;
+	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+	scmd->cdb_len = SC_G1_CDBLEN;
+	scmd->sense_len = CCS_SENSE_LEN;
+	scmd->timeout = 4 * 60;         /* Needs up to 2 minutes */
+	scmd->cdb.g1_cdb.cmd = 0x52;
+	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
+	scmd->cdb.g1_cdb.reladr = 1;
+	g1_cdbaddr(&scmd->cdb.g1_cdb, track);
+	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+	scgp->cmdname = "read rzone info";
+
+	if (scg_cmd(scgp) < 0)
+		return (-1);
+	return (0);
+}
+
 EXPORT int
 read_subchannel(scgp, bp, track, cnt, msf, subq, fmt)
 	SCSI	*scgp;
@@ -948,6 +979,30 @@
 }
 
 EXPORT int
+reserve_track(scgp, size)
+	SCSI    *scgp;
+	Ulong   size;
+
+{
+	register struct scg_cmd *scmd = scgp->scmd;
+
+	fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+	scmd->flags = SCG_DISRE_ENA;
+	scmd->cdb_len = SC_G1_CDBLEN;
+	scmd->sense_len = CCS_SENSE_LEN;
+	scmd->cdb.g1_cdb.cmd = 0x53;
+	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
+	i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], size);
+
+	scgp->cmdname = "reserve track";
+
+	if (scg_cmd(scgp) < 0)
+		return (-1);
+
+	return (0);
+}
+
+EXPORT int
 read_dvd_structure(scgp, bp, cnt, fmt)
 	SCSI	*scgp;
 	caddr_t	bp;

Reply to: