patch-2.2.16 linux/drivers/s390/block/dasd_eckd.c
Next file: linux/drivers/s390/block/dasd_eckd_erp.c
Previous file: linux/drivers/s390/block/dasd_ccwstuff.h
Back to the patch index
Back to the overall index
- Lines: 383
- Date:
Wed Jun 7 14:26:43 2000
- Orig file:
v2.2.15/linux/drivers/s390/block/dasd_eckd.c
- Orig date:
Wed May 3 17:16:43 2000
diff -urN v2.2.15/linux/drivers/s390/block/dasd_eckd.c linux/drivers/s390/block/dasd_eckd.c
@@ -8,11 +8,10 @@
#include <linux/stddef.h>
#include <linux/kernel.h>
-#ifdef MODULE
-#include <linux/module.h>
-#endif /* MODULE */
-
#include <linux/malloc.h>
+#include <linux/dasd.h>
+#include <linux/hdreg.h> /* HDIO_GETGEO */
+
#include <asm/io.h>
#include <asm/irq.h>
@@ -20,8 +19,6 @@
#include "dasd_types.h"
#include "dasd_ccwstuff.h"
-#include "dasd.h"
-
#ifdef PRINTK_HEADER
#undef PRINTK_HEADER
#endif /* PRINTK_HEADER */
@@ -270,16 +267,7 @@
eckd_home_t;
-/* eckd count area */
-typedef struct {
- __u16 cyl;
- __u16 head;
- __u8 record;
- __u8 kl;
- __u16 dl;
-} __attribute__ ((packed))
-
-eckd_count_t;
+dasd_era_t dasd_eckd_erp_examine (cqr_t *, devstat_t *);
static unsigned int
round_up_multiple (unsigned int no, unsigned int mult)
@@ -401,7 +389,7 @@
memset (de_ccw, 0, sizeof (ccw1_t));
de_ccw->cmd_code = CCW_DEFINE_EXTENT;
de_ccw->count = 16;
- de_ccw->cda = (void *) virt_to_phys (data);
+ de_ccw->cda = (void *) __pa (data);
memset (data, 0, sizeof (DE_eckd_data_t));
switch (cmd) {
@@ -417,6 +405,7 @@
break;
case DASD_ECKD_CCW_WRITE:
case DASD_ECKD_CCW_WRITE_MT:
+ data->mask.perm = 0x02;
data->attributes.operation = 0x3; /* enable seq. caching */
break;
case DASD_ECKD_CCW_WRITE_CKD:
@@ -458,7 +447,7 @@
memset (lo_ccw, 0, sizeof (ccw1_t));
lo_ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
lo_ccw->count = 16;
- lo_ccw->cda = (void *) virt_to_phys (data);
+ lo_ccw->cda = (void *) __pa (data);
memset (data, 0, sizeof (LO_eckd_data_t));
switch (cmd) {
@@ -471,7 +460,7 @@
data->operation.operation = 0x16;
break;
case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
- data->operation.orientation = 0x3;
+ data->operation.orientation = 0x1;
data->operation.operation = 0x03;
data->count++;
break;
@@ -623,10 +612,10 @@
r0_data->record = 0;
r0_data->kl = 0;
r0_data->dl = 8;
- last_ccw->cmd_code = 0x03;
+ last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
last_ccw->count = 8;
last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI;
- last_ccw->cda = (void *) virt_to_phys (r0_data);
+ last_ccw->cda = (void *) __pa (r0_data);
last_ccw++;
}
/* write remaining records */
@@ -640,14 +629,14 @@
last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI;
last_ccw->count = 8;
- last_ccw->cda = (void *)
- virt_to_phys (ct_data + i);
+ last_ccw->cda = (void *) __pa (ct_data + i);
}
(last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC);
fcp -> devindex = di;
fcp -> flags = DASD_DO_IO_SLEEP;
do {
- struct wait_queue wait = {current, NULL};
+ struct wait_queue wait =
+ {current, NULL};
unsigned long flags;
int irq;
int cs;
@@ -698,15 +687,11 @@
int blk_per_trk = recs_per_track (&(info->rdc_data->eckd),
0, info->sizes.bp_block);
int byt_per_blk = info->sizes.bp_block;
- int noblk = req-> nr_sectors >> info->sizes.s2b_shift;
int btrk = (req->sector >> info->sizes.s2b_shift) / blk_per_trk;
int etrk = ((req->sector + req->nr_sectors - 1) >>
info->sizes.s2b_shift) / blk_per_trk;
-
- if ( ! noblk ) {
- PRINT_ERR("No blocks to write...returning\n");
- return NULL;
- }
+ int bhct;
+ long size;
if (req->cmd == READ) {
rw_cmd = DASD_ECKD_CCW_READ_MT;
@@ -724,7 +709,21 @@
}
#endif /* DASD_PARANOIA */
/* Build the request */
- rw_cp = request_cqr (2 + noblk,
+#if 0
+ PRINT_INFO ("req %d %d %d %d\n", devindex, req->cmd, req->sector, req->nr_sectors);
+#endif
+ /* 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++;
+ }
+
+ rw_cp = request_cqr (2 + bhct,
sizeof (DE_eckd_data_t) +
sizeof (LO_eckd_data_t));
if ( ! rw_cp ) {
@@ -743,58 +742,38 @@
req->nr_sectors >> info->sizes.s2b_shift,
rw_cmd, info);
ccw->flags = CCW_FLAG_CC;
- for (bh = req->bh; bh; bh = bh->b_reqnext) {
- long size;
+ for (bh = req->bh; bh != NULL;) {
+ if (bh->b_size > byt_per_blk) {
for (size = 0; size < bh->b_size; size += byt_per_blk) {
ccw++;
ccw->flags = CCW_FLAG_CC;
ccw->cmd_code = rw_cmd;
ccw->count = byt_per_blk;
- ccw->cda = (void *) virt_to_phys (bh->b_data + size);
+ ccw->cda = (void *) __pa (bh->b_data + size);
+ }
+ bh = bh->b_reqnext;
+ } else { /* group N bhs to fit into byt_per_blk */
+ for (size = 0; bh != NULL && size < byt_per_blk;) {
+ ccw++;
+ ccw->flags = CCW_FLAG_DC;
+ ccw->cmd_code = rw_cmd;
+ ccw->count = bh->b_size;
+ ccw->cda = (void *) __pa (bh->b_data);
+ size += bh->b_size;
+ bh = bh->b_reqnext;
+ }
+ if (size != byt_per_blk) {
+ PRINT_WARN ("Cannot fulfill small request %d vs. %d (%d sects)\n", size, byt_per_blk, req->nr_sectors);
+ release_cqr (rw_cp);
+ return NULL;
+ }
+ ccw->flags = CCW_FLAG_CC;
}
}
ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC);
return rw_cp;
}
-cqr_t *
-dasd_eckd_rw_label (int devindex, int rw, char *buffer)
-{
- int cmd_code = 0x03;
- dasd_information_t *info = dasd_info[devindex];
- cqr_t *cqr;
- ccw1_t *ccw;
-
- switch (rw) {
- case READ:
- cmd_code = DASD_ECKD_CCW_READ;
- break;
- case WRITE:
- cmd_code = DASD_ECKD_CCW_WRITE;
- break;
-#if DASD_PARANOIA > 2
- default:
- INTERNAL_ERROR ("unknown cmd %d", rw);
- return NULL;
-#endif /* DASD_PARANOIA */
- }
- cqr = request_cqr (3, sizeof (DE_eckd_data_t) +
- sizeof (LO_eckd_data_t));
- ccw = cqr->cpaddr;
- define_extent (ccw, cqr->data, 0, 0, cmd_code, info);
- ccw->flags |= CCW_FLAG_CC;
- ccw++;
- locate_record (ccw, cqr->data + 1, 0, 2, 1, cmd_code, info);
- ccw->flags |= CCW_FLAG_CC;
- ccw++;
- ccw->cmd_code = cmd_code;
- ccw->flags |= CCW_FLAG_SLI;
- ccw->count = sizeof (dasd_volume_label_t);
- ccw->cda = (void *) virt_to_phys ((void *) buffer);
- return cqr;
-
-}
-
void
dasd_eckd_print_char (dasd_characteristics_t * i)
{
@@ -886,27 +865,23 @@
return rc;
}
-int
-dasd_eckd_read_count (int di)
+cqr_t *
+dasd_eckd_fill_sizes_first (int di)
{
- int rc;
cqr_t *rw_cp = NULL;
ccw1_t *ccw;
DE_eckd_data_t *DE_data;
LO_eckd_data_t *LO_data;
- eckd_count_t *count_data;
- int retries = 5;
- unsigned long flags;
- int irq;
- int cs;
dasd_information_t *info = dasd_info[di];
+ eckd_count_t *count_data = &(info->private.eckd.count_data);
+
+ dasd_info[di]->sizes.label_block = 2;
+
rw_cp = request_cqr (3,
sizeof (DE_eckd_data_t) +
- sizeof (LO_eckd_data_t) +
- sizeof (eckd_count_t));
+ sizeof (LO_eckd_data_t));
DE_data = rw_cp->data;
LO_data = rw_cp->data + sizeof (DE_eckd_data_t);
- count_data = (eckd_count_t*)((long)LO_data + sizeof (LO_eckd_data_t));
ccw = rw_cp->cpaddr;
define_extent (ccw, DE_data, 0, 0, DASD_ECKD_CCW_READ_COUNT, info);
ccw->flags = CCW_FLAG_CC;
@@ -916,43 +891,18 @@
ccw++;
ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
ccw->count = 8;
- ccw->cda = (void *) virt_to_phys (count_data);
+ ccw->cda = (void *) __pa (count_data);
rw_cp->devindex = di;
- rw_cp -> options = DOIO_WAIT_FOR_INTERRUPT;
- do {
- irq = dasd_info[di]->info.irq;
- s390irq_spin_lock_irqsave (irq, flags);
- atomic_set(&rw_cp -> status, CQR_STATUS_QUEUED);
- rc = dasd_start_IO ( rw_cp );
- s390irq_spin_unlock_irqrestore (irq, flags);
- retries --;
- cs = atomic_read(&rw_cp->status);
- if ( cs != CQR_STATUS_DONE && retries == 5 ) {
- dasd_eckd_print_error(rw_cp->dstat);
- }
- } while ( ( ( cs != CQR_STATUS_DONE) || rc ) && retries );
- if ( ( rc || cs != CQR_STATUS_DONE) ) {
- if ( ( cs == CQR_STATUS_ERROR ) &&
- ( rw_cp -> dstat -> ii.sense.data[1] == 0x08 ) ) {
- rc = -EMEDIUMTYPE;
- } else {
- dasd_eckd_print_error (rw_cp->dstat);
- rc = -EIO;
- }
- } else {
- rc = count_data->dl;
- }
- release_cqr (rw_cp);
- return rc;
+ atomic_set (&rw_cp->status, CQR_STATUS_FILLED);
+ return rw_cp;
}
int
-dasd_eckd_fill_sizes (int devindex)
+dasd_eckd_fill_sizes_last (int devindex)
{
- int bs = 0;
- int sb;
+ int sb,rpt;
dasd_information_t *in = dasd_info[devindex];
- bs = dasd_eckd_read_count (devindex);
+ int bs = in->private.eckd.count_data.dl;
if (bs <= 0) {
PRINT_INFO("Cannot figure out blocksize. did you format the disk?\n");
memset (&(in -> sizes), 0, sizeof(dasd_sizes_t ));
@@ -962,10 +912,10 @@
}
in->sizes.bp_sector = in->sizes.bp_block;
- in->sizes.b2k_shift = 0; /* bits to shift a block to get 1k */
- for (sb = 1024; sb < bs; sb = sb << 1)
- in->sizes.b2k_shift++;
-
+ if (bs & 511) {
+ PRINT_INFO ("Probably no Linux formatted device!\n");
+ return -EMEDIUMTYPE;
+ }
in->sizes.s2b_shift = 0; /* bits to shift 512 to get a block */
for (sb = 512; sb < bs; sb = sb << 1)
in->sizes.s2b_shift++;
@@ -973,26 +923,42 @@
in->sizes.blocks = in->rdc_data->eckd.no_cyl *
in->rdc_data->eckd.trk_per_cyl *
recs_per_track (&(in->rdc_data->eckd), 0, bs);
- in->sizes.kbytes = in->sizes.blocks << in->sizes.b2k_shift;
+
+ in->sizes.kbytes = ( in->sizes.blocks << in->sizes.s2b_shift) >> 1;
+
+ rpt = recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block),
PRINT_INFO ("Verified: %d B/trk %d B/Blk(%d B) %d Blks/trk %d kB/trk \n",
bytes_per_track (&(in->rdc_data->eckd)),
- bytes_per_record (&(in->rdc_data->eckd), 0, in->sizes.bp_block),
+ bytes_per_record (&(in->rdc_data->eckd), 0,
+ in->sizes.bp_block),
in->sizes.bp_block,
- recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block),
- (recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block) <<
- in->sizes.b2k_shift ));
+ rpt,
+ (rpt << in->sizes.s2b_shift) >> 1);
return 0;
}
+void
+dasd_eckd_fill_geometry (int di, struct hd_geometry *geo)
+{
+ dasd_information_t *info = dasd_info[di];
+ geo->cylinders = info->rdc_data->eckd.no_cyl;
+ geo->heads = info->rdc_data->eckd.trk_per_cyl;
+ geo->sectors = recs_per_track (&(info->rdc_data->eckd),
+ 0, info->sizes.bp_block);
+ geo->start = info->sizes.label_block + 1;
+}
+
dasd_operations_t dasd_eckd_operations =
{
- dasd_eckd_ck_devinfo,
- dasd_eckd_build_req,
- dasd_eckd_rw_label,
- dasd_eckd_ck_char,
- dasd_eckd_fill_sizes,
- dasd_eckd_format,
+ ck_devinfo:dasd_eckd_ck_devinfo,
+ get_req_ccw:dasd_eckd_build_req,
+ ck_characteristics:dasd_eckd_ck_char,
+ fill_sizes_first:dasd_eckd_fill_sizes_first,
+ fill_sizes_last:dasd_eckd_fill_sizes_last,
+ dasd_format:dasd_eckd_format,
+ fill_geometry:dasd_eckd_fill_geometry,
+ erp_examine:dasd_eckd_erp_examine
};
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)