2 * Copyright (C) 1993-1996 Bas Laarhoven,
3 * 1996-1997 Claus-Justus Heine.
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)
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.
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.
20 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.c,v $
22 * $Date: 1997/11/11 14:37:44 $
24 * This file contains the non-read/write ftape functions for the
25 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
28 #include <linux/errno.h>
30 #include <linux/mman.h>
32 #include <linux/ftape.h>
33 #include <linux/qic117.h>
34 #include <asm/uaccess.h>
37 /* ease porting between pre-2.4.x and later kernels */
38 #define vma_get_pgoff(v) ((v)->vm_pgoff)
40 #include "../lowlevel/ftape-tracing.h"
41 #include "../lowlevel/ftape-io.h"
42 #include "../lowlevel/ftape-ctl.h"
43 #include "../lowlevel/ftape-write.h"
44 #include "../lowlevel/ftape-read.h"
45 #include "../lowlevel/ftape-rw.h"
46 #include "../lowlevel/ftape-bsm.h"
50 ftape_info ftape_status
= {
51 /* vendor information */
52 { 0, }, /* drive type */
54 500, /* used data rate */
55 500, /* drive max rate */
56 500, /* fdc max rate */
57 /* drive selection, either FTAPE_SEL_A/B/C/D */
58 -1, /* drive selection */
59 /* flags set after decode the drive and tape status */
62 1, /* write protected */
64 /* values of last queried drive/tape status and error */
65 {{0,}}, /* last error code */
66 {{0,}}, /* drive status, configuration, tape status */
67 /* cartridge geometry */
68 20, /* tracks_per_tape */
69 102, /* segments_per_track */
70 /* location of header segments, etc. */
71 -1, /* used_header_segment */
72 -1, /* header_segment_1 */
73 -1, /* header_segment_2 */
74 -1, /* first_data_segment */
75 -1, /* last_data_segment */
76 /* the format code as stored in the header segment */
77 fmt_normal
, /* format code */
78 /* the default for the qic std: unknown */
80 /* is tape running? */
81 idle
, /* runner_state */
82 /* is tape reading/writing/verifying/formatting/deleting */
83 idle
, /* driver state */
84 /* flags fatal hardware error */
87 { 0, } /* history record */
90 int ftape_segments_per_head
= 1020;
91 int ftape_segments_per_cylinder
= 4;
92 int ftape_init_drive_needed
= 1; /* need to be global for ftape_reset_drive()
98 static const vendor_struct vendors
[] = QIC117_VENDORS
;
99 static const wakeup_method methods
[] = WAKEUP_METHODS
;
101 const ftape_info
*ftape_get_status(void)
103 #if defined(STATUS_PARANOYA)
104 static ftape_info get_status
;
106 get_status
= ftape_status
;
109 return &ftape_status
; /* maybe return only a copy of it to assure
115 static int ftape_not_operational(int status
)
117 /* return true if status indicates tape can not be used.
119 return ((status
^ QIC_STATUS_CARTRIDGE_PRESENT
) &
121 QIC_STATUS_CARTRIDGE_PRESENT
|
122 QIC_STATUS_NEW_CARTRIDGE
));
125 int ftape_seek_to_eot(void)
130 TRACE_CATCH(ftape_ready_wait(ftape_timeout
.pause
, &status
),);
131 while ((status
& QIC_STATUS_AT_EOT
) == 0) {
132 if (ftape_not_operational(status
)) {
135 TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_FORWARD
,
136 ftape_timeout
.rewind
,&status
),);
141 int ftape_seek_to_bot(void)
146 TRACE_CATCH(ftape_ready_wait(ftape_timeout
.pause
, &status
),);
147 while ((status
& QIC_STATUS_AT_BOT
) == 0) {
148 if (ftape_not_operational(status
)) {
151 TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_REVERSE
,
152 ftape_timeout
.rewind
,&status
),);
157 static int ftape_new_cartridge(void)
159 ft_location
.track
= -1; /* force seek on first access */
160 ftape_zap_read_buffers();
161 ftape_zap_write_buffers();
165 int ftape_abort_operation(void)
169 TRACE_FUN(ft_t_flow
);
171 if (ft_runner_status
== running
) {
172 TRACE(ft_t_noise
, "aborting runner, waiting");
174 ft_runner_status
= do_abort
;
175 /* set timeout so that the tape will run to logical EOT
176 * if we missed the last sector and there are no queue pulses.
178 result
= ftape_dumb_stop();
180 if (ft_runner_status
!= idle
) {
181 if (ft_runner_status
== do_abort
) {
182 TRACE(ft_t_noise
, "forcing runner abort");
184 TRACE(ft_t_noise
, "stopping tape");
185 result
= ftape_stop_tape(&status
);
186 ft_location
.known
= 0;
187 ft_runner_status
= idle
;
189 ftape_reset_buffer();
190 ftape_zap_read_buffers();
191 ftape_set_state(idle
);
195 static int lookup_vendor_id(unsigned int vendor_id
)
199 while (vendors
[i
].vendor_id
!= vendor_id
) {
200 if (++i
>= NR_ITEMS(vendors
)) {
207 static void ftape_detach_drive(void)
211 TRACE(ft_t_flow
, "disabling tape drive and fdc");
212 ftape_put_drive_to_sleep(ft_drive_type
.wake_up
);
213 fdc_catch_stray_interrupts(1); /* one always comes */
215 fdc_release_irq_and_dma();
216 fdc_release_regions();
220 static void clear_history(void)
223 ft_history
.id_am_errors
=
224 ft_history
.id_crc_errors
=
225 ft_history
.data_am_errors
=
226 ft_history
.data_crc_errors
=
227 ft_history
.overrun_errors
=
228 ft_history
.no_data_errors
=
230 ft_history
.crc_errors
=
231 ft_history
.crc_failures
=
232 ft_history
.ecc_failures
=
233 ft_history
.corrected
=
235 ft_history
.rewinds
= 0;
238 static int ftape_activate_drive(vendor_struct
* drive_type
)
241 TRACE_FUN(ft_t_flow
);
243 /* If we already know the drive type, wake it up.
244 * Else try to find out what kind of drive is attached.
246 if (drive_type
->wake_up
!= unknown_wake_up
) {
247 TRACE(ft_t_flow
, "enabling tape drive and fdc");
248 result
= ftape_wakeup_drive(drive_type
->wake_up
);
250 TRACE(ft_t_err
, "known wakeup method failed");
253 wake_up_types method
;
254 const ft_trace_t old_tracing
= TRACE_LEVEL
;
255 if (TRACE_LEVEL
< ft_t_flow
) {
256 SET_TRACE_LEVEL(ft_t_bug
);
259 /* Try to awaken the drive using all known methods.
260 * Lower tracing for a while.
262 for (method
=no_wake_up
; method
< NR_ITEMS(methods
); ++method
) {
263 drive_type
->wake_up
= method
;
264 #ifdef CONFIG_FT_TWO_DRIVES
265 /* Test setup for dual drive configuration.
266 * /dev/rft2 uses mountain wakeup
267 * /dev/rft3 uses colorado wakeup
268 * Other systems will use the normal scheme.
270 if ((ft_drive_sel
< 2) ||
271 (ft_drive_sel
== 2 && method
== FT_WAKE_UP_1
) ||
272 (ft_drive_sel
== 3 && method
== FT_WAKE_UP_2
)) {
273 result
=ftape_wakeup_drive(drive_type
->wake_up
);
278 result
= ftape_wakeup_drive(drive_type
->wake_up
);
281 TRACE(ft_t_warn
, "drive wakeup method: %s",
282 methods
[drive_type
->wake_up
].name
);
286 SET_TRACE_LEVEL(old_tracing
);
288 if (method
>= NR_ITEMS(methods
)) {
289 /* no response at all, cannot open this drive */
290 drive_type
->wake_up
= unknown_wake_up
;
291 TRACE(ft_t_err
, "no tape drive found !");
298 static int ftape_get_drive_status(void)
302 TRACE_FUN(ft_t_flow
);
304 ft_no_tape
= ft_write_protected
= 0;
305 /* Tape drive is activated now.
306 * First clear error status if present.
309 result
= ftape_ready_wait(ftape_timeout
.reset
, &status
);
311 if (result
== -ETIME
) {
312 TRACE(ft_t_err
, "ftape_ready_wait timeout");
313 } else if (result
== -EINTR
) {
314 TRACE(ft_t_err
, "ftape_ready_wait aborted");
316 TRACE(ft_t_err
, "ftape_ready_wait failed");
320 /* Clear error condition (drive is ready !)
322 if (status
& QIC_STATUS_ERROR
) {
324 qic117_cmd_t command
;
326 TRACE(ft_t_err
, "error status set");
327 result
= ftape_report_error(&error
, &command
, 1);
330 "report_error_code failed: %d", result
);
331 /* hope it's working next time */
334 } else if (error
!= 0) {
335 TRACE(ft_t_noise
, "error code : %d", error
);
336 TRACE(ft_t_noise
, "error command: %d", command
);
339 if (status
& QIC_STATUS_NEW_CARTRIDGE
) {
341 qic117_cmd_t command
;
342 const ft_trace_t old_tracing
= TRACE_LEVEL
;
343 SET_TRACE_LEVEL(ft_t_bug
);
345 /* Undocumented feature: Must clear (not present!)
346 * error here or we'll fail later.
348 ftape_report_error(&error
, &command
, 1);
350 SET_TRACE_LEVEL(old_tracing
);
351 TRACE(ft_t_info
, "status: new cartridge");
356 FT_SIGNAL_EXIT(_DONT_BLOCK
);
357 } while (status
& QIC_STATUS_ERROR
);
359 ft_no_tape
= !(status
& QIC_STATUS_CARTRIDGE_PRESENT
);
360 ft_write_protected
= (status
& QIC_STATUS_WRITE_PROTECT
) != 0;
362 TRACE(ft_t_warn
, "no cartridge present");
364 if (ft_write_protected
) {
365 TRACE(ft_t_noise
, "Write protected cartridge");
371 static void ftape_log_vendor_id(void)
374 TRACE_FUN(ft_t_flow
);
376 ftape_report_vendor_id(&ft_drive_type
.vendor_id
);
377 vendor_index
= lookup_vendor_id(ft_drive_type
.vendor_id
);
378 if (ft_drive_type
.vendor_id
== UNKNOWN_VENDOR
&&
379 ft_drive_type
.wake_up
== wake_up_colorado
) {
381 /* hack to get rid of all this mail */
382 ft_drive_type
.vendor_id
= 0;
384 if (vendor_index
< 0) {
385 /* Unknown vendor id, first time opening device. The
386 * drive_type remains set to type found at wakeup
387 * time, this will probably keep the driver operating
388 * for this new vendor.
390 TRACE(ft_t_warn
, "\n"
391 KERN_INFO
"============ unknown vendor id ===========\n"
392 KERN_INFO
"A new, yet unsupported tape drive is found\n"
393 KERN_INFO
"Please report the following values:\n"
394 KERN_INFO
" Vendor id : 0x%04x\n"
395 KERN_INFO
" Wakeup method : %s\n"
396 KERN_INFO
"And a description of your tape drive\n"
397 KERN_INFO
"to "THE_FTAPE_MAINTAINER
"\n"
398 KERN_INFO
"==========================================",
399 ft_drive_type
.vendor_id
,
400 methods
[ft_drive_type
.wake_up
].name
);
401 ft_drive_type
.speed
= 0; /* unknown */
403 ft_drive_type
.name
= vendors
[vendor_index
].name
;
404 ft_drive_type
.speed
= vendors
[vendor_index
].speed
;
405 TRACE(ft_t_info
, "tape drive type: %s", ft_drive_type
.name
);
406 /* scan all methods for this vendor_id in table */
407 while(ft_drive_type
.wake_up
!= vendors
[vendor_index
].wake_up
) {
408 if (vendor_index
< NR_ITEMS(vendors
) - 1 &&
409 vendors
[vendor_index
+ 1].vendor_id
411 ft_drive_type
.vendor_id
) {
417 if (ft_drive_type
.wake_up
!= vendors
[vendor_index
].wake_up
) {
418 TRACE(ft_t_warn
, "\n"
419 KERN_INFO
"==========================================\n"
420 KERN_INFO
"wakeup type mismatch:\n"
421 KERN_INFO
"found: %s, expected: %s\n"
422 KERN_INFO
"please report this to "THE_FTAPE_MAINTAINER
"\n"
423 KERN_INFO
"==========================================",
424 methods
[ft_drive_type
.wake_up
].name
,
425 methods
[vendors
[vendor_index
].wake_up
].name
);
431 void ftape_calc_timeouts(unsigned int qic_std
,
432 unsigned int data_rate
,
433 unsigned int tape_len
)
435 int speed
; /* deci-ips ! */
440 /* tape transport speed
441 * data rate: QIC-40 QIC-80 QIC-3010 QIC-3020
443 * 250 Kbps 25 ips n/a n/a n/a
444 * 500 Kbps 50 ips 34 ips 22.6 ips n/a
445 * 1 Mbps n/a 68 ips 45.2 ips 22.6 ips
446 * 2 Mbps n/a n/a n/a 45.2 ips
448 * fast tape transport speed is at least 68 ips.
452 speed
= (data_rate
== 250) ? 250 : 500;
455 speed
= (data_rate
== 500) ? 340 : 680;
457 case QIC_TAPE_QIC3010
:
458 speed
= (data_rate
== 500) ? 226 : 452;
460 case QIC_TAPE_QIC3020
:
461 speed
= (data_rate
== 1000) ? 226 : 452;
464 TRACE(ft_t_bug
, "Unknown qic_std (bug) ?");
468 if (ft_drive_type
.speed
== 0) {
470 static int dt
= 0; /* keep gcc from complaining */
471 static int first_time
= 1;
473 /* Measure the time it takes to wind to EOT and back to BOT.
474 * If the tape length is known, calculate the rewind speed.
475 * Else keep the time value for calculation of the rewind
476 * speed later on, when the length _is_ known.
477 * Ask for a report only when length and speed are both known.
484 dt
= (int) (((jiffies
- t0
) * FT_USPT
) / 1000);
486 dt
= 1; /* prevent div by zero on failures */
490 "trying to determine seek timeout, got %d msec",
494 ft_drive_type
.speed
=
495 (2 * 12 * tape_len
* 1000) / dt
;
496 TRACE(ft_t_warn
, "\n"
497 KERN_INFO
"==========================================\n"
498 KERN_INFO
"drive type: %s\n"
499 KERN_INFO
"delta time = %d ms, length = %d ft\n"
500 KERN_INFO
"has a maximum tape speed of %d ips\n"
501 KERN_INFO
"please report this to "THE_FTAPE_MAINTAINER
"\n"
502 KERN_INFO
"==========================================",
503 ft_drive_type
.name
, dt
, tape_len
,
504 ft_drive_type
.speed
);
507 /* Handle unknown length tapes as very long ones. We'll
508 * determine the actual length from a header segment later.
509 * This is normal for all modern (Wide,TR1/2/3) formats.
513 "Unknown tape length, using maximal timeouts");
514 length
= QIC_TOP_TAPE_LEN
; /* use worst case values */
516 length
= tape_len
; /* use actual values */
518 if (ft_drive_type
.speed
== 0) {
521 ff_speed
= ft_drive_type
.speed
;
523 /* time to go from bot to eot at normal speed (data rate):
524 * time = (1+delta) * length (ft) * 12 (inch/ft) / speed (ips)
525 * delta = 10 % for seek speed, 20 % for rewind speed.
527 ftape_timeout
.seek
= (length
* 132 * FT_SECOND
) / speed
;
528 ftape_timeout
.rewind
= (length
* 144 * FT_SECOND
) / (10 * ff_speed
);
529 ftape_timeout
.reset
= 20 * FT_SECOND
+ ftape_timeout
.rewind
;
530 TRACE(ft_t_noise
, "timeouts for speed = %d, length = %d\n"
531 KERN_INFO
"seek timeout : %d sec\n"
532 KERN_INFO
"rewind timeout: %d sec\n"
533 KERN_INFO
"reset timeout : %d sec",
535 (ftape_timeout
.seek
+ 500) / 1000,
536 (ftape_timeout
.rewind
+ 500) / 1000,
537 (ftape_timeout
.reset
+ 500) / 1000);
541 /* This function calibrates the datarate (i.e. determines the maximal
542 * usable data rate) and sets the global variable ft_qic_std to qic_std
545 int ftape_calibrate_data_rate(unsigned int qic_std
)
547 int rate
= ft_fdc_rate_limit
;
549 TRACE_FUN(ft_t_flow
);
551 ft_qic_std
= qic_std
;
553 if (ft_qic_std
== -1) {
554 TRACE_ABORT(-EIO
, ft_t_err
,
555 "Unable to determine data rate if QIC standard is unknown");
558 /* Select highest rate supported by both fdc and drive.
559 * Start with highest rate supported by the fdc.
561 while (fdc_set_data_rate(rate
) < 0 && rate
> 250) {
565 "Highest FDC supported data rate: %d Kbps", rate
);
566 ft_fdc_max_rate
= rate
;
568 result
= ftape_set_data_rate(rate
, ft_qic_std
);
569 } while (result
== -EINVAL
&& (rate
/= 2) > 250);
571 TRACE_ABORT(-EIO
, ft_t_err
, "set datarate failed");
577 static int ftape_init_drive(void)
581 unsigned int qic_std
;
582 unsigned int data_rate
;
583 TRACE_FUN(ft_t_flow
);
585 ftape_init_drive_needed
= 0; /* don't retry if this fails ? */
586 TRACE_CATCH(ftape_report_raw_drive_status(&status
),);
587 if (status
& QIC_STATUS_CARTRIDGE_PRESENT
) {
588 if (!(status
& QIC_STATUS_AT_BOT
)) {
589 /* Antique drives will get here after a soft reset,
590 * modern ones only if the driver is loaded when the
591 * tape wasn't rewound properly.
593 /* Tape should be at bot if new cartridge ! */
596 if (!(status
& QIC_STATUS_REFERENCED
)) {
597 TRACE(ft_t_flow
, "starting seek_load_point");
598 TRACE_CATCH(ftape_command_wait(QIC_SEEK_LOAD_POINT
,
603 ft_formatted
= (status
& QIC_STATUS_REFERENCED
) != 0;
605 TRACE(ft_t_warn
, "Warning: tape is not formatted !");
608 /* report configuration aborts when ftape_tape_len == -1
609 * unknown qic_std is okay if not formatted.
611 TRACE_CATCH(ftape_report_configuration(&model
,
616 /* Maybe add the following to the /proc entry
618 TRACE(ft_t_info
, "%s drive @ %d Kbps",
619 (model
== prehistoric
) ? "prehistoric" :
620 ((model
== pre_qic117c
) ? "pre QIC-117C" :
621 ((model
== post_qic117b
) ? "post QIC-117B" :
622 "post QIC-117D")), data_rate
);
625 /* initialize ft_used_data_rate to maximum value
628 TRACE_CATCH(ftape_calibrate_data_rate(qic_std
),);
629 if (ftape_tape_len
== 0) {
630 TRACE(ft_t_info
, "unknown length QIC-%s tape",
631 (ft_qic_std
== QIC_TAPE_QIC40
) ? "40" :
632 ((ft_qic_std
== QIC_TAPE_QIC80
) ? "80" :
633 ((ft_qic_std
== QIC_TAPE_QIC3010
)
634 ? "3010" : "3020")));
636 TRACE(ft_t_info
, "%d ft. QIC-%s tape", ftape_tape_len
,
637 (ft_qic_std
== QIC_TAPE_QIC40
) ? "40" :
638 ((ft_qic_std
== QIC_TAPE_QIC80
) ? "80" :
639 ((ft_qic_std
== QIC_TAPE_QIC3010
)
640 ? "3010" : "3020")));
642 ftape_calc_timeouts(ft_qic_std
, ft_data_rate
, ftape_tape_len
);
643 /* soft write-protect QIC-40/QIC-80 cartridges used with a
644 * Colorado T3000 drive. Buggy hardware!
646 if ((ft_drive_type
.vendor_id
== 0x011c6) &&
647 ((ft_qic_std
== QIC_TAPE_QIC40
||
648 ft_qic_std
== QIC_TAPE_QIC80
) &&
649 !ft_write_protected
)) {
650 TRACE(ft_t_warn
, "\n"
651 KERN_INFO
"The famous Colorado T3000 bug:\n"
652 KERN_INFO
"%s drives can't write QIC40 and QIC80\n"
653 KERN_INFO
"cartridges but don't set the write-protect flag!",
655 ft_write_protected
= 1;
658 /* Doesn't make too much sense to set the data rate
659 * because we don't know what to use for the write
661 * Need to do this again when formatting the cartridge.
663 ft_data_rate
= data_rate
;
664 ftape_calc_timeouts(QIC_TAPE_QIC40
,
668 ftape_new_cartridge();
672 static void ftape_munmap(void)
675 TRACE_FUN(ft_t_flow
);
677 for (i
= 0; i
< ft_nr_buffers
; i
++) {
678 ft_buffer
[i
]->mmapped
= 0;
683 /* Map the dma buffers into the virtual address range given by vma.
684 * We only check the caller doesn't map non-existent buffers. We
685 * don't check for multiple mappings.
687 int ftape_mmap(struct vm_area_struct
*vma
)
691 TRACE_FUN(ft_t_flow
);
696 if (!(vma
->vm_flags
& (VM_READ
|VM_WRITE
))) {
697 TRACE_ABORT(-EINVAL
, ft_t_err
, "Undefined mmap() access");
699 if (vma_get_pgoff(vma
) != 0) {
700 TRACE_ABORT(-EINVAL
, ft_t_err
, "page offset must be 0");
702 if ((vma
->vm_end
- vma
->vm_start
) % FT_BUFF_SIZE
!= 0) {
703 TRACE_ABORT(-EINVAL
, ft_t_err
,
704 "size = %ld, should be a multiple of %d",
705 vma
->vm_end
- vma
->vm_start
,
708 num_buffers
= (vma
->vm_end
- vma
->vm_start
) / FT_BUFF_SIZE
;
709 if (num_buffers
> ft_nr_buffers
) {
711 ft_t_err
, "size = %ld, should be less than %d",
712 vma
->vm_end
- vma
->vm_start
,
713 ft_nr_buffers
* FT_BUFF_SIZE
);
715 if (ft_driver_state
!= idle
) {
716 /* this also clears the buffer states
718 ftape_abort_operation();
720 ftape_reset_buffer();
722 for (i
= 0; i
< num_buffers
; i
++) {
725 pfn
= virt_to_phys(ft_buffer
[i
]->address
) >> PAGE_SHIFT
;
726 TRACE_CATCH(remap_pfn_range(vma
, vma
->vm_start
+
732 TRACE(ft_t_noise
, "remapped dma buffer @ %p to location @ %p",
733 ft_buffer
[i
]->address
,
734 (void *)(vma
->vm_start
+ i
* FT_BUFF_SIZE
));
736 for (i
= 0; i
< num_buffers
; i
++) {
737 memset(ft_buffer
[i
]->address
, 0xAA, FT_BUFF_SIZE
);
738 ft_buffer
[i
]->mmapped
++;
743 static void ftape_init_driver(void); /* forward declaration */
745 /* OPEN routine called by kernel-interface code
747 int ftape_enable(int drive_selection
)
751 if (ft_drive_sel
== -1 || ft_drive_sel
!= drive_selection
) {
752 /* Other selection than last time
756 ft_drive_sel
= FTAPE_SEL(drive_selection
);
758 TRACE_CATCH(fdc_init(),); /* init & detect fdc */
759 TRACE_CATCH(ftape_activate_drive(&ft_drive_type
),
761 fdc_release_irq_and_dma();
762 fdc_release_regions());
763 TRACE_CATCH(ftape_get_drive_status(), ftape_detach_drive());
764 if (ft_drive_type
.vendor_id
== UNKNOWN_VENDOR
) {
765 ftape_log_vendor_id();
768 ftape_init_drive_needed
= 1;
770 if (!ft_no_tape
&& ftape_init_drive_needed
) {
771 TRACE_CATCH(ftape_init_drive(), ftape_detach_drive());
773 ftape_munmap(); /* clear the mmap flag */
778 /* release routine called by the high level interface modules
781 void ftape_disable(void)
786 for (i
= 0; i
< ft_nr_buffers
; i
++) {
787 if (ft_buffer
[i
]->mmapped
) {
788 TRACE(ft_t_noise
, "first byte of buffer %d: 0x%02x",
789 i
, *ft_buffer
[i
]->address
);
792 if (sigtestsetmask(¤t
->pending
.signal
, _DONT_BLOCK
) &&
793 !(sigtestsetmask(¤t
->pending
.signal
, _NEVER_BLOCK
)) &&
794 ftape_tape_running
) {
796 "Interrupted by fatal signal and tape still running");
798 ftape_abort_operation(); /* it's annoying */
800 ftape_set_state(idle
);
802 ftape_detach_drive();
803 if (ft_history
.used
) {
804 TRACE(ft_t_info
, "== Non-fatal errors this run: ==");
805 TRACE(ft_t_info
, "fdc isr statistics:\n"
806 KERN_INFO
" id_am_errors : %3d\n"
807 KERN_INFO
" id_crc_errors : %3d\n"
808 KERN_INFO
" data_am_errors : %3d\n"
809 KERN_INFO
" data_crc_errors : %3d\n"
810 KERN_INFO
" overrun_errors : %3d\n"
811 KERN_INFO
" no_data_errors : %3d\n"
812 KERN_INFO
" retries : %3d",
813 ft_history
.id_am_errors
, ft_history
.id_crc_errors
,
814 ft_history
.data_am_errors
, ft_history
.data_crc_errors
,
815 ft_history
.overrun_errors
, ft_history
.no_data_errors
,
817 if (ft_history
.used
& 1) {
818 TRACE(ft_t_info
, "ecc statistics:\n"
819 KERN_INFO
" crc_errors : %3d\n"
820 KERN_INFO
" crc_failures : %3d\n"
821 KERN_INFO
" ecc_failures : %3d\n"
822 KERN_INFO
" sectors corrected: %3d",
823 ft_history
.crc_errors
, ft_history
.crc_failures
,
824 ft_history
.ecc_failures
, ft_history
.corrected
);
826 if (ft_history
.defects
> 0) {
827 TRACE(ft_t_warn
, "Warning: %d media defects!",
830 if (ft_history
.rewinds
> 0) {
831 TRACE(ft_t_info
, "tape motion statistics:\n"
832 KERN_INFO
"repositions : %3d",
840 static void ftape_init_driver(void)
842 TRACE_FUN(ft_t_flow
);
844 ft_drive_type
.vendor_id
= UNKNOWN_VENDOR
;
845 ft_drive_type
.speed
= 0;
846 ft_drive_type
.wake_up
= unknown_wake_up
;
847 ft_drive_type
.name
= "Unknown";
849 ftape_timeout
.seek
= 650 * FT_SECOND
;
850 ftape_timeout
.reset
= 670 * FT_SECOND
;
851 ftape_timeout
.rewind
= 650 * FT_SECOND
;
852 ftape_timeout
.head_seek
= 15 * FT_SECOND
;
853 ftape_timeout
.stop
= 5 * FT_SECOND
;
854 ftape_timeout
.pause
= 16 * FT_SECOND
;
857 ftape_tape_len
= 0; /* unknown */
858 ftape_current_command
= 0;
859 ftape_current_cylinder
= -1;
861 ft_segments_per_track
= 102;
862 ftape_segments_per_head
= 1020;
863 ftape_segments_per_cylinder
= 4;
864 ft_tracks_per_tape
= 20;
870 ft_write_protected
= 1;
873 ft_driver_state
= idle
;
876 ft_fdc_max_rate
= 500;
877 ft_drive_max_rate
= 0; /* triggers set_rate_test() */
879 ftape_init_drive_needed
= 1;
881 ft_header_segment_1
= -1;
882 ft_header_segment_2
= -1;
883 ft_used_header_segment
= -1;
884 ft_first_data_segment
= -1;
885 ft_last_data_segment
= -1;
887 ft_location
.track
= -1;
888 ft_location
.known
= 0;
890 ftape_tape_running
= 0;
891 ftape_might_be_off_track
= 1;
893 ftape_new_cartridge(); /* init some tape related variables */