patch-2.4.4 linux/drivers/s390/block/dasd_eckd.c
Next file: linux/drivers/s390/block/dasd_eckd.h
Previous file: linux/drivers/s390/block/dasd_diag.c
Back to the patch index
Back to the overall index
- Lines: 769
- Date:
Wed Apr 11 19:02:28 2001
- Orig file:
v2.4.3/linux/drivers/s390/block/dasd_eckd.c
- Orig date:
Tue Feb 13 14:13:44 2001
diff -u --recursive --new-file v2.4.3/linux/drivers/s390/block/dasd_eckd.c linux/drivers/s390/block/dasd_eckd.c
@@ -15,6 +15,8 @@
* 10/10/00 reverted last change according to ESS exploitation
* 10/10/00 now dequeuing init_cqr before freeing *ouch*
* 26/10/00 fixed ITPM20144ASC (problems when accesing a device formatted by VIF)
+ * 01/23/01 fixed kmalloc statement in dump_sense to be GFP_ATOMIC
+ * fixed partition handling and HDIO_GETGEO
*/
#include <linux/config.h>
@@ -40,6 +42,8 @@
#undef PRINTK_HEADER
#endif /* PRINTK_HEADER */
#define PRINTK_HEADER DASD_NAME"(eckd): "
+#undef DASD_CDL // Support compatible disk layout
+#undef CDL_PRINTK
#define ECKD_C0(i) (i->home_bytes)
#define ECKD_F(i) (i->formula)
@@ -52,36 +56,21 @@
#define ECKD_F7(i) (i->factor7)
#define ECKD_F8(i) (i->factor8)
-#define DASD_ECKD_CCW_WRITE 0x05
-#define DASD_ECKD_CCW_READ 0x06
-#define DASD_ECKD_CCW_WRITE_HOME_ADDRESS 0x09
-#define DASD_ECKD_CCW_READ_HOME_ADDRESS 0x0a
-#define DASD_ECKD_CCW_WRITE_KD 0x0d
-#define DASD_ECKD_CCW_READ_KD 0x0e
-#define DASD_ECKD_CCW_READ_COUNT 0x12
-#define DASD_ECKD_CCW_WRITE_RECORD_ZERO 0x15
-#define DASD_ECKD_CCW_READ_RECORD_ZERO 0x16
-#define DASD_ECKD_CCW_WRITE_CKD 0x1d
-#define DASD_ECKD_CCW_READ_CKD 0x1e
-#define DASD_ECKD_CCW_LOCATE_RECORD 0x47
-#define DASD_ECKD_CCW_DEFINE_EXTENT 0x63
-#define DASD_ECKD_CCW_WRITE_MT 0x85
-#define DASD_ECKD_CCW_READ_MT 0x86
-#define DASD_ECKD_CCW_WRITE_KD_MT 0x8d
-#define DASD_ECKD_CCW_READ_KD_MT 0x8e
-#define DASD_ECKD_CCW_RELEASE 0x94
-#define DASD_ECKD_CCW_READ_CKD_MT 0x9e
-#define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d
-#define DASD_ECKD_CCW_RESERVE 0xB4
-
dasd_discipline_t dasd_eckd_discipline;
typedef struct
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
} dasd_eckd_private_t;
#ifdef CONFIG_DASD_DYNAMIC
@@ -91,27 +80,38 @@
{
ci:
{hc:
- {ctype:0x3990, dtype:0x3390}},
- flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+ {ctype:0x3990}},
+ flag: (DEVREG_MATCH_CU_TYPE |
+ DEVREG_NO_DEV_INFO|
+ DEVREG_TYPE_DEVCHARS),
oper_func:dasd_oper_handler
},
{
ci:
{hc:
- {ctype:0x3990, dtype:0x3380}},
- flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+ {ctype:0x2105}},
+ flag:(DEVREG_MATCH_CU_TYPE |
+ DEVREG_NO_DEV_INFO|
+ DEVREG_TYPE_DEVCHARS),
oper_func:dasd_oper_handler
},
{
ci:
{hc:
- {ctype:0x9343, dtype:0x9345}},
- flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+ {ctype:0x9343}},
+ flag:(DEVREG_MATCH_CU_TYPE |
+ DEVREG_NO_DEV_INFO|
+ DEVREG_TYPE_DEVCHARS),
oper_func:dasd_oper_handler
}
};
#endif
+#ifdef DASD_CDL
+int sizes_trk0[]={28,148,84};
+#define LABEL_SIZE 140
+#endif
+
static inline unsigned int
round_up_multiple (unsigned int no, unsigned int mult)
{
@@ -210,6 +210,7 @@
return rpt;
}
+
static inline void
define_extent (ccw1_t * de_ccw,
DE_eckd_data_t * data,
@@ -269,7 +270,11 @@
break;
}
data->attributes.mode = 0x3;
- if (private->rdc_data.cu_type == 0x2105) {
+ if (private->rdc_data.cu_type == 0x2105
+#ifdef DASD_CDL
+ && !(private->uses_cdl && trk < 2)
+#endif
+ ) {
data->reserved |= 0x40;
}
data->beg_ext.cyl = beg.cyl;
@@ -296,6 +301,9 @@
{trk / (geo.head), trk % (geo.head)};
int sector;
+#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);
+#endif
memset (lo_ccw, 0, sizeof (ccw1_t));
lo_ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
lo_ccw->count = 16;
@@ -411,13 +419,14 @@
"Null device pointer passed to characteristics checker\n");
return -ENODEV;
}
+ if (device->private != NULL) {
+ kfree(device->private);
+ }
+ device->private = kmalloc (sizeof (dasd_eckd_private_t), GFP_KERNEL);
if (device->private == NULL) {
- 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;
- }
+ 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);
@@ -468,6 +477,22 @@
return 0;
}
+#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;
+}
+#endif
+
static ccw_req_t *
dasd_eckd_init_analysis (struct dasd_device_t *device)
{
@@ -476,9 +501,20 @@
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);
-
- cqr = ccw_alloc_request (dasd_eckd_discipline.name, 3 + 1, sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t));
+#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
if (cqr == NULL) {
printk (KERN_WARNING PRINTK_HEADER
"No memory to allocate initialization request\n");
@@ -489,72 +525,159 @@
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
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
ccw->flags |= CCW_FLAG_CC;
ccw++;
ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
ccw->count = 8;
- set_normalized_cda (ccw, __pa (count_data));
+ 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));
cqr->device = device;
cqr->retries = 0;
cqr->status = CQR_STATUS_FILLED;
-
return cqr;
}
static int
dasd_eckd_do_analysis (struct dasd_device_t *device)
{
- int rc = 0;
int sb, rpt;
dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
- int bs = private->count_area.dl;
-
+ 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!");
+ }
+ }
+ 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 (bs) {
+ switch (private->count_area.dl) {
case 512:
case 1024:
case 2048:
case 4096:
- device->sizes.bp_block = bs;
+ device->sizes.bp_block = private->count_area.dl;
break;
- default:
- printk (KERN_INFO PRINTK_HEADER
- "/dev/%s (%04X): invalid blocksize %d\n"
- KERN_INFO PRINTK_HEADER
- "/dev/%s (%04X): capacity (at 4kB blks): %dkB at %dkB/trk\n",
- device->name, device->devinfo.devno, bs,
- device->name, device->devinfo.devno,
- (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl *
- recs_per_track (&private->rdc_data, 0, 4096)),
- recs_per_track (&private->rdc_data, 0, 4096));
- 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 */
- for (sb = 512; sb < bs; sb = sb << 1)
+ 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));
-
- printk (KERN_INFO PRINTK_HEADER
- "/dev/%s (%04X): capacity (%dkB blks): %dkB at %dkB/trk\n",
- device->name, device->devinfo.devno,
- (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);
+ 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);
return 0;
-
- return rc;
}
static int
@@ -574,7 +697,6 @@
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);
- geo->start = 2;
return rc;
}
@@ -600,6 +722,9 @@
int head = trk % 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)) ||
@@ -623,7 +748,15 @@
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;
break;
+#endif
default:
printk (KERN_WARNING PRINTK_HEADER "Invalid flags 0x%x...terminating!\n", flags);
return NULL;
@@ -678,6 +811,7 @@
switch (flags) {
case 0x03:
+ case 0x0b:
define_extent (last_ccw, DE_data, trk, trk,
DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device);
last_ccw->flags |= CCW_FLAG_CC;
@@ -688,6 +822,7 @@
last_ccw++;
break;
case 0x01:
+ case 0x09:
define_extent (last_ccw, DE_data, trk, trk,
DASD_ECKD_CCW_WRITE_RECORD_ZERO, device);
last_ccw->flags |= CCW_FLAG_CC;
@@ -699,6 +834,7 @@
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;
@@ -710,6 +846,7 @@
last_ccw++;
break;
case 0x04:
+ case 0x0c:
define_extent (last_ccw, DE_data, trk, trk,
DASD_ECKD_CCW_WRITE_CKD, device);
last_ccw->flags |= CCW_FLAG_CC;
@@ -747,7 +884,29 @@
(ct_data + i)->head = head;
(ct_data + i)->record = i + 1;
(ct_data + i)->kl = 0;
- (ct_data + i)->dl = bs;
+#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;
last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI;
last_ccw->count = 8;
@@ -791,7 +950,7 @@
switch (device->devinfo.sid_data.cu_type) {
case 0x3990:
case 0x2105:
- /* return dasd_3990_erp_action; */
+ return dasd_3990_erp_action;
case 0x9343:
/* Return dasd_9343_erp_action; */
default:
@@ -802,13 +961,42 @@
static dasd_erp_postaction_fn_t
dasd_eckd_erp_postaction (ccw_req_t * cqr)
{
- if (cqr->function != default_erp_action)
- printk (KERN_WARNING PRINTK_HEADER
- "unknown ERP action [<%p>]\n",
- cqr->function);
return 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
+}
+#endif
+
static ccw_req_t *
dasd_eckd_build_cp_from_req (dasd_device_t * device, struct request *req)
{
@@ -826,6 +1014,11 @@
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
if (req->cmd == READ) {
rw_cmd = DASD_ECKD_CCW_READ_MT;
@@ -845,43 +1038,123 @@
else
bhct++;
}
-
+#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,
+ 2 + nlocs + bhct + 1,
+ sizeof (DE_eckd_data_t) +
+ (1+nlocs)*sizeof (LO_eckd_data_t));
+#endif
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);
+ locate_record (ccw, LO_data, btrk, (req->sector >> shift) % blk_per_trk + 1,
+ req->nr_sectors >> shift, rw_cmd, device, device->sizes.bp_block);
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) {
+ /* 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,
+ 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 = byt_per_blk;
- set_normalized_cda (ccw, __pa (bh->b_data + size));
+ 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 {
+ // 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;
+ }
+#endif
ccw++;
+#ifndef DASD_CDL
ccw->flags |= CCW_FLAG_DC;
- ccw->cmd_code = rw_cmd;
+ 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",
@@ -1000,14 +1273,13 @@
ccw_req_t *
dasd_eckd_merge_cp ( dasd_device_t *device )
{
- ccw_req_t * cqr;
return NULL;
}
static char *
dasd_eckd_dump_sense (struct dasd_device_t *device, ccw_req_t * req)
{
- char *page = (char *) get_free_page (GFP_KERNEL);
+ char *page = (char *) get_free_page (GFP_ATOMIC);
devstat_t *stat = &device->dev_status;
char *sense = stat->ii.sense.data;
int len, sl, sct;
@@ -1027,13 +1299,13 @@
ccw1_t *act = req -> cpaddr;
int i = req -> cplength;
do {
-#if 0
+#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
+#endif /* ERP_DEBUG */
act ++;
} while ( --i );
}
@@ -1071,6 +1343,7 @@
{
name:"ECKD",
ebcname:"ECKD",
+ max_blocks:255,
id_check:dasd_eckd_id_check,
check_characteristics:dasd_eckd_check_characteristics,
init_analysis:dasd_eckd_init_analysis,
@@ -1101,14 +1374,12 @@
{
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 DEV: %04X/%02Xi\n",
+ 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,
- dasd_eckd_known_devices[i].ci.hc.dtype,
- dasd_eckd_known_devices[i].ci.hc.dmode);
+ dasd_eckd_known_devices[i].ci.hc.cmode);
s390_device_register (&dasd_eckd_known_devices[i]);
- }
+ }
}
#endif /* CONFIG_DASD_DYNAMIC */
return rc;
@@ -1123,12 +1394,10 @@
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 DEV: %04X/%02Xi\n",
+ "We were interested in: CU %04X/%02x\n",
dasd_eckd_known_devices[i].ci.hc.ctype,
- dasd_eckd_known_devices[i].ci.hc.cmode,
- dasd_eckd_known_devices[i].ci.hc.dtype,
- dasd_eckd_known_devices[i].ci.hc.dmode);
- s390_device_register(&dasd_eckd_known_devices[i]);
+ dasd_eckd_known_devices[i].ci.hc.cmode);
+ s390_device_unregister(&dasd_eckd_known_devices[i]);
}
}
#endif /* CONFIG_DASD_DYNAMIC */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)