From mmcg@mjolnir.cs.monash.edu.au  Thu Jun 19 19:34:08 1997
Received: from mjolnir.cs.monash.edu.au (heraclitus.cs.monash.edu.au [130.194.64.241])
          by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id TAA04522
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 19 Jun 1997 19:33:59 -0700 (PDT)
Received: (from mmcg@localhost)
	by mjolnir.cs.monash.edu.au (8.8.5/8.8.5) id MAA06498;
	Fri, 20 Jun 1997 12:33:07 +1000 (EST)
Message-Id: <199706200233.MAA06498@mjolnir.cs.monash.edu.au>
Date: Fri, 20 Jun 1997 12:33:07 +1000 (EST)
From: Mike McGaughey <mmcg@mjolnir.cs.monash.edu.au>
Reply-To: mmcg@mjolnir.cs.monash.edu.au
To: FreeBSD-gnats-submit@freebsd.org
Subject: Patches - new worm drivers for CDrom burners: Philips CDD522 and T.Yuden EW-50
X-Send-Pr-Version: 3.2

>Number:         3909
>Category:       kern
>Synopsis:       A patch supporting some new worm drivers
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    joerg
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jun 19 19:40:01 PDT 1997
>Closed-Date:    Fri Nov 5 08:51:45 MET 1999
>Last-Modified:  Fri Nov  5 08:52:51 MET 1999
>Originator:     Mike McGaughey
>Release:        FreeBSD 2.2.2-RELEASE i386
>Organization:
Monash University
>Environment:

Tested on:

2.2.2-RELEASE
T.YUDEN EW-50 CDrom burner (on slow scsi board)

>Description:

Here is a modification to the 2.2.2-RELEASE worm.c which implements
support for the Philips CDD 522 and T.Yuden EW-50 (very cheap in
Australia).  I suspect that the CDD522 is the `philips' in
`Philips/IMS/Kodak' drives, so this may work for many other CD burners.

NOTE: I have made a slight change to the handling of other CDrom
cutters.  In particular, the spindown/medium unload commands are
now sent *after* the cache flush when finalizing a track.  I suspect
this is the way it should have been in the first place, but am
interested in hearing reports on whether or not it made a difference.

I have burned a bunch of data CDs using this; I haven't tried
audios, multi-track, or multi-session disks (the multisession
support looks broken anyway, due to a block addressing issue).

>How-To-Repeat:

Apply the patch below.

>Fix:

Context diffs for /usr/src/sys/scsi/worm.c (the only
file that I modified).

*** worm.c.orig	Thu Jun 12 08:19:47 1997
--- worm.c	Sat Jun 14 20:54:00 1997
***************
*** 142,147 ****
--- 142,152 ----
  static errval hp4020i_finalize_track(struct scsi_link *);
  static errval hp4020i_finalize_disk(struct scsi_link *, int toc_type, int onp);
  
+ static errval cdd522_prepare_disk(struct scsi_link *, int dummy, int speed);
+ static errval cdd522_prepare_track(struct scsi_link *, int audio, int preemp);
+ static errval cdd522_finalize_track(struct scsi_link *);
+ static errval cdd522_finalize_disk(struct scsi_link *, int toc_type, int onp);
+ 
  static worm_devsw_installed = 0;
  
  static	d_open_t	wormopen;
***************
*** 205,210 ****
--- 210,226 ----
  		hp4020i_prepare_disk, hp4020i_prepare_track,
  		hp4020i_finalize_track, hp4020i_finalize_disk
  	},
+ 	{
+ 		"PHILIPS", "CDD522",
+ 		cdd522_prepare_disk, cdd522_prepare_track,
+ 		cdd522_finalize_track, cdd522_finalize_disk
+ 	},
+ 	{
+ 	/* (aic0:4:0): "T.YUDEN CD-WO EW-50 2.16" type 4 removable SCSI 2 */
+ 		"T.YUDEN", "EW-50",
+ 		cdd522_prepare_disk, cdd522_prepare_track,
+ 		cdd522_finalize_track, cdd522_finalize_disk
+ 	},
  	{0}
  };
  
***************
*** 563,577 ****
  	error = 0;
  
  	if ((worm->worm_flags & WORMFL_IOCTL_ONLY) == 0) {
- 		scsi_stop_unit(sc_link, 0, SCSI_SILENT);
- 		scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
  
! 		sc_link->flags &= ~SDEV_OPEN;
  
  		if ((flags & FWRITE) != 0) {
  			worm->worm_flags &= ~WORMFL_TRACK_PREPED;
  			error = (worm->quirks->finalize_track)(sc_link);
  		}
  	}
  	sc_link->flags &= ~SDEV_OPEN;
  	worm->worm_flags &= ~WORMFL_IOCTL_ONLY;
--- 579,603 ----
  	error = 0;
  
  	if ((worm->worm_flags & WORMFL_IOCTL_ONLY) == 0) {
  
! 		/*
! 		 * XXX: My T.YUDEN dies if we issue the stop_unit and allow_eject
! 		 * before flushing the cache, so I have called the finalizer before
! 		 * stopping the unit.  I suspect this is a far more reasonable
! 		 * ordering (but do not know if this breaks anything else) - MMCG
! 		 *
! 		 * It is concievable that another driver could break if its
! 		 * finalize_track routine relied on SDEV_OPEN having been reset
! 		 * by the time it is called (subtly different error semantics?)
! 		 */
  
  		if ((flags & FWRITE) != 0) {
  			worm->worm_flags &= ~WORMFL_TRACK_PREPED;
  			error = (worm->quirks->finalize_track)(sc_link);
  		}
+ 
+ 		scsi_stop_unit(sc_link, 0, SCSI_SILENT);
+ 		scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
  	}
  	sc_link->flags &= ~SDEV_OPEN;
  	worm->worm_flags &= ~WORMFL_IOCTL_ONLY;
***************
*** 1385,1388 ****
--- 1411,1698 ----
  
  /*
   * End HP C4324/C4325 (4020i) section.
+  */
+ 
+ /*
+  * Philips CDD522/Taiyo Yuden EW-50 section.
+  *
+  * Ack: I am very grateful to Philips, who supplied me with a SCSI manual
+  * for their unit.  Taiyo Yuden considers their manual proprietry.
+  *
+  * This section was written using the CDD522 SCSI manual, but has only
+  * been tested on my T.YUDEN EW-50 (it's a long story).
+  */
+ 
+ struct cdd_522_pages
+ {
+ 	u_char	page_code;
+ #define CDD522_PAGE_CODE_20 0x20
+ #define CDD522_PAGE_CODE_21 0x21
+ #define CDD522_PAGE_CODE_22 0x22
+ #define CDD522_PAGE_CODE_23 0x23
+ #define CDD522_PAGE_CODE_24 0x24
+ #define CDD522_PAGE_CODE_25 0x25
+ 	u_char	param_len;
+ 	union
+ 	{
+ 		/* page 0x20 omitted by now */
+ 		struct
+ 		{
+ 			u_char	reserved1;
+ 			u_char	mode;
+ #define CDD522_RAW_MODE		0x10	/* raw mode enabled */
+ #define CDD522_MIXED_MODE	0x08	/* mixed mode data enabled */
+ #define CDD522_AUDIO_MODE	0x04	/* audio mode data enabled */
+ #define CDD522_MODE_1		0x01	/* mode 1 blocks are enabled */
+ #define CDD522_MODE_2		0x02	/* mode 2 blocks are enabled */
+ 			u_char	track_number;
+ 			u_char	isrc_i1; /* country code, ASCII */
+ 			u_char	isrc_i2;
+ 			u_char	isrc_i3; /* owner code, ASCII */
+ 			u_char	isrc_i4;
+ 			u_char	isrc_i5;
+ 			u_char	isrc_i6_7; /* country code, BCD */
+ 			u_char	isrc_i8_9; /* serial number, BCD */
+ 			u_char	isrc_i10_11;
+ 			u_char	isrc_i12_0;
+ 			u_char	reserved2[2];
+ 		}
+ 		page_0x21;
+ 		/* mode page 0x22 omitted by now */
+ 		struct
+ 		{
+ 			u_char	speed_select;
+ #define CDD522_SPEED_AUDIO	0x01
+ #define CDD522_SPEED_DOUBLE	0x02
+ 			u_char	dummy_write;
+ #define CDD522_DUMMY_WRITE	0x01
+ 			u_char	reserved[4];
+ 		}
+ 		page_0x23;
+ 		/* pages 0x24 and 0x25 omitted by now */
+ 	}
+ 	pages;
+ };
+ 
+ 
+ static errval
+ cdd522_prepare_disk(struct scsi_link *sc_link, int dummy, int speed)
+ {
+ 	struct scsi_mode_select scsi_cmd;
+ 	struct {
+ 		struct scsi_mode_header header;
+ 		struct cdd_522_pages page;
+ 	} dat;
+ 	u_int32_t pagelen, dat_len;
+ 
+ 	pagelen = sizeof(dat.page.pages.page_0x23) + PAGE_HEADERLEN;
+ 	dat_len = sizeof(struct scsi_mode_header) + pagelen;
+ 
+ 	SC_DEBUG(sc_link, SDEV_DB2, ("cdd522_prepare_disk"));
+ 
+ 	if (speed != CDD522_SPEED_AUDIO && speed != CDD522_SPEED_DOUBLE)
+ 		return EINVAL;
+ 
+ 	/*
+ 	 * Set up a mode page 0x23
+ 	 */
+ 	bzero(&dat, sizeof(dat));
+ 	bzero(&scsi_cmd, sizeof(scsi_cmd));
+ 	scsi_cmd.op_code = MODE_SELECT;
+ 	scsi_cmd.byte2 |= SMS_PF;
+ 	scsi_cmd.length = dat_len;
+ 	/* dat.header.dev_spec = host application code; (see spec) */
+ 	dat.page.page_code = CDD522_PAGE_CODE_23;
+ 	dat.page.param_len = sizeof(dat.page.pages.page_0x23);
+ 	dat.page.pages.page_0x23.speed_select = speed;
+ 	dat.page.pages.page_0x23.dummy_write = dummy? CDD522_DUMMY_WRITE: 0;
+ 	/*
+ 	 * Fire it off.
+ 	 */
+ 	return scsi_scsi_cmd(sc_link,
+ 			     (struct scsi_generic *) &scsi_cmd,
+ 			     sizeof(scsi_cmd),
+ 			     (u_char *) &dat,
+ 			     dat_len,
+ 			     /*WORM_RETRIES*/ 4,
+ 			     5000,
+ 			     NULL,
+ 			     SCSI_DATA_OUT);
+ }
+ 
+ 
+ static errval
+ cdd522_prepare_track(struct scsi_link *sc_link, int audio, int preemp)
+ {
+ 	struct scsi_mode_select scsi_cmd;
+ 	struct {
+ 		struct scsi_mode_header header;
+ 		struct blk_desc blk_desc;
+ 		struct cdd_522_pages page;
+ 	} dat;
+ 	u_int32_t pagelen, dat_len, blk_len;
+ 	errval cmd_1_val;
+ 
+ 	pagelen = sizeof(dat.page.pages.page_0x21) + PAGE_HEADERLEN;
+ 	dat_len = sizeof(struct scsi_mode_header)
+ 		+ sizeof(struct blk_desc)
+ 		+ pagelen;
+ 
+ 	SC_DEBUG(sc_link, SDEV_DB2, ("cdd522_prepare_track"));
+ 
+ 	if (!audio && preemp)
+ 		return EINVAL;
+ 
+ 	/*
+ 	 * By now, make a simple decision about the block length to be
+ 	 * used.  It's just only Red Book (Audio) == 2352 bytes, or
+ 	 * Yellow Book (CD-ROM) Mode 1 == 2048 bytes.
+ 	 */
+ 	blk_len = audio? 2352: 2048;
+ 
+ 	/*
+ 	 * It turns out that the Yuden needs a WRITE_TRACK command.
+ 	 * It is simplest to send the original page 21 mode select
+ 	 * command, then to follow it with an unadorned WRITE_TRACK.
+ 	 */
+ 	bzero(&dat, sizeof(dat));
+ 	bzero(&scsi_cmd, sizeof(scsi_cmd));
+ 	scsi_cmd.op_code = MODE_SELECT;
+ 	scsi_cmd.byte2 |= SMS_PF;
+ 	scsi_cmd.length = dat_len;
+ 	dat.header.blk_desc_len = sizeof(struct blk_desc);
+ 	/* dat.header.dev_spec = host application code; (see spec) */
+ 	scsi_uto3b(blk_len, dat.blk_desc.blklen);
+ 	dat.page.page_code = CDD522_PAGE_CODE_21;
+ 	dat.page.param_len = sizeof(dat.page.pages.page_0x21);
+ 	dat.page.pages.page_0x21.mode =
+ 		(audio? CDD522_AUDIO_MODE: CDD522_MODE_1) +
+ 		(preemp? CDD522_MODE_1: 0);
+ 	/* dat.page.pages.page_0x21.track_number = 0; (current track) */
+ 	
+ 	/*
+ 	 * Send the mode select.
+ 	 */
+ 	cmd_1_val = scsi_scsi_cmd(sc_link,
+ 			     (struct scsi_generic *) &scsi_cmd,
+ 			     sizeof(scsi_cmd),
+ 			     (u_char *) &dat,
+ 			     dat_len,
+ 			     /*WORM_RETRIES*/ 4,
+ 			     5000,
+ 			     NULL,
+ 			     SCSI_DATA_OUT);
+ 
+ 	/*
+ 	 * Abort now if error.
+ 	 */
+ 
+ 	if (cmd_1_val)
+ 	{
+ 		return cmd_1_val;
+ 	}
+ 
+ 	/*
+ 	 * Next: an explicit WRITE_TRACK command - CDD522 Spec: `The WRITE
+ 	 * command is available only when the limited command set (after
+ 	 * a WRITE_TRACK command) is available'.  I.e. it's insufficient
+ 	 * for us to rely on the mode select command.  It appears that
+ 	 * WRITE_TRACK triggers my Yuden to start doing a laser power
+ 	 * calibration - which can take 10-20 secs - before it will accept
+ 	 * any data.  Hence the 60 second timeout.
+ 	 *
+ 	 * NB: This 60s timeout probably obviates the need for the 100 second
+ 	 * timeout in the strategy routine (but only when using this burner) -
+ 	 * that timeout could instead be set to a small multiple of the expected
+ 	 * time to transfer the given data at the given recording speed (or a
+ 	 * buffer full of data - 2M on my CD cutter - if it is larger).
+ 	 * Not that it matters...
+ 	 */
+ 	{
+ 	struct scsi_write_track cmd2;
+ 	
+ 	SC_DEBUG(sc_link, SDEV_DB2, ("cdd522_prepare_track (WRITE_TRACK)"));
+ 
+ 	bzero(&cmd2, sizeof(cmd2));
+ 	cmd2.op_code = WRITE_TRACK;
+ 	cmd2.mode =
+ 		(audio? WORM_TRACK_MODE_AUDIO: WORM_TRACK_MODE_MODE1) +
+ 		(preemp? WORM_TRACK_MODE_MODE1: 0);
+ 	return scsi_scsi_cmd(sc_link,
+ 			     (struct scsi_generic *) &cmd2,
+ 			     sizeof(cmd2),
+ 			     0,	/* no data transfer */
+ 			     0, /* no retries (it'd be bad form) */
+ 			     1,
+ 			     60000,
+ 			     NULL,
+ 			     0);
+ 	}
+ }
+ 
+ 
+ static errval
+ cdd522_finalize_track(struct scsi_link *sc_link)
+ {
+ 	struct scsi_synchronize_cache cmd;
+ 	
+ 	SC_DEBUG(sc_link, SDEV_DB2, ("cdd522_finalize_track"));
+ 
+ 	/*
+ 	 * Only a "synchronize cache" is needed.
+ 	 * NB: the Yuden gets confused if the
+ 	 * spindown (stop unit) is issued before the cache flush.
+ 	 */
+ 	bzero(&cmd, sizeof(cmd));
+ 	cmd.op_code = SYNCHRONIZE_CACHE;
+ 	return scsi_scsi_cmd(sc_link,
+ 			     (struct scsi_generic *) &cmd,
+ 			     sizeof(cmd),
+ 			     0,	/* no data transfer */
+ 			     0,
+ 			     1,
+ 			     120000, /* XXX: Upped out of caution */
+ 			     NULL,
+ 			     0);
+ }
+ 
+ 
+ static errval
+ cdd522_finalize_disk(struct scsi_link *sc_link, int toc_type, int onp)
+ {
+ 	struct scsi_fixation cmd;
+ 
+ 	SC_DEBUG(sc_link, SDEV_DB2, ("cdd522_finalize_disk"));
+ 
+ 	if (toc_type < 0 || toc_type > WORM_TOC_TYPE_CDI)
+ 		return EINVAL;
+ 
+ 	/*
+ 	 * Fixate this session.  Mark the next one as opened if onp
+ 	 * is true.  Otherwise, the disk will be finalized once and
+ 	 * for all.  ONP stands for "open next program area".
+ 	 *
+ 	 * XXX: If we're planning on multiple sessions, we need to fix the
+ 	 * block writes to go to the correct logical address on the CD (it
+ 	 * only starts at 0 for the first track).  IE, start off with
+ 	 * a FIRST_WRITEABLE_ADDR query (or force the writes to specify
+ 	 * addresses of 0).
+ 	 */
+ 	
+ 	bzero(&cmd, sizeof(cmd));
+ 	cmd.op_code = FIXATION;
+ 	cmd.action = (onp? WORM_FIXATION_ONP: 0) + toc_type;
+ 	return scsi_scsi_cmd(sc_link,
+ 			     (struct scsi_generic *) &cmd,
+ 			     sizeof(cmd),
+ 			     0,	/* no data transfer */
+ 			     0,
+ 			     1,
+ 			     20*60*1000, /* takes a huge amount of time */
+ 			     NULL,
+ 			     0);
+ }
+ 
+ /*
+  * End Philips CDD522/T.Yuden EW-50 section.
   */
>Release-Note:
>Audit-Trail:

From: j@uriah.heep.sax.de (J Wunsch)
To: mmcg@mjolnir.cs.monash.edu.au
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: kern/3909: Patches - new worm drivers for CDrom burners: Philips CDD522 and T.Yuden EW-50
Date: Fri, 20 Jun 1997 07:09:31 +0200

 As Mike McGaughey wrote:
 
 > Here is a modification to the 2.2.2-RELEASE worm.c which implements
 > support for the Philips CDD 522 and T.Yuden EW-50 (very cheap in
 > Australia).
 
 Thanks!
 
 > NOTE: I have made a slight change to the handling of other CDrom
 > cutters.  In particular, the spindown/medium unload commands are
 > now sent *after* the cache flush when finalizing a track.
 
 You ought to have a look at the current driver...  Jean-Marc has
 already fixed this (and improved many other things).
 
 > I have burned a bunch of data CDs using this; I haven't tried
 > audios, multi-track, or multi-session disks (the multisession
 > support looks broken anyway, due to a block addressing issue).
 
 Multisession works fine for me (one of my test CDs bailed out with
 `volume overflow' at 29 sessions :); the block addressing problem can
 be reduced to read operations, but with the current overall kernel
 struct (namely the b_blkno handling), it cannot be fixed at all.  For
 writing, you should always set the block number to 0.
 
 > + 	{
 > + 		"PHILIPS", "CDD522",
 > + 		cdd522_prepare_disk, cdd522_prepare_track,
 > + 		cdd522_finalize_track, cdd522_finalize_disk
 > + 	},
 > + 	{
 > + 	/* (aic0:4:0): "T.YUDEN CD-WO EW-50 2.16" type 4 removable SCSI 2 */
 > + 		"T.YUDEN", "EW-50",
 > + 		cdd522_prepare_disk, cdd522_prepare_track,
 > + 		cdd522_finalize_track, cdd522_finalize_disk
 > + 	},
 
 These things have been moved out to scsiconfig.c.  I assume you had to
 modify scsiconfig.c anyway, in order to make the device known as a
 CD-R, did you?  At any rate, please tell us where the `CD-WO' string
 belongs to in the inquiry data.  I.e., is the required entry for
 scsiconfig { "T.YUDEN CD-WO", "EW-50", ...} or { "T.YUDEN", "CD-WO
 EW-50", ... }?
 
 > + /*
 > +  * Philips CDD522/Taiyo Yuden EW-50 section.
 > +  *
 > +  * Ack: I am very grateful to Philips, who supplied me with a SCSI manual
 > +  * for their unit.  Taiyo Yuden considers their manual proprietry.
 > +  *
 > +  * This section was written using the CDD522 SCSI manual, but has only
 > +  * been tested on my T.YUDEN EW-50 (it's a long story).
 > +  */
 
 What's the difference to the existing HP4020/HP6020/CDD2000/CDD2660
 option?  From a cursory look, i didn't see any.  There's not much use
 to duplicate code.
 
 I suspect you could have been successfully using the old code, too, by
 pretending it to be an HP 4020i?
 
 -- 
 cheers, J"org
 
 joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE
 Never trust an operating system you don't have sources for. ;-)
Responsible-Changed-From-To: freebsd-bugs->joerg 
Responsible-Changed-By: jkh 
Responsible-Changed-When: Thu Jun 19 23:34:20 PDT 1997 
Responsible-Changed-Why:  
The worm driver is Joerg's baby! 

From: mmcg@cs.monash.edu.au
To: freebsd-gnats-submit@freebsd.org, j@uriah.heep.sax.de
Cc: mmcg@heraclitus.cs.monash.edu.au
Subject: Re:kern/3909:Apatchsupportingsomenewwormdrivers
Date: Mon, 23 Jun 1997 13:55:12 +1000 (EST)

 >          Mike McGaughey Mike McGaughey <mmcg@mjolnir.cs.monash.edu.au>
 
 An apology: Mjolnir is firewalled, and I forgot to edit my sendmail.cf.
 Use mmcg@cs.monash.edu.au (or heraclitus.cs.monash.edu.au).
 
 
 >From: j@uriah.heep.sax.de (J Wunsch)
 >
 > You ought to have a look at the current driver...  Jean-Marc has
 > already fixed this (and improved many other things).
 
 I'd better figure out how to get hold of it easily then :)
 
 > &gt; support looks broken anyway, due to a block addressing issue).
 >
 > Multisession works fine for me (one of my test CDs bailed out with [...]
 > For writing, you should always set the block number to 0.
 
 Hmm.  My SCSI manual claims that blocks are always relative to
 logical block 0, which is at 0:02:00 (I presumed this included
 when writing).  Do I want to ruin my perfect record to test
 this? (29 CDs, 0 coasters :)
 
 > &gt; +                 "T.YUDEN", "EW-50",
 >
 > These things have been moved out to scsiconfig.c.  I assume you had to
 > modify scsiconfig.c anyway, in order to make the device known as a
 > CD-R, did you?
 
 No, it's configured as a `worm' type scsi device (device type 4?),
 and the kernel happily attaches it to worm0.  I just use wormcontrol
 to set it up.
 
 > At any rate, please tell us where the `CD-WO' string
 > belongs to in the inquiry data.  I.e., is the required entry for
 > scsiconfig { "T.YUDEN CD-WO", "EW-50", ...} or { "T.YUDEN", "CD-WO
 > EW-50", ... }?
 
 I'm not sure about scsiconf.c (I'll look into it some time), but:
 
 # scsi -f /dev/worm0 -c "12 0 0 0 64 0" -i 64 - > /dev/null
 
 SCIOCCOMMAND ioctl: Command accepted.
  host adapter status 2
 Command out (6 of 6):
 12 00 00 00 64 00 
 
 Data in (64 of 64):
 04 80 02 02 27 00 00 18 54 2e 59 55 44 45 4e 20  # ....'...T.YUDEN 
 43 44 2d 57 4f 20 45 57 2d 35 30 20 20 20 20 20  # CD-WO EW-50     
 32 2e 31 36 31 38 2f 31 30 2f 39 36 00 00 00 00  # 2.1618/10/96....
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  # ................
 
 No sense sent.
 
 > What's the difference to the existing HP4020/HP6020/CDD2000/CDD2660
 > option?  From a cursory look, i didn't see any.  There's not much use
 > to duplicate code.
 
 You're quite right - the only quirk function that changed was the
 prepare_track routine.  I added a `Write Track' command, which
 causes laser calibration to commence on the unit.  I also modified
 the general (non drive-specific) finalize_track routine to do the
 flush to disk before issuing the spindown; doing it in the other
 order confused my drive.
 
 > I suspect you could have been successfully using the old code, too, by
 > pretending it to be an HP 4020i?
 
 No, this failed when finalizing the track.  Although, now that the
 finalize track handling is modified, it's quite likely that the HP
 quirk functions will work on my drive (I don't know whether the
 WRITE_TRACK command is actually necessary for a successful burn,
 although the manual seems to suggest that it is).  Still, I like
 to see it do a power calibration before it starts writing :)
 
 Cheers,
 
     Mike.
State-Changed-From-To: open->closed 
State-Changed-By: joerg 
State-Changed-When: Fri Nov 5 08:51:45 MET 1999 
State-Changed-Why:  
worm(4) is no longer supported under CAM.  If it will ever be again, it 
will certainly be a total rewrite, and layered on top of cd(4). 
>Unformatted:
