vserver 1.9.3
[linux-2.6.git] / drivers / s390 / block / dasd_eckd.c
1 /* 
2  * File...........: linux/drivers/s390/block/dasd_eckd.c
3  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
4  *                  Horst Hummel <Horst.Hummel@de.ibm.com> 
5  *                  Carsten Otte <Cotte@de.ibm.com>
6  *                  Martin Schwidefsky <schwidefsky@de.ibm.com>
7  * Bugreports.to..: <Linux390@de.ibm.com>
8  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
9  *
10  * $Revision: 1.61 $
11  */
12
13 #include <linux/config.h>
14 #include <linux/stddef.h>
15 #include <linux/kernel.h>
16 #include <linux/slab.h>
17 #include <linux/hdreg.h>        /* HDIO_GETGEO                      */
18 #include <linux/bio.h>
19 #include <linux/module.h>
20 #include <linux/init.h>
21
22 #include <asm/debug.h>
23 #include <asm/idals.h>
24 #include <asm/ebcdic.h>
25 #include <asm/io.h>
26 #include <asm/todclk.h>
27 #include <asm/uaccess.h>
28 #include <asm/ccwdev.h>
29
30 #include "dasd_int.h"
31 #include "dasd_eckd.h"
32
33 #ifdef PRINTK_HEADER
34 #undef PRINTK_HEADER
35 #endif                          /* PRINTK_HEADER */
36 #define PRINTK_HEADER "dasd(eckd):"
37
38 #define ECKD_C0(i) (i->home_bytes)
39 #define ECKD_F(i) (i->formula)
40 #define ECKD_F1(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f1):(i->factors.f_0x02.f1))
41 #define ECKD_F2(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f2):(i->factors.f_0x02.f2))
42 #define ECKD_F3(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f3):(i->factors.f_0x02.f3))
43 #define ECKD_F4(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f4):0)
44 #define ECKD_F5(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f5):0)
45 #define ECKD_F6(i) (i->factor6)
46 #define ECKD_F7(i) (i->factor7)
47 #define ECKD_F8(i) (i->factor8)
48
49 MODULE_LICENSE("GPL");
50
51 static struct dasd_discipline dasd_eckd_discipline;
52
53 struct dasd_eckd_private {
54         struct dasd_eckd_characteristics rdc_data;
55         struct dasd_eckd_confdata conf_data;
56         struct eckd_count count_area[5];
57         int init_cqr_status;
58         int uses_cdl;
59         struct attrib_data_t attrib;    /* e.g. cache operations */
60 };
61
62 /* The ccw bus type uses this table to find devices that it sends to
63  * dasd_eckd_probe */
64 static struct ccw_device_id dasd_eckd_ids[] = {
65         { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), driver_info: 0x1},
66         { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), driver_info: 0x2},
67         { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), driver_info: 0x3},
68         { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), driver_info: 0x4},
69         { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), driver_info: 0x5},
70         { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), driver_info: 0x6},
71         { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3390, 0), driver_info: 0x7},
72         { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3380, 0), driver_info: 0x8},
73         { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3390, 0), driver_info: 0x9},
74         { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3380, 0), driver_info: 0xa},
75         { /* end of list */ },
76 };
77
78 MODULE_DEVICE_TABLE(ccw, dasd_eckd_ids);
79
80 static struct ccw_driver dasd_eckd_driver; /* see below */
81
82 /* initial attempt at a probe function. this can be simplified once
83  * the other detection code is gone */
84 static int
85 dasd_eckd_probe (struct ccw_device *cdev)
86 {
87         int ret;
88
89         ret = dasd_generic_probe (cdev, &dasd_eckd_discipline);
90         if (ret)
91                 return ret;
92         ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE);
93         return 0;
94 }
95
96 static int
97 dasd_eckd_set_online(struct ccw_device *cdev)
98 {
99         return dasd_generic_set_online (cdev, &dasd_eckd_discipline);
100 }
101
102 static struct ccw_driver dasd_eckd_driver = {
103         .name        = "dasd-eckd",
104         .owner       = THIS_MODULE,
105         .ids         = dasd_eckd_ids,
106         .probe       = dasd_eckd_probe,
107         .remove      = dasd_generic_remove,
108         .set_offline = dasd_generic_set_offline,
109         .set_online  = dasd_eckd_set_online,
110         .notify      = dasd_generic_notify,
111 };
112
113 static const int sizes_trk0[] = { 28, 148, 84 };
114 #define LABEL_SIZE 140
115
116 static inline unsigned int
117 round_up_multiple(unsigned int no, unsigned int mult)
118 {
119         int rem = no % mult;
120         return (rem ? no - rem + mult : no);
121 }
122
123 static inline unsigned int
124 ceil_quot(unsigned int d1, unsigned int d2)
125 {
126         return (d1 + (d2 - 1)) / d2;
127 }
128
129 static inline int
130 bytes_per_record(struct dasd_eckd_characteristics *rdc, int kl, int dl)
131 {
132         unsigned int fl1, fl2, int1, int2;
133         int bpr;
134
135         switch (rdc->formula) {
136         case 0x01:
137                 fl1 = round_up_multiple(ECKD_F2(rdc) + dl, ECKD_F1(rdc));
138                 fl2 = round_up_multiple(kl ? ECKD_F2(rdc) + kl : 0,
139                                         ECKD_F1(rdc));
140                 bpr = fl1 + fl2;
141                 break;
142         case 0x02:
143                 int1 = ceil_quot(dl + ECKD_F6(rdc), ECKD_F5(rdc) << 1);
144                 int2 = ceil_quot(kl + ECKD_F6(rdc), ECKD_F5(rdc) << 1);
145                 fl1 = round_up_multiple(ECKD_F1(rdc) * ECKD_F2(rdc) + dl +
146                                         ECKD_F6(rdc) + ECKD_F4(rdc) * int1,
147                                         ECKD_F1(rdc));
148                 fl2 = round_up_multiple(ECKD_F1(rdc) * ECKD_F3(rdc) + kl +
149                                         ECKD_F6(rdc) + ECKD_F4(rdc) * int2,
150                                         ECKD_F1(rdc));
151                 bpr = fl1 + fl2;
152                 break;
153         default:
154                 MESSAGE(KERN_ERR, "unknown formula%d", rdc->formula);
155                 bpr = 0;
156                 break;
157         }
158         return bpr;
159 }
160
161 static inline unsigned int
162 bytes_per_track(struct dasd_eckd_characteristics *rdc)
163 {
164         return *(unsigned int *) (rdc->byte_per_track) >> 8;
165 }
166
167 static inline unsigned int
168 recs_per_track(struct dasd_eckd_characteristics * rdc,
169                unsigned int kl, unsigned int dl)
170 {
171         int dn, kn;
172
173         switch (rdc->dev_type) {
174         case 0x3380:
175                 if (kl)
176                         return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) +
177                                        ceil_quot(dl + 12, 32));
178                 else
179                         return 1499 / (15 + ceil_quot(dl + 12, 32));
180         case 0x3390:
181                 dn = ceil_quot(dl + 6, 232) + 1;
182                 if (kl) {
183                         kn = ceil_quot(kl + 6, 232) + 1;
184                         return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) +
185                                        9 + ceil_quot(dl + 6 * dn, 34));
186                 } else
187                         return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
188         case 0x9345:
189                 dn = ceil_quot(dl + 6, 232) + 1;
190                 if (kl) {
191                         kn = ceil_quot(kl + 6, 232) + 1;
192                         return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) +
193                                        ceil_quot(dl + 6 * dn, 34));
194                 } else
195                         return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34));
196         }
197         return 0;
198 }
199
200 static inline void
201 check_XRC (struct ccw1         *de_ccw,
202            struct DE_eckd_data *data,
203            struct dasd_device  *device)
204 {
205         struct dasd_eckd_private *private;
206
207         private = (struct dasd_eckd_private *) device->private;
208
209         /* switch on System Time Stamp - needed for XRC Support */
210         if (private->rdc_data.facilities.XRC_supported) {
211                 
212                 data->ga_extended |= 0x08;   /* switch on 'Time Stamp Valid'   */
213                 data->ga_extended |= 0x02;   /* switch on 'Extended Parameter' */
214                 
215                 data->ep_sys_time = get_clock ();
216                 
217                 de_ccw->count = sizeof (struct DE_eckd_data);
218                 de_ccw->flags |= CCW_FLAG_SLI;  
219         }
220
221         return;
222
223 } /* end check_XRC */
224
225 static inline void
226 define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
227               int totrk, int cmd, struct dasd_device * device)
228 {
229         struct dasd_eckd_private *private;
230         struct ch_t geo, beg, end;
231
232         private = (struct dasd_eckd_private *) device->private;
233
234         ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
235         ccw->flags = 0;
236         ccw->count = 16;
237         ccw->cda = (__u32) __pa(data);
238
239         memset(data, 0, sizeof (struct DE_eckd_data));
240         switch (cmd) {
241         case DASD_ECKD_CCW_READ_HOME_ADDRESS:
242         case DASD_ECKD_CCW_READ_RECORD_ZERO:
243         case DASD_ECKD_CCW_READ:
244         case DASD_ECKD_CCW_READ_MT:
245         case DASD_ECKD_CCW_READ_CKD:
246         case DASD_ECKD_CCW_READ_CKD_MT:
247         case DASD_ECKD_CCW_READ_KD:
248         case DASD_ECKD_CCW_READ_KD_MT:
249         case DASD_ECKD_CCW_READ_COUNT:
250                 data->mask.perm = 0x1;
251                 data->attributes.operation = private->attrib.operation;
252                 break;
253         case DASD_ECKD_CCW_WRITE:
254         case DASD_ECKD_CCW_WRITE_MT:
255         case DASD_ECKD_CCW_WRITE_KD:
256         case DASD_ECKD_CCW_WRITE_KD_MT:
257                 data->mask.perm = 0x02;
258                 data->attributes.operation = private->attrib.operation;
259                 check_XRC (ccw, data, device);
260                 break;
261         case DASD_ECKD_CCW_WRITE_CKD:
262         case DASD_ECKD_CCW_WRITE_CKD_MT:
263                 data->attributes.operation = DASD_BYPASS_CACHE;
264                 check_XRC (ccw, data, device);
265                 break;
266         case DASD_ECKD_CCW_ERASE:
267         case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
268         case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
269                 data->mask.perm = 0x3;
270                 data->mask.auth = 0x1;
271                 data->attributes.operation = DASD_BYPASS_CACHE;
272                 check_XRC (ccw, data, device);
273                 break;
274         default:
275                 MESSAGE(KERN_ERR, "unknown opcode 0x%x", cmd);
276                 break;
277         }
278
279         data->attributes.mode = 0x3;    /* ECKD */
280
281         if ((private->rdc_data.cu_type == 0x2105 ||
282              private->rdc_data.cu_type == 0x2107 ||
283              private->rdc_data.cu_type == 0x1750)
284             && !(private->uses_cdl && trk < 2))
285                 data->ga_extended |= 0x40; /* Regular Data Format Mode */
286
287         geo.cyl = private->rdc_data.no_cyl;
288         geo.head = private->rdc_data.trk_per_cyl;
289         beg.cyl = trk / geo.head;
290         beg.head = trk % geo.head;
291         end.cyl = totrk / geo.head;
292         end.head = totrk % geo.head;
293
294         /* check for sequential prestage - enhance cylinder range */
295         if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
296             data->attributes.operation == DASD_SEQ_ACCESS) {
297                 
298                 if (end.cyl + private->attrib.nr_cyl < geo.cyl) 
299                         end.cyl += private->attrib.nr_cyl;
300                 else
301                         end.cyl = (geo.cyl - 1);
302         }
303
304         data->beg_ext.cyl = beg.cyl;
305         data->beg_ext.head = beg.head;
306         data->end_ext.cyl = end.cyl;
307         data->end_ext.head = end.head;
308 }
309
310 static inline void
311 locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
312               int rec_on_trk, int no_rec, int cmd,
313               struct dasd_device * device, int reclen)
314 {
315         struct dasd_eckd_private *private;
316         int sector;
317         int dn, d;
318                                 
319         private = (struct dasd_eckd_private *) device->private;
320
321         DBF_EVENT(DBF_INFO,
322                   "Locate: trk %d, rec %d, no_rec %d, cmd %d, reclen %d",
323                   trk, rec_on_trk, no_rec, cmd, reclen);
324
325         ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
326         ccw->flags = 0;
327         ccw->count = 16;
328         ccw->cda = (__u32) __pa(data);
329
330         memset(data, 0, sizeof (struct LO_eckd_data));
331         sector = 0;
332         if (rec_on_trk) {
333                 switch (private->rdc_data.dev_type) {
334                 case 0x3390:
335                         dn = ceil_quot(reclen + 6, 232);
336                         d = 9 + ceil_quot(reclen + 6 * (dn + 1), 34);
337                         sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8;
338                         break;
339                 case 0x3380:
340                         d = 7 + ceil_quot(reclen + 12, 32);
341                         sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7;
342                         break;
343                 }
344         }
345         data->sector = sector;
346         data->count = no_rec;
347         switch (cmd) {
348         case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
349                 data->operation.orientation = 0x3;
350                 data->operation.operation = 0x03;
351                 break;
352         case DASD_ECKD_CCW_READ_HOME_ADDRESS:
353                 data->operation.orientation = 0x3;
354                 data->operation.operation = 0x16;
355                 break;
356         case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
357                 data->operation.orientation = 0x1;
358                 data->operation.operation = 0x03;
359                 data->count++;
360                 break;
361         case DASD_ECKD_CCW_READ_RECORD_ZERO:
362                 data->operation.orientation = 0x3;
363                 data->operation.operation = 0x16;
364                 data->count++;
365                 break;
366         case DASD_ECKD_CCW_WRITE:
367         case DASD_ECKD_CCW_WRITE_MT:
368         case DASD_ECKD_CCW_WRITE_KD:
369         case DASD_ECKD_CCW_WRITE_KD_MT:
370                 data->auxiliary.last_bytes_used = 0x1;
371                 data->length = reclen;
372                 data->operation.operation = 0x01;
373                 break;
374         case DASD_ECKD_CCW_WRITE_CKD:
375         case DASD_ECKD_CCW_WRITE_CKD_MT:
376                 data->auxiliary.last_bytes_used = 0x1;
377                 data->length = reclen;
378                 data->operation.operation = 0x03;
379                 break;
380         case DASD_ECKD_CCW_READ:
381         case DASD_ECKD_CCW_READ_MT:
382         case DASD_ECKD_CCW_READ_KD:
383         case DASD_ECKD_CCW_READ_KD_MT:
384                 data->auxiliary.last_bytes_used = 0x1;
385                 data->length = reclen;
386                 data->operation.operation = 0x06;
387                 break;
388         case DASD_ECKD_CCW_READ_CKD:
389         case DASD_ECKD_CCW_READ_CKD_MT:
390                 data->auxiliary.last_bytes_used = 0x1;
391                 data->length = reclen;
392                 data->operation.operation = 0x16;
393                 break;
394         case DASD_ECKD_CCW_READ_COUNT:
395                 data->operation.operation = 0x06;
396                 break;
397         case DASD_ECKD_CCW_ERASE:
398                 data->length = reclen;
399                 data->auxiliary.last_bytes_used = 0x1;
400                 data->operation.operation = 0x0b;
401                 break;
402         default:
403                 MESSAGE(KERN_ERR, "unknown opcode 0x%x", cmd);
404         }
405         data->seek_addr.cyl = data->search_arg.cyl =
406                 trk / private->rdc_data.trk_per_cyl;
407         data->seek_addr.head = data->search_arg.head =
408                 trk % private->rdc_data.trk_per_cyl;
409         data->search_arg.record = rec_on_trk;
410 }
411
412 /*
413  * Returns 1 if the block is one of the special blocks that needs
414  * to get read/written with the KD variant of the command.
415  * That is DASD_ECKD_READ_KD_MT instead of DASD_ECKD_READ_MT and
416  * DASD_ECKD_WRITE_KD_MT instead of DASD_ECKD_WRITE_MT.
417  * Luckily the KD variants differ only by one bit (0x08) from the
418  * normal variant. So don't wonder about code like:
419  * if (dasd_eckd_cdl_special(blk_per_trk, recid))
420  *         ccw->cmd_code |= 0x8;
421  */
422 static inline int
423 dasd_eckd_cdl_special(int blk_per_trk, int recid)
424 {
425         if (recid < 3)
426                 return 1;
427         if (recid < blk_per_trk)
428                 return 0;
429         if (recid < 2 * blk_per_trk)
430                 return 1;
431         return 0;
432 }
433
434 /*
435  * Returns the record size for the special blocks of the cdl format.
436  * Only returns something useful if dasd_eckd_cdl_special is true
437  * for the recid.
438  */
439 static inline int
440 dasd_eckd_cdl_reclen(int recid)
441 {
442         if (recid < 3)
443                 return sizes_trk0[recid];
444         return LABEL_SIZE;
445 }
446
447 static int
448 dasd_eckd_check_characteristics(struct dasd_device *device)
449 {
450         struct dasd_eckd_private *private;
451         void *rdc_data;
452         void *conf_data;
453         int conf_len;
454         int rc;
455
456         private = (struct dasd_eckd_private *) device->private;
457         if (private == NULL) {
458                 private = kmalloc(sizeof(struct dasd_eckd_private),
459                                   GFP_KERNEL | GFP_DMA);
460                 if (private == NULL) {
461                         MESSAGE(KERN_WARNING, "%s",
462                                 "memory allocation failed for private data");
463                         return -ENOMEM;
464                 }
465                 device->private = (void *) private;
466         }
467         /* Invalidate status of initial analysis. */
468         private->init_cqr_status = -1;
469         /* Set default cache operations. */
470         private->attrib.operation = DASD_NORMAL_CACHE;
471         private->attrib.nr_cyl = 0;
472
473         /* Read Device Characteristics */
474         rdc_data = (void *) &(private->rdc_data);
475         rc = read_dev_chars(device->cdev, &rdc_data, 64);
476         if (rc) {
477                 MESSAGE(KERN_WARNING,
478                         "Read device characteristics returned error %d", rc);
479                 return rc;
480         }
481
482         DEV_MESSAGE(KERN_INFO, device,
483                     "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
484                     private->rdc_data.dev_type,
485                     private->rdc_data.dev_model,
486                     private->rdc_data.cu_type,
487                     private->rdc_data.cu_model.model,
488                     private->rdc_data.no_cyl,
489                     private->rdc_data.trk_per_cyl,
490                     private->rdc_data.sec_per_trk);
491
492         /* Read Configuration Data */
493         rc = read_conf_data(device->cdev, &conf_data, &conf_len);
494         if (rc && rc != -EOPNOTSUPP) {  /* -EOPNOTSUPP is ok */
495                 MESSAGE(KERN_WARNING,
496                         "Read configuration data returned error %d", rc);
497                 return rc;
498         }
499         if (conf_data == NULL) {
500                 MESSAGE(KERN_WARNING, "%s", "No configuration data retrieved");
501                 return 0;       /* no errror */
502         }
503         if (conf_len != sizeof (struct dasd_eckd_confdata)) {
504                 MESSAGE(KERN_WARNING,
505                         "sizes of configuration data mismatch"
506                         "%d (read) vs %ld (expected)",
507                         conf_len, sizeof (struct dasd_eckd_confdata));
508
509                 kfree(conf_data); /* allocated by read_conf_data() */
510                 return 0;       /* no errror */
511         }
512         memcpy(&private->conf_data, conf_data,
513                sizeof (struct dasd_eckd_confdata));
514         kfree(conf_data); /* allocated by read_conf_data() */
515         return 0;
516 }
517
518 static struct dasd_ccw_req *
519 dasd_eckd_analysis_ccw(struct dasd_device *device)
520 {
521         struct dasd_eckd_private *private;
522         struct eckd_count *count_data;
523         struct LO_eckd_data *LO_data;
524         struct dasd_ccw_req *cqr;
525         struct ccw1 *ccw;
526         int cplength, datasize;
527         int i;
528
529         private = (struct dasd_eckd_private *) device->private;
530
531         cplength = 8;
532         datasize = sizeof(struct DE_eckd_data) + 2*sizeof(struct LO_eckd_data);
533         cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
534                                    cplength, datasize, device);
535         if (IS_ERR(cqr))
536                 return cqr;
537         ccw = cqr->cpaddr;
538         /* Define extent for the first 3 tracks. */
539         define_extent(ccw++, cqr->data, 0, 2,
540                       DASD_ECKD_CCW_READ_COUNT, device);
541         LO_data = cqr->data + sizeof (struct DE_eckd_data);
542         /* Locate record for the first 4 records on track 0. */
543         ccw[-1].flags |= CCW_FLAG_CC;
544         locate_record(ccw++, LO_data++, 0, 0, 4,
545                       DASD_ECKD_CCW_READ_COUNT, device, 0);
546
547         count_data = private->count_area;
548         for (i = 0; i < 4; i++) {
549                 ccw[-1].flags |= CCW_FLAG_CC;
550                 ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
551                 ccw->flags = 0;
552                 ccw->count = 8;
553                 ccw->cda = (__u32)(addr_t) count_data;
554                 ccw++;
555                 count_data++;
556         }
557
558         /* Locate record for the first record on track 2. */
559         ccw[-1].flags |= CCW_FLAG_CC;
560         locate_record(ccw++, LO_data++, 2, 0, 1,
561                       DASD_ECKD_CCW_READ_COUNT, device, 0);
562         /* Read count ccw. */
563         ccw[-1].flags |= CCW_FLAG_CC;
564         ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
565         ccw->flags = 0;
566         ccw->count = 8;
567         ccw->cda = (__u32)(addr_t) count_data;
568
569         cqr->device = device;
570         cqr->retries = 0;
571         cqr->buildclk = get_clock();
572         cqr->status = DASD_CQR_FILLED;
573         return cqr;
574 }
575
576 /*
577  * This is the callback function for the init_analysis cqr. It saves
578  * the status of the initial analysis ccw before it frees it and kicks
579  * the device to continue the startup sequence. This will call
580  * dasd_eckd_do_analysis again (if the devices has not been marked
581  * for deletion in the meantime).
582  */
583 static void
584 dasd_eckd_analysis_callback(struct dasd_ccw_req *init_cqr, void *data)
585 {
586         struct dasd_eckd_private *private;
587         struct dasd_device *device;
588
589         device = init_cqr->device;
590         private = (struct dasd_eckd_private *) device->private;
591         private->init_cqr_status = init_cqr->status;
592         dasd_sfree_request(init_cqr, device);
593         dasd_kick_device(device);
594 }
595
596 static int
597 dasd_eckd_start_analysis(struct dasd_device *device)
598 {
599         struct dasd_eckd_private *private;
600         struct dasd_ccw_req *init_cqr;
601
602         private = (struct dasd_eckd_private *) device->private;
603         init_cqr = dasd_eckd_analysis_ccw(device);
604         if (IS_ERR(init_cqr))
605                 return PTR_ERR(init_cqr);
606         init_cqr->callback = dasd_eckd_analysis_callback;
607         init_cqr->callback_data = NULL;
608         init_cqr->expires = 5*HZ;
609         dasd_add_request_head(init_cqr);
610         return -EAGAIN;
611 }
612
613 static int
614 dasd_eckd_end_analysis(struct dasd_device *device)
615 {
616         struct dasd_eckd_private *private;
617         struct eckd_count *count_area;
618         unsigned int sb, blk_per_trk;
619         int status, i;
620
621         private = (struct dasd_eckd_private *) device->private;
622         status = private->init_cqr_status;
623         private->init_cqr_status = -1;
624         if (status != DASD_CQR_DONE) {
625                 DEV_MESSAGE(KERN_WARNING, device, "%s",
626                             "volume analysis returned unformatted disk");
627                 return -EMEDIUMTYPE;
628         }
629
630         private->uses_cdl = 1;
631         /* Calculate number of blocks/records per track. */
632         blk_per_trk = recs_per_track(&private->rdc_data, 0, device->bp_block);
633         /* Check Track 0 for Compatible Disk Layout */
634         count_area = NULL;
635         for (i = 0; i < 3; i++) {
636                 if (private->count_area[i].kl != 4 ||
637                     private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4) {
638                         private->uses_cdl = 0;
639                         break;
640                 }
641         }
642         if (i == 3)
643                 count_area = &private->count_area[4];
644
645         if (private->uses_cdl == 0) {
646                 for (i = 0; i < 5; i++) {
647                         if ((private->count_area[i].kl != 0) ||
648                             (private->count_area[i].dl !=
649                              private->count_area[0].dl))
650                                 break;
651                 }
652                 if (i == 5)
653                         count_area = &private->count_area[0];
654         } else {
655                 if (private->count_area[3].record == 1)
656                         DEV_MESSAGE(KERN_WARNING, device, "%s",
657                                     "Trk 0: no records after VTOC!");
658         }
659         if (count_area != NULL && count_area->kl == 0) {
660                 /* we found notthing violating our disk layout */
661                 if (dasd_check_blocksize(count_area->dl) == 0)
662                         device->bp_block = count_area->dl;
663         }
664         if (device->bp_block == 0) {
665                 DEV_MESSAGE(KERN_WARNING, device, "%s",
666                             "Volume has incompatible disk layout");
667                 return -EMEDIUMTYPE;
668         }
669         device->s2b_shift = 0;  /* bits to shift 512 to get a block */
670         for (sb = 512; sb < device->bp_block; sb = sb << 1)
671                 device->s2b_shift++;
672
673         blk_per_trk = recs_per_track(&private->rdc_data, 0, device->bp_block);
674         device->blocks = (private->rdc_data.no_cyl *
675                           private->rdc_data.trk_per_cyl *
676                           blk_per_trk);
677
678         DEV_MESSAGE(KERN_INFO, device,
679                     "(%dkB blks): %dkB at %dkB/trk %s",
680                     (device->bp_block >> 10),
681                     ((private->rdc_data.no_cyl *
682                       private->rdc_data.trk_per_cyl *
683                       blk_per_trk * (device->bp_block >> 9)) >> 1),
684                     ((blk_per_trk * device->bp_block) >> 10), 
685                     private->uses_cdl ?
686                     "compatible disk layout" : "linux disk layout");
687
688         return 0;
689 }
690
691 static int
692 dasd_eckd_do_analysis(struct dasd_device *device)
693 {
694         struct dasd_eckd_private *private;
695
696         private = (struct dasd_eckd_private *) device->private;
697         if (private->init_cqr_status < 0)
698                 return dasd_eckd_start_analysis(device);
699         else
700                 return dasd_eckd_end_analysis(device);
701 }
702
703 static int
704 dasd_eckd_fill_geometry(struct dasd_device *device, struct hd_geometry *geo)
705 {
706         struct dasd_eckd_private *private;
707
708         private = (struct dasd_eckd_private *) device->private;
709         if (dasd_check_blocksize(device->bp_block) == 0) {
710                 geo->sectors = recs_per_track(&private->rdc_data,
711                                               0, device->bp_block);
712         }
713         geo->cylinders = private->rdc_data.no_cyl;
714         geo->heads = private->rdc_data.trk_per_cyl;
715         return 0;
716 }
717
718 static struct dasd_ccw_req *
719 dasd_eckd_format_device(struct dasd_device * device,
720                         struct format_data_t * fdata)
721 {
722         struct dasd_eckd_private *private;
723         struct dasd_ccw_req *fcp;
724         struct eckd_count *ect;
725         struct ccw1 *ccw;
726         void *data;
727         int rpt, cyl, head;
728         int cplength, datasize;
729         int i;
730
731         private = (struct dasd_eckd_private *) device->private;
732         rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
733         cyl = fdata->start_unit / private->rdc_data.trk_per_cyl;
734         head = fdata->start_unit % private->rdc_data.trk_per_cyl;
735
736         /* Sanity checks. */
737         if (fdata->start_unit >=
738             (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) {
739                 DEV_MESSAGE(KERN_INFO, device, "Track no %d too big!",
740                             fdata->start_unit);
741                 return ERR_PTR(-EINVAL);
742         }
743         if (fdata->start_unit > fdata->stop_unit) {
744                 DEV_MESSAGE(KERN_INFO, device, "Track %d reached! ending.",
745                             fdata->start_unit);
746                 return ERR_PTR(-EINVAL);
747         }
748         if (dasd_check_blocksize(fdata->blksize) != 0) {
749                 MESSAGE(KERN_WARNING, "Invalid blocksize %d...terminating!",
750                         fdata->blksize);
751                 return ERR_PTR(-EINVAL);
752         }
753
754         /*
755          * fdata->intensity is a bit string that tells us what to do:
756          *   Bit 0: write record zero
757          *   Bit 1: write home address, currently not supported
758          *   Bit 2: invalidate tracks
759          *   Bit 3: use OS/390 compatible disk layout (cdl)
760          * Only some bit combinations do make sense.
761          */
762         switch (fdata->intensity) {
763         case 0x00:      /* Normal format */
764         case 0x08:      /* Normal format, use cdl. */
765                 cplength = 2 + rpt;
766                 datasize = sizeof(struct DE_eckd_data) +
767                         sizeof(struct LO_eckd_data) +
768                         rpt * sizeof(struct eckd_count);
769                 break;
770         case 0x01:      /* Write record zero and format track. */
771         case 0x09:      /* Write record zero and format track, use cdl. */
772                 cplength = 3 + rpt;
773                 datasize = sizeof(struct DE_eckd_data) +
774                         sizeof(struct LO_eckd_data) +
775                         sizeof(struct eckd_count) +
776                         rpt * sizeof(struct eckd_count);
777                 break;
778         case 0x04:      /* Invalidate track. */
779         case 0x0c:      /* Invalidate track, use cdl. */
780                 cplength = 3;
781                 datasize = sizeof(struct DE_eckd_data) +
782                         sizeof(struct LO_eckd_data) +
783                         sizeof(struct eckd_count);
784                 break;
785         default:
786                 MESSAGE(KERN_WARNING, "Invalid flags 0x%x.", fdata->intensity);
787                 return ERR_PTR(-EINVAL);
788         }
789         /* Allocate the format ccw request. */
790         fcp = dasd_smalloc_request(dasd_eckd_discipline.name,
791                                    cplength, datasize, device);
792         if (IS_ERR(fcp))
793                 return fcp;
794
795         data = fcp->data;
796         ccw = fcp->cpaddr;
797
798         switch (fdata->intensity & ~0x08) {
799         case 0x00: /* Normal format. */
800                 define_extent(ccw++, (struct DE_eckd_data *) data,
801                               fdata->start_unit, fdata->start_unit,
802                               DASD_ECKD_CCW_WRITE_CKD, device);
803                 data += sizeof(struct DE_eckd_data);
804                 ccw[-1].flags |= CCW_FLAG_CC;
805                 locate_record(ccw++, (struct LO_eckd_data *) data,
806                               fdata->start_unit, 0, rpt,
807                               DASD_ECKD_CCW_WRITE_CKD, device,
808                               fdata->blksize);
809                 data += sizeof(struct LO_eckd_data);
810                 break;
811         case 0x01: /* Write record zero + format track. */
812                 define_extent(ccw++, (struct DE_eckd_data *) data,
813                               fdata->start_unit, fdata->start_unit,
814                               DASD_ECKD_CCW_WRITE_RECORD_ZERO,
815                               device);
816                 data += sizeof(struct DE_eckd_data);
817                 ccw[-1].flags |= CCW_FLAG_CC;
818                 locate_record(ccw++, (struct LO_eckd_data *) data,
819                               fdata->start_unit, 0, rpt + 1,
820                               DASD_ECKD_CCW_WRITE_RECORD_ZERO, device,
821                               device->bp_block);
822                 data += sizeof(struct LO_eckd_data);
823                 break;
824         case 0x04: /* Invalidate track. */
825                 define_extent(ccw++, (struct DE_eckd_data *) data,
826                               fdata->start_unit, fdata->start_unit,
827                               DASD_ECKD_CCW_WRITE_CKD, device);
828                 data += sizeof(struct DE_eckd_data);
829                 ccw[-1].flags |= CCW_FLAG_CC;
830                 locate_record(ccw++, (struct LO_eckd_data *) data,
831                               fdata->start_unit, 0, 1,
832                               DASD_ECKD_CCW_WRITE_CKD, device, 8);
833                 data += sizeof(struct LO_eckd_data);
834                 break;
835         }
836         if (fdata->intensity & 0x01) {  /* write record zero */
837                 ect = (struct eckd_count *) data;
838                 data += sizeof(struct eckd_count);
839                 ect->cyl = cyl;
840                 ect->head = head;
841                 ect->record = 0;
842                 ect->kl = 0;
843                 ect->dl = 8;
844                 ccw[-1].flags |= CCW_FLAG_CC;
845                 ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
846                 ccw->flags = CCW_FLAG_SLI;
847                 ccw->count = 8;
848                 ccw->cda = (__u32)(addr_t) ect;
849                 ccw++;
850         }
851         if ((fdata->intensity & ~0x08) & 0x04) {        /* erase track */
852                 ect = (struct eckd_count *) data;
853                 data += sizeof(struct eckd_count);
854                 ect->cyl = cyl;
855                 ect->head = head;
856                 ect->record = 1;
857                 ect->kl = 0;
858                 ect->dl = 0;
859                 ccw[-1].flags |= CCW_FLAG_CC;
860                 ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
861                 ccw->flags = CCW_FLAG_SLI;
862                 ccw->count = 8;
863                 ccw->cda = (__u32)(addr_t) ect;
864         } else {                /* write remaining records */
865                 for (i = 0; i < rpt; i++) {
866                         ect = (struct eckd_count *) data;
867                         data += sizeof(struct eckd_count);
868                         ect->cyl = cyl;
869                         ect->head = head;
870                         ect->record = i + 1;
871                         ect->kl = 0;
872                         ect->dl = fdata->blksize;
873                         /* Check for special tracks 0-1 when formatting CDL */
874                         if ((fdata->intensity & 0x08) &&
875                             fdata->start_unit == 0) {
876                                 if (i < 3) {
877                                         ect->kl = 4;
878                                         ect->dl = sizes_trk0[i] - 4;
879                                 } 
880                         }
881                         if ((fdata->intensity & 0x08) &&
882                             fdata->start_unit == 1) {
883                                 ect->kl = 44;
884                                 ect->dl = LABEL_SIZE - 44;
885                         }
886                         ccw[-1].flags |= CCW_FLAG_CC;
887                         ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
888                         ccw->flags = CCW_FLAG_SLI;
889                         ccw->count = 8;
890                         ccw->cda = (__u32)(addr_t) ect;
891                         ccw++;
892                 }
893         }
894         fcp->device = device;
895         fcp->retries = 2;       /* set retry counter to enable ERP */
896         fcp->buildclk = get_clock();
897         fcp->status = DASD_CQR_FILLED;
898         return fcp;
899 }
900
901 static dasd_era_t
902 dasd_eckd_examine_error(struct dasd_ccw_req * cqr, struct irb * irb)
903 {
904         struct dasd_device *device = (struct dasd_device *) cqr->device;
905         struct ccw_device *cdev = device->cdev;
906
907         if (irb->scsw.cstat == 0x00 &&
908             irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
909                 return dasd_era_none;
910
911         switch (cdev->id.cu_type) {
912         case 0x3990:
913         case 0x2105:
914         case 0x2107:
915         case 0x1750:
916                 return dasd_3990_erp_examine(cqr, irb);
917         case 0x9343:
918                 return dasd_9343_erp_examine(cqr, irb);
919         case 0x3880:
920         default:
921                 MESSAGE(KERN_WARNING, "%s",
922                         "default (unknown CU type) - RECOVERABLE return");
923                 return dasd_era_recover;
924         }
925 }
926
927 static dasd_erp_fn_t
928 dasd_eckd_erp_action(struct dasd_ccw_req * cqr)
929 {
930         struct dasd_device *device = (struct dasd_device *) cqr->device;
931         struct ccw_device *cdev = device->cdev;
932
933         switch (cdev->id.cu_type) {
934         case 0x3990:
935         case 0x2105:
936         case 0x2107:
937         case 0x1750:
938                 return dasd_3990_erp_action;
939         case 0x9343:
940                 /* Return dasd_9343_erp_action; */
941         case 0x3880:
942         default:
943                 return dasd_default_erp_action;
944         }
945 }
946
947 static dasd_erp_fn_t
948 dasd_eckd_erp_postaction(struct dasd_ccw_req * cqr)
949 {
950         return dasd_default_erp_postaction;
951 }
952
953 static struct dasd_ccw_req *
954 dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
955 {
956         struct dasd_eckd_private *private;
957         unsigned long *idaws;
958         struct LO_eckd_data *LO_data;
959         struct dasd_ccw_req *cqr;
960         struct ccw1 *ccw;
961         struct bio *bio;
962         struct bio_vec *bv;
963         char *dst;
964         unsigned int blksize, blk_per_trk, off;
965         int count, cidaw, cplength, datasize;
966         sector_t recid, first_rec, last_rec;
967         sector_t first_trk, last_trk;
968         unsigned int first_offs, last_offs;
969         unsigned char cmd, rcmd;
970         int i;
971
972         private = (struct dasd_eckd_private *) device->private;
973         if (rq_data_dir(req) == READ)
974                 cmd = DASD_ECKD_CCW_READ_MT;
975         else if (rq_data_dir(req) == WRITE)
976                 cmd = DASD_ECKD_CCW_WRITE_MT;
977         else
978                 return ERR_PTR(-EINVAL);
979         /* Calculate number of blocks/records per track. */
980         blksize = device->bp_block;
981         blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
982         /* Calculate record id of first and last block. */
983         first_rec = first_trk = req->sector >> device->s2b_shift;
984         first_offs = sector_div(first_trk, blk_per_trk);
985         last_rec = last_trk =
986                 (req->sector + req->nr_sectors - 1) >> device->s2b_shift;
987         last_offs = sector_div(last_trk, blk_per_trk);
988         /* Check struct bio and count the number of blocks for the request. */
989         count = 0;
990         cidaw = 0;
991         rq_for_each_bio(bio, req) {
992                 bio_for_each_segment(bv, bio, i) {
993                         if (bv->bv_len & (blksize - 1))
994                                 /* Eckd can only do full blocks. */
995                                 return ERR_PTR(-EINVAL);
996                         count += bv->bv_len >> (device->s2b_shift + 9);
997 #if defined(CONFIG_ARCH_S390X)
998                         if (idal_is_needed (page_address(bv->bv_page), bv->bv_len))
999                                 cidaw += bv->bv_len >> (device->s2b_shift + 9);
1000 #endif
1001                 }
1002         }
1003         /* Paranoia. */
1004         if (count != last_rec - first_rec + 1)
1005                 return ERR_PTR(-EINVAL);
1006         /* 1x define extent + 1x locate record + number of blocks */
1007         cplength = 2 + count;
1008         /* 1x define extent + 1x locate record + cidaws*sizeof(long) */
1009         datasize = sizeof(struct DE_eckd_data) + sizeof(struct LO_eckd_data) +
1010                 cidaw * sizeof(unsigned long);
1011         /* Find out the number of additional locate record ccws for cdl. */
1012         if (private->uses_cdl && first_rec < 2*blk_per_trk) {
1013                 if (last_rec >= 2*blk_per_trk)
1014                         count = 2*blk_per_trk - first_rec;
1015                 cplength += count;
1016                 datasize += count*sizeof(struct LO_eckd_data);
1017         }
1018         /* Allocate the ccw request. */
1019         cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1020                                    cplength, datasize, device);
1021         if (IS_ERR(cqr))
1022                 return cqr;
1023         ccw = cqr->cpaddr;
1024         /* First ccw is define extent. */
1025         define_extent(ccw++, cqr->data, first_trk, last_trk, cmd, device);
1026         /* Build locate_record+read/write/ccws. */
1027         idaws = (unsigned long *) (cqr->data + sizeof(struct DE_eckd_data));
1028         LO_data = (struct LO_eckd_data *) (idaws + cidaw);
1029         recid = first_rec;
1030         if (private->uses_cdl == 0 || recid > 2*blk_per_trk) {
1031                 /* Only standard blocks so there is just one locate record. */
1032                 ccw[-1].flags |= CCW_FLAG_CC;
1033                 locate_record(ccw++, LO_data++, first_trk, first_offs + 1,
1034                               last_rec - recid + 1, cmd, device, blksize);
1035         }
1036         rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) {
1037                 dst = page_address(bv->bv_page) + bv->bv_offset;
1038                 for (off = 0; off < bv->bv_len; off += blksize) {
1039                         sector_t trkid = recid;
1040                         unsigned int recoffs = sector_div(trkid, blk_per_trk);
1041                         rcmd = cmd;
1042                         count = blksize;
1043                         /* Locate record for cdl special block ? */
1044                         if (private->uses_cdl && recid < 2*blk_per_trk) {
1045                                 if (dasd_eckd_cdl_special(blk_per_trk, recid)){
1046                                         rcmd |= 0x8;
1047                                         count = dasd_eckd_cdl_reclen(recid);
1048                                         if (count < blksize)
1049                                                 memset(dst + count, 0xe5,
1050                                                        blksize - count);
1051                                 }
1052                                 ccw[-1].flags |= CCW_FLAG_CC;
1053                                 locate_record(ccw++, LO_data++,
1054                                               trkid, recoffs + 1,
1055                                               1, rcmd, device, count);
1056                         }
1057                         /* Locate record for standard blocks ? */
1058                         if (private->uses_cdl && recid == 2*blk_per_trk) {
1059                                 ccw[-1].flags |= CCW_FLAG_CC;
1060                                 locate_record(ccw++, LO_data++,
1061                                               trkid, recoffs + 1,
1062                                               last_rec - recid + 1,
1063                                               cmd, device, count);
1064                         }
1065                         /* Read/write ccw. */
1066                         ccw[-1].flags |= CCW_FLAG_CC;
1067                         ccw->cmd_code = rcmd;
1068                         ccw->count = count;
1069                         if (idal_is_needed(dst, blksize)) {
1070                                 ccw->cda = (__u32)(addr_t) idaws;
1071                                 ccw->flags = CCW_FLAG_IDA;
1072                                 idaws = idal_create_words(idaws, dst, blksize);
1073                         } else {
1074                                 ccw->cda = (__u32)(addr_t) dst;
1075                                 ccw->flags = 0;
1076                         }
1077                         ccw++;
1078                         dst += blksize;
1079                         recid++;
1080                 }
1081         }
1082         cqr->device = device;
1083         cqr->expires = 5 * 60 * HZ;     /* 5 minutes */
1084         cqr->lpm = LPM_ANYPATH;
1085         cqr->retries = 256;
1086         cqr->buildclk = get_clock();
1087         cqr->status = DASD_CQR_FILLED;
1088         return cqr;
1089 }
1090
1091 static int
1092 dasd_eckd_fill_info(struct dasd_device * device,
1093                     struct dasd_information2_t * info)
1094 {
1095         struct dasd_eckd_private *private;
1096
1097         private = (struct dasd_eckd_private *) device->private;
1098         info->label_block = 2;
1099         info->FBA_layout = private->uses_cdl ? 0 : 1;
1100         info->format = private->uses_cdl ? DASD_FORMAT_CDL : DASD_FORMAT_LDL;
1101         info->characteristics_size = sizeof(struct dasd_eckd_characteristics);
1102         memcpy(info->characteristics, &private->rdc_data,
1103                sizeof(struct dasd_eckd_characteristics));
1104         info->confdata_size = sizeof (struct dasd_eckd_confdata);
1105         memcpy(info->configuration_data, &private->conf_data,
1106                sizeof (struct dasd_eckd_confdata));
1107         return 0;
1108 }
1109
1110 /*
1111  * SECTION: ioctl functions for eckd devices.
1112  */
1113
1114 /*
1115  * Release device ioctl.
1116  * Buils a channel programm to releases a prior reserved 
1117  * (see dasd_eckd_reserve) device.
1118  */
1119 static int
1120 dasd_eckd_release(struct block_device *bdev, int no, long args)
1121 {
1122         struct dasd_device *device;
1123         struct dasd_ccw_req *cqr;
1124         int rc;
1125
1126         if (!capable(CAP_SYS_ADMIN))
1127                 return -EACCES;
1128
1129         device = bdev->bd_disk->private_data;
1130         if (device == NULL)
1131                 return -ENODEV;
1132
1133         cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1134                                    1, 32, device);
1135         if (cqr == NULL) {
1136                 MESSAGE(KERN_WARNING, "%s",
1137                         "No memory to allocate initialization request");
1138                 return -ENOMEM;
1139         }
1140         cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE;
1141         cqr->cpaddr->flags |= CCW_FLAG_SLI;
1142         cqr->cpaddr->count = 32;
1143         cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
1144         cqr->device = device;
1145         clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
1146         cqr->retries = 0;
1147         cqr->expires = 2 * HZ;
1148         cqr->buildclk = get_clock();
1149         cqr->status = DASD_CQR_FILLED;
1150
1151         rc = dasd_sleep_on_immediatly(cqr);
1152
1153         dasd_sfree_request(cqr, cqr->device);
1154         return rc;
1155 }
1156
1157 /*
1158  * Reserve device ioctl.
1159  * Options are set to 'synchronous wait for interrupt' and
1160  * 'timeout the request'. This leads to a terminate IO if 
1161  * the interrupt is outstanding for a certain time. 
1162  */
1163 static int
1164 dasd_eckd_reserve(struct block_device *bdev, int no, long args)
1165 {
1166         struct dasd_device *device;
1167         struct dasd_ccw_req *cqr;
1168         int rc;
1169
1170         if (!capable(CAP_SYS_ADMIN))
1171                 return -EACCES;
1172
1173         device = bdev->bd_disk->private_data;
1174         if (device == NULL)
1175                 return -ENODEV;
1176
1177         cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1178                                    1, 32, device);
1179         if (cqr == NULL) {
1180                 MESSAGE(KERN_WARNING, "%s",
1181                         "No memory to allocate initialization request");
1182                 return -ENOMEM;
1183         }
1184         cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE;
1185         cqr->cpaddr->flags |= CCW_FLAG_SLI;
1186         cqr->cpaddr->count = 32;
1187         cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
1188         cqr->device = device;
1189         clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
1190         cqr->retries = 0;
1191         cqr->expires = 2 * HZ;
1192         cqr->buildclk = get_clock();
1193         cqr->status = DASD_CQR_FILLED;
1194
1195         rc = dasd_sleep_on_immediatly(cqr);
1196
1197         dasd_sfree_request(cqr, cqr->device);
1198         return rc;
1199 }
1200
1201 /*
1202  * Steal lock ioctl - unconditional reserve device.
1203  * Buils a channel programm to break a device's reservation. 
1204  * (unconditional reserve)
1205  */
1206 static int
1207 dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
1208 {
1209         struct dasd_device *device;
1210         struct dasd_ccw_req *cqr;
1211         int rc;
1212
1213         if (!capable(CAP_SYS_ADMIN))
1214                 return -EACCES;
1215
1216         device = bdev->bd_disk->private_data;
1217         if (device == NULL)
1218                 return -ENODEV;
1219
1220         cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1221                                    1, 32, device);
1222         if (cqr == NULL) {
1223                 MESSAGE(KERN_WARNING, "%s",
1224                         "No memory to allocate initialization request");
1225                 return -ENOMEM;
1226         }
1227         cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK;
1228         cqr->cpaddr->flags |= CCW_FLAG_SLI;
1229         cqr->cpaddr->count = 32;
1230         cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
1231         cqr->device = device;
1232         clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
1233         cqr->retries = 0;
1234         cqr->expires = 2 * HZ;
1235         cqr->buildclk = get_clock();
1236         cqr->status = DASD_CQR_FILLED;
1237
1238         rc = dasd_sleep_on_immediatly(cqr);
1239
1240         dasd_sfree_request(cqr, cqr->device);
1241         return rc;
1242 }
1243
1244 /*
1245  * Read performance statistics
1246  */
1247 static int
1248 dasd_eckd_performance(struct block_device *bdev, int no, long args)
1249 {
1250         struct dasd_device *device;
1251         struct dasd_psf_prssd_data *prssdp;
1252         struct dasd_rssd_perf_stats_t *stats;
1253         struct dasd_ccw_req *cqr;
1254         struct ccw1 *ccw;
1255         int rc;
1256
1257         device = bdev->bd_disk->private_data;
1258         if (device == NULL)
1259                 return -ENODEV;
1260
1261         cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1262                                    1 /* PSF */  + 1 /* RSSD */ ,
1263                                    (sizeof (struct dasd_psf_prssd_data) +
1264                                     sizeof (struct dasd_rssd_perf_stats_t)),
1265                                    device);
1266         if (cqr == NULL) {
1267                 MESSAGE(KERN_WARNING, "%s",
1268                         "No memory to allocate initialization request");
1269                 return -ENOMEM;
1270         }
1271         cqr->device = device;
1272         cqr->retries = 0;
1273         cqr->expires = 10 * HZ;
1274
1275         /* Prepare for Read Subsystem Data */
1276         prssdp = (struct dasd_psf_prssd_data *) cqr->data;
1277         memset(prssdp, 0, sizeof (struct dasd_psf_prssd_data));
1278         prssdp->order = PSF_ORDER_PRSSD;
1279         prssdp->suborder = 0x01;        /* Perfomance Statistics */
1280         prssdp->varies[1] = 0x01;       /* Perf Statistics for the Subsystem */
1281
1282         ccw = cqr->cpaddr;
1283         ccw->cmd_code = DASD_ECKD_CCW_PSF;
1284         ccw->count = sizeof (struct dasd_psf_prssd_data);
1285         ccw->flags |= CCW_FLAG_CC;
1286         ccw->cda = (__u32)(addr_t) prssdp;
1287
1288         /* Read Subsystem Data - Performance Statistics */
1289         stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);
1290         memset(stats, 0, sizeof (struct dasd_rssd_perf_stats_t));
1291
1292         ccw++;
1293         ccw->cmd_code = DASD_ECKD_CCW_RSSD;
1294         ccw->count = sizeof (struct dasd_rssd_perf_stats_t);
1295         ccw->cda = (__u32)(addr_t) stats;
1296
1297         cqr->buildclk = get_clock();
1298         cqr->status = DASD_CQR_FILLED;
1299         rc = dasd_sleep_on(cqr);
1300         if (rc == 0) {
1301                 /* Prepare for Read Subsystem Data */
1302                 prssdp = (struct dasd_psf_prssd_data *) cqr->data;
1303                 stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);
1304                 rc = copy_to_user((long __user *) args, (long *) stats,
1305                                   sizeof(struct dasd_rssd_perf_stats_t));
1306         }
1307         dasd_sfree_request(cqr, cqr->device);
1308         return rc;
1309 }
1310
1311 /*
1312  * Get attributes (cache operations)
1313  * Returnes the cache attributes used in Define Extend (DE).
1314  */
1315 static int
1316 dasd_eckd_get_attrib (struct block_device *bdev, int no, long args)
1317 {
1318         struct dasd_device *device;
1319         struct dasd_eckd_private *private;
1320         struct attrib_data_t attrib;
1321         int rc;
1322
1323         if (!capable(CAP_SYS_ADMIN))
1324                 return -EACCES;
1325         if (!args)
1326                 return -EINVAL;
1327
1328         device = bdev->bd_disk->private_data;
1329         if (device == NULL)
1330                 return -ENODEV;
1331
1332         private = (struct dasd_eckd_private *) device->private;
1333         attrib = private->attrib;
1334
1335         rc = copy_to_user((long __user *) args, (long *) &attrib,
1336                           sizeof (struct attrib_data_t));
1337
1338         return rc;
1339 }
1340
1341 /*
1342  * Set attributes (cache operations)
1343  * Stores the attributes for cache operation to be used in Define Extend (DE).
1344  */
1345 static int
1346 dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
1347 {
1348         struct dasd_device *device;
1349         struct dasd_eckd_private *private;
1350         struct attrib_data_t attrib;
1351
1352         if (!capable(CAP_SYS_ADMIN))
1353                 return -EACCES;
1354         if (!args)
1355                 return -EINVAL;
1356
1357         device = bdev->bd_disk->private_data;
1358         if (device == NULL)
1359                 return -ENODEV;
1360
1361         if (copy_from_user(&attrib, (void __user *) args,
1362                            sizeof (struct attrib_data_t))) {
1363                 return -EFAULT;
1364         }
1365
1366         private = (struct dasd_eckd_private *) device->private;
1367
1368         private->attrib = attrib;
1369
1370         DBF_DEV_EVENT(DBF_ERR, device,
1371                       "cache operation mode set to "
1372                       "%x (%i cylinder prestage)",
1373                       private->attrib.operation, private->attrib.nr_cyl);
1374         
1375         return 0;
1376 }
1377
1378 static void
1379 dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
1380                      struct irb *irb)
1381 {
1382
1383         char *page;
1384         struct ccw1 *act;
1385         int len, sl, sct;
1386
1387         page = (char *) get_zeroed_page(GFP_ATOMIC);
1388         if (page == NULL) {
1389                 MESSAGE(KERN_ERR, "%s", "No memory to dump sense data");
1390                 return;
1391         }
1392         len = sprintf(page, KERN_ERR PRINTK_HEADER
1393                       "device %s: I/O status report:\n",
1394                       device->cdev->dev.bus_id);
1395         len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1396                        "in req: %p CS: 0x%02X DS: 0x%02X\n", req,
1397                        irb->scsw.cstat, irb->scsw.dstat);
1398         len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1399                        "Failing CCW: %p\n", 
1400                        (void *) (addr_t) irb->scsw.cpa);
1401         act = req->cpaddr;
1402         do {
1403                 DBF_EVENT(DBF_INFO,
1404                           "CCW %p: %08X %08X",
1405                           act, ((int *) act)[0], ((int *) act)[1]);
1406                 DBF_EVENT(DBF_INFO,
1407                           "DAT: %08X %08X %08X %08X",
1408                           ((int *) (addr_t) act->cda)[0],
1409                           ((int *) (addr_t) act->cda)[1],
1410                           ((int *) (addr_t) act->cda)[2],
1411                           ((int *) (addr_t) act->cda)[3]);
1412         } while (act++->flags & (CCW_FLAG_CC | CCW_FLAG_DC));
1413         if (irb->esw.esw0.erw.cons) {
1414                 for (sl = 0; sl < 4; sl++) {
1415                         len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1416                                        "Sense(hex) %2d-%2d:",
1417                                        (8 * sl), ((8 * sl) + 7));
1418
1419                         for (sct = 0; sct < 8; sct++) {
1420                                 len += sprintf(page + len, " %02x",
1421                                                irb->ecw[8 * sl + sct]);
1422                         }
1423                         len += sprintf(page + len, "\n");
1424                 }
1425
1426                 if (irb->ecw[27] & DASD_SENSE_BIT_0) {
1427                         /* 24 Byte Sense Data */
1428                         len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1429                                        "24 Byte: %x MSG %x, %s MSGb to SYSOP\n",
1430                                        irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
1431                                        irb->ecw[1] & 0x10 ? "" : "no");
1432                 } else {
1433                         /* 32 Byte Sense Data */
1434                         len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1435                                        "32 Byte: Format: %x "
1436                                        "Exception class %x\n",
1437                                        irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
1438                 }
1439         } else {
1440                 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1441                                "SORRY - NO VALID SENSE AVAILABLE\n");
1442         }
1443
1444         MESSAGE(KERN_ERR, "Sense data:\n%s", page);
1445
1446         free_page((unsigned long) page);
1447 }
1448
1449 /*
1450  * max_blocks is dependent on the amount of storage that is available
1451  * in the static io buffer for each device. Currently each device has
1452  * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has
1453  * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use
1454  * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In
1455  * addition we have one define extent ccw + 16 bytes of data and one
1456  * locate record ccw + 16 bytes of data. That makes:
1457  * (8192 - 24 - 136 - 8 - 16 - 8 - 16) / 16 = 499 blocks at maximum.
1458  * We want to fit two into the available memory so that we can immediately
1459  * start the next request if one finishes off. That makes 249.5 blocks
1460  * for one request. Give a little safety and the result is 240.
1461  */
1462 static struct dasd_discipline dasd_eckd_discipline = {
1463         .owner = THIS_MODULE,
1464         .name = "ECKD",
1465         .ebcname = "ECKD",
1466         .max_blocks = 240,
1467         .check_device = dasd_eckd_check_characteristics,
1468         .do_analysis = dasd_eckd_do_analysis,
1469         .fill_geometry = dasd_eckd_fill_geometry,
1470         .start_IO = dasd_start_IO,
1471         .term_IO = dasd_term_IO,
1472         .format_device = dasd_eckd_format_device,
1473         .examine_error = dasd_eckd_examine_error,
1474         .erp_action = dasd_eckd_erp_action,
1475         .erp_postaction = dasd_eckd_erp_postaction,
1476         .build_cp = dasd_eckd_build_cp,
1477         .dump_sense = dasd_eckd_dump_sense,
1478         .fill_info = dasd_eckd_fill_info,
1479 };
1480
1481 static int __init
1482 dasd_eckd_init(void)
1483 {
1484         int ret;
1485
1486         dasd_ioctl_no_register(THIS_MODULE, BIODASDGATTR,
1487                                dasd_eckd_get_attrib);
1488         dasd_ioctl_no_register(THIS_MODULE, BIODASDSATTR,
1489                                dasd_eckd_set_attrib);
1490         dasd_ioctl_no_register(THIS_MODULE, BIODASDPSRD,
1491                                dasd_eckd_performance);
1492         dasd_ioctl_no_register(THIS_MODULE, BIODASDRLSE,
1493                                dasd_eckd_release);
1494         dasd_ioctl_no_register(THIS_MODULE, BIODASDRSRV,
1495                                dasd_eckd_reserve);
1496         dasd_ioctl_no_register(THIS_MODULE, BIODASDSLCK,
1497                                dasd_eckd_steal_lock);
1498
1499         ASCEBC(dasd_eckd_discipline.ebcname, 4);
1500
1501         ret = ccw_driver_register(&dasd_eckd_driver);
1502         if (ret) {
1503                 dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR,
1504                                          dasd_eckd_get_attrib);
1505                 dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR,
1506                                          dasd_eckd_set_attrib);
1507                 dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD,
1508                                          dasd_eckd_performance);
1509                 dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE,
1510                                          dasd_eckd_release);
1511                 dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV,
1512                                          dasd_eckd_reserve);
1513                 dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK,
1514                                          dasd_eckd_steal_lock);
1515                 return ret;
1516         }
1517
1518         dasd_generic_auto_online(&dasd_eckd_driver);
1519         return 0;
1520 }
1521
1522 static void __exit
1523 dasd_eckd_cleanup(void)
1524 {
1525         ccw_driver_unregister(&dasd_eckd_driver);
1526
1527         dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR,
1528                                  dasd_eckd_get_attrib);
1529         dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR,
1530                                  dasd_eckd_set_attrib);
1531         dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD,
1532                                  dasd_eckd_performance);
1533         dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE,
1534                                  dasd_eckd_release);
1535         dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV,
1536                                  dasd_eckd_reserve);
1537         dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK,
1538                                  dasd_eckd_steal_lock);
1539 }
1540
1541 module_init(dasd_eckd_init);
1542 module_exit(dasd_eckd_cleanup);
1543
1544 /*
1545  * Overrides for Emacs so that we follow Linus's tabbing style.
1546  * Emacs will notice this stuff at the end of the file and automatically
1547  * adjust the settings for this buffer only.  This must remain at the end
1548  * of the file.
1549  * ---------------------------------------------------------------------------
1550  * Local variables:
1551  * c-indent-level: 4 
1552  * c-brace-imaginary-offset: 0
1553  * c-brace-offset: -4
1554  * c-argdecl-indent: 4
1555  * c-label-offset: -4
1556  * c-continued-statement-offset: 4
1557  * c-continued-brace-offset: 0
1558  * indent-tabs-mode: 1
1559  * tab-width: 8
1560  * End:
1561  */