From: Peter Osterlund <petero2@telia.com>

This patch implements packet writing for DVD-RW and DVD+RW discs, ie it makes
it possible to use DVD+/-RW discs as writable block devices.  DVD-RW discs
must be in restricted overwrite mode.  The setup procedure is the same as for
CD-RW discs:

     # pktsetup /dev/pktcdvd0 /dev/hdc
     # mount /dev/pktcdvd0 /cdrom -t udf -o rw,noatime

The patch works by asking the drive for the current mmc3 profile, and if the
drive reports DVD+RW (0x1a) or DVD-RW (0x13) media, some steps in the
initialization code that are specific to CD-RW discs are skipped.

Signed-off-by: Peter Osterlund <petero2@telia.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/block/Kconfig   |    3 ++-
 25-akpm/drivers/block/pktcdvd.c |   37 ++++++++++++++++++++++++++++++++++---
 25-akpm/include/linux/pktcdvd.h |    1 +
 3 files changed, 37 insertions(+), 4 deletions(-)

diff -puN drivers/block/Kconfig~dvd-rw-packet-writing-update drivers/block/Kconfig
--- 25/drivers/block/Kconfig~dvd-rw-packet-writing-update	2004-07-31 22:48:26.337988808 -0700
+++ 25-akpm/drivers/block/Kconfig	2004-07-31 22:48:26.346987440 -0700
@@ -348,7 +348,8 @@ config CDROM_PKTCDVD
 	  compliant ATAPI or SCSI drive, which is just about any newer CD
 	  writer.
 
-	  Currently only writing to CD-RW discs is possible.
+	  Currently only writing to CD-RW, DVD-RW and DVD+RW discs is possible.
+	  DVD-RW disks must be in restricted overwrite mode.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called pktcdvd.
diff -puN drivers/block/pktcdvd.c~dvd-rw-packet-writing-update drivers/block/pktcdvd.c
--- 25/drivers/block/pktcdvd.c~dvd-rw-packet-writing-update	2004-07-31 22:48:26.340988352 -0700
+++ 25-akpm/drivers/block/pktcdvd.c	2004-07-31 22:48:26.347987288 -0700
@@ -1414,6 +1414,10 @@ static int pkt_set_write_settings(struct
 	char buffer[128];
 	int ret, size;
 
+	/* doesn't apply to DVD+RW */
+	if (pd->mmc3_profile == 0x1a)
+		return 0;
+
 	memset(buffer, 0, sizeof(buffer));
 	init_cdrom_command(&cgc, buffer, sizeof(*wp), CGC_DATA_READ);
 	cgc.sense = &sense;
@@ -1519,6 +1523,18 @@ static int pkt_good_track(track_informat
  */
 static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
 {
+	switch (pd->mmc3_profile) {
+		case 0x0a: /* CD-RW */
+		case 0xffff: /* MMC3 not supported */
+			break;
+		case 0x1a: /* DVD+RW */
+		case 0x13: /* DVD-RW */
+			return 0;
+		default:
+			printk("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
+			return 1;
+	}
+
 	/*
 	 * for disc type 0xff we should probably reserve a new track.
 	 * but i'm not sure, should we leave this to user apps? probably.
@@ -1548,10 +1564,18 @@ static int pkt_good_disc(struct pktcdvd_
 
 static int pkt_probe_settings(struct pktcdvd_device *pd)
 {
+	struct packet_command cgc;
+	unsigned char buf[12];
 	disc_information di;
 	track_information ti;
 	int ret, track;
 
+	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+	cgc.cmd[8] = 8;
+	ret = pkt_generic_packet(pd, &cgc);
+	pd->mmc3_profile = ret ? 0xffff : buf[6] << 8 | buf[7];
+
 	memset(&di, 0, sizeof(disc_information));
 	memset(&ti, 0, sizeof(track_information));
 
@@ -1849,9 +1873,16 @@ static int pkt_open_write(struct pktcdvd
 
 	if ((ret = pkt_get_max_speed(pd, &write_speed)))
 		write_speed = 16;
-	if ((ret = pkt_media_speed(pd, &media_write_speed)))
-		media_write_speed = 16;
-	write_speed = min(write_speed, media_write_speed);
+	switch (pd->mmc3_profile) {
+		case 0x13: /* DVD-RW */
+		case 0x1a: /* DVD+RW */
+			break;
+		default:
+			if ((ret = pkt_media_speed(pd, &media_write_speed)))
+				media_write_speed = 16;
+			write_speed = min(write_speed, media_write_speed);
+			break;
+	}
 	read_speed = write_speed;
 
 	if ((ret = pkt_set_speed(pd, write_speed, read_speed))) {
diff -puN include/linux/pktcdvd.h~dvd-rw-packet-writing-update include/linux/pktcdvd.h
--- 25/include/linux/pktcdvd.h~dvd-rw-packet-writing-update	2004-07-31 22:48:26.342988048 -0700
+++ 25-akpm/include/linux/pktcdvd.h	2004-07-31 22:48:26.348987136 -0700
@@ -242,6 +242,7 @@ struct pktcdvd_device
 	__u8			mode_offset;	/* 0 / 8 */
 	__u8			type;
 	unsigned long		flags;
+	__u16			mmc3_profile;
 	__u32			nwa;		/* next writable address */
 	__u32			lra;		/* last recorded address */
 	struct packet_cdrw	cdrw;
_