diff -ruN linux-2.4.21.orig/drivers/s390/block/dasd.c linux-2.4.21/drivers/s390/block/dasd.c
--- linux-2.4.21.orig/drivers/s390/block/dasd.c	2003-07-21 23:46:01.000000000 -0500
+++ linux-2.4.21/drivers/s390/block/dasd.c	2003-07-23 03:06:06.000000000 -0500
@@ -577,15 +577,22 @@
                         if (strlen(buffer)) { 
                                 if (!strcmp(buffer,"ro")) { /* handle 'ro' feature */
                                         (*features) |= DASD_FEATURE_READONLY;
-                                        break;
                                 }
 
-                                MESSAGE (KERN_WARNING,
-                                         "unsupported feature: %s, "
-                                         "ignoring setting",
-                                         buffer);
+                                else if (!strcmp(buffer,"diag")) { /* handle 'diag' feature */
+                                        (*features) |= DASD_FEATURE_USEDIAG;
+                                }
+
+                                else {
+                                        MESSAGE (KERN_WARNING,
+                                                "unsupported feature: %s, "
+                                                 "ignoring setting",
+                                                 buffer);
+                                }
                         }
                 }
+                if (temp[i] == ')')
+                        i++;
         }
 
         *stra = temp+i;
@@ -995,7 +1002,6 @@
 dasd_features_from_devno (int devno)
 {
 	dasd_range_t *temp;
-	int devindex = 0;
 	unsigned long flags;
 	struct list_head *l;
 
@@ -1006,7 +1012,6 @@
 			spin_unlock_irqrestore (&range_lock, flags);
 			return temp->features;
 		}
-		devindex += temp->to - temp->from + 1;
 	}
 	spin_unlock_irqrestore (&range_lock, flags);
 	return -ENODEV;
@@ -1106,7 +1111,7 @@
  * checks the list of disciplines for the first one able to access the device
  */
 static inline dasd_discipline_t *
-dasd_find_disc (dasd_device_t * device, dasd_discipline_t *discipline)
+dasd_find_disc (dasd_device_t * device, dasd_discipline_t *discipline, int features)
 {
         dasd_discipline_t *t;
         struct list_head *l = discipline ? 
@@ -1114,8 +1119,9 @@
 
         do {
                 t = list_entry(l,dasd_discipline_t,list);
-
-                if ( ( t->id_check == NULL ||
+                if ( ( !( features & DASD_FEATURE_USEDIAG ) ||
+                       strncmp (t->name, "DIAG", 4) == 0 )  &&
+                     ( t->id_check == NULL ||
                        t->id_check (&device->devinfo) == 0 ) &&
                      ( t->check_characteristics == NULL ||
                        t->check_characteristics (device) == 0 ) )
@@ -3946,6 +3952,7 @@
         struct list_head *l;
         major_info_t *major_info, *tmp;
         int i;
+        int features;
         dasd_device_t *device = *dptr;
         devfs_handle_t dir;
         char buffer[5];
@@ -3993,8 +4000,11 @@
         if ( devno != device->devinfo.devno )
                 BUG();
 
+	features = dasd_features_from_devno(device->devinfo.devno);
+
         device->discipline = dasd_find_disc (device, 
-                                             discipline);
+                                             discipline,
+                                             features);
         if ( device->discipline == NULL ) {
                 rc = -ENODEV;
                 goto out;
@@ -4004,7 +4014,7 @@
         dir = devfs_mk_dir (dasd_devfs_handle, buffer, device);
         device->major_info->gendisk.de_arr[MINOR(device->kdev)
                                           >> DASD_PARTN_BITS] = dir;
-	if (dasd_features_from_devno(device->devinfo.devno)&DASD_FEATURE_READONLY) {
+	if (features&DASD_FEATURE_READONLY) {
 	        devfs_perm &= ~(S_IWUSR);
 	}
         device->devfs_entry = devfs_register (dir,"device",DEVFS_FL_DEFAULT,
@@ -4527,6 +4537,7 @@
 			dasd_device_t *device;
                         int devno = dasd_devno_from_devindex(index+i);
                         int features;
+                        char *featstr = "";
 
                         if ( devno == -ENODEV )
                                 continue;
@@ -4535,6 +4546,14 @@
                         if (features < DASD_FEATURE_DEFAULT)
                                 features = DASD_FEATURE_DEFAULT;
 
+                        if ( (features & DASD_FEATURE_READONLY) &&
+                             (features & DASD_FEATURE_USEDIAG) )
+                                featstr = "(ru}";
+                        else if (features & DASD_FEATURE_READONLY)
+                                featstr = "(ro)";
+                        else if (features & DASD_FEATURE_USEDIAG)
+                                featstr = "(ud)";
+                                
                         device = temp->dasd_device[i];
 			if (device) {
 
@@ -4547,8 +4566,7 @@
 						temp->gendisk.major,
 						i << DASD_PARTN_BITS,
 						device->name,
-                                                (features & DASD_FEATURE_READONLY) ? 
-                                                "(ro)" : " ");
+						featstr);
                                 
 				switch (device->level) {
 				case DASD_STATE_NEW:
@@ -4618,8 +4636,7 @@
 						temp->gendisk.major,
 						i << DASD_PARTN_BITS,
 						buffer,
-                                                (features & DASD_FEATURE_READONLY) ? 
-                                                "(ro)" : " ");
+						featstr);
                         }
                         if ( dasd_probeonly )
                             len += sprintf(info->data + len,"(probeonly)");
@@ -4686,7 +4703,10 @@
         /* remove blanks after device range */
 	for (; isspace(*str); str++);
 
-        if (range->from < 0 || range->to < 0) {
+        /* Negative numbers in str/from/to indicate errors */
+        if ((range->from < 0) || (range->to < 0) ||
+            (range->from > 65535) || (range->to > 65535) ||
+            (range->from > range->to)) {
                 MESSAGE (KERN_WARNING,
                          "/proc/dasd/devices: range parse error in '%s'", 
                          buffer);
@@ -4709,21 +4729,19 @@
         str = dasd_parse_range (buffer, 
                                 &range);
         
-        /* Negative numbers in str/from/to indicate errors */
-        if (IS_ERR (str) || (range.from < 0) || (range.to < 0)
-            || (range.from > 65535) || (range.to > 65535)) 
+        if (IS_ERR (str))
                 return;
 
-        if (strncmp (str, "on", 2) == 0) {
+        if (strcmp (str, "on") == 0) {
                 dasd_enable_ranges (&range, NULL, 0);
 
-        } else if (strncmp (str, "off", 3) == 0) {
+        } else if (strcmp (str, "off") == 0) {
                 dasd_disable_ranges (&range, NULL, 0, 1);
                 
         } else {
                 MESSAGE (KERN_WARNING,
                          "/proc/dasd/devices: "
-                         "only 'on' and 'off' are alowed in 'set' "
+                         "only 'on' and 'off' are allowed in 'set' "
                          "command ('%s'/'%s')",
                          buffer,
                          str);
@@ -4734,6 +4752,60 @@
 } /* end dasd_proc_set */
 
 /* 
+ * Set / Unset the given feature after validateion
+ */
+static void
+dasd_proc_feature (char *buffer, char *cmd, int feature)
+{
+	dasd_range_t *temp;
+	unsigned long flags;
+	struct list_head *l;
+	dasd_range_t range;
+        char *str;
+        int on;
+
+        str = dasd_parse_range (buffer, 
+                                &range);
+        
+        if (IS_ERR (str))
+                return;
+
+        if (strcmp (str, "on") == 0) {
+                on = 1;
+
+        } else if (strcmp (str, "off") == 0) {
+                on = 0;
+                
+        } else {
+                MESSAGE (KERN_WARNING,
+                         "/proc/dasd/devices: "
+                         "only 'on' and 'off' are allowed in '%s' "
+                         "command ('%s')",
+                         cmd,
+                         str);
+                return;
+        }
+
+	spin_lock_irqsave (&range_lock, flags);
+        list_for_each (l, &dasd_range_head.list) {
+                temp = list_entry (l, dasd_range_t, list);
+                if ( (range.from >= temp->from && range.from <= temp->to) ||
+                     (range.to >= temp->from && range.to <= temp->to) ||
+                     (temp->from >= range.from && temp->from <= range.to) ||
+                     (temp->to >= range.from && temp->to <= range.to) ) {
+                        if (on)
+                                temp->features |= feature;
+                        else
+                                temp->features &= ~feature;
+                }
+        }
+	spin_unlock_irqrestore (&range_lock, flags);
+
+        return;
+
+} /* end dasd_proc_feature */
+
+/* 
  * Add the given devices
  */
 static void
@@ -4745,9 +4817,7 @@
         str = dasd_parse_range (buffer, 
                                 &range);
         
-        /* Negative numbers in str/from/to indicate errors */
-        if (IS_ERR (str) || (range.from < 0) || (range.to < 0)
-            || (range.from > 65535) || (range.to > 65535))
+        if (IS_ERR (str))
                 return;
 
         dasd_add_range (range.from, range.to, range.features);
@@ -4926,6 +4996,14 @@
                 /* handle 'brk <devno> <discipline>' */
                 dasd_proc_brk (buffer);
 
+	} else if (strncmp (buffer, "readonly ", 9) == 0) {
+                /* handle 'readonly <devno> on/off' */
+                dasd_proc_feature (&buffer[5], "readonly", DASD_FEATURE_READONLY);
+
+	} else if (strncmp (buffer, "usediag ", 8) == 0) {
+                /* handle 'usediag <devno> on/off' */
+                dasd_proc_feature (&buffer[4], "usediag", DASD_FEATURE_USEDIAG);
+
         } else {
 		MESSAGE (KERN_WARNING, "%s",
                          "/proc/dasd/devices: only 'set' ,'add' and "
diff -ruN linux-2.4.21.orig/include/asm-s390/dasd.h linux-2.4.21/include/asm-s390/dasd.h
--- linux-2.4.21.orig/include/asm-s390/dasd.h	2003-07-21 23:45:46.000000000 -0500
+++ linux-2.4.21/include/asm-s390/dasd.h	2003-07-23 03:00:41.000000000 -0500
@@ -79,6 +79,7 @@
  */
 #define DASD_FEATURE_DEFAULT  0
 #define DASD_FEATURE_READONLY 1
+#define DASD_FEATURE_USEDIAG  2
 
 #define DASD_PARTN_BITS 2
 
diff -ruN linux-2.4.21.orig/include/asm-s390x/dasd.h linux-2.4.21/include/asm-s390x/dasd.h
--- linux-2.4.21.orig/include/asm-s390x/dasd.h	2003-07-21 23:45:46.000000000 -0500
+++ linux-2.4.21/include/asm-s390x/dasd.h	2003-07-23 03:00:41.000000000 -0500
@@ -79,6 +79,7 @@
  */
 #define DASD_FEATURE_DEFAULT  0
 #define DASD_FEATURE_READONLY 1
+#define DASD_FEATURE_USEDIAG  2
 
 #define DASD_PARTN_BITS 2
 
