|
@@ -159,6 +159,14 @@ recs_per_track(struct dasd_eckd_characteristics * rdc,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void set_ch_t(struct ch_t *geo, __u32 cyl, __u8 head)
|
|
|
+{
|
|
|
+ geo->cyl = (__u16) cyl;
|
|
|
+ geo->head = cyl >> 16;
|
|
|
+ geo->head <<= 4;
|
|
|
+ geo->head |= head;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
check_XRC (struct ccw1 *de_ccw,
|
|
|
struct DE_eckd_data *data,
|
|
@@ -186,11 +194,12 @@ check_XRC (struct ccw1 *de_ccw,
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
|
|
|
- int totrk, int cmd, struct dasd_device * device)
|
|
|
+define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk,
|
|
|
+ unsigned int totrk, int cmd, struct dasd_device *device)
|
|
|
{
|
|
|
struct dasd_eckd_private *private;
|
|
|
- struct ch_t geo, beg, end;
|
|
|
+ u32 begcyl, endcyl;
|
|
|
+ u16 heads, beghead, endhead;
|
|
|
int rc = 0;
|
|
|
|
|
|
private = (struct dasd_eckd_private *) device->private;
|
|
@@ -248,27 +257,24 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
|
|
|
&& !(private->uses_cdl && trk < 2))
|
|
|
data->ga_extended |= 0x40; /* Regular Data Format Mode */
|
|
|
|
|
|
- geo.cyl = private->rdc_data.no_cyl;
|
|
|
- geo.head = private->rdc_data.trk_per_cyl;
|
|
|
- beg.cyl = trk / geo.head;
|
|
|
- beg.head = trk % geo.head;
|
|
|
- end.cyl = totrk / geo.head;
|
|
|
- end.head = totrk % geo.head;
|
|
|
+ heads = private->rdc_data.trk_per_cyl;
|
|
|
+ begcyl = trk / heads;
|
|
|
+ beghead = trk % heads;
|
|
|
+ endcyl = totrk / heads;
|
|
|
+ endhead = totrk % heads;
|
|
|
|
|
|
/* check for sequential prestage - enhance cylinder range */
|
|
|
if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
|
|
|
data->attributes.operation == DASD_SEQ_ACCESS) {
|
|
|
|
|
|
- if (end.cyl + private->attrib.nr_cyl < geo.cyl)
|
|
|
- end.cyl += private->attrib.nr_cyl;
|
|
|
+ if (endcyl + private->attrib.nr_cyl < private->real_cyl)
|
|
|
+ endcyl += private->attrib.nr_cyl;
|
|
|
else
|
|
|
- end.cyl = (geo.cyl - 1);
|
|
|
+ endcyl = (private->real_cyl - 1);
|
|
|
}
|
|
|
|
|
|
- data->beg_ext.cyl = beg.cyl;
|
|
|
- data->beg_ext.head = beg.head;
|
|
|
- data->end_ext.cyl = end.cyl;
|
|
|
- data->end_ext.head = end.head;
|
|
|
+ set_ch_t(&data->beg_ext, begcyl, beghead);
|
|
|
+ set_ch_t(&data->end_ext, endcyl, endhead);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -294,13 +300,14 @@ static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata,
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk,
|
|
|
- int totrk, int cmd, struct dasd_device *basedev,
|
|
|
- struct dasd_device *startdev)
|
|
|
+static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata,
|
|
|
+ unsigned int trk, unsigned int totrk, int cmd,
|
|
|
+ struct dasd_device *basedev, struct dasd_device *startdev)
|
|
|
{
|
|
|
struct dasd_eckd_private *basepriv, *startpriv;
|
|
|
struct DE_eckd_data *data;
|
|
|
- struct ch_t geo, beg, end;
|
|
|
+ u32 begcyl, endcyl;
|
|
|
+ u16 heads, beghead, endhead;
|
|
|
int rc = 0;
|
|
|
|
|
|
basepriv = (struct dasd_eckd_private *) basedev->private;
|
|
@@ -374,33 +381,30 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk,
|
|
|
&& !(basepriv->uses_cdl && trk < 2))
|
|
|
data->ga_extended |= 0x40; /* Regular Data Format Mode */
|
|
|
|
|
|
- geo.cyl = basepriv->rdc_data.no_cyl;
|
|
|
- geo.head = basepriv->rdc_data.trk_per_cyl;
|
|
|
- beg.cyl = trk / geo.head;
|
|
|
- beg.head = trk % geo.head;
|
|
|
- end.cyl = totrk / geo.head;
|
|
|
- end.head = totrk % geo.head;
|
|
|
+ heads = basepriv->rdc_data.trk_per_cyl;
|
|
|
+ begcyl = trk / heads;
|
|
|
+ beghead = trk % heads;
|
|
|
+ endcyl = totrk / heads;
|
|
|
+ endhead = totrk % heads;
|
|
|
|
|
|
/* check for sequential prestage - enhance cylinder range */
|
|
|
if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
|
|
|
data->attributes.operation == DASD_SEQ_ACCESS) {
|
|
|
|
|
|
- if (end.cyl + basepriv->attrib.nr_cyl < geo.cyl)
|
|
|
- end.cyl += basepriv->attrib.nr_cyl;
|
|
|
+ if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl)
|
|
|
+ endcyl += basepriv->attrib.nr_cyl;
|
|
|
else
|
|
|
- end.cyl = (geo.cyl - 1);
|
|
|
+ endcyl = (basepriv->real_cyl - 1);
|
|
|
}
|
|
|
|
|
|
- data->beg_ext.cyl = beg.cyl;
|
|
|
- data->beg_ext.head = beg.head;
|
|
|
- data->end_ext.cyl = end.cyl;
|
|
|
- data->end_ext.head = end.head;
|
|
|
+ set_ch_t(&data->beg_ext, begcyl, beghead);
|
|
|
+ set_ch_t(&data->end_ext, endcyl, endhead);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
|
|
|
- int rec_on_trk, int no_rec, int cmd,
|
|
|
+locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk,
|
|
|
+ unsigned int rec_on_trk, int no_rec, int cmd,
|
|
|
struct dasd_device * device, int reclen)
|
|
|
{
|
|
|
struct dasd_eckd_private *private;
|
|
@@ -493,10 +497,11 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
|
|
|
default:
|
|
|
DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
|
|
|
}
|
|
|
- data->seek_addr.cyl = data->search_arg.cyl =
|
|
|
- trk / private->rdc_data.trk_per_cyl;
|
|
|
- data->seek_addr.head = data->search_arg.head =
|
|
|
- trk % private->rdc_data.trk_per_cyl;
|
|
|
+ set_ch_t(&data->seek_addr,
|
|
|
+ trk / private->rdc_data.trk_per_cyl,
|
|
|
+ trk % private->rdc_data.trk_per_cyl);
|
|
|
+ data->search_arg.cyl = data->seek_addr.cyl;
|
|
|
+ data->search_arg.head = data->seek_addr.head;
|
|
|
data->search_arg.record = rec_on_trk;
|
|
|
}
|
|
|
|
|
@@ -1002,13 +1007,20 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
|
|
|
"rc=%d", rc);
|
|
|
goto out_err3;
|
|
|
}
|
|
|
+ /* find the vaild cylinder size */
|
|
|
+ if (private->rdc_data.no_cyl == LV_COMPAT_CYL &&
|
|
|
+ private->rdc_data.long_no_cyl)
|
|
|
+ private->real_cyl = private->rdc_data.long_no_cyl;
|
|
|
+ else
|
|
|
+ private->real_cyl = private->rdc_data.no_cyl;
|
|
|
+
|
|
|
DEV_MESSAGE(KERN_INFO, device,
|
|
|
"%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
|
|
|
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->real_cyl,
|
|
|
private->rdc_data.trk_per_cyl,
|
|
|
private->rdc_data.sec_per_trk);
|
|
|
return 0;
|
|
@@ -1157,8 +1169,6 @@ dasd_eckd_end_analysis(struct dasd_block *block)
|
|
|
}
|
|
|
|
|
|
private->uses_cdl = 1;
|
|
|
- /* Calculate number of blocks/records per track. */
|
|
|
- blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block);
|
|
|
/* Check Track 0 for Compatible Disk Layout */
|
|
|
count_area = NULL;
|
|
|
for (i = 0; i < 3; i++) {
|
|
@@ -1200,14 +1210,14 @@ dasd_eckd_end_analysis(struct dasd_block *block)
|
|
|
block->s2b_shift++;
|
|
|
|
|
|
blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block);
|
|
|
- block->blocks = (private->rdc_data.no_cyl *
|
|
|
+ block->blocks = (private->real_cyl *
|
|
|
private->rdc_data.trk_per_cyl *
|
|
|
blk_per_trk);
|
|
|
|
|
|
DEV_MESSAGE(KERN_INFO, device,
|
|
|
"(%dkB blks): %dkB at %dkB/trk %s",
|
|
|
(block->bp_block >> 10),
|
|
|
- ((private->rdc_data.no_cyl *
|
|
|
+ ((private->real_cyl *
|
|
|
private->rdc_data.trk_per_cyl *
|
|
|
blk_per_trk * (block->bp_block >> 9)) >> 1),
|
|
|
((blk_per_trk * block->bp_block) >> 10),
|
|
@@ -1262,7 +1272,8 @@ dasd_eckd_format_device(struct dasd_device * device,
|
|
|
struct eckd_count *ect;
|
|
|
struct ccw1 *ccw;
|
|
|
void *data;
|
|
|
- int rpt, cyl, head;
|
|
|
+ int rpt;
|
|
|
+ struct ch_t address;
|
|
|
int cplength, datasize;
|
|
|
int i;
|
|
|
int intensity = 0;
|
|
@@ -1270,24 +1281,25 @@ dasd_eckd_format_device(struct dasd_device * device,
|
|
|
|
|
|
private = (struct dasd_eckd_private *) device->private;
|
|
|
rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
|
|
|
- cyl = fdata->start_unit / private->rdc_data.trk_per_cyl;
|
|
|
- head = fdata->start_unit % private->rdc_data.trk_per_cyl;
|
|
|
+ set_ch_t(&address,
|
|
|
+ fdata->start_unit / private->rdc_data.trk_per_cyl,
|
|
|
+ fdata->start_unit % private->rdc_data.trk_per_cyl);
|
|
|
|
|
|
/* Sanity checks. */
|
|
|
if (fdata->start_unit >=
|
|
|
- (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) {
|
|
|
- DEV_MESSAGE(KERN_INFO, device, "Track no %d too big!",
|
|
|
+ (private->real_cyl * private->rdc_data.trk_per_cyl)) {
|
|
|
+ DEV_MESSAGE(KERN_INFO, device, "Track no %u too big!",
|
|
|
fdata->start_unit);
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
}
|
|
|
if (fdata->start_unit > fdata->stop_unit) {
|
|
|
- DEV_MESSAGE(KERN_INFO, device, "Track %d reached! ending.",
|
|
|
+ DEV_MESSAGE(KERN_INFO, device, "Track %u reached! ending.",
|
|
|
fdata->start_unit);
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
}
|
|
|
if (dasd_check_blocksize(fdata->blksize) != 0) {
|
|
|
DEV_MESSAGE(KERN_WARNING, device,
|
|
|
- "Invalid blocksize %d...terminating!",
|
|
|
+ "Invalid blocksize %u...terminating!",
|
|
|
fdata->blksize);
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
}
|
|
@@ -1389,8 +1401,8 @@ dasd_eckd_format_device(struct dasd_device * device,
|
|
|
if (intensity & 0x01) { /* write record zero */
|
|
|
ect = (struct eckd_count *) data;
|
|
|
data += sizeof(struct eckd_count);
|
|
|
- ect->cyl = cyl;
|
|
|
- ect->head = head;
|
|
|
+ ect->cyl = address.cyl;
|
|
|
+ ect->head = address.head;
|
|
|
ect->record = 0;
|
|
|
ect->kl = 0;
|
|
|
ect->dl = 8;
|
|
@@ -1404,8 +1416,8 @@ dasd_eckd_format_device(struct dasd_device * device,
|
|
|
if ((intensity & ~0x08) & 0x04) { /* erase track */
|
|
|
ect = (struct eckd_count *) data;
|
|
|
data += sizeof(struct eckd_count);
|
|
|
- ect->cyl = cyl;
|
|
|
- ect->head = head;
|
|
|
+ ect->cyl = address.cyl;
|
|
|
+ ect->head = address.head;
|
|
|
ect->record = 1;
|
|
|
ect->kl = 0;
|
|
|
ect->dl = 0;
|
|
@@ -1418,8 +1430,8 @@ dasd_eckd_format_device(struct dasd_device * device,
|
|
|
for (i = 0; i < rpt; i++) {
|
|
|
ect = (struct eckd_count *) data;
|
|
|
data += sizeof(struct eckd_count);
|
|
|
- ect->cyl = cyl;
|
|
|
- ect->head = head;
|
|
|
+ ect->cyl = address.cyl;
|
|
|
+ ect->head = address.head;
|
|
|
ect->record = i + 1;
|
|
|
ect->kl = 0;
|
|
|
ect->dl = fdata->blksize;
|