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 
print_error_cause(int cause)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 
fdc_mode_txt(fdc_mode_enum mode)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 
decode_irq_cause(fdc_mode_enum mode,__u8 st[])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 
update_history(error_cause cause)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 
skip_bad_sector(buffer_struct * buff)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 
update_error_maps(buffer_struct * buff,unsigned int error_offset)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 
print_progress(buffer_struct * buff,error_cause cause)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  */
determine_verify_progress(buffer_struct * buff,error_cause cause,__u8 sector)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 
determine_progress(buffer_struct * buff,error_cause cause,__u8 sector)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 
calc_steps(int cmd)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 
pause_tape(int retry,int mode)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 
continue_xfer(buffer_struct * buff,fdc_mode_enum mode,unsigned int skip)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 
retry_sector(buffer_struct * buff,int mode,unsigned int skip)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 
find_resume_point(buffer_struct * buff)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  */
determine_fmt_progress(buffer_struct * buff,error_cause cause)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  */
continue_formatting(buffer_struct * buff)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  */
handle_fdc_busy(buffer_struct * buff)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  */
fdc_isr(void)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 #if LINUX_VERSION_CODE >= KERNEL_VER(2,0,16)
1123 		} else if (!waitqueue_active(&ftape_wait_intr)) {
1124 #else
1125 		} else if (!ftape_wait_intr) {
1126 #endif
1127 			if (ft_expected_stray_interrupts == 0) {
1128 				TRACE(ft_t_warn, "unexpected stray interrupt");
1129 			} else {
1130 				TRACE(ft_t_flow, "expected stray interrupt");
1131 				--ft_expected_stray_interrupts;
1132 			}
1133 		} else {
1134 			if (fdc_mode == fdc_reading_data ||
1135 			    fdc_mode == fdc_verifying    ||
1136 			    fdc_mode == fdc_writing_data ||
1137 			    fdc_mode == fdc_deleting     ||
1138 			    fdc_mode == fdc_formatting   ||
1139 			    fdc_mode == fdc_reading_id) {
1140 				if (inb_p(fdc.msr) & FDC_BUSY) {
1141 					TRACE(ft_t_bug,
1142 					"***** FDC failure, busy too late");
1143 				} else {
1144 					TRACE(ft_t_bug,
1145 					      "***** FDC failure, no busy");
1146 				}
1147 			} else {
1148 				TRACE(ft_t_fdc_dma, "awaited stray interrupt");
1149 			}
1150 		}
1151 		ft_hide_interrupt = 0;
1152 	}
1153 	/*    Handle sleep code.
1154 	 */
1155 	if (!ft_hide_interrupt) {
1156 		ft_interrupt_seen ++;
1157 #if LINUX_VERSION_CODE >= KERNEL_VER(2,0,16)
1158 		if (waitqueue_active(&ftape_wait_intr)) {
1159 			wake_up_interruptible(&ftape_wait_intr);
1160 		}
1161 #else
1162 		if (ftape_wait_intr) {
1163 			wake_up_interruptible(&ftape_wait_intr);
1164 		}
1165 #endif
1166 	} else {
1167 #if LINUX_VERSION_CODE >= KERNEL_VER(2,0,16)
1168 		TRACE(ft_t_flow, "hiding interrupt while %s",
1169 		      waitqueue_active(&ftape_wait_intr) ? "waiting":"active");
1170 #else
1171 		TRACE(ft_t_flow, "hiding interrupt while %s",
1172 		      ftape_wait_intr ? "waiting" : "active");
1173 #endif
1174 	}
1175 #ifdef TESTING
1176 	t0 = ftape_timediff(t0, ftape_timestamp());
1177 	if (t0 >= 1000) {
1178 		/* only tell us about long calls */
1179 		TRACE(ft_t_noise, "isr() duration: %5d usec", t0);
1180 	}
1181 #endif
1182 	*fdc.hook = fdc_isr;	/* hook our handler into the fdc code again */
1183 	--isr_active;
1184 	TRACE_EXIT;
1185 }
1186