v2.5.0.7 -> v2.5.0.8
[opensuse:kernel.git] / drivers / s390 / block / dasd.c
1 /*
2  * File...........: linux/drivers/s390/block/dasd.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  * Bugreports.to..: <Linux390@de.ibm.com>
7  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
8  *
9  * History of changes (starts July 2000)
10  * 11/09/00 complete redesign after code review
11  * 02/01/01 added dynamic registration of ioctls
12  *          fixed bug in registration of new majors
13  *          fixed handling of request during dasd_end_request
14  *          fixed handling of plugged queues
15  *          fixed partition handling and HDIO_GETGEO
16  *          fixed traditional naming scheme for devices beyond 702
17  *          fixed some race conditions related to modules
18  *          added devfs suupport
19  * 03/06/01 refined dynamic attach/detach for leaving devices which are online.
20  * 03/09/01 refined dynamic modifiaction of devices
21  * 03/12/01 moved policy in dasd_format to dasdfmt (renamed BIODASDFORMAT)
22  * 03/19/01 added BIODASDINFO-ioctl
23  *          removed 2.2 compatibility
24  * 04/27/01 fixed PL030119COT (dasd_disciplines does not work)
25  * 04/30/01 fixed PL030146HSM (module locking with dynamic ioctls)
26  *          fixed PL030130SBA (handling of invalid ranges)
27  * 05/02/01 fixed PL030145SBA (killing dasdmt)
28  *          fixed PL030149SBA (status of 'accepted' devices)
29  *          fixed PL030146SBA (BUG in ibm.c after adding device)
30  *          added BIODASDPRRD ioctl interface
31  * 05/11/01 fixed  PL030164MVE (trap in probeonly mode)
32  * 05/15/01 fixed devfs support for unformatted devices
33  * 06/26/01 hopefully fixed PL030172SBA,PL030234SBA
34  * 07/09/01 fixed PL030324MSH (wrong statistics output)
35  * 07/16/01 merged in new fixes for handling low-mem situations
36  */
37
38 #include <linux/config.h>
39 #include <linux/version.h>
40 #include <linux/kmod.h>
41 #include <linux/init.h>
42 #include <linux/blkdev.h>
43 #include <linux/stddef.h>
44 #include <linux/kernel.h>
45 #include <linux/tqueue.h>
46 #include <linux/timer.h>
47 #include <linux/slab.h>
48 #include <linux/genhd.h>
49 #include <linux/hdreg.h>
50 #include <linux/interrupt.h>
51 #include <linux/ctype.h>
52 #ifdef CONFIG_PROC_FS
53 #include <linux/proc_fs.h>
54 #endif                          /* CONFIG_PROC_FS */
55 #include <linux/spinlock.h>
56 #include <linux/devfs_fs_kernel.h>
57 #include <linux/blkpg.h>
58 #include <linux/wait.h>
59
60 #include <asm/ccwcache.h>
61 #include <asm/debug.h>
62
63 #include <asm/atomic.h>
64 #include <asm/delay.h>
65 #include <asm/io.h>
66 #include <asm/semaphore.h>
67 #include <asm/ebcdic.h>
68 #include <asm/uaccess.h>
69 #include <asm/irq.h>
70 #include <asm/s390_ext.h>
71 #include <asm/s390dyn.h>
72 #include <asm/idals.h>
73 #include <asm/dasd.h>
74
75 #include "dasd_int.h"
76
77 #ifdef CONFIG_DASD_ECKD
78 #include "dasd_eckd.h"
79 #endif                          /*  CONFIG_DASD_ECKD */
80 #ifdef CONFIG_DASD_FBA
81 #include "dasd_fba.h"
82 #endif                          /*  CONFIG_DASD_FBA */
83 #ifdef CONFIG_DASD_DIAG
84 #include "dasd_diag.h"
85 #endif                          /*  CONFIG_DASD_DIAG */
86
87 /* SECTION: exported variables of dasd.c */
88
89 debug_info_t *dasd_debug_area;
90
91 MODULE_AUTHOR ("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
92 MODULE_DESCRIPTION ("Linux on S/390 DASD device driver,"
93                     " Copyright 2000 IBM Corporation");
94 MODULE_SUPPORTED_DEVICE ("dasd");
95 MODULE_PARM (dasd, "1-" __MODULE_STRING (256) "s");
96 MODULE_PARM (dasd_disciplines, "1-" __MODULE_STRING (8) "s");
97 EXPORT_SYMBOL (dasd_chanq_enq_head);
98 EXPORT_SYMBOL (dasd_debug_area);
99 EXPORT_SYMBOL (dasd_chanq_enq);
100 EXPORT_SYMBOL (dasd_chanq_deq);
101 EXPORT_SYMBOL (dasd_discipline_add);
102 EXPORT_SYMBOL (dasd_discipline_del);
103 EXPORT_SYMBOL (dasd_start_IO);
104 EXPORT_SYMBOL (dasd_term_IO);
105 EXPORT_SYMBOL (dasd_schedule_bh);
106 EXPORT_SYMBOL (dasd_int_handler);
107 EXPORT_SYMBOL (dasd_oper_handler);
108 EXPORT_SYMBOL (dasd_alloc_request);
109 EXPORT_SYMBOL (dasd_free_request);
110 EXPORT_SYMBOL (dasd_ioctl_no_register);
111 EXPORT_SYMBOL (dasd_ioctl_no_unregister);
112 EXPORT_SYMBOL (dasd_default_erp_action);
113 EXPORT_SYMBOL (dasd_default_erp_postaction);
114 EXPORT_SYMBOL (dasd_sleep_on_req);
115 EXPORT_SYMBOL (dasd_set_normalized_cda);
116
117 /* SECTION: Constant definitions to be used within this file */
118
119 #define PRINTK_HEADER DASD_NAME":"
120 #undef  DASD_PROFILE            /* fill profile information - used for */
121                                 /* statistics and perfomance           */
122
123 #define DASD_MIN_SIZE_FOR_QUEUE 32
124 #undef CONFIG_DYNAMIC_QUEUE_MIN_SIZE
125 #define DASD_CHANQ_MAX_SIZE 6
126
127 /* SECTION: prototypes for static functions of dasd.c */
128
129 static request_fn_proc do_dasd_request;
130 static int dasd_set_device_level (unsigned int, dasd_discipline_t *, int);
131 static request_queue_t *dasd_get_queue (kdev_t kdev);
132 static void cleanup_dasd (void);
133 static void dasd_plug_device (dasd_device_t * device);
134 static int dasd_fillgeo (int kdev, struct hd_geometry *geo);
135 static void dasd_enable_ranges (dasd_range_t *, dasd_discipline_t *, int); 
136 static void dasd_disable_ranges (dasd_range_t *, dasd_discipline_t *, int, int); 
137 static void dasd_enable_single_device ( unsigned long);
138 static inline int dasd_state_init_to_ready(dasd_device_t*);
139 static inline void dasd_setup_partitions ( dasd_device_t *);
140 static inline void dasd_destroy_partitions ( dasd_device_t *);
141 static inline int dasd_setup_blkdev(dasd_device_t*);
142 static void dasd_deactivate_queue (dasd_device_t *);
143 static inline int dasd_disable_blkdev(dasd_device_t*);
144 static void dasd_flush_chanq ( dasd_device_t * device, int destroy ); 
145 static void dasd_flush_request_queues ( dasd_device_t * device, int destroy );
146 static struct block_device_operations dasd_device_operations;
147 static inline dasd_device_t ** dasd_device_from_devno (int);
148 static void dasd_process_queues (dasd_device_t * device);
149 /* SECTION: static variables of dasd.c */
150
151 static devfs_handle_t dasd_devfs_handle;
152 static wait_queue_head_t dasd_init_waitq;
153 static atomic_t dasd_init_pending = ATOMIC_INIT (0);
154
155 #ifdef CONFIG_DASD_DYNAMIC
156
157 /* SECTION: managing dynamic configuration of dasd_driver */
158
159 static struct list_head dasd_devreg_head = LIST_HEAD_INIT (dasd_devreg_head);
160
161 /*
162  * function: dasd_create_devreg
163  * creates a dasd_devreg_t related to a devno
164  */
165 static inline dasd_devreg_t *
166 dasd_create_devreg (int devno)
167 {
168         dasd_devreg_t *r = kmalloc (sizeof (dasd_devreg_t), GFP_KERNEL);
169         if (r != NULL) {
170                 memset (r, 0, sizeof (dasd_devreg_t));
171                 r->devreg.ci.devno = devno;
172                 r->devreg.flag = DEVREG_TYPE_DEVNO;
173                 r->devreg.oper_func = dasd_oper_handler;
174         }
175         return r;
176 }
177
178 /*
179  * function: dasd_destroy_devreg
180  * destroys the dasd_devreg_t given as argument
181  */
182 static inline void
183 dasd_destroy_devreg (dasd_devreg_t * devreg)
184 {
185         kfree (devreg);
186 }
187
188 #endif                          /* CONFIG_DASD_DYNAMIC */
189
190 /* SECTION: managing setup of dasd_driver */
191
192 /* default setting is probeonly, autodetect */
193 static int dasd_probeonly = 1;  /* is true, when probeonly mode is active */
194 static int dasd_autodetect = 1; /* is true, when autodetection is active */
195
196 static dasd_range_t dasd_range_head =
197     { list:LIST_HEAD_INIT (dasd_range_head.list) };
198 static spinlock_t range_lock = SPIN_LOCK_UNLOCKED;
199
200 /*
201  * function: dasd_create_range
202  * creates a dasd_range_t according to the arguments
203  * FIXME: no check is performed for reoccurrence of a devno
204  */
205 static inline dasd_range_t *
206 dasd_create_range (int from, int to, int features)
207 {
208         dasd_range_t *range = NULL;
209         int i;
210
211         if ( from > to ) {
212                 printk (KERN_WARNING PRINTK_HEADER 
213                         "Adding device range %04x-%04x: range invalid, ignoring.\n",
214                         from,
215                         to);
216
217                 return NULL;
218         }
219         for (i=from;i<=to;i++) {
220                 if (dasd_device_from_devno(i)) {
221                         printk (KERN_WARNING PRINTK_HEADER 
222                                 "device range %04x-%04x: device %04x is already in a range.\n",
223                                 from,
224                                 to,
225                                 i);
226                 }
227         }
228         range = (dasd_range_t *) kmalloc (sizeof (dasd_range_t), GFP_KERNEL);
229         if (range == NULL)
230                 return NULL;
231         memset (range, 0, sizeof (dasd_range_t));
232         range->from = from;
233         range->to = to;
234         range->features = features;
235         return range;
236 }
237
238 /*
239  * function dasd_destroy_range
240  * destroy a range allocated wit dasd_crate_range
241  * CAUTION: must not be callen in arunning sysztem, because it destroys
242  * the mapping of DASDs
243  */
244 static inline void
245 dasd_destroy_range (dasd_range_t * range)
246 {
247         kfree (range);
248 }
249
250 /*
251  * function: dasd_append_range
252  * appends the range given as argument to the list anchored at dasd_range_head.
253  */
254 static inline void
255 dasd_append_range (dasd_range_t * range)
256 {
257         long flags;
258
259         spin_lock_irqsave (&range_lock, flags);
260         list_add_tail (&range->list, &dasd_range_head.list);
261         spin_unlock_irqrestore (&range_lock, flags);
262 }
263
264 /*
265  * function dasd_dechain_range
266  * removes a range from the chain of ranges
267  * CAUTION: must not be called in a running system because it destroys
268  * the mapping of devices
269  */
270 static inline void
271 dasd_dechain_range (dasd_range_t * range)
272 {
273         unsigned long flags;
274
275         spin_lock_irqsave (&range_lock, flags);
276         list_del (&range->list);
277         spin_unlock_irqrestore (&range_lock, flags);
278 }
279
280 /*
281  * function: dasd_add_range
282  * creates a dasd_range_t according to the arguments and
283  * appends it to the list of ranges
284  * additionally a devreg_t is created and added to the list of devregs
285  */
286 static inline dasd_range_t *
287 dasd_add_range (int from, int to, int features)
288 {
289         dasd_range_t *range;
290
291         range = dasd_create_range (from, to, features);
292         if (!range)
293                 return NULL;
294
295         dasd_append_range (range);
296 #ifdef CONFIG_DASD_DYNAMIC
297         /* allocate and chain devreg infos for the devnos... */
298         {
299                 int i;
300                 for (i = range->from; i <= range->to; i++) {
301                         dasd_devreg_t *reg = dasd_create_devreg (i);
302                         s390_device_register (&reg->devreg);
303                         list_add (&reg->list, &dasd_devreg_head);
304                 }
305         }
306 #endif                          /* CONFIG_DASD_DYNAMIC */
307         return range;
308 }
309
310 /*
311  * function: dasd_remove_range
312  * removes a range and the corresponding devregs from all of the chains
313  * CAUTION: must not be called in a running system because it destroys
314  * the mapping of devices!
315  */
316 static inline void
317 dasd_remove_range (dasd_range_t * range)
318 {
319 #ifdef CONFIG_DASD_DYNAMIC
320         /* deallocate and dechain devreg infos for the devnos... */
321         {
322                 int i;
323                 for (i = range->from; i <= range->to; i++) {
324                         struct list_head *l;
325                         dasd_devreg_t *reg = NULL;
326                         list_for_each (l, &dasd_devreg_head) {
327                                 reg = list_entry (l, dasd_devreg_t, list);
328                                 if (reg->devreg.flag == DEVREG_TYPE_DEVNO &&
329                                     reg->devreg.ci.devno == i &&
330                                     reg->devreg.oper_func == dasd_oper_handler)
331                                         break;
332                         }
333                         if (l == &dasd_devreg_head)
334                                 BUG ();
335                         list_del(&reg->list);
336                         s390_device_unregister (&reg->devreg);
337                         dasd_destroy_devreg (reg);
338                 }
339         }
340 #endif                          /* CONFIG_DASD_DYNAMIC */
341         dasd_dechain_range (range);
342         dasd_destroy_range (range);
343 }
344
345 /* 
346  * function: dasd_devindex_from_devno
347  * finds the logical number of the devno supplied as argument in the list
348  * of dasd ranges and returns it or ENODEV when not found
349  */
350 static int
351 dasd_devindex_from_devno (int devno)
352 {
353         dasd_range_t *temp;
354         int devindex = 0;
355         unsigned long flags;
356         struct list_head *l;
357
358         spin_lock_irqsave (&range_lock, flags);
359         list_for_each (l, &dasd_range_head.list) {
360                 temp = list_entry (l, dasd_range_t, list);
361                 if (devno >= temp->from && devno <= temp->to) {
362                         spin_unlock_irqrestore (&range_lock, flags);
363                         return devindex + devno - temp->from;
364                 }
365                 devindex += temp->to - temp->from + 1;
366         }
367         spin_unlock_irqrestore (&range_lock, flags);
368         return -ENODEV;
369 }
370
371 /*
372  * function: dasd_devno_from_devindex
373  */
374 static int
375 dasd_devno_from_devindex (int devindex)
376 {
377         dasd_range_t *temp;
378         unsigned long flags;
379         struct list_head *l;
380
381         spin_lock_irqsave (&range_lock, flags);
382         list_for_each (l, &dasd_range_head.list) {
383                 temp = list_entry (l, dasd_range_t, list);
384                 if ( devindex < temp->to - temp->from + 1) {
385                         spin_unlock_irqrestore (&range_lock, flags);
386                         return temp->from + devindex;
387                 }
388                 devindex -= temp->to - temp->from + 1;
389         }
390         spin_unlock_irqrestore (&range_lock, flags);
391         return -ENODEV;
392 }
393
394 /* SECTION: parsing the dasd= parameter of the parmline/insmod cmdline */
395
396 /*
397  * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
398  * it is named 'dasd' to directly be filled by insmod with the comma separated
399  * strings when running as a module.
400  * a maximum of 256 ranges can be supplied, as the parmline is limited to
401  * <1024 Byte anyway.
402  */
403 char *dasd[256];
404 char *dasd_disciplines[8];
405
406 #ifndef MODULE
407 /*
408  * function: dasd_split_parm_string
409  * splits the parmline given to the kernel into comma separated strings
410  * which are filled into the 'dasd[]' array, to be parsed later on
411  */
412 static void
413 dasd_split_parm_string (char *str)
414 {
415         char *tmp = str;
416         int count = 0;
417         while (tmp != NULL && *tmp != '\0') {
418                 char *end;
419                 int len;
420                 end = strchr (tmp, ',');
421                 if (end == NULL) {
422                         len = strlen (tmp) + 1;
423                 } else {
424                         len = (long) end - (long) tmp + 1;
425                         *end = '\0';
426                         end++;
427                 }
428                 dasd[count] = kmalloc (len * sizeof (char), GFP_ATOMIC);
429                 if (dasd[count] == NULL) {
430                         printk (KERN_WARNING PRINTK_HEADER
431                                 "can't store dasd= parameter no %d\n",
432                                 count + 1);
433                         break;
434                 }
435                 memset (dasd[count], 0, len * sizeof (char));
436                 memcpy (dasd[count], tmp, len * sizeof (char));
437                 count++;
438                 tmp = end;
439         };
440 }
441
442 /*
443  * dasd_parm_string holds a concatenated version of all 'dasd=' parameters
444  * supplied in the parmline, which is later to be split by
445  * dasd_split_parm_string
446  * FIXME: why first concatenate then split ?
447  */
448 static char dasd_parm_string[1024] __initdata = { 0, };
449
450 /*
451  * function: dasd_setup
452  * is invoked for any single 'dasd=' parameter supplied in the parmline
453  * it merges all the arguments into dasd_parm_string
454  */
455 void __init
456 dasd_setup (char *str, int *ints)
457 {
458         int len = strlen (dasd_parm_string);
459         if (len != 0) {
460                 strcat (dasd_parm_string, ",");
461         }
462         strcat (dasd_parm_string, str);
463 }
464
465 /*
466  * function: dasd_call_setup
467  * is the 2.4 version of dasd_setup and
468  * is invoked for any single 'dasd=' parameter supplied in the parmline
469  */
470 int __init
471 dasd_call_setup (char *str)
472 {
473         int dummy;
474         dasd_setup (str, &dummy);
475         return 1;
476 }
477
478 int __init
479 dasd_disciplines_setup (char *str)
480 {
481         return 1;
482 }
483
484 __setup ("dasd=", dasd_call_setup);
485 __setup ("dasd_disciplines=", dasd_disciplines_setup);
486
487 #endif                          /* MODULE */
488
489 /*
490  * function: dasd_strtoul
491  * provides a wrapper to simple_strtoul to strip leading '0x' and
492  * interpret any argument to dasd=[range,...] as hexadecimal
493  */
494 static inline int
495 dasd_strtoul (char *str, char **stra, int* features)
496 {
497         char *temp=str;
498         char *buffer;
499         int val,i,start;
500
501         buffer=(char*)kmalloc((strlen(str)+1)*sizeof(char),GFP_ATOMIC);
502         if (buffer==NULL) {
503             printk (KERN_WARNING PRINTK_HEADER
504                     "can't parse dasd= parameter %s due to low memory\n",
505                     str);
506         }
507
508         /* remove leading '0x' */
509         if (*temp == '0') {
510                 temp++;         /* strip leading zero */
511                 if (*temp == 'x')
512                         temp++; /* strip leading x */
513         }
514
515         /* copy device no to buffer and convert to decimal */
516         for (i=0; temp[i]!='\0' && temp[i]!='(' && 
517                   temp[i]!='-'  && temp[i]!=' '; i++){
518                 if (isxdigit(temp[i])) {
519                         buffer[i]=temp[i];
520                 } else {
521                         return -EINVAL;
522                 }
523         }
524
525         buffer[i]='\0';
526
527         val = simple_strtoul (buffer, &buffer, 16);
528
529         /* check for features - e.g. (ro) ; the '\0', ')' and '-' stops check */
530         *features = DASD_DEFAULT_FEATURES;
531
532         if (temp[i]=='(') {
533
534                 while (temp[i]!='\0' && temp[i]!=')'&&temp[i]!='-') { 
535                         start=++i;      
536         
537                         /* move next feature to buffer */
538                         for (;temp[i]!='\0'&&temp[i]!=':'&&temp[i]!=')'&&temp[i]!='-';i++)
539                                 buffer[i-start]=temp[i];
540                         buffer[i-start]='\0';
541
542                         if (strlen(buffer)) { 
543                                 if (!strcmp(buffer,"ro")) { /* handle 'ro' feature */
544                                         (*features) |= DASD_FEATURE_READONLY;
545                                         break;
546                                 }
547                                 printk (KERN_WARNING PRINTK_HEADER 
548                                         "unsupported feature: %s, ignoring setting",
549                                         buffer);
550                         }
551                 }
552         }
553
554         *stra = temp+i;
555         return val;
556 }
557
558 /*
559  * function: dasd_parse
560  * examines the strings given in the string array str and
561  * creates and adds the ranges to the apropriate lists
562  */
563 static int
564 dasd_parse (char **str)
565 {
566         char *temp;
567         int from, to;
568         int features;
569         int rc = 0;
570
571         if (*str) {
572                 /* turn off probeonly mode, if any dasd parameter is present */
573                 dasd_probeonly = 0;
574                 dasd_autodetect = 0;
575         }
576         while (*str) {
577                 temp = *str;
578                 from = 0;
579                 to = 0;
580                 if (strcmp ("autodetect", *str) == 0) {
581                         dasd_autodetect = 1;
582                         printk (KERN_INFO "turning to autodetection mode\n");
583                         break;
584                 } else if (strcmp ("probeonly", *str) == 0) {
585                         dasd_probeonly = 1;
586                         printk (KERN_INFO "turning to probeonly mode\n");
587                         break;
588                 } else {
589                         /* turn off autodetect mode, if any range is present */
590                         dasd_autodetect = 0;
591                         from = dasd_strtoul (temp, &temp, &features);
592                         to = from;
593                         if (*temp == '-') {
594                                 temp++;
595                                 to = dasd_strtoul (temp, &temp, &features);
596                         }
597                         if (from == -EINVAL ||
598                             to   == -EINVAL    ) {
599                                 rc = -EINVAL;
600                                 break;
601                         } else {
602                                 dasd_add_range (from, to ,features);
603                         }
604                 }
605                 str++;
606         }
607
608         return rc;
609 }
610
611 /* SECTION: Dealing with devices registered to multiple major numbers */
612
613 static spinlock_t dasd_major_lock = SPIN_LOCK_UNLOCKED;
614
615 static major_info_t dasd_major_info[] = {
616         {
617               list:LIST_HEAD_INIT (dasd_major_info[1].list)
618          },
619         {
620               list:LIST_HEAD_INIT (dasd_major_info[0].list),
621               gendisk:{
622           INIT_GENDISK (94, DASD_NAME, DASD_PARTN_BITS, DASD_PER_MAJOR)
623           },
624       flags:DASD_MAJOR_INFO_IS_STATIC}
625 };
626
627 static major_info_t *
628 get_new_major_info (void)
629 {
630         major_info_t *major_info = NULL;
631
632         major_info = kmalloc (sizeof (major_info_t), GFP_KERNEL);
633         if (major_info) {
634                 static major_info_t temp_major_info = {
635                         gendisk:{
636                                  INIT_GENDISK (0, DASD_NAME, DASD_PARTN_BITS,
637                                                DASD_PER_MAJOR)}
638                 };
639                 memcpy (major_info, &temp_major_info, sizeof (major_info_t));
640         }
641         return major_info;
642 }
643
644 /*
645  * register major number
646  * is called with the 'static' major_info during init of the driver or 'NULL' to
647  * allocate an additional dynamic major.
648  */
649 static int
650 dasd_register_major (major_info_t * major_info)
651 {
652         int rc = 0;
653         int major;
654         unsigned long flags;
655
656         /* allocate dynamic major */
657         if (major_info == NULL) {
658                 major_info = get_new_major_info ();
659                 if (!major_info) {
660                         printk (KERN_WARNING PRINTK_HEADER
661                                 "Cannot get memory to allocate another major number\n");
662                         return -ENOMEM;
663                 }
664         }
665
666         major = major_info->gendisk.major;
667
668         /* init devfs array */
669         major_info->gendisk.de_arr = (devfs_handle_t *)
670             kmalloc (DASD_PER_MAJOR * sizeof (devfs_handle_t), GFP_KERNEL);
671         memset (major_info->gendisk.de_arr, 0,
672                 DASD_PER_MAJOR * sizeof (devfs_handle_t));
673
674         /* init flags */
675         major_info->gendisk.flags = (char *)
676             kmalloc (DASD_PER_MAJOR * sizeof (char), GFP_KERNEL);
677         memset (major_info->gendisk.flags, 0, DASD_PER_MAJOR * sizeof (char));
678
679         /* register blockdevice */
680         rc = devfs_register_blkdev (major, DASD_NAME, &dasd_device_operations);
681         if (rc < 0) {
682                 printk (KERN_WARNING PRINTK_HEADER
683                         "Cannot register to major no %d, rc = %d\n",
684                         major, 
685                         rc);
686                 goto out_reg_blkdev; 
687         } else {
688                 major_info->flags |= DASD_MAJOR_INFO_REGISTERED;
689         }
690
691         /* Insert the new major info into dasd_major_info if needed (dynamic major) */
692         if (!(major_info->flags & DASD_MAJOR_INFO_IS_STATIC)) {
693                 spin_lock_irqsave (&dasd_major_lock, flags);
694                 list_add_tail (&major_info->list, &dasd_major_info[0].list);
695                 spin_unlock_irqrestore (&dasd_major_lock, flags);
696         }
697
698         if (major == 0) {
699                 major = rc;
700                 rc = 0;
701         }
702
703         /* init array of devices */
704         major_info->dasd_device =
705             (dasd_device_t **) kmalloc (DASD_PER_MAJOR *
706                                         sizeof (dasd_device_t *), GFP_ATOMIC);
707         if (!major_info->dasd_device)
708                 goto out_devices;
709         memset (major_info->dasd_device, 0,
710                 DASD_PER_MAJOR * sizeof (dasd_device_t *));
711
712         /* init blk_size */
713         blk_size[major] =
714             (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
715         if (!blk_size[major])
716                 goto out_blk_size;
717         memset (blk_size[major], 0, (1 << MINORBITS) * sizeof (int));
718
719         /* init blksize_size */
720         blksize_size[major] =
721             (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
722         if (!blksize_size[major])
723                 goto out_blksize_size;
724         memset (blksize_size[major], 0, (1 << MINORBITS) * sizeof (int));
725
726         /* init_hardsect_size */
727         hardsect_size[major] =
728             (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
729         if (!hardsect_size[major])
730                 goto out_hardsect_size;
731         memset (hardsect_size[major], 0, (1 << MINORBITS) * sizeof (int));
732
733         /* finally do the gendisk stuff */
734         major_info->gendisk.part = kmalloc ((1 << MINORBITS) *
735                                             sizeof (struct hd_struct),
736                                             GFP_ATOMIC);
737         if (!major_info->gendisk.part)
738                 goto out_gendisk;
739         memset (major_info->gendisk.part, 0, (1 << MINORBITS) *
740                 sizeof (struct hd_struct));
741
742         INIT_BLK_DEV (major, do_dasd_request, dasd_get_queue, NULL);
743
744         major_info->gendisk.sizes = blk_size[major];
745         major_info->gendisk.major = major;
746         add_gendisk (&major_info->gendisk);
747         return major;
748
749         /* error handling - free the prior allocated memory */  
750       out_gendisk:
751         kfree (hardsect_size[major]);
752         hardsect_size[major] = NULL;
753
754       out_hardsect_size:
755         kfree (blksize_size[major]);
756         blksize_size[major] = NULL;
757
758       out_blksize_size:
759         kfree (blk_size[major]);
760         blk_size[major] = NULL;
761
762       out_blk_size:
763         kfree (major_info->dasd_device);
764
765       out_devices:
766         /* Delete the new major info from dasd_major_info list if needed (dynamic) +*/
767         if (!(major_info->flags & DASD_MAJOR_INFO_IS_STATIC)) {
768                 spin_lock_irqsave (&dasd_major_lock, flags);
769                 list_del (&major_info->list);
770                 spin_unlock_irqrestore (&dasd_major_lock, flags);
771         }
772
773         /* unregister blockdevice */
774         rc = devfs_unregister_blkdev (major, DASD_NAME);
775         if (rc < 0) {
776                 printk (KERN_WARNING PRINTK_HEADER
777                         "Unable to unregister from major no %d, rc = %d\n", 
778                         major,
779                         rc);
780         } else {
781                 major_info->flags &= ~DASD_MAJOR_INFO_REGISTERED;
782         }
783
784       out_reg_blkdev:
785         kfree (major_info->gendisk.flags);
786         kfree (major_info->gendisk.de_arr);
787
788         /* Delete the new major info from dasd_major_info if needed */
789         if (!(major_info->flags & DASD_MAJOR_INFO_IS_STATIC)) {
790                 kfree (major_info);
791         }
792
793         return -ENOMEM;
794 }
795
796 static int
797 dasd_unregister_major (major_info_t * major_info)
798 {
799         int rc = 0;
800         int major;
801         unsigned long flags;
802
803         if (major_info == NULL) {
804                 return -EINVAL;
805         }
806         major = major_info->gendisk.major;
807         INIT_BLK_DEV (major, NULL, NULL, NULL);
808
809         del_gendisk (&major_info->gendisk);
810
811         kfree (major_info->dasd_device);
812         kfree (major_info->gendisk.part);
813
814         kfree (blk_size[major]);
815         kfree (blksize_size[major]);
816         kfree (hardsect_size[major]);
817
818         blk_clear(major);
819
820         rc = devfs_unregister_blkdev (major, DASD_NAME);
821         if (rc < 0) {
822                 printk (KERN_WARNING PRINTK_HEADER
823                         "Cannot unregister from major no %d, rc = %d\n",
824                         major,
825                         rc);
826                 return rc;
827         } else {
828                 major_info->flags &= ~DASD_MAJOR_INFO_REGISTERED;
829         }
830
831         kfree (major_info->gendisk.flags);
832         kfree (major_info->gendisk.de_arr);
833
834         /* Delete the new major info from dasd_major_info if needed */
835         if (!(major_info->flags & DASD_MAJOR_INFO_IS_STATIC)) {
836                 spin_lock_irqsave (&dasd_major_lock, flags);
837                 list_del (&major_info->list);
838                 spin_unlock_irqrestore (&dasd_major_lock, flags);
839                 kfree (major_info);
840         }
841         return rc;
842 }
843
844 /*
845  * function: dasd_device_from_kdev
846  * finds the device structure corresponding to the kdev supplied as argument
847  * in the major_info structures and returns it or NULL when not found
848  */
849 static inline dasd_device_t *
850 dasd_device_from_kdev (kdev_t kdev)
851 {
852         major_info_t *major_info = NULL;
853         struct list_head *l;
854         unsigned long flags;
855
856         spin_lock_irqsave (&dasd_major_lock, flags);
857         list_for_each (l, &dasd_major_info[0].list) {
858                 major_info = list_entry (l, major_info_t, list);
859                 if (major_info->gendisk.major == MAJOR (kdev))
860                         break;
861         }
862         spin_unlock_irqrestore (&dasd_major_lock, flags);
863         if (major_info != &dasd_major_info[0])
864                 return major_info->dasd_device[MINOR (kdev) >> DASD_PARTN_BITS];
865         return NULL;
866 }
867
868 /*
869  * function: dasd_device_from_devno
870  * finds the address of the device structure corresponding to the devno
871  * supplied as argument in the major_info structures and returns
872  * it or NULL when not found
873  */
874 static inline dasd_device_t **
875 dasd_device_from_devno (int devno)
876 {
877         major_info_t *major_info;
878         struct list_head *l;
879         int devindex = dasd_devindex_from_devno (devno);
880         unsigned long flags;
881
882         spin_lock_irqsave (&dasd_major_lock, flags);
883         list_for_each (l, &dasd_major_info[0].list) {
884                 major_info = list_entry (l, major_info_t, list);
885                 if (devindex < DASD_PER_MAJOR) {
886                         spin_unlock_irqrestore (&dasd_major_lock, flags);
887                         return &major_info->dasd_device[devindex];
888                 }
889                 devindex -= DASD_PER_MAJOR;
890         }
891         spin_unlock_irqrestore (&dasd_major_lock, flags);
892         return NULL;
893 }
894
895 /*
896  * function: dasd_features_from_devno
897  * finds the device range corresponding to the devno
898  * supplied as argument in the major_info structures and returns
899  * the features set for it
900  */
901
902 static int
903 dasd_features_from_devno (int devno)
904 {
905         dasd_range_t *temp;
906         int devindex = 0;
907         unsigned long flags;
908         struct list_head *l;
909
910         spin_lock_irqsave (&range_lock, flags);
911         list_for_each (l, &dasd_range_head.list) {
912                 temp = list_entry (l, dasd_range_t, list);
913                 if (devno >= temp->from && devno <= temp->to) {
914                         spin_unlock_irqrestore (&range_lock, flags);
915                         return temp->features;
916                 }
917                 devindex += temp->to - temp->from + 1;
918         }
919         spin_unlock_irqrestore (&range_lock, flags);
920         return -ENODEV;
921 }
922
923
924
925 /* SECTION: managing dasd disciplines */
926
927 /* anchor and spinlock for list of disciplines */
928 static struct list_head dasd_disc_head = LIST_HEAD_INIT(dasd_disc_head);
929 static spinlock_t discipline_lock = SPIN_LOCK_UNLOCKED;
930
931 /*
932  * function dasd_discipline_enq
933  * chains the discpline given as argument to the head of disiplines
934  * head chaining policy is required to allow module disciplines to
935  * be preferred against those, who are statically linked
936  */
937 static inline void
938 dasd_discipline_enq (dasd_discipline_t * d)
939 {
940     list_add(&d->list, &dasd_disc_head);
941 }
942
943 /*
944  * function dasd_discipline_deq
945  * removes the discipline given as argument from the list of disciplines
946  */
947 static inline void
948 dasd_discipline_deq (dasd_discipline_t * d)
949 {
950         list_del(&d->list);
951 }
952
953 void
954 dasd_discipline_add (dasd_discipline_t * d)
955 {
956         unsigned long flags;
957         MOD_INC_USE_COUNT;
958         spin_lock_irqsave (&discipline_lock,flags);
959         dasd_discipline_enq (d);
960         spin_unlock_irqrestore (&discipline_lock,flags);
961         dasd_enable_ranges (&dasd_range_head, d, DASD_STATE_ONLINE);
962 }
963
964 void dasd_discipline_del (dasd_discipline_t * d)
965 {
966         unsigned long flags;
967         spin_lock_irqsave (&discipline_lock,flags);
968         dasd_disable_ranges(&dasd_range_head, d, DASD_STATE_DEL, 1);
969         dasd_discipline_deq (d);
970         spin_unlock_irqrestore (&discipline_lock,flags);
971         MOD_DEC_USE_COUNT;
972 }
973
974 static inline dasd_discipline_t *
975 dasd_find_disc (dasd_device_t * device, dasd_discipline_t *d)
976 {
977         dasd_discipline_t *t;
978         struct list_head *l = d ? &d->list : dasd_disc_head.next;
979         do {
980                 t = list_entry(l,dasd_discipline_t,list);
981                 if ( ( t->id_check == NULL ||
982                        t->id_check (&device->devinfo) == 0 ) &&
983                      ( t->check_characteristics == NULL ||
984                        t->check_characteristics (device) == 0 ) )
985                         break;
986                 l = l->next;
987                 if ( d || 
988                      l == &dasd_disc_head ) {
989                         t = NULL;
990                         break;
991                 }
992          } while ( 1 );
993         return t;
994 }
995
996 /* SECTION: profiling stuff */
997
998 static dasd_profile_info_t dasd_global_profile;
999
1000 #ifdef DASD_PROFILE
1001 /*
1002  * macro: dasd_profile_add_counter
1003  * increments counter in global and local profiling structures
1004  * according to the value
1005  */
1006 #define dasd_profile_add_counter( value, counter, device ) \
1007 { \
1008         int ind; \
1009         long help; \
1010         for (ind = 0, help = value >> 3; \
1011              ind < 31 && help; \
1012              help = help >> 1, ind++) {} \
1013         dasd_global_profile.counter[ind]++; \
1014         device->profile.counter[ind]++; \
1015 }
1016
1017 /*
1018  * function dasd_profile_add
1019  * adds the profiling information from the cqr given as argument to the
1020  * global and device specific profiling information
1021  */
1022 void
1023 dasd_profile_add (ccw_req_t * cqr)
1024 {
1025         long strtime, irqtime, endtime, tottime; /* in microsecnds*/
1026         long tottimeps, sectors;
1027         dasd_device_t *device = cqr->device;
1028
1029         if (!cqr->req)          /* safeguard against abnormal cqrs */
1030                 return;
1031
1032         if ((!cqr->buildclk) ||
1033             (!cqr->startclk) ||
1034             (!cqr->stopclk ) ||
1035             (!cqr->endclk  ) ||
1036             (!(sectors = ((struct request *) (cqr->req))->nr_sectors)))
1037                 return;
1038
1039         strtime = ((cqr->startclk - cqr->buildclk) >> 12);
1040         irqtime = ((cqr->stopclk - cqr->startclk) >> 12);
1041         endtime = ((cqr->endclk - cqr->stopclk) >> 12);
1042         tottime = ((cqr->endclk - cqr->buildclk) >> 12);
1043         tottimeps = tottime / sectors;
1044
1045         if (!dasd_global_profile.dasd_io_reqs) {
1046                 memset (&dasd_global_profile, 0, sizeof (dasd_profile_info_t));
1047         };
1048         if (!device->profile.dasd_io_reqs) {
1049                 memset (&device->profile, 0, sizeof (dasd_profile_info_t));
1050         };
1051
1052         dasd_global_profile.dasd_io_reqs++;
1053         device->profile.dasd_io_reqs++;
1054         dasd_global_profile.dasd_io_sects+=sectors;
1055         device->profile.dasd_io_sects+=sectors;
1056         dasd_profile_add_counter (sectors, dasd_io_secs, device);
1057         dasd_profile_add_counter (tottime, dasd_io_times, device);
1058         dasd_profile_add_counter (tottimeps, dasd_io_timps, device);
1059         dasd_profile_add_counter (strtime, dasd_io_time1, device);
1060         dasd_profile_add_counter (irqtime, dasd_io_time2, device);
1061         dasd_profile_add_counter (irqtime / sectors, dasd_io_time2ps, device);
1062         dasd_profile_add_counter (endtime, dasd_io_time3, device);
1063 }
1064 #endif
1065
1066 /* SECTION: All the gendisk stuff */
1067
1068
1069 /* SECTION: Managing wrappers for ccwcache */
1070
1071 /*
1072  * function dasd_alloc_request
1073  * tries to return space for a channel program of length cplength with
1074  * additional data of size datasize.
1075  * If the ccwcache cannot fulfill the request it tries the emergeny requests
1076  * before giving up finally
1077  * FIXME: initialization of ccw_req_t should be done by function of ccwcache
1078  */
1079 ccw_req_t *
1080 dasd_alloc_request (char *magic, int cplength, int datasize, dasd_device_t* device)
1081 {
1082         ccw_req_t *rv = NULL;
1083
1084         if ((rv = ccw_alloc_request (magic, cplength, datasize)) != NULL) {
1085                 return rv;
1086         }
1087         if ((((sizeof (ccw_req_t) + 7) & -8) +
1088              cplength * sizeof (ccw1_t) + datasize) > PAGE_SIZE) {
1089                 BUG ();
1090                 }
1091         if (device->lowmem_cqr==NULL) {
1092                 DASD_DRIVER_DEBUG_EVENT (2, dasd_alloc_request,
1093                                          "(%04x) Low memory! Using emergency request %p.",
1094                                          device->devinfo.devno,
1095                                          device->lowmem_ccws);
1096
1097                 device->lowmem_cqr=device->lowmem_ccws;
1098                 rv = device->lowmem_ccws;
1099                 memset (rv, 0, PAGE_SIZE);
1100                 strncpy ((char *) (&rv->magic), magic, 4);
1101                 ASCEBC ((char *) (&rv->magic), 4);
1102                 rv->cplength = cplength;
1103                 rv->datasize = datasize;
1104                 rv->data = (void *) ((long) rv + PAGE_SIZE - datasize);
1105                 rv->cpaddr = (ccw1_t *) ((long) rv + sizeof (ccw_req_t));
1106         } else {
1107                 DASD_DRIVER_DEBUG_EVENT (2, dasd_alloc_request,
1108                                          "(%04x) Refusing emergency mem for request "
1109                                          "NULL, already in use at %p.",
1110                                          device->devinfo.devno,
1111                                          device->lowmem_ccws);
1112         }
1113         return rv;
1114 }
1115
1116 /*
1117  * function dasd_free_request
1118  * returns a ccw_req_t to the appropriate cache or emergeny request line
1119  */
1120 void
1121 dasd_free_request (ccw_req_t * request, dasd_device_t* device)
1122 {
1123 #ifdef CONFIG_ARCH_S390X
1124         ccw1_t* ccw;
1125         /* clear any idals used for chain */
1126         ccw=request->cpaddr-1;
1127         do {
1128                 ccw++;
1129                 if ((ccw->cda < (unsigned long) device->lowmem_idals           ) || 
1130                     (ccw->cda >= (unsigned long) device->lowmem_idals+PAGE_SIZE)   )
1131                         clear_normalized_cda (ccw);
1132                 else {
1133                         if (device->lowmem_idal_ptr != device->lowmem_idals)
1134                                 DASD_MESSAGE (KERN_WARNING, device,
1135                                               "Freeing emergency idals from request at %p.",
1136                                               request);
1137                         device->lowmem_idal_ptr = device->lowmem_idals;
1138                         device->lowmem_cqr=NULL;
1139                 }
1140         } while ((ccw->flags & CCW_FLAG_CC) || 
1141                  (ccw->flags & CCW_FLAG_DC)   );
1142 #endif
1143         if (request != device->lowmem_ccws) { 
1144                 /* compare to lowmem_ccws to protect usage of lowmem_cqr for IDAL only ! */
1145                 ccw_free_request (request);
1146         } else {
1147                 DASD_MESSAGE (KERN_WARNING, device,
1148                               "Freeing emergency request at %p",
1149                               request);
1150                 device->lowmem_cqr=NULL;
1151         }
1152 }
1153
1154 int
1155 dasd_set_normalized_cda (ccw1_t * cp, unsigned long address, 
1156                          ccw_req_t* request, dasd_device_t* device )
1157 {
1158 #ifdef CONFIG_ARCH_S390X
1159         int nridaws;
1160         int count = cp->count;
1161         
1162         if (set_normalized_cda (cp, address)!=-ENOMEM) {
1163                 return 0;
1164         }
1165
1166         if ((device->lowmem_cqr!=NULL) && (device->lowmem_cqr!=request)) {
1167                 DASD_MESSAGE (KERN_WARNING, device, 
1168                               "Refusing emergency idals for request %p, memory"
1169                               " is already in use for request %p",
1170                               request,
1171                               device->lowmem_cqr);
1172                 return -ENOMEM;
1173         }
1174         device->lowmem_cqr=request;
1175         if (device->lowmem_idal_ptr == device->lowmem_idals) {
1176             DASD_MESSAGE (KERN_WARNING,device, 
1177                           "Low memory! Using emergency IDALs for request %p.\n",
1178                           request);
1179         }
1180         nridaws = ((address & (IDA_BLOCK_SIZE-1)) + count + 
1181                    (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
1182         if ( device->lowmem_idal_ptr>=device->lowmem_idals + PAGE_SIZE ) {
1183                 /* Ouch! No Idals left for emergency request */
1184                 BUG();
1185         }
1186         cp->flags |= CCW_FLAG_IDA;
1187         cp->cda = (__u32)(unsigned long)device->lowmem_idal_ptr;
1188         do {
1189                 *((long*)device->lowmem_idal_ptr) = address;
1190                 address = (address & -(IDA_BLOCK_SIZE)) + (IDA_BLOCK_SIZE);
1191                 nridaws --;
1192                 device->lowmem_idal_ptr += sizeof(unsigned long);
1193         } while ( nridaws > 0 );
1194 #else 
1195         cp -> cda = address;
1196 #endif
1197         return 0;
1198 }
1199
1200
1201 /* SECTION: (de)queueing of requests to channel program queues */
1202
1203 /*
1204  * function dasd_chanq_enq
1205  * appends the cqr given as argument to the queue
1206  * has to be called with the queue lock (namely the s390_irq_lock) acquired
1207  */
1208 inline void
1209 dasd_chanq_enq (dasd_chanq_t * q, ccw_req_t * cqr)
1210 {
1211         if (q->head != NULL) {
1212                 q->tail->next = cqr;
1213         } else
1214                 q->head = cqr;
1215         cqr->next = NULL;
1216         q->tail = cqr;
1217         check_then_set (&cqr->status, 
1218                         CQR_STATUS_FILLED, 
1219                         CQR_STATUS_QUEUED);
1220
1221        
1222 #ifdef DASD_PROFILE
1223         /* save profile information for non erp cqr */
1224         if (cqr->refers == NULL) {
1225                 unsigned int  counter = 0;
1226                 ccw_req_t     *ptr;
1227                 dasd_device_t *device = cqr->device;
1228
1229                 /* count the length of the chanq for statistics */
1230                 for (ptr = q->head; 
1231                      ptr->next != NULL && counter <=31; 
1232                      ptr = ptr->next) {
1233                         counter++;
1234                 }                
1235                 
1236                 dasd_global_profile.dasd_io_nr_req[counter]++;
1237                 device->profile.dasd_io_nr_req[counter]++;
1238         }
1239 #endif 
1240 }
1241
1242 /*
1243  * function dasd_chanq_enq_head
1244  * chains the cqr given as argument to the queue head
1245  * has to be called with the queue lock (namely the s390_irq_lock) acquired
1246  */
1247 inline void
1248 dasd_chanq_enq_head (dasd_chanq_t * q, ccw_req_t * cqr)
1249 {
1250         cqr->next = q->head;
1251         q->head = cqr;
1252         if (q->tail == NULL)
1253                 q->tail = cqr;
1254         check_then_set (&cqr->status, CQR_STATUS_FILLED, CQR_STATUS_QUEUED);
1255 }
1256
1257 /*
1258  * function dasd_chanq_deq
1259  * dechains the cqr given as argument from the queue
1260  * has to be called with the queue lock (namely the s390_irq_lock) acquired
1261  */
1262 inline void
1263 dasd_chanq_deq (dasd_chanq_t * q, ccw_req_t * cqr)
1264 {
1265         ccw_req_t *prev;
1266
1267         if (cqr == NULL)
1268                 BUG ();
1269
1270         if (cqr == q->head) {
1271                 q->head = cqr->next;
1272                 if (q->head == NULL)
1273                         q->tail = NULL;
1274
1275         } else {
1276                 prev = q->head;
1277                 while (prev && prev->next != cqr)
1278                         prev = prev->next;
1279                 if (prev == NULL)
1280                         return;
1281                 prev->next = cqr->next;
1282                 if (prev->next == NULL)
1283                         q->tail = prev;
1284         }
1285         cqr->next = NULL;
1286 }
1287
1288 /* SECTION: Managing the device queues etc. */
1289
1290 /*
1291  * DASD_TERM_IO
1292  *
1293  * attempts to terminate the the current IO and set it to failed if termination
1294  * was successful.
1295  * returns an appropriate return code
1296  */
1297 int
1298 dasd_term_IO (ccw_req_t * cqr)
1299 {
1300         int rc = 0;
1301         dasd_device_t *device = cqr->device;
1302         int irq;
1303         int retries = 0;
1304
1305         if (!cqr) {
1306                 BUG ();
1307         }
1308         irq = device->devinfo.irq;
1309         if (strncmp ((char *) &cqr->magic, device->discipline->ebcname, 4)) {
1310                 DASD_MESSAGE (KERN_WARNING, device,
1311                               " ccw_req_t 0x%08x magic doesn't match"
1312                               " discipline 0x%08x\n",
1313                               cqr->magic,
1314                               *(unsigned int *) device->discipline->name);
1315                 return -EINVAL;
1316         }
1317         
1318         while ((retries < 5                    ) &&
1319                (cqr->status == CQR_STATUS_IN_IO)   ) {
1320
1321                 if ( retries < 2 )
1322                         rc = halt_IO(irq, (long)cqr, 
1323                                      cqr->options | DOIO_WAIT_FOR_INTERRUPT);
1324                 else
1325                         rc = clear_IO(irq, (long)cqr, 
1326                                       cqr->options | DOIO_WAIT_FOR_INTERRUPT);
1327
1328                 switch (rc) {
1329                 case 0:         /* termination successful */
1330                         check_then_set (&cqr->status,
1331                                         CQR_STATUS_IN_IO, 
1332                                         CQR_STATUS_FAILED);
1333                         
1334                         asm volatile ("STCK %0":"=m" (cqr->stopclk));
1335                         break;
1336                 case -ENODEV:
1337                         DASD_MESSAGE (KERN_WARNING, device, "%s",
1338                                       "device gone, retry\n");
1339                         break;
1340                 case -EIO:
1341                         DASD_MESSAGE (KERN_WARNING, device, "%s",
1342                                       "I/O error, retry\n");
1343                         break;
1344                 case -EBUSY:
1345                         DASD_MESSAGE (KERN_WARNING, device, "%s",
1346                                       "device busy, retry later\n");
1347                         break;
1348                 default:
1349                         DASD_MESSAGE (KERN_ERR, device,
1350                                       "line %d unknown RC=%d, please report"
1351                                       " to linux390@de.ibm.com\n", 
1352                                       __LINE__, 
1353                                       rc);
1354                         BUG ();
1355                         break;
1356                 }
1357
1358                 retries ++;
1359         }
1360         return rc;
1361 }
1362
1363 /*
1364  * function dasd_start_IO
1365  * attempts to start the IO and returns an appropriate return code
1366  */
1367 int
1368 dasd_start_IO (ccw_req_t * cqr)
1369 {
1370         int rc = 0;
1371         dasd_device_t *device = cqr->device;
1372         int irq;
1373         unsigned long long now;
1374
1375         if (!cqr) {
1376                 BUG ();
1377         }
1378         irq = device->devinfo.irq;
1379         if (strncmp ((char *) &cqr->magic, device->discipline->ebcname, 4)) {
1380                 DASD_MESSAGE (KERN_WARNING, device,
1381                               " ccw_req_t 0x%08x magic doesn't match"
1382                               " discipline 0x%08x\n",
1383                               cqr->magic,
1384                               *(unsigned int *) device->discipline->name);
1385                 return -EINVAL;
1386         }
1387
1388         asm volatile ("STCK %0":"=m" (now));
1389         cqr->startclk = now;
1390
1391         rc = do_IO (irq, cqr->cpaddr, (long) cqr, cqr->lpm, cqr->options);
1392
1393         switch (rc) {
1394         case 0:
1395                 if (cqr->options & DOIO_WAIT_FOR_INTERRUPT) {
1396                         /* request already finished (synchronous IO) */
1397                         DASD_MESSAGE (KERN_ERR, device, "%s",
1398                                       " do_IO finished request... "
1399                                       "DOIO_WAIT_FOR_INTERRUPT was set");
1400                         check_then_set (&cqr->status,
1401                                         CQR_STATUS_QUEUED, 
1402                                         CQR_STATUS_DONE);
1403
1404                         cqr->stopclk = now;
1405                         dasd_schedule_bh (device);
1406                         
1407                 } else {
1408                         check_then_set (&cqr->status,
1409                                         CQR_STATUS_QUEUED, 
1410                                         CQR_STATUS_IN_IO);
1411                 }
1412                 break;
1413         case -EBUSY:
1414                 DASD_MESSAGE (KERN_WARNING, device, "%s",
1415                               "device busy, retry later\n");
1416                 break;
1417         case -ETIMEDOUT: 
1418                 DASD_MESSAGE (KERN_WARNING, device, "%s",
1419                               "request timeout - terminated\n");
1420         case -ENODEV:
1421         case -EIO:
1422                 check_then_set (&cqr->status,
1423                                 CQR_STATUS_QUEUED, 
1424                                 CQR_STATUS_FAILED);
1425
1426                 cqr->stopclk = now;
1427                 dasd_schedule_bh (device);
1428                 break;
1429         default:
1430                 DASD_MESSAGE (KERN_ERR, device,
1431                               "line %d unknown RC=%d, please report"
1432                               " to linux390@de.ibm.com\n", __LINE__, rc);
1433                 BUG ();
1434                 break;
1435         }
1436
1437         return rc;
1438 }
1439
1440 /*
1441  * function dasd_sleep_on_req
1442  * attempts to start the IO and waits for completion
1443  * FIXME: replace handmade sleeping by wait_event
1444  */
1445 int
1446 dasd_sleep_on_req (ccw_req_t * req)
1447 {
1448         unsigned long flags;
1449         int cs;
1450         int rc = 0;
1451         dasd_device_t *device = (dasd_device_t *) req->device;
1452
1453         if ( signal_pending(current) ) {
1454                 return -ERESTARTSYS;
1455         }
1456         s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
1457         dasd_chanq_enq (&device->queue, req);
1458         /* let the bh start the request to keep them in order */
1459         dasd_schedule_bh (device);
1460         do {
1461                 s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags);
1462                 wait_event ( device->wait_q,
1463                              (((cs = req->status) == CQR_STATUS_DONE) ||
1464                              (cs == CQR_STATUS_FAILED) ||
1465                              signal_pending(current)));
1466                 s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
1467                 if ( signal_pending(current) ) {
1468                         rc = -ERESTARTSYS;
1469                         if (req->status == CQR_STATUS_IN_IO ) 
1470                                 device->discipline->term_IO(req);
1471                         break;
1472                 } else if ( req->status == CQR_STATUS_FAILED) {
1473                         rc = -EIO;
1474                         break;
1475                 }
1476         } while (cs != CQR_STATUS_DONE && cs != CQR_STATUS_FAILED);
1477         s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags);
1478         return rc;
1479 }                               /* end dasd_sleep_on_req */
1480
1481 /*
1482  * function dasd_end_request
1483  * posts the buffer_cache about a finalized request
1484  * FIXME: for requests splitted to serveral cqrs
1485  */
1486 static inline void
1487 dasd_end_request (struct request *req, int uptodate)
1488 {
1489         while (end_that_request_first (req, uptodate, DASD_NAME)) {
1490         }
1491 #ifndef DEVICE_NO_RANDOM
1492         add_blkdev_randomness (MAJOR (req->rq_dev));
1493 #endif
1494         end_that_request_last (req);
1495         return;
1496 }
1497
1498 /*
1499  * function dasd_get_queue
1500  * returns the queue corresponding to a device behind a kdev
1501  */
1502 static request_queue_t *
1503 dasd_get_queue (kdev_t kdev)
1504 {
1505         dasd_device_t *device = dasd_device_from_kdev (kdev);
1506
1507         if (!device) {
1508                 return NULL;
1509         }
1510
1511         return device->request_queue;
1512 }
1513
1514 /*
1515  * function dasd_check_expire_time
1516  * check the request given as argument for expiration
1517  * and returns 0 if not yet expired, EIO else
1518  */
1519 static inline int
1520 dasd_check_expire_time (ccw_req_t * cqr)
1521 {
1522         unsigned long long now;
1523         int rc = 0;
1524
1525         asm volatile ("STCK %0":"=m" (now));
1526         if (cqr->expires && cqr->expires + cqr->startclk < now) {
1527                 DASD_MESSAGE (KERN_ERR, ((dasd_device_t *) cqr->device),
1528                               "IO timeout 0x%08lx%08lx usecs in req %p\n",
1529                               (long) (cqr->expires >> 44),
1530                               (long) (cqr->expires >> 12), cqr);
1531                 cqr->expires <<= 1;
1532                 rc = -EIO;
1533         }
1534         return rc;
1535 }
1536
1537 /*
1538  * function dasd_finalize_request
1539  * implemets the actions to perform, when a request is finally finished
1540  * namely in status CQR_STATUS_DONE || CQR_STATUS_FAILED
1541  */
1542 static inline void
1543 dasd_finalize_request (ccw_req_t * cqr)
1544 {
1545         dasd_device_t *device = cqr->device;
1546
1547         asm volatile ("STCK %0":"=m" (cqr->endclk));
1548         if (cqr->req) {
1549 #ifdef DASD_PROFILE
1550                 dasd_profile_add (cqr);
1551 #endif
1552                 dasd_end_request (cqr->req, (cqr->status == CQR_STATUS_DONE));
1553                 /* free request if nobody is waiting on it */
1554                 dasd_free_request (cqr, cqr->device);
1555         } else {
1556                 if ( cqr == device->init_cqr && /* bring late devices online */
1557                      device->level <= DASD_STATE_ONLINE ) { 
1558                         device->timer.function = dasd_enable_single_device; 
1559                         device->timer.data     = (unsigned long) device;
1560                         device->timer.expires  = jiffies;
1561                         add_timer(&device->timer);
1562                 }
1563                 /* notify sleeping task about finished postprocessing */
1564                 wake_up (&device->wait_q);
1565                 
1566         }
1567         return;
1568 }
1569
1570 /*
1571  * function dasd_process_queues
1572  * transfers the requests on the queue given as argument to the chanq
1573  * if possible, the request ist started on a fastpath
1574  */
1575 static void
1576 dasd_process_queues (dasd_device_t * device)
1577 {
1578         unsigned long flags;
1579         struct request *req;
1580         request_queue_t *queue = device->request_queue;
1581         dasd_chanq_t *qp = &device->queue;
1582         int irq = device->devinfo.irq;
1583         ccw_req_t *final_requests = NULL;
1584         static int chanq_min_size = DASD_MIN_SIZE_FOR_QUEUE;
1585         int chanq_max_size = DASD_CHANQ_MAX_SIZE;
1586         ccw_req_t *cqr = NULL, *temp;
1587         dasd_erp_postaction_fn_t erp_postaction;
1588
1589
1590         s390irq_spin_lock_irqsave (irq, flags);
1591
1592         /* First we dechain the requests, processed with completed status */
1593         while (qp->head &&
1594                ((qp->head->status == CQR_STATUS_DONE  ) ||
1595                 (qp->head->status == CQR_STATUS_FAILED) ||
1596                 (qp->head->status == CQR_STATUS_ERROR )   )) {
1597
1598                 dasd_erp_action_fn_t erp_action;
1599                 ccw_req_t            *erp_cqr = NULL;
1600
1601                 /*  preprocess requests with CQR_STATUS_ERROR */
1602                 if (qp->head->status == CQR_STATUS_ERROR) {
1603
1604                         qp->head->retries--; 
1605
1606                         if (qp->head->dstat->flag & DEVSTAT_HALT_FUNCTION) {
1607
1608                                 check_then_set (&qp->head->status,
1609                                                 CQR_STATUS_ERROR,
1610                                                 CQR_STATUS_FAILED);
1611
1612                                 asm volatile ("STCK %0":"=m" (qp->head->stopclk));
1613
1614                         } else if ((device->discipline->erp_action == NULL                          ) ||
1615                                    ((erp_action = device->discipline->erp_action (qp->head)) == NULL)   ) {
1616                                 
1617                                 erp_cqr = dasd_default_erp_action (qp->head);
1618
1619                         } else { /* call discipline ERP action */
1620
1621                                 erp_cqr = erp_action (qp->head);
1622                         }
1623                         continue;
1624
1625                 } else if (qp->head->refers) {  /* we deal with a finished ERP */
1626
1627                         if (qp->head->status == CQR_STATUS_DONE) {
1628
1629                                 DASD_MESSAGE (KERN_DEBUG, device, "%s",
1630                                               "ERP successful");
1631                         } else {
1632
1633                                 DASD_MESSAGE (KERN_ERR, device, "%s",
1634                                               "ERP unsuccessful");
1635                         }
1636
1637                         if ((device->discipline->erp_postaction == NULL                              )||
1638                             ((erp_postaction = device->discipline->erp_postaction (qp->head)) == NULL)  ) {
1639
1640                                 dasd_default_erp_postaction (qp->head);
1641
1642                         } else {  /* call ERP postaction of discipline */
1643
1644                                 erp_postaction (qp->head);
1645                         }
1646
1647                         continue;
1648                 }
1649
1650                 /* dechain request now */
1651                 if (final_requests == NULL)
1652                         final_requests = qp->head;
1653
1654                 cqr      = qp->head;
1655                 qp->head = qp->head->next;
1656
1657                 if (qp->head == NULL)
1658                         qp->tail = NULL;
1659
1660         } /* end while over completed requests */
1661
1662         if (cqr)
1663                 cqr->next = NULL;
1664         /* Now clean the requests with final status */
1665         while (final_requests) { 
1666                 temp = final_requests;
1667                 final_requests = temp->next;
1668                 dasd_finalize_request (temp);
1669         }
1670         /* Now we try to fetch requests from the request queue */
1671         for (temp = cqr; temp != NULL; temp = temp->next)
1672                 if (temp->status == CQR_STATUS_QUEUED)
1673                         chanq_max_size--;
1674         while ((atomic_read(&device->plugged) == 0) &&
1675                (!queue->plugged) &&
1676                (!list_empty (&queue->queue_head)) &&
1677                (req = dasd_next_request (queue)) != NULL) {
1678                 /* queue empty or certain critera fulfilled -> transfer */
1679                 if (qp->head == NULL ||
1680                     chanq_max_size > 0 || (req->nr_sectors >= chanq_min_size)) {
1681                         ccw_req_t *cqr = NULL;
1682                         if (is_read_only(device->kdev) && req->cmd == WRITE) {
1683
1684                                 DASD_DRIVER_DEBUG_EVENT (3, dasd_int_handler,
1685                                                          "(%04x) Rejecting write request %p\n",
1686                                                          device->devinfo.devno,
1687                                                          req);
1688
1689                                 dasd_end_request (req, 0);
1690                                 dasd_dequeue_request (queue,req);
1691                         } else {
1692                             cqr = device->discipline->build_cp_from_req (device, req);
1693                             if (cqr == NULL) {
1694
1695                                     DASD_DRIVER_DEBUG_EVENT (3, dasd_int_handler,
1696                                                              "(%04x) CCW creation failed "
1697                                                              "on request %p\n",
1698                                                              device->devinfo.devno,
1699                                                              req);
1700
1701                                     break;      /* terminate request queue loop */
1702                                     
1703                             }
1704 #ifdef CONFIG_DYNAMIC_QUEUE_MIN_SIZE
1705                             chanq_min_size =
1706                                 (chanq_min_size + req->nr_sectors) >> 1;
1707 #endif                          /* CONFIG_DYNAMIC_QUEUE_MIN_SIZE */
1708                             dasd_dequeue_request (queue, req);
1709                             dasd_chanq_enq (qp, cqr);
1710                         }
1711                 } else {        /* queue not empty OR criteria not met */
1712                         break;  /* terminate request queue loop */
1713                 }
1714         }
1715         /* we process the requests with non-final status */
1716         if (qp->head) {
1717                 switch (qp->head->status) {
1718                 case CQR_STATUS_QUEUED:
1719                         /* try to start the first I/O that can be started */
1720                         if (device->discipline->start_IO == NULL)
1721                                 BUG ();
1722                         device->discipline->start_IO(qp->head);
1723                         break;
1724                 case CQR_STATUS_IN_IO:
1725                         /* Check, if to invoke the missing interrupt handler */
1726                         if (dasd_check_expire_time (qp->head)) {
1727                                 /* to be filled with MIH */
1728                         }
1729                         break;
1730
1731                 case CQR_STATUS_PENDING:
1732                         /* just wait */
1733                         break;
1734                 default:
1735                         BUG ();
1736                 }
1737         }
1738         s390irq_spin_unlock_irqrestore (irq, flags);
1739
1740 } /* end dasd_process_queues */
1741
1742 /*
1743  * function dasd_run_bh
1744  * acquires the locks needed and then runs the bh
1745  */
1746 static void
1747 dasd_run_bh (dasd_device_t * device)
1748 {
1749         long flags;
1750         spin_lock_irqsave (&device->request_queue.queue_lock, flags);
1751         atomic_set (&device->bh_scheduled, 0);
1752         dasd_process_queues (device);
1753         spin_unlock_irqrestore (&device->request_queue.queue_lock, flags);
1754 }
1755
1756 /*
1757  * function dasd_schedule_bh
1758  * schedules the request_fn to run with next run_bh cycle
1759  */
1760 void
1761 dasd_schedule_bh (dasd_device_t * device)
1762 {
1763         /* Protect against rescheduling, when already running */
1764         if (atomic_compare_and_swap (0, 1, &device->bh_scheduled)) {
1765                 return;
1766         }
1767
1768         INIT_LIST_HEAD (&device->bh_tq.list);
1769         device->bh_tq.sync = 0;
1770         device->bh_tq.routine = (void *) (void *) dasd_run_bh;
1771         device->bh_tq.data = device;
1772
1773         queue_task (&device->bh_tq, &tq_immediate);
1774         mark_bh (IMMEDIATE_BH);
1775         return;
1776 }
1777
1778 /*
1779  * function do_dasd_request
1780  * is called from ll_rw_blk.c and provides the caller of
1781  * dasd_process_queues
1782  */
1783 static void
1784 do_dasd_request (request_queue_t * queue)
1785 {
1786         dasd_device_t *device = (dasd_device_t *)queue->queuedata;
1787         dasd_process_queues (device);
1788 }
1789
1790 /*
1791  * DASD_HANDLE_STATE_CHANGE_PENDING
1792  *
1793  * DESCRIPTION
1794  *   Handles the state change pending interrupt.
1795  *   Search for the device related request queue and check if the first
1796  *   cqr in queue in in status 'CQR_STATUE_PENDING'.
1797  *   If so the status is set to 'CQR_STATUS_QUEUED' to reactivate
1798  *   the device.
1799  *
1800  *  PARAMETER
1801  *   stat               device status of state change pending interrupt.
1802  */
1803 void
1804 dasd_handle_state_change_pending (devstat_t * stat)
1805 {
1806         dasd_device_t **device_addr;
1807         ccw_req_t *cqr;
1808
1809         device_addr = dasd_device_from_devno (stat->devno);
1810
1811         if (device_addr == NULL) {
1812
1813                 printk (KERN_DEBUG PRINTK_HEADER
1814                         "unable to find device for state change pending "
1815                         "interrupt: devno%04x\n", 
1816                         stat->devno);
1817                 return;
1818         } 
1819
1820         /* re-activate first request in queue */
1821         cqr = (*device_addr)->queue.head;
1822         
1823         if (cqr->status == CQR_STATUS_PENDING) {
1824                 
1825                 DASD_MESSAGE (KERN_DEBUG, (*device_addr), "%s",
1826                               "device request queue restarted by "
1827                               "state change pending interrupt\n");
1828                 
1829                 del_timer (&(*device_addr)->timer);
1830                 
1831                 check_then_set (&cqr->status,
1832                                 CQR_STATUS_PENDING, CQR_STATUS_QUEUED);
1833                 
1834                 dasd_schedule_bh (*device_addr);
1835                 
1836         }
1837
1838 } /* end dasd_handle_state_change_pending */
1839
1840 /*
1841  * function dasd_int_handler
1842  * is the DASD driver's default interrupt handler for SSCH-IO
1843  */
1844 void
1845 dasd_int_handler (int irq, void *ds, struct pt_regs *regs)
1846 {
1847         int ip;
1848         ccw_req_t *cqr;
1849         dasd_device_t *device;
1850         unsigned long long now;
1851         dasd_era_t era = dasd_era_none; /* default is everything is okay */
1852         devstat_t *stat = (devstat_t *)ds;
1853
1854         DASD_DRIVER_DEBUG_EVENT (6, dasd_int_handler,
1855                                  "Interrupt: IRQ %02x, stat %02x, devno %04x",
1856                                  irq,
1857                                  stat->dstat,
1858                                  stat->devno);
1859         asm volatile ("STCK %0":"=m" (now));
1860         if (stat == NULL) {
1861                 BUG();
1862         }
1863
1864         /* first of all check for state change pending interrupt */
1865         if ((stat->dstat & DEV_STAT_ATTENTION ) && 
1866             (stat->dstat & DEV_STAT_DEV_END   ) &&
1867             (stat->dstat & DEV_STAT_UNIT_EXCEP)   ) {
1868                 DASD_DRIVER_DEBUG_EVENT (2, dasd_int_handler,
1869                                          "State change Interrupt: %04x",
1870                                          stat->devno);
1871                 dasd_handle_state_change_pending (stat);
1872                 return;
1873         }
1874
1875         ip = stat->intparm;
1876         if (!ip) {              /* no intparm: unsolicited interrupt */
1877                 DASD_DRIVER_DEBUG_EVENT (2, dasd_int_handler,
1878                                          "Unsolicited Interrupt: %04x",
1879                                          stat->devno);
1880                 printk (KERN_DEBUG PRINTK_HEADER
1881                         "unsolicited interrupt: irq 0x%x devno %04x\n",
1882                         irq,
1883                         stat->devno);
1884                 return;
1885         }
1886         if (ip & 0x80000001) {
1887                 DASD_DRIVER_DEBUG_EVENT (2, dasd_int_handler,
1888                                          "spurious Interrupt: %04x",
1889                                          stat->devno);
1890                 printk (KERN_DEBUG PRINTK_HEADER
1891                         "spurious interrupt: irq 0x%x devno %04x, parm %08x\n",
1892                         irq,
1893                         stat->devno,ip);
1894                 return;
1895         }
1896
1897         cqr = (ccw_req_t *)(long)ip;
1898
1899         /* check status - the request might have been killed because of dyn dettach */
1900         if (cqr->status != CQR_STATUS_IN_IO) {
1901                 DASD_DRIVER_DEBUG_EVENT (2, dasd_int_handler,
1902                                          "invalid status %02x on device %04x",
1903                                          cqr->status,
1904                                          stat->devno);
1905
1906                 printk (KERN_DEBUG PRINTK_HEADER
1907                         "invalid status: irq 0x%x devno %04x, status %02x\n",
1908                         irq,
1909                         stat->devno,
1910                         cqr->status);
1911                 return;
1912         }
1913
1914         device = (dasd_device_t *) cqr->device;
1915         if (device == NULL || 
1916             device != ds-offsetof(dasd_device_t,dev_status)) {
1917                 BUG();
1918         }
1919         if (device->devinfo.irq != irq) {
1920                 BUG();
1921         }
1922         if (strncmp (device->discipline->ebcname, (char *) &cqr->magic, 4)) {
1923                 BUG();
1924         }
1925
1926         /* first of all lets try to find out the appropriate era_action */
1927         DASD_DEVICE_DEBUG_EVENT (4, device," Int: CS/DS 0x%04x",
1928                                  ((stat->cstat<<8)|stat->dstat));
1929
1930         /* first of all lets try to find out the appropriate era_action */
1931         if (stat->flag & DEVSTAT_FLAG_SENSE_AVAIL ||
1932             stat->dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) {
1933                 /* anything abnormal ? */
1934                 if (device->discipline->examine_error == NULL ||
1935                     stat->flag & DEVSTAT_HALT_FUNCTION) {
1936                         era = dasd_era_fatal;
1937                 } else {
1938                         era = device->discipline->examine_error (cqr, stat);
1939                 }
1940                 DASD_DRIVER_DEBUG_EVENT (1, dasd_int_handler," era_code %d",
1941                                          era);
1942         }
1943         if ( era == dasd_era_none ) {
1944                 check_then_set(&cqr->status, 
1945                                CQR_STATUS_IN_IO, 
1946                                CQR_STATUS_DONE);
1947
1948                 cqr->stopclk=now;
1949                 /* start the next queued request if possible -> fast_io */
1950                 if (cqr->next &&
1951                     cqr->next->status == CQR_STATUS_QUEUED) {
1952                         if (device->discipline->start_IO (cqr->next) != 0) {
1953                                 printk (KERN_WARNING PRINTK_HEADER
1954                                         "Interrupt fastpath failed!\n");
1955                         } 
1956                 }
1957         } else { /* error */
1958                 if (cqr->dstat == NULL)
1959                         cqr->dstat = kmalloc (sizeof (devstat_t), GFP_ATOMIC);
1960                 if (cqr->dstat) {
1961                         memcpy (cqr->dstat, stat, sizeof (devstat_t));
1962                 } else {
1963                         PRINT_ERR ("no memory for dstat...ignoring\n");
1964                 }
1965
1966 #ifdef ERP_DEBUG
1967                 /* dump sense data */
1968                 if (device->discipline            && 
1969                     device->discipline->dump_sense  ) {
1970
1971                         device->discipline->dump_sense (device, 
1972                                                         cqr);
1973                 }
1974 #endif
1975
1976                 switch (era) {
1977                 case dasd_era_fatal:
1978                         check_then_set (&cqr->status, 
1979                                         CQR_STATUS_IN_IO,
1980                                         CQR_STATUS_FAILED);
1981
1982                         cqr->stopclk = now;
1983                         break;
1984                 case dasd_era_recover:
1985                         check_then_set (&cqr->status, 
1986                                         CQR_STATUS_IN_IO,
1987                                         CQR_STATUS_ERROR);
1988                         break;
1989                 default:
1990                         BUG ();
1991                 }
1992         }
1993         if ( cqr == device->init_cqr &&
1994              ( cqr->status == CQR_STATUS_DONE ||
1995                cqr->status == CQR_STATUS_FAILED )){
1996                 dasd_state_init_to_ready(device);
1997                 if ( atomic_read(&dasd_init_pending) == 0)
1998                         wake_up (&dasd_init_waitq);
1999         }
2000         dasd_schedule_bh (device);
2001
2002 } /* end dasd_int_handler */
2003
2004 /* SECTION: Some stuff related to error recovery */
2005
2006 /*
2007  * DEFAULT_ERP_ACTION
2008  *
2009  * DESCRIPTION
2010  *   sets up the default-ERP ccw_req_t, namely one, which performs a TIC
2011  *   to the original channel program with a retry counter of 16
2012  *
2013  * PARAMETER
2014  *   cqr                failed CQR
2015  *
2016  * RETURN VALUES
2017  *   erp                CQR performing the ERP
2018  */
2019 ccw_req_t *
2020 dasd_default_erp_action (ccw_req_t * cqr)
2021 {
2022
2023         dasd_device_t *device = cqr->device;
2024         ccw_req_t     *erp    = dasd_alloc_request ((char *) &cqr->magic, 1, 0, cqr->device);
2025
2026         printk (KERN_DEBUG PRINTK_HEADER "Default ERP called... \n");
2027
2028         if (!erp) {
2029
2030                 DASD_MESSAGE (KERN_ERR, device, "%s",
2031                               "Unable to allocate ERP request");
2032                 
2033                 check_then_set (&cqr->status,
2034                                 CQR_STATUS_ERROR,
2035                                 CQR_STATUS_FAILED);
2036
2037                 asm volatile ("STCK %0":"=m" (cqr->stopclk));
2038
2039                 return cqr;
2040         }
2041
2042         erp->cpaddr->cmd_code = CCW_CMD_TIC;
2043         erp->cpaddr->cda = (__u32) (addr_t) cqr->cpaddr;
2044         erp->function = dasd_default_erp_action;
2045         erp->refers = cqr;
2046         erp->device = cqr->device;
2047         erp->magic = cqr->magic;
2048         erp->retries = 16;
2049
2050         erp->status = CQR_STATUS_FILLED;
2051
2052         dasd_chanq_enq_head (&device->queue,
2053                              erp);
2054
2055         return erp;
2056
2057 } /* end dasd_default_erp_action */
2058
2059 /*
2060  * DEFAULT_ERP_POSTACTION
2061  *
2062  * DESCRIPTION
2063  *   Frees all ERPs of the current ERP Chain and set the status
2064  *   of the original CQR either to CQR_STATUS_DONE if ERP was successful
2065  *   or to CQR_STATUS_FAILED if ERP was NOT successful.
2066  *   NOTE: This function is only called if no discipline postaction
2067  *         is available
2068  *
2069  * PARAMETER
2070  *   erp                current erp_head
2071  *
2072  * RETURN VALUES
2073  *   cqr                pointer to the original CQR
2074  */
2075 ccw_req_t *
2076 dasd_default_erp_postaction (ccw_req_t *erp)
2077 {
2078
2079         ccw_req_t     *cqr      = NULL, 
2080                       *free_erp = NULL;
2081         dasd_device_t *device   = erp->device;
2082         int           success;
2083
2084         if (erp->refers   == NULL || 
2085             erp->function == NULL   ) {
2086
2087                 BUG ();
2088         }
2089
2090         if (erp->status == CQR_STATUS_DONE)
2091                 success = 1;
2092         else
2093                 success = 0;
2094
2095         /* free all ERPs - but NOT the original cqr */
2096         while (erp->refers != NULL) {
2097
2098                 free_erp = erp;
2099                 erp      = erp->refers;
2100
2101                 /* remove the request from the device queue */
2102                 dasd_chanq_deq (&device->queue,
2103                                 free_erp);
2104
2105                 /* free the finished erp request */
2106                 dasd_free_request (free_erp, free_erp->device);
2107         }
2108
2109         /* save ptr to original cqr */
2110         cqr = erp;
2111
2112         /* set corresponding status to original cqr */
2113         if (success) {
2114
2115                 check_then_set (&cqr->status, 
2116                                 CQR_STATUS_ERROR,
2117                                 CQR_STATUS_DONE);
2118         } else {
2119
2120                 check_then_set (&cqr->status,
2121                                 CQR_STATUS_ERROR, 
2122                                 CQR_STATUS_FAILED);
2123
2124                 asm volatile ("STCK %0":"=m" (cqr->stopclk));
2125         }
2126
2127         return cqr;
2128
2129 } /* end default_erp_postaction */
2130
2131 /* SECTION: The helpers of the struct file_operations */
2132
2133 /*
2134  * function dasd_format
2135  * performs formatting of _device_ according to _fdata_
2136  * Note: The discipline's format_function is assumed to deliver formatting
2137  * commands to format a single unit of the device. In terms of the ECKD
2138  * devices this means CCWs are generated to format a single track.
2139  */
2140
2141 static int
2142 dasd_format (dasd_device_t * device, format_data_t * fdata)
2143 {
2144         int rc = 0;
2145         int openct = atomic_read (&device->open_count);
2146
2147         if (openct > 1) {
2148                 DASD_MESSAGE (KERN_WARNING, device, "%s",
2149                               "dasd_format: device is open! expect errors.");
2150         }
2151         DASD_MESSAGE (KERN_INFO, device,
2152                       "formatting units %d to %d (%d B blocks) flags %d",
2153                       fdata->start_unit, 
2154                       fdata->stop_unit,
2155                       fdata->blksize, 
2156                       fdata->intensity);
2157         while ((!rc) && (fdata->start_unit <= fdata->stop_unit)) {
2158                 ccw_req_t *req;
2159                 dasd_format_fn_t ffn = device->discipline->format_device;
2160                 ffn = device->discipline->format_device;
2161                 if (ffn == NULL)
2162                         break;
2163                 req = ffn (device, fdata);
2164                 if (req == NULL) {
2165                         rc = -ENOMEM;
2166                         break;
2167                 }
2168                 if ((rc = dasd_sleep_on_req (req)) != 0) {
2169                         DASD_MESSAGE (KERN_WARNING, device,
2170                                       " Formatting of unit %d failed with rc = %d\n",
2171                                       fdata->start_unit, rc);
2172                         break;
2173                 } 
2174                 dasd_free_request (req, device);        /* request is no longer used */
2175                 if ( signal_pending(current) ) {
2176                         rc = -ERESTARTSYS;
2177                         break;          
2178                 }
2179                 fdata->start_unit++;
2180         }
2181         return rc;
2182 }                               /* end dasd_format */
2183
2184 static struct list_head dasd_ioctls = LIST_HEAD_INIT (dasd_ioctls);
2185
2186 static dasd_ioctl_list_t *
2187 dasd_find_ioctl (int no)
2188 {
2189         struct list_head *curr;
2190         list_for_each (curr, &dasd_ioctls) {
2191                 if (list_entry (curr, dasd_ioctl_list_t, list)->no == no) {
2192                         return list_entry (curr, dasd_ioctl_list_t, list);
2193                 }
2194         }
2195         return NULL;
2196 }
2197
2198 int
2199 dasd_ioctl_no_register (struct module *owner, int no, dasd_ioctl_fn_t handler)
2200 {
2201         dasd_ioctl_list_t *new;
2202         if (dasd_find_ioctl (no))
2203                 return -EBUSY;
2204         new = kmalloc (sizeof (dasd_ioctl_list_t), GFP_KERNEL);
2205         if (new == NULL)
2206                 return -ENOMEM;
2207         new->owner = owner;
2208         new->no = no;
2209         new->handler = handler;
2210         list_add (&new->list, &dasd_ioctls);
2211         MOD_INC_USE_COUNT;
2212         return 0;
2213 }
2214
2215 int
2216 dasd_ioctl_no_unregister (struct module *owner, int no, dasd_ioctl_fn_t handler)
2217 {
2218         dasd_ioctl_list_t *old = dasd_find_ioctl (no);
2219         if (old == NULL)
2220                 return -ENOENT;
2221         if (old->no != no || old->handler != handler || owner != old->owner )
2222                 return -EINVAL;
2223         list_del (&old->list);
2224         kfree (old);
2225         MOD_DEC_USE_COUNT;
2226         return 0;
2227 }
2228
2229 static int
2230 dasd_revalidate (dasd_device_t * device)
2231 {
2232         int rc = 0;
2233         int i;
2234         kdev_t kdev = device->kdev;
2235         int openct = atomic_read (&device->open_count);
2236         int start = MINOR (kdev);
2237         if (openct != 1) {
2238                 DASD_MESSAGE (KERN_WARNING, device, "%s",
2239                               "BLKRRPART: device is open! expect errors.");
2240         }
2241         for (i = (1 << DASD_PARTN_BITS) - 1; i >= 0; i--) {
2242                 int major = device->major_info->gendisk.major;
2243                 invalidate_device(MKDEV (major, start+i), 1);
2244         }
2245         dasd_destroy_partitions(device);
2246         dasd_setup_partitions(device);
2247         return rc;
2248
2249 }
2250 static int
2251 do_dasd_ioctl (struct inode *inp, /* unsigned */ int no, unsigned long data)
2252 {
2253         int rc = 0;
2254         dasd_device_t *device = dasd_device_from_kdev (inp->i_rdev);
2255         major_info_t *major_info;
2256
2257         if (!device) {
2258                 printk (KERN_WARNING PRINTK_HEADER
2259                         "No device registered as device (%d:%d)\n",
2260                         MAJOR (inp->i_rdev), 
2261                         MINOR (inp->i_rdev));
2262                 return -EINVAL;
2263         }
2264         if ((_IOC_DIR (no) != _IOC_NONE) && (data == 0)) {
2265                 PRINT_DEBUG ("empty data ptr");
2266                 return -EINVAL;
2267         }
2268         major_info = device->major_info;
2269 #if 0
2270         printk (KERN_DEBUG PRINTK_HEADER
2271                 "ioctl 0x%08x %s'0x%x'%d(%d) on /dev/%s (%d:%d,"
2272                 " devno 0x%04x on irq %d) with data %8lx\n",
2273                 no,
2274                 _IOC_DIR (no) == _IOC_NONE ? "0" :
2275                 _IOC_DIR (no) == _IOC_READ ? "r" :
2276                 _IOC_DIR (no) == _IOC_WRITE ? "w" :
2277                 _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u",
2278                 _IOC_TYPE (no),
2279                 _IOC_NR (no),
2280                 _IOC_SIZE (no),
2281                 device->name, 
2282                 MAJOR (inp->i_rdev), 
2283                 MINOR (inp->i_rdev),
2284                 device->devinfo.devno, 
2285                 device->devinfo.irq, 
2286                 data);
2287 #endif
2288         switch (no) {
2289         case DASDAPIVER: {
2290                         int ver = DASD_API_VERSION;
2291                         rc = put_user(ver, (int *) data);
2292                         break;
2293         }
2294         case BLKRRPART:{
2295                         if (!capable (CAP_SYS_ADMIN)) {
2296                                 rc = -EACCES;
2297                                 break;
2298                         }
2299                         rc = dasd_revalidate (device);
2300                         break;
2301                 }
2302         case HDIO_GETGEO:{
2303                         struct hd_geometry geo = { 0, };
2304                         rc = dasd_fillgeo (inp->i_rdev, &geo);
2305                         if (rc)
2306                                 break;
2307
2308                         rc = copy_to_user ((struct hd_geometry *) data, &geo,
2309                                            sizeof (struct hd_geometry));
2310                         if (rc)
2311                                 rc = -EFAULT;
2312                         break;
2313                 }
2314         case BIODASDDISABLE:{
2315                         if (!capable (CAP_SYS_ADMIN)) {
2316                                 rc = -EACCES;
2317                                 break;
2318                         }
2319                         if ( device->level > DASD_STATE_ACCEPT) {
2320                                 dasd_deactivate_queue(device);
2321                                 if ( device->request_queue)
2322                                         dasd_flush_request_queues(device,0);
2323                                 dasd_flush_chanq(device,0);
2324                                 dasd_disable_blkdev(device);
2325                                 dasd_set_device_level (device->devinfo.devno, 
2326                                                        device->discipline, 
2327                                                        DASD_STATE_ACCEPT);
2328                         }
2329                         break;
2330         }
2331         case BIODASDENABLE:{
2332                         dasd_range_t range = { 
2333                                 from: device->devinfo.devno,
2334                                 to: device->devinfo.devno 
2335                         };
2336                         if (!capable (CAP_SYS_ADMIN)) {
2337                                 rc = -EACCES;
2338                                 break;
2339                         }
2340                         dasd_enable_ranges (&range, device->discipline, 0);
2341                         break;
2342         }
2343         case BIODASDFMT:{
2344                         /* fdata == NULL is no longer a valid arg to dasd_format ! */
2345                         int partn = MINOR (inp->i_rdev) &
2346                             ((1 << major_info->gendisk.minor_shift) - 1);
2347                         format_data_t fdata;
2348
2349                         if (!capable (CAP_SYS_ADMIN)) {
2350                                 rc = -EACCES;
2351                                 break;
2352                         }
2353                         if (dasd_features_from_devno(device->devinfo.devno)&DASD_FEATURE_READONLY) {
2354                                 rc = -EROFS;
2355                                 break;
2356                         }
2357                         if (!data) {
2358                                 rc = -EINVAL;
2359                                 break;
2360                         }
2361                         rc = copy_from_user (&fdata, (void *) data,
2362                                              sizeof (format_data_t));
2363                         if (rc) {
2364                                 rc = -EFAULT;
2365                                 break;
2366                         }
2367                         if (partn != 0) {
2368                                 DASD_MESSAGE (KERN_WARNING, device, "%s",
2369                                               "Cannot low-level format a partition");
2370                                 return -EINVAL;
2371                         }
2372                         rc = dasd_format (device, &fdata);
2373                         break;
2374                 }
2375         case BIODASDPRRST:{     /* reset device profile information */
2376                         if (!capable (CAP_SYS_ADMIN)) {
2377                                 rc = -EACCES;
2378                                 break;
2379                         }
2380                         memset (&device->profile, 0,
2381                                 sizeof (dasd_profile_info_t));
2382                         break;
2383                 }
2384         case BIODASDPRRD:{      /* retrun device profile information */
2385                         rc = copy_to_user((long *)data,
2386                                           (long *)&device->profile,
2387                                           sizeof(dasd_profile_info_t));
2388                         if (rc)
2389                                 rc = -EFAULT;
2390                         break;
2391                 }
2392         case BIODASDRSRV:{      /* reserve */
2393                         ccw_req_t *req;
2394                         if (!capable (CAP_SYS_ADMIN)) {
2395                                 rc = -EACCES;
2396                                 break;
2397                         }
2398                         req = device->discipline->reserve (device);
2399                         rc = dasd_sleep_on_req (req);
2400                         dasd_free_request (req, device);
2401                         break;
2402                 }
2403         case BIODASDRLSE:{      /* release */
2404                         ccw_req_t *req;
2405                         if (!capable (CAP_SYS_ADMIN)) {
2406                                 rc = -EACCES;
2407                                 break;
2408                         }
2409                         req = device->discipline->release (device);
2410                         rc = dasd_sleep_on_req (req);
2411                         dasd_free_request (req, device);
2412                         break;
2413                 }
2414         case BIODASDSLCK:{      /* steal lock - unconditional reserve */
2415                         ccw_req_t *req;
2416                         if (!capable (CAP_SYS_ADMIN)) {
2417                                 rc = -EACCES;
2418                                 break;
2419                         }
2420                         req = device->discipline->steal_lock (device);
2421                         rc = dasd_sleep_on_req (req);
2422                         dasd_free_request (req, device);
2423                         break;
2424                 }
2425         case BIODASDINFO:{
2426                         dasd_information_t dasd_info;
2427                         unsigned long flags;
2428                         rc = device->discipline->fill_info (device, &dasd_info);
2429                         dasd_info.label_block = device->sizes.pt_block;
2430                         dasd_info.devno = device->devinfo.devno;
2431                         dasd_info.schid = device->devinfo.irq;
2432                         dasd_info.cu_type = device->devinfo.sid_data.cu_type;
2433                         dasd_info.cu_model = device->devinfo.sid_data.cu_model;
2434                         dasd_info.dev_type = device->devinfo.sid_data.dev_type;
2435                         dasd_info.dev_model = device->devinfo.sid_data.dev_model;
2436                         dasd_info.open_count =
2437                             atomic_read (&device->open_count);
2438                         dasd_info.status = device->level;
2439                         if (device->discipline) {
2440                                 memcpy (dasd_info.type,
2441                                         device->discipline->name, 4);
2442                         } else {
2443                                 memcpy (dasd_info.type, "none", 4);
2444                         }
2445                         dasd_info.req_queue_len = 0;
2446                         dasd_info.chanq_len = 0;
2447                         if (device->request_queue->request_fn) {
2448                                 struct list_head *l;
2449                                 request_queue_t *q = drive->request_queue;
2450                                 ccw_req_t *cqr = device->queue.head;
2451                                 spin_lock_irqsave (&q->queue_lock, flags);
2452                                 list_for_each (l, q->queue_head, queue_head)
2453                                         dasd_info.req_queue_len++;
2454                                 spin_unlock_irqrestore (&q->queue_lock,
2455                                                         flags);
2456                                 s390irq_spin_lock_irqsave (device->devinfo.irq,
2457                                                            flags);
2458                                 while (cqr) {
2459                                         cqr = cqr->next;
2460                                         dasd_info.chanq_len++;
2461                                 }
2462                                 s390irq_spin_unlock_irqrestore (device->devinfo.
2463                                                                 irq, flags);
2464                         }
2465                         rc =
2466                             copy_to_user ((long *) data, (long *) &dasd_info,
2467                                           sizeof (dasd_information_t));
2468                         if (rc)
2469                                 rc = -EFAULT;
2470                         break;
2471                 }
2472 #if 0 /* needed for XFS */
2473         case BLKBSZSET:{
2474                 int bsz;
2475                 rc = copy_from_user ((long *)&bsz,(long *)data,sizeof(int));
2476                 if ( rc ) {
2477                         rc = -EFAULT;
2478                 } else {
2479                         if ( bsz >= device->sizes.bp_block )
2480                                 rc = blk_ioctl (inp->i_rdev, no, data);
2481                         else
2482                                 rc = -EINVAL; 
2483                 }
2484                 break;
2485                 }
2486 #endif /* 0 */
2487         case BLKGETSIZE:
2488         case BLKGETSIZE64:
2489         case BLKSSZGET:
2490         case BLKROSET:
2491         case BLKROGET:
2492         case BLKRASET:
2493         case BLKRAGET:
2494         case BLKFLSBUF:
2495         case BLKPG:
2496         case BLKELVGET:
2497         case BLKELVSET:
2498                 return blk_ioctl (inp->i_rdev, no, data);
2499                 break;
2500         default:{
2501
2502                         dasd_ioctl_list_t *old = dasd_find_ioctl (no);
2503                         if (old) {
2504                                 if ( old->owner )
2505                                         __MOD_INC_USE_COUNT(old->owner);
2506                                 rc = old->handler (inp, no, data);
2507                                 if ( old->owner )
2508                                         __MOD_DEC_USE_COUNT(old->owner);
2509                         } else {
2510                                 DASD_MESSAGE (KERN_INFO, device,
2511                                               "ioctl 0x%08x=%s'0x%x'%d(%d) data %8lx\n",
2512                                               no,
2513                                               _IOC_DIR (no) == _IOC_NONE ? "0" :
2514                                               _IOC_DIR (no) == _IOC_READ ? "r" :
2515                                               _IOC_DIR (no) == _IOC_WRITE ? "w" : 
2516                                               _IOC_DIR (no) == 
2517                                               (_IOC_READ | _IOC_WRITE) ? "rw" : "u",
2518                                               _IOC_TYPE (no),
2519                                               _IOC_NR (no), 
2520                                               _IOC_SIZE (no),
2521                                               data);
2522                                 rc = -ENOTTY;
2523                         }
2524                         break;
2525                 }
2526         }
2527         return rc;
2528 }
2529
2530 /* SECTION: The members of the struct file_operations */
2531
2532 static int
2533 dasd_ioctl (struct inode *inp, struct file *filp,
2534             unsigned int no, unsigned long data)
2535 {
2536         int rc = 0;
2537         if ((!inp) || !(inp->i_rdev)) {
2538                 return -EINVAL;
2539         }
2540         rc = do_dasd_ioctl (inp, no, data);
2541         return rc;
2542 }
2543
2544 static int
2545 dasd_open (struct inode *inp, struct file *filp)
2546 {
2547         int rc = 0;
2548         unsigned long flags;
2549         dasd_device_t *device;
2550
2551         if ((!inp) || !(inp->i_rdev)) {
2552                 rc = -EINVAL;
2553                 goto fail;
2554         }
2555         if (dasd_probeonly) {
2556                 printk ("\n" KERN_INFO PRINTK_HEADER
2557                         "No access to device (%d:%d) due to probeonly mode\n",
2558                         MAJOR (inp->i_rdev), 
2559                         MINOR (inp->i_rdev));
2560                 rc = -EPERM;
2561                 goto fail;
2562         }
2563         spin_lock_irqsave(&discipline_lock,flags);
2564         device = dasd_device_from_kdev (inp->i_rdev);
2565         if (!device) {
2566                 printk (KERN_WARNING PRINTK_HEADER
2567                         "No device registered as (%d:%d)\n",
2568                         MAJOR (inp->i_rdev), 
2569                         MINOR (inp->i_rdev));
2570                 rc = -ENODEV;
2571                 goto unlock;
2572         }
2573         if (device->level <= DASD_STATE_ACCEPT ) {
2574                 DASD_MESSAGE (KERN_WARNING, device, " %s", 
2575                               " Cannot open unrecognized device\n");
2576                 rc = -ENODEV;
2577                 goto unlock;
2578         }
2579         if (atomic_inc_return (&device->open_count) == 1 ) {
2580                 if ( device->discipline->owner )
2581                         __MOD_INC_USE_COUNT(device->discipline->owner);
2582         }
2583  unlock:
2584         spin_unlock_irqrestore(&discipline_lock,flags);
2585  fail:
2586         return rc;
2587 }
2588
2589 /*
2590  * DASD_RELEASE
2591  *
2592  * DESCRIPTION
2593  */
2594 static int
2595 dasd_release (struct inode *inp, struct file *filp)
2596 {
2597         int rc = 0;
2598         int count;
2599         dasd_device_t *device;
2600
2601         if ((!inp) || !(inp->i_rdev)) {
2602                 rc = -EINVAL;
2603                 goto out;
2604         }
2605         device = dasd_device_from_kdev (inp->i_rdev);
2606         if (!device) {
2607                 printk (KERN_WARNING PRINTK_HEADER
2608                         "No device registered as %d:%d\n",
2609                         MAJOR (inp->i_rdev), 
2610                         MINOR (inp->i_rdev));
2611                 rc = -EINVAL;
2612                 goto out;
2613         }
2614
2615         if (device->level < DASD_STATE_ACCEPT ) {
2616                 DASD_MESSAGE (KERN_WARNING, device, " %s",
2617                               " Cannot release unrecognized device\n");
2618                 rc = -ENODEV;
2619                 goto out;
2620         }
2621         count = atomic_dec_return (&device->open_count);
2622         if ( count == 0) {
2623                 invalidate_buffers (inp->i_rdev);
2624                 if ( device->discipline->owner )
2625                         __MOD_DEC_USE_COUNT(device->discipline->owner);
2626                 MOD_DEC_USE_COUNT;
2627         } else if ( count == -1 ) { /* paranoia only */
2628                 atomic_set (&device->open_count,0);
2629                 printk (KERN_WARNING PRINTK_HEADER
2630                         "release called with open count==0\n");
2631         }
2632  out:
2633         return rc;
2634 }
2635
2636 static struct
2637 block_device_operations dasd_device_operations =
2638 {
2639         owner:THIS_MODULE,
2640         open:dasd_open,
2641         release:dasd_release,
2642         ioctl:dasd_ioctl,
2643 };
2644
2645 /* SECTION: Management of device list */
2646 int
2647 dasd_fillgeo(kdev_t kdev,struct hd_geometry *geo)
2648 {
2649         dasd_device_t *device = dasd_device_from_kdev (kdev);
2650
2651         if (!device)
2652                 return -EINVAL;
2653
2654         if (!device->discipline->fill_geometry)
2655                 return -EINVAL;
2656
2657         device->discipline->fill_geometry (device, geo);
2658         geo->start = get_start_sect(kdev);
2659         return 0;
2660
2661
2662
2663 /* This one is needed for naming 18000+ possible dasd devices */
2664 int
2665 dasd_device_name (char *str, int index, int partition, struct gendisk *hd)
2666 {
2667         int len = 0;
2668         char first, second, third;
2669
2670         if (hd) {
2671                 major_info_t *major_info = NULL;
2672                 struct list_head *l;
2673
2674                 list_for_each (l, &dasd_major_info[0].list) {
2675                         major_info = list_entry (l, major_info_t, list);
2676                         if (&major_info->gendisk == hd) {
2677                                 break;
2678                         }
2679                         index += DASD_PER_MAJOR;
2680                 }
2681                 if (major_info == &dasd_major_info[0]) {
2682                         return -EINVAL;
2683                 }
2684         }
2685         third = index % 26;
2686         second = ((index - 26) / 26) % 26;
2687         first = (((index - 702) / 26) / 26) % 26;
2688
2689         len = sprintf (str, "dasd");
2690         if (index > 701) {
2691                 len += sprintf (str + len, "%c", first + 'a');
2692         }
2693         if (index > 25) {
2694                 len += sprintf (str + len, "%c", second + 'a');
2695         }
2696         len += sprintf (str + len, "%c", third + 'a');
2697         if (partition) {
2698                 if (partition > 9)