Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / char / ftape / lowlevel / fdc-isr.c
1 /*
2  *      Copyright (C) 1994-1996 Bas Laarhoven,
3  *                (C) 1996-1997 Claus-Justus Heine.
4
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2, or (at your option)
8  any later version.
9
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14
15  You should have received a copy of the GNU General Public License
16  along with this program; see the file COPYING.  If not, write to
17  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18
19  *
20  * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.c,v $
21  * $Revision: 1.9 $
22  * $Date: 1997/10/17 23:01:53 $
23  *
24  *      This file contains the interrupt service routine and
25  *      associated code for the QIC-40/80/3010/3020 floppy-tape driver
26  *      "ftape" for Linux.
27  */
28
29 #include <asm/io.h>
30 #include <asm/dma.h>
31
32 #define volatile                /* */
33
34 #include <linux/ftape.h>
35 #include <linux/qic117.h>
36 #include "../lowlevel/ftape-tracing.h"
37 #include "../lowlevel/fdc-isr.h"
38 #include "../lowlevel/fdc-io.h"
39 #include "../lowlevel/ftape-ctl.h"
40 #include "../lowlevel/ftape-rw.h"
41 #include "../lowlevel/ftape-io.h"
42 #include "../lowlevel/ftape-calibr.h"
43 #include "../lowlevel/ftape-bsm.h"
44
45 /*      Global vars.
46  */
47 volatile int ft_expected_stray_interrupts;
48 volatile int ft_interrupt_seen;
49 volatile int ft_seek_completed;
50 volatile int ft_hide_interrupt;
51 /*      Local vars.
52  */
53 typedef enum {
54         no_error = 0, id_am_error = 0x01, id_crc_error = 0x02,
55         data_am_error = 0x04, data_crc_error = 0x08,
56         no_data_error = 0x10, overrun_error = 0x20,
57 } error_cause;
58 static int stop_read_ahead;
59
60
61 static void print_error_cause(int cause)
62 {
63         TRACE_FUN(ft_t_any);
64
65         switch (cause) {
66         case no_data_error:
67                 TRACE(ft_t_noise, "no data error");
68                 break;
69         case id_am_error:
70                 TRACE(ft_t_noise, "id am error");
71                 break;
72         case id_crc_error:
73                 TRACE(ft_t_noise, "id crc error");
74                 break;
75         case data_am_error:
76                 TRACE(ft_t_noise, "data am error");
77                 break;
78         case data_crc_error:
79                 TRACE(ft_t_noise, "data crc error");
80                 break;
81         case overrun_error:
82                 TRACE(ft_t_noise, "overrun error");
83                 break;
84         default:;
85         }
86         TRACE_EXIT;
87 }
88
89 static char *fdc_mode_txt(fdc_mode_enum mode)
90 {
91         switch (mode) {
92         case fdc_idle:
93                 return "fdc_idle";
94         case fdc_reading_data:
95                 return "fdc_reading_data";
96         case fdc_seeking:
97                 return "fdc_seeking";
98         case fdc_writing_data:
99                 return "fdc_writing_data";
100         case fdc_reading_id:
101                 return "fdc_reading_id";
102         case fdc_recalibrating:
103                 return "fdc_recalibrating";
104         case fdc_formatting:
105                 return "fdc_formatting";
106         case fdc_verifying:
107                 return "fdc_verifying";
108         default:
109                 return "unknown";
110         }
111 }
112
113 static inline error_cause decode_irq_cause(fdc_mode_enum mode, __u8 st[])
114 {
115         error_cause cause = no_error;
116         TRACE_FUN(ft_t_any);
117
118         /*  Valid st[], decode cause of interrupt.
119          */
120         switch (st[0] & ST0_INT_MASK) {
121         case FDC_INT_NORMAL:
122                 TRACE(ft_t_fdc_dma,"normal completion: %s",fdc_mode_txt(mode));
123                 break;
124         case FDC_INT_ABNORMAL:
125                 TRACE(ft_t_flow, "abnormal completion %s", fdc_mode_txt(mode));
126                 TRACE(ft_t_fdc_dma, "ST0: 0x%02x, ST1: 0x%02x, ST2: 0x%02x",
127                       st[0], st[1], st[2]);
128                 TRACE(ft_t_fdc_dma,
129                       "C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x",
130                       st[3], st[4], st[5], st[6]);
131                 if (st[1] & 0x01) {
132                         if (st[2] & 0x01) {
133                                 cause = data_am_error;
134                         } else {
135                                 cause = id_am_error;
136                         }
137                 } else if (st[1] & 0x20) {
138                         if (st[2] & 0x20) {
139                                 cause = data_crc_error;
140                         } else {
141                                 cause = id_crc_error;
142                         }
143                 } else if (st[1] & 0x04) {
144                         cause = no_data_error;
145                 } else if (st[1] & 0x10) {
146                         cause = overrun_error;
147                 }
148                 print_error_cause(cause);
149                 break;
150         case FDC_INT_INVALID:
151                 TRACE(ft_t_flow, "invalid completion %s", fdc_mode_txt(mode));
152                 break;
153         case FDC_INT_READYCH:
154                 if (st[0] & ST0_SEEK_END) {
155                         TRACE(ft_t_flow, "drive poll completed");
156                 } else {
157                         TRACE(ft_t_flow, "ready change %s",fdc_mode_txt(mode));
158                 }
159                 break;
160         default:
161                 break;
162         }
163         TRACE_EXIT cause;
164 }
165
166 static void update_history(error_cause cause)
167 {
168         switch (cause) {
169         case id_am_error:
170                 ft_history.id_am_errors++;
171                 break;
172         case id_crc_error:
173                 ft_history.id_crc_errors++;
174                 break;
175         case data_am_error:
176                 ft_history.data_am_errors++;
177                 break;
178         case data_crc_error:
179                 ft_history.data_crc_errors++;
180                 break;
181         case overrun_error:
182                 ft_history.overrun_errors++;
183                 break;
184         case no_data_error:
185                 ft_history.no_data_errors++;
186                 break;
187         default:;
188         }
189 }
190
191 static void skip_bad_sector(buffer_struct * buff)
192 {
193         TRACE_FUN(ft_t_any);
194
195         /*  Mark sector as soft error and skip it
196          */
197         if (buff->remaining > 0) {
198                 ++buff->sector_offset;
199                 ++buff->data_offset;
200                 --buff->remaining;
201                 buff->ptr += FT_SECTOR_SIZE;
202                 buff->bad_sector_map >>= 1;
203         } else {
204                 /*  Hey, what is this????????????? C code: if we shift 
205                  *  more than 31 bits, we get no shift. That's bad!!!!!!
206                  */
207                 ++buff->sector_offset;  /* hack for error maps */
208                 TRACE(ft_t_warn, "skipping last sector in segment");
209         }
210         TRACE_EXIT;
211 }
212
213 static void update_error_maps(buffer_struct * buff, unsigned int error_offset)
214 {
215         int hard = 0;
216         TRACE_FUN(ft_t_any);
217
218         if (buff->retry < FT_SOFT_RETRIES) {
219                 buff->soft_error_map |= (1 << error_offset);
220         } else {
221                 buff->hard_error_map |= (1 << error_offset);
222                 buff->soft_error_map &= ~buff->hard_error_map;
223                 buff->retry = -1;  /* will be set to 0 in setup_segment */
224                 hard = 1;
225         }
226         TRACE(ft_t_noise, "sector %d : %s error\n"
227               KERN_INFO "hard map: 0x%08lx\n"
228               KERN_INFO "soft map: 0x%08lx",
229               FT_SECTOR(error_offset), hard ? "hard" : "soft",
230               (long) buff->hard_error_map, (long) buff->soft_error_map);
231         TRACE_EXIT;
232 }
233
234 static void print_progress(buffer_struct *buff, error_cause cause)
235 {
236         TRACE_FUN(ft_t_any);
237
238         switch (cause) {
239         case no_error: 
240                 TRACE(ft_t_flow,"%d Sector(s) transferred", buff->sector_count);
241                 break;
242         case no_data_error:
243                 TRACE(ft_t_flow, "Sector %d not found",
244                       FT_SECTOR(buff->sector_offset));
245                 break;
246         case overrun_error:
247                 /*  got an overrun error on the first byte, must be a
248                  *  hardware problem
249                  */
250                 TRACE(ft_t_bug,
251                       "Unexpected error: failing DMA or FDC controller ?");
252                 break;
253         case data_crc_error:
254                 TRACE(ft_t_flow, "Error in sector %d",
255                       FT_SECTOR(buff->sector_offset - 1));
256                 break;
257         case id_crc_error:
258         case id_am_error:
259         case data_am_error:
260                 TRACE(ft_t_flow, "Error in sector %d",
261                       FT_SECTOR(buff->sector_offset));
262                 break;
263         default:
264                 TRACE(ft_t_flow, "Unexpected error at sector %d",
265                       FT_SECTOR(buff->sector_offset));
266                 break;
267         }
268         TRACE_EXIT;
269 }
270
271 /*
272  *  Error cause:   Amount xferred:  Action:
273  *
274  *  id_am_error         0           mark bad and skip
275  *  id_crc_error        0           mark bad and skip
276  *  data_am_error       0           mark bad and skip
277  *  data_crc_error    % 1024        mark bad and skip
278  *  no_data_error       0           retry on write
279  *                                  mark bad and skip on read
280  *  overrun_error  [ 0..all-1 ]     mark bad and skip
281  *  no_error           all          continue
282  */
283
284 /*  the arg `sector' is returned by the fdc and tells us at which sector we
285  *  are positioned at (relative to starting sector of segment)
286  */
287 static void determine_verify_progress(buffer_struct *buff,
288                                       error_cause cause,
289                                       __u8 sector)
290 {
291         TRACE_FUN(ft_t_any);
292
293         if (cause == no_error && sector == 1) {
294                 buff->sector_offset = FT_SECTORS_PER_SEGMENT;
295                 buff->remaining     = 0;
296                 if (TRACE_LEVEL >= ft_t_flow) {
297                         print_progress(buff, cause);
298                 }
299         } else {
300                 buff->sector_offset = sector - buff->sect;
301                 buff->remaining = FT_SECTORS_PER_SEGMENT - buff->sector_offset;
302                 TRACE(ft_t_noise, "%ssector offset: 0x%04x", 
303                       (cause == no_error) ? "unexpected " : "",
304                       buff->sector_offset);
305                 switch (cause) {
306                 case overrun_error:
307                         break;
308 #if 0
309                 case no_data_error:
310                         buff->retry = FT_SOFT_RETRIES;
311                         if (buff->hard_error_map    &&
312                             buff->sector_offset > 1 &&
313                             (buff->hard_error_map & 
314                              (1 << (buff->sector_offset-2)))) {
315                                 buff->retry --;
316                         }
317                         break;
318 #endif
319                 default:
320                         buff->retry = FT_SOFT_RETRIES;
321                         break;
322                 }
323                 if (TRACE_LEVEL >= ft_t_flow) {
324                         print_progress(buff, cause);
325                 }
326                 /*  Sector_offset points to the problem area Now adjust
327                  *  sector_offset so it always points one past he failing
328                  *  sector. I.e. skip the bad sector.
329                  */
330                 ++buff->sector_offset;
331                 --buff->remaining;
332                 update_error_maps(buff, buff->sector_offset - 1);
333         }
334         TRACE_EXIT;
335 }
336
337 static void determine_progress(buffer_struct *buff,
338                                error_cause cause,
339                                __u8 sector)
340 {
341         unsigned int dma_residue;
342         TRACE_FUN(ft_t_any);
343
344         /*  Using less preferred order of disable_dma and
345          *  get_dma_residue because this seems to fail on at least one
346          *  system if reversed!
347          */
348         dma_residue = get_dma_residue(fdc.dma);
349         disable_dma(fdc.dma);
350         if (cause != no_error || dma_residue != 0) {
351                 TRACE(ft_t_noise, "%sDMA residue: 0x%04x", 
352                       (cause == no_error) ? "unexpected " : "",
353                       dma_residue);
354                 /* adjust to actual value: */
355                 if (dma_residue == 0) {
356                         /* this happens sometimes with overrun errors.
357                          * I don't know whether we could ignore the
358                          * overrun error. Play save.
359                          */
360                         buff->sector_count --;
361                 } else {
362                         buff->sector_count -= ((dma_residue + 
363                                                 (FT_SECTOR_SIZE - 1)) /
364                                                FT_SECTOR_SIZE);
365                 }
366         }
367         /*  Update var's influenced by the DMA operation.
368          */
369         if (buff->sector_count > 0) {
370                 buff->sector_offset   += buff->sector_count;
371                 buff->data_offset     += buff->sector_count;
372                 buff->ptr             += (buff->sector_count *
373                                           FT_SECTOR_SIZE);
374                 buff->remaining       -= buff->sector_count;
375                 buff->bad_sector_map >>= buff->sector_count;
376         }
377         if (TRACE_LEVEL >= ft_t_flow) {
378                 print_progress(buff, cause);
379         }
380         if (cause != no_error) {
381                 if (buff->remaining == 0) {
382                         TRACE(ft_t_warn, "foo?\n"
383                               KERN_INFO "count : %d\n"
384                               KERN_INFO "offset: %d\n"
385                               KERN_INFO "soft  : %08x\n"
386                               KERN_INFO "hard  : %08x",
387                               buff->sector_count,
388                               buff->sector_offset,
389                               buff->soft_error_map,
390                               buff->hard_error_map);
391                 }
392                 /*  Sector_offset points to the problem area, except if we got
393                  *  a data_crc_error. In that case it points one past the
394                  *  failing sector.
395                  *
396                  *  Now adjust sector_offset so it always points one past he
397                  *  failing sector. I.e. skip the bad sector.  
398                  */
399                 if (cause != data_crc_error) {
400                         skip_bad_sector(buff);
401                 }
402                 update_error_maps(buff, buff->sector_offset - 1);
403         }
404         TRACE_EXIT;
405 }
406
407 static int calc_steps(int cmd)
408 {
409         if (ftape_current_cylinder > cmd) {
410                 return ftape_current_cylinder - cmd;
411         } else {
412                 return ftape_current_cylinder + cmd;
413         }
414 }
415
416 static void pause_tape(int retry, int mode)
417 {
418         int result;
419         __u8 out[3] = {FDC_SEEK, ft_drive_sel, 0};
420         TRACE_FUN(ft_t_any);
421
422         /*  We'll use a raw seek command to get the tape to rewind and
423          *  stop for a retry.
424          */
425         ++ft_history.rewinds;
426         if (qic117_cmds[ftape_current_command].non_intr) {
427                 TRACE(ft_t_warn, "motion command may be issued too soon");
428         }
429         if (retry && (mode == fdc_reading_data ||
430                       mode == fdc_reading_id   ||
431                       mode == fdc_verifying)) {
432                 ftape_current_command = QIC_MICRO_STEP_PAUSE;
433                 ftape_might_be_off_track = 1;
434         } else {
435                 ftape_current_command = QIC_PAUSE;
436         }
437         out[2] = calc_steps(ftape_current_command);
438         result = fdc_command(out, 3); /* issue QIC_117 command */
439         ftape_current_cylinder = out[ 2];
440         if (result < 0) {
441                 TRACE(ft_t_noise, "qic-pause failed, status = %d", result);
442         } else {
443                 ft_location.known  = 0;
444                 ft_runner_status   = idle;
445                 ft_hide_interrupt     = 1;
446                 ftape_tape_running = 0;
447         }
448         TRACE_EXIT;
449 }
450
451 static void continue_xfer(buffer_struct *buff,
452                           fdc_mode_enum mode, 
453                           unsigned int skip)
454 {
455         int write = 0;
456         TRACE_FUN(ft_t_any);
457
458         if (mode == fdc_writing_data || mode == fdc_deleting) {
459                 write = 1;
460         }
461         /*  This part can be removed if it never happens
462          */
463         if (skip > 0 &&
464             (ft_runner_status != running ||
465              (write && (buff->status != writing)) ||
466              (!write && (buff->status != reading && 
467                          buff->status != verifying)))) {
468                 TRACE(ft_t_err, "unexpected runner/buffer state %d/%d",
469                       ft_runner_status, buff->status);
470                 buff->status = error;
471                 /* finish this buffer: */
472                 (void)ftape_next_buffer(ft_queue_head);
473                 ft_runner_status = aborting;
474                 fdc_mode         = fdc_idle;
475         } else if (buff->remaining > 0 && ftape_calc_next_cluster(buff) > 0) {
476                 /*  still sectors left in current segment, continue
477                  *  with this segment
478                  */
479                 if (fdc_setup_read_write(buff, mode) < 0) {
480                         /* failed, abort operation
481                          */
482                         buff->bytes = buff->ptr - buff->address;
483                         buff->status = error;
484                         /* finish this buffer: */
485                         (void)ftape_next_buffer(ft_queue_head);
486                         ft_runner_status = aborting;
487                         fdc_mode         = fdc_idle;
488                 }
489         } else {
490                 /* current segment completed
491                  */
492                 unsigned int last_segment = buff->segment_id;
493                 int eot = ((last_segment + 1) % ft_segments_per_track) == 0;
494                 unsigned int next = buff->next_segment; /* 0 means stop ! */
495
496                 buff->bytes = buff->ptr - buff->address;
497                 buff->status = done;
498                 buff = ftape_next_buffer(ft_queue_head);
499                 if (eot) {
500                         /*  finished last segment on current track,
501                          *  can't continue
502                          */
503                         ft_runner_status = logical_eot;
504                         fdc_mode         = fdc_idle;
505                         TRACE_EXIT;
506                 }
507                 if (next <= 0) {
508                         /*  don't continue with next segment
509                          */
510                         TRACE(ft_t_noise, "no %s allowed, stopping tape",
511                               (write) ? "write next" : "read ahead");
512                         pause_tape(0, mode);
513                         ft_runner_status = idle;  /*  not quite true until
514                                                    *  next irq 
515                                                    */
516                         TRACE_EXIT;
517                 }
518                 /*  continue with next segment
519                  */
520                 if (buff->status != waiting) {
521                         TRACE(ft_t_noise, "all input buffers %s, pausing tape",
522                               (write) ? "empty" : "full");
523                         pause_tape(0, mode);
524                         ft_runner_status = idle;  /*  not quite true until
525                                                    *  next irq 
526                                                    */
527                         TRACE_EXIT;
528                 }
529                 if (write && next != buff->segment_id) {
530                         TRACE(ft_t_noise, 
531                               "segments out of order, aborting write");
532                         ft_runner_status = do_abort;
533                         fdc_mode         = fdc_idle;
534                         TRACE_EXIT;
535                 }
536                 ftape_setup_new_segment(buff, next, 0);
537                 if (stop_read_ahead) {
538                         buff->next_segment = 0;
539                         stop_read_ahead = 0;
540                 }
541                 if (ftape_calc_next_cluster(buff) == 0 ||
542                     fdc_setup_read_write(buff, mode) != 0) {
543                         TRACE(ft_t_err, "couldn't start %s-ahead",
544                               write ? "write" : "read");
545                         ft_runner_status = do_abort;
546                         fdc_mode         = fdc_idle;
547                 } else {
548                         /* keep on going */
549                         switch (ft_driver_state) {
550                         case   reading: buff->status = reading;   break;
551                         case verifying: buff->status = verifying; break;
552                         case   writing: buff->status = writing;   break;
553                         case  deleting: buff->status = deleting;  break;
554                         default:
555                                 TRACE(ft_t_err, 
556                       "BUG: ft_driver_state %d should be one out of "
557                       "{reading, writing, verifying, deleting}",
558                                       ft_driver_state);
559                                 buff->status = write ? writing : reading;
560                                 break;
561                         }
562                 }
563         }
564         TRACE_EXIT;
565 }
566
567 static void retry_sector(buffer_struct *buff, 
568                          int mode,
569                          unsigned int skip)
570 {
571         TRACE_FUN(ft_t_any);
572
573         TRACE(ft_t_noise, "%s error, will retry",
574               (mode == fdc_writing_data || mode == fdc_deleting) ? "write" : "read");
575         pause_tape(1, mode);
576         ft_runner_status = aborting;
577         buff->status     = error;
578         buff->skip       = skip;
579         TRACE_EXIT;
580 }
581
582 static unsigned int find_resume_point(buffer_struct *buff)
583 {
584         int i = 0;
585         SectorMap mask;
586         SectorMap map;
587         TRACE_FUN(ft_t_any);
588
589         /*  This function is to be called after all variables have been
590          *  updated to point past the failing sector.
591          *  If there are any soft errors before the failing sector,
592          *  find the first soft error and return the sector offset.
593          *  Otherwise find the last hard error.
594          *  Note: there should always be at least one hard or soft error !
595          */
596         if (buff->sector_offset < 1 || buff->sector_offset > 32) {
597                 TRACE(ft_t_bug, "BUG: sector_offset = %d",
598                       buff->sector_offset);
599                 TRACE_EXIT 0;
600         }
601         if (buff->sector_offset >= 32) { /* C-limitation on shift ! */
602                 mask = 0xffffffff;
603         } else {
604                 mask = (1 << buff->sector_offset) - 1;
605         }
606         map = buff->soft_error_map & mask;
607         if (map) {
608                 while ((map & (1 << i)) == 0) {
609                         ++i;
610                 }
611                 TRACE(ft_t_noise, "at sector %d", FT_SECTOR(i));
612         } else {
613                 map = buff->hard_error_map & mask;
614                 i = buff->sector_offset - 1;
615                 if (map) {
616                         while ((map & (1 << i)) == 0) {
617                                 --i;
618                         }
619                         TRACE(ft_t_noise, "after sector %d", FT_SECTOR(i));
620                         ++i; /* first sector after last hard error */
621                 } else {
622                         TRACE(ft_t_bug, "BUG: no soft or hard errors");
623                 }
624         }
625         TRACE_EXIT i;
626 }
627
628 /*  check possible dma residue when formatting, update position record in
629  *  buffer struct. This is, of course, modelled after determine_progress(), but
630  *  we don't need to set up for retries because the format process cannot be
631  *  interrupted (except at the end of the tape track).
632  */
633 static int determine_fmt_progress(buffer_struct *buff, error_cause cause)
634 {
635         unsigned int dma_residue;
636         TRACE_FUN(ft_t_any);
637
638         /*  Using less preferred order of disable_dma and
639          *  get_dma_residue because this seems to fail on at least one
640          *  system if reversed!
641          */
642         dma_residue = get_dma_residue(fdc.dma);
643         disable_dma(fdc.dma);
644         if (cause != no_error || dma_residue != 0) {
645                 TRACE(ft_t_info, "DMA residue = 0x%04x", dma_residue);
646                 fdc_mode = fdc_idle;
647                 switch(cause) {
648                 case no_error:
649                         ft_runner_status = aborting;
650                         buff->status = idle;
651                         break;
652                 case overrun_error:
653                         /*  got an overrun error on the first byte, must be a
654                          *  hardware problem 
655                          */
656                         TRACE(ft_t_bug, 
657                               "Unexpected error: failing DMA controller ?");
658                         ft_runner_status = do_abort;
659                         buff->status = error;
660                         break;
661                 default:
662                         TRACE(ft_t_noise, "Unexpected error at segment %d",
663                               buff->segment_id);
664                         ft_runner_status = do_abort;
665                         buff->status = error;
666                         break;
667                 }
668                 TRACE_EXIT -EIO; /* can only retry entire track in format mode
669                                   */
670         }
671         /*  Update var's influenced by the DMA operation.
672          */
673         buff->ptr             += FT_SECTORS_PER_SEGMENT * 4;
674         buff->bytes           -= FT_SECTORS_PER_SEGMENT * 4;
675         buff->remaining       -= FT_SECTORS_PER_SEGMENT;
676         buff->segment_id ++; /* done with segment */
677         TRACE_EXIT 0;
678 }
679
680 /*
681  *  Continue formatting, switch buffers if there is no data left in
682  *  current buffer. This is, of course, modelled after
683  *  continue_xfer(), but we don't need to set up for retries because
684  *  the format process cannot be interrupted (except at the end of the
685  *  tape track).
686  */
687 static void continue_formatting(buffer_struct *buff)
688 {
689         TRACE_FUN(ft_t_any);
690
691         if (buff->remaining <= 0) { /*  no space left in dma buffer */
692                 unsigned int next = buff->next_segment; 
693
694                 if (next == 0) { /* end of tape track */
695                         buff->status     = done;
696                         ft_runner_status = logical_eot;
697                         fdc_mode         = fdc_idle;
698                         TRACE(ft_t_noise, "Done formatting track %d",
699                               ft_location.track);
700                         TRACE_EXIT;
701                 }
702                 /*
703                  *  switch to next buffer!
704                  */
705                 buff->status   = done;
706                 buff = ftape_next_buffer(ft_queue_head);
707
708                 if (buff->status != waiting  || next != buff->segment_id) {
709                         goto format_setup_error;
710                 }
711         }
712         if (fdc_setup_formatting(buff) < 0) {
713                 goto format_setup_error;
714         }
715         buff->status = formatting;
716         TRACE(ft_t_fdc_dma, "Formatting segment %d on track %d",
717               buff->segment_id, ft_location.track);
718         TRACE_EXIT;
719  format_setup_error:
720         ft_runner_status = do_abort;
721         fdc_mode         = fdc_idle;
722         buff->status     = error;
723         TRACE(ft_t_err, "Error setting up for segment %d on track %d",
724               buff->segment_id, ft_location.track);
725         TRACE_EXIT;
726
727 }
728
729 /*  this handles writing, read id, reading and formatting
730  */
731 static void handle_fdc_busy(buffer_struct *buff)
732 {
733         static int no_data_error_count;
734         int retry = 0;
735         error_cause cause;
736         __u8 in[7];
737         int skip;
738         fdc_mode_enum fmode = fdc_mode;
739         TRACE_FUN(ft_t_any);
740
741         if (fdc_result(in, 7) < 0) { /* better get it fast ! */
742                 TRACE(ft_t_err, 
743                       "Probably fatal error during FDC Result Phase\n"
744                       KERN_INFO
745                       "drive may hang until (power on) reset :-(");
746                 /*  what to do next ????
747                  */
748                 TRACE_EXIT;
749         }
750         cause = decode_irq_cause(fdc_mode, in);
751 #ifdef TESTING
752         { int i;
753         for (i = 0; i < (int)ft_nr_buffers; ++i)
754                 TRACE(ft_t_any, "buffer[%d] status: %d, segment_id: %d",
755                       i, ft_buffer[i]->status, ft_buffer[i]->segment_id);
756         }
757 #endif
758         if (fmode == fdc_reading_data && ft_driver_state == verifying) {
759                 fmode = fdc_verifying;
760         }
761         switch (fmode) {
762         case fdc_verifying:
763                 if (ft_runner_status == aborting ||
764                     ft_runner_status == do_abort) {
765                         TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode));
766                         break;
767                 }
768                 if (buff->retry > 0) {
769                         TRACE(ft_t_flow, "this is retry nr %d", buff->retry);
770                 }
771                 switch (cause) {
772                 case no_error:
773                         no_data_error_count = 0;
774                         determine_verify_progress(buff, cause, in[5]);
775                         if (in[2] & 0x40) {
776                                 /*  This should not happen when verifying
777                                  */
778                                 TRACE(ft_t_warn,
779                                       "deleted data in segment %d/%d",
780                                       buff->segment_id,
781                                       FT_SECTOR(buff->sector_offset - 1));
782                                 buff->remaining = 0; /* abort transfer */
783                                 buff->hard_error_map = EMPTY_SEGMENT;
784                                 skip = 1;
785                         } else {
786                                 skip = 0;
787                         }
788                         continue_xfer(buff, fdc_mode, skip);
789                         break;
790                 case no_data_error:
791                         no_data_error_count ++;
792                 case overrun_error:
793                         retry ++;
794                 case id_am_error:
795                 case id_crc_error:
796                 case data_am_error:
797                 case data_crc_error:
798                         determine_verify_progress(buff, cause, in[5]); 
799                         if (cause == no_data_error) {
800                                 if (no_data_error_count >= 2) {
801                                         TRACE(ft_t_warn,
802                                               "retrying because of successive "
803                                               "no data errors");
804                                         no_data_error_count = 0;
805                                 } else {
806                                         retry --;
807                                 }
808                         } else {
809                                 no_data_error_count = 0;
810                         }
811                         if (retry) {
812                                 skip = find_resume_point(buff);
813                         } else {
814                                 skip = buff->sector_offset;
815                         }
816                         if (retry && skip < 32) {
817                                 retry_sector(buff, fdc_mode, skip);
818                         } else {
819                                 continue_xfer(buff, fdc_mode, skip);
820                         }
821                         update_history(cause);
822                         break;
823                 default:
824                         /*  Don't know why this could happen 
825                          *  but find out.
826                          */
827                         determine_verify_progress(buff, cause, in[5]);
828                         retry_sector(buff, fdc_mode, 0);
829                         TRACE(ft_t_err, "Error: unexpected error");
830                         break;
831                 }
832                 break;
833         case fdc_reading_data:
834 #ifdef TESTING
835                 /* I'm sorry, but: NOBODY ever used this trace
836                  * messages for ages. I guess that Bas was the last person
837                  * that ever really used this (thank you, between the lines)
838                  */
839                 if (cause == no_error) {
840                         TRACE(ft_t_flow,"reading segment %d",buff->segment_id);
841                 } else {
842                         TRACE(ft_t_noise, "error reading segment %d",
843                               buff->segment_id);
844                         TRACE(ft_t_noise, "\n"
845                               KERN_INFO
846                              "IRQ:C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x\n"
847                               KERN_INFO
848                               "BUF:C: 0x%02x, H: 0x%02x, R: 0x%02x",
849                               in[3], in[4], in[5], in[6],
850                               buff->cyl, buff->head, buff->sect);
851                 }
852 #endif
853                 if (ft_runner_status == aborting ||
854                     ft_runner_status == do_abort) {
855                         TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode));
856                         break;
857                 }
858                 if (buff->bad_sector_map == FAKE_SEGMENT) {
859                         /* This condition occurs when reading a `fake'
860                          * sector that's not accessible. Doesn't
861                          * really matter as we would have ignored it
862                          * anyway !
863                          *
864                          * Chance is that we're past the next segment
865                          * now, so the next operation may fail and
866                          * result in a retry.  
867                          */
868                         buff->remaining = 0;    /* skip failing sector */
869                         /* buff->ptr       = buff->address; */
870                         /* fake success: */
871                         continue_xfer(buff, fdc_mode, 1);
872                         /*  trace calls are expensive: place them AFTER
873                          *  the real stuff has been done.
874                          *  
875                          */
876                         TRACE(ft_t_noise, "skipping empty segment %d (read), size? %d",
877                               buff->segment_id, buff->ptr - buff->address);
878                         TRACE_EXIT;
879                 }
880                 if (buff->retry > 0) {
881                         TRACE(ft_t_flow, "this is retry nr %d", buff->retry);
882                 }
883                 switch (cause) {
884                 case no_error:
885                         determine_progress(buff, cause, in[5]);
886                         if (in[2] & 0x40) {
887                                 /*  Handle deleted data in header segments.
888                                  *  Skip segment and force read-ahead.
889                                  */
890                                 TRACE(ft_t_warn,
891                                       "deleted data in segment %d/%d",
892                                       buff->segment_id,
893                                       FT_SECTOR(buff->sector_offset - 1));
894                                 buff->deleted = 1;
895                                 buff->remaining = 0;/*abort transfer */
896                                 buff->soft_error_map |=
897                                                 (-1L << buff->sector_offset);
898                                 if (buff->segment_id == 0) {
899                                         /* stop on next segment */
900                                         stop_read_ahead = 1;
901                                 }
902                                 /* force read-ahead: */
903                                 buff->next_segment = 
904                                         buff->segment_id + 1;
905                                 skip = (FT_SECTORS_PER_SEGMENT - 
906                                         buff->sector_offset);
907                         } else {
908                                 skip = 0;
909                         }
910                         continue_xfer(buff, fdc_mode, skip);
911                         break;
912                 case no_data_error:
913                         /* Tape started too far ahead of or behind the
914                          * right sector.  This may also happen in the
915                          * middle of a segment !
916                          *
917                          * Handle no-data as soft error. If next
918                          * sector fails too, a retry (with needed
919                          * reposition) will follow.
920                          */
921                         retry ++;
922                 case id_am_error:
923                 case id_crc_error:
924                 case data_am_error:
925                 case data_crc_error:
926                 case overrun_error:
927                         retry += (buff->soft_error_map != 0 ||
928                                   buff->hard_error_map != 0);
929                         determine_progress(buff, cause, in[5]); 
930 #if 1 || defined(TESTING)
931                         if (cause == overrun_error) retry ++;
932 #endif
933                         if (retry) {
934                                 skip = find_resume_point(buff);
935                         } else {
936                                 skip = buff->sector_offset;
937                         }
938                         /*  Try to resume with next sector on single
939                          *  errors (let ecc correct it), but retry on
940                          *  no_data (we'll be past the target when we
941                          *  get here so we cannot retry) or on
942                          *  multiple errors (reduce chance on ecc
943                          *  failure).
944                          */
945                         /*  cH: 23/02/97: if the last sector in the 
946                          *  segment was a hard error, then there is 
947                          *  no sense in a retry. This occasion seldom
948                          *  occurs but ... @:³²¸`@%&§$
949                          */
950                         if (retry && skip < 32) {
951                                 retry_sector(buff, fdc_mode, skip);
952                         } else {
953                                 continue_xfer(buff, fdc_mode, skip);
954                         }
955                         update_history(cause);
956                         break;
957                 default:
958                         /*  Don't know why this could happen 
959                          *  but find out.
960                          */
961                         determine_progress(buff, cause, in[5]);
962                         retry_sector(buff, fdc_mode, 0);
963                         TRACE(ft_t_err, "Error: unexpected error");
964                         break;
965                 }
966                 break;
967         case fdc_reading_id:
968                 if (cause == no_error) {
969                         fdc_cyl = in[3];
970                         fdc_head = in[4];
971                         fdc_sect = in[5];
972                         TRACE(ft_t_fdc_dma,
973                               "id read: C: 0x%02x, H: 0x%02x, R: 0x%02x",
974                               fdc_cyl, fdc_head, fdc_sect);
975                 } else {        /* no valid information, use invalid sector */
976                         fdc_cyl = fdc_head = fdc_sect = 0;
977                         TRACE(ft_t_flow, "Didn't find valid sector Id");
978                 }
979                 fdc_mode = fdc_idle;
980                 break;
981         case fdc_deleting:
982         case fdc_writing_data:
983 #ifdef TESTING
984                 if (cause == no_error) {
985                         TRACE(ft_t_flow, "writing segment %d", buff->segment_id);
986                 } else {
987                         TRACE(ft_t_noise, "error writing segment %d",
988                               buff->segment_id);
989                 }
990 #endif
991                 if (ft_runner_status == aborting ||
992                     ft_runner_status == do_abort) {
993                         TRACE(ft_t_flow, "aborting %s",fdc_mode_txt(fdc_mode));
994                         break;
995                 }
996                 if (buff->retry > 0) {
997                         TRACE(ft_t_flow, "this is retry nr %d", buff->retry);
998                 }
999                 if (buff->bad_sector_map == FAKE_SEGMENT) {
1000                         /* This condition occurs when trying to write to a
1001                          * `fake' sector that's not accessible. Doesn't really
1002                          * matter as it isn't used anyway ! Might be located
1003                          * at wrong segment, then we'll fail on the next
1004                          * segment.
1005                          */
1006                         TRACE(ft_t_noise, "skipping empty segment (write)");
1007                         buff->remaining = 0;    /* skip failing sector */
1008                         /* fake success: */
1009                         continue_xfer(buff, fdc_mode, 1);
1010                         break;
1011                 }
1012                 switch (cause) {
1013                 case no_error:
1014                         determine_progress(buff, cause, in[5]);
1015                         continue_xfer(buff, fdc_mode, 0);
1016                         break;
1017                 case no_data_error:
1018                 case id_am_error:
1019                 case id_crc_error:
1020                 case data_am_error:
1021                 case overrun_error:
1022                         update_history(cause);
1023                         determine_progress(buff, cause, in[5]);
1024                         skip = find_resume_point(buff);
1025                         retry_sector(buff, fdc_mode, skip);
1026                         break;
1027                 default:
1028                         if (in[1] & 0x02) {
1029                                 TRACE(ft_t_err, "media not writable");
1030                         } else {
1031                                 TRACE(ft_t_bug, "unforeseen write error");
1032                         }
1033                         fdc_mode = fdc_idle;
1034                         break;
1035                 }
1036                 break; /* fdc_deleting || fdc_writing_data */
1037         case fdc_formatting:
1038                 /*  The interrupt comes after formatting a segment. We then
1039                  *  have to set up QUICKLY for the next segment. But
1040                  *  afterwards, there is plenty of time.
1041                  */
1042                 switch (cause) {
1043                 case no_error:
1044                         /*  would like to keep most of the formatting stuff
1045                          *  outside the isr code, but timing is too critical
1046                          */
1047                         if (determine_fmt_progress(buff, cause) >= 0) {
1048                                 continue_formatting(buff);
1049                         }
1050                         break;
1051                 case no_data_error:
1052                 case id_am_error:
1053                 case id_crc_error:
1054                 case data_am_error:
1055                 case overrun_error:
1056                 default:
1057                         determine_fmt_progress(buff, cause);
1058                         update_history(cause);
1059                         if (in[1] & 0x02) {
1060                                 TRACE(ft_t_err, "media not writable");
1061                         } else {
1062                                 TRACE(ft_t_bug, "unforeseen write error");
1063                         }
1064                         break;
1065                 } /* cause */
1066                 break;
1067         default:
1068                 TRACE(ft_t_warn, "Warning: unexpected irq during: %s",
1069                       fdc_mode_txt(fdc_mode));
1070                 fdc_mode = fdc_idle;
1071                 break;
1072         }
1073         TRACE_EXIT;
1074 }
1075
1076 /*      FDC interrupt service routine.
1077  */
1078 void fdc_isr(void)
1079 {
1080         static int isr_active;
1081 #ifdef TESTING
1082         unsigned int t0 = ftape_timestamp();
1083 #endif
1084         TRACE_FUN(ft_t_any);
1085
1086         if (isr_active++) {
1087                 --isr_active;
1088                 TRACE(ft_t_bug, "BUG: nested interrupt, not good !");
1089                 *fdc.hook = fdc_isr; /*  hook our handler into the fdc
1090                                       *  code again 
1091                                       */
1092                 TRACE_EXIT;
1093         }
1094         sti();
1095         if (inb_p(fdc.msr) & FDC_BUSY) {        /*  Entering Result Phase */
1096                 ft_hide_interrupt = 0;
1097                 handle_fdc_busy(ftape_get_buffer(ft_queue_head));
1098                 if (ft_runner_status == do_abort) {
1099                         /*      cease operation, remember tape position
1100                          */
1101                         TRACE(ft_t_flow, "runner aborting");
1102                         ft_runner_status = aborting;
1103                         ++ft_expected_stray_interrupts;
1104                 }
1105         } else { /* !FDC_BUSY */
1106                 /*  clear interrupt, cause should be gotten by issuing
1107                  *  a Sense Interrupt Status command.
1108                  */
1109                 if (fdc_mode == fdc_recalibrating || fdc_mode == fdc_seeking) {
1110                         if (ft_hide_interrupt) {
1111                                 int st0;
1112                                 int pcn;
1113
1114                                 if (fdc_sense_interrupt_status(&st0, &pcn) < 0)
1115                                         TRACE(ft_t_err,
1116                                               "sense interrupt status failed");
1117                                 ftape_current_cylinder = pcn;
1118                                 TRACE(ft_t_flow, "handled hidden interrupt");
1119                         }
1120                         ft_seek_completed = 1;
1121                         fdc_mode = fdc_idle;
1122                 } else if (!waitqueue_active(&ftape_wait_intr)) {
1123                         if (ft_expected_stray_interrupts == 0) {
1124                                 TRACE(ft_t_warn, "unexpected stray interrupt");
1125                         } else {
1126                                 TRACE(ft_t_flow, "expected stray interrupt");
1127                                 --ft_expected_stray_interrupts;
1128                         }
1129                 } else {
1130                         if (fdc_mode == fdc_reading_data ||
1131                             fdc_mode == fdc_verifying    ||
1132                             fdc_mode == fdc_writing_data ||
1133                             fdc_mode == fdc_deleting     ||
1134                             fdc_mode == fdc_formatting   ||
1135                             fdc_mode == fdc_reading_id) {
1136                                 if (inb_p(fdc.msr) & FDC_BUSY) {
1137                                         TRACE(ft_t_bug,
1138                                         "***** FDC failure, busy too late");
1139                                 } else {
1140                                         TRACE(ft_t_bug,
1141                                               "***** FDC failure, no busy");
1142                                 }
1143                         } else {
1144                                 TRACE(ft_t_fdc_dma, "awaited stray interrupt");
1145                         }
1146                 }
1147                 ft_hide_interrupt = 0;
1148         }
1149         /*    Handle sleep code.
1150          */
1151         if (!ft_hide_interrupt) {
1152                 ft_interrupt_seen ++;
1153                 if (waitqueue_active(&ftape_wait_intr)) {
1154                         wake_up_interruptible(&ftape_wait_intr);
1155                 }
1156         } else {
1157                 TRACE(ft_t_flow, "hiding interrupt while %s", 
1158                       waitqueue_active(&ftape_wait_intr) ? "waiting":"active");
1159         }
1160 #ifdef TESTING
1161         t0 = ftape_timediff(t0, ftape_timestamp());
1162         if (t0 >= 1000) {
1163                 /* only tell us about long calls */
1164                 TRACE(ft_t_noise, "isr() duration: %5d usec", t0);
1165         }
1166 #endif
1167         *fdc.hook = fdc_isr;    /* hook our handler into the fdc code again */
1168         --isr_active;
1169         TRACE_EXIT;
1170 }