public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Allow random write for PDT 5 profile 2 Removable Disk
@ 2004-02-11 22:10 John McKell
  0 siblings, 0 replies; 2+ messages in thread
From: John McKell @ 2004-02-11 22:10 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-scsi

Jens,

I see linux-2.6.2 extends the list of writable PDT x05 DVD/CD devices
to include MRW, not just DVD-RAM and MO.

With that change in place, this small further patch allows write
through to PDT 0x05 DVD/CD for profile x0002 Removable Disk:

a) if feature x0020 "Random Writable" present (no matter if current or
not) at plug-in time, and...

b) if feature x0024 "Hardware Defect Management" present (no matter if
current or not) at plug-in time, and...

c) if both features "current" at /dev/* open time (e.g., mount time),
and ...

d) the device in question is not any of MRW, MRW_W, DVD_RAM, CD_R,
CD_RW, DVD, DVD_R

Since 1999 MMC-2, MMC says these tests in combination say this device
writes at random like DVD-RAM: no load balancing (aka wear leveling)
required and blocks of the size the x0020 feature reports (64 KiB if
like CD, 32 KiB if like DVD).

This composite version of this patch includes the already posted
patch:

Subject:[PATCH] DVD-R capability flag set incorrectly, /proc
                formatting fix
http://marc.theaimsgroup.com/?l=linux-scsi&m=107637086904512&w=2

Please let me know if you'd rather have an incremental patch.

---John McKell


--- linux-2.6.2/include/linux/cdrom.h	2004-02-03 20:43:06.000000000 -0700
+++ linux/include/linux/cdrom.h	2004-02-07 15:21:53.000000000 -0700
@@ -721,7 +721,9 @@ struct request_sense {
 /*
  * feature profile
  */
-#define CDF_MRW		0x28
+#define CDF_RWRT	0x0020
+#define CDF_HWDM	0x0024
+#define CDF_MRW		0x0028
 
 /*
  * media status bits
@@ -770,6 +772,34 @@ struct mrw_feature_desc {
 	__u8 reserved5;
 };
 
+/* cf. mmc4r02g.pdf 5.3.10 Random Writable Feature (0020h) pg 197 of 635 */
+struct rwrt_feature_desc {	
+	__u16 feature_code;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved1		: 2;
+	__u8 feature_version	: 4;
+	__u8 persistent		: 1;
+	__u8 curr		: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 curr		: 1;
+	__u8 persistent		: 1;
+	__u8 feature_version	: 4;
+	__u8 reserved1		: 2;
+#endif
+	__u8 add_len;
+	__u32 last_lba;
+	__u32 block_size;
+	__u16 blocking;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2		: 7;
+	__u8 page_present	: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 page_present	: 1;
+	__u8 reserved2		: 7;
+#endif
+	__u8 reserved3;
+};
+
 typedef struct {
 	__u16 disc_information_length;
 #if defined(__BIG_ENDIAN_BITFIELD)
@@ -1129,6 +1159,7 @@ struct media_event_desc {
 
 extern int cdrom_get_media_event(struct cdrom_device_info *cdi, struct media_event_desc *med);
 extern int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write);
+extern int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write);
 
 #endif  /* End of kernel only stuff */ 
 
--- linux-2.6.2/drivers/ide/ide-cd.c	2004-02-03 20:43:44.000000000 -0700
+++ linux/drivers/ide/ide-cd.c	2004-02-09 16:08:13.000000000 -0700
@@ -2911,6 +2911,8 @@ static int ide_cdrom_register (ide_drive
 		devinfo->mask |= CDC_MRW;
 	if (!CDROM_CONFIG_FLAGS(drive)->mrw_w)
 		devinfo->mask |= CDC_MRW_W;
+	if (!CDROM_CONFIG_FLAGS(drive)->ram)
+		devinfo->mask |= CDC_RAM;
 
 	return register_cdrom(devinfo);
 }
@@ -2946,7 +2948,7 @@ int ide_cdrom_probe_capabilities (ide_dr
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
 	struct atapi_capabilities_page cap;
-	int nslots = 1, mrw_write = 0;
+	int nslots = 1, mrw_write = 0, ram_write = 0;
 
 	if (drive->media == ide_optical) {
 		CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
@@ -2982,7 +2984,11 @@ int ide_cdrom_probe_capabilities (ide_dr
 			CDROM_CONFIG_FLAGS(drive)->ram = 1;
 		}
 	}
-
+	if (!cdrom_is_random_writable(cdi, &ram_write)) {
+		if (ram_write) {
+			CDROM_CONFIG_FLAGS(drive)->ram = 1;
+		}
+	}
 	if (cap.lock == 0)
 		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
 	if (cap.eject)
--- linux-2.6.2/drivers/scsi/sr.c	2004-02-03 20:43:19.000000000 -0700
+++ linux/drivers/scsi/sr.c	2004-02-10 16:39:23.000000000 -0700
@@ -693,7 +693,7 @@ Enomem:
 static void get_capabilities(struct scsi_cd *cd)
 {
 	unsigned char *buffer;
-	int rc, n, mrw_write = 0, mrw = 1;
+	int rc, n, mrw_write = 0, mrw = 1,ram_write=0;
 	struct scsi_mode_data data;
 	struct scsi_request *SRpnt;
 	unsigned char cmd[MAX_COMMAND_SIZE];
@@ -775,6 +775,12 @@ static void get_capabilities(struct scsi
 	if (!mrw_write)
 		cd->cdi.mask |= CDC_MRW_W;
 
+	if (cdrom_is_random_writable(&cd->cdi, &ram_write)) {
+		cd->cdi.mask |= CDC_RAM;
+	}
+	if (!ram_write)
+		cd->cdi.mask |= CDC_RAM;
+
 	n = data.header_length + data.block_descriptor_length;
 	cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
 	cd->readcd_known = 1;
@@ -795,10 +801,9 @@ static void get_capabilities(struct scsi
 	if ((buffer[n + 2] & 0x8) == 0)
 		/* not a DVD drive */
 		cd->cdi.mask |= CDC_DVD;
-	if ((buffer[n + 3] & 0x20) == 0) {
+	if ((buffer[n + 3] & 0x20) == 0)
 		/* can't write DVD-RAM media */
 		cd->cdi.mask |= CDC_DVD_RAM;
-	} else
 	if ((buffer[n + 3] & 0x10) == 0)
 		/* can't write DVD-R media */
 		cd->cdi.mask |= CDC_DVD_R;
@@ -825,7 +830,8 @@ static void get_capabilities(struct scsi
 	/*
 	 * if DVD-RAM of MRW-W, we are randomly writeable
 	 */
-	if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W)) != (CDC_DVD_RAM | CDC_MRW_W))
+	if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM)) != 
+	    (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM))
 		cd->device->writeable = 1;
 
 	scsi_release_request(SRpnt);
--- linux-2.6.2/drivers/cdrom/cdrom.c	2004-02-05 14:30:46.000000000 -0700
+++ linux/drivers/cdrom/cdrom.c	2004-02-11 11:14:23.995187637 -0700
@@ -641,6 +641,80 @@ static int cdrom_mrw_set_lba_space(struc
 	return 0;
 }
 
+int cdrom_get_random_writable(struct cdrom_device_info *cdi, 
+			      struct rwrt_feature_desc *rfd)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[24];
+	struct feature_header *fh;
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;	/* often 0x46 */
+	cgc.cmd[3] = CDF_RWRT;			/* often 0x0020 */
+	cgc.cmd[8] = sizeof(buffer);		/* often 0x18 */
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc))) 
+		return ret;
+
+	fh = (struct feature_header *)&buffer[0];
+	if (be32_to_cpu(fh->data_len) >= (sizeof(struct feature_header)+
+					  sizeof(struct rwrt_feature_desc))) {
+		memcpy(rfd, &buffer[sizeof(struct feature_header)], 
+		       sizeof (*rfd));
+	} else {
+		memset(rfd, 0, sizeof(*rfd));
+	}
+	return 0;
+}
+
+int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[16];
+	struct feature_header *fh;
+	__u16 *feature_code;
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;	/* often 0x46 */
+	cgc.cmd[3] = CDF_HWDM;			/* often 0x0024 */
+	cgc.cmd[8] = sizeof(buffer);		/* often 0x10 */
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc))) 
+		return ret;
+
+	fh = (struct feature_header *)&buffer[0];
+	ret = 1;
+	if (be32_to_cpu(fh->data_len) >= (sizeof(struct feature_header)+8)) {
+		feature_code = (__u16 *)&buffer[sizeof(struct feature_header)];
+		if (CDF_HWDM == be16_to_cpu(*feature_code)) 
+			ret = 0;
+	} 
+	return ret;
+}
+
+
+int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+	
+	*write = 0;
+
+	if ((ret = cdrom_get_random_writable(cdi, &rfd))) 
+		return ret;
+
+	if (CDF_RWRT == be16_to_cpu(rfd.feature_code)) 
+		*write = 1;
+
+	return 0;
+}
+
 static int cdrom_media_erasable(struct cdrom_device_info *cdi)
 {
 	disc_information di;
@@ -695,6 +769,24 @@ static int cdrom_mrw_open_write(struct c
 	return ret;
 }
 
+static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+
+	if ((ret = cdrom_has_defect_mgt(cdi))) {
+		return ret;
+	} else {
+		if ((ret = cdrom_get_random_writable(cdi, &rfd))) {
+			return ret;
+		} else if (CDF_RWRT == be16_to_cpu(rfd.feature_code)) {
+			ret = !rfd.curr;
+		}
+	}
+	cdinfo(CD_OPEN, "can open for random write\n");
+	return ret;
+}
+
 /*
  * returns 0 for ok to open write, non-0 to disallow
  */
@@ -706,6 +798,10 @@ static int cdrom_open_write(struct cdrom
 		ret = cdrom_mrw_open_write(cdi);
 	else if (CDROM_CAN(CDC_DVD_RAM))
 		ret = cdrom_dvdram_open_write(cdi);
+	else if (CDROM_CAN(CDC_RAM) && 
+		 !CDROM_CAN(CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_MRW)) {
+		ret = cdrom_ram_open_write(cdi);
+	}
 	/*
 	 * needs to really check whether media is writeable
 	 */
@@ -2644,6 +2740,7 @@ EXPORT_SYMBOL(cdrom_mode_sense);
 EXPORT_SYMBOL(init_cdrom_command);
 EXPORT_SYMBOL(cdrom_get_media_event);
 EXPORT_SYMBOL(cdrom_is_mrw);
+EXPORT_SYMBOL(cdrom_is_random_writable);
 
 #ifdef CONFIG_SYSCTL
 
@@ -2740,13 +2837,17 @@ int cdrom_sysctl_info(ctl_table *ctl, in
 	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
 	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
 
-	pos += sprintf(info+pos, "\nCan read MRW:");
+	pos += sprintf(info+pos, "\nCan read MRW:\t");
+	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
+
+	pos += sprintf(info+pos, "\nCan write MRW:\t");
 	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW) != 0);
+	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
 
-	pos += sprintf(info+pos, "\nCan write MRW:");
+	pos += sprintf(info+pos, "\nCan write RAM:\t");
 	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW_W) != 0);
+	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
 
 	strcpy(info+pos,"\n\n");
 		




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-02-12 11:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1076536919.3112.149.camel@lintest.iomegacorp.com>
2004-02-12 11:10 ` [PATCH] Allow random write for PDT 5 profile 2 Removable Disk Jens Axboe
2004-02-11 22:10 John McKell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox