1/*
2 * File...........: linux/drivers/s390/block/dasd_3990_erp.c
3 * Author(s)......: Horst  Hummel    <Horst.Hummel@de.ibm.com>
4 *                  Holger Smolinski <Holger.Smolinski@de.ibm.com>
5 * Bugreports.to..: <Linux390@de.ibm.com>
6 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
7 *
8 * History of changes:
9 * 05/14/01 fixed PL030160GTO (BUG() in erp_action_5)
10 */
11
12#include <asm/ccwcache.h>
13#include <asm/idals.h>
14#include <asm/s390io.h>
15#include <linux/timer.h>
16
17#include "dasd_int.h"
18#include "dasd_eckd.h"
19#include "dasd_3990_erp.h"
20
21#ifdef PRINTK_HEADER
22#undef PRINTK_HEADER
23#endif				/* PRINTK_HEADER */
24#define PRINTK_HEADER "dasd_erp(3990): "
25
26/*
27 *****************************************************************************
28 * SECTION DEBUG ROUTINES
29 *****************************************************************************
30 */
31void
32log_erp_chain (ccw_req_t *cqr,
33               int       caller,
34               __u32     cpa)
35{
36
37        ccw_req_t     *loop_cqr = cqr;
38	dasd_device_t *device   = cqr->device;
39
40        int     i;
41        char    *nl,
42                *end_cqr,
43                *begin,
44                *end;
45
46        /* dump sense data */
47        if (device->discipline            &&
48            device->discipline->dump_sense  ) {
49
50                device->discipline->dump_sense (device,
51                                                cqr);
52        }
53
54        /* log the channel program */
55        while (loop_cqr != NULL) {
56
57                DASD_MESSAGE (KERN_ERR, device,
58                              "(%s) ERP chain report for req: %p",
59                              caller == 0 ? "EXAMINE" : "ACTION",
60                              loop_cqr);
61
62                nl      = (char *) loop_cqr;
63                end_cqr = nl + sizeof (ccw_req_t);
64
65                while (nl < end_cqr) {
66
67                        DASD_MESSAGE (KERN_ERR, device,
68                                      "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
69                                      "%02x%02x%02x%02x %02x%02x%02x%02x",
70                                      nl,
71                                      nl[0], nl[1], nl[2], nl[3],
72                                      nl[4], nl[5], nl[6], nl[7],
73                                      nl[8], nl[9], nl[10], nl[11],
74                                      nl[12], nl[13], nl[14], nl[15]);
75                        nl +=16;
76                }
77
78                nl  = (char *) loop_cqr->cpaddr;
79
80                if (loop_cqr->cplength > 40) { /* log only parts of the CP */
81
82                        DASD_MESSAGE (KERN_ERR, device, "%s",
83                                      "Start of channel program:");
84
85                        for (i = 0; i < 20; i += 2) {
86
87                                DASD_MESSAGE (KERN_ERR, device,
88                                              "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
89                                              "%02x%02x%02x%02x %02x%02x%02x%02x",
90                                              nl,
91                                              nl[0], nl[1], nl[2], nl[3],
92                                              nl[4], nl[5], nl[6], nl[7],
93                                              nl[8], nl[9], nl[10], nl[11],
94                                              nl[12], nl[13], nl[14], nl[15]);
95
96                                nl += 16;
97                        }
98
99                        DASD_MESSAGE (KERN_ERR, device, "%s",
100                                      "End of channel program:");
101
102                        nl  = (char *) loop_cqr->cpaddr;
103                        nl  += ((loop_cqr->cplength - 10) * 8);
104
105                        for (i = 0; i < 20; i += 2) {
106
107                                DASD_MESSAGE (KERN_ERR, device,
108                                              "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
109                                              "%02x%02x%02x%02x %02x%02x%02x%02x",
110                                              nl,
111                                              nl[0], nl[1], nl[2], nl[3],
112                                              nl[4], nl[5], nl[6], nl[7],
113                                              nl[8], nl[9], nl[10], nl[11],
114                                              nl[12], nl[13], nl[14], nl[15]);
115
116                                nl += 16;
117                        }
118
119                } else { /* log the whole CP */
120
121                        DASD_MESSAGE (KERN_ERR, device, "%s",
122                                      "Channel program (complete):");
123
124                        for (i = 0; i < (loop_cqr->cplength + 4); i += 2) {
125
126                                DASD_MESSAGE (KERN_ERR, device,
127                                              "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
128                                              "%02x%02x%02x%02x %02x%02x%02x%02x",
129                                              nl,
130                                              nl[0], nl[1], nl[2], nl[3],
131                                              nl[4], nl[5], nl[6], nl[7],
132                                              nl[8], nl[9], nl[10], nl[11],
133                                              nl[12], nl[13], nl[14], nl[15]);
134
135                                nl += 16;
136                        }
137                }
138
139                /* log bytes arround failed CCW if not already done */
140                begin = (char *) loop_cqr->cpaddr;
141                end   = begin + ((loop_cqr->cplength+4) * 8);
142                nl = (void *)(long)cpa;
143
144                if (loop_cqr == cqr) {  /* log only once */
145
146                        /* if not whole CP logged OR CCW outside logged CP */
147                        if ((loop_cqr->cplength > 40) ||
148                            ((nl < begin        ) &&
149                             (nl > end          )   )   ) {
150
151                                nl -= 10*8;     /* start some bytes before */
152
153                                DASD_MESSAGE (KERN_ERR, device,
154                                                "Failed CCW (%p) (area):",
155                                                (void *)(long)cpa);
156
157                                for (i = 0; i < 20; i += 2) {
158
159                                        DASD_MESSAGE (KERN_ERR, device,
160                                                      "%p: %02x%02x%02x%02x %02x%02x%02x%02x "
161                                                      "%02x%02x%02x%02x %02x%02x%02x%02x",
162                                                      nl,
163                                                      nl[0], nl[1], nl[2], nl[3],
164                                                      nl[4], nl[5], nl[6], nl[7],
165                                                      nl[8], nl[9], nl[10], nl[11],
166                                                      nl[12], nl[13], nl[14], nl[15]);
167
168                                        nl += 16;
169                                }
170
171                        } else {
172
173                                DASD_MESSAGE (KERN_ERR, device,
174                                              "Failed CCW (%p) already logged",
175                                              (void *)(long)cpa);
176                        }
177                }
178
179                loop_cqr = loop_cqr->refers;
180        }
181
182} /* end log_erp_chain */
183
184/*
185 *****************************************************************************
186 * SECTION ERP EXAMINATION
187 *****************************************************************************
188 */
189
190/*
191 * DASD_3990_ERP_EXAMINE_24
192 *
193 * DESCRIPTION
194 *   Checks only for fatal (unrecoverable) error.
195 *   A detailed examination of the sense data is done later outside
196 *   the interrupt handler.
197 *
198 *   Each bit configuration leading to an action code 2 (Exit with
199 *   programming error or unusual condition indication)
200 *   are handled as fatal error�s.
201 *
202 *   All other configurations are handled as recoverable errors.
203 *
204 * RETURN VALUES
205 *   dasd_era_fatal     for all fatal (unrecoverable errors)
206 *   dasd_era_recover   for all others.
207 */
208dasd_era_t
209dasd_3990_erp_examine_24 (ccw_req_t *cqr,
210                          char      *sense)
211{
212
213        dasd_device_t *device = cqr->device;
214
215	/* check for 'Command Reject' */
216	if ((  sense[0] & SNS0_CMD_REJECT       ) &&
217	    (!(sense[2] & SNS2_ENV_DATA_PRESENT))   ) {
218
219                DASD_MESSAGE (KERN_ERR, device, "%s",
220                              "EXAMINE 24: Command Reject detected - "
221                              "fatal error");
222
223                return dasd_era_fatal;
224	}
225
226	/* check for 'Invalid Track Format' */
227	if ((  sense[1] & SNS1_INV_TRACK_FORMAT ) &&
228            (!(sense[2] & SNS2_ENV_DATA_PRESENT))   ) {
229
230                DASD_MESSAGE (KERN_ERR, device, "%s",
231                              "EXAMINE 24: Invalid Track Format detected "
232                              "- fatal error");
233
234                return dasd_era_fatal;
235	}
236
237	/* check for 'No Record Found' */
238	if (sense[1] & SNS1_NO_REC_FOUND) {
239
240                DASD_MESSAGE (KERN_ERR, device,
241                              "EXAMINE 24: No Record Found detected %s",
242                              cqr == device->init_cqr ? " " :
243                              "- fatal error");
244
245                return dasd_era_fatal;
246	}
247
248	/* return recoverable for all others */
249  	return dasd_era_recover;
250} /* END dasd_3990_erp_examine_24 */
251
252/*
253 * DASD_3990_ERP_EXAMINE_32
254 *
255 * DESCRIPTION
256 *   Checks only for fatal/no/recoverable error.
257 *   A detailed examination of the sense data is done later outside
258 *   the interrupt handler.
259 *
260 * RETURN VALUES
261 *   dasd_era_none      no error
262 *   dasd_era_fatal     for all fatal (unrecoverable errors)
263 *   dasd_era_recover   for recoverable others.
264 */
265dasd_era_t
266dasd_3990_erp_examine_32 (ccw_req_t *cqr,
267                          char      *sense)
268{
269
270        dasd_device_t *device = cqr->device;
271
272	switch (sense[25]) {
273	case 0x00:
274		return dasd_era_none;
275
276	case 0x01:
277                DASD_MESSAGE (KERN_ERR, device, "%s",
278                              "EXAMINE 32: fatal error");
279		return dasd_era_fatal;
280
281	default:
282
283		return dasd_era_recover;
284	}
285
286} /* end dasd_3990_erp_examine_32 */
287
288/*
289 * DASD_3990_ERP_EXAMINE
290 *
291 * DESCRIPTION
292 *   Checks only for fatal/no/recover error.
293 *   A detailed examination of the sense data is done later outside
294 *   the interrupt handler.
295 *
296 *   The logic is based on the 'IBM 3990 Storage Control  Reference' manual
297 *   'Chapter 7. Error Recovery Procedures'.
298 *
299 * RETURN VALUES
300 *   dasd_era_none      no error
301 *   dasd_era_fatal     for all fatal (unrecoverable errors)
302 *   dasd_era_recover   for all others.
303 */
304dasd_era_t
305dasd_3990_erp_examine (ccw_req_t *cqr,
306                       devstat_t *stat)
307{
308
309	char          *sense  = stat->ii.sense.data;
310        dasd_era_t     era    = dasd_era_recover;
311        dasd_device_t *device = cqr->device;
312
313	/* check for successful execution first */
314	if (stat->cstat == 0x00                                 &&
315	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)  )
316		return dasd_era_none;
317
318	/* distinguish between 24 and 32 byte sense data */
319	if (sense[27] & DASD_SENSE_BIT_0) {
320
321		era = dasd_3990_erp_examine_24 (cqr,
322                                                sense);
323
324	} else {
325
326		era = dasd_3990_erp_examine_32 (cqr,
327                                                sense);
328
329	}
330
331        /* log the erp chain if fatal error occurred */
332        if ((era == dasd_era_fatal  ) &&
333            (cqr != device->init_cqr)   ){
334
335                log_erp_chain (cqr,
336                               0,
337                               stat->cpa);
338        }
339
340        return era;
341
342} /* END dasd_3990_erp_examine */
343
344/*
345 *****************************************************************************
346 * SECTION ERP HANDLING
347 *****************************************************************************
348 */
349/*
350 *****************************************************************************
351 * 24 and 32 byte sense ERP functions
352 *****************************************************************************
353 */
354
355/*
356 * DASD_3990_ERP_CLEANUP
357 *
358 * DESCRIPTION
359 *   Removes the already build but not neccessary ERP request and sets
360 *   the status of the original cqr / erp to the given (final) status
361 *
362 *  PARAMETER
363 *   erp                request to be blocked
364 *   final_status       either CQR_STATUS_DONE or CQR_STATUS_FAILED
365 *
366 * RETURN VALUES
367 *   cqr                original cqr
368 */
369ccw_req_t *
370dasd_3990_erp_cleanup (ccw_req_t *erp,
371                       char      final_status)
372{
373
374        ccw_req_t *cqr = erp->refers;
375
376        dasd_free_request (erp, erp->device);
377
378        check_then_set (&cqr->status,
379                        CQR_STATUS_ERROR,
380                        final_status);
381
382        return cqr;
383
384} /* end dasd_3990_erp_cleanup */
385
386/*
387 * DASD_3990_ERP_BLOCK_QUEUE
388 *
389 * DESCRIPTION
390 *   Block the given device request queue to prevent from further
391 *   processing until the started timer has expired or an related
392 *   interrupt was received.
393 *
394 *  PARAMETER
395 *   erp                request to be blocked
396 *   expires            time to wait until restart (in seconds)
397 *
398 * RETURN VALUES
399 *   void
400 */
401void
402dasd_3990_erp_block_queue (ccw_req_t     *erp,
403                           unsigned long expires)
404{
405
406	dasd_device_t *device = erp->device;
407
408        DASD_MESSAGE (KERN_INFO, device,
409                      "blocking request queue for %is",
410                      (int) expires);
411
412        check_then_set (&erp->status,
413                        CQR_STATUS_ERROR,
414                        CQR_STATUS_PENDING);
415
416        /* restart queue after some time */
417        device->timer.function = dasd_3990_erp_restart_queue;
418        device->timer.data     = (unsigned long) erp;
419        device->timer.expires  = jiffies + (expires * HZ);
420
421        add_timer(&device->timer);
422
423} /* end dasd_3990_erp_block_queue */
424
425/*
426 * DASD_3990_ERP_RESTART_QUEUE
427 *
428 * DESCRIPTION
429 *   Restarts request currently in status PENDING.
430 *   This has to be done if either an related interrupt has received, or
431 *   a timer has expired.
432 *
433 *
434 *  PARAMETER
435 *   erp                pointer to the PENDING ERP
436 *
437 * RETURN VALUES
438 *   void
439 *
440 */
441void
442dasd_3990_erp_restart_queue (unsigned long erp)
443{
444
445        ccw_req_t     *cqr    = (void *) erp;
446	dasd_device_t *device = cqr->device;
447	unsigned long flags;
448
449        /* get the needed locks to modify the request queue */
450	s390irq_spin_lock_irqsave (device->devinfo.irq,
451                                   flags);
452
453        /* 'restart' the device queue */
454        if (cqr->status == CQR_STATUS_PENDING) {
455
456                DASD_MESSAGE (KERN_INFO, device, "%s",
457                              "request queue restarted by MIH");
458
459                check_then_set (&cqr->status,
460                                CQR_STATUS_PENDING,
461                                CQR_STATUS_QUEUED);
462        }
463
464        /* release the lock */
465        s390irq_spin_unlock_irqrestore (device->devinfo.irq,
466                                        flags);
467
468        dasd_schedule_bh (device);
469
470} /* end dasd_3990_erp_restart_queue */
471
472/*
473 * DASD_3990_ERP_INT_REQ
474 *
475 * DESCRIPTION
476 *   Handles 'Intervention Required' error.
477 *   This means either device offline or not installed.
478 *
479 * PARAMETER
480 *   erp                current erp
481 * RETURN VALUES
482 *   erp                modified erp
483 */
484ccw_req_t *
485dasd_3990_erp_int_req (ccw_req_t *erp)
486{
487
488	dasd_device_t *device = erp->device;
489
490        /* first time set initial retry counter and erp_function */
491        /* and retry once without blocking queue                 */
492        /* (this enables easier enqueing of the cqr)             */
493        if (erp->function != dasd_3990_erp_int_req) {
494
495                erp->retries  = 256;
496                erp->function = dasd_3990_erp_int_req;
497
498        } else {
499
500                /* issue a message and wait for 'device ready' interrupt */
501                DASD_MESSAGE (KERN_ERR, device, "%s",
502                              "is offline or not installed - "
503                              "INTERVENTION REQUIRED!!");
504
505                dasd_3990_erp_block_queue (erp,
506                                           60);
507        }
508
509	return erp;
510
511} /* end dasd_3990_erp_int_req */
512
513/*
514 * DASD_3990_ERP_ALTERNATE_PATH
515 *
516 * DESCRIPTION
517 *   Repeat the operation on a different channel path.
518 *   If all alternate paths have been tried, the request is posted with a
519 *   permanent error.
520 *
521 *  PARAMETER
522 *   erp                pointer to the current ERP
523 *
524 * RETURN VALUES
525 *   erp                modified pointer to the ERP
526 *
527 */
528void
529dasd_3990_erp_alternate_path (ccw_req_t *erp)
530{
531
532	dasd_device_t *device = erp->device;
533        int irq = device->devinfo.irq;
534
535        /* try alternate valid path */
536        erp->lpm     &= ~(erp->dstat->lpum);
537        erp->options |= DOIO_VALID_LPM;		/* use LPM for DO_IO */
538
539	if ((erp->lpm & ioinfo[irq]->opm) != 0x00) {
540
541		DASD_MESSAGE (KERN_DEBUG, device,
542                              "try alternate lpm=%x (lpum=%x / opm=%x)",
543                              erp->lpm,
544                              erp->dstat->lpum,
545                              ioinfo[irq]->opm);
546
547		/* reset status to queued to handle the request again... */
548		check_then_set (&erp->status,
549                                CQR_STATUS_ERROR,
550                                CQR_STATUS_QUEUED);
551
552                erp->retries = 1;
553
554	} else {
555
556                DASD_MESSAGE (KERN_ERR, device,
557                              "No alternate channel path left (lpum=%x / "
558                              "opm=%x) -> permanent error",
559                              erp->dstat->lpum,
560                              ioinfo[irq]->opm);
561
562                /* post request with permanent error */
563                check_then_set (&erp->status,
564                                CQR_STATUS_ERROR,
565                                CQR_STATUS_FAILED);
566
567        }
568
569} /* end dasd_3990_erp_alternate_path */
570
571/*
572 * DASD_3990_ERP_DCTL
573 *
574 * DESCRIPTION
575 *   Setup cqr to do the Diagnostic Control (DCTL) command with an
576 *   Inhibit Write subcommand (0x20) and the given modifier.
577 *
578 *  PARAMETER
579 *   erp                pointer to the current (failed) ERP
580 *   modifier           subcommand modifier
581 *
582 * RETURN VALUES
583 *   dctl_cqr           pointer to NEW dctl_cqr
584 *
585 */
586ccw_req_t *
587dasd_3990_erp_DCTL (ccw_req_t *erp,
588                    char      modifier)
589{
590
591	dasd_device_t *device = erp->device;
592	DCTL_data_t   *DCTL_data;
593        ccw1_t        *ccw;
594        ccw_req_t     *dctl_cqr = dasd_alloc_request ((char *) &erp->magic,
595                                                      1,
596                                                      sizeof(DCTL_data_t),
597                                                      erp->device);
598
599	if (!dctl_cqr) {
600
601                DASD_MESSAGE (KERN_ERR, device, "%s",
602                              "Unable to allocate DCTL-CQR");
603
604                check_then_set (&erp->status,
605                                CQR_STATUS_ERROR,
606                                CQR_STATUS_FAILED);
607
608		return erp;
609        }
610
611	DCTL_data = dctl_cqr->data;
612
613        DCTL_data->subcommand = 0x02; /* Inhibit Write */
614        DCTL_data->modifier   = modifier;
615
616	ccw = dctl_cqr->cpaddr;
617	memset (ccw, 0, sizeof (ccw1_t));
618        ccw->cmd_code = CCW_CMD_DCTL;
619        ccw->count    = 4;
620        if (dasd_set_normalized_cda(ccw,
621                                    __pa (DCTL_data), dctl_cqr, erp->device)) {
622                dasd_free_request (dctl_cqr, erp->device);
623                DASD_MESSAGE (KERN_ERR, device, "%s",
624                              "Unable to allocate DCTL-CQR");
625
626                check_then_set (&erp->status,
627                                CQR_STATUS_ERROR,
628                                CQR_STATUS_FAILED);
629		return erp;
630        }
631        dctl_cqr->function = dasd_3990_erp_DCTL;
632        dctl_cqr->refers   = erp;
633        dctl_cqr->device   = erp->device;
634        dctl_cqr->magic    = erp->magic;
635        dctl_cqr->lpm      = LPM_ANYPATH;
636        dctl_cqr->expires  = 5 * TOD_MIN;
637        dctl_cqr->retries  = 2;
638	asm volatile ("STCK %0":"=m" (dctl_cqr->buildclk));
639
640        dctl_cqr->status = CQR_STATUS_FILLED;
641
642	return dctl_cqr;
643
644} /* end dasd_3990_erp_DCTL */
645
646/*
647 * DASD_3990_ERP_ACTION_1
648 *
649 * DESCRIPTION
650 *   Setup ERP to do the ERP action 1 (see Reference manual).
651 *   Repeat the operation on a different channel path.
652 *   If all alternate paths have been tried, the request is posted with a
653 *   permanent error.
654 *   Note: duplex handling is not implemented (yet).
655 *
656 *  PARAMETER
657 *   erp                pointer to the current ERP
658 *
659 * RETURN VALUES
660 *   erp                pointer to the ERP
661 *
662 */
663ccw_req_t *
664dasd_3990_erp_action_1 (ccw_req_t *erp)
665{
666
667        erp->function = dasd_3990_erp_action_1;
668
669        dasd_3990_erp_alternate_path (erp);
670
671	return erp;
672
673} /* end dasd_3990_erp_action_1 */
674
675/*
676 * DASD_3990_ERP_ACTION_4
677 *
678 * DESCRIPTION
679 *   Setup ERP to do the ERP action 4 (see Reference manual).
680 *   Set the current request to PENDING to block the CQR queue for that device
681 *   until the state change interrupt appears.
682 *   Use a timer (20 seconds) to retry the cqr if the interrupt is still missing.
683 *
684 *  PARAMETER
685 *   sense              sense data of the actual error
686 *   erp                pointer to the current ERP
687 *
688 * RETURN VALUES
689 *   erp                pointer to the ERP
690 *
691 */
692ccw_req_t *
693dasd_3990_erp_action_4 (ccw_req_t *erp,
694			char      *sense)
695{
696
697	dasd_device_t *device = erp->device;
698
699        /* first time set initial retry counter and erp_function    */
700        /* and retry once without waiting for state change pending  */
701        /* interrupt (this enables easier enqueing of the cqr)      */
702        if (erp->function != dasd_3990_erp_action_4) {
703
704                erp->retries  = 256;
705                erp->function = dasd_3990_erp_action_4;
706
707        } else {
708
709                if (sense[25] & 0x1D) {	/* state change pending */
710
711                        DASD_MESSAGE (KERN_INFO, device, "%s",
712                                      "waiting for state change pending "
713                                      "int");
714
715                        dasd_3990_erp_block_queue (erp,
716                                                   30);
717
718                } else {
719
720                        /* no state change pending - retry */
721                        check_then_set (&erp->status,
722                                        CQR_STATUS_ERROR,
723                                        CQR_STATUS_QUEUED);
724                }
725        }
726
727	return erp;
728
729} /* end dasd_3990_erp_action_4 */
730
731/*
732 *****************************************************************************
733 * 24 byte sense ERP functions (only)
734 *****************************************************************************
735 */
736
737/*
738 * DASD_3990_ERP_ACTION_5
739 *
740 * DESCRIPTION
741 *   Setup ERP to do the ERP action 5 (see Reference manual).
742 *   NOTE: Further handling is done in xxx_further_erp after the retries.
743 *
744 *  PARAMETER
745 *   erp                pointer to the current ERP
746 *
747 * RETURN VALUES
748 *   erp                pointer to the ERP
749 *
750 */
751ccw_req_t *
752dasd_3990_erp_action_5 (ccw_req_t *erp)
753{
754
755        /* first of all retry */
756        erp->retries = 10;
757        erp->function = dasd_3990_erp_action_5;
758
759        return erp;
760
761} /* end dasd_3990_erp_action_5 */
762
763/*
764 * DASD_3990_HANDLE_ENV_DATA
765 *
766 * DESCRIPTION
767 *   Handles 24 byte 'Environmental data present'.
768 *   Does a analysis of the sense data (message Format)
769 *   and prints the error messages.
770 *
771 * PARAMETER
772 *   sense              current sense data
773 *
774 * RETURN VALUES
775 *   void
776 */
777void
778dasd_3990_handle_env_data (ccw_req_t *erp,
779                           char      *sense)
780{
781
782        dasd_device_t *device = erp->device;
783	char msg_format       = (sense[7] & 0xF0);
784	char msg_no           = (sense[7] & 0x0F);
785
786
787	switch (msg_format) {
788	case 0x00:	/* Format 0 - Program or System Checks */
789
790		if (sense[1] & 0x10) {	/* check message to operator bit */
791
792			switch (msg_no) {
793			case 0x00:	/* No Message */
794				break;
795			case 0x01:
796                                DASD_MESSAGE (KERN_WARNING, device, "%s",
797                                              "FORMAT 0 - Invalid Command");
798				break;
799			case 0x02:
800                                DASD_MESSAGE (KERN_WARNING, device, "%s",
801                                              "FORMAT 0 - Invalid Command "
802                                              "Sequence");
803				break;
804			case 0x03:
805                                DASD_MESSAGE (KERN_WARNING, device, "%s",
806                                              "FORMAT 0 - CCW Count less than "
807                                              "required");
808				break;
809			case 0x04:
810                                DASD_MESSAGE (KERN_WARNING, device, "%s",
811                                              "FORMAT 0 - Invalid Parameter");
812				break;
813			case 0x05:
814                                DASD_MESSAGE (KERN_WARNING, device, "%s",
815                                              "FORMAT 0 - Diagnostic of Sepecial"
816                                              " Command Violates File Mask");
817				break;
818			case 0x07:
819                                DASD_MESSAGE (KERN_WARNING, device, "%s",
820                                              "FORMAT 0 - Channel Returned with "
821                                              "Incorrect retry CCW");
822				break;
823			case 0x08:
824                                DASD_MESSAGE (KERN_WARNING, device, "%s",
825                                              "FORMAT 0 - Reset Notification");
826				break;
827			case 0x09:
828                                DASD_MESSAGE (KERN_WARNING, device, "%s",
829                                              "FORMAT 0 - Storage Path Restart");
830				break;
831			case 0x0A:
832                                DASD_MESSAGE (KERN_WARNING, device,
833                                              "FORMAT 0 - Channel requested "
834                                              "... %02x",
835                                              sense[8]);
836				break;
837			case 0x0B:
838                                DASD_MESSAGE (KERN_WARNING, device, "%s",
839                                              "FORMAT 0 - Invalid Defective/"
840                                              "Alternate Track Pointer");
841				break;
842			case 0x0C:
843                                DASD_MESSAGE (KERN_WARNING, device, "%s",
844                                              "FORMAT 0 - DPS Installation "
845                                              "Check");
846				break;
847			case 0x0E:
848                                DASD_MESSAGE (KERN_WARNING, device, "%s",
849                                              "FORMAT 0 - Command Invalid on "
850                                              "Secondary Address");
851				break;
852			case 0x0F:
853                                DASD_MESSAGE (KERN_WARNING, device,
854                                              "FORMAT 0 - Status Not As "
855                                              "Required: reason %02x",
856                                              sense[8]);
857				break;
858			default:
859                                DASD_MESSAGE (KERN_WARNING, device, "%s",
860                                              "FORMAT 0 - Reseved");
861			}
862		} else {
863			switch (msg_no) {
864			case 0x00:	/* No Message */
865				break;
866			case 0x01:
867                                DASD_MESSAGE (KERN_WARNING, device, "%s",
868                                              "FORMAT 0 - Device Error Source");
869				break;
870			case 0x02:
871                                DASD_MESSAGE (KERN_WARNING, device, "%s",
872                                              "FORMAT 0 - Reserved");
873				break;
874			case 0x03:
875                                DASD_MESSAGE (KERN_WARNING, device,
876                                              "FORMAT 0 - Device Fenced - "
877                                              "device = %02x",
878                                              sense[4]);
879				break;
880			case 0x04:
881                                DASD_MESSAGE (KERN_WARNING, device, "%s",
882                                              "FORMAT 0 - Data Pinned for "
883                                              "Device");
884				break;
885			default:
886                                DASD_MESSAGE (KERN_WARNING, device, "%s",
887                                              "FORMAT 0 - Reserved");
888			}
889                }
890                break;
891
892	case 0x10:	/* Format 1 - Device Equipment Checks */
893		switch (msg_no) {
894		case 0x00:	/* No Message */
895			break;
896		case 0x01:
897                        DASD_MESSAGE (KERN_WARNING, device, "%s",
898                                      "FORMAT 1 - Device Status 1 not as "
899                                      "expected");
900			break;
901		case 0x03:
902                        DASD_MESSAGE (KERN_WARNING, device, "%s",
903                                      "FORMAT 1 - Index missing");
904			break;
905		case 0x04:
906                        DASD_MESSAGE (KERN_WARNING, device, "%s",
907                                      "FORMAT 1 - Interruption cannot be reset");
908			break;
909		case 0x05:
910                        DASD_MESSAGE (KERN_WARNING, device, "%s",
911                                      "FORMAT 1 - Device did not respond to "
912                                      "selection");
913			break;
914		case 0x06:
915                        DASD_MESSAGE (KERN_WARNING, device, "%s",
916                                      "FORMAT 1 - Device check-2 error or Set "
917                                      "Sector is not complete");
918			break;
919		case 0x07:
920                        DASD_MESSAGE (KERN_WARNING, device, "%s",
921                                      "FORMAT 1 - Head address does not "
922                                      "compare");
923			break;
924		case 0x08:
925                        DASD_MESSAGE (KERN_WARNING, device, "%s",
926                                      "FORMAT 1 - Device status 1 not valid");
927			break;
928		case 0x09:
929                        DASD_MESSAGE (KERN_WARNING, device, "%s",
930                                      "FORMAT 1 - Device not ready");
931			break;
932		case 0x0A:
933                        DASD_MESSAGE (KERN_WARNING, device, "%s",
934                                      "FORMAT 1 - Track physical address did "
935                                      "not compare");
936			break;
937		case 0x0B:
938                        DASD_MESSAGE (KERN_WARNING, device, "%s",
939                                      "FORMAT 1 - Missing device address bit");
940			break;
941		case 0x0C:
942                        DASD_MESSAGE (KERN_WARNING, device, "%s",
943                                      "FORMAT 1 - Drive motor switch is off");
944			break;
945		case 0x0D:
946                        DASD_MESSAGE (KERN_WARNING, device, "%s",
947                                      "FORMAT 1 - Seek incomplete");
948			break;
949		case 0x0E:
950                        DASD_MESSAGE (KERN_WARNING, device, "%s",
951                                      "FORMAT 1 - Cylinder address did not "
952                                      "compare");
953			break;
954		case 0x0F:
955                        DASD_MESSAGE (KERN_WARNING, device, "%s",
956                                      "FORMAT 1 - Offset active cannot be "
957                                      "reset");
958			break;
959		default:
960                        DASD_MESSAGE (KERN_WARNING, device, "%s",
961                                      "FORMAT 1 - Reserved");
962		}
963                break;
964
965	case 0x20:	/* Format 2 - 3990 Equipment Checks */
966		switch (msg_no) {
967		case 0x08:
968                        DASD_MESSAGE (KERN_WARNING, device, "%s",
969                                      "FORMAT 2 - 3990 check-2 error");
970			break;
971		case 0x0E:
972                        DASD_MESSAGE (KERN_WARNING, device, "%s",
973                                      "FORMAT 2 - Support facility errors");
974			break;
975		case 0x0F:
976                        DASD_MESSAGE (KERN_WARNING, device,
977                                      "FORMAT 2 - Microcode detected error %02x",
978                                      sense[8]);
979			break;
980		default:
981                        DASD_MESSAGE (KERN_WARNING, device, "%s",
982                                      "FORMAT 2 - Reserved");
983		}
984                break;
985
986	case 0x30:	/* Format 3 - 3990 Control Checks */
987		switch (msg_no) {
988		case 0x0F:
989                        DASD_MESSAGE (KERN_WARNING, device, "%s",
990                                      "FORMAT 3 - Allegiance terminated");
991			break;
992		default:
993                        DASD_MESSAGE (KERN_WARNING, device, "%s",
994                                      "FORMAT 3 - Reserved");
995		}
996                break;
997
998	case 0x40:	/* Format 4 - Data Checks */
999		switch (msg_no) {
1000		case 0x00:
1001                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1002                                      "FORMAT 4 - Home address area error");
1003			break;
1004		case 0x01:
1005                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1006                                      "FORMAT 4 - Count area error");
1007			break;
1008		case 0x02:
1009                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1010                                      "FORMAT 4 - Key area error");
1011			break;
1012		case 0x03:
1013                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1014                                      "FORMAT 4 - Data area error");
1015			break;
1016		case 0x04:
1017                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1018                                      "FORMAT 4 - No sync byte in home address "
1019                                      "area");
1020			break;
1021		case 0x05:
1022                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1023                                      "FORMAT 4 - No sync byte in count address "
1024                                      "area");
1025			break;
1026		case 0x06:
1027                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1028                                      "FORMAT 4 - No sync byte in key area");
1029			break;
1030		case 0x07:
1031                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1032                                      "FORMAT 4 - No sync byte in data area");
1033			break;
1034		case 0x08:
1035                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1036                                      "FORMAT 4 - Home address area error; "
1037                                      "offset active");
1038			break;
1039		case 0x09:
1040                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1041                                      "FORMAT 4 - Count area error; offset "
1042                                      "active");
1043			break;
1044		case 0x0A:
1045                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1046                                      "FORMAT 4 - Key area error; offset "
1047                                      "active");
1048			break;
1049		case 0x0B:
1050                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1051                                      "FORMAT 4 - Data area error; "
1052                                      "offset active");
1053			break;
1054		case 0x0C:
1055                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1056                                      "FORMAT 4 - No sync byte in home "
1057                                      "address area; offset active");
1058			break;
1059		case 0x0D:
1060                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1061                                      "FORMAT 4 - No syn byte in count "
1062                                      "address area; offset active");
1063			break;
1064		case 0x0E:
1065                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1066                                      "FORMAT 4 - No sync byte in key area; "
1067                                      "offset active");
1068			break;
1069		case 0x0F:
1070                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1071                                      "FORMAT 4 - No syn byte in data area; "
1072                                      "offset active");
1073			break;
1074		default:
1075                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1076                                      "FORMAT 4 - Reserved");
1077		}
1078                break;
1079
1080	case 0x50:	/* Format 5 - Data Check with displacement information */
1081		switch (msg_no) {
1082		case 0x00:
1083                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1084                                      "FORMAT 5 - Data Check in the "
1085                                      "home address area");
1086			break;
1087		case 0x01:
1088                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1089                                      "FORMAT 5 - Data Check in the count area");
1090			break;
1091		case 0x02:
1092                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1093                                      "FORMAT 5 - Data Check in the key area");
1094			break;
1095		case 0x03:
1096                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1097                                      "FORMAT 5 - Data Check in the data area");
1098			break;
1099		case 0x08:
1100                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1101                                      "FORMAT 5 - Data Check in the "
1102                                      "home address area; offset active");
1103			break;
1104		case 0x09:
1105                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1106                                      "FORMAT 5 - Data Check in the count area; "
1107                                      "offset active");
1108			break;
1109		case 0x0A:
1110                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1111                                      "FORMAT 5 - Data Check in the key area; "
1112                                      "offset active");
1113			break;
1114		case 0x0B:
1115                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1116                                      "FORMAT 5 - Data Check in the data area; "
1117                                      "offset active");
1118			break;
1119		default:
1120                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1121                                      "FORMAT 5 - Reserved");
1122		}
1123                break;
1124
1125	case 0x60:	/* Format 6 - Usage Statistics/Overrun Errors */
1126		switch (msg_no) {
1127		case 0x00:
1128                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1129                                      "FORMAT 6 - Overrun on channel A");
1130			break;
1131		case 0x01:
1132                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1133                                      "FORMAT 6 - Overrun on channel B");
1134			break;
1135		case 0x02:
1136                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1137                                      "FORMAT 6 - Overrun on channel C");
1138			break;
1139		case 0x03:
1140                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1141                                      "FORMAT 6 - Overrun on channel D");
1142			break;
1143		case 0x04:
1144                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1145                                      "FORMAT 6 - Overrun on channel E");
1146			break;
1147		case 0x05:
1148                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1149                                      "FORMAT 6 - Overrun on channel F");
1150			break;
1151		case 0x06:
1152                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1153                                      "FORMAT 6 - Overrun on channel G");
1154			break;
1155		case 0x07:
1156                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1157                                      "FORMAT 6 - Overrun on channel H");
1158			break;
1159		default:
1160                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1161                                      "FORMAT 6 - Reserved");
1162		}
1163                break;
1164
1165	case 0x70:	/* Format 7 - Device Connection Control Checks */
1166		switch (msg_no) {
1167		case 0x00:
1168                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1169                                      "FORMAT 7 - RCC initiated by a connection "
1170                                      "check alert");
1171			break;
1172		case 0x01:
1173                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1174                                      "FORMAT 7 - RCC 1 sequence not "
1175                                      "successful");
1176			break;
1177		case 0x02:
1178                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1179                                      "FORMAT 7 - RCC 1 and RCC 2 sequences not "
1180                                      "successful");
1181			break;
1182		case 0x03:
1183                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1184                                      "FORMAT 7 - Invalid tag-in during "
1185                                      "selection sequence");
1186			break;
1187		case 0x04:
1188                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1189                                      "FORMAT 7 - extra RCC required");
1190			break;
1191		case 0x05:
1192                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1193                                      "FORMAT 7 - Invalid DCC selection "
1194                                      "response or timeout");
1195			break;
1196		case 0x06:
1197                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1198                                      "FORMAT 7 - Missing end operation; device "
1199                                      "transfer complete");
1200			break;
1201		case 0x07:
1202                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1203                                      "FORMAT 7 - Missing end operation; device "
1204                                      "transfer incomplete");
1205			break;
1206		case 0x08:
1207                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1208                                      "FORMAT 7 - Invalid tag-in for an "
1209                                      "immediate command sequence");
1210			break;
1211		case 0x09:
1212                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1213                                      "FORMAT 7 - Invalid tag-in for an "
1214                                      "extended command sequence");
1215			break;
1216		case 0x0A:
1217                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1218                                      "FORMAT 7 - 3990 microcode time out when "
1219                                      "stopping selection");
1220			break;
1221		case 0x0B:
1222                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1223                                      "FORMAT 7 - No response to selection "
1224                                      "after a poll interruption");
1225			break;
1226		case 0x0C:
1227                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1228                                      "FORMAT 7 - Permanent path error (DASD "
1229                                      "controller not available)");
1230			break;
1231		case 0x0D:
1232                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1233                                      "FORMAT 7 - DASD controller not available"
1234                                      " on disconnected command chain");
1235			break;
1236		default:
1237                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1238                                      "FORMAT 7 - Reserved");
1239		}
1240                break;
1241
1242	case 0x80:	/* Format 8 - Additional Device Equipment Checks */
1243		switch (msg_no) {
1244		case 0x00:	/* No Message */
1245		case 0x01:
1246                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1247                                      "FORMAT 8 - Error correction code "
1248                                      "hardware fault");
1249			break;
1250		case 0x03:
1251                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1252                                      "FORMAT 8 - Unexpected end operation "
1253                                      "response code");
1254			break;
1255		case 0x04:
1256                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1257                                      "FORMAT 8 - End operation with transfer "
1258                                      "count not zero");
1259			break;
1260		case 0x05:
1261                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1262                                      "FORMAT 8 - End operation with transfer "
1263                                      "count zero");
1264			break;
1265		case 0x06:
1266                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1267                                      "FORMAT 8 - DPS checks after a system "
1268                                      "reset or selective reset");
1269			break;
1270		case 0x07:
1271                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1272                                      "FORMAT 8 - DPS cannot be filled");
1273			break;
1274		case 0x08:
1275                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1276                                      "FORMAT 8 - Short busy time-out during "
1277                                      "device selection");
1278			break;
1279		case 0x09:
1280                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1281                                      "FORMAT 8 - DASD controller failed to "
1282                                      "set or reset the long busy latch");
1283			break;
1284		case 0x0A:
1285                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1286                                      "FORMAT 8 - No interruption from device "
1287                                      "during a command chain");
1288			break;
1289		default:
1290                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1291                                      "FORMAT 8 - Reserved");
1292		}
1293                break;
1294
1295	case 0x90:	/* Format 9 - Device Read, Write, and Seek Checks */
1296		switch (msg_no) {
1297		case 0x00:
1298			break;	/* No Message */
1299		case 0x06:
1300                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1301                                      "FORMAT 9 - Device check-2 error");
1302			break;
1303		case 0x07:
1304                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1305                                      "FORMAT 9 - Head address did not compare");
1306			break;
1307		case 0x0A:
1308                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1309                                      "FORMAT 9 - Track physical address did "
1310                                      "not compare while oriented");
1311			break;
1312		case 0x0E:
1313                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1314                                      "FORMAT 9 - Cylinder address did not "
1315                                      "compare");
1316			break;
1317		default:
1318                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1319                                      "FORMAT 9 - Reserved");
1320		}
1321                break;
1322
1323	case 0xF0:		/* Format F - Cache Storage Checks */
1324		switch (msg_no) {
1325		case 0x00:
1326                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1327                                      "FORMAT F - Operation Terminated");
1328			break;
1329		case 0x01:
1330                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1331                                      "FORMAT F - Subsystem Processing Error");
1332			break;
1333		case 0x02:
1334                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1335                                      "FORMAT F - Cache or nonvolatile storage "
1336                                      "equipment failure");
1337			break;
1338		case 0x04:
1339                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1340                                      "FORMAT F - Caching terminated");
1341			break;
1342		case 0x06:
1343                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1344                                      "FORMAT F - Cache fast write access not "
1345                                      "authorized");
1346			break;
1347		case 0x07:
1348                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1349                                      "FORMAT F - Track format incorrect");
1350			break;
1351		case 0x09:
1352                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1353                                      "FORMAT F - Caching reinitiated");
1354			break;
1355		case 0x0A:
1356                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1357                                      "FORMAT F - Nonvolatile storage "
1358                                      "terminated");
1359			break;
1360		case 0x0B:
1361                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1362                                      "FORMAT F - Volume is suspended duplex");
1363			break;
1364		case 0x0C:
1365                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1366                                      "FORMAT F - Subsystem status connot be "
1367                                      "determined");
1368			break;
1369		case 0x0D:
1370                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1371                                      "FORMAT F - Caching status reset to "
1372                                      "default");
1373			break;
1374		case 0x0E:
1375                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1376                                      "FORMAT F - DASD Fast Write inhibited");
1377			break;
1378		default:
1379                        DASD_MESSAGE (KERN_WARNING, device, "%s",
1380                                      "FORMAT D - Reserved");
1381		}
1382                break;
1383
1384	default:	/* unknown message format - should not happen */
1385
1386	} /* end switch message format */
1387
1388} /* end dasd_3990_handle_env_data */
1389
1390/*
1391 * DASD_3990_ERP_COM_REJ
1392 *
1393 * DESCRIPTION
1394 *   Handles 24 byte 'Command Reject' error.
1395 *
1396 * PARAMETER
1397 *   erp                current erp_head
1398 *   sense              current sense data
1399 *
1400 * RETURN VALUES
1401 *   erp                'new' erp_head - pointer to new ERP
1402 */
1403ccw_req_t *
1404dasd_3990_erp_com_rej (ccw_req_t *erp,
1405		       char      *sense)
1406{
1407
1408	dasd_device_t *device = erp->device;
1409
1410        erp->function = dasd_3990_erp_com_rej;
1411
1412	/* env data present (ACTION 10 - retry should work) */
1413	if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1414
1415                DASD_MESSAGE (KERN_DEBUG, device, "%s",
1416                              "Command Reject - environmental data present");
1417
1418		dasd_3990_handle_env_data (erp,
1419                                           sense);
1420
1421		erp->retries = 5;
1422
1423	} else {
1424		/* fatal error -  set status to FAILED */
1425                DASD_MESSAGE (KERN_ERR, device, "%s",
1426                              "Command Reject - Fatal error");
1427
1428                erp = dasd_3990_erp_cleanup (erp,
1429                                             CQR_STATUS_FAILED);
1430	}
1431
1432	return erp;
1433
1434} /* end dasd_3990_erp_com_rej */
1435
1436/*
1437 * DASD_3990_ERP_BUS_OUT
1438 *
1439 * DESCRIPTION
1440 *   Handles 24 byte 'Bus Out Parity Check' error.
1441 *
1442 * PARAMETER
1443 *   erp                current erp_head
1444 * RETURN VALUES
1445 *   erp                new erp_head - pointer to new ERP
1446 */
1447ccw_req_t *
1448dasd_3990_erp_bus_out (ccw_req_t *erp)
1449{
1450
1451	dasd_device_t *device = erp->device;
1452
1453        /* first time set initial retry counter and erp_function */
1454        /* and retry once without blocking queue                 */
1455        /* (this enables easier enqueing of the cqr)             */
1456        if (erp->function != dasd_3990_erp_bus_out) {
1457                erp->retries  = 256;
1458                erp->function = dasd_3990_erp_bus_out;
1459
1460        } else {
1461
1462                /* issue a message and wait for 'device ready' interrupt */
1463                DASD_MESSAGE (KERN_DEBUG, device, "%s",
1464                              "bus out parity error or BOPC requested by "
1465                              "channel");
1466
1467                dasd_3990_erp_block_queue (erp,
1468                                           60);
1469
1470        }
1471
1472	return erp;
1473
1474} /* end dasd_3990_erp_bus_out */
1475
1476/*
1477 * DASD_3990_ERP_EQUIP_CHECK
1478 *
1479 * DESCRIPTION
1480 *   Handles 24 byte 'Equipment Check' error.
1481 *
1482 * PARAMETER
1483 *   erp                current erp_head
1484 * RETURN VALUES
1485 *   erp                new erp_head - pointer to new ERP
1486 */
1487ccw_req_t *
1488dasd_3990_erp_equip_check (ccw_req_t *erp,
1489			   char      *sense)
1490{
1491
1492	dasd_device_t *device = erp->device;
1493
1494	erp->function = dasd_3990_erp_equip_check;
1495
1496	if (sense[1] & SNS1_WRITE_INHIBITED) {
1497
1498		DASD_MESSAGE (KERN_DEBUG, device, "%s",
1499                              "Write inhibited path encountered");
1500
1501		/* vary path offline */
1502		DASD_MESSAGE (KERN_ERR, device, "%s",
1503                              "Path should be varied off-line. "
1504                              "This is not implemented yet \n - please report "
1505                              "to linux390@de.ibm.com");
1506
1507		erp = dasd_3990_erp_action_1 (erp);
1508
1509	} else if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1510
1511                DASD_MESSAGE (KERN_DEBUG, device, "%s",
1512                              "Equipment Check - "
1513                              "environmental data present");
1514
1515                dasd_3990_handle_env_data (erp,
1516                                           sense);
1517
1518                erp = dasd_3990_erp_action_4 (erp,
1519                                              sense);
1520
1521        } else if (sense[1] & SNS1_PERM_ERR) {
1522                DASD_MESSAGE (KERN_DEBUG, device, "%s",
1523                              "Equipment Check - retry exhausted or "
1524                              "undesirable");
1525
1526                erp = dasd_3990_erp_action_1 (erp);
1527
1528        } else {
1529                /* all other equipment checks - Action 5 */
1530                /* rest is done when retries == 0 */
1531                DASD_MESSAGE (KERN_DEBUG, device, "%s",
1532                              "Equipment check or processing error");
1533
1534                erp = dasd_3990_erp_action_5 (erp);
1535        }
1536
1537        return erp;
1538
1539} /* end dasd_3990_erp_equip_check */
1540
1541/*
1542 * DASD_3990_ERP_DATA_CHECK
1543 *
1544 * DESCRIPTION
1545 *   Handles 24 byte 'Data Check' error.
1546 *
1547 * PARAMETER
1548 *   erp                current erp_head
1549 * RETURN VALUES
1550 *   erp                new erp_head - pointer to new ERP
1551 */
1552ccw_req_t *
1553dasd_3990_erp_data_check (ccw_req_t *erp,
1554			  char      *sense)
1555{
1556
1557	dasd_device_t *device = erp->device;
1558
1559	erp->function = dasd_3990_erp_data_check;
1560
1561	if (sense[2] & SNS2_CORRECTABLE) {	/* correctable data check */
1562
1563		/* issue message that the data has been corrected */
1564		DASD_MESSAGE (KERN_EMERG, device, "%s",
1565                              "Data recovered during retry with PCI "
1566                              "fetch mode active");
1567
1568                /* not possible to handle this situation in Linux */
1569                panic("No way to inform appliction about the possibly "
1570                      "incorret data");
1571
1572	} else if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1573
1574		DASD_MESSAGE (KERN_DEBUG, device, "%s",
1575                              "Uncorrectable data check recovered secondary "
1576                              "addr of duplex pair");
1577
1578		erp = dasd_3990_erp_action_4 (erp,
1579					      sense);
1580
1581	} else if (sense[1] & SNS1_PERM_ERR) {
1582
1583		DASD_MESSAGE (KERN_DEBUG, device, "%s",
1584                              "Uncorrectable data check with internal "
1585                              "retry exhausted");
1586
1587		erp = dasd_3990_erp_action_1 (erp);
1588
1589	} else {
1590		/* all other data checks */
1591		DASD_MESSAGE (KERN_DEBUG, device, "%s",
1592                              "Uncorrectable data check with retry count "
1593                              "exhausted...");
1594
1595		erp = dasd_3990_erp_action_5 (erp);
1596	}
1597
1598	return erp;
1599
1600} /* end dasd_3990_erp_data_check */
1601
1602/*
1603 * DASD_3990_ERP_OVERRUN
1604 *
1605 * DESCRIPTION
1606 *   Handles 24 byte 'Overrun' error.
1607 *
1608 * PARAMETER
1609 *   erp                current erp_head
1610 * RETURN VALUES
1611 *   erp                new erp_head - pointer to new ERP
1612 */
1613ccw_req_t *
1614dasd_3990_erp_overrun (ccw_req_t *erp,
1615		       char      *sense)
1616{
1617
1618	dasd_device_t *device = erp->device;
1619
1620	erp->function = dasd_3990_erp_overrun;
1621
1622        DASD_MESSAGE (KERN_DEBUG, device, "%s",
1623                      "Overrun - service overrun or overrun"
1624                      " error requested by channel");
1625
1626        erp = dasd_3990_erp_action_5 (erp);
1627
1628	return erp;
1629
1630} /* end dasd_3990_erp_overrun */
1631
1632/*
1633 * DASD_3990_ERP_INV_FORMAT
1634 *
1635 * DESCRIPTION
1636 *   Handles 24 byte 'Invalid Track Format' error.
1637 *
1638 * PARAMETER
1639 *   erp                current erp_head
1640 * RETURN VALUES
1641 *   erp                new erp_head - pointer to new ERP
1642 */
1643ccw_req_t *
1644dasd_3990_erp_inv_format (ccw_req_t *erp,
1645			  char      *sense)
1646{
1647
1648	dasd_device_t *device = erp->device;
1649
1650	erp->function = dasd_3990_erp_inv_format;
1651
1652	if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1653
1654		DASD_MESSAGE (KERN_DEBUG, device, "%s",
1655                              "Track format error when destaging or "
1656                              "staging data");
1657
1658		dasd_3990_handle_env_data (erp,
1659                                           sense);
1660
1661		erp = dasd_3990_erp_action_4 (erp,
1662					      sense);
1663
1664	} else {
1665		DASD_MESSAGE (KERN_ERR, device, "%s",
1666                              "Invalid Track Format - Fatal error should have "
1667                              "been handled within the interrupt handler");
1668
1669                erp= dasd_3990_erp_cleanup (erp,
1670                                            CQR_STATUS_FAILED);
1671        }
1672
1673	return erp;
1674
1675} /* end dasd_3990_erp_inv_format */
1676
1677/*
1678 * DASD_3990_ERP_EOC
1679 *
1680 * DESCRIPTION
1681 *   Handles 24 byte 'End-of-Cylinder' error.
1682 *
1683 * PARAMETER
1684 *   erp                already added default erp
1685 * RETURN VALUES
1686 *   erp                pointer to original (failed) cqr.
1687 */
1688ccw_req_t *
1689dasd_3990_erp_EOC (ccw_req_t *default_erp,
1690		   char      *sense)
1691{
1692
1693	dasd_device_t *device = default_erp->device;
1694
1695        DASD_MESSAGE (KERN_ERR, device, "%s",
1696                      "End-of-Cylinder - must never happen");
1697
1698        /* implement action 7 - BUG */
1699        return dasd_3990_erp_cleanup (default_erp,
1700                                      CQR_STATUS_FAILED);
1701
1702} /* end dasd_3990_erp_EOC */
1703
1704/*
1705 * DASD_3990_ERP_ENV_DATA
1706 *
1707 * DESCRIPTION
1708 *   Handles 24 byte 'Environmental-Data Present' error.
1709 *
1710 * PARAMETER
1711 *   erp                current erp_head
1712 * RETURN VALUES
1713 *   erp                new erp_head - pointer to new ERP
1714 */
1715ccw_req_t *
1716dasd_3990_erp_env_data (ccw_req_t *erp,
1717			char      *sense)
1718{
1719
1720	dasd_device_t *device = erp->device;
1721
1722	erp->function = dasd_3990_erp_env_data;
1723
1724        DASD_MESSAGE (KERN_DEBUG, device, "%s",
1725                      "Environmental data present");
1726
1727        dasd_3990_handle_env_data (erp,
1728                                   sense);
1729
1730        /* don't retry on disabled interface */
1731        if (sense[7] != 0x0F) {
1732
1733                erp = dasd_3990_erp_action_4 (erp,
1734                                              sense);
1735        } else {
1736
1737                erp = dasd_3990_erp_cleanup (erp,
1738                                             CQR_STATUS_IN_IO);
1739        }
1740
1741	return erp;
1742
1743} /* end dasd_3990_erp_env_data */
1744
1745/*
1746 * DASD_3990_ERP_NO_REC
1747 *
1748 * DESCRIPTION
1749 *   Handles 24 byte 'No Record Found' error.
1750 *
1751 * PARAMETER
1752 *   erp                already added default ERP
1753 *
1754 * RETURN VALUES
1755 *   erp                new erp_head - pointer to new ERP
1756 */
1757ccw_req_t *
1758dasd_3990_erp_no_rec (ccw_req_t *default_erp,
1759		      char      *sense)
1760{
1761
1762	dasd_device_t *device = default_erp->device;
1763
1764        DASD_MESSAGE (KERN_ERR, device, "%s",
1765                      "No Record Found - Fatal error should "
1766                      "have been handled within the interrupt handler");
1767
1768        return dasd_3990_erp_cleanup (default_erp,
1769                                      CQR_STATUS_FAILED);
1770
1771} /* end dasd_3990_erp_no_rec */
1772
1773/*
1774 * DASD_3990_ERP_FILE_PROT
1775 *
1776 * DESCRIPTION
1777 *   Handles 24 byte 'File Protected' error.
1778 *   Note: Seek related recovery is not implemented because
1779 *         wee don't use the seek command yet.
1780 *
1781 * PARAMETER
1782 *   erp                current erp_head
1783 * RETURN VALUES
1784 *   erp                new erp_head - pointer to new ERP
1785 */
1786ccw_req_t *
1787dasd_3990_erp_file_prot (ccw_req_t *erp)
1788{
1789
1790	dasd_device_t *device = erp->device;
1791
1792        DASD_MESSAGE (KERN_ERR, device, "%s",
1793                      "File Protected");
1794
1795        return dasd_3990_erp_cleanup (erp,
1796                                      CQR_STATUS_FAILED);
1797
1798} /* end dasd_3990_erp_file_prot */
1799
1800/*
1801 * DASD_3990_ERP_INSPECT_24
1802 *
1803 * DESCRIPTION
1804 *   Does a detailed inspection of the 24 byte sense data
1805 *   and sets up a related error recovery action.
1806 *
1807 * PARAMETER
1808 *   sense              sense data of the actual error
1809 *   erp                pointer to the currently created default ERP
1810 *
1811 * RETURN VALUES
1812 *   erp                pointer to the (addtitional) ERP
1813 */
1814ccw_req_t *
1815dasd_3990_erp_inspect_24 (ccw_req_t *erp,
1816                          char      *sense)
1817{
1818
1819	ccw_req_t *erp_filled = NULL;
1820
1821	/* Check sense for ....    */
1822	/* 'Command Reject'        */
1823	if ((erp_filled == NULL) &&
1824	    (sense[0] & SNS0_CMD_REJECT)) {
1825		erp_filled = dasd_3990_erp_com_rej (erp,
1826						    sense);
1827	}
1828	/* 'Intervention Required' */
1829	if ((erp_filled == NULL) &&
1830	    (sense[0] & SNS0_INTERVENTION_REQ)) {
1831		erp_filled = dasd_3990_erp_int_req (erp);
1832	}
1833	/* 'Bus Out Parity Check'  */
1834	if ((erp_filled == NULL) &&
1835	    (sense[0] & SNS0_BUS_OUT_CHECK)) {
1836		erp_filled = dasd_3990_erp_bus_out (erp);
1837	}
1838	/* 'Equipment Check'       */
1839	if ((erp_filled == NULL) &&
1840	    (sense[0] & SNS0_EQUIPMENT_CHECK)) {
1841		erp_filled = dasd_3990_erp_equip_check (erp,
1842							sense);
1843	}
1844	/* 'Data Check'            */
1845	if ((erp_filled == NULL) &&
1846	    (sense[0] & SNS0_DATA_CHECK)) {
1847		erp_filled = dasd_3990_erp_data_check (erp,
1848						       sense);
1849	}
1850	/* 'Overrun'               */
1851	if ((erp_filled == NULL) &&
1852	    (sense[0] & SNS0_OVERRUN)) {
1853		erp_filled = dasd_3990_erp_overrun (erp,
1854						    sense);
1855	}
1856	/* 'Invalid Track Format'  */
1857	if ((erp_filled == NULL) &&
1858	    (sense[1] & SNS1_INV_TRACK_FORMAT)) {
1859		erp_filled = dasd_3990_erp_inv_format (erp,
1860						       sense);
1861	}
1862	/* 'End-of-Cylinder'       */
1863	if ((erp_filled == NULL) &&
1864	    (sense[1] & SNS1_EOC)) {
1865		erp_filled = dasd_3990_erp_EOC (erp,
1866						sense);
1867	}
1868	/* 'Environmental Data'    */
1869	if ((erp_filled == NULL) &&
1870	    (sense[2] & SNS2_ENV_DATA_PRESENT)) {
1871		erp_filled = dasd_3990_erp_env_data (erp,
1872						     sense);
1873	}
1874	/* 'No Record Found'       */
1875	if ((erp_filled == NULL) &&
1876	    (sense[1] & SNS1_NO_REC_FOUND)) {
1877		erp_filled = dasd_3990_erp_no_rec (erp,
1878						   sense);
1879	}
1880	/* 'File Protected'        */
1881	if ((erp_filled == NULL) &&
1882	    (sense[1] & SNS1_FILE_PROTECTED)) {
1883		erp_filled = dasd_3990_erp_file_prot (erp);
1884	}
1885	/* other (unknown) error - do default ERP */
1886	if (erp_filled == NULL) {
1887
1888		erp_filled = erp;
1889	}
1890
1891	return erp_filled;
1892
1893} /* END dasd_3990_erp_inspect_24 */
1894
1895/*
1896 *****************************************************************************
1897 * 32 byte sense ERP functions (only)
1898 *****************************************************************************
1899 */
1900
1901/*
1902 * DASD_3990_ERPACTION_10_32
1903 *
1904 * DESCRIPTION
1905 *   Handles 32 byte 'Action 10' of Single Program Action Codes.
1906 *   Just retry and if retry doesn't work, return with error.
1907 *
1908 * PARAMETER
1909 *   erp                current erp_head
1910 *   sense              current sense data
1911 * RETURN VALUES
1912 *   erp                modified erp_head
1913 */
1914ccw_req_t *
1915dasd_3990_erp_action_10_32 (ccw_req_t *erp,
1916                            char      *sense)
1917{
1918
1919	dasd_device_t *device = erp->device;
1920
1921        erp->retries  = 256;
1922        erp->function = dasd_3990_erp_action_10_32;
1923
1924	DASD_MESSAGE (KERN_DEBUG, device, "%s",
1925                      "Perform logging requested");
1926
1927	return erp;
1928
1929} /* end dasd_3990_erp_action_10_32 */
1930
1931/*
1932 * DASD_3990_ERP_ACTION_1B_32
1933 *
1934 * DESCRIPTION
1935 *   Handles 32 byte 'Action 1B' of Single Program Action Codes.
1936 *   A write operation could not be finished because of an unexpected
1937 *   condition.
1938 *   The already created 'default erp' is used to get the link to
1939 *   the erp chain, but it can not be used for this recovery
1940 *   action because it contains no DE/LO data space.
1941 *
1942 * PARAMETER
1943 *   default_erp        already added default erp.
1944 *   sense              current sense data
1945 *
1946 * RETURN VALUES
1947 *   erp                new erp or
1948 *                      default_erp in case of imprecise ending or error
1949 */
1950ccw_req_t *
1951dasd_3990_erp_action_1B_32 (ccw_req_t *default_erp,
1952                            char      *sense)
1953{
1954
1955	dasd_device_t  *device = default_erp->device;
1956        __u32          cpa     = 0;
1957        ccw_req_t      *cqr;
1958	ccw_req_t      *erp;
1959	DE_eckd_data_t *DE_data;
1960	char           *LO_data;   /* LO_eckd_data_t */
1961        ccw1_t         *ccw;
1962
1963	DASD_MESSAGE (KERN_DEBUG, device, "%s",
1964                      "Write not finished because of unexpected condition");
1965
1966        default_erp->function = dasd_3990_erp_action_1B_32;
1967
1968        /* determine the original cqr */
1969        cqr = default_erp;
1970
1971        while (cqr->refers != NULL){
1972                cqr = cqr->refers;
1973        }
1974
1975        /* for imprecise ending just do default erp */
1976        if (sense[1] & 0x01) {
1977
1978                DASD_MESSAGE (KERN_DEBUG, device, "%s",
1979                              "Imprecise ending is set - just retry");
1980
1981                return default_erp;
1982        }
1983
1984        /* determine the address of the CCW to be restarted */
1985        /* Imprecise ending is not set -> addr from IRB-SCSW */
1986        cpa = default_erp->refers->dstat->cpa;
1987
1988        if (cpa == 0) {
1989
1990                DASD_MESSAGE (KERN_DEBUG, device, "%s",
1991                              "Unable to determine address of the CCW "
1992                              "to be restarted");
1993
1994                return dasd_3990_erp_cleanup (default_erp,
1995                                              CQR_STATUS_FAILED);
1996        }
1997
1998	/* Build new ERP request including DE/LO */
1999	erp = dasd_alloc_request ((char *) &cqr->magic,
2000                                  2 + 1,                    /* DE/LO + TIC */
2001                                  sizeof (DE_eckd_data_t) +
2002                                  sizeof (LO_eckd_data_t),
2003                                  device);
2004
2005	if (!erp) {
2006
2007                DASD_MESSAGE (KERN_ERR, device, "%s",
2008                              "Unable to allocate ERP");
2009
2010                return dasd_3990_erp_cleanup (default_erp,
2011                                              CQR_STATUS_FAILED);
2012	}
2013
2014        /* use original DE */
2015	DE_data = erp->data;
2016        memcpy (DE_data,
2017                cqr->data,
2018                sizeof (DE_eckd_data_t));
2019
2020        /* create LO */
2021	LO_data = erp->data + sizeof (DE_eckd_data_t);
2022
2023        if ((sense[3]  == 0x01) &&
2024            (LO_data[1] & 0x01)   ){
2025
2026                DASD_MESSAGE (KERN_ERR, device, "%s",
2027                              "BUG - this should not happen");
2028
2029                return dasd_3990_erp_cleanup (default_erp,
2030                                              CQR_STATUS_FAILED);
2031        }
2032
2033        if ((sense[7] & 0x3F) == 0x01) {
2034                /* operation code is WRITE DATA -> data area orientation */
2035                LO_data[0] = 0x81;
2036
2037        } else if ((sense[7] & 0x3F) == 0x03) {
2038                /* operation code is FORMAT WRITE -> index orientation */
2039                LO_data[0] = 0xC3;
2040
2041        } else {
2042                LO_data[0] = sense[7];  /* operation */
2043        }
2044
2045        LO_data[1] = sense[8];  /* auxiliary */
2046        LO_data[2] = sense[9];
2047        LO_data[3] = sense[3];  /* count */
2048        LO_data[4] = sense[29]; /* seek_addr.cyl */
2049        LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */
2050        LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */
2051
2052        memcpy (&(LO_data[8]), &(sense[11]), 8);
2053
2054        /* create DE ccw */
2055        ccw = erp->cpaddr;
2056	memset (ccw, 0, sizeof (ccw1_t));
2057	ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
2058	ccw->flags    = CCW_FLAG_CC;
2059	ccw->count    = 16;
2060	if (dasd_set_normalized_cda (ccw,
2061                                     __pa (DE_data), erp, device)) {
2062                dasd_free_request (erp, device);
2063                DASD_MESSAGE (KERN_ERR, device, "%s",
2064                              "Unable to allocate ERP");
2065
2066                return dasd_3990_erp_cleanup (default_erp,
2067                                              CQR_STATUS_FAILED);
2068        }
2069
2070        /* create LO ccw */
2071        ccw++;
2072	memset (ccw, 0, sizeof (ccw1_t));
2073	ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
2074	ccw->flags    = CCW_FLAG_CC;
2075	ccw->count    = 16;
2076	if (dasd_set_normalized_cda (ccw,
2077                                     __pa (LO_data), erp, device)){
2078                dasd_free_request (erp, device);
2079                DASD_MESSAGE (KERN_ERR, device, "%s",
2080                              "Unable to allocate ERP");
2081
2082                return dasd_3990_erp_cleanup (default_erp,
2083                                              CQR_STATUS_FAILED);
2084        }
2085
2086        /* TIC to the failed ccw */
2087        ccw++;
2088	ccw->cmd_code = CCW_CMD_TIC;
2089	ccw->cda      = cpa;
2090
2091        /* fill erp related fields */
2092        erp->function = dasd_3990_erp_action_1B_32;
2093	erp->refers   = default_erp->refers;
2094	erp->device   = device;
2095	erp->magic    = default_erp->magic;
2096	erp->lpm      = 0xFF;
2097	erp->expires  = 0;
2098	erp->retries  = 256;
2099	erp->status   = CQR_STATUS_FILLED;
2100
2101        /* remove the default erp */
2102        dasd_free_request (default_erp, device);
2103
2104	return erp;
2105
2106} /* end dasd_3990_erp_action_1B_32 */
2107
2108/*
2109 * DASD_3990_UPDATE_1B
2110 *
2111 * DESCRIPTION
2112 *   Handles the update to the 32 byte 'Action 1B' of Single Program
2113 *   Action Codes in case the first action was not successful.
2114 *   The already created 'previous_erp' is the currently not successful
2115 *   ERP.
2116 *
2117 * PARAMETER
2118 *   previous_erp       already created previous erp.
2119 *   sense              current sense data
2120 * RETURN VALUES
2121 *   erp                modified erp
2122 */
2123ccw_req_t *
2124dasd_3990_update_1B (ccw_req_t *previous_erp,
2125                     char      *sense)
2126{
2127
2128	dasd_device_t  *device = previous_erp->device;
2129        __u32          cpa     = 0;
2130        ccw_req_t      *cqr;
2131	ccw_req_t      *erp;
2132	char           *LO_data;   /* LO_eckd_data_t */
2133        ccw1_t         *ccw;
2134
2135	DASD_MESSAGE (KERN_DEBUG, device, "%s",
2136                      "Write not finished because of unexpected condition"
2137                      " - follow on");
2138
2139        /* determine the original cqr */
2140        cqr = previous_erp;
2141
2142        while (cqr->refers != NULL){
2143                cqr = cqr->refers;
2144        }
2145
2146        /* for imprecise ending just do default erp */
2147        if (sense[1] & 0x01) {
2148
2149                DASD_MESSAGE (KERN_DEBUG, device, "%s",
2150                              "Imprecise ending is set - just retry");
2151
2152                check_then_set (&previous_erp->status,
2153                                CQR_STATUS_ERROR,
2154                                CQR_STATUS_QUEUED);
2155
2156                return previous_erp;
2157        }
2158
2159        /* determine the address of the CCW to be restarted */
2160        /* Imprecise ending is not set -> addr from IRB-SCSW */
2161        cpa = previous_erp->dstat->cpa;
2162
2163        if (cpa == 0) {
2164
2165                DASD_MESSAGE (KERN_DEBUG, device, "%s",
2166                              "Unable to determine address of the CCW "
2167                              "to be restarted");
2168
2169                check_then_set (&previous_erp->status,
2170                                CQR_STATUS_ERROR,
2171                                CQR_STATUS_FAILED);
2172
2173                return previous_erp;
2174        }
2175
2176        erp = previous_erp;
2177
2178	/* update the LO with the new returned sense data  */
2179	LO_data = erp->data + sizeof (DE_eckd_data_t);
2180
2181        if ((sense[3]  == 0x01) &&
2182            (LO_data[1] & 0x01)   ){
2183
2184                DASD_MESSAGE (KERN_ERR, device, "%s",
2185                              "BUG - this should not happen");
2186
2187                check_then_set (&previous_erp->status,
2188                                CQR_STATUS_ERROR,
2189                                CQR_STATUS_FAILED);
2190
2191                return previous_erp;
2192        }
2193
2194        if ((sense[7] & 0x3F) == 0x01) {
2195                /* operation code is WRITE DATA -> data area orientation */
2196                LO_data[0] = 0x81;
2197
2198        } else if ((sense[7] & 0x3F) == 0x03) {
2199                /* operation code is FORMAT WRITE -> index orientation */
2200                LO_data[0] = 0xC3;
2201
2202        } else {
2203                LO_data[0] = sense[7];  /* operation */
2204        }
2205
2206        LO_data[1] = sense[8];  /* auxiliary */
2207        LO_data[2] = sense[9];
2208        LO_data[3] = sense[3];  /* count */
2209        LO_data[4] = sense[29]; /* seek_addr.cyl */
2210        LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */
2211        LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */
2212
2213        memcpy (&(LO_data[8]), &(sense[11]), 8);
2214
2215        /* TIC to the failed ccw */
2216        ccw = erp->cpaddr;  /* addr of DE ccw */
2217        ccw++;              /* addr of LE ccw */
2218        ccw++;              /* addr of TIC ccw */
2219	ccw->cda = cpa;
2220
2221	check_then_set (&erp->status,
2222                        CQR_STATUS_ERROR,
2223                        CQR_STATUS_QUEUED);
2224
2225	return erp;
2226
2227} /* end dasd_3990_update_1B */
2228
2229/*
2230 * DASD_3990_ERP_COMPOUND_RETRY
2231 *
2232 * DESCRIPTION
2233 *   Handles the compound ERP action retry code.
2234 *   NOTE: At least one retry is done even if zero is specified
2235 *         by the sense data. This makes enqueueing of the request
2236 *         easier.
2237 *
2238 * PARAMETER
2239 *   sense              sense data of the actual error
2240 *   erp                pointer to the currently created ERP
2241 *
2242 * RETURN VALUES
2243 *   erp                modified ERP pointer
2244 *
2245 */
2246void
2247dasd_3990_erp_compound_retry (ccw_req_t *erp,
2248                              char      *sense)
2249{
2250
2251        switch (sense[25] & 0x03) {
2252        case 0x00:	/* no not retry */
2253                erp->retries = 1;
2254                break;
2255
2256        case 0x01:	/* retry 2 times */
2257                erp->retries = 2;
2258                break;
2259
2260        case 0x02:	/* retry 10 times */
2261                erp->retries = 10;
2262                break;
2263
2264        case 0x03:	/* retry 256 times */
2265                erp->retries = 256;
2266                break;
2267
2268        default:
2269                BUG();
2270        }
2271
2272        erp->function = dasd_3990_erp_compound_retry;
2273
2274} /* end dasd_3990_erp_compound_retry */
2275
2276/*
2277 * DASD_3990_ERP_COMPOUND_PATH
2278 *
2279 * DESCRIPTION
2280 *   Handles the compound ERP action for retry on alternate
2281 *   channel path.
2282 *
2283 * PARAMETER
2284 *   sense              sense data of the actual error
2285 *   erp                pointer to the currently created ERP
2286 *
2287 * RETURN VALUES
2288 *   erp                modified ERP pointer
2289 *
2290 */
2291void
2292dasd_3990_erp_compound_path (ccw_req_t *erp,
2293                             char      *sense)
2294{
2295
2296        if (sense[25] & DASD_SENSE_BIT_3) {
2297                dasd_3990_erp_alternate_path (erp);
2298
2299                if (erp->status == CQR_STATUS_FAILED) {
2300                        /* reset the lpm and the status to be able to
2301                         * try further actions. */
2302
2303                        erp->lpm = LPM_ANYPATH;
2304
2305                        check_then_set (&erp->status,
2306                                        CQR_STATUS_FAILED,
2307                                        CQR_STATUS_ERROR);
2308
2309                }
2310        }
2311
2312        erp->function = dasd_3990_erp_compound_path;
2313
2314} /* end dasd_3990_erp_compound_path */
2315
2316/*
2317 * DASD_3990_ERP_COMPOUND_CODE
2318 *
2319 * DESCRIPTION
2320 *   Handles the compound ERP action for retry code.
2321 *
2322 * PARAMETER
2323 *   sense              sense data of the actual error
2324 *   erp                pointer to the currently created ERP
2325 *
2326 * RETURN VALUES
2327 *   erp                NEW ERP pointer
2328 *
2329 */
2330ccw_req_t *
2331dasd_3990_erp_compound_code (ccw_req_t *erp,
2332                             char      *sense)
2333{
2334
2335        if (sense[25] & DASD_SENSE_BIT_2) {
2336
2337                switch (sense[28]) {
2338                case 0x17:
2339                        /* issue a Diagnostic Control command with an
2340                         * Inhibit Write subcommand and controler modifier */
2341                        erp = dasd_3990_erp_DCTL (erp,
2342                                                  0x20);
2343                        break;
2344
2345                case 0x25:
2346                        /* wait for 5 seconds and retry again */
2347                        erp->retries = 1;
2348
2349                        dasd_3990_erp_block_queue (erp,
2350                                                   5);
2351                        break;
2352
2353                default:
2354                        /* should not happen - continue */
2355
2356                }
2357        }
2358
2359        erp->function = dasd_3990_erp_compound_code;
2360
2361        return erp;
2362
2363} /* end dasd_3990_erp_compound_code */
2364
2365/*
2366 * DASD_3990_ERP_COMPOUND_CONFIG
2367 *
2368 * DESCRIPTION
2369 *   Handles the compound ERP action for configruation
2370 *   dependent error.
2371 *   Note: duplex handling is not implemented (yet).
2372 *
2373 * PARAMETER
2374 *   sense              sense data of the actual error
2375 *   erp                pointer to the currently created ERP
2376 *
2377 * RETURN VALUES
2378 *   erp                modified ERP pointer
2379 *
2380 */
2381void
2382dasd_3990_erp_compound_config (ccw_req_t *erp,
2383                               char      *sense)
2384{
2385
2386        if ((sense[25] & DASD_SENSE_BIT_1) &&
2387            (sense[26] & DASD_SENSE_BIT_2)   ) {
2388
2389                /* set to suspended duplex state then restart */
2390                dasd_device_t *device  = erp->device;
2391
2392                DASD_MESSAGE (KERN_ERR, device, "%s",
2393                              "Set device to suspended duplex state should be "
2394                              "done!\n"
2395                              "This is not implemented yet (for compound ERP)"
2396                              " - please report to linux390@de.ibm.com");
2397
2398        }
2399
2400        erp->function = dasd_3990_erp_compound_config;
2401
2402} /* end dasd_3990_erp_compound_config */
2403
2404/*
2405 * DASD_3990_ERP_COMPOUND
2406 *
2407 * DESCRIPTION
2408 *   Does the further compound program action if
2409 *   compound retry was not successful.
2410 *
2411 * PARAMETER
2412 *   sense              sense data of the actual error
2413 *   erp                pointer to the current (failed) ERP
2414 *
2415 * RETURN VALUES
2416 *   erp                (additional) ERP pointer
2417 *
2418 */
2419ccw_req_t *
2420dasd_3990_erp_compound (ccw_req_t *erp,
2421                        char      *sense)
2422{
2423
2424        if ((erp->function == dasd_3990_erp_compound_retry) &&
2425            (erp->status   == CQR_STATUS_ERROR            )   ) {
2426
2427                dasd_3990_erp_compound_path (erp,
2428                                             sense);
2429        }
2430
2431        if ((erp->function == dasd_3990_erp_compound_path) &&
2432            (erp->status   == CQR_STATUS_ERROR           )    ){
2433
2434                erp = dasd_3990_erp_compound_code (erp,
2435                                                   sense);
2436        }
2437
2438        if ((erp->function == dasd_3990_erp_compound_code) &&
2439            (erp->status   == CQR_STATUS_ERROR           )   ) {
2440
2441                dasd_3990_erp_compound_config (erp,
2442                                               sense);
2443        }
2444
2445        /* if no compound action ERP specified, the request failed */
2446        if (erp->status == CQR_STATUS_ERROR) {
2447
2448                check_then_set (&erp->status,
2449                                CQR_STATUS_ERROR,
2450                                CQR_STATUS_FAILED);
2451        }
2452
2453        return erp;
2454
2455} /* end dasd_3990_erp_compound */
2456
2457/*
2458 * DASD_3990_ERP_INSPECT_32
2459 *
2460 * DESCRIPTION
2461 *   Does a detailed inspection of the 32 byte sense data
2462 *   and sets up a related error recovery action.
2463 *
2464 * PARAMETER
2465 *   sense              sense data of the actual error
2466 *   erp                pointer to the currently created default ERP
2467 *
2468 * RETURN VALUES
2469 *   erp_filled         pointer to the ERP
2470 *
2471 */
2472ccw_req_t *
2473dasd_3990_erp_inspect_32 ( ccw_req_t *erp,
2474                           char      *sense )
2475{
2476
2477	dasd_device_t *device = erp->device;
2478
2479	erp->function = dasd_3990_erp_inspect_32;
2480
2481	if (sense[25] & DASD_SENSE_BIT_0) {
2482
2483		/* compound program action codes (byte25 bit 0 == '1') */
2484                dasd_3990_erp_compound_retry (erp,
2485                                              sense);
2486
2487	} else {
2488
2489		/* single program action codes (byte25 bit 0 == '0') */
2490		switch (sense[25]) {
2491
2492		case 0x00:	/* success */
2493                        DASD_MESSAGE (KERN_DEBUG, device,
2494                                      "ERP called for successful request %p"
2495                                      " - NO ERP necessary",
2496                                      erp);
2497
2498                        erp = dasd_3990_erp_cleanup (erp,
2499                                                     CQR_STATUS_DONE);
2500
2501                        break;
2502
2503		case 0x01:	/* fatal error */
2504                        DASD_MESSAGE (KERN_ERR, device, "%s",
2505                                      "Fatal error should have been "
2506                                      "handled within the interrupt handler");
2507
2508                        erp = dasd_3990_erp_cleanup (erp,
2509                                                     CQR_STATUS_FAILED);
2510                        break;
2511
2512		case 0x02:	/* intervention required */
2513		case 0x03:	/* intervention required during dual copy */
2514                        erp = dasd_3990_erp_int_req (erp);
2515                        break;
2516
2517		case 0x0F:	/* length mismatch during update write command */
2518                        DASD_MESSAGE (KERN_ERR, device, "%s",
2519                                      "update write command error - should not "
2520                                      "happen;\n"
2521                                      "Please send this message together with "
2522                                      "the above sense data to linux390@de."
2523                                      "ibm.com");
2524
2525                        erp = dasd_3990_erp_cleanup (erp,
2526                                                     CQR_STATUS_FAILED);
2527                        break;
2528
2529		case 0x10:	/* logging required for other channel program */
2530                        erp = dasd_3990_erp_action_10_32 (erp,
2531                                                    sense);
2532                        break;
2533
2534		case 0x15:	/* next track outside defined extend */
2535                        DASD_MESSAGE (KERN_ERR, device, "%s",
2536                                      "next track outside defined extend - "
2537                                      "should not happen;\n"
2538                                      "Please send this message together with "
2539                                      "the above sense data to linux390@de."
2540                                      "ibm.com");
2541
2542                        erp= dasd_3990_erp_cleanup (erp,
2543                                                    CQR_STATUS_FAILED);
2544                        break;
2545
2546		case 0x1B:	/* unexpected condition during write */
2547
2548                        erp = dasd_3990_erp_action_1B_32 (erp,
2549                                                          sense);
2550                        break;
2551
2552		case 0x1C:	/* invalid data */
2553                        DASD_MESSAGE (KERN_EMERG, device, "%s",
2554                                      "Data recovered during retry with PCI "
2555                                      "fetch mode active");
2556
2557                        /* not possible to handle this situation in Linux */
2558                        panic("Invalid data - No way to inform appliction about "
2559                              "the possibly incorret data");
2560			break;
2561
2562		case 0x1D:	/* state-change pending */
2563                        DASD_MESSAGE (KERN_DEBUG, device, "%s",
2564                                      "A State change pending condition exists "
2565                                      "for the subsystem or device");
2566
2567                        erp = dasd_3990_erp_action_4 (erp,
2568                                                      sense);
2569			break;
2570
2571		default:	/* all others errors - default erp  */
2572
2573		}
2574	}
2575
2576	return erp;
2577
2578} /* end dasd_3990_erp_inspect_32 */
2579
2580/*
2581 *****************************************************************************
2582 * main ERP control fuctions (24 and 32 byte sense)
2583 *****************************************************************************
2584 */
2585
2586/*
2587 * DASD_3990_ERP_INSPECT
2588 *
2589 * DESCRIPTION
2590 *   Does a detailed inspection for sense data by calling either
2591 *   the 24-byte or the 32-byte inspection routine.
2592 *
2593 * PARAMETER
2594 *   erp                pointer to the currently created default ERP
2595 * RETURN VALUES
2596 *   erp_new            contens was possibly modified
2597 */
2598ccw_req_t *
2599dasd_3990_erp_inspect (ccw_req_t *erp)
2600{
2601
2602	ccw_req_t *erp_new = NULL;
2603	/* sense data are located in the refers record of the */
2604	/* already set up new ERP !                           */
2605	char *sense = erp->refers->dstat->ii.sense.data;
2606
2607	/* distinguish between 24 and 32 byte sense data */
2608	if (sense[27] & DASD_SENSE_BIT_0) {
2609
2610		/* inspect the 24 byte sense data */
2611		erp_new = dasd_3990_erp_inspect_24 (erp,
2612                                                    sense);
2613
2614	} else {
2615
2616		/* inspect the 32 byte sense data */
2617		erp_new = dasd_3990_erp_inspect_32 (erp,
2618                                                    sense);
2619
2620	} /* end distinguish between 24 and 32 byte sense data */
2621
2622	return erp_new;
2623
2624} /* END dasd_3990_erp_inspect */
2625
2626/*
2627 * DASD_3990_ERP_ADD_ERP
2628 *
2629 * DESCRIPTION
2630 *   This funtion adds an additional request block (ERP) to the head of
2631 *   the given cqr (or erp).
2632 *   This erp is initialized as an default erp (retry TIC)
2633 *
2634 * PARAMETER
2635 *   cqr                head of the current ERP-chain (or single cqr if
2636 *                      first error)
2637 * RETURN VALUES
2638 *   erp                pointer to new ERP-chain head
2639 */
2640ccw_req_t *
2641dasd_3990_erp_add_erp (ccw_req_t *cqr)
2642{
2643
2644	dasd_device_t *device = cqr->device;
2645
2646	/* allocate additional request block */
2647	ccw_req_t *erp = dasd_alloc_request ((char *) &cqr->magic, 1, 0, cqr->device);
2648
2649	if (!erp) {
2650
2651                DASD_MESSAGE (KERN_ERR, device, "%s",
2652                              "Unable to allocate ERP request");
2653
2654                check_then_set (&cqr->status,
2655                                CQR_STATUS_ERROR,
2656                                CQR_STATUS_FAILED);
2657
2658                return cqr;
2659	}
2660
2661	/* initialize request with default TIC to current ERP/CQR */
2662	erp->cpaddr->cmd_code = CCW_CMD_TIC;
2663	erp->cpaddr->cda      = (long)(cqr->cpaddr);
2664	erp->function = dasd_3990_erp_add_erp;
2665	erp->refers   = cqr;
2666	erp->device   = cqr->device;
2667	erp->magic    = cqr->magic;
2668	erp->lpm      = 0xFF;
2669	erp->expires  = 0;
2670	erp->retries  = 256;
2671
2672	erp->status = CQR_STATUS_FILLED;
2673
2674	return erp;
2675}
2676
2677/*
2678 * DASD_3990_ERP_ADDITIONAL_ERP
2679 *
2680 * DESCRIPTION
2681 *   An additional ERP is needed to handle the current error.
2682 *   Add ERP to the head of the ERP-chain containing the ERP processing
2683 *   determined based on the sense data.
2684 *
2685 * PARAMETER
2686 *   cqr                head of the current ERP-chain (or single cqr if
2687 *                      first error)
2688 *
2689 * RETURN VALUES
2690 *   erp                pointer to new ERP-chain head
2691 */
2692ccw_req_t *
2693dasd_3990_erp_additional_erp (ccw_req_t *cqr)
2694{
2695
2696	ccw_req_t *erp = NULL;
2697
2698	/* add erp and initialize with default TIC */
2699	erp = dasd_3990_erp_add_erp (cqr);
2700
2701	/* inspect sense, determine specific ERP if possible */
2702        if (erp != cqr) {
2703
2704                erp = dasd_3990_erp_inspect (erp);
2705        }
2706
2707	return erp;
2708
2709} /* end dasd_3990_erp_additional_erp */
2710
2711/*
2712 * DASD_3990_ERP_ERROR_MATCH
2713 *
2714 * DESCRIPTION
2715 *   check if the the device status of the given cqr is the same.
2716 *   This means that the failed CCW and the relevant sense data
2717 *   must match.
2718 *   I don't distinguish between 24 and 32 byte sense becaus in case of
2719 *   24 byte sense byte 25 and 27 is set as well.
2720 *
2721 * PARAMETER
2722 *   cqr1               first cqr, which will be compared with the
2723 *   cqr2               second cqr.
2724 *
2725 * RETURN VALUES
2726 *   match              'boolean' for match found
2727 *                      returns 1 if match found, otherwise 0.
2728 */
2729int
2730dasd_3990_erp_error_match (ccw_req_t *cqr1,
2731			   ccw_req_t *cqr2)
2732{
2733
2734	/* check failed CCW */
2735	if (cqr1->dstat->cpa !=
2736	    cqr2->dstat->cpa) {
2737	//	return 0;	/* CCW doesn't match */
2738	}
2739
2740	/* check sense data; byte 0-2,25,27 */
2741	if (!((strncmp (cqr1->dstat->ii.sense.data,
2742			cqr2->dstat->ii.sense.data,
2743			3) == 0) &&
2744	      (cqr1->dstat->ii.sense.data[27] ==
2745	       cqr2->dstat->ii.sense.data[27]   ) &&
2746	      (cqr1->dstat->ii.sense.data[25] ==
2747	       cqr2->dstat->ii.sense.data[25]   )   )) {
2748
2749		return 0;	/* sense doesn't match */
2750	}
2751
2752	return 1;		/* match */
2753
2754} /* end dasd_3990_erp_error_match */
2755
2756/*
2757 * DASD_3990_ERP_IN_ERP
2758 *
2759 * DESCRIPTION
2760 *   check if the current error already happened before.
2761 *   quick exit if current cqr is not an ERP (cqr->refers=NULL)
2762 *
2763 * PARAMETER
2764 *   cqr                failed cqr (either original cqr or already an erp)
2765 *
2766 * RETURN VALUES
2767 *   erp                erp-pointer to the already defined error
2768 *                      recovery procedure OR
2769 *                      NULL if a 'new' error occurred.
2770 */
2771ccw_req_t *
2772dasd_3990_erp_in_erp (ccw_req_t *cqr)
2773{
2774
2775	ccw_req_t *erp_head  = cqr,	/* save erp chain head */
2776                  *erp_match = NULL;	/* save erp chain head */
2777	int match = 0;		/* 'boolean' for matching error found */
2778
2779	if (cqr->refers == NULL) {	/* return if not in erp */
2780		return NULL;
2781	}
2782
2783	/* check the erp/cqr chain for current error */
2784	do {
2785		match = dasd_3990_erp_error_match (erp_head,
2786						   cqr->refers);
2787		erp_match = cqr;	 /* save possible matching erp  */
2788		cqr       = cqr->refers; /* check next erp/cqr in queue */
2789
2790	} while ((cqr->refers != NULL) &&
2791		 (!match             )   );
2792
2793	if (!match) {
2794		return NULL; 	/* no match was found */
2795	}
2796
2797        return erp_match;	/* return address of matching erp */
2798
2799} /* END dasd_3990_erp_in_erp */
2800
2801/*
2802 * DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense)
2803 *
2804 * DESCRIPTION
2805 *   No retry is left for the current ERP. Check what has to be done
2806 *   with the ERP.
2807 *     - do further defined ERP action or
2808 *     - wait for interrupt or
2809 *     - exit with permanent error
2810 *
2811 * PARAMETER
2812 *   erp                ERP which is in progress wiht no retry left
2813 *
2814 * RETURN VALUES
2815 *   erp                modified/additional ERP
2816 */
2817ccw_req_t *
2818dasd_3990_erp_further_erp (ccw_req_t *erp)
2819{
2820
2821        dasd_device_t *device = erp->device;
2822        char          *sense  = erp->dstat->ii.sense.data;
2823
2824        /* check for 24 byte sense ERP */
2825	if ((erp->function == dasd_3990_erp_bus_out ) ||
2826            (erp->function == dasd_3990_erp_action_1) ||
2827            (erp->function == dasd_3990_erp_action_4)   ){
2828
2829                erp = dasd_3990_erp_action_1 (erp);
2830
2831	} else if (erp->function == dasd_3990_erp_action_5) {
2832
2833                /* retries have not been successful */
2834                /* prepare erp for retry on different channel path */
2835                erp = dasd_3990_erp_action_1 (erp);
2836
2837                if (!(sense[ 2] & DASD_SENSE_BIT_0)) {
2838
2839                        /* issue a Diagnostic Control command with an
2840                         * Inhibit Write subcommand */
2841
2842                        switch (sense[25]) {
2843                        case 0x17:
2844                        case 0x57: { /* controller */
2845                                erp = dasd_3990_erp_DCTL (erp,
2846                                                          0x20);
2847                                break;
2848                        }
2849                        case 0x18:
2850                        case 0x58: { /* channel path */
2851                                erp = dasd_3990_erp_DCTL (erp,
2852                                                          0x40);
2853                                break;
2854                        }
2855                        case 0x19:
2856                        case 0x59: { /* storage director */
2857                                erp = dasd_3990_erp_DCTL (erp,
2858                                                          0x80);
2859                                break;
2860                        }
2861                        default:
2862                                DASD_MESSAGE (KERN_DEBUG, device,
2863                                              "invalid subcommand modifier 0x%x "
2864                                              "for Diagnostic Control Command",
2865                                              sense[25]);
2866                        }
2867                }
2868
2869        /* check for 32 byte sense ERP */
2870	} else if ((erp->function == dasd_3990_erp_compound_retry ) ||
2871                   (erp->function == dasd_3990_erp_compound_path  ) ||
2872                   (erp->function == dasd_3990_erp_compound_code  ) ||
2873                   (erp->function == dasd_3990_erp_compound_config)   ) {
2874
2875                erp = dasd_3990_erp_compound (erp,
2876                                              sense);
2877
2878	} else {
2879                /* no retry left and no additional special handling necessary */
2880                DASD_MESSAGE (KERN_ERR, device,
2881                              "no retries left for erp %p - "
2882                              "set status to FAILED",
2883                              erp);
2884
2885		check_then_set (&erp->status,
2886                                CQR_STATUS_ERROR,
2887                                CQR_STATUS_FAILED);
2888	}
2889
2890	return erp;
2891
2892} /* end dasd_3990_erp_further_erp */
2893
2894/*
2895 * DASD_3990_ERP_HANDLE_MATCH_ERP
2896 *
2897 * DESCRIPTION
2898 *   An error occurred again and an ERP has been detected which is already
2899 *   used to handle this error (e.g. retries).
2900 *   All prior ERP's are asumed to be successful and therefore removed
2901 *   from queue.
2902 *   If retry counter of matching erp is already 0, it is checked if further
2903 *   action is needed (besides retry) or if the ERP has failed.
2904 *
2905 * PARAMETER
2906 *   erp_head           first ERP in ERP-chain
2907 *   erp                ERP that handles the actual error.
2908 *                      (matching erp)
2909 *
2910 * RETURN VALUES
2911 *   erp                modified/additional ERP
2912 */
2913ccw_req_t *
2914dasd_3990_erp_handle_match_erp (ccw_req_t *erp_head,
2915				ccw_req_t *erp)
2916{
2917
2918	dasd_device_t *device   = erp_head->device;
2919	ccw_req_t     *erp_done = erp_head;  /* finished req */
2920        ccw_req_t     *erp_free = NULL;      /* req to be freed */
2921
2922	/* loop over successful ERPs and remove them from chanq */
2923	while (erp_done != erp) {
2924
2925                if (erp_done == NULL) 	/* end of chain reached */
2926                        panic (PRINTK_HEADER "Programming error in ERP! The "
2927                               "original request was lost\n");
2928
2929		/* remove the request from the device queue */
2930		dasd_chanq_deq (&device->queue,
2931				erp_done);
2932
2933                erp_free = erp_done;
2934		erp_done = erp_done->refers;
2935
2936		/* free the finished erp request */
2937		dasd_free_request (erp_free, erp_free->device);
2938
2939	} /* end while */
2940
2941        if (erp->retries > 0) {
2942
2943                char *sense = erp->dstat->ii.sense.data;
2944
2945                /* check for special retries */
2946                if (erp->function == dasd_3990_erp_action_4) {
2947
2948                        erp = dasd_3990_erp_action_4 (erp,
2949                                                      sense);
2950
2951                } else if (erp->function == dasd_3990_erp_action_1B_32) {
2952
2953                        erp = dasd_3990_update_1B (erp,
2954                                                   sense);
2955
2956                } else if (erp->function == dasd_3990_erp_int_req) {
2957
2958                        erp = dasd_3990_erp_int_req (erp);
2959
2960                } else {
2961                        /* simple retry   */
2962                        DASD_MESSAGE (KERN_DEBUG, device,
2963                                      "%i retries left for erp %p",
2964                                      erp->retries,
2965                                      erp);
2966
2967                        /* handle the request again... */
2968                        check_then_set (&erp->status,
2969                                        CQR_STATUS_ERROR,
2970                                        CQR_STATUS_QUEUED);
2971                }
2972
2973        } else {
2974                /* no retry left - check for further necessary action    */
2975                /* if no further actions, handle rest as permanent error */
2976                erp = dasd_3990_erp_further_erp (erp);
2977	}
2978
2979        return erp;
2980
2981} /* end dasd_3990_erp_handle_match_erp */
2982
2983/*
2984 * DASD_3990_ERP_ACTION
2985 *
2986 * DESCRIPTION
2987 *   controll routine for 3990 erp actions.
2988 *   Has to be called with the queue lock (namely the s390_irq_lock) acquired.
2989 *
2990 * PARAMETER
2991 *   cqr                failed cqr (either original cqr or already an erp)
2992 *
2993 * RETURN VALUES
2994 *   erp                erp-pointer to the head of the ERP action chain.
2995 *                      This means:
2996 *                       - either a ptr to an additional ERP cqr or
2997 *                       - the original given cqr (which's status might
2998 *                         be modified)
2999 */
3000ccw_req_t *
3001dasd_3990_erp_action (ccw_req_t *cqr)
3002{
3003
3004	ccw_req_t     *erp    = NULL;
3005	dasd_device_t *device = cqr->device;
3006        __u32         cpa     = cqr->dstat->cpa;
3007
3008#ifdef ERP_DEBUG
3009        DASD_MESSAGE (KERN_DEBUG, device,
3010                      "entering 3990 ERP for "
3011                      "0x%04X on sch %d = /dev/%s ",
3012                      device->devinfo.devno,
3013                      device->devinfo.irq,
3014                      device->name);
3015
3016	/* print current erp_chain */
3017        DASD_MESSAGE (KERN_DEBUG, device, "%s",
3018                      "ERP chain at BEGINNING of ERP-ACTION");
3019        {
3020                ccw_req_t *temp_erp = NULL;
3021                for (temp_erp = cqr;
3022                     temp_erp != NULL;
3023                     temp_erp = temp_erp->refers){
3024
3025                        DASD_MESSAGE (KERN_DEBUG, device,
3026                                      "      erp %p refers to %p",
3027                                      temp_erp,
3028                                      temp_erp->refers);
3029                }
3030        }
3031#endif /* ERP_DEBUG */
3032
3033	/* double-check if current erp/cqr was successfull */
3034	if ((cqr->dstat->cstat == 0x00                                 ) &&
3035	    (cqr->dstat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))   ) {
3036
3037                DASD_MESSAGE (KERN_DEBUG, device,
3038                              "ERP called for successful request %p"
3039                              " - NO ERP necessary",
3040                              cqr);
3041
3042                check_then_set (&cqr->status,
3043                                CQR_STATUS_ERROR,
3044                                CQR_STATUS_DONE);
3045
3046		return cqr;
3047	}
3048	/* check if sense data are available */
3049	if (!cqr->dstat->ii.sense.data) {
3050		DASD_MESSAGE (KERN_DEBUG, device,
3051			"ERP called witout sense data avail ..."
3052			"request %p - NO ERP possible",
3053			cqr);
3054
3055                check_then_set (&cqr->status,
3056                                CQR_STATUS_ERROR,
3057                                CQR_STATUS_FAILED);
3058
3059		return cqr;
3060
3061	}
3062
3063	/* check if error happened before */
3064	erp = dasd_3990_erp_in_erp (cqr);
3065
3066	if (erp == NULL) {
3067		/* no matching erp found - set up erp */
3068		erp = dasd_3990_erp_additional_erp (cqr);
3069	} else {
3070		/* matching erp found - set all leading erp's to DONE */
3071		erp = dasd_3990_erp_handle_match_erp (cqr,
3072                                                      erp);
3073	}
3074
3075#ifdef ERP_DEBUG
3076	/* print current erp_chain */
3077        DASD_MESSAGE (KERN_DEBUG, device, "%s",
3078                      "ERP chain at END of ERP-ACTION");
3079        {
3080                ccw_req_t *temp_erp = NULL;
3081                for (temp_erp = erp;
3082                     temp_erp != NULL;
3083                     temp_erp = temp_erp->refers) {
3084
3085                        DASD_MESSAGE (KERN_DEBUG, device,
3086                                      "      erp %p refers to %p",
3087                                      temp_erp,
3088                                      temp_erp->refers);
3089                }
3090        }
3091#endif /* ERP_DEBUG */
3092
3093        if (erp->status == CQR_STATUS_FAILED) {
3094
3095                log_erp_chain (erp,
3096                               1,
3097                               cpa);
3098        }
3099
3100        /* enqueue added ERP request */
3101        if ((erp != cqr                      ) &&
3102            (erp->status == CQR_STATUS_FILLED)   ){
3103
3104                dasd_chanq_enq_head (&device->queue,
3105                                     erp);
3106        } else {
3107                if ((erp->status == CQR_STATUS_FILLED )||
3108                    (erp != cqr                       )  ){
3109                        /* something strange happened - log the error and throw a BUG() */
3110                        DASD_MESSAGE (KERN_ERR, device, "%s",
3111                                      "Problems with ERP chain!!! BUG");
3112
3113                        /* print current erp_chain */
3114                        DASD_MESSAGE (KERN_DEBUG, device, "%s",
3115                                      "ERP chain at END of ERP-ACTION");
3116                        {
3117                                ccw_req_t *temp_erp = NULL;
3118                                for (temp_erp = erp;
3119                                     temp_erp != NULL;
3120                                     temp_erp = temp_erp->refers) {
3121
3122                                        DASD_MESSAGE (KERN_DEBUG, device,
3123                                                      "      erp %p (function %p) refers to %p",
3124                                                      temp_erp,
3125                                                      temp_erp->function,
3126                                                      temp_erp->refers);
3127                                }
3128                        }
3129                        BUG();
3130                }
3131
3132        }
3133
3134	return erp;
3135
3136} /* end dasd_3990_erp_action */
3137
3138/*
3139 * DASD_3990_ERP_POSTACTION
3140 *
3141 * DESCRIPTION
3142 *   Frees all ERPs of the current ERP Chain and set the status
3143 *   of the original CQR either to CQR_STATUS_DONE if ERP was successful
3144 *   or to CQR_STATUS_FAILED if ERP was NOT successful.
3145 *
3146 * PARAMETER
3147 *   erp                current erp_head
3148 *
3149 * RETURN VALUES
3150 *   cqr                pointer to the original CQR
3151 */
3152ccw_req_t *
3153dasd_3990_erp_postaction (ccw_req_t *erp)
3154{
3155
3156	ccw_req_t     *cqr      = NULL,
3157                      *free_erp = NULL;
3158	dasd_device_t *device   = erp->device;
3159	int           success;
3160
3161	if (erp->refers   == NULL ||
3162            erp->function == NULL   ) {
3163
3164		BUG ();
3165	}
3166
3167	if (erp->status == CQR_STATUS_DONE)
3168		success = 1;
3169	else
3170		success = 0;
3171
3172#ifdef ERP_DEBUG
3173
3174	/* print current erp_chain */
3175	printk (KERN_DEBUG PRINTK_HEADER
3176		"3990 ERP postaction called for erp chain:\n");
3177	{
3178		ccw_req_t *temp_erp = NULL;
3179
3180		for (temp_erp = erp;
3181                     temp_erp != NULL;
3182		     temp_erp = temp_erp->refers) {
3183
3184			printk (KERN_DEBUG PRINTK_HEADER
3185				"       erp %p refers to %p with erp function %p\n",
3186				temp_erp, temp_erp->refers, temp_erp->function);
3187		}
3188	}
3189
3190#endif /* ERP_DEBUG */
3191
3192	/* free all ERPs - but NOT the original cqr */
3193	while (erp->refers != NULL) {
3194
3195		free_erp = erp;
3196		erp      = erp->refers;
3197
3198		/* remove the request from the device queue */
3199		dasd_chanq_deq (&device->queue,
3200                                free_erp);
3201
3202		/* free the finished erp request */
3203		dasd_free_request (free_erp, free_erp->device);
3204	}
3205
3206	/* save ptr to original cqr */
3207	cqr = erp;
3208
3209	/* set corresponding status to original cqr */
3210	if (success) {
3211
3212		check_then_set (&cqr->status,
3213                                CQR_STATUS_ERROR,
3214				CQR_STATUS_DONE);
3215	} else {
3216
3217		check_then_set (&cqr->status,
3218				CQR_STATUS_ERROR,
3219                                CQR_STATUS_FAILED);
3220	}
3221
3222#ifdef ERP_DEBUG
3223	/* print current erp_chain */
3224	printk (KERN_DEBUG PRINTK_HEADER
3225		"3990 ERP postaction finished with remaining chain:\n");
3226	{
3227		ccw_req_t *temp_erp = NULL;
3228
3229		for (temp_erp = cqr;
3230                     temp_erp != NULL;
3231		     temp_erp = temp_erp->refers) {
3232
3233			printk (KERN_DEBUG PRINTK_HEADER
3234				" erp %p refers to %p \n", temp_erp,
3235				temp_erp->refers);
3236		}
3237	}
3238#endif /* ERP_DEBUG */
3239
3240	return cqr;
3241
3242} /* end dasd_3990_erp_postaction */
3243
3244/*
3245 * Overrides for Emacs so that we follow Linus's tabbing style.
3246 * Emacs will notice this stuff at the end of the file and automatically
3247 * adjust the settings for this buffer only.  This must remain at the end
3248 * of the file.
3249 * ---------------------------------------------------------------------------
3250 * Local variables:
3251 * c-indent-level: 4
3252 * c-brace-imaginary-offset: 0
3253 * c-brace-offset: -4
3254 * c-argdecl-indent: 4
3255 * c-label-offset: -4
3256 * c-continued-statement-offset: 4
3257 * c-continued-brace-offset: 0
3258 * indent-tabs-mode: nil
3259 * tab-width: 8
3260 * End:
3261 */
3262