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