patch-2.4.8 linux/drivers/s390/block/dasd_eckd.c

Next file: linux/drivers/s390/block/dasd_eckd.h
Previous file: linux/drivers/s390/block/dasd_diag.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.7/linux/drivers/s390/block/dasd_eckd.c linux/drivers/s390/block/dasd_eckd.c
@@ -1,6 +1,7 @@
 /* 
  * File...........: linux/drivers/s390/block/dasd_eckd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+                    Carsten Otte <Cotte@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
 
@@ -22,27 +23,25 @@
 #include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
-#include <asm/debug.h>
-
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/hdreg.h>	/* HDIO_GETGEO                      */
 #include <linux/blk.h>
+
+#include <asm/debug.h>
 #include <asm/ccwcache.h>
 #include <asm/idals.h>
-#include <asm/dasd.h>
-
 #include <asm/ebcdic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/s390dyn.h>
 
+#include "dasd_int.h"
 #include "dasd_eckd.h"
 
 #ifdef PRINTK_HEADER
 #undef PRINTK_HEADER
 #endif				/* PRINTK_HEADER */
-#define PRINTK_HEADER DASD_NAME"(eckd): "
-#undef DASD_CDL // Support compatible disk layout
+#define PRINTK_HEADER DASD_NAME"(eckd):"
 #undef CDL_PRINTK
 
 #define ECKD_C0(i) (i->home_bytes)
@@ -62,55 +61,39 @@
 dasd_eckd_private_t {
 	dasd_eckd_characteristics_t rdc_data;
 	dasd_eckd_confdata_t conf_data;
-#ifdef DASD_CDL
-        eckd_count_t count_area[5];
-#else
-	eckd_count_t count_area;
-#endif
-	ccw_req_t *init_cqr;
-#ifdef DASD_CDL
-        int uses_cdl; 
-#endif
+	eckd_count_t count_area[5];
+	int uses_cdl;
 } dasd_eckd_private_t;
 
 #ifdef CONFIG_DASD_DYNAMIC
 static
-devreg_t dasd_eckd_known_devices[] =
-{
-	{
-		ci:
-		{hc:
-		 {ctype:0x3990}},
-		flag: (DEVREG_MATCH_CU_TYPE |
-                       DEVREG_NO_DEV_INFO| 
-                       DEVREG_TYPE_DEVCHARS),
-		oper_func:dasd_oper_handler
-	},
+devreg_t dasd_eckd_known_devices[] = {
+        {
+                ci: { hc: {ctype:0x3880, dtype: 3390}},
+                flag:(DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE | 
+                      DEVREG_TYPE_DEVCHARS),
+                oper_func:dasd_oper_handler
+        },
+        {
+                ci: { hc: {ctype:0x3990}},
+                flag:(DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS),
+                oper_func:dasd_oper_handler
+        },
 	{
-		ci:
-		{hc:
-		 {ctype:0x2105}},
-		flag:(DEVREG_MATCH_CU_TYPE |
-                       DEVREG_NO_DEV_INFO| 
-                       DEVREG_TYPE_DEVCHARS),
-		oper_func:dasd_oper_handler
-	},
+                ci: { hc: {ctype:0x2105}},
+                flag:(DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS),
+                oper_func:dasd_oper_handler
+        },
 	{
-		ci:
-		{hc:
-		 {ctype:0x9343}},
-		flag:(DEVREG_MATCH_CU_TYPE |
-                       DEVREG_NO_DEV_INFO| 
-                       DEVREG_TYPE_DEVCHARS),
-		oper_func:dasd_oper_handler
-	}
+                ci: { hc: {ctype:0x9343}},
+                flag:(DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS),
+                oper_func:dasd_oper_handler
+        }
 };
 #endif
 
-#ifdef DASD_CDL
-int sizes_trk0[]={28,148,84};
+int sizes_trk0[] = { 28, 148, 84 };
 #define LABEL_SIZE 140
-#endif
 
 static inline unsigned int
 round_up_multiple (unsigned int no, unsigned int mult)
@@ -126,8 +109,7 @@
 }
 
 static inline int
-bytes_per_record (dasd_eckd_characteristics_t * rdc,
-		  int kl,	/* key length */
+bytes_per_record (dasd_eckd_characteristics_t * rdc, int kl,	/* key length */
 		  int dl /* data length */ )
 {
 	int bpr = 0;
@@ -194,8 +176,7 @@
 				       9 + ceil_quot (kl + 6 * kn, 34) +
 				       9 + ceil_quot (dl + 6 * dn, 34));
 		} else
-			return 1729 / (10 +
-				       9 + ceil_quot (dl + 6 * dn, 34));
+			return 1729 / (10 + 9 + ceil_quot (dl + 6 * dn, 34));
 	case 0x9345:
 		dn = ceil_quot (dl + 6, 232) + 1;
 		if (kl) {
@@ -204,21 +185,17 @@
 				       7 + ceil_quot (kl + 6 * kn, 34) +
 				       ceil_quot (dl + 6 * dn, 34));
 		} else
-			return 1420 / (18 +
-				       7 + ceil_quot (dl + 6 * dn, 34));
+			return 1420 / (18 + 7 + ceil_quot (dl + 6 * dn, 34));
 	}
 	return rpt;
 }
 
-
-static inline void
+static inline int
 define_extent (ccw1_t * de_ccw,
 	       DE_eckd_data_t * data,
-	       int trk,
-	       int totrk,
-	       int cmd,
-	       dasd_device_t * device)
+	       int trk, int totrk, int cmd, dasd_device_t * device, ccw_req_t* cqr)
 {
+        int rc=0;
 	ch_t geo, beg, end;
 	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
 
@@ -232,7 +209,8 @@
 	memset (de_ccw, 0, sizeof (ccw1_t));
 	de_ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
 	de_ccw->count = 16;
-	set_normalized_cda (de_ccw, __pa (data));
+	if (rc=dasd_set_normalized_cda (de_ccw, __pa (data), cqr, device)) 
+                return rc;
 
 	memset (data, 0, sizeof (DE_eckd_data_t));
 	switch (cmd) {
@@ -259,6 +237,7 @@
 	case DASD_ECKD_CCW_WRITE_CKD_MT:
 		data->attributes.operation = 0x1;	/* format through cache */
 		break;
+	case DASD_ECKD_CCW_ERASE:
 	case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
 	case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
 		data->mask.perm = 0x3;
@@ -270,46 +249,66 @@
 		break;
 	}
 	data->attributes.mode = 0x3;
-	if (private->rdc_data.cu_type == 0x2105 
-#ifdef DASD_CDL
-            && !(private->uses_cdl && trk < 2)
-#endif
-            ) {
+	if (private->rdc_data.cu_type == 0x2105
+	    && !(private->uses_cdl && trk < 2)
+	    ) {
 		data->reserved |= 0x40;
 	}
 	data->beg_ext.cyl = beg.cyl;
 	data->beg_ext.head = beg.head;
 	data->end_ext.cyl = end.cyl;
 	data->end_ext.head = end.head;
+        return rc;
 }
 
-static inline void
+static inline int
 locate_record (ccw1_t * lo_ccw,
 	       LO_eckd_data_t * data,
 	       int trk,
 	       int rec_on_trk,
-	       int no_rec,
-	       int cmd,
-	       dasd_device_t * device,
-	       int reclen)
+	       int no_rec, int cmd, dasd_device_t * device, int reclen, ccw_req_t* cqr)
 {
+        int rc=0;
 	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
-	ch_t geo =
-	{private->rdc_data.no_cyl,
-	 private->rdc_data.trk_per_cyl};
-	ch_t seek =
-	{trk / (geo.head), trk % (geo.head)};
-	int sector;
+	ch_t geo = { private->rdc_data.no_cyl,
+		private->rdc_data.trk_per_cyl
+	};
+	ch_t seek = { trk / (geo.head), trk % (geo.head) };
+	int sector = 0;
 
 #ifdef CDL_PRINTK
-        printk ("Locate: trk %d, rec %d, no_rec %d, cmd %d, reclen %d\n",trk,rec_on_trk,no_rec,cmd,reclen);
+	printk ("Locate: trk %d, rec %d, no_rec %d, cmd %d, reclen %d\n", trk,
+		rec_on_trk, no_rec, cmd, reclen);
 #endif
 	memset (lo_ccw, 0, sizeof (ccw1_t));
 	lo_ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
 	lo_ccw->count = 16;
-	set_normalized_cda (lo_ccw, __pa (data));
+	if (rc=dasd_set_normalized_cda (lo_ccw, __pa (data), cqr, device))
+                return rc;
 
 	memset (data, 0, sizeof (LO_eckd_data_t));
+        if (rec_on_trk) {
+                switch (private->rdc_data.dev_type) {
+                case 0x3390:{
+                        int dn, d;
+                        dn = ceil_quot (reclen + 6, 232);
+                        d = 9 + ceil_quot (reclen + 6 * (dn + 1), 34);
+                        sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8;
+                        break;
+                }
+                case 0x3380:{
+                        int d;
+                        d = 7 + ceil_quot (reclen + 12, 32);
+                        sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7;
+                        break;
+                }
+                case 0x9345:
+                default:
+                        sector = 0;
+                }
+        }
+        data->sector = sector;
+	data->count = no_rec;
 	switch (cmd) {
 	case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
 		data->operation.orientation = 0x3;
@@ -360,32 +359,18 @@
 	case DASD_ECKD_CCW_READ_COUNT:
 		data->operation.operation = 0x06;
 		break;
+	case DASD_ECKD_CCW_ERASE:
+                data->length = reclen;
+                data->auxiliary.last_bytes_used = 0x1;
+		data->operation.operation = 0x0b;
+		break;
 	default:
 		INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd);
 	}
-	switch (private->rdc_data.dev_type) {
-	case 0x3390:{
-			int dn, d;
-			dn = ceil_quot (reclen + 6, 232);
-			d = 9 + ceil_quot (reclen + 6 * (dn + 1), 34);
-			sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8;
-			break;
-		}
-	case 0x3380:{
-			int d;
-			d = 7 + ceil_quot (reclen + 12, 32);
-			sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7;
-			break;
-		}
-	case 0x9345:
-	default:
-		sector = 0;
-	}
-	data->sector = sector;
 	memcpy (&(data->seek_addr), &seek, sizeof (ch_t));
 	memcpy (&(data->search_arg), &seek, sizeof (ch_t));
 	data->search_arg.record = rec_on_trk;
-	data->count += no_rec;
+        return rc;
 }
 
 static int
@@ -393,12 +378,10 @@
 {
 	if (info->sid_data.cu_type == 0x3990 ||
 	    info->sid_data.cu_type == 0x2105)
-		if (info->sid_data.dev_type == 0x3390)
-			return 0;
+		    if (info->sid_data.dev_type == 0x3390) return 0;
 	if (info->sid_data.cu_type == 0x3990 ||
 	    info->sid_data.cu_type == 0x2105)
-		if (info->sid_data.dev_type == 0x3380)
-			return 0;
+		    if (info->sid_data.dev_type == 0x3380) return 0;
 	if (info->sid_data.cu_type == 0x9343)
 		if (info->sid_data.dev_type == 0x9345)
 			return 0;
@@ -408,7 +391,7 @@
 static int
 dasd_eckd_check_characteristics (struct dasd_device_t *device)
 {
-	int rc = -ENODEV;
+	int rc = 0;
 	void *conf_data;
 	void *rdc_data;
 	int conf_len;
@@ -416,82 +399,89 @@
 
 	if (device == NULL) {
 		printk (KERN_WARNING PRINTK_HEADER
-		   "Null device pointer passed to characteristics checker\n");
-		return -ENODEV;
+			"Null device pointer passed to characteristics checker\n");
+                return -ENODEV;
+	}
+	device->private = kmalloc (sizeof (dasd_eckd_private_t), GFP_KERNEL);
+	if (device->private == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"memory allocation failed for private data\n");
+		rc = -ENOMEM;
+                goto fail;
 	}
-        if (device->private != NULL) {
-                kfree(device->private);
-        }
-        device->private = kmalloc (sizeof (dasd_eckd_private_t), GFP_KERNEL);
-        if (device->private == NULL) {
-                printk (KERN_WARNING PRINTK_HEADER
-                        "memory allocation failed for private data\n");
-                return -ENOMEM;
-        }
 	private = (dasd_eckd_private_t *) device->private;
 	rdc_data = (void *) &(private->rdc_data);
 	rc = read_dev_chars (device->devinfo.irq, &rdc_data, 64);
 	if (rc) {
 		printk (KERN_WARNING PRINTK_HEADER
 			"Read device characteristics returned error %d\n", rc);
-		return rc;
-	}
+                goto fail;
+        }
 	printk (KERN_INFO PRINTK_HEADER
-	    "%04X on sch %d: %04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d\n",
+		"%04X on sch %d: %04X/%02X(CU:%04X/%02X) "
+                "Cyl:%d Head:%d Sec:%d\n",
 		device->devinfo.devno, device->devinfo.irq,
 		private->rdc_data.dev_type, private->rdc_data.dev_model,
 		private->rdc_data.cu_type, private->rdc_data.cu_model.model,
 		private->rdc_data.no_cyl, private->rdc_data.trk_per_cyl,
 		private->rdc_data.sec_per_trk);
-	rc = 0 ? 0 : read_conf_data (device->devinfo.irq, &conf_data, &conf_len, LPM_ANYPATH);
+	rc = read_conf_data (device->devinfo.irq, &conf_data, &conf_len,
+                             LPM_ANYPATH);
+
+        if (rc == -EOPNOTSUPP) {
+                rc = 0; /* this one is ok */
+        }
 	if (rc) {
-		if (rc == -EOPNOTSUPP)
-			return 0;
 		printk (KERN_WARNING PRINTK_HEADER
 			"Read configuration data returned error %d\n", rc);
-		return rc;
-	}
-	if (conf_len != sizeof (dasd_eckd_confdata_t)) {
-		printk (KERN_WARNING PRINTK_HEADER
-			"sizes of configuration data mismatch %d (read) vs %ld (expected)\n",
-			conf_len, sizeof (dasd_eckd_confdata_t));
-		return rc;
+                goto fail;
 	}
-	if (conf_data == NULL) {
+        if (conf_data == NULL) {
 		printk (KERN_WARNING PRINTK_HEADER
 			"No configuration data retrieved\n");
-		return -ENOMEM;
-	}
-	memcpy (&private->conf_data, conf_data, sizeof (dasd_eckd_confdata_t));
-	printk (KERN_INFO PRINTK_HEADER
-                "%04X on sch %d: %04X/%02X(CU:%04X/%02X): Configuration data read\n",
-		device->devinfo.devno, device->devinfo.irq,
-		private->rdc_data.dev_type, private->rdc_data.dev_model,
-		private->rdc_data.cu_type, private->rdc_data.cu_model.model);
-	device->sizes.bp_block = 4096;
-	device->sizes.s2b_shift = 3;
-	device->sizes.blocks = (private->rdc_data.no_cyl *
-				private->rdc_data.trk_per_cyl *
-				recs_per_track (&private->rdc_data,
-						0, device->sizes.bp_block));
-	return 0;
+                goto out; /* no errror */
+	} 
+        if (conf_len != sizeof (dasd_eckd_confdata_t)) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"sizes of configuration data mismatch"
+                        "%d (read) vs %ld (expected)\n",
+			conf_len, sizeof (dasd_eckd_confdata_t));
+                goto out; /* no errror */
+	} 
+        memcpy (&private->conf_data, conf_data, 
+                sizeof (dasd_eckd_confdata_t));
+        printk (KERN_INFO PRINTK_HEADER
+                "%04X on sch %d: %04X/%02X(CU:%04X/%02X): "
+                "Configuration data read\n",
+                device->devinfo.devno, device->devinfo.irq,
+                private->rdc_data.dev_type, 
+                private->rdc_data.dev_model,
+                private->rdc_data.cu_type, 
+                private->rdc_data.cu_model.model);
+        goto out;
+ fail:
+        if ( rc ) {
+                kfree (device->private);
+                device->private = NULL;
+        }
+ out:
+	return rc;
 }
 
-#ifdef DASD_CDL
 static inline int
-dasd_eckd_cdl_reclen (dasd_device_t* device,int recid) {
-        dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
-        int byt_per_blk = device->sizes.bp_block;
-        int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk);
-        if (recid < 3) 
-                return sizes_trk0[recid];
-        if (recid < blk_per_trk)
-                return byt_per_blk;
-        if (recid < 2*blk_per_trk )
-                return LABEL_SIZE;
-        return byt_per_blk;
+dasd_eckd_cdl_reclen (dasd_device_t * device, int recid)
+{
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
+	int byt_per_blk = device->sizes.bp_block;
+	int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk);
+	if (recid < 3)
+		return sizes_trk0[recid];
+	if (recid < blk_per_trk)
+		return byt_per_blk;
+	if (recid < 2 * blk_per_trk)
+		return LABEL_SIZE;
+	return byt_per_blk;
 }
-#endif
 
 static ccw_req_t *
 dasd_eckd_init_analysis (struct dasd_device_t *device)
@@ -500,76 +490,82 @@
 	ccw1_t *ccw;
 	DE_eckd_data_t *DE_data;
 	LO_eckd_data_t *LO_data;
-	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
-#ifdef DASD_CDL
-        eckd_count_t *count_data = private->count_area;
-#else
-	eckd_count_t *count_data = &(private->count_area);
-#endif
-#ifdef DASD_CDL
-        cqr = ccw_alloc_request (dasd_eckd_discipline.name, 8 + 1, 
-                                 sizeof (DE_eckd_data_t) + 
-                                 2*sizeof (LO_eckd_data_t));
-#else
-	cqr = ccw_alloc_request (dasd_eckd_discipline.name, 3 + 1, 
-                                 sizeof (DE_eckd_data_t) + 
-                                 sizeof (LO_eckd_data_t));
-#endif
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *)device->private;
+	eckd_count_t *count_data = private->count_area;
+
+	cqr = dasd_alloc_request (dasd_eckd_discipline.name, 8 + 1,
+				 sizeof (DE_eckd_data_t) +
+				 2 * sizeof (LO_eckd_data_t),
+                                 device);
 	if (cqr == NULL) {
-		printk (KERN_WARNING PRINTK_HEADER
-			"No memory to allocate initialization request\n");
-		return NULL;
-	} else {
-		private->init_cqr = cqr;
+                printk (KERN_WARNING PRINTK_HEADER
+                        "No memory to allocate initialization request\n");
+                goto out;
 	}
 	DE_data = cqr->data;
 	LO_data = cqr->data + sizeof (DE_eckd_data_t);
 	ccw = cqr->cpaddr;
-#ifdef DASD_CDL
-        define_extent (ccw, DE_data, 0, 2, DASD_ECKD_CCW_READ_COUNT, device);
-#else
-	define_extent (ccw, DE_data, 0, 0, DASD_ECKD_CCW_READ_COUNT, device);
-#endif
+	if (define_extent (ccw, DE_data, 0, 2, DASD_ECKD_CCW_READ_COUNT, device, cqr)) {
+                goto clear_cqr;
+        }        
 	ccw->flags |= CCW_FLAG_CC;
 	ccw++;
-#ifdef DASD_CDL
-        locate_record (ccw, LO_data++, 0, 0, 4, DASD_ECKD_CCW_READ_COUNT, device, 0);
-#else
-	locate_record (ccw, LO_data, 0, 0, 1, DASD_ECKD_CCW_READ_COUNT, device, 0);
-#endif
-#ifdef DASD_CDL
+	if (locate_record (ccw, LO_data++, 0, 0, 4, DASD_ECKD_CCW_READ_COUNT,
+                           device, 0, cqr)) {
+                goto clear_cqr;
+        }       
 	ccw->flags |= CCW_FLAG_CC;
 	ccw++;
 	ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
 	ccw->count = 8;
-        set_normalized_cda (ccw, __pa (count_data++));
-        ccw->flags |= CCW_FLAG_CC;
-        ccw++;
-        ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
-        ccw->count = 8;
-        set_normalized_cda (ccw, __pa (count_data++));
-        ccw->flags |= CCW_FLAG_CC;
-        ccw++;
-        ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
-        ccw->count = 8;
-        set_normalized_cda (ccw, __pa (count_data++));
-        ccw->flags |= CCW_FLAG_CC;
-        ccw++;
-        ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
-        ccw->count = 8;
-        set_normalized_cda (ccw, __pa (count_data++));
-        ccw->flags |= CCW_FLAG_CC;
-        ccw++;
-        locate_record (ccw, LO_data++, 2, 0, 1, DASD_ECKD_CCW_READ_COUNT, device, 0);
-#endif
-        ccw->flags |= CCW_FLAG_CC;
-        ccw++;
-        ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
-        ccw->count = 8;
-        set_normalized_cda (ccw, __pa (count_data));
+	if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) {
+                goto clear_cqr;
+        }
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
+	ccw->count = 8;
+	if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) {
+                goto clear_cqr;
+        }
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
+	ccw->count = 8;
+	if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) {
+                goto clear_cqr;
+        }
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
+	ccw->count = 8;
+	if (dasd_set_normalized_cda (ccw, __pa (count_data++), cqr, device)) {
+                goto clear_cqr;
+        }
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	if (locate_record (ccw, LO_data++, 2, 0, 1, DASD_ECKD_CCW_READ_COUNT,
+                           device, 0, cqr)) {
+                goto clear_cqr;
+        }       
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
+	ccw->count = 8;
+	if (dasd_set_normalized_cda (ccw, __pa (count_data), cqr, device)) {
+                goto clear_cqr;
+        }
 	cqr->device = device;
 	cqr->retries = 0;
 	cqr->status = CQR_STATUS_FILLED;
+        dasd_chanq_enq (&device->queue, cqr);
+        goto out;
+ clear_cqr:
+        dasd_free_request (cqr,device);
+        printk (KERN_WARNING PRINTK_HEADER
+                "No memory to allocate initialization request\n");
+        cqr=NULL;
+ out:
 	return cqr;
 }
 
@@ -578,105 +574,91 @@
 {
 	int sb, rpt;
 	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
-        eckd_count_t *count_area = NULL;
-        char *cdl_msg;
-#ifdef DASD_CDL /* BAD HACK SO FIX ME UP */
-        int i;
-        private -> uses_cdl = 1;
-
-        /* Free the cqr and cleanup device->sizes */
-        dasd_chanq_deq (&device->queue, private->init_cqr);
-        ccw_free_request (private->init_cqr);
-        private->init_cqr = NULL;
-        memset (&(device->sizes), 0, sizeof (dasd_sizes_t));
-        /* Check Track 0 for Compatible Disk Layout */
-        for (i = 0; i < 3; i++) { 
-                if ((i < 3) &&
-                    ((private->count_area[i].kl != 4) ||
-                     (private->count_area[i].dl != 
-                      dasd_eckd_cdl_reclen (device,i) - 4))) {
-                        private -> uses_cdl = 0;
-                        break;
-                } 
-        }
-        if ( i == 3 ) {
-                count_area = &private->count_area[4];
-        }
-        if (private->uses_cdl == 0) { 
-                for (i = 0; i < 5; i++) {
-                        if ((private->count_area[i].kl != 0) ||
-                            (private->count_area[i].dl != 
-                             private->count_area[0].dl)) {
-                                break;
-                        }
-                }
-                if ( i == 5 ) {
-                        count_area = &private->count_area[0];
-                }
-        } else {
-                if (private->count_area[3].record == 1) {
-                        DASD_MESSAGE(KERN_WARNING,device,"%s",
-                                     "Trk 0: no records after VTOC!");
-                }
+	eckd_count_t *count_area = NULL;
+	char *cdl_msg;
+        int status;
+	int i;
+	private->uses_cdl = 1;
+        status = device->init_cqr->status;
+	dasd_chanq_deq (&device->queue, device->init_cqr);
+	dasd_free_request (device->init_cqr, device);
+	/* Free the cqr and cleanup device->sizes */
+        if ( status != CQR_STATUS_DONE ) {
+                DASD_MESSAGE (KERN_WARNING,device,"%s",
+                              "volume analysis returned fatal error");
+                return -EMEDIUMTYPE;
         }
-        if (count_area != NULL && /* we found notthing violating our disk layout */
-            count_area ->kl == 0) { 
+	/* Check Track 0 for Compatible Disk Layout */
+	for (i = 0; i < 3; i++) {
+		if ((i < 3) &&
+		    ((private->count_area[i].kl != 4) ||
+		     (private->count_area[i].dl !=
+		      dasd_eckd_cdl_reclen (device, i) - 4))) {
+			private->uses_cdl = 0;
+			break;
+		}
+	}
+	if (i == 3) {
+		count_area = &private->count_area[4];
+	}
+	if (private->uses_cdl == 0) {
+		for (i = 0; i < 5; i++) {
+			if ((private->count_area[i].kl != 0) ||
+			    (private->count_area[i].dl !=
+			     private->count_area[0].dl)) {
+				break;
+			}
+		}
+		if (i == 5) {
+			count_area = &private->count_area[0];
+		}
+	} else {
+		if (private->count_area[3].record == 1) {
+			DASD_MESSAGE (KERN_WARNING, device, "%s",
+				      "Trk 0: no records after VTOC!");
+		}
+	}
+	if (count_area != NULL &&	/* we found notthing violating our disk layout */
+	    count_area->kl == 0) {
                 /* find out blocksize */
                 switch (count_area->dl) {
                 case 512:
-                case 1024:
-                case 2048:
-                case 4096:
-                        device->sizes.bp_block = count_area->dl;
-                        break;
-                }
-        }
-#else
-	dasd_chanq_deq (&device->queue, private->init_cqr);
-	ccw_free_request (private->init_cqr);
-	private->init_cqr = NULL;
-	memset (&(device->sizes), 0, sizeof (dasd_sizes_t));
-	switch (private->count_area.dl) {
-	case 512:
-	case 1024:
-	case 2048:
-	case 4096:
-		device->sizes.bp_block = private->count_area.dl;
-		break;
+		case 1024:
+		case 2048:
+		case 4096:
+			device->sizes.bp_block = count_area->dl;
+			break;
+		}
+	}
+	if (device->sizes.bp_block == 0) {
+		DASD_MESSAGE (KERN_WARNING, device, "%s\n",
+			      "Volume has incompatible disk layout");
+		return -EMEDIUMTYPE;
 	}
-#endif
-        if ( device->sizes.bp_block == 0 ) {
-                DASD_MESSAGE(KERN_WARNING, device,"%s\n",
-                             "Volume has incompatible disk layout");
-                return -EMEDIUMTYPE;
-        }
 	device->sizes.s2b_shift = 0;	/* bits to shift 512 to get a block */
-        device->sizes.pt_block = 2;
+	device->sizes.pt_block = 2;
 	for (sb = 512; sb < device->sizes.bp_block; sb = sb << 1)
 		device->sizes.s2b_shift++;
 
 	rpt = recs_per_track (&private->rdc_data, 0, device->sizes.bp_block);
-	device->sizes.blocks = (private->rdc_data.no_cyl * 
-                                private->rdc_data.trk_per_cyl *
-                                recs_per_track (&private->rdc_data, 0, 
-                                                device->sizes.bp_block));
-#ifdef DASD_CDL
-        cdl_msg = private->uses_cdl?"compatible disk layout":"classic disk layout";
-#else
-        cdl_msg = "classic disk layout";
-#endif           
-                  
-        DASD_MESSAGE(KERN_INFO,device,"(%dkB blks): %dkB at %dkB/trk %s",
-                     (device->sizes.bp_block >> 10),
-                     (private->rdc_data.no_cyl * 
-                      private->rdc_data.trk_per_cyl *
-                      recs_per_track (&private->rdc_data, 0, 
-                                      device->sizes.bp_block) *
-                      (device->sizes.bp_block >> 9)) >> 1,
-                     (recs_per_track (&private->rdc_data, 0, 
-                                      device->sizes.bp_block) * 
-                      device->sizes.bp_block) >> 10,
-                     cdl_msg);
+	device->sizes.blocks = (private->rdc_data.no_cyl *
+				private->rdc_data.trk_per_cyl *
+				recs_per_track (&private->rdc_data, 0,
+						device->sizes.bp_block));
+	cdl_msg =
+	    private->
+	    uses_cdl ? "compatible disk layout" : "classic disk layout";
+
+	DASD_MESSAGE (KERN_INFO, device, "(%dkB blks): %dkB at %dkB/trk %s",
+		      (device->sizes.bp_block >> 10),
+		      (private->rdc_data.no_cyl *
+		       private->rdc_data.trk_per_cyl *
+		       recs_per_track (&private->rdc_data, 0,
+				       device->sizes.bp_block) *
+		       (device->sizes.bp_block >> 9)) >> 1,
+		      (recs_per_track (&private->rdc_data, 0,
+				       device->sizes.bp_block) *
+		       device->sizes.bp_block) >> 10, cdl_msg);
 	return 0;
 }
 
@@ -690,13 +672,14 @@
 	case 1024:
 	case 2048:
 	case 4096:
-		break;
+            geo->sectors = recs_per_track (&(private->rdc_data), 
+                                           0, device->sizes.bp_block);
+            break;
 	default:
-		return -EINVAL;
+            break;
 	}
 	geo->cylinders = private->rdc_data.no_cyl;
 	geo->heads = private->rdc_data.trk_per_cyl;
-	geo->sectors = recs_per_track (&(private->rdc_data), 0, device->sizes.bp_block);
 	return rc;
 }
 
@@ -713,95 +696,89 @@
 	ccw1_t *last_ccw = NULL;
 	void *last_data = NULL;
 	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
-	int trk = fdata->start_unit;
-	int bs = fdata->blksize == DASD_FORMAT_DEFAULT_BLOCKSIZE ? 4096 : fdata->blksize;
-	int flags = fdata->intensity == DASD_FORMAT_DEFAULT_INTENSITY ? 0 : fdata->intensity;
-
-	int rpt = recs_per_track (&(private->rdc_data), 0, bs);
-	int cyl = trk / private->rdc_data.trk_per_cyl;
-	int head = trk % private->rdc_data.trk_per_cyl;
+
+	int rpt = recs_per_track (&(private->rdc_data), 0, fdata->blksize);
+	int cyl = fdata->start_unit / private->rdc_data.trk_per_cyl;
+	int head = fdata->start_unit % private->rdc_data.trk_per_cyl;
 	int wrccws = rpt;
 	int datasize = sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t);
-#ifdef DASD_CDL
-        int formatCDL=0;
-#endif
-
-	if (((fdata->stop_unit == DASD_FORMAT_DEFAULT_STOP_UNIT) &&
-	 trk >= (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) ||
-	    ((fdata->stop_unit != DASD_FORMAT_DEFAULT_STOP_UNIT) &&
-	     trk > fdata->stop_unit)) {
-		DASD_MESSAGE(KERN_INFO, device,"Track %d reached! ending.", trk);
+        
+	if (fdata->start_unit >= (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)){
+                DASD_MESSAGE (KERN_INFO, device, "Track no %d too big!", fdata->start_unit);
+                return NULL;
+        }
+        if ( fdata->start_unit > fdata->stop_unit) {
+                DASD_MESSAGE (KERN_INFO, device, "Track %d reached! ending.",
+                              fdata->start_unit);
 		return NULL;
 	}
-	switch (bs) {
+	switch (fdata->blksize) {
 	case 512:
 	case 1024:
 	case 2048:
 	case 4096:
 		break;
 	default:
-		printk (KERN_WARNING PRINTK_HEADER "Invalid blocksize %d...terminating!\n", bs);
+		printk (KERN_WARNING PRINTK_HEADER
+			"Invalid blocksize %d...terminating!\n", fdata->blksize);
 		return NULL;
 	}
-	switch (flags) {
+	switch (fdata->intensity) {
 	case 0x00:
 	case 0x01:
 	case 0x03:
 	case 0x04:		/* make track invalid */
-                break;
-#ifdef DASD_CDL /* Format compatible disk Layout */
-        case 0x08:
-        case 0x09:
-        case 0x0b:
-        case 0x0c:
-                formatCDL=1;
+	case 0x08:
+	case 0x09:
+	case 0x0b:
+	case 0x0c:
 		break;
-#endif
 	default:
-		printk (KERN_WARNING PRINTK_HEADER "Invalid flags 0x%x...terminating!\n", flags);
+		printk (KERN_WARNING PRINTK_HEADER
+			"Invalid flags 0x%x...terminating!\n", fdata->intensity);
 		return NULL;
 	}
 
 	/* print status line */
 	if ((private->rdc_data.no_cyl < 20) ?
-	    (trk % private->rdc_data.no_cyl == 0) :
-	    (trk % private->rdc_data.no_cyl == 0 &&
-	     (trk / private->rdc_data.no_cyl) %
+	    (fdata->start_unit % private->rdc_data.no_cyl == 0) :
+	    (fdata->start_unit % private->rdc_data.no_cyl == 0 &&
+	     (fdata->start_unit / private->rdc_data.no_cyl) %
 	     (private->rdc_data.no_cyl / 20))) {
-		DASD_MESSAGE(KERN_INFO, device, "Format Cylinder: %d Flags: %d\n",
-			trk / private->rdc_data.trk_per_cyl,
-			flags);
+		DASD_MESSAGE (KERN_INFO, device,
+			      "Format Cylinder: %d Flags: %d\n",
+			      fdata->start_unit / private->rdc_data.trk_per_cyl, fdata->intensity);
 	}
-	if (flags & 0x04) {
-                rpt = 1;
+	if ((fdata->intensity & ~0x8) & 0x04) {
 		wrccws = 1;
-                bs = 8;
+		rpt = 1;
 	} else {
-		if (flags & 0x1) {
+		if (fdata->intensity & 0x1) {
 			wrccws++;
 			datasize += sizeof (eckd_count_t);
 		}
-		if (flags & 0x2) {
+		if (fdata->intensity & 0x2) {
 			wrccws++;
 			datasize += sizeof (eckd_home_t);
 		}
 	}
-	fcp = ccw_alloc_request (dasd_eckd_discipline.name,
+	fcp = dasd_alloc_request (dasd_eckd_discipline.name,
 				 wrccws + 2 + 1,
-				 datasize + rpt * sizeof (eckd_count_t));
+				 datasize + rpt * sizeof (eckd_count_t),
+                                 device );
 	if (fcp != NULL) {
 		fcp->device = device;
-                fcp->retries = 2;       /* set retry counter to enable ERP */
+		fcp->retries = 2;	/* set retry counter to enable ERP */
 		last_data = fcp->data;
 		DE_data = (DE_eckd_data_t *) last_data;
 		last_data = (void *) (DE_data + 1);
 		LO_data = (LO_eckd_data_t *) last_data;
 		last_data = (void *) (LO_data + 1);
-		if (flags & 0x2) {
+		if (fdata->intensity & 0x2) {
 			ha_data = (eckd_home_t *) last_data;
 			last_data = (void *) (ha_data + 1);
 		}
-		if (flags & 0x1) {
+		if (fdata->intensity & 0x1) {
 			r0_data = (eckd_count_t *) last_data;
 			last_data = (void *) (r0_data + 1);
 		}
@@ -809,63 +786,65 @@
 
 		last_ccw = fcp->cpaddr;
 
-		switch (flags) {
+		switch (fdata->intensity & ~0x08) {
 		case 0x03:
-                case 0x0b:
-			define_extent (last_ccw, DE_data, trk, trk,
-				    DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device);
+			if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit,
+				       DASD_ECKD_CCW_WRITE_HOME_ADDRESS,
+                                           device, fcp)) {
+                                goto clear_fcp;
+                        }
 			last_ccw->flags |= CCW_FLAG_CC;
 			last_ccw++;
-			locate_record (last_ccw, LO_data, trk, 0, wrccws,
-				       DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device, device->sizes.bp_block);
+			if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws,
+				       DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device,
+                                           device->sizes.bp_block, fcp)) {
+                                goto clear_fcp;
+                        }
 			last_ccw->flags |= CCW_FLAG_CC;
 			last_ccw++;
 			break;
 		case 0x01:
-                case 0x09:
-			define_extent (last_ccw, DE_data, trk, trk,
-				     DASD_ECKD_CCW_WRITE_RECORD_ZERO, device);
+			if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit,
+                                           DASD_ECKD_CCW_WRITE_RECORD_ZERO, device, fcp)) {
+                                goto clear_fcp;
+                        }
 			last_ccw->flags |= CCW_FLAG_CC;
 			last_ccw++;
-			locate_record (last_ccw, LO_data, trk, 0, wrccws,
-				       DASD_ECKD_CCW_WRITE_RECORD_ZERO, device, device->sizes.bp_block);
+			if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws,
+				       DASD_ECKD_CCW_WRITE_RECORD_ZERO, device,
+                                           device->sizes.bp_block, fcp)) {
+                                goto clear_fcp;
+                        }
 			last_ccw->flags |= CCW_FLAG_CC;
 			last_ccw++;
 			memset (r0_data, 0, sizeof (eckd_count_t));
 			break;
-		case 0x00:
-                case 0x08:
-			define_extent (last_ccw, DE_data, trk, trk,
-				       DASD_ECKD_CCW_WRITE_CKD, device);
-			last_ccw->flags |= CCW_FLAG_CC;
-			last_ccw++;
-			locate_record (last_ccw, LO_data, trk, 0, wrccws,
-				       DASD_ECKD_CCW_WRITE_CKD, device, device->sizes.bp_block);
-			LO_data->length = bs;
-			last_ccw->flags |= CCW_FLAG_CC;
-			last_ccw++;
-			break;
 		case 0x04:
-                case 0x0c:
-			define_extent (last_ccw, DE_data, trk, trk,
-				       DASD_ECKD_CCW_WRITE_CKD, device);
+                        fdata->blksize = 8;
+		case 0x00:
+			if (define_extent (last_ccw, DE_data, fdata->start_unit, fdata->start_unit,
+                                           DASD_ECKD_CCW_WRITE_CKD, device, fcp)) {
+                                dasd_free_request (fcp, device);
+                                return NULL;
+                        }
 			last_ccw->flags |= CCW_FLAG_CC;
 			last_ccw++;
-			locate_record (last_ccw, LO_data, trk, 0, wrccws,
-				       DASD_ECKD_CCW_WRITE_CKD, device, 0);
-			LO_data->length = bs;
+			if (locate_record (last_ccw, LO_data, fdata->start_unit, 0, wrccws,
+                                           DASD_ECKD_CCW_WRITE_CKD, device, fdata->blksize, fcp)) {
+                                goto clear_fcp;
+                        }
 			last_ccw->flags |= CCW_FLAG_CC;
 			last_ccw++;
 			break;
 		default:
-			PRINT_WARN ("Unknown format flags...%d\n", flags);
+			PRINT_WARN ("Unknown format flags...%d\n", fdata->intensity);
 			return NULL;
 		}
-		if (flags & 0x02) {
-			PRINT_WARN ("Unsupported format flag...%d\n", flags);
+		if (fdata->intensity & 0x02) {
+			PRINT_WARN ("Unsupported format flag...%d\n", fdata->intensity);
 			return NULL;
 		}
-		if (flags & 0x01) {	/* write record zero */
+		if (fdata->intensity & 0x01) {	/* write record zero */
 			r0_data->cyl = cyl;
 			r0_data->head = head;
 			r0_data->record = 0;
@@ -874,49 +853,73 @@
 			last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
 			last_ccw->count = 8;
 			last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI;
-			set_normalized_cda (last_ccw, __pa (r0_data));
+			if (dasd_set_normalized_cda (last_ccw, __pa (r0_data), fcp, device)) {
+                                goto clear_fcp;
+                        }
 			last_ccw++;
 		}
-		/* write remaining records */
-		for (i = 0; i < rpt; i++) {
-			memset (ct_data + i, 0, sizeof (eckd_count_t));
-			(ct_data + i)->cyl = cyl;
-			(ct_data + i)->head = head;
-			(ct_data + i)->record = i + 1;
-			(ct_data + i)->kl = 0;
-#ifdef DASD_CDL
-                        if (formatCDL) { 
-                            // special handling when formatting CDL
-                            switch (trk) {
-                            case 0:
-                                if (i<3) {
-                                    (ct_data + i)->kl = 4;
-                                    (ct_data + i)->dl = sizes_trk0[i]-4;
-                                } else 
-                                    (ct_data + i)->dl = bs;
-                                break;
-                            case 1:
-                                (ct_data + i)->kl = 44;
-                                (ct_data + i)->dl = LABEL_SIZE-44;
-                                break;
-                            default:
-                                (ct_data + i)->dl = bs;
-                                break;
-                            }
-                        }
-                        else
-#endif                            
-                        (ct_data + i)->dl = bs;
+		if ((fdata->intensity & ~0x08) & 0x04) {	/* erase track */
+			memset (ct_data, 0, sizeof (eckd_count_t));
+			ct_data->cyl = cyl;
+			ct_data->head = head;
+			ct_data->record = 1;
+			ct_data->kl = 0;
+			ct_data->dl = 0;
 			last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
-			last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI;
 			last_ccw->count = 8;
-			set_normalized_cda (last_ccw, __pa (ct_data + i));
+			last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI;
+			if (dasd_set_normalized_cda (last_ccw, __pa (ct_data), fcp, device)) {
+                                goto clear_fcp;
+                        }
 			last_ccw++;
+		} else {	/* write remaining records */
+			for (i = 0; i < rpt; i++) {
+				memset (ct_data + i, 0, sizeof (eckd_count_t));
+				(ct_data + i)->cyl = cyl;
+				(ct_data + i)->head = head;
+				(ct_data + i)->record = i + 1;
+				(ct_data + i)->kl = 0;
+				if (fdata->intensity & 0x08) {
+					// special handling when formatting CDL
+					switch (fdata->start_unit) {
+					case 0:
+						if (i < 3) {
+							(ct_data + i)->kl = 4;
+							
+							    (ct_data + i)->dl =
+							    sizes_trk0[i] - 4;
+						} else
+							(ct_data + i)->dl = fdata->blksize;
+						break;
+					case 1:
+						(ct_data + i)->kl = 44;
+						(ct_data + i)->dl = LABEL_SIZE - 44;
+						break;
+					default:
+						(ct_data + i)->dl = fdata->blksize;
+						break;
+					}
+				} else
+					(ct_data + i)->dl = fdata->blksize;
+				last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
+				last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI;
+				last_ccw->count = 8;
+				if (dasd_set_normalized_cda (last_ccw,
+                                                             __pa (ct_data + i), fcp, device)) {
+                                goto clear_fcp;
+                                }
+				last_ccw++;
+			}
 		}
 		(last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC);
 		fcp->device = device;
 		fcp->status = CQR_STATUS_FILLED;
 	}
+        goto out;
+ clear_fcp:
+        dasd_free_request (fcp, device);
+        fcp=NULL;
+ out:
 	return fcp;
 }
 
@@ -927,7 +930,7 @@
 
 	if (stat->cstat == 0x00 &&
 	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
-		return dasd_era_none;
+		    return dasd_era_none;
 
 	switch (device->devinfo.sid_data.cu_type) {
 	case 0x3990:
@@ -946,56 +949,56 @@
 dasd_eckd_erp_action (ccw_req_t * cqr)
 {
 	dasd_device_t *device = (dasd_device_t *) cqr->device;
-        
+
 	switch (device->devinfo.sid_data.cu_type) {
 	case 0x3990:
 	case 0x2105:
 		return dasd_3990_erp_action;
 	case 0x9343:
-                /* Return dasd_9343_erp_action; */
+		/* Return dasd_9343_erp_action; */
 	default:
-		return default_erp_action;
+		return dasd_default_erp_action;
 	}
 }
 
 static dasd_erp_postaction_fn_t
 dasd_eckd_erp_postaction (ccw_req_t * cqr)
 {
-	return default_erp_postaction;
+	return dasd_default_erp_postaction;
 }
 
 
-#ifdef DASD_CDL
 inline unsigned char
-dasd_eckd_cdl_cmd(dasd_device_t *device,int recid,int cmd) {
-    dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
-    int byt_per_blk = device->sizes.bp_block;
-    int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk);
-    switch (cmd) {
-    case READ:
-        if (recid < 3) 
-            return DASD_ECKD_CCW_READ_KD_MT;
-        if (recid < blk_per_trk)
-            return DASD_ECKD_CCW_READ_MT;
-        if (recid < 2*blk_per_trk)
-            return DASD_ECKD_CCW_READ_KD_MT;
-        return DASD_ECKD_CCW_READ_MT;
-        break;
-    case WRITE:
-        if (recid < 3)
-            return DASD_ECKD_CCW_WRITE_KD_MT;
-        if (recid < blk_per_trk)
-            return DASD_ECKD_CCW_WRITE_MT;
-        if (recid < 2*blk_per_trk)
-            return DASD_ECKD_CCW_WRITE_KD_MT;
-        return DASD_ECKD_CCW_WRITE_MT;
-        break;
-    default:
-        BUG();
-    }
-    return 0; // never executed
+dasd_eckd_cdl_cmd (dasd_device_t * device, int recid, int cmd)
+{
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
+	int byt_per_blk = device->sizes.bp_block;
+	int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk);
+	switch (cmd) {
+	case READ:
+		if (recid < 3)
+			return DASD_ECKD_CCW_READ_KD_MT;
+		if (recid < blk_per_trk)
+			return DASD_ECKD_CCW_READ_MT;
+		if (recid < 2 * blk_per_trk)
+			return DASD_ECKD_CCW_READ_KD_MT;
+		return DASD_ECKD_CCW_READ_MT;
+		break;
+	case WRITE:
+		if (recid < 3)
+			return DASD_ECKD_CCW_WRITE_KD_MT;
+		if (recid < blk_per_trk)
+			return DASD_ECKD_CCW_WRITE_MT;
+		if (recid < 2 * blk_per_trk)
+			return DASD_ECKD_CCW_WRITE_KD_MT;
+		return DASD_ECKD_CCW_WRITE_MT;
+		break;
+	default:
+		BUG ();
+	}
+	return 0;		// never executed
 }
-#endif
+
 
 static ccw_req_t *
 dasd_eckd_build_cp_from_req (dasd_device_t * device, struct request *req)
@@ -1014,11 +1017,9 @@
 	int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk);
 	int btrk = (req->sector >> shift) / blk_per_trk;
 	int etrk = ((req->sector + req->nr_sectors - 1) >> shift) / blk_per_trk;
-#ifdef DASD_CDL
-        int recid = req->sector >> shift;
-        int locate4k_set=0;
-        int nlocs=0;
-#endif
+	int recid = req->sector >> shift;
+	int locate4k_set = 0;
+	int nlocs = 0;
 
 	if (req->cmd == READ) {
 		rw_cmd = DASD_ECKD_CCW_READ_MT;
@@ -1032,142 +1033,78 @@
 	/* count bhs to prevent errors, when bh smaller than block */
 	bhct = 0;
 	for (bh = req->bh; bh; bh = bh->b_reqnext) {
-		if (bh->b_size > byt_per_blk)
-			for (size = 0; size < bh->b_size; size += byt_per_blk)
-				bhct++;
-		else
-			bhct++;
+		if (bh->b_size < byt_per_blk)
+                        BUG();
+                bhct+= bh->b_size >> (device->sizes.s2b_shift+9);
+	}
+	if (btrk < 2 && private->uses_cdl) {
+		if (etrk < 2)
+                        nlocs = bhct;
+                else
+                        nlocs = 2 * blk_per_trk - recid;
 	}
-#ifndef DASD_CDL
-	rw_cp = dasd_alloc_request (dasd_eckd_discipline.name,
-				    2 + bhct + 1,
-				    sizeof (DE_eckd_data_t) +
-				    sizeof (LO_eckd_data_t));
-#else
-        if (btrk<2 && private->uses_cdl) {
-            nlocs+= 2*blk_per_trk-recid;
-            if (etrk<2)
-                nlocs-=2*blk_per_trk-((req->sector + req->nr_sectors - 1) >> shift);
-        }
-        rw_cp = dasd_alloc_request (dasd_eckd_discipline.name,
+	rw_cp = dasd_alloc_request (dasd_eckd_discipline.name, 
                                     2 + nlocs + bhct + 1,
-                                    sizeof (DE_eckd_data_t) +
-                                    (1+nlocs)*sizeof (LO_eckd_data_t));
-#endif
+                                    sizeof (DE_eckd_data_t) + (1 +
+                                                               nlocs) *
+                                    sizeof (LO_eckd_data_t),
+                                    device);
 	if (!rw_cp) {
 		return NULL;
 	}
 	DE_data = rw_cp->data;
 	LO_data = rw_cp->data + sizeof (DE_eckd_data_t);
 	ccw = rw_cp->cpaddr;
-	define_extent (ccw, DE_data, btrk, etrk, rw_cmd, device);
-	ccw->flags |= CCW_FLAG_CC;
-#ifndef DASD_CDL
-	ccw++;
-        locate_record (ccw, LO_data, btrk, (req->sector >> shift) % blk_per_trk + 1,
-                       req->nr_sectors >> shift, rw_cmd, device, device->sizes.bp_block);
+	if (define_extent (ccw, DE_data, btrk, etrk, rw_cmd, device, rw_cp)) {
+                goto clear_rw_cp;
+        }
 	ccw->flags |= CCW_FLAG_CC;
-#endif
 	for (bh = req->bh; bh != NULL;) {
-		if (bh->b_size > byt_per_blk) {
-			for (size = 0; size < bh->b_size; size += byt_per_blk) {
-#ifdef DASD_CDL
-                                if (!locate4k_set) {
-                                    // we need to chain a locate record before our rw-ccw
-                                    ccw++;
-                                    if ((recid/blk_per_trk)<2 && private->uses_cdl) {
+                for (size = 0; size < bh->b_size; size += byt_per_blk) {
+                        if (!locate4k_set) {
+                                // we need to chain a locate record before our rw-ccw
+                                ccw++;
+                                if ((recid / blk_per_trk) < 2
+                                    && private->uses_cdl) {
                                         /* Do a locate record for our special blocks */
-                                        locate_record (ccw, LO_data++, recid/blk_per_trk, 
-                                                       recid % blk_per_trk + 1, 1, 
-                                                       dasd_eckd_cdl_cmd(device,recid,req->cmd), 
-                                                       device, 
-                                                       dasd_eckd_cdl_reclen(device,recid));
-                                    } else {
-                                        // Do a locate record for standard blocks */
-                                        locate_record (ccw, LO_data++, recid/blk_per_trk,
+                                        int cmd = dasd_eckd_cdl_cmd (device,recid, req->cmd);
+                                        if (locate_record (ccw, 
+                                                       LO_data++,
+                                                       recid / blk_per_trk, 
                                                        recid % blk_per_trk + 1, 
-                                                       (((req->sector + req->nr_sectors) >> shift)-recid),
-                                                       rw_cmd,device, device->sizes.bp_block);
-                                        locate4k_set=1;
-                                    }                                        
-                                    ccw->flags |= CCW_FLAG_CC;
-                                }
-#endif
-				ccw++;
-#ifndef DASD_CDL
-				ccw->flags |= CCW_FLAG_CC;
-				ccw->cmd_code= rw_cmd;
-				ccw->count = bh->b_size;
-#else
-                                ccw->flags |= CCW_FLAG_CC;
-                                ccw->cmd_code=locate4k_set?rw_cmd:
-                                    dasd_eckd_cdl_cmd(device,recid,req->cmd);
-                                ccw->count =locate4k_set?bh->b_size:
-                                    dasd_eckd_cdl_reclen(device,recid);
-#endif
-				set_normalized_cda (ccw, __pa (bh->b_data));
-				size += bh->b_size;
-				bh = bh->b_reqnext;
-#ifdef DASD_CDL
-                                recid++;
-#endif
-			}
-			bh = bh->b_reqnext;
-		} else {	/* group N bhs to fit into byt_per_blk */
-			for (size = 0; bh != NULL && size < byt_per_blk;) {
-#ifdef DASD_CDL
-                                if (!locate4k_set) {
-                                    // we need to chain a locate record before our rw-ccw
-                                    ccw++;
-                                    if ((recid/blk_per_trk)<2 && private->uses_cdl) {
-                                        /* Do a locate record for our special blocks */
-                                        locate_record (ccw, LO_data++, recid/blk_per_trk, 
-                                                       recid % blk_per_trk + 1, 1, 
-                                                       dasd_eckd_cdl_cmd(device,recid,req->cmd), 
-                                                       device, 
-                                                       dasd_eckd_cdl_reclen(device,recid));
-                                    } else {
+                                                       1, cmd, device,
+                                                           dasd_eckd_cdl_reclen(device, recid), rw_cp)) {
+                                                goto clear_rw_cp;
+                                        }
+                                } else {
                                         // Do a locate record for standard blocks */
-                                        locate_record (ccw, LO_data++, recid/blk_per_trk,
-                                                       recid % blk_per_trk + 1, 
-                                                       (((req->sector + req->nr_sectors) >> shift)-recid),
-                                                       rw_cmd,device, device->sizes.bp_block);
-                                        locate4k_set=1;
-                                    }                                        
-                                    ccw->flags |= CCW_FLAG_CC;
+                                        if (locate_record (ccw, 
+                                                       LO_data++,
+                                                       recid /blk_per_trk,
+                                                       recid %blk_per_trk + 1,
+                                                       (((req->sector +
+                                                          req->nr_sectors) >>
+                                                         shift) - recid), 
+                                                       rw_cmd, device,
+                                                           device->sizes.bp_block, rw_cp)) {
+                                                goto clear_rw_cp;
+                                        }
+                                        locate4k_set = 1;
                                 }
-#endif
-				ccw++;
-#ifndef DASD_CDL
-				ccw->flags |= CCW_FLAG_DC;
-				ccw->cmd_code= rw_cmd;
-				ccw->count = bh->b_size;
-#else
-                                ccw->flags |= locate4k_set?CCW_FLAG_DC:CCW_FLAG_CC;
-                                ccw->cmd_code=locate4k_set?rw_cmd:
-                                    dasd_eckd_cdl_cmd(device,recid,req->cmd);
-                                ccw->count =locate4k_set?bh->b_size:
-                                    dasd_eckd_cdl_reclen(device,recid);
-#endif
-				set_normalized_cda (ccw, __pa (bh->b_data));
-				size += bh->b_size;
-				bh = bh->b_reqnext;
-#ifdef DASD_CDL
-                                recid++;
-#endif
-			}
-			if (size != byt_per_blk) {
-				PRINT_WARN ("Cannot fulfill small request %ld vs. %d (%ld sects)\n",
-					    size,
-					    byt_per_blk,
-					    req->nr_sectors);
-
-				ccw_free_request (rw_cp);
-				return NULL;
-			}
-			ccw->flags &= ~CCW_FLAG_DC;
-			ccw->flags |= CCW_FLAG_CC;
-		}
+                                ccw->flags |= CCW_FLAG_CC;
+                        }
+                        ccw++;
+                        ccw->flags |= CCW_FLAG_CC;
+                        ccw->cmd_code = locate4k_set ? rw_cmd :
+                                dasd_eckd_cdl_cmd (device, recid, req->cmd);
+                        ccw->count = locate4k_set ? byt_per_blk :
+                                dasd_eckd_cdl_reclen (device, recid);
+                        if (dasd_set_normalized_cda (ccw, __pa (bh->b_data+size), rw_cp, device)) {
+                                goto clear_rw_cp;
+                        }
+                        recid++;
+                }
+                bh = bh->b_reqnext;
 	}
 	ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC);
 	rw_cp->device = device;
@@ -1176,11 +1113,15 @@
 	rw_cp->lpm = LPM_ANYPATH;
 	rw_cp->retries = 2;
 	asm volatile ("STCK %0":"=m" (rw_cp->buildclk));
-	check_then_set (&rw_cp->status,
-				       CQR_STATUS_EMPTY,
-				       CQR_STATUS_FILLED);
+	check_then_set (&rw_cp->status, CQR_STATUS_EMPTY, CQR_STATUS_FILLED);
+        goto out;
+ clear_rw_cp:
+        dasd_free_request (rw_cp, device);
+        rw_cp=NULL;
+ out:
 	return rw_cp;
 }
+
 #if 0
 int
 dasd_eckd_cleanup_request (ccw_req_t * cqr)
@@ -1197,7 +1138,8 @@
 				ccw->flags |= CCW_FLAG_CC;
 				ccw->cmd_code = rw_cmd;
 				ccw->count = byt_per_blk;
-				set_normalized_cda (ccw, __pa (bh->b_data + size));
+				set_normalized_cda (ccw,
+						    __pa (bh->b_data + size));
 			}
 			bh = bh->b_reqnext;
 		} else {	/* group N bhs to fit into byt_per_blk */
@@ -1218,7 +1160,8 @@
 ccw_req_t *
 dasd_eckd_reserve (struct dasd_device_t * device)
 {
-	ccw_req_t *cqr = ccw_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0);
+	ccw_req_t *cqr =
+	    dasd_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0, device);
 	if (cqr == NULL) {
 		printk (KERN_WARNING PRINTK_HEADER
 			"No memory to allocate initialization request\n");
@@ -1234,7 +1177,8 @@
 ccw_req_t *
 dasd_eckd_release (struct dasd_device_t * device)
 {
-	ccw_req_t *cqr = ccw_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0);
+	ccw_req_t *cqr =
+	    dasd_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0, device);
 	if (cqr == NULL) {
 		printk (KERN_WARNING PRINTK_HEADER
 			"No memory to allocate initialization request\n");
@@ -1254,67 +1198,91 @@
 	ccw1_t *cp;
 
 	cp = cqr->cpaddr;
-        do {
+	do {
 		if (cp->cmd_code == cmd)
 			return cp;
 		if (cp->cmd_code == CCW_CMD_TIC) {
-			cp = (ccw1_t *)cp->cda;
-                        continue;
-		} 
-                if ( cp->flags & (CCW_FLAG_DC | CCW_FLAG_CC) ) {
-                        cp ++;
-                        continue;
-		}
-                break;
-	} while ( 1 );
-        return NULL;
+			cp = (ccw1_t *) (long) cp->cda;
+			continue;
+		}
+		if (cp->flags & (CCW_FLAG_DC | CCW_FLAG_CC)) {
+			cp++;
+			continue;
+		}
+		break;
+	} while (1);
+	return NULL;
 }
 
-ccw_req_t *
-dasd_eckd_merge_cp ( dasd_device_t *device )
+static ccw_req_t *
+dasd_eckd_merge_cp (dasd_device_t * device)
 {
-        return NULL;
+	return NULL;
 }
 
-static char *
-dasd_eckd_dump_sense (struct dasd_device_t *device, ccw_req_t * req)
+static int
+dasd_eckd_fill_info (dasd_device_t * device, dasd_information_t * info)
 {
+	int rc = 0;
+	info->label_block = 2;
+	if (((dasd_eckd_private_t *) device->private)->uses_cdl)
+		info->FBA_layout = 0;
+	else
+		info->FBA_layout = 1;
+	info->characteristics_size = sizeof (dasd_eckd_characteristics_t);
+	memcpy (info->characteristics,
+		&((dasd_eckd_private_t *) device->private)->rdc_data,
+		sizeof (dasd_eckd_characteristics_t));
+	info->confdata_size = sizeof (dasd_eckd_confdata_t);
+	memcpy (info->configuration_data,
+		&((dasd_eckd_private_t *) device->private)->conf_data,
+		sizeof (dasd_eckd_confdata_t));
+	return rc;
+}
+
+static char*
+dasd_eckd_dump_sense (struct dasd_device_t *device, 
+                      ccw_req_t            *req)
+{
+
 	char *page = (char *) get_free_page (GFP_ATOMIC);
 	devstat_t *stat = &device->dev_status;
 	char *sense = stat->ii.sense.data;
 	int len, sl, sct;
 
 	if (page == NULL) {
+                printk (KERN_ERR PRINTK_HEADER
+                        "No memory to dump sense data\n");
 		return NULL;
 	}
-	len = sprintf (page, KERN_WARNING PRINTK_HEADER
+
+	len = sprintf (page, KERN_ERR PRINTK_HEADER
 		       "device %04X on irq %d: I/O status report:\n",
 		       device->devinfo.devno, device->devinfo.irq);
-	len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
+	len += sprintf (page + len, KERN_ERR PRINTK_HEADER
 			"in req: %p CS: 0x%02X DS: 0x%02X\n",
 			req, stat->cstat, stat->dstat);
-	len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
-			"Failing CCW: %p\n", (void *) stat->cpa);
-        {
-            ccw1_t *act = req -> cpaddr;
-            int i = req -> cplength;
-            do {
-#ifdef ERP_DEBUB
-                printk ( KERN_INFO "CCW %p: %08X %08X\n", 
-                         act,((int*)act)[0],((int*)act)[1]);
-                printk ( KERN_INFO "DAT: %08X %08X %08X %08X\n", 
-                         ((int*)act->cda)[0],((int*)act->cda)[1],
-                         ((int*)act->cda)[2],((int*)act->cda)[3]);
-#endif /* ERP_DEBUG */
-                act ++;
-            } while ( --i );
-        }
+	len += sprintf (page + len, KERN_ERR PRINTK_HEADER
+			"Failing CCW: %p\n", (void *) (long) stat->cpa);
+	{
+		ccw1_t *act = req->cpaddr;
+		int i = req->cplength;
+		do {
+#ifdef ERP_DEBUG
+			printk (KERN_ERR "CCW %p: %08X %08X\n",
+				act, ((int *) act)[0], ((int *) act)[1]);
+			printk (KERN_ERR "DAT: %08X %08X %08X %08X\n",
+				((int *) act->cda)[0], ((int *) act->cda)[1],
+				((int *) act->cda)[2], ((int *) act->cda)[3]);
+#endif				/* ERP_DEBUG */
+			act++;
+		} while (--i);
+	}
 	if (stat->flag & DEVSTAT_FLAG_SENSE_AVAIL) {
 		for (sl = 0; sl < 4; sl++) {
-			len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
+			len += sprintf (page + len, KERN_ERR PRINTK_HEADER
 					"Sense(hex) %2d-%2d:",
-					(8 * sl),
-					((8 * sl) + 7));
+					(8 * sl), ((8 * sl) + 7));
 
 			for (sct = 0; sct < 8; sct++) {
 				len += sprintf (page + len, " %02x",
@@ -1325,22 +1293,29 @@
 
 		if (sense[27] & DASD_SENSE_BIT_0) {
 			/* 24 Byte Sense Data */
-			len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
-				     "24 Byte: %x MSG %x, %s MSGb to SYSOP\n",
+			len += sprintf (page + len, KERN_ERR PRINTK_HEADER
+					"24 Byte: %x MSG %x, %s MSGb to SYSOP\n",
 					sense[7] >> 4, sense[7] & 0x0f,
 					sense[1] & 0x10 ? "" : "no");
 		} else {
 			/* 32 Byte Sense Data */
-			len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
-				   "32 Byte: Format: %x Exception class %x\n",
+			len += sprintf (page + len, KERN_ERR PRINTK_HEADER
+					"32 Byte: Format: %x Exception class %x\n",
 					sense[6] & 0x0f, sense[22] >> 4);
 		}
 	}
-	return page;
+
+        printk ("Sense data:\n%s", 
+                page);
+
+        free_page ((unsigned long) page);
+        
+	return NULL;
 }
 
-dasd_discipline_t dasd_eckd_discipline =
-{
+
+dasd_discipline_t dasd_eckd_discipline = {
+        owner: THIS_MODULE,
 	name:"ECKD",
 	ebcname:"ECKD",
 	max_blocks:255,
@@ -1350,6 +1325,7 @@
 	do_analysis:dasd_eckd_do_analysis,
 	fill_geometry:dasd_eckd_fill_geometry,
 	start_IO:dasd_start_IO,
+	term_IO:dasd_term_IO,
 	format_device:dasd_eckd_format_device,
 	examine_error:dasd_eckd_examine_error,
 	erp_action:dasd_eckd_erp_action,
@@ -1359,7 +1335,8 @@
 	int_handler:dasd_int_handler,
 	reserve:dasd_eckd_reserve,
 	release:dasd_eckd_release,
-	merge_cp:dasd_eckd_merge_cp
+	merge_cp:dasd_eckd_merge_cp,
+	fill_info:dasd_eckd_fill_info,
 };
 
 int
@@ -1369,40 +1346,62 @@
 	printk (KERN_INFO PRINTK_HEADER
 		"%s discipline initializing\n", dasd_eckd_discipline.name);
 	ASCEBC (dasd_eckd_discipline.ebcname, 4);
-	dasd_discipline_enq (&dasd_eckd_discipline);
+	dasd_discipline_add (&dasd_eckd_discipline);
 #ifdef CONFIG_DASD_DYNAMIC
-        {
-	int i;
-	for (i = 0; i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t); i++) {
-                printk (KERN_INFO PRINTK_HEADER
-                        "We are interested in: CU %04X/%02x\n",
-			dasd_eckd_known_devices[i].ci.hc.ctype,
-			dasd_eckd_known_devices[i].ci.hc.cmode);
-		s390_device_register (&dasd_eckd_known_devices[i]);
-        }
-        }
+	{
+		int i;
+		for (i = 0;
+		     i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t);
+		     i++) {
+			printk (KERN_INFO PRINTK_HEADER
+				"We are interested in: CU %04X/%02x\n",
+				dasd_eckd_known_devices[i].ci.hc.ctype,
+				dasd_eckd_known_devices[i].ci.hc.cmode);
+			s390_device_register (&dasd_eckd_known_devices[i]);
+		}
+	}
 #endif				/* CONFIG_DASD_DYNAMIC */
 	return rc;
 }
 
 void
-dasd_eckd_cleanup( void ) {
-        printk ( KERN_INFO PRINTK_HEADER
-                 "%s discipline cleaning up\n", dasd_eckd_discipline.name);
+dasd_eckd_cleanup (void)
+{
+	printk (KERN_INFO PRINTK_HEADER
+		"%s discipline cleaning up\n", dasd_eckd_discipline.name);
 #ifdef CONFIG_DASD_DYNAMIC
-        {
-	int i;
-        for ( i=0; i<sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++) {
-		printk (KERN_INFO PRINTK_HEADER
-			"We were interested in: CU %04X/%02x\n",
-			dasd_eckd_known_devices[i].ci.hc.ctype,
-			dasd_eckd_known_devices[i].ci.hc.cmode);
-		s390_device_unregister(&dasd_eckd_known_devices[i]);
-	}
-        } 
-#endif /* CONFIG_DASD_DYNAMIC */
-        dasd_discipline_deq(&dasd_eckd_discipline);
+	{
+		int i;
+		for (i = 0;
+		     i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t);
+		     i++) {
+			printk (KERN_INFO PRINTK_HEADER
+				"We were interested in: CU %04X/%02x\n",
+				dasd_eckd_known_devices[i].ci.hc.ctype,
+				dasd_eckd_known_devices[i].ci.hc.cmode);
+			s390_device_unregister (&dasd_eckd_known_devices[i]);
+		}
+	}
+#endif				/* CONFIG_DASD_DYNAMIC */
+	dasd_discipline_del (&dasd_eckd_discipline);
 }
+
+#ifdef MODULE
+int
+init_module (void)
+{
+	int rc = 0;
+	rc = dasd_eckd_init ();
+	return rc;
+}
+
+void
+cleanup_module (void)
+{
+	dasd_eckd_cleanup ();
+	return;
+}
+#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)