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