aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ftape/lowlevel
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ftape/lowlevel')
-rw-r--r--drivers/char/ftape/lowlevel/Makefile43
-rw-r--r--drivers/char/ftape/lowlevel/fc-10.c175
-rw-r--r--drivers/char/ftape/lowlevel/fc-10.h39
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c1349
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.h252
-rw-r--r--drivers/char/ftape/lowlevel/fdc-isr.c1170
-rw-r--r--drivers/char/ftape/lowlevel/fdc-isr.h55
-rw-r--r--drivers/char/ftape/lowlevel/ftape-bsm.c491
-rw-r--r--drivers/char/ftape/lowlevel/ftape-bsm.h66
-rw-r--r--drivers/char/ftape/lowlevel/ftape-buffer.c130
-rw-r--r--drivers/char/ftape/lowlevel/ftape-buffer.h32
-rw-r--r--drivers/char/ftape/lowlevel/ftape-calibr.c275
-rw-r--r--drivers/char/ftape/lowlevel/ftape-calibr.h37
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ctl.c896
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ctl.h162
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ecc.c853
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ecc.h84
-rw-r--r--drivers/char/ftape/lowlevel/ftape-format.c344
-rw-r--r--drivers/char/ftape/lowlevel/ftape-format.h37
-rw-r--r--drivers/char/ftape/lowlevel/ftape-init.c160
-rw-r--r--drivers/char/ftape/lowlevel/ftape-init.h43
-rw-r--r--drivers/char/ftape/lowlevel/ftape-io.c992
-rw-r--r--drivers/char/ftape/lowlevel/ftape-io.h90
-rw-r--r--drivers/char/ftape/lowlevel/ftape-proc.c214
-rw-r--r--drivers/char/ftape/lowlevel/ftape-proc.h35
-rw-r--r--drivers/char/ftape/lowlevel/ftape-read.c621
-rw-r--r--drivers/char/ftape/lowlevel/ftape-read.h51
-rw-r--r--drivers/char/ftape/lowlevel/ftape-rw.c1092
-rw-r--r--drivers/char/ftape/lowlevel/ftape-rw.h111
-rw-r--r--drivers/char/ftape/lowlevel/ftape-setup.c104
-rw-r--r--drivers/char/ftape/lowlevel/ftape-tracing.c118
-rw-r--r--drivers/char/ftape/lowlevel/ftape-tracing.h179
-rw-r--r--drivers/char/ftape/lowlevel/ftape-write.c336
-rw-r--r--drivers/char/ftape/lowlevel/ftape-write.h53
-rw-r--r--drivers/char/ftape/lowlevel/ftape_syms.c87
35 files changed, 0 insertions, 10776 deletions
diff --git a/drivers/char/ftape/lowlevel/Makefile b/drivers/char/ftape/lowlevel/Makefile
deleted file mode 100644
index febab07ba427..000000000000
--- a/drivers/char/ftape/lowlevel/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
1#
2# Copyright (C) 1996, 1997 Clau-Justus Heine.
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2, or (at your option)
7# any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; see the file COPYING. If not, write to
16# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17#
18# $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/Makefile,v $
19# $Revision: 1.4 $
20# $Date: 1997/10/07 09:26:02 $
21#
22# Makefile for the lowlevel part QIC-40/80/3010/3020 floppy-tape
23# driver for Linux.
24#
25
26obj-$(CONFIG_FTAPE) += ftape.o
27
28ftape-objs := ftape-init.o fdc-io.o fdc-isr.o \
29 ftape-bsm.o ftape-ctl.o ftape-read.o ftape-rw.o \
30 ftape-write.o ftape-io.o ftape-calibr.o ftape-ecc.o fc-10.o \
31 ftape-buffer.o ftape-format.o ftape_syms.o
32
33ifeq ($(CONFIG_FTAPE),y)
34ftape-objs += ftape-setup.o
35endif
36
37ifndef CONFIG_FT_NO_TRACE_AT_ALL
38ftape-objs += ftape-tracing.o
39endif
40
41ifeq ($(CONFIG_FT_PROC_FS),y)
42ftape-objs += ftape-proc.o
43endif
diff --git a/drivers/char/ftape/lowlevel/fc-10.c b/drivers/char/ftape/lowlevel/fc-10.c
deleted file mode 100644
index 9bc1cddade76..000000000000
--- a/drivers/char/ftape/lowlevel/fc-10.c
+++ /dev/null
@@ -1,175 +0,0 @@
1/*
2 *
3
4 Copyright (C) 1993,1994 Jon Tombs.
5
6 This program is distributed in the hope that it will be useful,
7 but WITHOUT ANY WARRANTY; without even the implied warranty of
8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 GNU General Public License for more details.
10
11 The entire guts of this program was written by dosemu, modified to
12 record reads and writes to the ports in the 0x180-0x188 address space,
13 while running the CMS program TAPE.EXE V2.0.5 supplied with the drive.
14
15 Modified to use an array of addresses and generally cleaned up (made
16 much shorter) 4 June 94, dosemu isn't that good at writing short code it
17 would seem :-). Made independent of 0x180, but I doubt it will work
18 at any other address.
19
20 Modified for distribution with ftape source. 21 June 94, SJL.
21
22 Modifications on 20 October 95, by Daniel Cohen (catman@wpi.edu):
23 Modified to support different DMA, IRQ, and IO Ports. Borland's
24 Turbo Debugger in virtual 8086 mode (TD386.EXE with hardware breakpoints
25 provided by the TDH386.SYS Device Driver) was used on the CMS program
26 TAPE V4.0.5. I set breakpoints on I/O to ports 0x180-0x187. Note that
27 CMS's program will not successfully configure the tape drive if you set
28 breakpoints on IO Reads, but you can set them on IO Writes without problems.
29 Known problems:
30 - You can not use DMA Channels 5 or 7.
31
32 Modification on 29 January 96, by Daniel Cohen (catman@wpi.edu):
33 Modified to only accept IRQs 3 - 7, or 9. Since we can only send a 3 bit
34 number representing the IRQ to the card, special handling is required when
35 IRQ 9 is selected. IRQ 2 and 9 are the same, and we should request IRQ 9
36 from the kernel while telling the card to use IRQ 2. Thanks to Greg
37 Crider (gcrider@iclnet.org) for finding and locating this bug, as well as
38 testing the patch.
39
40 Modification on 11 December 96, by Claus Heine (claus@momo.math.rwth-aachen.de):
41 Modified a little to use variahle ft_fdc_base, ft_fdc_irq, ft_fdc_dma
42 instead of preprocessor symbols. Thus we can compile this into the module
43 or kernel and let the user specify the options as command line arguments.
44
45 *
46 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.c,v $
47 * $Revision: 1.2 $
48 * $Date: 1997/10/05 19:18:04 $
49 *
50 * This file contains code for the CMS FC-10/FC-20 card.
51 */
52
53#include <asm/io.h>
54#include <linux/ftape.h>
55#include "../lowlevel/ftape-tracing.h"
56#include "../lowlevel/fdc-io.h"
57#include "../lowlevel/fc-10.h"
58
59static __u16 inbs_magic[] = {
60 0x3, 0x3, 0x0, 0x4, 0x7, 0x2, 0x5, 0x3, 0x1, 0x4,
61 0x3, 0x5, 0x2, 0x0, 0x3, 0x7, 0x4, 0x2,
62 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
63};
64
65static __u16 fc10_ports[] = {
66 0x180, 0x210, 0x2A0, 0x300, 0x330, 0x340, 0x370
67};
68
69int fc10_enable(void)
70{
71 int i;
72 __u8 cardConfig = 0x00;
73 __u8 x;
74 TRACE_FUN(ft_t_flow);
75
76/* This code will only work if the FC-10 (or FC-20) is set to
77 * use DMA channels 1, 2, or 3. DMA channels 5 and 7 seem to be
78 * initialized by the same command as channels 1 and 3, respectively.
79 */
80 if (ft_fdc_dma > 3) {
81 TRACE_ABORT(0, ft_t_err,
82"Error: The FC-10/20 must be set to use DMA channels 1, 2, or 3!");
83 }
84/* Only allow the FC-10/20 to use IRQ 3-7, or 9. Note that CMS's program
85 * only accepts IRQ's 2-7, but in linux, IRQ 2 is the same as IRQ 9.
86 */
87 if (ft_fdc_irq < 3 || ft_fdc_irq == 8 || ft_fdc_irq > 9) {
88 TRACE_ABORT(0, ft_t_err,
89"Error: The FC-10/20 must be set to use IRQ levels 3 - 7, or 9!\n"
90KERN_INFO "Note: IRQ 9 is the same as IRQ 2");
91 }
92 /* Clear state machine ???
93 */
94 for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
95 inb(ft_fdc_base + inbs_magic[i]);
96 }
97 outb(0x0, ft_fdc_base);
98
99 x = inb(ft_fdc_base);
100 if (x == 0x13 || x == 0x93) {
101 for (i = 1; i < 8; i++) {
102 if (inb(ft_fdc_base + i) != x) {
103 TRACE_EXIT 0;
104 }
105 }
106 } else {
107 TRACE_EXIT 0;
108 }
109
110 outb(0x8, ft_fdc_base);
111
112 for (i = 0; i < 8; i++) {
113 if (inb(ft_fdc_base + i) != 0x0) {
114 TRACE_EXIT 0;
115 }
116 }
117 outb(0x10, ft_fdc_base);
118
119 for (i = 0; i < 8; i++) {
120 if (inb(ft_fdc_base + i) != 0xff) {
121 TRACE_EXIT 0;
122 }
123 }
124
125 /* Okay, we found a FC-10 card ! ???
126 */
127 outb(0x0, fdc.ccr);
128
129 /* Clear state machine again ???
130 */
131 for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
132 inb(ft_fdc_base + inbs_magic[i]);
133 }
134 /* Send io port */
135 for (i = 0; i < NR_ITEMS(fc10_ports); i++)
136 if (ft_fdc_base == fc10_ports[i])
137 cardConfig = i + 1;
138 if (cardConfig == 0) {
139 TRACE_EXIT 0; /* Invalid I/O Port */
140 }
141 /* and IRQ - If using IRQ 9, tell the FC card it is actually IRQ 2 */
142 if (ft_fdc_irq != 9)
143 cardConfig |= ft_fdc_irq << 3;
144 else
145 cardConfig |= 2 << 3;
146
147 /* and finally DMA Channel */
148 cardConfig |= ft_fdc_dma << 6;
149 outb(cardConfig, ft_fdc_base); /* DMA [2 bits]/IRQ [3 bits]/BASE [3 bits] */
150
151 /* Enable FC-10 ???
152 */
153 outb(0, fdc.ccr);
154 outb(0, fdc.dor2);
155 outb(FDC_DMA_MODE /* 8 */, fdc.dor);
156 outb(FDC_DMA_MODE /* 8 */, fdc.dor);
157 outb(1, fdc.dor2);
158
159 /*************************************
160 *
161 * cH: why the hell should this be necessary? This is done
162 * by fdc_reset()!!!
163 *
164 *************************************/
165 /* Initialize fdc, select drive B:
166 */
167 outb(FDC_DMA_MODE, fdc.dor); /* assert reset, dma & irq enabled */
168 /* 0x08 */
169 outb(FDC_DMA_MODE|FDC_RESET_NOT, fdc.dor); /* release reset */
170 /* 0x08 | 0x04 = 0x0c */
171 outb(FDC_DMA_MODE|FDC_RESET_NOT|FDC_MOTOR_1|FTAPE_SEL_B, fdc.dor);
172 /* 0x08 | 0x04 | 0x20 | 0x01 = 0x2d */
173 /* select drive 1 */ /* why not drive 0 ???? */
174 TRACE_EXIT (x == 0x93) ? 2 : 1;
175}
diff --git a/drivers/char/ftape/lowlevel/fc-10.h b/drivers/char/ftape/lowlevel/fc-10.h
deleted file mode 100644
index da7b88bca889..000000000000
--- a/drivers/char/ftape/lowlevel/fc-10.h
+++ /dev/null
@@ -1,39 +0,0 @@
1#ifndef _FC_10_H
2#define _FC_10_H
3
4/*
5 * Copyright (C) 1994-1996 Bas Laarhoven.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.h,v $
23 * $Revision: 1.1 $
24 * $Date: 1997/09/19 09:05:22 $
25 *
26 * This file contains definitions for the FC-10 code
27 * of the QIC-40/80 floppy-tape driver for Linux.
28 */
29
30/*
31 * fc-10.c defined global vars.
32 */
33
34/*
35 * fc-10.c defined global functions.
36 */
37extern int fc10_enable(void);
38
39#endif
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
deleted file mode 100644
index bbcf918f056f..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ /dev/null
@@ -1,1349 +0,0 @@
1/*
2 * Copyright (C) 1993-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-io.c,v $
21 * $Revision: 1.7.4.2 $
22 * $Date: 1997/11/16 14:48:17 $
23 *
24 * This file contains the low-level floppy disk interface code
25 * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for
26 * Linux.
27 */
28
29#include <linux/errno.h>
30#include <linux/sched.h>
31#include <linux/ioport.h>
32#include <linux/interrupt.h>
33#include <linux/kernel.h>
34#include <asm/system.h>
35#include <asm/io.h>
36#include <asm/dma.h>
37#include <asm/irq.h>
38
39#include <linux/ftape.h>
40#include <linux/qic117.h>
41#include "../lowlevel/ftape-tracing.h"
42#include "../lowlevel/fdc-io.h"
43#include "../lowlevel/fdc-isr.h"
44#include "../lowlevel/ftape-io.h"
45#include "../lowlevel/ftape-rw.h"
46#include "../lowlevel/ftape-ctl.h"
47#include "../lowlevel/ftape-calibr.h"
48#include "../lowlevel/fc-10.h"
49
50/* Global vars.
51 */
52static int ftape_motor;
53volatile int ftape_current_cylinder = -1;
54volatile fdc_mode_enum fdc_mode = fdc_idle;
55fdc_config_info fdc;
56DECLARE_WAIT_QUEUE_HEAD(ftape_wait_intr);
57
58unsigned int ft_fdc_base = CONFIG_FT_FDC_BASE;
59unsigned int ft_fdc_irq = CONFIG_FT_FDC_IRQ;
60unsigned int ft_fdc_dma = CONFIG_FT_FDC_DMA;
61unsigned int ft_fdc_threshold = CONFIG_FT_FDC_THR; /* bytes */
62unsigned int ft_fdc_rate_limit = CONFIG_FT_FDC_MAX_RATE; /* bits/sec */
63int ft_probe_fc10 = CONFIG_FT_PROBE_FC10;
64int ft_mach2 = CONFIG_FT_MACH2;
65
66/* Local vars.
67 */
68static spinlock_t fdc_io_lock;
69static unsigned int fdc_calibr_count;
70static unsigned int fdc_calibr_time;
71static int fdc_status;
72volatile __u8 fdc_head; /* FDC head from sector id */
73volatile __u8 fdc_cyl; /* FDC track from sector id */
74volatile __u8 fdc_sect; /* FDC sector from sector id */
75static int fdc_data_rate = 500; /* data rate (Kbps) */
76static int fdc_rate_code; /* data rate code (0 == 500 Kbps) */
77static int fdc_seek_rate = 2; /* step rate (msec) */
78static void (*do_ftape) (void);
79static int fdc_fifo_state; /* original fifo setting - fifo enabled */
80static int fdc_fifo_thr; /* original fifo setting - threshold */
81static int fdc_lock_state; /* original lock setting - locked */
82static int fdc_fifo_locked; /* has fifo && lock set ? */
83static __u8 fdc_precomp; /* default precomp. value (nsec) */
84static __u8 fdc_prec_code; /* fdc precomp. select code */
85
86static char ftape_id[] = "ftape"; /* used by request irq and free irq */
87
88static int fdc_set_seek_rate(int seek_rate);
89
90void fdc_catch_stray_interrupts(int count)
91{
92 unsigned long flags;
93
94 spin_lock_irqsave(&fdc_io_lock, flags);
95 if (count == 0) {
96 ft_expected_stray_interrupts = 0;
97 } else {
98 ft_expected_stray_interrupts += count;
99 }
100 spin_unlock_irqrestore(&fdc_io_lock, flags);
101}
102
103/* Wait during a timeout period for a given FDC status.
104 * If usecs == 0 then just test status, else wait at least for usecs.
105 * Returns -ETIME on timeout. Function must be calibrated first !
106 */
107static int fdc_wait(unsigned int usecs, __u8 mask, __u8 state)
108{
109 int count_1 = (fdc_calibr_count * usecs +
110 fdc_calibr_count - 1) / fdc_calibr_time;
111
112 do {
113 fdc_status = inb_p(fdc.msr);
114 if ((fdc_status & mask) == state) {
115 return 0;
116 }
117 } while (count_1-- >= 0);
118 return -ETIME;
119}
120
121int fdc_ready_wait(unsigned int usecs)
122{
123 return fdc_wait(usecs, FDC_DATA_READY | FDC_BUSY, FDC_DATA_READY);
124}
125
126/* Why can't we just use udelay()?
127 */
128static void fdc_usec_wait(unsigned int usecs)
129{
130 fdc_wait(usecs, 0, 1); /* will always timeout ! */
131}
132
133static int fdc_ready_out_wait(unsigned int usecs)
134{
135 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
136 return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);
137}
138
139void fdc_wait_calibrate(void)
140{
141 ftape_calibrate("fdc_wait",
142 fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time);
143}
144
145/* Wait for a (short) while for the FDC to become ready
146 * and transfer the next command byte.
147 * Return -ETIME on timeout on getting ready (depends on hardware!).
148 */
149static int fdc_write(const __u8 data)
150{
151 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
152 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) {
153 return -ETIME;
154 } else {
155 outb(data, fdc.fifo);
156 return 0;
157 }
158}
159
160/* Wait for a (short) while for the FDC to become ready
161 * and transfer the next result byte.
162 * Return -ETIME if timeout on getting ready (depends on hardware!).
163 */
164static int fdc_read(__u8 * data)
165{
166 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
167 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) {
168 return -ETIME;
169 } else {
170 *data = inb(fdc.fifo);
171 return 0;
172 }
173}
174
175/* Output a cmd_len long command string to the FDC.
176 * The FDC should be ready to receive a new command or
177 * an error (EBUSY or ETIME) will occur.
178 */
179int fdc_command(const __u8 * cmd_data, int cmd_len)
180{
181 int result = 0;
182 unsigned long flags;
183 int count = cmd_len;
184 int retry = 0;
185#ifdef TESTING
186 static unsigned int last_time;
187 unsigned int time;
188#endif
189 TRACE_FUN(ft_t_any);
190
191 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
192 spin_lock_irqsave(&fdc_io_lock, flags);
193 if (!in_interrupt())
194 /* Yes, I know, too much comments inside this function
195 * ...
196 *
197 * Yet another bug in the original driver. All that
198 * havoc is caused by the fact that the isr() sends
199 * itself a command to the floppy tape driver (pause,
200 * micro step pause). Now, the problem is that
201 * commands are transmitted via the fdc_seek
202 * command. But: the fdc performs seeks in the
203 * background i.e. it doesn't signal busy while
204 * sending the step pulses to the drive. Therefore the
205 * non-interrupt level driver has no chance to tell
206 * whether the isr() just has issued a seek. Therefore
207 * we HAVE TO have a look at the ft_hide_interrupt
208 * flag: it signals the non-interrupt level part of
209 * the driver that it has to wait for the fdc until it
210 * has completet seeking.
211 *
212 * THIS WAS PRESUMABLY THE REASON FOR ALL THAT
213 * "fdc_read timeout" errors, I HOPE :-)
214 */
215 if (ft_hide_interrupt) {
216 restore_flags(flags);
217 TRACE(ft_t_info,
218 "Waiting for the isr() completing fdc_seek()");
219 if (fdc_interrupt_wait(2 * FT_SECOND) < 0) {
220 TRACE(ft_t_warn,
221 "Warning: timeout waiting for isr() seek to complete");
222 }
223 if (ft_hide_interrupt || !ft_seek_completed) {
224 /* There cannot be another
225 * interrupt. The isr() only stops
226 * the tape and the next interrupt
227 * won't come until we have send our
228 * command to the drive.
229 */
230 TRACE_ABORT(-EIO, ft_t_bug,
231 "BUG? isr() is still seeking?\n"
232 KERN_INFO "hide: %d\n"
233 KERN_INFO "seek: %d",
234 ft_hide_interrupt,
235 ft_seek_completed);
236
237 }
238 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
239 spin_lock_irqsave(&fdc_io_lock, flags);
240 }
241 fdc_status = inb(fdc.msr);
242 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {
243 spin_unlock_irqrestore(&fdc_io_lock, flags);
244 TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");
245 }
246 fdc_mode = *cmd_data; /* used by isr */
247#ifdef TESTING
248 if (fdc_mode == FDC_SEEK) {
249 time = ftape_timediff(last_time, ftape_timestamp());
250 if (time < 6000) {
251 TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d",
252 time);
253 }
254 }
255#endif
256 if (!in_interrupt()) {
257 /* shouldn't be cleared if called from isr
258 */
259 ft_interrupt_seen = 0;
260 }
261 while (count) {
262 result = fdc_write(*cmd_data);
263 if (result < 0) {
264 TRACE(ft_t_fdc_dma,
265 "fdc_mode = %02x, status = %02x at index %d",
266 (int) fdc_mode, (int) fdc_status,
267 cmd_len - count);
268 if (++retry <= 3) {
269 TRACE(ft_t_warn, "fdc_write timeout, retry");
270 } else {
271 TRACE(ft_t_err, "fdc_write timeout, fatal");
272 /* recover ??? */
273 break;
274 }
275 } else {
276 --count;
277 ++cmd_data;
278 }
279 }
280#ifdef TESTING
281 if (fdc_mode == FDC_SEEK) {
282 last_time = ftape_timestamp();
283 }
284#endif
285 spin_unlock_irqrestore(&fdc_io_lock, flags);
286 TRACE_EXIT result;
287}
288
289/* Input a res_len long result string from the FDC.
290 * The FDC should be ready to send the result or an error
291 * (EBUSY or ETIME) will occur.
292 */
293int fdc_result(__u8 * res_data, int res_len)
294{
295 int result = 0;
296 unsigned long flags;
297 int count = res_len;
298 int retry = 0;
299 TRACE_FUN(ft_t_any);
300
301 spin_lock_irqsave(&fdc_io_lock, flags);
302 fdc_status = inb(fdc.msr);
303 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {
304 TRACE(ft_t_err, "fdc not ready");
305 result = -EBUSY;
306 } else while (count) {
307 if (!(fdc_status & FDC_BUSY)) {
308 spin_unlock_irqrestore(&fdc_io_lock, flags);
309 TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");
310 }
311 result = fdc_read(res_data);
312 if (result < 0) {
313 TRACE(ft_t_fdc_dma,
314 "fdc_mode = %02x, status = %02x at index %d",
315 (int) fdc_mode,
316 (int) fdc_status,
317 res_len - count);
318 if (++retry <= 3) {
319 TRACE(ft_t_warn, "fdc_read timeout, retry");
320 } else {
321 TRACE(ft_t_err, "fdc_read timeout, fatal");
322 /* recover ??? */
323 break;
324 ++retry;
325 }
326 } else {
327 --count;
328 ++res_data;
329 }
330 }
331 spin_unlock_irqrestore(&fdc_io_lock, flags);
332 fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */
333 TRACE_EXIT result;
334}
335
336/* Handle command and result phases for
337 * commands without data phase.
338 */
339static int fdc_issue_command(const __u8 * out_data, int out_count,
340 __u8 * in_data, int in_count)
341{
342 TRACE_FUN(ft_t_any);
343
344 if (out_count > 0) {
345 TRACE_CATCH(fdc_command(out_data, out_count),);
346 }
347 /* will take 24 - 30 usec for fdc_sense_drive_status and
348 * fdc_sense_interrupt_status commands.
349 * 35 fails sometimes (5/9/93 SJL)
350 * On a loaded system it incidentally takes longer than
351 * this for the fdc to get ready ! ?????? WHY ??????
352 * So until we know what's going on use a very long timeout.
353 */
354 TRACE_CATCH(fdc_ready_out_wait(500 /* usec */),);
355 if (in_count > 0) {
356 TRACE_CATCH(fdc_result(in_data, in_count),
357 TRACE(ft_t_err, "result phase aborted"));
358 }
359 TRACE_EXIT 0;
360}
361
362/* Wait for FDC interrupt with timeout (in milliseconds).
363 * Signals are blocked so the wait will not be aborted.
364 * Note: interrupts must be enabled ! (23/05/93 SJL)
365 */
366int fdc_interrupt_wait(unsigned int time)
367{
368 DECLARE_WAITQUEUE(wait,current);
369 sigset_t old_sigmask;
370 static int resetting;
371 long timeout;
372
373 TRACE_FUN(ft_t_fdc_dma);
374
375 if (waitqueue_active(&ftape_wait_intr)) {
376 TRACE_ABORT(-EIO, ft_t_err, "error: nested call");
377 }
378 /* timeout time will be up to USPT microseconds too long ! */
379 timeout = (1000 * time + FT_USPT - 1) / FT_USPT;
380
381 spin_lock_irq(&current->sighand->siglock);
382 old_sigmask = current->blocked;
383 sigfillset(&current->blocked);
384 recalc_sigpending();
385 spin_unlock_irq(&current->sighand->siglock);
386
387 set_current_state(TASK_INTERRUPTIBLE);
388 add_wait_queue(&ftape_wait_intr, &wait);
389 while (!ft_interrupt_seen && timeout)
390 timeout = schedule_timeout_interruptible(timeout);
391
392 spin_lock_irq(&current->sighand->siglock);
393 current->blocked = old_sigmask;
394 recalc_sigpending();
395 spin_unlock_irq(&current->sighand->siglock);
396
397 remove_wait_queue(&ftape_wait_intr, &wait);
398 /* the following IS necessary. True: as well
399 * wake_up_interruptible() as the schedule() set TASK_RUNNING
400 * when they wakeup a task, BUT: it may very well be that
401 * ft_interrupt_seen is already set to 1 when we enter here
402 * in which case schedule() gets never called, and
403 * TASK_RUNNING never set. This has the funny effect that we
404 * execute all the code until we leave kernel space, but then
405 * the task is stopped (a task CANNOT be preempted while in
406 * kernel mode. Sending a pair of SIGSTOP/SIGCONT to the
407 * tasks wakes it up again. Funny! :-)
408 */
409 current->state = TASK_RUNNING;
410 if (ft_interrupt_seen) { /* woken up by interrupt */
411 ft_interrupt_seen = 0;
412 TRACE_EXIT 0;
413 }
414 /* Original comment:
415 * In first instance, next statement seems unnecessary since
416 * it will be cleared in fdc_command. However, a small part of
417 * the software seems to rely on this being cleared here
418 * (ftape_close might fail) so stick to it until things get fixed !
419 */
420 /* My deeply sought of knowledge:
421 * Behold NO! It is obvious. fdc_reset() doesn't call fdc_command()
422 * but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to
423 * be reset here.
424 */
425 ft_interrupt_seen = 0; /* clear for next call */
426 if (!resetting) {
427 resetting = 1; /* break infinite recursion if reset fails */
428 TRACE(ft_t_any, "cleanup reset");
429 fdc_reset();
430 resetting = 0;
431 }
432 TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;
433}
434
435/* Start/stop drive motor. Enable DMA mode.
436 */
437void fdc_motor(int motor)
438{
439 int unit = ft_drive_sel;
440 int data = unit | FDC_RESET_NOT | FDC_DMA_MODE;
441 TRACE_FUN(ft_t_any);
442
443 ftape_motor = motor;
444 if (ftape_motor) {
445 data |= FDC_MOTOR_0 << unit;
446 TRACE(ft_t_noise, "turning motor %d on", unit);
447 } else {
448 TRACE(ft_t_noise, "turning motor %d off", unit);
449 }
450 if (ft_mach2) {
451 outb_p(data, fdc.dor2);
452 } else {
453 outb_p(data, fdc.dor);
454 }
455 ftape_sleep(10 * FT_MILLISECOND);
456 TRACE_EXIT;
457}
458
459static void fdc_update_dsr(void)
460{
461 TRACE_FUN(ft_t_any);
462
463 TRACE(ft_t_flow, "rate = %d Kbps, precomp = %d ns",
464 fdc_data_rate, fdc_precomp);
465 if (fdc.type >= i82077) {
466 outb_p((fdc_rate_code & 0x03) | fdc_prec_code, fdc.dsr);
467 } else {
468 outb_p(fdc_rate_code & 0x03, fdc.ccr);
469 }
470 TRACE_EXIT;
471}
472
473void fdc_set_write_precomp(int precomp)
474{
475 TRACE_FUN(ft_t_any);
476
477 TRACE(ft_t_noise, "New precomp: %d nsec", precomp);
478 fdc_precomp = precomp;
479 /* write precompensation can be set in multiples of 41.67 nsec.
480 * round the parameter to the nearest multiple and convert it
481 * into a fdc setting. Note that 0 means default to the fdc,
482 * 7 is used instead of that.
483 */
484 fdc_prec_code = ((fdc_precomp + 21) / 42) << 2;
485 if (fdc_prec_code == 0 || fdc_prec_code > (6 << 2)) {
486 fdc_prec_code = 7 << 2;
487 }
488 fdc_update_dsr();
489 TRACE_EXIT;
490}
491
492/* Reprogram the 82078 registers to use Data Rate Table 1 on all drives.
493 */
494static void fdc_set_drive_specs(void)
495{
496 __u8 cmd[] = { FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};
497 int result;
498 TRACE_FUN(ft_t_any);
499
500 TRACE(ft_t_flow, "Setting of drive specs called");
501 if (fdc.type >= i82078_1) {
502 cmd[1] = (0 << 5) | (2 << 2);
503 cmd[2] = (1 << 5) | (2 << 2);
504 cmd[3] = (2 << 5) | (2 << 2);
505 cmd[4] = (3 << 5) | (2 << 2);
506 result = fdc_command(cmd, NR_ITEMS(cmd));
507 if (result < 0) {
508 TRACE(ft_t_err, "Setting of drive specs failed");
509 }
510 }
511 TRACE_EXIT;
512}
513
514/* Select clock for fdc, must correspond with tape drive setting !
515 * This also influences the fdc timing so we must adjust some values.
516 */
517int fdc_set_data_rate(int rate)
518{
519 int bad_rate = 0;
520 TRACE_FUN(ft_t_any);
521
522 /* Select clock for fdc, must correspond with tape drive setting !
523 * This also influences the fdc timing so we must adjust some values.
524 */
525 TRACE(ft_t_fdc_dma, "new rate = %d", rate);
526 switch (rate) {
527 case 250:
528 fdc_rate_code = fdc_data_rate_250;
529 break;
530 case 500:
531 fdc_rate_code = fdc_data_rate_500;
532 break;
533 case 1000:
534 if (fdc.type < i82077) {
535 bad_rate = 1;
536 } else {
537 fdc_rate_code = fdc_data_rate_1000;
538 }
539 break;
540 case 2000:
541 if (fdc.type < i82078_1) {
542 bad_rate = 1;
543 } else {
544 fdc_rate_code = fdc_data_rate_2000;
545 }
546 break;
547 default:
548 bad_rate = 1;
549 }
550 if (bad_rate) {
551 TRACE_ABORT(-EIO,
552 ft_t_fdc_dma, "%d is not a valid data rate", rate);
553 }
554 fdc_data_rate = rate;
555 fdc_update_dsr();
556 fdc_set_seek_rate(fdc_seek_rate); /* clock changed! */
557 ftape_udelay(1000);
558 TRACE_EXIT 0;
559}
560
561/* keep the unit select if keep_select is != 0,
562 */
563static void fdc_dor_reset(int keep_select)
564{
565 __u8 fdc_ctl = ft_drive_sel;
566
567 if (keep_select != 0) {
568 fdc_ctl |= FDC_DMA_MODE;
569 if (ftape_motor) {
570 fdc_ctl |= FDC_MOTOR_0 << ft_drive_sel;
571 }
572 }
573 ftape_udelay(10); /* ??? but seems to be necessary */
574 if (ft_mach2) {
575 outb_p(fdc_ctl & 0x0f, fdc.dor);
576 outb_p(fdc_ctl, fdc.dor2);
577 } else {
578 outb_p(fdc_ctl, fdc.dor);
579 }
580 fdc_usec_wait(10); /* delay >= 14 fdc clocks */
581 if (keep_select == 0) {
582 fdc_ctl = 0;
583 }
584 fdc_ctl |= FDC_RESET_NOT;
585 if (ft_mach2) {
586 outb_p(fdc_ctl & 0x0f, fdc.dor);
587 outb_p(fdc_ctl, fdc.dor2);
588 } else {
589 outb_p(fdc_ctl, fdc.dor);
590 }
591}
592
593/* Reset the floppy disk controller. Leave the ftape_unit selected.
594 */
595void fdc_reset(void)
596{
597 int st0;
598 int i;
599 int dummy;
600 unsigned long flags;
601 TRACE_FUN(ft_t_any);
602
603 spin_lock_irqsave(&fdc_io_lock, flags);
604
605 fdc_dor_reset(1); /* keep unit selected */
606
607 fdc_mode = fdc_idle;
608
609 /* maybe the spin_lock_irq* pair is not necessary, BUT:
610 * the following line MUST be here. Otherwise fdc_interrupt_wait()
611 * won't wait. Note that fdc_reset() is called from
612 * ftape_dumb_stop() when the fdc is busy transferring data. In this
613 * case fdc_isr() MOST PROBABLY sets ft_interrupt_seen, and tries
614 * to get the result bytes from the fdc etc. CLASH.
615 */
616 ft_interrupt_seen = 0;
617
618 /* Program data rate
619 */
620 fdc_update_dsr(); /* restore data rate and precomp */
621
622 spin_unlock_irqrestore(&fdc_io_lock, flags);
623
624 /*
625 * Wait for first polling cycle to complete
626 */
627 if (fdc_interrupt_wait(1 * FT_SECOND) < 0) {
628 TRACE(ft_t_err, "no drive polling interrupt!");
629 } else { /* clear all disk-changed statuses */
630 for (i = 0; i < 4; ++i) {
631 if(fdc_sense_interrupt_status(&st0, &dummy) != 0) {
632 TRACE(ft_t_err, "sense failed for %d", i);
633 }
634 if (i == ft_drive_sel) {
635 ftape_current_cylinder = dummy;
636 }
637 }
638 TRACE(ft_t_noise, "drive polling completed");
639 }
640 /*
641 * SPECIFY COMMAND
642 */
643 fdc_set_seek_rate(fdc_seek_rate);
644 /*
645 * DRIVE SPECIFICATION COMMAND (if fdc type known)
646 */
647 if (fdc.type >= i82078_1) {
648 fdc_set_drive_specs();
649 }
650 TRACE_EXIT;
651}
652
653#if !defined(CLK_48MHZ)
654# define CLK_48MHZ 1
655#endif
656
657/* When we're done, put the fdc into reset mode so that the regular
658 * floppy disk driver will figure out that something is wrong and
659 * initialize the controller the way it wants.
660 */
661void fdc_disable(void)
662{
663 __u8 cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00};
664 __u8 cmd2[] = {FDC_LOCK};
665 __u8 cmd3[] = {FDC_UNLOCK};
666 __u8 stat[1];
667 TRACE_FUN(ft_t_flow);
668
669 if (!fdc_fifo_locked) {
670 fdc_reset();
671 TRACE_EXIT;
672 }
673 if (fdc_issue_command(cmd3, 1, stat, 1) < 0 || stat[0] != 0x00) {
674 fdc_dor_reset(0);
675 TRACE_ABORT(/**/, ft_t_bug,
676 "couldn't unlock fifo, configuration remains changed");
677 }
678 fdc_fifo_locked = 0;
679 if (CLK_48MHZ && fdc.type >= i82078) {
680 cmd1[0] |= FDC_CLK48_BIT;
681 }
682 cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1);
683 if (fdc_command(cmd1, NR_ITEMS(cmd1)) < 0) {
684 fdc_dor_reset(0);
685 TRACE_ABORT(/**/, ft_t_bug,
686 "couldn't reconfigure fifo to old state");
687 }
688 if (fdc_lock_state &&
689 fdc_issue_command(cmd2, 1, stat, 1) < 0) {
690 fdc_dor_reset(0);
691 TRACE_ABORT(/**/, ft_t_bug, "couldn't lock old state again");
692 }
693 TRACE(ft_t_noise, "fifo restored: %sabled, thr. %d, %slocked",
694 fdc_fifo_state ? "en" : "dis",
695 fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");
696 fdc_dor_reset(0);
697 TRACE_EXIT;
698}
699
700/* Specify FDC seek-rate (milliseconds)
701 */
702static int fdc_set_seek_rate(int seek_rate)
703{
704 /* set step rate, dma mode, and minimal head load and unload times
705 */
706 __u8 in[3] = { FDC_SPECIFY, 1, (1 << 1)};
707
708 fdc_seek_rate = seek_rate;
709 in[1] |= (16 - (fdc_data_rate * fdc_seek_rate) / 500) << 4;
710
711 return fdc_command(in, 3);
712}
713
714/* Sense drive status: get unit's drive status (ST3)
715 */
716int fdc_sense_drive_status(int *st3)
717{
718 __u8 out[2];
719 __u8 in[1];
720 TRACE_FUN(ft_t_any);
721
722 out[0] = FDC_SENSED;
723 out[1] = ft_drive_sel;
724 TRACE_CATCH(fdc_issue_command(out, 2, in, 1),);
725 *st3 = in[0];
726 TRACE_EXIT 0;
727}
728
729/* Sense Interrupt Status command:
730 * should be issued at the end of each seek.
731 * get ST0 and current cylinder.
732 */
733int fdc_sense_interrupt_status(int *st0, int *current_cylinder)
734{
735 __u8 out[1];
736 __u8 in[2];
737 TRACE_FUN(ft_t_any);
738
739 out[0] = FDC_SENSEI;
740 TRACE_CATCH(fdc_issue_command(out, 1, in, 2),);
741 *st0 = in[0];
742 *current_cylinder = in[1];
743 TRACE_EXIT 0;
744}
745
746/* step to track
747 */
748int fdc_seek(int track)
749{
750 __u8 out[3];
751 int st0, pcn;
752#ifdef TESTING
753 unsigned int time;
754#endif
755 TRACE_FUN(ft_t_any);
756
757 out[0] = FDC_SEEK;
758 out[1] = ft_drive_sel;
759 out[2] = track;
760#ifdef TESTING
761 time = ftape_timestamp();
762#endif
763 /* We really need this command to work !
764 */
765 ft_seek_completed = 0;
766 TRACE_CATCH(fdc_command(out, 3),
767 fdc_reset();
768 TRACE(ft_t_noise, "destination was: %d, resetting FDC...",
769 track));
770 /* Handle interrupts until ft_seek_completed or timeout.
771 */
772 for (;;) {
773 TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),);
774 if (ft_seek_completed) {
775 TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),);
776 if ((st0 & ST0_SEEK_END) == 0) {
777 TRACE_ABORT(-EIO, ft_t_err,
778 "no seek-end after seek completion !??");
779 }
780 break;
781 }
782 }
783#ifdef TESTING
784 time = ftape_timediff(time, ftape_timestamp()) / abs(track - ftape_current_cylinder);
785 if ((time < 900 || time > 3100) && abs(track - ftape_current_cylinder) > 5) {
786 TRACE(ft_t_warn, "Wrong FDC STEP interval: %d usecs (%d)",
787 time, track - ftape_current_cylinder);
788 }
789#endif
790 /* Verify whether we issued the right tape command.
791 */
792 /* Verify that we seek to the proper track. */
793 if (pcn != track) {
794 TRACE_ABORT(-EIO, ft_t_err, "bad seek..");
795 }
796 ftape_current_cylinder = track;
797 TRACE_EXIT 0;
798}
799
800static int perpend_mode; /* set if fdc is in perpendicular mode */
801
802static int perpend_off(void)
803{
804 __u8 perpend[] = {FDC_PERPEND, 0x00};
805 TRACE_FUN(ft_t_any);
806
807 if (perpend_mode) {
808 /* Turn off perpendicular mode */
809 perpend[1] = 0x80;
810 TRACE_CATCH(fdc_command(perpend, 2),
811 TRACE(ft_t_err,"Perpendicular mode exit failed!"));
812 perpend_mode = 0;
813 }
814 TRACE_EXIT 0;
815}
816
817static int handle_perpend(int segment_id)
818{
819 __u8 perpend[] = {FDC_PERPEND, 0x00};
820 TRACE_FUN(ft_t_any);
821
822 /* When writing QIC-3020 tapes, turn on perpendicular mode
823 * if tape is moving in forward direction (even tracks).
824 */
825 if (ft_qic_std == QIC_TAPE_QIC3020 &&
826 ((segment_id / ft_segments_per_track) & 1) == 0) {
827/* FIXME: some i82077 seem to support perpendicular mode as
828 * well.
829 */
830#if 0
831 if (fdc.type < i82077AA) {}
832#else
833 if (fdc.type < i82077 && ft_data_rate < 1000) {
834#endif
835 /* fdc does not support perpendicular mode: complain
836 */
837 TRACE_ABORT(-EIO, ft_t_err,
838 "Your FDC does not support QIC-3020.");
839 }
840 perpend[1] = 0x03 /* 0x83 + (0x4 << ft_drive_sel) */ ;
841 TRACE_CATCH(fdc_command(perpend, 2),
842 TRACE(ft_t_err,"Perpendicular mode entry failed!"));
843 TRACE(ft_t_flow, "Perpendicular mode set");
844 perpend_mode = 1;
845 TRACE_EXIT 0;
846 }
847 TRACE_EXIT perpend_off();
848}
849
850static inline void fdc_setup_dma(char mode,
851 volatile void *addr, unsigned int count)
852{
853 /* Program the DMA controller.
854 */
855 disable_dma(fdc.dma);
856 clear_dma_ff(fdc.dma);
857 set_dma_mode(fdc.dma, mode);
858 set_dma_addr(fdc.dma, virt_to_bus((void*)addr));
859 set_dma_count(fdc.dma, count);
860 enable_dma(fdc.dma);
861}
862
863/* Setup fdc and dma for formatting the next segment
864 */
865int fdc_setup_formatting(buffer_struct * buff)
866{
867 unsigned long flags;
868 __u8 out[6] = {
869 FDC_FORMAT, 0x00, 3, 4 * FT_SECTORS_PER_SEGMENT, 0x00, 0x6b
870 };
871 TRACE_FUN(ft_t_any);
872
873 TRACE_CATCH(handle_perpend(buff->segment_id),);
874 /* Program the DMA controller.
875 */
876 TRACE(ft_t_fdc_dma,
877 "phys. addr. = %lx", virt_to_bus((void*) buff->ptr));
878 spin_lock_irqsave(&fdc_io_lock, flags);
879 fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4);
880 /* Issue FDC command to start reading/writing.
881 */
882 out[1] = ft_drive_sel;
883 out[4] = buff->gap3;
884 TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)),
885 restore_flags(flags); fdc_mode = fdc_idle);
886 spin_unlock_irqrestore(&fdc_io_lock, flags);
887 TRACE_EXIT 0;
888}
889
890
891/* Setup Floppy Disk Controller and DMA to read or write the next cluster
892 * of good sectors from or to the current segment.
893 */
894int fdc_setup_read_write(buffer_struct * buff, __u8 operation)
895{
896 unsigned long flags;
897 __u8 out[9];
898 int dma_mode;
899 TRACE_FUN(ft_t_any);
900
901 switch(operation) {
902 case FDC_VERIFY:
903 if (fdc.type < i82077) {
904 operation = FDC_READ;
905 }
906 case FDC_READ:
907 case FDC_READ_DELETED:
908 dma_mode = DMA_MODE_READ;
909 TRACE(ft_t_fdc_dma, "xfer %d sectors to 0x%p",
910 buff->sector_count, buff->ptr);
911 TRACE_CATCH(perpend_off(),);
912 break;
913 case FDC_WRITE_DELETED:
914 TRACE(ft_t_noise, "deleting segment %d", buff->segment_id);
915 case FDC_WRITE:
916 dma_mode = DMA_MODE_WRITE;
917 /* When writing QIC-3020 tapes, turn on perpendicular mode
918 * if tape is moving in forward direction (even tracks).
919 */
920 TRACE_CATCH(handle_perpend(buff->segment_id),);
921 TRACE(ft_t_fdc_dma, "xfer %d sectors from 0x%p",
922 buff->sector_count, buff->ptr);
923 break;
924 default:
925 TRACE_ABORT(-EIO,
926 ft_t_bug, "bug: invalid operation parameter");
927 }
928 TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr));
929 spin_lock_irqsave(&fdc_io_lock, flags);
930 if (operation != FDC_VERIFY) {
931 fdc_setup_dma(dma_mode, buff->ptr,
932 FT_SECTOR_SIZE * buff->sector_count);
933 }
934 /* Issue FDC command to start reading/writing.
935 */
936 out[0] = operation;
937 out[1] = ft_drive_sel;
938 out[2] = buff->cyl;
939 out[3] = buff->head;
940 out[4] = buff->sect + buff->sector_offset;
941 out[5] = 3; /* Sector size of 1K. */
942 out[6] = out[4] + buff->sector_count - 1; /* last sector */
943 out[7] = 109; /* Gap length. */
944 out[8] = 0xff; /* No limit to transfer size. */
945 TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",
946 out[2], out[3], out[4], out[6] - out[4] + 1);
947 spin_unlock_irqrestore(&fdc_io_lock, flags);
948 TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle);
949 TRACE_EXIT 0;
950}
951
952int fdc_fifo_threshold(__u8 threshold,
953 int *fifo_state, int *lock_state, int *fifo_thr)
954{
955 const __u8 cmd0[] = {FDC_DUMPREGS};
956 __u8 cmd1[] = {FDC_CONFIGURE, 0, (0x0f & (threshold - 1)), 0};
957 const __u8 cmd2[] = {FDC_LOCK};
958 const __u8 cmd3[] = {FDC_UNLOCK};
959 __u8 reg[10];
960 __u8 stat;
961 int i;
962 int result;
963 TRACE_FUN(ft_t_any);
964
965 if (CLK_48MHZ && fdc.type >= i82078) {
966 cmd1[0] |= FDC_CLK48_BIT;
967 }
968 /* Dump fdc internal registers for examination
969 */
970 TRACE_CATCH(fdc_command(cmd0, NR_ITEMS(cmd0)),
971 TRACE(ft_t_warn, "dumpreg cmd failed, fifo unchanged"));
972 /* Now read fdc internal registers from fifo
973 */
974 for (i = 0; i < (int)NR_ITEMS(reg); ++i) {
975 fdc_read(&reg[i]);
976 TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]);
977 }
978 if (fifo_state && lock_state && fifo_thr) {
979 *fifo_state = (reg[8] & 0x20) == 0;
980 *lock_state = reg[7] & 0x80;
981 *fifo_thr = 1 + (reg[8] & 0x0f);
982 }
983 TRACE(ft_t_noise,
984 "original fifo state: %sabled, threshold %d, %slocked",
985 ((reg[8] & 0x20) == 0) ? "en" : "dis",
986 1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not ");
987 /* If fdc is already locked, unlock it first ! */
988 if (reg[7] & 0x80) {
989 fdc_ready_wait(100);
990 TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1),
991 TRACE(ft_t_bug, "FDC unlock command failed, "
992 "configuration unchanged"));
993 }
994 fdc_fifo_locked = 0;
995 /* Enable fifo and set threshold at xx bytes to allow a
996 * reasonably large latency and reduce number of dma bursts.
997 */
998 fdc_ready_wait(100);
999 if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) {
1000 TRACE(ft_t_bug, "configure cmd failed, fifo unchanged");
1001 }
1002 /* Now lock configuration so reset will not change it
1003 */
1004 if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 ||
1005 stat != 0x10) {
1006 TRACE_ABORT(-EIO, ft_t_bug,
1007 "FDC lock command failed, stat = 0x%02x", stat);
1008 }
1009 fdc_fifo_locked = 1;
1010 TRACE_EXIT result;
1011}
1012
1013static int fdc_fifo_enable(void)
1014{
1015 TRACE_FUN(ft_t_any);
1016
1017 if (fdc_fifo_locked) {
1018 TRACE_ABORT(0, ft_t_warn, "Fifo not enabled because locked");
1019 }
1020 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1021 &fdc_fifo_state,
1022 &fdc_lock_state,
1023 &fdc_fifo_thr),);
1024 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1025 NULL, NULL, NULL),);
1026 TRACE_EXIT 0;
1027}
1028
1029/* Determine fd controller type
1030 */
1031static __u8 fdc_save_state[2];
1032
1033static int fdc_probe(void)
1034{
1035 __u8 cmd[1];
1036 __u8 stat[16]; /* must be able to hold dumpregs & save results */
1037 int i;
1038 TRACE_FUN(ft_t_any);
1039
1040 /* Try to find out what kind of fd controller we have to deal with
1041 * Scheme borrowed from floppy driver:
1042 * first try if FDC_DUMPREGS command works
1043 * (this indicates that we have a 82072 or better)
1044 * then try the FDC_VERSION command (82072 doesn't support this)
1045 * then try the FDC_UNLOCK command (some older 82077's don't support this)
1046 * then try the FDC_PARTID command (82078's support this)
1047 */
1048 cmd[0] = FDC_DUMPREGS;
1049 if (fdc_issue_command(cmd, 1, stat, 1) != 0) {
1050 TRACE_ABORT(no_fdc, ft_t_bug, "No FDC found");
1051 }
1052 if (stat[0] == 0x80) {
1053 /* invalid command: must be pre 82072 */
1054 TRACE_ABORT(i8272,
1055 ft_t_warn, "Type 8272A/765A compatible FDC found");
1056 }
1057 fdc_result(&stat[1], 9);
1058 fdc_save_state[0] = stat[7];
1059 fdc_save_state[1] = stat[8];
1060 cmd[0] = FDC_VERSION;
1061 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1062 TRACE_ABORT(i8272, ft_t_warn, "Type 82072 FDC found");
1063 }
1064 if (*stat != 0x90) {
1065 TRACE_ABORT(i8272, ft_t_warn, "Unknown FDC found");
1066 }
1067 cmd[0] = FDC_UNLOCK;
1068 if(fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] != 0x00) {
1069 TRACE_ABORT(i8272, ft_t_warn,
1070 "Type pre-1991 82077 FDC found, "
1071 "treating it like a 82072");
1072 }
1073 if (fdc_save_state[0] & 0x80) { /* was locked */
1074 cmd[0] = FDC_LOCK; /* restore lock */
1075 (void)fdc_issue_command(cmd, 1, stat, 1);
1076 TRACE(ft_t_warn, "FDC is already locked");
1077 }
1078 /* Test for a i82078 FDC */
1079 cmd[0] = FDC_PARTID;
1080 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1081 /* invalid command: not a i82078xx type FDC */
1082 for (i = 0; i < 4; ++i) {
1083 outb_p(i, fdc.tdr);
1084 if ((inb_p(fdc.tdr) & 0x03) != i) {
1085 TRACE_ABORT(i82077,
1086 ft_t_warn, "Type 82077 FDC found");
1087 }
1088 }
1089 TRACE_ABORT(i82077AA, ft_t_warn, "Type 82077AA FDC found");
1090 }
1091 /* FDC_PARTID cmd succeeded */
1092 switch (stat[0] >> 5) {
1093 case 0x0:
1094 /* i82078SL or i82078-1. The SL part cannot run at
1095 * 2Mbps (the SL and -1 dies are identical; they are
1096 * speed graded after production, according to Intel).
1097 * Some SL's can be detected by doing a SAVE cmd and
1098 * look at bit 7 of the first byte (the SEL3V# bit).
1099 * If it is 0, the part runs off 3Volts, and hence it
1100 * is a SL.
1101 */
1102 cmd[0] = FDC_SAVE;
1103 if(fdc_issue_command(cmd, 1, stat, 16) < 0) {
1104 TRACE(ft_t_err, "FDC_SAVE failed. Dunno why");
1105 /* guess we better claim the fdc to be a i82078 */
1106 TRACE_ABORT(i82078,
1107 ft_t_warn,
1108 "Type i82078 FDC (i suppose) found");
1109 }
1110 if ((stat[0] & FDC_SEL3V_BIT)) {
1111 /* fdc running off 5Volts; Pray that it's a i82078-1
1112 */
1113 TRACE_ABORT(i82078_1, ft_t_warn,
1114 "Type i82078-1 or 5Volt i82078SL FDC found");
1115 }
1116 TRACE_ABORT(i82078, ft_t_warn,
1117 "Type 3Volt i82078SL FDC (1Mbps) found");
1118 case 0x1:
1119 case 0x2: /* S82078B */
1120 /* The '78B isn't '78 compatible. Detect it as a '77AA */
1121 TRACE_ABORT(i82077AA, ft_t_warn, "Type i82077AA FDC found");
1122 case 0x3: /* NSC PC8744 core; used in several super-IO chips */
1123 TRACE_ABORT(i82077AA,
1124 ft_t_warn, "Type 82077AA compatible FDC found");
1125 default:
1126 TRACE(ft_t_warn, "A previously undetected FDC found");
1127 TRACE_ABORT(i82077AA, ft_t_warn,
1128 "Treating it as a 82077AA. Please report partid= %d",
1129 stat[0]);
1130 } /* switch(stat[ 0] >> 5) */
1131 TRACE_EXIT no_fdc;
1132}
1133
1134static int fdc_request_regions(void)
1135{
1136 TRACE_FUN(ft_t_flow);
1137
1138 if (ft_mach2 || ft_probe_fc10) {
1139 if (!request_region(fdc.sra, 8, "fdc (ft)")) {
1140#ifndef BROKEN_FLOPPY_DRIVER
1141 TRACE_EXIT -EBUSY;
1142#else
1143 TRACE(ft_t_warn,
1144"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1145#endif
1146 }
1147 } else {
1148 if (!request_region(fdc.sra, 6, "fdc (ft)")) {
1149#ifndef BROKEN_FLOPPY_DRIVER
1150 TRACE_EXIT -EBUSY;
1151#else
1152 TRACE(ft_t_warn,
1153"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1154#endif
1155 }
1156 if (!request_region(fdc.sra + 7, 1, "fdc (ft)")) {
1157#ifndef BROKEN_FLOPPY_DRIVER
1158 release_region(fdc.sra, 6);
1159 TRACE_EXIT -EBUSY;
1160#else
1161 TRACE(ft_t_warn,
1162"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra + 7);
1163#endif
1164 }
1165 }
1166 TRACE_EXIT 0;
1167}
1168
1169void fdc_release_regions(void)
1170{
1171 TRACE_FUN(ft_t_flow);
1172
1173 if (fdc.sra != 0) {
1174 if (fdc.dor2 != 0) {
1175 release_region(fdc.sra, 8);
1176 } else {
1177 release_region(fdc.sra, 6);
1178 release_region(fdc.dir, 1);
1179 }
1180 }
1181 TRACE_EXIT;
1182}
1183
1184static int fdc_config_regs(unsigned int fdc_base,
1185 unsigned int fdc_irq,
1186 unsigned int fdc_dma)
1187{
1188 TRACE_FUN(ft_t_flow);
1189
1190 fdc.irq = fdc_irq;
1191 fdc.dma = fdc_dma;
1192 fdc.sra = fdc_base;
1193 fdc.srb = fdc_base + 1;
1194 fdc.dor = fdc_base + 2;
1195 fdc.tdr = fdc_base + 3;
1196 fdc.msr = fdc.dsr = fdc_base + 4;
1197 fdc.fifo = fdc_base + 5;
1198 fdc.dir = fdc.ccr = fdc_base + 7;
1199 fdc.dor2 = (ft_mach2 || ft_probe_fc10) ? fdc_base + 6 : 0;
1200 TRACE_CATCH(fdc_request_regions(), fdc.sra = 0);
1201 TRACE_EXIT 0;
1202}
1203
1204static int fdc_config(void)
1205{
1206 static int already_done;
1207 TRACE_FUN(ft_t_any);
1208
1209 if (already_done) {
1210 TRACE_CATCH(fdc_request_regions(),);
1211 *(fdc.hook) = fdc_isr; /* hook our handler in */
1212 TRACE_EXIT 0;
1213 }
1214 if (ft_probe_fc10) {
1215 int fc_type;
1216
1217 TRACE_CATCH(fdc_config_regs(ft_fdc_base,
1218 ft_fdc_irq, ft_fdc_dma),);
1219 fc_type = fc10_enable();
1220 if (fc_type != 0) {
1221 TRACE(ft_t_warn, "FC-%c0 controller found", '0' + fc_type);
1222 fdc.type = fc10;
1223 fdc.hook = &do_ftape;
1224 *(fdc.hook) = fdc_isr; /* hook our handler in */
1225 already_done = 1;
1226 TRACE_EXIT 0;
1227 } else {
1228 TRACE(ft_t_warn, "FC-10/20 controller not found");
1229 fdc_release_regions();
1230 fdc.type = no_fdc;
1231 ft_probe_fc10 = 0;
1232 ft_fdc_base = 0x3f0;
1233 ft_fdc_irq = 6;
1234 ft_fdc_dma = 2;
1235 }
1236 }
1237 TRACE(ft_t_warn, "fdc base: 0x%x, irq: %d, dma: %d",
1238 ft_fdc_base, ft_fdc_irq, ft_fdc_dma);
1239 TRACE_CATCH(fdc_config_regs(ft_fdc_base, ft_fdc_irq, ft_fdc_dma),);
1240 fdc.hook = &do_ftape;
1241 *(fdc.hook) = fdc_isr; /* hook our handler in */
1242 already_done = 1;
1243 TRACE_EXIT 0;
1244}
1245
1246static irqreturn_t ftape_interrupt(int irq, void *dev_id)
1247{
1248 void (*handler) (void) = *fdc.hook;
1249 int handled = 0;
1250 TRACE_FUN(ft_t_any);
1251
1252 *fdc.hook = NULL;
1253 if (handler) {
1254 handled = 1;
1255 handler();
1256 } else {
1257 TRACE(ft_t_bug, "Unexpected ftape interrupt");
1258 }
1259 TRACE_EXIT IRQ_RETVAL(handled);
1260}
1261
1262static int fdc_grab_irq_and_dma(void)
1263{
1264 TRACE_FUN(ft_t_any);
1265
1266 if (fdc.hook == &do_ftape) {
1267 /* Get fast interrupt handler.
1268 */
1269 if (request_irq(fdc.irq, ftape_interrupt,
1270 IRQF_DISABLED, "ft", ftape_id)) {
1271 TRACE_ABORT(-EIO, ft_t_bug,
1272 "Unable to grab IRQ%d for ftape driver",
1273 fdc.irq);
1274 }
1275 if (request_dma(fdc.dma, ftape_id)) {
1276 free_irq(fdc.irq, ftape_id);
1277 TRACE_ABORT(-EIO, ft_t_bug,
1278 "Unable to grab DMA%d for ftape driver",
1279 fdc.dma);
1280 }
1281 }
1282 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1283 /* Using same dma channel or irq as standard fdc, need
1284 * to disable the dma-gate on the std fdc. This
1285 * couldn't be done in the floppy driver as some
1286 * laptops are using the dma-gate to enter a low power
1287 * or even suspended state :-(
1288 */
1289 outb_p(FDC_RESET_NOT, 0x3f2);
1290 TRACE(ft_t_noise, "DMA-gate on standard fdc disabled");
1291 }
1292 TRACE_EXIT 0;
1293}
1294
1295int fdc_release_irq_and_dma(void)
1296{
1297 TRACE_FUN(ft_t_any);
1298
1299 if (fdc.hook == &do_ftape) {
1300 disable_dma(fdc.dma); /* just in case... */
1301 free_dma(fdc.dma);
1302 free_irq(fdc.irq, ftape_id);
1303 }
1304 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1305 /* Using same dma channel as standard fdc, need to
1306 * disable the dma-gate on the std fdc. This couldn't
1307 * be done in the floppy driver as some laptops are
1308 * using the dma-gate to enter a low power or even
1309 * suspended state :-(
1310 */
1311 outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);
1312 TRACE(ft_t_noise, "DMA-gate on standard fdc enabled again");
1313 }
1314 TRACE_EXIT 0;
1315}
1316
1317int fdc_init(void)
1318{
1319 TRACE_FUN(ft_t_any);
1320
1321 /* find a FDC to use */
1322 TRACE_CATCH(fdc_config(),);
1323 TRACE_CATCH(fdc_grab_irq_and_dma(), fdc_release_regions());
1324 ftape_motor = 0;
1325 fdc_catch_stray_interrupts(0); /* clear number of awainted
1326 * stray interrupte
1327 */
1328 fdc_catch_stray_interrupts(1); /* one always comes (?) */
1329 TRACE(ft_t_flow, "resetting fdc");
1330 fdc_set_seek_rate(2); /* use nominal QIC step rate */
1331 fdc_reset(); /* init fdc & clear track counters */
1332 if (fdc.type == no_fdc) { /* no FC-10 or FC-20 found */
1333 fdc.type = fdc_probe();
1334 fdc_reset(); /* update with new knowledge */
1335 }
1336 if (fdc.type == no_fdc) {
1337 fdc_release_irq_and_dma();
1338 fdc_release_regions();
1339 TRACE_EXIT -ENXIO;
1340 }
1341 if (fdc.type >= i82077) {
1342 if (fdc_fifo_enable() < 0) {
1343 TRACE(ft_t_warn, "couldn't enable fdc fifo !");
1344 } else {
1345 TRACE(ft_t_flow, "fdc fifo enabled and locked");
1346 }
1347 }
1348 TRACE_EXIT 0;
1349}
diff --git a/drivers/char/ftape/lowlevel/fdc-io.h b/drivers/char/ftape/lowlevel/fdc-io.h
deleted file mode 100644
index 7ec3c72178bb..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-io.h
+++ /dev/null
@@ -1,252 +0,0 @@
1#ifndef _FDC_IO_H
2#define _FDC_IO_H
3
4/*
5 * Copyright (C) 1993-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-io.h,v $
24 * $Revision: 1.3 $
25 * $Date: 1997/10/05 19:18:06 $
26 *
27 * This file contains the declarations for the low level
28 * functions that communicate with the floppy disk controller,
29 * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for
30 * Linux.
31 */
32
33#include <linux/fdreg.h>
34
35#include "../lowlevel/ftape-bsm.h"
36
37#define FDC_SK_BIT (0x20)
38#define FDC_MT_BIT (0x80)
39
40#define FDC_READ (FD_READ & ~(FDC_SK_BIT | FDC_MT_BIT))
41#define FDC_WRITE (FD_WRITE & ~FDC_MT_BIT)
42#define FDC_READ_DELETED (0x4c)
43#define FDC_WRITE_DELETED (0x49)
44#define FDC_VERIFY (0x56)
45#define FDC_READID (0x4a)
46#define FDC_SENSED (0x04)
47#define FDC_SENSEI (FD_SENSEI)
48#define FDC_FORMAT (FD_FORMAT)
49#define FDC_RECAL (FD_RECALIBRATE)
50#define FDC_SEEK (FD_SEEK)
51#define FDC_SPECIFY (FD_SPECIFY)
52#define FDC_RECALIBR (FD_RECALIBRATE)
53#define FDC_VERSION (FD_VERSION)
54#define FDC_PERPEND (FD_PERPENDICULAR)
55#define FDC_DUMPREGS (FD_DUMPREGS)
56#define FDC_LOCK (FD_LOCK)
57#define FDC_UNLOCK (FD_UNLOCK)
58#define FDC_CONFIGURE (FD_CONFIGURE)
59#define FDC_DRIVE_SPEC (0x8e) /* i82078 has this (any others?) */
60#define FDC_PARTID (0x18) /* i82078 has this */
61#define FDC_SAVE (0x2e) /* i82078 has this (any others?) */
62#define FDC_RESTORE (0x4e) /* i82078 has this (any others?) */
63
64#define FDC_STATUS_MASK (STATUS_BUSY | STATUS_DMA | STATUS_DIR | STATUS_READY)
65#define FDC_DATA_READY (STATUS_READY)
66#define FDC_DATA_OUTPUT (STATUS_DIR)
67#define FDC_DATA_READY_MASK (STATUS_READY | STATUS_DIR)
68#define FDC_DATA_OUT_READY (STATUS_READY | STATUS_DIR)
69#define FDC_DATA_IN_READY (STATUS_READY)
70#define FDC_BUSY (STATUS_BUSY)
71#define FDC_CLK48_BIT (0x80)
72#define FDC_SEL3V_BIT (0x40)
73
74#define ST0_INT_MASK (ST0_INTR)
75#define FDC_INT_NORMAL (ST0_INTR & 0x00)
76#define FDC_INT_ABNORMAL (ST0_INTR & 0x40)
77#define FDC_INT_INVALID (ST0_INTR & 0x80)
78#define FDC_INT_READYCH (ST0_INTR & 0xC0)
79#define ST0_SEEK_END (ST0_SE)
80#define ST3_TRACK_0 (ST3_TZ)
81
82#define FDC_RESET_NOT (0x04)
83#define FDC_DMA_MODE (0x08)
84#define FDC_MOTOR_0 (0x10)
85#define FDC_MOTOR_1 (0x20)
86
87typedef struct {
88 void (**hook) (void); /* our wedge into the isr */
89 enum {
90 no_fdc, i8272, i82077, i82077AA, fc10,
91 i82078, i82078_1
92 } type; /* FDC type */
93 unsigned int irq; /* FDC irq nr */
94 unsigned int dma; /* FDC dma channel nr */
95 __u16 sra; /* Status register A (PS/2 only) */
96 __u16 srb; /* Status register B (PS/2 only) */
97 __u16 dor; /* Digital output register */
98 __u16 tdr; /* Tape Drive Register (82077SL-1 &
99 82078 only) */
100 __u16 msr; /* Main Status Register */
101 __u16 dsr; /* Datarate Select Register (8207x only) */
102 __u16 fifo; /* Data register / Fifo on 8207x */
103 __u16 dir; /* Digital Input Register */
104 __u16 ccr; /* Configuration Control Register */
105 __u16 dor2; /* Alternate dor on MACH-2 controller,
106 also used with FC-10, meaning unknown */
107} fdc_config_info;
108
109typedef enum {
110 fdc_data_rate_250 = 2,
111 fdc_data_rate_300 = 1, /* any fdc in default configuration */
112 fdc_data_rate_500 = 0,
113 fdc_data_rate_1000 = 3,
114 fdc_data_rate_2000 = 1, /* i82078-1: when using Data Rate Table #2 */
115} fdc_data_rate_type;
116
117typedef enum {
118 fdc_idle = 0,
119 fdc_reading_data = FDC_READ,
120 fdc_seeking = FDC_SEEK,
121 fdc_writing_data = FDC_WRITE,
122 fdc_deleting = FDC_WRITE_DELETED,
123 fdc_reading_id = FDC_READID,
124 fdc_recalibrating = FDC_RECAL,
125 fdc_formatting = FDC_FORMAT,
126 fdc_verifying = FDC_VERIFY
127} fdc_mode_enum;
128
129typedef enum {
130 waiting = 0,
131 reading,
132 writing,
133 formatting,
134 verifying,
135 deleting,
136 done,
137 error,
138 mmapped,
139} buffer_state_enum;
140
141typedef struct {
142 __u8 *address;
143 volatile buffer_state_enum status;
144 volatile __u8 *ptr;
145 volatile unsigned int bytes;
146 volatile unsigned int segment_id;
147
148 /* bitmap for remainder of segment not yet handled.
149 * one bit set for each bad sector that must be skipped.
150 */
151 volatile SectorMap bad_sector_map;
152
153 /* bitmap with bad data blocks in data buffer.
154 * the errors in this map may be retried.
155 */
156 volatile SectorMap soft_error_map;
157
158 /* bitmap with bad data blocks in data buffer
159 * the errors in this map may not be retried.
160 */
161 volatile SectorMap hard_error_map;
162
163 /* retry counter for soft errors.
164 */
165 volatile int retry;
166
167 /* sectors to skip on retry ???
168 */
169 volatile unsigned int skip;
170
171 /* nr of data blocks in data buffer
172 */
173 volatile unsigned int data_offset;
174
175 /* offset in segment for first sector to be handled.
176 */
177 volatile unsigned int sector_offset;
178
179 /* size of cluster of good sectors to be handled.
180 */
181 volatile unsigned int sector_count;
182
183 /* size of remaining part of segment to be handled.
184 */
185 volatile unsigned int remaining;
186
187 /* points to next segment (contiguous) to be handled,
188 * or is zero if no read-ahead is allowed.
189 */
190 volatile unsigned int next_segment;
191
192 /* flag being set if deleted data was read.
193 */
194 volatile int deleted;
195
196 /* floppy coordinates of first sector in segment */
197 volatile __u8 head;
198 volatile __u8 cyl;
199 volatile __u8 sect;
200
201 /* gap to use when formatting */
202 __u8 gap3;
203 /* flag set when buffer is mmaped */
204 int mmapped;
205} buffer_struct;
206
207/*
208 * fdc-io.c defined public variables
209 */
210extern volatile fdc_mode_enum fdc_mode;
211extern int fdc_setup_error; /* outdated ??? */
212extern wait_queue_head_t ftape_wait_intr;
213extern volatile int ftape_current_cylinder; /* track nr FDC thinks we're on */
214extern volatile __u8 fdc_head; /* FDC head */
215extern volatile __u8 fdc_cyl; /* FDC track */
216extern volatile __u8 fdc_sect; /* FDC sector */
217extern fdc_config_info fdc; /* FDC hardware configuration */
218
219extern unsigned int ft_fdc_base;
220extern unsigned int ft_fdc_irq;
221extern unsigned int ft_fdc_dma;
222extern unsigned int ft_fdc_threshold;
223extern unsigned int ft_fdc_rate_limit;
224extern int ft_probe_fc10;
225extern int ft_mach2;
226/*
227 * fdc-io.c defined public functions
228 */
229extern void fdc_catch_stray_interrupts(int count);
230extern int fdc_ready_wait(unsigned int timeout);
231extern int fdc_command(const __u8 * cmd_data, int cmd_len);
232extern int fdc_result(__u8 * res_data, int res_len);
233extern int fdc_interrupt_wait(unsigned int time);
234extern int fdc_seek(int track);
235extern int fdc_sense_drive_status(int *st3);
236extern void fdc_motor(int motor);
237extern void fdc_reset(void);
238extern void fdc_disable(void);
239extern int fdc_fifo_threshold(__u8 threshold,
240 int *fifo_state, int *lock_state, int *fifo_thr);
241extern void fdc_wait_calibrate(void);
242extern int fdc_sense_interrupt_status(int *st0, int *current_cylinder);
243extern void fdc_save_drive_specs(void);
244extern void fdc_restore_drive_specs(void);
245extern int fdc_set_data_rate(int rate);
246extern void fdc_set_write_precomp(int precomp);
247extern int fdc_release_irq_and_dma(void);
248extern void fdc_release_regions(void);
249extern int fdc_init(void);
250extern int fdc_setup_read_write(buffer_struct * buff, __u8 operation);
251extern int fdc_setup_formatting(buffer_struct * buff);
252#endif
diff --git a/drivers/char/ftape/lowlevel/fdc-isr.c b/drivers/char/ftape/lowlevel/fdc-isr.c
deleted file mode 100644
index ad2bc733ae1b..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-isr.c
+++ /dev/null
@@ -1,1170 +0,0 @@
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 */
47volatile int ft_expected_stray_interrupts;
48volatile int ft_interrupt_seen;
49volatile int ft_seek_completed;
50volatile int ft_hide_interrupt;
51/* Local vars.
52 */
53typedef 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;
58static int stop_read_ahead;
59
60
61static 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
89static 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
113static 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
166static 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
191static 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
213static 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
234static 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 */
287static 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
337static 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
407static 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
416static 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
451static 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
567static 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
582static 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 */
633static 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 */
687static 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 */
731static 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 */
1078void 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}
diff --git a/drivers/char/ftape/lowlevel/fdc-isr.h b/drivers/char/ftape/lowlevel/fdc-isr.h
deleted file mode 100644
index 065aa978942d..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-isr.h
+++ /dev/null
@@ -1,55 +0,0 @@
1#ifndef _FDC_ISR_H
2#define _FDC_ISR_H
3
4/*
5 * Copyright (C) 1993-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:07 $
26 *
27 * This file declares the global variables necessary to
28 * synchronize the interrupt service routine (isr) with the
29 * remainder of the QIC-40/80/3010/3020 floppy-tape driver
30 * "ftape" for Linux.
31 */
32
33/*
34 * fdc-isr.c defined public variables
35 */
36extern volatile int ft_expected_stray_interrupts; /* masks stray interrupts */
37extern volatile int ft_seek_completed; /* flag set by isr */
38extern volatile int ft_interrupt_seen; /* flag set by isr */
39extern volatile int ft_hide_interrupt; /* flag set by isr */
40
41/*
42 * fdc-io.c defined public functions
43 */
44extern void fdc_isr(void);
45
46/*
47 * A kernel hook that steals one interrupt from the floppy
48 * driver (Should be fixed when the new fdc driver gets ready)
49 * See the linux kernel source files:
50 * drivers/block/floppy.c & drivers/block/blk.h
51 * for the details.
52 */
53extern void (*do_floppy) (void);
54
55#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-bsm.c b/drivers/char/ftape/lowlevel/ftape-bsm.c
deleted file mode 100644
index d1a301cc344f..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-bsm.c
+++ /dev/null
@@ -1,491 +0,0 @@
1/*
2 * Copyright (C) 1994-1996 Bas Laarhoven,
3 * (C) 1996-1997 Claus 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/ftape-bsm.c,v $
21 * $Revision: 1.3 $
22 * $Date: 1997/10/05 19:15:15 $
23 *
24 * This file contains the bad-sector map handling code for
25 * the QIC-117 floppy tape driver for Linux.
26 * QIC-40, QIC-80, QIC-3010 and QIC-3020 maps are implemented.
27 */
28
29#include <linux/string.h>
30
31#include <linux/ftape.h>
32#include "../lowlevel/ftape-tracing.h"
33#include "../lowlevel/ftape-bsm.h"
34#include "../lowlevel/ftape-ctl.h"
35#include "../lowlevel/ftape-rw.h"
36
37/* Global vars.
38 */
39
40/* Local vars.
41 */
42static __u8 *bad_sector_map;
43static SectorCount *bsm_hash_ptr;
44
45typedef enum {
46 forward, backward
47} mode_type;
48
49#if 0
50static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map);
51#endif
52
53#if 0
54/* fix_tape converts a normal QIC-80 tape into a 'wide' tape.
55 * For testing purposes only !
56 */
57void fix_tape(__u8 * buffer, ft_format_type new_code)
58{
59 static __u8 list[BAD_SECTOR_MAP_SIZE];
60 SectorMap *src_ptr = (SectorMap *) list;
61 __u8 *dst_ptr = bad_sector_map;
62 SectorMap map;
63 unsigned int sector = 1;
64 int i;
65
66 if (format_code != fmt_var && format_code != fmt_big) {
67 memcpy(list, bad_sector_map, sizeof(list));
68 memset(bad_sector_map, 0, sizeof(bad_sector_map));
69 while ((__u8 *) src_ptr - list < sizeof(list)) {
70 map = *src_ptr++;
71 if (map == EMPTY_SEGMENT) {
72 *(SectorMap *) dst_ptr = 0x800000 + sector;
73 dst_ptr += 3;
74 sector += SECTORS_PER_SEGMENT;
75 } else {
76 for (i = 0; i < SECTORS_PER_SEGMENT; ++i) {
77 if (map & 1) {
78 *(SewctorMap *) dst_ptr = sector;
79 dst_ptr += 3;
80 }
81 map >>= 1;
82 ++sector;
83 }
84 }
85 }
86 }
87 bad_sector_map_changed = 1;
88 *(buffer + 4) = new_code; /* put new format code */
89 if (format_code != fmt_var && new_code == fmt_big) {
90 PUT4(buffer, FT_6_HSEG_1, (__u32)GET2(buffer, 6));
91 PUT4(buffer, FT_6_HSEG_2, (__u32)GET2(buffer, 8));
92 PUT4(buffer, FT_6_FRST_SEG, (__u32)GET2(buffer, 10));
93 PUT4(buffer, FT_6_LAST_SEG, (__u32)GET2(buffer, 12));
94 memset(buffer+6, '\0', 8);
95 }
96 format_code = new_code;
97}
98
99#endif
100
101/* given buffer that contains a header segment, find the end of
102 * of the bsm list
103 */
104__u8 * ftape_find_end_of_bsm_list(__u8 * address)
105{
106 __u8 *ptr = address + FT_HEADER_END; /* start of bsm list */
107 __u8 *limit = address + FT_SEGMENT_SIZE;
108 while (ptr + 2 < limit) {
109 if (ptr[0] || ptr[1] || ptr[2]) {
110 ptr += 3;
111 } else {
112 return ptr;
113 }
114 }
115 return NULL;
116}
117
118static inline void put_sector(SectorCount *ptr, unsigned int sector)
119{
120 ptr->bytes[0] = sector & 0xff;
121 sector >>= 8;
122 ptr->bytes[1] = sector & 0xff;
123 sector >>= 8;
124 ptr->bytes[2] = sector & 0xff;
125}
126
127static inline unsigned int get_sector(SectorCount *ptr)
128{
129#if 1
130 unsigned int sector;
131
132 sector = ptr->bytes[0];
133 sector += ptr->bytes[1] << 8;
134 sector += ptr->bytes[2] << 16;
135
136 return sector;
137#else
138 /* GET4 gets the next four bytes in Intel little endian order
139 * and converts them to host byte order and handles unaligned
140 * access.
141 */
142 return (GET4(ptr, 0) & 0x00ffffff); /* back to host byte order */
143#endif
144}
145
146static void bsm_debug_fake(void)
147{
148 /* for testing of bad sector handling at end of tape
149 */
150#if 0
151 ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 3,
152 0x000003e0;
153 ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 2,
154 0xff3fffff;
155 ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 1,
156 0xffffe000;
157#endif
158 /* Enable to test bad sector handling
159 */
160#if 0
161 ftape_put_bad_sector_entry(30, 0xfffffffe)
162 ftape_put_bad_sector_entry(32, 0x7fffffff);
163 ftape_put_bad_sector_entry(34, 0xfffeffff);
164 ftape_put_bad_sector_entry(36, 0x55555555);
165 ftape_put_bad_sector_entry(38, 0xffffffff);
166 ftape_put_bad_sector_entry(50, 0xffff0000);
167 ftape_put_bad_sector_entry(51, 0xffffffff);
168 ftape_put_bad_sector_entry(52, 0xffffffff);
169 ftape_put_bad_sector_entry(53, 0x0000ffff);
170#endif
171 /* Enable when testing multiple volume tar dumps.
172 */
173#if 0
174 {
175 int i;
176
177 for (i = ft_first_data_segment;
178 i <= ft_last_data_segment - 7; ++i) {
179 ftape_put_bad_sector_entry(i, EMPTY_SEGMENT);
180 }
181 }
182#endif
183 /* Enable when testing bit positions in *_error_map
184 */
185#if 0
186 {
187 int i;
188
189 for (i = first_data_segment; i <= last_data_segment; ++i) {
190 ftape_put_bad_sector_entry(i,
191 ftape_get_bad_sector_entry(i)
192 | 0x00ff00ff);
193 }
194 }
195#endif
196}
197
198static void print_bad_sector_map(void)
199{
200 unsigned int good_sectors;
201 unsigned int total_bad = 0;
202 int i;
203 TRACE_FUN(ft_t_flow);
204
205 if (ft_format_code == fmt_big ||
206 ft_format_code == fmt_var ||
207 ft_format_code == fmt_1100ft) {
208 SectorCount *ptr = (SectorCount *)bad_sector_map;
209 unsigned int sector;
210 __u16 *ptr16;
211
212 while((sector = get_sector(ptr++)) != 0) {
213 if ((ft_format_code == fmt_big ||
214 ft_format_code == fmt_var) &&
215 sector & 0x800000) {
216 total_bad += FT_SECTORS_PER_SEGMENT - 3;
217 TRACE(ft_t_noise, "bad segment at sector: %6d",
218 sector & 0x7fffff);
219 } else {
220 ++total_bad;
221 TRACE(ft_t_noise, "bad sector: %6d", sector);
222 }
223 }
224 /* Display old ftape's end-of-file marks
225 */
226 ptr16 = (__u16*)ptr;
227 while ((sector = get_unaligned(ptr16++)) != 0) {
228 TRACE(ft_t_noise, "Old ftape eof mark: %4d/%2d",
229 sector, get_unaligned(ptr16++));
230 }
231 } else { /* fixed size format */
232 for (i = ft_first_data_segment;
233 i < (int)(ft_segments_per_track * ft_tracks_per_tape); ++i) {
234 SectorMap map = ((SectorMap *) bad_sector_map)[i];
235
236 if (map) {
237 TRACE(ft_t_noise,
238 "bsm for segment %4d: 0x%08x", i, (unsigned int)map);
239 total_bad += ((map == EMPTY_SEGMENT)
240 ? FT_SECTORS_PER_SEGMENT - 3
241 : count_ones(map));
242 }
243 }
244 }
245 good_sectors =
246 ((ft_segments_per_track * ft_tracks_per_tape - ft_first_data_segment)
247 * (FT_SECTORS_PER_SEGMENT - 3)) - total_bad;
248 TRACE(ft_t_info, "%d Kb usable on this tape", good_sectors);
249 if (total_bad == 0) {
250 TRACE(ft_t_info,
251 "WARNING: this tape has no bad blocks registered !");
252 } else {
253 TRACE(ft_t_info, "%d bad sectors", total_bad);
254 }
255 TRACE_EXIT;
256}
257
258
259void ftape_extract_bad_sector_map(__u8 * buffer)
260{
261 TRACE_FUN(ft_t_any);
262
263 /* Fill the bad sector map with the contents of buffer.
264 */
265 if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
266 /* QIC-3010/3020 and wide QIC-80 tapes no longer have a failed
267 * sector log but use this area to extend the bad sector map.
268 */
269 bad_sector_map = &buffer[FT_HEADER_END];
270 } else {
271 /* non-wide QIC-80 tapes have a failed sector log area that
272 * mustn't be included in the bad sector map.
273 */
274 bad_sector_map = &buffer[FT_FSL + FT_FSL_SIZE];
275 }
276 if (ft_format_code == fmt_1100ft ||
277 ft_format_code == fmt_var ||
278 ft_format_code == fmt_big) {
279 bsm_hash_ptr = (SectorCount *)bad_sector_map;
280 } else {
281 bsm_hash_ptr = NULL;
282 }
283 bsm_debug_fake();
284 if (TRACE_LEVEL >= ft_t_info) {
285 print_bad_sector_map();
286 }
287 TRACE_EXIT;
288}
289
290static inline SectorMap cvt2map(unsigned int sector)
291{
292 return 1 << (((sector & 0x7fffff) - 1) % FT_SECTORS_PER_SEGMENT);
293}
294
295static inline int cvt2segment(unsigned int sector)
296{
297 return ((sector & 0x7fffff) - 1) / FT_SECTORS_PER_SEGMENT;
298}
299
300static int forward_seek_entry(int segment_id,
301 SectorCount **ptr,
302 SectorMap *map)
303{
304 unsigned int sector;
305 int segment;
306
307 do {
308 sector = get_sector((*ptr)++);
309 segment = cvt2segment(sector);
310 } while (sector != 0 && segment < segment_id);
311 (*ptr) --; /* point to first sector >= segment_id */
312 /* Get all sectors in segment_id
313 */
314 if (sector == 0 || segment != segment_id) {
315 *map = 0;
316 return 0;
317 } else if ((sector & 0x800000) &&
318 (ft_format_code == fmt_var || ft_format_code == fmt_big)) {
319 *map = EMPTY_SEGMENT;
320 return FT_SECTORS_PER_SEGMENT;
321 } else {
322 int count = 1;
323 SectorCount *tmp_ptr = (*ptr) + 1;
324
325 *map = cvt2map(sector);
326 while ((sector = get_sector(tmp_ptr++)) != 0 &&
327 (segment = cvt2segment(sector)) == segment_id) {
328 *map |= cvt2map(sector);
329 ++count;
330 }
331 return count;
332 }
333}
334
335static int backwards_seek_entry(int segment_id,
336 SectorCount **ptr,
337 SectorMap *map)
338{
339 unsigned int sector;
340 int segment; /* max unsigned int */
341
342 if (*ptr <= (SectorCount *)bad_sector_map) {
343 *map = 0;
344 return 0;
345 }
346 do {
347 sector = get_sector(--(*ptr));
348 segment = cvt2segment(sector);
349 } while (*ptr > (SectorCount *)bad_sector_map && segment > segment_id);
350 if (segment > segment_id) { /* at start of list, no entry found */
351 *map = 0;
352 return 0;
353 } else if (segment < segment_id) {
354 /* before smaller entry, adjust for overshoot */
355 (*ptr) ++;
356 *map = 0;
357 return 0;
358 } else if ((sector & 0x800000) &&
359 (ft_format_code == fmt_big || ft_format_code == fmt_var)) {
360 *map = EMPTY_SEGMENT;
361 return FT_SECTORS_PER_SEGMENT;
362 } else { /* get all sectors in segment_id */
363 int count = 1;
364
365 *map = cvt2map(sector);
366 while(*ptr > (SectorCount *)bad_sector_map) {
367 sector = get_sector(--(*ptr));
368 segment = cvt2segment(sector);
369 if (segment != segment_id) {
370 break;
371 }
372 *map |= cvt2map(sector);
373 ++count;
374 }
375 if (segment < segment_id) {
376 (*ptr) ++;
377 }
378 return count;
379 }
380}
381
382#if 0
383static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map)
384{
385 SectorCount *ptr = (SectorCount *)bad_sector_map;
386 int count;
387 int new_count;
388 SectorMap map;
389 TRACE_FUN(ft_t_any);
390
391 if (ft_format_code == fmt_1100ft ||
392 ft_format_code == fmt_var ||
393 ft_format_code == fmt_big) {
394 count = forward_seek_entry(segment_id, &ptr, &map);
395 new_count = count_ones(new_map);
396 /* If format code == 4 put empty segment instead of 32
397 * bad sectors.
398 */
399 if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
400 if (new_count == FT_SECTORS_PER_SEGMENT) {
401 new_count = 1;
402 }
403 if (count == FT_SECTORS_PER_SEGMENT) {
404 count = 1;
405 }
406 }
407 if (count != new_count) {
408 /* insert (or delete if < 0) new_count - count
409 * entries. Move trailing part of list
410 * including terminating 0.
411 */
412 SectorCount *hi_ptr = ptr;
413
414 do {
415 } while (get_sector(hi_ptr++) != 0);
416 /* Note: ptr is of type byte *, and each bad sector
417 * consumes 3 bytes.
418 */
419 memmove(ptr + new_count, ptr + count,
420 (size_t)(hi_ptr - (ptr + count))*sizeof(SectorCount));
421 }
422 TRACE(ft_t_noise, "putting map 0x%08x at %p, segment %d",
423 (unsigned int)new_map, ptr, segment_id);
424 if (new_count == 1 && new_map == EMPTY_SEGMENT) {
425 put_sector(ptr++, (0x800001 +
426 segment_id *
427 FT_SECTORS_PER_SEGMENT));
428 } else {
429 int i = 0;
430
431 while (new_map) {
432 if (new_map & 1) {
433 put_sector(ptr++,
434 1 + segment_id *
435 FT_SECTORS_PER_SEGMENT + i);
436 }
437 ++i;
438 new_map >>= 1;
439 }
440 }
441 } else {
442 ((SectorMap *) bad_sector_map)[segment_id] = new_map;
443 }
444 TRACE_EXIT;
445}
446#endif /* 0 */
447
448SectorMap ftape_get_bad_sector_entry(int segment_id)
449{
450 if (ft_used_header_segment == -1) {
451 /* When reading header segment we'll need a blank map.
452 */
453 return 0;
454 } else if (bsm_hash_ptr != NULL) {
455 /* Invariants:
456 * map - mask value returned on last call.
457 * bsm_hash_ptr - points to first sector greater or equal to
458 * first sector in last_referenced segment.
459 * last_referenced - segment id used in the last call,
460 * sector and map belong to this id.
461 * This code is designed for sequential access and retries.
462 * For true random access it may have to be redesigned.
463 */
464 static int last_reference = -1;
465 static SectorMap map;
466
467 if (segment_id > last_reference) {
468 /* Skip all sectors before segment_id
469 */
470 forward_seek_entry(segment_id, &bsm_hash_ptr, &map);
471 } else if (segment_id < last_reference) {
472 /* Skip backwards until begin of buffer or
473 * first sector in segment_id
474 */
475 backwards_seek_entry(segment_id, &bsm_hash_ptr, &map);
476 } /* segment_id == last_reference : keep map */
477 last_reference = segment_id;
478 return map;
479 } else {
480 return ((SectorMap *) bad_sector_map)[segment_id];
481 }
482}
483
484/* This is simply here to prevent us from overwriting other kernel
485 * data. Writes will result in NULL Pointer dereference.
486 */
487void ftape_init_bsm(void)
488{
489 bad_sector_map = NULL;
490 bsm_hash_ptr = NULL;
491}
diff --git a/drivers/char/ftape/lowlevel/ftape-bsm.h b/drivers/char/ftape/lowlevel/ftape-bsm.h
deleted file mode 100644
index ed45465af4d4..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-bsm.h
+++ /dev/null
@@ -1,66 +0,0 @@
1#ifndef _FTAPE_BSM_H
2#define _FTAPE_BSM_H
3
4/*
5 * Copyright (C) 1994-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-bsm.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:07 $
26 *
27 * This file contains definitions for the bad sector map handling
28 * routines for the QIC-117 floppy-tape driver for Linux.
29 */
30
31#include <linux/ftape.h>
32#include <linux/ftape-header-segment.h>
33
34#define EMPTY_SEGMENT (0xffffffff)
35#define FAKE_SEGMENT (0xfffffffe)
36
37/* maximum (format code 4) bad sector map size (bytes).
38 */
39#define BAD_SECTOR_MAP_SIZE (29 * SECTOR_SIZE - 256)
40
41/* format code 4 bad sector entry, ftape uses this
42 * internally for all format codes
43 */
44typedef __u32 SectorMap;
45/* variable and 1100 ft bad sector map entry. These three bytes represent
46 * a single sector address measured from BOT.
47 */
48typedef struct NewSectorMap {
49 __u8 bytes[3];
50} SectorCount;
51
52
53/*
54 * ftape-bsm.c defined global vars.
55 */
56
57/*
58 * ftape-bsm.c defined global functions.
59 */
60extern void update_bad_sector_map(__u8 * buffer);
61extern void ftape_extract_bad_sector_map(__u8 * buffer);
62extern SectorMap ftape_get_bad_sector_entry(int segment_id);
63extern __u8 *ftape_find_end_of_bsm_list(__u8 * address);
64extern void ftape_init_bsm(void);
65
66#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.c b/drivers/char/ftape/lowlevel/ftape-buffer.c
deleted file mode 100644
index c706ff162771..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-buffer.c
+++ /dev/null
@@ -1,130 +0,0 @@
1/*
2 * Copyright (C) 1997 Claus-Justus Heine
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 *
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $
20 * $Revision: 1.3 $
21 * $Date: 1997/10/16 23:33:11 $
22 *
23 * This file contains the allocator/dealloctor for ftape's dynamic dma
24 * buffer.
25 */
26
27#include <linux/slab.h>
28#include <linux/mm.h>
29#include <linux/mman.h>
30#include <asm/dma.h>
31
32#include <linux/ftape.h>
33#include "../lowlevel/ftape-rw.h"
34#include "../lowlevel/ftape-read.h"
35#include "../lowlevel/ftape-tracing.h"
36#include "../lowlevel/ftape-buffer.h"
37
38/* DMA'able memory allocation stuff.
39 */
40
41static inline void *dmaalloc(size_t size)
42{
43 unsigned long addr;
44
45 if (size == 0) {
46 return NULL;
47 }
48 addr = __get_dma_pages(GFP_KERNEL, get_order(size));
49 if (addr) {
50 struct page *page;
51
52 for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)
53 SetPageReserved(page);
54 }
55 return (void *)addr;
56}
57
58static inline void dmafree(void *addr, size_t size)
59{
60 if (size > 0) {
61 struct page *page;
62
63 for (page = virt_to_page((unsigned long)addr);
64 page < virt_to_page((unsigned long)addr+size); page++)
65 ClearPageReserved(page);
66 free_pages((unsigned long) addr, get_order(size));
67 }
68}
69
70static int add_one_buffer(void)
71{
72 TRACE_FUN(ft_t_flow);
73
74 if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) {
75 TRACE_EXIT -ENOMEM;
76 }
77 ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL);
78 if (ft_buffer[ft_nr_buffers] == NULL) {
79 TRACE_EXIT -ENOMEM;
80 }
81 memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct));
82 ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE);
83 if (ft_buffer[ft_nr_buffers]->address == NULL) {
84 kfree(ft_buffer[ft_nr_buffers]);
85 ft_buffer[ft_nr_buffers] = NULL;
86 TRACE_EXIT -ENOMEM;
87 }
88 ft_nr_buffers ++;
89 TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p",
90 ft_nr_buffers,
91 ft_buffer[ft_nr_buffers-1],
92 ft_buffer[ft_nr_buffers-1]->address);
93 TRACE_EXIT 0;
94}
95
96static void del_one_buffer(void)
97{
98 TRACE_FUN(ft_t_flow);
99 if (ft_nr_buffers > 0) {
100 TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p",
101 ft_nr_buffers,
102 ft_buffer[ft_nr_buffers-1],
103 ft_buffer[ft_nr_buffers-1]->address);
104 ft_nr_buffers --;
105 dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE);
106 kfree(ft_buffer[ft_nr_buffers]);
107 ft_buffer[ft_nr_buffers] = NULL;
108 }
109 TRACE_EXIT;
110}
111
112int ftape_set_nr_buffers(int cnt)
113{
114 int delta = cnt - ft_nr_buffers;
115 TRACE_FUN(ft_t_flow);
116
117 if (delta > 0) {
118 while (delta--) {
119 if (add_one_buffer() < 0) {
120 TRACE_EXIT -ENOMEM;
121 }
122 }
123 } else if (delta < 0) {
124 while (delta++) {
125 del_one_buffer();
126 }
127 }
128 ftape_zap_read_buffers();
129 TRACE_EXIT 0;
130}
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.h b/drivers/char/ftape/lowlevel/ftape-buffer.h
deleted file mode 100644
index eec99cee8f82..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-buffer.h
+++ /dev/null
@@ -1,32 +0,0 @@
1#ifndef _FTAPE_BUFFER_H
2#define _FTAPE_BUFFER_H
3
4/*
5 * Copyright (C) 1997 Claus-Justus Heine.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:18:08 $
25 *
26 * This file contains the allocator/dealloctor for ftape's dynamic dma
27 * buffer.
28 */
29
30extern int ftape_set_nr_buffers(int cnt);
31
32#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c
deleted file mode 100644
index 8e50bfd35a52..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-calibr.c
+++ /dev/null
@@ -1,275 +0,0 @@
1/*
2 * Copyright (C) 1993-1996 Bas Laarhoven.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 *
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.c,v $
20 * $Revision: 1.2 $
21 * $Date: 1997/10/05 19:18:08 $
22 *
23 * GP calibration routine for processor speed dependent
24 * functions.
25 */
26
27#include <linux/errno.h>
28#include <linux/jiffies.h>
29#include <asm/system.h>
30#include <asm/io.h>
31#if defined(__alpha__)
32# include <asm/hwrpb.h>
33#elif defined(__x86_64__)
34# include <asm/msr.h>
35# include <asm/timex.h>
36#elif defined(__i386__)
37# include <linux/timex.h>
38#endif
39#include <linux/ftape.h>
40#include "../lowlevel/ftape-tracing.h"
41#include "../lowlevel/ftape-calibr.h"
42#include "../lowlevel/fdc-io.h"
43
44#undef DEBUG
45
46#if !defined(__alpha__) && !defined(__i386__) && !defined(__x86_64__)
47# error Ftape is not implemented for this architecture!
48#endif
49
50#if defined(__alpha__) || defined(__x86_64__)
51static unsigned long ps_per_cycle = 0;
52#endif
53
54static spinlock_t calibr_lock;
55
56/*
57 * Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is
58 * too slow for certain timeouts (and that clock doesn't even tick
59 * when interrupts are disabled). For that reason, the 8254 timer is
60 * used directly to implement fine-grained timeouts. However, on
61 * Alpha PCs, the 8254 is *not* used to implement the clock tick
62 * (which is 1024 Hz, normally) and the 8254 timer runs at some
63 * "random" frequency (it seems to run at 18Hz, but it's not safe to
64 * rely on this value). Instead, we use the Alpha's "rpcc"
65 * instruction to read cycle counts. As this is a 32 bit counter,
66 * it will overflow only once per 30 seconds (on a 200MHz machine),
67 * which is plenty.
68 */
69
70unsigned int ftape_timestamp(void)
71{
72#if defined(__alpha__)
73 unsigned long r;
74
75 asm volatile ("rpcc %0" : "=r" (r));
76 return r;
77#elif defined(__x86_64__)
78 unsigned long r;
79 rdtscl(r);
80 return r;
81#elif defined(__i386__)
82
83/*
84 * Note that there is some time between counter underflowing and jiffies
85 * increasing, so the code below won't always give correct output.
86 * -Vojtech
87 */
88
89 unsigned long flags;
90 __u16 lo;
91 __u16 hi;
92
93 spin_lock_irqsave(&calibr_lock, flags);
94 outb_p(0x00, 0x43); /* latch the count ASAP */
95 lo = inb_p(0x40); /* read the latched count */
96 lo |= inb(0x40) << 8;
97 hi = jiffies;
98 spin_unlock_irqrestore(&calibr_lock, flags);
99 return ((hi + 1) * (unsigned int) LATCH) - lo; /* downcounter ! */
100#endif
101}
102
103static unsigned int short_ftape_timestamp(void)
104{
105#if defined(__alpha__) || defined(__x86_64__)
106 return ftape_timestamp();
107#elif defined(__i386__)
108 unsigned int count;
109 unsigned long flags;
110
111 spin_lock_irqsave(&calibr_lock, flags);
112 outb_p(0x00, 0x43); /* latch the count ASAP */
113 count = inb_p(0x40); /* read the latched count */
114 count |= inb(0x40) << 8;
115 spin_unlock_irqrestore(&calibr_lock, flags);
116 return (LATCH - count); /* normal: downcounter */
117#endif
118}
119
120static unsigned int diff(unsigned int t0, unsigned int t1)
121{
122#if defined(__alpha__) || defined(__x86_64__)
123 return (t1 - t0);
124#elif defined(__i386__)
125 /*
126 * This is tricky: to work for both short and full ftape_timestamps
127 * we'll have to discriminate between these.
128 * If it _looks_ like short stamps with wrapping around we'll
129 * asume it are. This will generate a small error if it really
130 * was a (very large) delta from full ftape_timestamps.
131 */
132 return (t1 <= t0 && t0 <= LATCH) ? t1 + LATCH - t0 : t1 - t0;
133#endif
134}
135
136static unsigned int usecs(unsigned int count)
137{
138#if defined(__alpha__) || defined(__x86_64__)
139 return (ps_per_cycle * count) / 1000000UL;
140#elif defined(__i386__)
141 return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
142#endif
143}
144
145unsigned int ftape_timediff(unsigned int t0, unsigned int t1)
146{
147 /*
148 * Calculate difference in usec for ftape_timestamp results t0 & t1.
149 * Note that on the i386 platform with short time-stamps, the
150 * maximum allowed timespan is 1/HZ or we'll lose ticks!
151 */
152 return usecs(diff(t0, t1));
153}
154
155/* To get an indication of the I/O performance,
156 * measure the duration of the inb() function.
157 */
158static void time_inb(void)
159{
160 int i;
161 int t0, t1;
162 unsigned long flags;
163 int status;
164 TRACE_FUN(ft_t_any);
165
166 spin_lock_irqsave(&calibr_lock, flags);
167 t0 = short_ftape_timestamp();
168 for (i = 0; i < 1000; ++i) {
169 status = inb(fdc.msr);
170 }
171 t1 = short_ftape_timestamp();
172 spin_unlock_irqrestore(&calibr_lock, flags);
173 TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1));
174 TRACE_EXIT;
175}
176
177static void init_clock(void)
178{
179 TRACE_FUN(ft_t_any);
180
181#if defined(__x86_64__)
182 ps_per_cycle = 1000000000UL / cpu_khz;
183#elif defined(__alpha__)
184 extern struct hwrpb_struct *hwrpb;
185 ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
186#endif
187 TRACE_EXIT;
188}
189
190/*
191 * Input: function taking int count as parameter.
192 * pointers to calculated calibration variables.
193 */
194void ftape_calibrate(char *name,
195 void (*fun) (unsigned int),
196 unsigned int *calibr_count,
197 unsigned int *calibr_time)
198{
199 static int first_time = 1;
200 int i;
201 unsigned int tc = 0;
202 unsigned int count;
203 unsigned int time;
204#if defined(__i386__)
205 unsigned int old_tc = 0;
206 unsigned int old_count = 1;
207 unsigned int old_time = 1;
208#endif
209 TRACE_FUN(ft_t_flow);
210
211 if (first_time) { /* get idea of I/O performance */
212 init_clock();
213 time_inb();
214 first_time = 0;
215 }
216 /* value of timeout must be set so that on very slow systems
217 * it will give a time less than one jiffy, and on
218 * very fast systems it'll give reasonable precision.
219 */
220
221 count = 40;
222 for (i = 0; i < 15; ++i) {
223 unsigned int t0;
224 unsigned int t1;
225 unsigned int once;
226 unsigned int multiple;
227 unsigned long flags;
228
229 *calibr_count =
230 *calibr_time = count; /* set TC to 1 */
231 spin_lock_irqsave(&calibr_lock, flags);
232 fun(0); /* dummy, get code into cache */
233 t0 = short_ftape_timestamp();
234 fun(0); /* overhead + one test */
235 t1 = short_ftape_timestamp();
236 once = diff(t0, t1);
237 t0 = short_ftape_timestamp();
238 fun(count); /* overhead + count tests */
239 t1 = short_ftape_timestamp();
240 multiple = diff(t0, t1);
241 spin_unlock_irqrestore(&calibr_lock, flags);
242 time = ftape_timediff(0, multiple - once);
243 tc = (1000 * time) / (count - 1);
244 TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
245 usecs(once), count - 1, usecs(multiple), tc);
246#if defined(__alpha__) || defined(__x86_64__)
247 /*
248 * Increase the calibration count exponentially until the
249 * calibration time exceeds 100 ms.
250 */
251 if (time >= 100*1000) {
252 break;
253 }
254#elif defined(__i386__)
255 /*
256 * increase the count until the resulting time nears 2/HZ,
257 * then the tc will drop sharply because we lose LATCH counts.
258 */
259 if (tc <= old_tc / 2) {
260 time = old_time;
261 count = old_count;
262 break;
263 }
264 old_tc = tc;
265 old_count = count;
266 old_time = time;
267#endif
268 count *= 2;
269 }
270 *calibr_count = count - 1;
271 *calibr_time = time;
272 TRACE(ft_t_info, "TC for `%s()' = %d nsec (at %d counts)",
273 name, (1000 * *calibr_time) / *calibr_count, *calibr_count);
274 TRACE_EXIT;
275}
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.h b/drivers/char/ftape/lowlevel/ftape-calibr.h
deleted file mode 100644
index 0c7e75246c7d..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-calibr.h
+++ /dev/null
@@ -1,37 +0,0 @@
1#ifndef _FTAPE_CALIBR_H
2#define _FTAPE_CALIBR_H
3
4/*
5 * Copyright (C) 1993-1996 Bas Laarhoven.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.h,v $
23 * $Revision: 1.1 $
24 * $Date: 1997/09/19 09:05:26 $
25 *
26 * This file contains a gp calibration routine for
27 * hardware dependent timeout functions.
28 */
29
30extern void ftape_calibrate(char *name,
31 void (*fun) (unsigned int),
32 unsigned int *calibr_count,
33 unsigned int *calibr_time);
34extern unsigned int ftape_timestamp(void);
35extern unsigned int ftape_timediff(unsigned int t0, unsigned int t1);
36
37#endif /* _FTAPE_CALIBR_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.c b/drivers/char/ftape/lowlevel/ftape-ctl.c
deleted file mode 100644
index 5d7c1ce92d59..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ctl.c
+++ /dev/null
@@ -1,896 +0,0 @@
1/*
2 * Copyright (C) 1993-1996 Bas Laarhoven,
3 * 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/ftape-ctl.c,v $
21 * $Revision: 1.4 $
22 * $Date: 1997/11/11 14:37:44 $
23 *
24 * This file contains the non-read/write ftape functions for the
25 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
26 */
27
28#include <linux/errno.h>
29#include <linux/mm.h>
30#include <linux/mman.h>
31
32#include <linux/ftape.h>
33#include <linux/qic117.h>
34#include <asm/uaccess.h>
35#include <asm/io.h>
36
37/* ease porting between pre-2.4.x and later kernels */
38#define vma_get_pgoff(v) ((v)->vm_pgoff)
39
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"
47
48/* Global vars.
49 */
50ftape_info ftape_status = {
51/* vendor information */
52 { 0, }, /* drive type */
53/* data rates */
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 */
60 0, /* formatted */
61 1, /* no tape */
62 1, /* write protected */
63 1, /* new tape */
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 */
79 -1,
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 */
85 1, /* failure */
86/* history record */
87 { 0, } /* history record */
88};
89
90int ftape_segments_per_head = 1020;
91int ftape_segments_per_cylinder = 4;
92int ftape_init_drive_needed = 1; /* need to be global for ftape_reset_drive()
93 * in ftape-io.c
94 */
95
96/* Local vars.
97 */
98static const vendor_struct vendors[] = QIC117_VENDORS;
99static const wakeup_method methods[] = WAKEUP_METHODS;
100
101const ftape_info *ftape_get_status(void)
102{
103#if defined(STATUS_PARANOYA)
104 static ftape_info get_status;
105
106 get_status = ftape_status;
107 return &get_status;
108#else
109 return &ftape_status; /* maybe return only a copy of it to assure
110 * read only access
111 */
112#endif
113}
114
115static int ftape_not_operational(int status)
116{
117 /* return true if status indicates tape can not be used.
118 */
119 return ((status ^ QIC_STATUS_CARTRIDGE_PRESENT) &
120 (QIC_STATUS_ERROR |
121 QIC_STATUS_CARTRIDGE_PRESENT |
122 QIC_STATUS_NEW_CARTRIDGE));
123}
124
125int ftape_seek_to_eot(void)
126{
127 int status;
128 TRACE_FUN(ft_t_any);
129
130 TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
131 while ((status & QIC_STATUS_AT_EOT) == 0) {
132 if (ftape_not_operational(status)) {
133 TRACE_EXIT -EIO;
134 }
135 TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_FORWARD,
136 ftape_timeout.rewind,&status),);
137 }
138 TRACE_EXIT 0;
139}
140
141int ftape_seek_to_bot(void)
142{
143 int status;
144 TRACE_FUN(ft_t_any);
145
146 TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
147 while ((status & QIC_STATUS_AT_BOT) == 0) {
148 if (ftape_not_operational(status)) {
149 TRACE_EXIT -EIO;
150 }
151 TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_REVERSE,
152 ftape_timeout.rewind,&status),);
153 }
154 TRACE_EXIT 0;
155}
156
157static int ftape_new_cartridge(void)
158{
159 ft_location.track = -1; /* force seek on first access */
160 ftape_zap_read_buffers();
161 ftape_zap_write_buffers();
162 return 0;
163}
164
165int ftape_abort_operation(void)
166{
167 int result = 0;
168 int status;
169 TRACE_FUN(ft_t_flow);
170
171 if (ft_runner_status == running) {
172 TRACE(ft_t_noise, "aborting runner, waiting");
173
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.
177 */
178 result = ftape_dumb_stop();
179 }
180 if (ft_runner_status != idle) {
181 if (ft_runner_status == do_abort) {
182 TRACE(ft_t_noise, "forcing runner abort");
183 }
184 TRACE(ft_t_noise, "stopping tape");
185 result = ftape_stop_tape(&status);
186 ft_location.known = 0;
187 ft_runner_status = idle;
188 }
189 ftape_reset_buffer();
190 ftape_zap_read_buffers();
191 ftape_set_state(idle);
192 TRACE_EXIT result;
193}
194
195static int lookup_vendor_id(unsigned int vendor_id)
196{
197 int i = 0;
198
199 while (vendors[i].vendor_id != vendor_id) {
200 if (++i >= NR_ITEMS(vendors)) {
201 return -1;
202 }
203 }
204 return i;
205}
206
207static void ftape_detach_drive(void)
208{
209 TRACE_FUN(ft_t_any);
210
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 */
214 fdc_disable();
215 fdc_release_irq_and_dma();
216 fdc_release_regions();
217 TRACE_EXIT;
218}
219
220static void clear_history(void)
221{
222 ft_history.used = 0;
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 =
229 ft_history.retries =
230 ft_history.crc_errors =
231 ft_history.crc_failures =
232 ft_history.ecc_failures =
233 ft_history.corrected =
234 ft_history.defects =
235 ft_history.rewinds = 0;
236}
237
238static int ftape_activate_drive(vendor_struct * drive_type)
239{
240 int result = 0;
241 TRACE_FUN(ft_t_flow);
242
243 /* If we already know the drive type, wake it up.
244 * Else try to find out what kind of drive is attached.
245 */
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);
249 if (result < 0) {
250 TRACE(ft_t_err, "known wakeup method failed");
251 }
252 } else {
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);
257 }
258
259 /* Try to awaken the drive using all known methods.
260 * Lower tracing for a while.
261 */
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.
269 */
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);
274 } else {
275 result = -EIO;
276 }
277#else
278 result = ftape_wakeup_drive(drive_type->wake_up);
279#endif
280 if (result >= 0) {
281 TRACE(ft_t_warn, "drive wakeup method: %s",
282 methods[drive_type->wake_up].name);
283 break;
284 }
285 }
286 SET_TRACE_LEVEL(old_tracing);
287
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 !");
292 result = -ENODEV;
293 }
294 }
295 TRACE_EXIT result;
296}
297
298static int ftape_get_drive_status(void)
299{
300 int result;
301 int status;
302 TRACE_FUN(ft_t_flow);
303
304 ft_no_tape = ft_write_protected = 0;
305 /* Tape drive is activated now.
306 * First clear error status if present.
307 */
308 do {
309 result = ftape_ready_wait(ftape_timeout.reset, &status);
310 if (result < 0) {
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");
315 } else {
316 TRACE(ft_t_err, "ftape_ready_wait failed");
317 }
318 TRACE_EXIT -EIO;
319 }
320 /* Clear error condition (drive is ready !)
321 */
322 if (status & QIC_STATUS_ERROR) {
323 unsigned int error;
324 qic117_cmd_t command;
325
326 TRACE(ft_t_err, "error status set");
327 result = ftape_report_error(&error, &command, 1);
328 if (result < 0) {
329 TRACE(ft_t_err,
330 "report_error_code failed: %d", result);
331 /* hope it's working next time */
332 ftape_reset_drive();
333 TRACE_EXIT -EIO;
334 } else if (error != 0) {
335 TRACE(ft_t_noise, "error code : %d", error);
336 TRACE(ft_t_noise, "error command: %d", command);
337 }
338 }
339 if (status & QIC_STATUS_NEW_CARTRIDGE) {
340 unsigned int error;
341 qic117_cmd_t command;
342 const ft_trace_t old_tracing = TRACE_LEVEL;
343 SET_TRACE_LEVEL(ft_t_bug);
344
345 /* Undocumented feature: Must clear (not present!)
346 * error here or we'll fail later.
347 */
348 ftape_report_error(&error, &command, 1);
349
350 SET_TRACE_LEVEL(old_tracing);
351 TRACE(ft_t_info, "status: new cartridge");
352 ft_new_tape = 1;
353 } else {
354 ft_new_tape = 0;
355 }
356 FT_SIGNAL_EXIT(_DONT_BLOCK);
357 } while (status & QIC_STATUS_ERROR);
358
359 ft_no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT);
360 ft_write_protected = (status & QIC_STATUS_WRITE_PROTECT) != 0;
361 if (ft_no_tape) {
362 TRACE(ft_t_warn, "no cartridge present");
363 } else {
364 if (ft_write_protected) {
365 TRACE(ft_t_noise, "Write protected cartridge");
366 }
367 }
368 TRACE_EXIT 0;
369}
370
371static void ftape_log_vendor_id(void)
372{
373 int vendor_index;
374 TRACE_FUN(ft_t_flow);
375
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) {
380 vendor_index = 0;
381 /* hack to get rid of all this mail */
382 ft_drive_type.vendor_id = 0;
383 }
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.
389 */
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 */
402 } else {
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
410 ==
411 ft_drive_type.vendor_id) {
412 ++vendor_index;
413 } else {
414 break;
415 }
416 }
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);
426 }
427 }
428 TRACE_EXIT;
429}
430
431void ftape_calc_timeouts(unsigned int qic_std,
432 unsigned int data_rate,
433 unsigned int tape_len)
434{
435 int speed; /* deci-ips ! */
436 int ff_speed;
437 int length;
438 TRACE_FUN(ft_t_any);
439
440 /* tape transport speed
441 * data rate: QIC-40 QIC-80 QIC-3010 QIC-3020
442 *
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
447 *
448 * fast tape transport speed is at least 68 ips.
449 */
450 switch (qic_std) {
451 case QIC_TAPE_QIC40:
452 speed = (data_rate == 250) ? 250 : 500;
453 break;
454 case QIC_TAPE_QIC80:
455 speed = (data_rate == 500) ? 340 : 680;
456 break;
457 case QIC_TAPE_QIC3010:
458 speed = (data_rate == 500) ? 226 : 452;
459 break;
460 case QIC_TAPE_QIC3020:
461 speed = (data_rate == 1000) ? 226 : 452;
462 break;
463 default:
464 TRACE(ft_t_bug, "Unknown qic_std (bug) ?");
465 speed = 500;
466 break;
467 }
468 if (ft_drive_type.speed == 0) {
469 unsigned long t0;
470 static int dt = 0; /* keep gcc from complaining */
471 static int first_time = 1;
472
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.
478 */
479 if (first_time) {
480 ftape_seek_to_bot();
481 t0 = jiffies;
482 ftape_seek_to_eot();
483 ftape_seek_to_bot();
484 dt = (int) (((jiffies - t0) * FT_USPT) / 1000);
485 if (dt < 1) {
486 dt = 1; /* prevent div by zero on failures */
487 }
488 first_time = 0;
489 TRACE(ft_t_info,
490 "trying to determine seek timeout, got %d msec",
491 dt);
492 }
493 if (tape_len != 0) {
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);
505 }
506 }
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.
510 */
511 if (tape_len <= 0) {
512 TRACE(ft_t_noise,
513 "Unknown tape length, using maximal timeouts");
514 length = QIC_TOP_TAPE_LEN; /* use worst case values */
515 } else {
516 length = tape_len; /* use actual values */
517 }
518 if (ft_drive_type.speed == 0) {
519 ff_speed = speed;
520 } else {
521 ff_speed = ft_drive_type.speed;
522 }
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.
526 */
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",
534 speed, length,
535 (ftape_timeout.seek + 500) / 1000,
536 (ftape_timeout.rewind + 500) / 1000,
537 (ftape_timeout.reset + 500) / 1000);
538 TRACE_EXIT;
539}
540
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
543 *
544 */
545int ftape_calibrate_data_rate(unsigned int qic_std)
546{
547 int rate = ft_fdc_rate_limit;
548 int result;
549 TRACE_FUN(ft_t_flow);
550
551 ft_qic_std = qic_std;
552
553 if (ft_qic_std == -1) {
554 TRACE_ABORT(-EIO, ft_t_err,
555 "Unable to determine data rate if QIC standard is unknown");
556 }
557
558 /* Select highest rate supported by both fdc and drive.
559 * Start with highest rate supported by the fdc.
560 */
561 while (fdc_set_data_rate(rate) < 0 && rate > 250) {
562 rate /= 2;
563 }
564 TRACE(ft_t_info,
565 "Highest FDC supported data rate: %d Kbps", rate);
566 ft_fdc_max_rate = rate;
567 do {
568 result = ftape_set_data_rate(rate, ft_qic_std);
569 } while (result == -EINVAL && (rate /= 2) > 250);
570 if (result < 0) {
571 TRACE_ABORT(-EIO, ft_t_err, "set datarate failed");
572 }
573 ft_data_rate = rate;
574 TRACE_EXIT 0;
575}
576
577static int ftape_init_drive(void)
578{
579 int status;
580 qic_model model;
581 unsigned int qic_std;
582 unsigned int data_rate;
583 TRACE_FUN(ft_t_flow);
584
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.
592 */
593 /* Tape should be at bot if new cartridge ! */
594 ftape_seek_to_bot();
595 }
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,
599 ftape_timeout.reset,
600 &status),);
601 }
602 }
603 ft_formatted = (status & QIC_STATUS_REFERENCED) != 0;
604 if (!ft_formatted) {
605 TRACE(ft_t_warn, "Warning: tape is not formatted !");
606 }
607
608 /* report configuration aborts when ftape_tape_len == -1
609 * unknown qic_std is okay if not formatted.
610 */
611 TRACE_CATCH(ftape_report_configuration(&model,
612 &data_rate,
613 &qic_std,
614 &ftape_tape_len),);
615
616 /* Maybe add the following to the /proc entry
617 */
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);
623
624 if (ft_formatted) {
625 /* initialize ft_used_data_rate to maximum value
626 * and set ft_qic_std
627 */
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")));
635 } else {
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")));
641 }
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!
645 */
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!",
654 ft_drive_type.name);
655 ft_write_protected = 1;
656 }
657 } else {
658 /* Doesn't make too much sense to set the data rate
659 * because we don't know what to use for the write
660 * precompensation.
661 * Need to do this again when formatting the cartridge.
662 */
663 ft_data_rate = data_rate;
664 ftape_calc_timeouts(QIC_TAPE_QIC40,
665 data_rate,
666 ftape_tape_len);
667 }
668 ftape_new_cartridge();
669 TRACE_EXIT 0;
670}
671
672static void ftape_munmap(void)
673{
674 int i;
675 TRACE_FUN(ft_t_flow);
676
677 for (i = 0; i < ft_nr_buffers; i++) {
678 ft_buffer[i]->mmapped = 0;
679 }
680 TRACE_EXIT;
681}
682
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.
686 */
687int ftape_mmap(struct vm_area_struct *vma)
688{
689 int num_buffers;
690 int i;
691 TRACE_FUN(ft_t_flow);
692
693 if (ft_failure) {
694 TRACE_EXIT -ENODEV;
695 }
696 if (!(vma->vm_flags & (VM_READ|VM_WRITE))) {
697 TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access");
698 }
699 if (vma_get_pgoff(vma) != 0) {
700 TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0");
701 }
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,
706 FT_BUFF_SIZE);
707 }
708 num_buffers = (vma->vm_end - vma->vm_start) / FT_BUFF_SIZE;
709 if (num_buffers > ft_nr_buffers) {
710 TRACE_ABORT(-EINVAL,
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);
714 }
715 if (ft_driver_state != idle) {
716 /* this also clears the buffer states
717 */
718 ftape_abort_operation();
719 } else {
720 ftape_reset_buffer();
721 }
722 for (i = 0; i < num_buffers; i++) {
723 unsigned long pfn;
724
725 pfn = virt_to_phys(ft_buffer[i]->address) >> PAGE_SHIFT;
726 TRACE_CATCH(remap_pfn_range(vma, vma->vm_start +
727 i * FT_BUFF_SIZE,
728 pfn,
729 FT_BUFF_SIZE,
730 vma->vm_page_prot),
731 _res = -EAGAIN);
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));
735 }
736 for (i = 0; i < num_buffers; i++) {
737 memset(ft_buffer[i]->address, 0xAA, FT_BUFF_SIZE);
738 ft_buffer[i]->mmapped++;
739 }
740 TRACE_EXIT 0;
741}
742
743static void ftape_init_driver(void); /* forward declaration */
744
745/* OPEN routine called by kernel-interface code
746 */
747int ftape_enable(int drive_selection)
748{
749 TRACE_FUN(ft_t_any);
750
751 if (ft_drive_sel == -1 || ft_drive_sel != drive_selection) {
752 /* Other selection than last time
753 */
754 ftape_init_driver();
755 }
756 ft_drive_sel = FTAPE_SEL(drive_selection);
757 ft_failure = 0;
758 TRACE_CATCH(fdc_init(),); /* init & detect fdc */
759 TRACE_CATCH(ftape_activate_drive(&ft_drive_type),
760 fdc_disable();
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();
766 }
767 if (ft_new_tape) {
768 ftape_init_drive_needed = 1;
769 }
770 if (!ft_no_tape && ftape_init_drive_needed) {
771 TRACE_CATCH(ftape_init_drive(), ftape_detach_drive());
772 }
773 ftape_munmap(); /* clear the mmap flag */
774 clear_history();
775 TRACE_EXIT 0;
776}
777
778/* release routine called by the high level interface modules
779 * zftape or sftape.
780 */
781void ftape_disable(void)
782{
783 int i;
784 TRACE_FUN(ft_t_any);
785
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);
790 }
791 }
792 if (sigtestsetmask(&current->pending.signal, _DONT_BLOCK) &&
793 !(sigtestsetmask(&current->pending.signal, _NEVER_BLOCK)) &&
794 ftape_tape_running) {
795 TRACE(ft_t_warn,
796 "Interrupted by fatal signal and tape still running");
797 ftape_dumb_stop();
798 ftape_abort_operation(); /* it's annoying */
799 } else {
800 ftape_set_state(idle);
801 }
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,
816 ft_history.retries);
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);
825 }
826 if (ft_history.defects > 0) {
827 TRACE(ft_t_warn, "Warning: %d media defects!",
828 ft_history.defects);
829 }
830 if (ft_history.rewinds > 0) {
831 TRACE(ft_t_info, "tape motion statistics:\n"
832 KERN_INFO "repositions : %3d",
833 ft_history.rewinds);
834 }
835 }
836 ft_failure = 1;
837 TRACE_EXIT;
838}
839
840static void ftape_init_driver(void)
841{
842 TRACE_FUN(ft_t_flow);
843
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";
848
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;
855
856 ft_qic_std = -1;
857 ftape_tape_len = 0; /* unknown */
858 ftape_current_command = 0;
859 ftape_current_cylinder = -1;
860
861 ft_segments_per_track = 102;
862 ftape_segments_per_head = 1020;
863 ftape_segments_per_cylinder = 4;
864 ft_tracks_per_tape = 20;
865
866 ft_failure = 1;
867
868 ft_formatted = 0;
869 ft_no_tape = 1;
870 ft_write_protected = 1;
871 ft_new_tape = 1;
872
873 ft_driver_state = idle;
874
875 ft_data_rate =
876 ft_fdc_max_rate = 500;
877 ft_drive_max_rate = 0; /* triggers set_rate_test() */
878
879 ftape_init_drive_needed = 1;
880
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;
886
887 ft_location.track = -1;
888 ft_location.known = 0;
889
890 ftape_tape_running = 0;
891 ftape_might_be_off_track = 1;
892
893 ftape_new_cartridge(); /* init some tape related variables */
894 ftape_init_bsm();
895 TRACE_EXIT;
896}
diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.h b/drivers/char/ftape/lowlevel/ftape-ctl.h
deleted file mode 100644
index 5f5e30bc3615..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ctl.h
+++ /dev/null
@@ -1,162 +0,0 @@
1#ifndef _FTAPE_CTL_H
2#define _FTAPE_CTL_H
3
4/*
5 * Copyright (C) 1993-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:09 $
26 *
27 * This file contains the non-standard IOCTL related definitions
28 * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for
29 * Linux.
30 */
31
32#include <linux/ioctl.h>
33#include <linux/mtio.h>
34#include <linux/ftape-vendors.h>
35
36#include "../lowlevel/ftape-rw.h"
37#include <linux/ftape-header-segment.h>
38
39typedef struct {
40 int used; /* any reading or writing done */
41 /* isr statistics */
42 unsigned int id_am_errors; /* id address mark not found */
43 unsigned int id_crc_errors; /* crc error in id address mark */
44 unsigned int data_am_errors; /* data address mark not found */
45 unsigned int data_crc_errors; /* crc error in data field */
46 unsigned int overrun_errors; /* fdc access timing problem */
47 unsigned int no_data_errors; /* sector not found */
48 unsigned int retries; /* number of tape retries */
49 /* ecc statistics */
50 unsigned int crc_errors; /* crc error in data */
51 unsigned int crc_failures; /* bad data without crc error */
52 unsigned int ecc_failures; /* failed to correct */
53 unsigned int corrected; /* total sectors corrected */
54 /* general statistics */
55 unsigned int rewinds; /* number of tape rewinds */
56 unsigned int defects; /* bad sectors due to media defects */
57} history_record;
58
59/* this structure contains * ALL * information that we want
60 * our child modules to know about, but don't want them to
61 * modify.
62 */
63typedef struct {
64 /* vendor information */
65 vendor_struct fti_drive_type;
66 /* data rates */
67 unsigned int fti_used_data_rate;
68 unsigned int fti_drive_max_rate;
69 unsigned int fti_fdc_max_rate;
70 /* drive selection, either FTAPE_SEL_A/B/C/D */
71 int fti_drive_sel;
72 /* flags set after decode the drive and tape status */
73 unsigned int fti_formatted :1;
74 unsigned int fti_no_tape :1;
75 unsigned int fti_write_protected:1;
76 unsigned int fti_new_tape :1;
77 /* values of last queried drive/tape status and error */
78 ft_drive_error fti_last_error;
79 ft_drive_status fti_last_status;
80 /* cartridge geometry */
81 unsigned int fti_tracks_per_tape;
82 unsigned int fti_segments_per_track;
83 /* location of header segments, etc. */
84 int fti_used_header_segment;
85 int fti_header_segment_1;
86 int fti_header_segment_2;
87 int fti_first_data_segment;
88 int fti_last_data_segment;
89 /* the format code as stored in the header segment */
90 ft_format_type fti_format_code;
91 /* the following is the sole reason for the ftape_set_status() call */
92 unsigned int fti_qic_std;
93 /* is tape running? */
94 volatile enum runner_status_enum fti_runner_status;
95 /* is tape reading/writing/verifying/formatting/deleting */
96 buffer_state_enum fti_state;
97 /* flags fatal hardware error */
98 unsigned int fti_failure:1;
99 /* history record */
100 history_record fti_history;
101} ftape_info;
102
103/* vendor information */
104#define ft_drive_type ftape_status.fti_drive_type
105/* data rates */
106#define ft_data_rate ftape_status.fti_used_data_rate
107#define ft_drive_max_rate ftape_status.fti_drive_max_rate
108#define ft_fdc_max_rate ftape_status.fti_fdc_max_rate
109/* drive selection, either FTAPE_SEL_A/B/C/D */
110#define ft_drive_sel ftape_status.fti_drive_sel
111/* flags set after decode the drive and tape status */
112#define ft_formatted ftape_status.fti_formatted
113#define ft_no_tape ftape_status.fti_no_tape
114#define ft_write_protected ftape_status.fti_write_protected
115#define ft_new_tape ftape_status.fti_new_tape
116/* values of last queried drive/tape status and error */
117#define ft_last_error ftape_status.fti_last_error
118#define ft_last_status ftape_status.fti_last_status
119/* cartridge geometry */
120#define ft_tracks_per_tape ftape_status.fti_tracks_per_tape
121#define ft_segments_per_track ftape_status.fti_segments_per_track
122/* the format code as stored in the header segment */
123#define ft_format_code ftape_status.fti_format_code
124/* the qic status as returned by report drive configuration */
125#define ft_qic_std ftape_status.fti_qic_std
126#define ft_used_header_segment ftape_status.fti_used_header_segment
127#define ft_header_segment_1 ftape_status.fti_header_segment_1
128#define ft_header_segment_2 ftape_status.fti_header_segment_2
129#define ft_first_data_segment ftape_status.fti_first_data_segment
130#define ft_last_data_segment ftape_status.fti_last_data_segment
131/* is tape running? */
132#define ft_runner_status ftape_status.fti_runner_status
133/* is tape reading/writing/verifying/formatting/deleting */
134#define ft_driver_state ftape_status.fti_state
135/* flags fatal hardware error */
136#define ft_failure ftape_status.fti_failure
137/* history record */
138#define ft_history ftape_status.fti_history
139
140/*
141 * ftape-ctl.c defined global vars.
142 */
143extern ftape_info ftape_status;
144extern int ftape_segments_per_head;
145extern int ftape_segments_per_cylinder;
146extern int ftape_init_drive_needed;
147
148/*
149 * ftape-ctl.c defined global functions.
150 */
151extern int ftape_mmap(struct vm_area_struct *vma);
152extern int ftape_enable(int drive_selection);
153extern void ftape_disable(void);
154extern int ftape_seek_to_bot(void);
155extern int ftape_seek_to_eot(void);
156extern int ftape_abort_operation(void);
157extern void ftape_calc_timeouts(unsigned int qic_std,
158 unsigned int data_rate,
159 unsigned int tape_len);
160extern int ftape_calibrate_data_rate(unsigned int qic_std);
161extern const ftape_info *ftape_get_status(void);
162#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-ecc.c b/drivers/char/ftape/lowlevel/ftape-ecc.c
deleted file mode 100644
index e5632f674bc8..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ecc.c
+++ /dev/null
@@ -1,853 +0,0 @@
1/*
2 *
3 * Copyright (c) 1993 Ning and David Mosberger.
4
5 This is based on code originally written by Bas Laarhoven (bas@vimec.nl)
6 and David L. Brown, Jr., and incorporates improvements suggested by
7 Kai Harrekilde-Petersen.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
13
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
22 USA.
23
24 *
25 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.c,v $
26 * $Revision: 1.3 $
27 * $Date: 1997/10/05 19:18:10 $
28 *
29 * This file contains the Reed-Solomon error correction code
30 * for the QIC-40/80 floppy-tape driver for Linux.
31 */
32
33#include <linux/ftape.h>
34
35#include "../lowlevel/ftape-tracing.h"
36#include "../lowlevel/ftape-ecc.h"
37
38/* Machines that are big-endian should define macro BIG_ENDIAN.
39 * Unfortunately, there doesn't appear to be a standard include file
40 * that works for all OSs.
41 */
42
43#if defined(__sparc__) || defined(__hppa)
44#define BIG_ENDIAN
45#endif /* __sparc__ || __hppa */
46
47#if defined(__mips__)
48#error Find a smart way to determine the Endianness of the MIPS CPU
49#endif
50
51/* Notice: to minimize the potential for confusion, we use r to
52 * denote the independent variable of the polynomials in the
53 * Galois Field GF(2^8). We reserve x for polynomials that
54 * that have coefficients in GF(2^8).
55 *
56 * The Galois Field in which coefficient arithmetic is performed are
57 * the polynomials over Z_2 (i.e., 0 and 1) modulo the irreducible
58 * polynomial f(r), where f(r)=r^8 + r^7 + r^2 + r + 1. A polynomial
59 * is represented as a byte with the MSB as the coefficient of r^7 and
60 * the LSB as the coefficient of r^0. For example, the binary
61 * representation of f(x) is 0x187 (of course, this doesn't fit into 8
62 * bits). In this field, the polynomial r is a primitive element.
63 * That is, r^i with i in 0,...,255 enumerates all elements in the
64 * field.
65 *
66 * The generator polynomial for the QIC-80 ECC is
67 *
68 * g(x) = x^3 + r^105*x^2 + r^105*x + 1
69 *
70 * which can be factored into:
71 *
72 * g(x) = (x-r^-1)(x-r^0)(x-r^1)
73 *
74 * the byte representation of the coefficients are:
75 *
76 * r^105 = 0xc0
77 * r^-1 = 0xc3
78 * r^0 = 0x01
79 * r^1 = 0x02
80 *
81 * Notice that r^-1 = r^254 as exponent arithmetic is performed
82 * modulo 2^8-1 = 255.
83 *
84 * For more information on Galois Fields and Reed-Solomon codes, refer
85 * to any good book. I found _An Introduction to Error Correcting
86 * Codes with Applications_ by S. A. Vanstone and P. C. van Oorschot
87 * to be a good introduction into the former. _CODING THEORY: The
88 * Essentials_ I found very useful for its concise description of
89 * Reed-Solomon encoding/decoding.
90 *
91 */
92
93typedef __u8 Matrix[3][3];
94
95/*
96 * gfpow[] is defined such that gfpow[i] returns r^i if
97 * i is in the range [0..255].
98 */
99static const __u8 gfpow[] =
100{
101 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
102 0x87, 0x89, 0x95, 0xad, 0xdd, 0x3d, 0x7a, 0xf4,
103 0x6f, 0xde, 0x3b, 0x76, 0xec, 0x5f, 0xbe, 0xfb,
104 0x71, 0xe2, 0x43, 0x86, 0x8b, 0x91, 0xa5, 0xcd,
105 0x1d, 0x3a, 0x74, 0xe8, 0x57, 0xae, 0xdb, 0x31,
106 0x62, 0xc4, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x67,
107 0xce, 0x1b, 0x36, 0x6c, 0xd8, 0x37, 0x6e, 0xdc,
108 0x3f, 0x7e, 0xfc, 0x7f, 0xfe, 0x7b, 0xf6, 0x6b,
109 0xd6, 0x2b, 0x56, 0xac, 0xdf, 0x39, 0x72, 0xe4,
110 0x4f, 0x9e, 0xbb, 0xf1, 0x65, 0xca, 0x13, 0x26,
111 0x4c, 0x98, 0xb7, 0xe9, 0x55, 0xaa, 0xd3, 0x21,
112 0x42, 0x84, 0x8f, 0x99, 0xb5, 0xed, 0x5d, 0xba,
113 0xf3, 0x61, 0xc2, 0x03, 0x06, 0x0c, 0x18, 0x30,
114 0x60, 0xc0, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0,
115 0x47, 0x8e, 0x9b, 0xb1, 0xe5, 0x4d, 0x9a, 0xb3,
116 0xe1, 0x45, 0x8a, 0x93, 0xa1, 0xc5, 0x0d, 0x1a,
117 0x34, 0x68, 0xd0, 0x27, 0x4e, 0x9c, 0xbf, 0xf9,
118 0x75, 0xea, 0x53, 0xa6, 0xcb, 0x11, 0x22, 0x44,
119 0x88, 0x97, 0xa9, 0xd5, 0x2d, 0x5a, 0xb4, 0xef,
120 0x59, 0xb2, 0xe3, 0x41, 0x82, 0x83, 0x81, 0x85,
121 0x8d, 0x9d, 0xbd, 0xfd, 0x7d, 0xfa, 0x73, 0xe6,
122 0x4b, 0x96, 0xab, 0xd1, 0x25, 0x4a, 0x94, 0xaf,
123 0xd9, 0x35, 0x6a, 0xd4, 0x2f, 0x5e, 0xbc, 0xff,
124 0x79, 0xf2, 0x63, 0xc6, 0x0b, 0x16, 0x2c, 0x58,
125 0xb0, 0xe7, 0x49, 0x92, 0xa3, 0xc1, 0x05, 0x0a,
126 0x14, 0x28, 0x50, 0xa0, 0xc7, 0x09, 0x12, 0x24,
127 0x48, 0x90, 0xa7, 0xc9, 0x15, 0x2a, 0x54, 0xa8,
128 0xd7, 0x29, 0x52, 0xa4, 0xcf, 0x19, 0x32, 0x64,
129 0xc8, 0x17, 0x2e, 0x5c, 0xb8, 0xf7, 0x69, 0xd2,
130 0x23, 0x46, 0x8c, 0x9f, 0xb9, 0xf5, 0x6d, 0xda,
131 0x33, 0x66, 0xcc, 0x1f, 0x3e, 0x7c, 0xf8, 0x77,
132 0xee, 0x5b, 0xb6, 0xeb, 0x51, 0xa2, 0xc3, 0x01
133};
134
135/*
136 * This is a log table. That is, gflog[r^i] returns i (modulo f(r)).
137 * gflog[0] is undefined and the first element is therefore not valid.
138 */
139static const __u8 gflog[256] =
140{
141 0xff, 0x00, 0x01, 0x63, 0x02, 0xc6, 0x64, 0x6a,
142 0x03, 0xcd, 0xc7, 0xbc, 0x65, 0x7e, 0x6b, 0x2a,
143 0x04, 0x8d, 0xce, 0x4e, 0xc8, 0xd4, 0xbd, 0xe1,
144 0x66, 0xdd, 0x7f, 0x31, 0x6c, 0x20, 0x2b, 0xf3,
145 0x05, 0x57, 0x8e, 0xe8, 0xcf, 0xac, 0x4f, 0x83,
146 0xc9, 0xd9, 0xd5, 0x41, 0xbe, 0x94, 0xe2, 0xb4,
147 0x67, 0x27, 0xde, 0xf0, 0x80, 0xb1, 0x32, 0x35,
148 0x6d, 0x45, 0x21, 0x12, 0x2c, 0x0d, 0xf4, 0x38,
149 0x06, 0x9b, 0x58, 0x1a, 0x8f, 0x79, 0xe9, 0x70,
150 0xd0, 0xc2, 0xad, 0xa8, 0x50, 0x75, 0x84, 0x48,
151 0xca, 0xfc, 0xda, 0x8a, 0xd6, 0x54, 0x42, 0x24,
152 0xbf, 0x98, 0x95, 0xf9, 0xe3, 0x5e, 0xb5, 0x15,
153 0x68, 0x61, 0x28, 0xba, 0xdf, 0x4c, 0xf1, 0x2f,
154 0x81, 0xe6, 0xb2, 0x3f, 0x33, 0xee, 0x36, 0x10,
155 0x6e, 0x18, 0x46, 0xa6, 0x22, 0x88, 0x13, 0xf7,
156 0x2d, 0xb8, 0x0e, 0x3d, 0xf5, 0xa4, 0x39, 0x3b,
157 0x07, 0x9e, 0x9c, 0x9d, 0x59, 0x9f, 0x1b, 0x08,
158 0x90, 0x09, 0x7a, 0x1c, 0xea, 0xa0, 0x71, 0x5a,
159 0xd1, 0x1d, 0xc3, 0x7b, 0xae, 0x0a, 0xa9, 0x91,
160 0x51, 0x5b, 0x76, 0x72, 0x85, 0xa1, 0x49, 0xeb,
161 0xcb, 0x7c, 0xfd, 0xc4, 0xdb, 0x1e, 0x8b, 0xd2,
162 0xd7, 0x92, 0x55, 0xaa, 0x43, 0x0b, 0x25, 0xaf,
163 0xc0, 0x73, 0x99, 0x77, 0x96, 0x5c, 0xfa, 0x52,
164 0xe4, 0xec, 0x5f, 0x4a, 0xb6, 0xa2, 0x16, 0x86,
165 0x69, 0xc5, 0x62, 0xfe, 0x29, 0x7d, 0xbb, 0xcc,
166 0xe0, 0xd3, 0x4d, 0x8c, 0xf2, 0x1f, 0x30, 0xdc,
167 0x82, 0xab, 0xe7, 0x56, 0xb3, 0x93, 0x40, 0xd8,
168 0x34, 0xb0, 0xef, 0x26, 0x37, 0x0c, 0x11, 0x44,
169 0x6f, 0x78, 0x19, 0x9a, 0x47, 0x74, 0xa7, 0xc1,
170 0x23, 0x53, 0x89, 0xfb, 0x14, 0x5d, 0xf8, 0x97,
171 0x2e, 0x4b, 0xb9, 0x60, 0x0f, 0xed, 0x3e, 0xe5,
172 0xf6, 0x87, 0xa5, 0x17, 0x3a, 0xa3, 0x3c, 0xb7
173};
174
175/* This is a multiplication table for the factor 0xc0 (i.e., r^105 (mod f(r)).
176 * gfmul_c0[f] returns r^105 * f(r) (modulo f(r)).
177 */
178static const __u8 gfmul_c0[256] =
179{
180 0x00, 0xc0, 0x07, 0xc7, 0x0e, 0xce, 0x09, 0xc9,
181 0x1c, 0xdc, 0x1b, 0xdb, 0x12, 0xd2, 0x15, 0xd5,
182 0x38, 0xf8, 0x3f, 0xff, 0x36, 0xf6, 0x31, 0xf1,
183 0x24, 0xe4, 0x23, 0xe3, 0x2a, 0xea, 0x2d, 0xed,
184 0x70, 0xb0, 0x77, 0xb7, 0x7e, 0xbe, 0x79, 0xb9,
185 0x6c, 0xac, 0x6b, 0xab, 0x62, 0xa2, 0x65, 0xa5,
186 0x48, 0x88, 0x4f, 0x8f, 0x46, 0x86, 0x41, 0x81,
187 0x54, 0x94, 0x53, 0x93, 0x5a, 0x9a, 0x5d, 0x9d,
188 0xe0, 0x20, 0xe7, 0x27, 0xee, 0x2e, 0xe9, 0x29,
189 0xfc, 0x3c, 0xfb, 0x3b, 0xf2, 0x32, 0xf5, 0x35,
190 0xd8, 0x18, 0xdf, 0x1f, 0xd6, 0x16, 0xd1, 0x11,
191 0xc4, 0x04, 0xc3, 0x03, 0xca, 0x0a, 0xcd, 0x0d,
192 0x90, 0x50, 0x97, 0x57, 0x9e, 0x5e, 0x99, 0x59,
193 0x8c, 0x4c, 0x8b, 0x4b, 0x82, 0x42, 0x85, 0x45,
194 0xa8, 0x68, 0xaf, 0x6f, 0xa6, 0x66, 0xa1, 0x61,
195 0xb4, 0x74, 0xb3, 0x73, 0xba, 0x7a, 0xbd, 0x7d,
196 0x47, 0x87, 0x40, 0x80, 0x49, 0x89, 0x4e, 0x8e,
197 0x5b, 0x9b, 0x5c, 0x9c, 0x55, 0x95, 0x52, 0x92,
198 0x7f, 0xbf, 0x78, 0xb8, 0x71, 0xb1, 0x76, 0xb6,
199 0x63, 0xa3, 0x64, 0xa4, 0x6d, 0xad, 0x6a, 0xaa,
200 0x37, 0xf7, 0x30, 0xf0, 0x39, 0xf9, 0x3e, 0xfe,
201 0x2b, 0xeb, 0x2c, 0xec, 0x25, 0xe5, 0x22, 0xe2,
202 0x0f, 0xcf, 0x08, 0xc8, 0x01, 0xc1, 0x06, 0xc6,
203 0x13, 0xd3, 0x14, 0xd4, 0x1d, 0xdd, 0x1a, 0xda,
204 0xa7, 0x67, 0xa0, 0x60, 0xa9, 0x69, 0xae, 0x6e,
205 0xbb, 0x7b, 0xbc, 0x7c, 0xb5, 0x75, 0xb2, 0x72,
206 0x9f, 0x5f, 0x98, 0x58, 0x91, 0x51, 0x96, 0x56,
207 0x83, 0x43, 0x84, 0x44, 0x8d, 0x4d, 0x8a, 0x4a,
208 0xd7, 0x17, 0xd0, 0x10, 0xd9, 0x19, 0xde, 0x1e,
209 0xcb, 0x0b, 0xcc, 0x0c, 0xc5, 0x05, 0xc2, 0x02,
210 0xef, 0x2f, 0xe8, 0x28, 0xe1, 0x21, 0xe6, 0x26,
211 0xf3, 0x33, 0xf4, 0x34, 0xfd, 0x3d, 0xfa, 0x3a
212};
213
214
215/* Returns V modulo 255 provided V is in the range -255,-254,...,509.
216 */
217static inline __u8 mod255(int v)
218{
219 if (v > 0) {
220 if (v < 255) {
221 return v;
222 } else {
223 return v - 255;
224 }
225 } else {
226 return v + 255;
227 }
228}
229
230
231/* Add two numbers in the field. Addition in this field is equivalent
232 * to a bit-wise exclusive OR operation---subtraction is therefore
233 * identical to addition.
234 */
235static inline __u8 gfadd(__u8 a, __u8 b)
236{
237 return a ^ b;
238}
239
240
241/* Add two vectors of numbers in the field. Each byte in A and B gets
242 * added individually.
243 */
244static inline unsigned long gfadd_long(unsigned long a, unsigned long b)
245{
246 return a ^ b;
247}
248
249
250/* Multiply two numbers in the field:
251 */
252static inline __u8 gfmul(__u8 a, __u8 b)
253{
254 if (a && b) {
255 return gfpow[mod255(gflog[a] + gflog[b])];
256 } else {
257 return 0;
258 }
259}
260
261
262/* Just like gfmul, except we have already looked up the log of the
263 * second number.
264 */
265static inline __u8 gfmul_exp(__u8 a, int b)
266{
267 if (a) {
268 return gfpow[mod255(gflog[a] + b)];
269 } else {
270 return 0;
271 }
272}
273
274
275/* Just like gfmul_exp, except that A is a vector of numbers. That
276 * is, each byte in A gets multiplied by gfpow[mod255(B)].
277 */
278static inline unsigned long gfmul_exp_long(unsigned long a, int b)
279{
280 __u8 t;
281
282 if (sizeof(long) == 4) {
283 return (
284 ((t = (__u32)a >> 24 & 0xff) ?
285 (((__u32) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |
286 ((t = (__u32)a >> 16 & 0xff) ?
287 (((__u32) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |
288 ((t = (__u32)a >> 8 & 0xff) ?
289 (((__u32) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |
290 ((t = (__u32)a >> 0 & 0xff) ?
291 (((__u32) gfpow[mod255(gflog[t] + b)]) << 0) : 0));
292 } else if (sizeof(long) == 8) {
293 return (
294 ((t = (__u64)a >> 56 & 0xff) ?
295 (((__u64) gfpow[mod255(gflog[t] + b)]) << 56) : 0) |
296 ((t = (__u64)a >> 48 & 0xff) ?
297 (((__u64) gfpow[mod255(gflog[t] + b)]) << 48) : 0) |
298 ((t = (__u64)a >> 40 & 0xff) ?
299 (((__u64) gfpow[mod255(gflog[t] + b)]) << 40) : 0) |
300 ((t = (__u64)a >> 32 & 0xff) ?
301 (((__u64) gfpow[mod255(gflog[t] + b)]) << 32) : 0) |
302 ((t = (__u64)a >> 24 & 0xff) ?
303 (((__u64) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |
304 ((t = (__u64)a >> 16 & 0xff) ?
305 (((__u64) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |
306 ((t = (__u64)a >> 8 & 0xff) ?
307 (((__u64) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |
308 ((t = (__u64)a >> 0 & 0xff) ?
309 (((__u64) gfpow[mod255(gflog[t] + b)]) << 0) : 0));
310 } else {
311 TRACE_FUN(ft_t_any);
312 TRACE_ABORT(-1, ft_t_err, "Error: size of long is %d bytes",
313 (int)sizeof(long));
314 }
315}
316
317
318/* Divide two numbers in the field. Returns a/b (modulo f(x)).
319 */
320static inline __u8 gfdiv(__u8 a, __u8 b)
321{
322 if (!b) {
323 TRACE_FUN(ft_t_any);
324 TRACE_ABORT(0xff, ft_t_bug, "Error: division by zero");
325 } else if (a == 0) {
326 return 0;
327 } else {
328 return gfpow[mod255(gflog[a] - gflog[b])];
329 }
330}
331
332
333/* The following functions return the inverse of the matrix of the
334 * linear system that needs to be solved to determine the error
335 * magnitudes. The first deals with matrices of rank 3, while the
336 * second deals with matrices of rank 2. The error indices are passed
337 * in arguments L0,..,L2 (0=first sector, 31=last sector). The error
338 * indices must be sorted in ascending order, i.e., L0<L1<L2.
339 *
340 * The linear system that needs to be solved for the error magnitudes
341 * is A * b = s, where s is the known vector of syndromes, b is the
342 * vector of error magnitudes and A in the ORDER=3 case:
343 *
344 * A_3 = {{1/r^L[0], 1/r^L[1], 1/r^L[2]},
345 * { 1, 1, 1},
346 * { r^L[0], r^L[1], r^L[2]}}
347 */
348static inline int gfinv3(__u8 l0,
349 __u8 l1,
350 __u8 l2,
351 Matrix Ainv)
352{
353 __u8 det;
354 __u8 t20, t10, t21, t12, t01, t02;
355 int log_det;
356
357 /* compute some intermediate results: */
358 t20 = gfpow[l2 - l0]; /* t20 = r^l2/r^l0 */
359 t10 = gfpow[l1 - l0]; /* t10 = r^l1/r^l0 */
360 t21 = gfpow[l2 - l1]; /* t21 = r^l2/r^l1 */
361 t12 = gfpow[l1 - l2 + 255]; /* t12 = r^l1/r^l2 */
362 t01 = gfpow[l0 - l1 + 255]; /* t01 = r^l0/r^l1 */
363 t02 = gfpow[l0 - l2 + 255]; /* t02 = r^l0/r^l2 */
364 /* Calculate the determinant of matrix A_3^-1 (sometimes
365 * called the Vandermonde determinant):
366 */
367 det = gfadd(t20, gfadd(t10, gfadd(t21, gfadd(t12, gfadd(t01, t02)))));
368 if (!det) {
369 TRACE_FUN(ft_t_any);
370 TRACE_ABORT(0, ft_t_err,
371 "Inversion failed (3 CRC errors, >0 CRC failures)");
372 }
373 log_det = 255 - gflog[det];
374
375 /* Now, calculate all of the coefficients:
376 */
377 Ainv[0][0]= gfmul_exp(gfadd(gfpow[l1], gfpow[l2]), log_det);
378 Ainv[0][1]= gfmul_exp(gfadd(t21, t12), log_det);
379 Ainv[0][2]= gfmul_exp(gfadd(gfpow[255 - l1], gfpow[255 - l2]),log_det);
380
381 Ainv[1][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l2]), log_det);
382 Ainv[1][1]= gfmul_exp(gfadd(t20, t02), log_det);
383 Ainv[1][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l2]),log_det);
384
385 Ainv[2][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l1]), log_det);
386 Ainv[2][1]= gfmul_exp(gfadd(t10, t01), log_det);
387 Ainv[2][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l1]),log_det);
388
389 return 1;
390}
391
392
393static inline int gfinv2(__u8 l0, __u8 l1, Matrix Ainv)
394{
395 __u8 det;
396 __u8 t1, t2;
397 int log_det;
398
399 t1 = gfpow[255 - l0];
400 t2 = gfpow[255 - l1];
401 det = gfadd(t1, t2);
402 if (!det) {
403 TRACE_FUN(ft_t_any);
404 TRACE_ABORT(0, ft_t_err,
405 "Inversion failed (2 CRC errors, >0 CRC failures)");
406 }
407 log_det = 255 - gflog[det];
408
409 /* Now, calculate all of the coefficients:
410 */
411 Ainv[0][0] = Ainv[1][0] = gfpow[log_det];
412
413 Ainv[0][1] = gfmul_exp(t2, log_det);
414 Ainv[1][1] = gfmul_exp(t1, log_det);
415
416 return 1;
417}
418
419
420/* Multiply matrix A by vector S and return result in vector B. M is
421 * assumed to be of order NxN, S and B of order Nx1.
422 */
423static inline void gfmat_mul(int n, Matrix A,
424 __u8 *s, __u8 *b)
425{
426 int i, j;
427 __u8 dot_prod;
428
429 for (i = 0; i < n; ++i) {
430 dot_prod = 0;
431 for (j = 0; j < n; ++j) {
432 dot_prod = gfadd(dot_prod, gfmul(A[i][j], s[j]));
433 }
434 b[i] = dot_prod;
435 }
436}
437
438
439
440/* The Reed Solomon ECC codes are computed over the N-th byte of each
441 * block, where N=SECTOR_SIZE. There are up to 29 blocks of data, and
442 * 3 blocks of ECC. The blocks are stored contiguously in memory. A
443 * segment, consequently, is assumed to have at least 4 blocks: one or
444 * more data blocks plus three ECC blocks.
445 *
446 * Notice: In QIC-80 speak, a CRC error is a sector with an incorrect
447 * CRC. A CRC failure is a sector with incorrect data, but
448 * a valid CRC. In the error control literature, the former
449 * is usually called "erasure", the latter "error."
450 */
451/* Compute the parity bytes for C columns of data, where C is the
452 * number of bytes that fit into a long integer. We use a linear
453 * feed-back register to do this. The parity bytes P[0], P[STRIDE],
454 * P[2*STRIDE] are computed such that:
455 *
456 * x^k * p(x) + m(x) = 0 (modulo g(x))
457 *
458 * where k = NBLOCKS,
459 * p(x) = P[0] + P[STRIDE]*x + P[2*STRIDE]*x^2, and
460 * m(x) = sum_{i=0}^k m_i*x^i.
461 * m_i = DATA[i*SECTOR_SIZE]
462 */
463static inline void set_parity(unsigned long *data,
464 int nblocks,
465 unsigned long *p,
466 int stride)
467{
468 unsigned long p0, p1, p2, t1, t2, *end;
469
470 end = data + nblocks * (FT_SECTOR_SIZE / sizeof(long));
471 p0 = p1 = p2 = 0;
472 while (data < end) {
473 /* The new parity bytes p0_i, p1_i, p2_i are computed
474 * from the old values p0_{i-1}, p1_{i-1}, p2_{i-1}
475 * recursively as:
476 *
477 * p0_i = p1_{i-1} + r^105 * (m_{i-1} - p0_{i-1})
478 * p1_i = p2_{i-1} + r^105 * (m_{i-1} - p0_{i-1})
479 * p2_i = (m_{i-1} - p0_{i-1})
480 *
481 * With the initial condition: p0_0 = p1_0 = p2_0 = 0.
482 */
483 t1 = gfadd_long(*data, p0);
484 /*
485 * Multiply each byte in t1 by 0xc0:
486 */
487 if (sizeof(long) == 4) {
488 t2= (((__u32) gfmul_c0[(__u32)t1 >> 24 & 0xff]) << 24 |
489 ((__u32) gfmul_c0[(__u32)t1 >> 16 & 0xff]) << 16 |
490 ((__u32) gfmul_c0[(__u32)t1 >> 8 & 0xff]) << 8 |
491 ((__u32) gfmul_c0[(__u32)t1 >> 0 & 0xff]) << 0);
492 } else if (sizeof(long) == 8) {
493 t2= (((__u64) gfmul_c0[(__u64)t1 >> 56 & 0xff]) << 56 |
494 ((__u64) gfmul_c0[(__u64)t1 >> 48 & 0xff]) << 48 |
495 ((__u64) gfmul_c0[(__u64)t1 >> 40 & 0xff]) << 40 |
496 ((__u64) gfmul_c0[(__u64)t1 >> 32 & 0xff]) << 32 |
497 ((__u64) gfmul_c0[(__u64)t1 >> 24 & 0xff]) << 24 |
498 ((__u64) gfmul_c0[(__u64)t1 >> 16 & 0xff]) << 16 |
499 ((__u64) gfmul_c0[(__u64)t1 >> 8 & 0xff]) << 8 |
500 ((__u64) gfmul_c0[(__u64)t1 >> 0 & 0xff]) << 0);
501 } else {
502 TRACE_FUN(ft_t_any);
503 TRACE(ft_t_err, "Error: long is of size %d",
504 (int) sizeof(long));
505 TRACE_EXIT;
506 }
507 p0 = gfadd_long(t2, p1);
508 p1 = gfadd_long(t2, p2);
509 p2 = t1;
510 data += FT_SECTOR_SIZE / sizeof(long);
511 }
512 *p = p0;
513 p += stride;
514 *p = p1;
515 p += stride;
516 *p = p2;
517 return;
518}
519
520
521/* Compute the 3 syndrome values. DATA should point to the first byte
522 * of the column for which the syndromes are desired. The syndromes
523 * are computed over the first NBLOCKS of rows. The three bytes will
524 * be placed in S[0], S[1], and S[2].
525 *
526 * S[i] is the value of the "message" polynomial m(x) evaluated at the
527 * i-th root of the generator polynomial g(x).
528 *
529 * As g(x)=(x-r^-1)(x-1)(x-r^1) we evaluate the message polynomial at
530 * x=r^-1 to get S[0], at x=r^0=1 to get S[1], and at x=r to get S[2].
531 * This could be done directly and efficiently via the Horner scheme.
532 * However, it would require multiplication tables for the factors
533 * r^-1 (0xc3) and r (0x02). The following scheme does not require
534 * any multiplication tables beyond what's needed for set_parity()
535 * anyway and is slightly faster if there are no errors and slightly
536 * slower if there are errors. The latter is hopefully the infrequent
537 * case.
538 *
539 * To understand the alternative algorithm, notice that set_parity(m,
540 * k, p) computes parity bytes such that:
541 *
542 * x^k * p(x) = m(x) (modulo g(x)).
543 *
544 * That is, to evaluate m(r^m), where r^m is a root of g(x), we can
545 * simply evaluate (r^m)^k*p(r^m). Also, notice that p is 0 if and
546 * only if s is zero. That is, if all parity bytes are 0, we know
547 * there is no error in the data and consequently there is no need to
548 * compute s(x) at all! In all other cases, we compute s(x) from p(x)
549 * by evaluating (r^m)^k*p(r^m) for m=-1, m=0, and m=1. The p(x)
550 * polynomial is evaluated via the Horner scheme.
551 */
552static int compute_syndromes(unsigned long *data, int nblocks, unsigned long *s)
553{
554 unsigned long p[3];
555
556 set_parity(data, nblocks, p, 1);
557 if (p[0] | p[1] | p[2]) {
558 /* Some of the checked columns do not have a zero
559 * syndrome. For simplicity, we compute the syndromes
560 * for all columns that we have computed the
561 * remainders for.
562 */
563 s[0] = gfmul_exp_long(
564 gfadd_long(p[0],
565 gfmul_exp_long(
566 gfadd_long(p[1],
567 gfmul_exp_long(p[2], -1)),
568 -1)),
569 -nblocks);
570 s[1] = gfadd_long(gfadd_long(p[2], p[1]), p[0]);
571 s[2] = gfmul_exp_long(
572 gfadd_long(p[0],
573 gfmul_exp_long(
574 gfadd_long(p[1],
575 gfmul_exp_long(p[2], 1)),
576 1)),
577 nblocks);
578 return 0;
579 } else {
580 return 1;
581 }
582}
583
584
585/* Correct the block in the column pointed to by DATA. There are NBAD
586 * CRC errors and their indices are in BAD_LOC[0], up to
587 * BAD_LOC[NBAD-1]. If NBAD>1, Ainv holds the inverse of the matrix
588 * of the linear system that needs to be solved to determine the error
589 * magnitudes. S[0], S[1], and S[2] are the syndrome values. If row
590 * j gets corrected, then bit j will be set in CORRECTION_MAP.
591 */
592static inline int correct_block(__u8 *data, int nblocks,
593 int nbad, int *bad_loc, Matrix Ainv,
594 __u8 *s,
595 SectorMap * correction_map)
596{
597 int ncorrected = 0;
598 int i;
599 __u8 t1, t2;
600 __u8 c0, c1, c2; /* check bytes */
601 __u8 error_mag[3], log_error_mag;
602 __u8 *dp, l, e;
603 TRACE_FUN(ft_t_any);
604
605 switch (nbad) {
606 case 0:
607 /* might have a CRC failure: */
608 if (s[0] == 0) {
609 /* more than one error */
610 TRACE_ABORT(-1, ft_t_err,
611 "ECC failed (0 CRC errors, >1 CRC failures)");
612 }
613 t1 = gfdiv(s[1], s[0]);
614 if ((bad_loc[nbad++] = gflog[t1]) >= nblocks) {
615 TRACE(ft_t_err,
616 "ECC failed (0 CRC errors, >1 CRC failures)");
617 TRACE_ABORT(-1, ft_t_err,
618 "attempt to correct data at %d", bad_loc[0]);
619 }
620 error_mag[0] = s[1];
621 break;
622 case 1:
623 t1 = gfadd(gfmul_exp(s[1], bad_loc[0]), s[2]);
624 t2 = gfadd(gfmul_exp(s[0], bad_loc[0]), s[1]);
625 if (t1 == 0 && t2 == 0) {
626 /* one erasure, no error: */
627 Ainv[0][0] = gfpow[bad_loc[0]];
628 } else if (t1 == 0 || t2 == 0) {
629 /* one erasure and more than one error: */
630 TRACE_ABORT(-1, ft_t_err,
631 "ECC failed (1 erasure, >1 error)");
632 } else {
633 /* one erasure, one error: */
634 if ((bad_loc[nbad++] = gflog[gfdiv(t1, t2)])
635 >= nblocks) {
636 TRACE(ft_t_err, "ECC failed "
637 "(1 CRC errors, >1 CRC failures)");
638 TRACE_ABORT(-1, ft_t_err,
639 "attempt to correct data at %d",
640 bad_loc[1]);
641 }
642 if (!gfinv2(bad_loc[0], bad_loc[1], Ainv)) {
643 /* inversion failed---must have more
644 * than one error
645 */
646 TRACE_EXIT -1;
647 }
648 }
649 /* FALL THROUGH TO ERROR MAGNITUDE COMPUTATION:
650 */
651 case 2:
652 case 3:
653 /* compute error magnitudes: */
654 gfmat_mul(nbad, Ainv, s, error_mag);
655 break;
656
657 default:
658 TRACE_ABORT(-1, ft_t_err,
659 "Internal Error: number of CRC errors > 3");
660 }
661
662 /* Perform correction by adding ERROR_MAG[i] to the byte at
663 * offset BAD_LOC[i]. Also add the value of the computed
664 * error polynomial to the syndrome values. If the correction
665 * was successful, the resulting check bytes should be zero
666 * (i.e., the corrected data is a valid code word).
667 */
668 c0 = s[0];
669 c1 = s[1];
670 c2 = s[2];
671 for (i = 0; i < nbad; ++i) {
672 e = error_mag[i];
673 if (e) {
674 /* correct the byte at offset L by magnitude E: */
675 l = bad_loc[i];
676 dp = &data[l * FT_SECTOR_SIZE];
677 *dp = gfadd(*dp, e);
678 *correction_map |= 1 << l;
679 ++ncorrected;
680
681 log_error_mag = gflog[e];
682 c0 = gfadd(c0, gfpow[mod255(log_error_mag - l)]);
683 c1 = gfadd(c1, e);
684 c2 = gfadd(c2, gfpow[mod255(log_error_mag + l)]);
685 }
686 }
687 if (c0 || c1 || c2) {
688 TRACE_ABORT(-1, ft_t_err,
689 "ECC self-check failed, too many errors");
690 }
691 TRACE_EXIT ncorrected;
692}
693
694
695#if defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID)
696
697/* Perform a sanity check on the computed parity bytes:
698 */
699static int sanity_check(unsigned long *data, int nblocks)
700{
701 TRACE_FUN(ft_t_any);
702 unsigned long s[3];
703
704 if (!compute_syndromes(data, nblocks, s)) {
705 TRACE_ABORT(0, ft_bug,
706 "Internal Error: syndrome self-check failed");
707 }
708 TRACE_EXIT 1;
709}
710
711#endif /* defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID) */
712
713/* Compute the parity for an entire segment of data.
714 */
715int ftape_ecc_set_segment_parity(struct memory_segment *mseg)
716{
717 int i;
718 __u8 *parity_bytes;
719
720 parity_bytes = &mseg->data[(mseg->blocks - 3) * FT_SECTOR_SIZE];
721 for (i = 0; i < FT_SECTOR_SIZE; i += sizeof(long)) {
722 set_parity((unsigned long *) &mseg->data[i], mseg->blocks - 3,
723 (unsigned long *) &parity_bytes[i],
724 FT_SECTOR_SIZE / sizeof(long));
725#ifdef ECC_PARANOID
726 if (!sanity_check((unsigned long *) &mseg->data[i],
727 mseg->blocks)) {
728 return -1;
729 }
730#endif /* ECC_PARANOID */
731 }
732 return 0;
733}
734
735
736/* Checks and corrects (if possible) the segment MSEG. Returns one of
737 * ECC_OK, ECC_CORRECTED, and ECC_FAILED.
738 */
739int ftape_ecc_correct_data(struct memory_segment *mseg)
740{
741 int col, i, result;
742 int ncorrected = 0;
743 int nerasures = 0; /* # of erasures (CRC errors) */
744 int erasure_loc[3]; /* erasure locations */
745 unsigned long ss[3];
746 __u8 s[3];
747 Matrix Ainv;
748 TRACE_FUN(ft_t_flow);
749
750 mseg->corrected = 0;
751
752 /* find first column that has non-zero syndromes: */
753 for (col = 0; col < FT_SECTOR_SIZE; col += sizeof(long)) {
754 if (!compute_syndromes((unsigned long *) &mseg->data[col],
755 mseg->blocks, ss)) {
756 /* something is wrong---have to fix things */
757 break;
758 }
759 }
760 if (col >= FT_SECTOR_SIZE) {
761 /* all syndromes are ok, therefore nothing to correct */
762 TRACE_EXIT ECC_OK;
763 }
764 /* count the number of CRC errors if there were any: */
765 if (mseg->read_bad) {
766 for (i = 0; i < mseg->blocks; i++) {
767 if (BAD_CHECK(mseg->read_bad, i)) {
768 if (nerasures >= 3) {
769 /* this is too much for ECC */
770 TRACE_ABORT(ECC_FAILED, ft_t_err,
771 "ECC failed (>3 CRC errors)");
772 } /* if */
773 erasure_loc[nerasures++] = i;
774 }
775 }
776 }
777 /*
778 * If there are at least 2 CRC errors, determine inverse of matrix
779 * of linear system to be solved:
780 */
781 switch (nerasures) {
782 case 2:
783 if (!gfinv2(erasure_loc[0], erasure_loc[1], Ainv)) {
784 TRACE_EXIT ECC_FAILED;
785 }
786 break;
787 case 3:
788 if (!gfinv3(erasure_loc[0], erasure_loc[1],
789 erasure_loc[2], Ainv)) {
790 TRACE_EXIT ECC_FAILED;
791 }
792 break;
793 default:
794 /* this is not an error condition... */
795 break;
796 }
797
798 do {
799 for (i = 0; i < sizeof(long); ++i) {
800 s[0] = ss[0];
801 s[1] = ss[1];
802 s[2] = ss[2];
803 if (s[0] | s[1] | s[2]) {
804#ifdef BIG_ENDIAN
805 result = correct_block(
806 &mseg->data[col + sizeof(long) - 1 - i],
807 mseg->blocks,
808 nerasures,
809 erasure_loc,
810 Ainv,
811 s,
812 &mseg->corrected);
813#else
814 result = correct_block(&mseg->data[col + i],
815 mseg->blocks,
816 nerasures,
817 erasure_loc,
818 Ainv,
819 s,
820 &mseg->corrected);
821#endif
822 if (result < 0) {
823 TRACE_EXIT ECC_FAILED;
824 }
825 ncorrected += result;
826 }
827 ss[0] >>= 8;
828 ss[1] >>= 8;
829 ss[2] >>= 8;
830 }
831
832#ifdef ECC_SANITY_CHECK
833 if (!sanity_check((unsigned long *) &mseg->data[col],
834 mseg->blocks)) {
835 TRACE_EXIT ECC_FAILED;
836 }
837#endif /* ECC_SANITY_CHECK */
838
839 /* find next column with non-zero syndromes: */
840 while ((col += sizeof(long)) < FT_SECTOR_SIZE) {
841 if (!compute_syndromes((unsigned long *)
842 &mseg->data[col], mseg->blocks, ss)) {
843 /* something is wrong---have to fix things */
844 break;
845 }
846 }
847 } while (col < FT_SECTOR_SIZE);
848 if (ncorrected && nerasures == 0) {
849 TRACE(ft_t_warn, "block contained error not caught by CRC");
850 }
851 TRACE((ncorrected > 0) ? ft_t_noise : ft_t_any, "number of corrections: %d", ncorrected);
852 TRACE_EXIT ncorrected ? ECC_CORRECTED : ECC_OK;
853}
diff --git a/drivers/char/ftape/lowlevel/ftape-ecc.h b/drivers/char/ftape/lowlevel/ftape-ecc.h
deleted file mode 100644
index 4829146fe9a0..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-ecc.h
+++ /dev/null
@@ -1,84 +0,0 @@
1#ifndef _FTAPE_ECC_H_
2#define _FTAPE_ECC_H_
3
4/*
5 * Copyright (C) 1993 Ning and David Mosberger.
6 * Original:
7 * Copyright (C) 1993 Bas Laarhoven.
8 * Copyright (C) 1992 David L. Brown, Jr.
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; see the file COPYING. If not, write to
22 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
23 USA.
24
25 *
26 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.h,v $
27 * $Revision: 1.2 $
28 * $Date: 1997/10/05 19:18:11 $
29 *
30 * This file contains the definitions for the
31 * Reed-Solomon error correction code
32 * for the QIC-40/80 tape streamer device driver.
33 */
34
35#include "../lowlevel/ftape-bsm.h"
36
37#define BAD_CLEAR(entry) ((entry)=0)
38#define BAD_SET(entry,sector) ((entry)|=(1<<(sector)))
39#define BAD_CHECK(entry,sector) ((entry)&(1<<(sector)))
40
41/*
42 * Return values for ecc_correct_data:
43 */
44enum {
45 ECC_OK, /* Data was correct. */
46 ECC_CORRECTED, /* Correctable error in data. */
47 ECC_FAILED, /* Could not correct data. */
48};
49
50/*
51 * Representation of an in memory segment. MARKED_BAD lists the
52 * sectors that were marked bad during formatting. If the N-th sector
53 * in a segment is marked bad, bit 1<<N will be set in MARKED_BAD.
54 * The sectors should be read in from the disk and packed, as if the
55 * bad sectors were not there, and the segment just contained fewer
56 * sectors. READ_SECTORS is a bitmap of errors encountered while
57 * reading the data. These offsets are relative to the packed data.
58 * BLOCKS is a count of the sectors not marked bad. This is just to
59 * prevent having to count the zero bits in MARKED_BAD each time this
60 * is needed. DATA is the actual sector packed data from (or to) the
61 * tape.
62 */
63 struct memory_segment {
64 SectorMap marked_bad;
65 SectorMap read_bad;
66 int blocks;
67 __u8 *data;
68 SectorMap corrected;
69 };
70
71/*
72 * ecc.c defined global variables:
73 */
74#ifdef TEST
75extern int ftape_ecc_tracing;
76#endif
77
78/*
79 * ecc.c defined global functions:
80 */
81extern int ftape_ecc_correct_data(struct memory_segment *data);
82extern int ftape_ecc_set_segment_parity(struct memory_segment *data);
83
84#endif /* _FTAPE_ECC_H_ */
diff --git a/drivers/char/ftape/lowlevel/ftape-format.c b/drivers/char/ftape/lowlevel/ftape-format.c
deleted file mode 100644
index 5dd4c59a3f34..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-format.c
+++ /dev/null
@@ -1,344 +0,0 @@
1/*
2 * Copyright (C) 1997 Claus-Justus Heine.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 *
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.c,v $
20 * $Revision: 1.2.4.1 $
21 * $Date: 1997/11/14 16:05:39 $
22 *
23 * This file contains the code to support formatting of floppy
24 * tape cartridges with the QIC-40/80/3010/3020 floppy-tape
25 * driver "ftape" for Linux.
26 */
27
28#include <linux/string.h>
29#include <linux/errno.h>
30
31#include <linux/ftape.h>
32#include <linux/qic117.h>
33#include "../lowlevel/ftape-tracing.h"
34#include "../lowlevel/ftape-io.h"
35#include "../lowlevel/ftape-ctl.h"
36#include "../lowlevel/ftape-rw.h"
37#include "../lowlevel/ftape-ecc.h"
38#include "../lowlevel/ftape-bsm.h"
39#include "../lowlevel/ftape-format.h"
40
41#if defined(TESTING)
42#define FT_FMT_SEGS_PER_BUF 50
43#else
44#define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT))
45#endif
46
47static spinlock_t ftape_format_lock;
48
49/*
50 * first segment of the new buffer
51 */
52static int switch_segment;
53
54/*
55 * at most 256 segments fit into one 32 kb buffer. Even TR-1 cartridges have
56 * more than this many segments per track, so better be careful.
57 *
58 * buffer_struct *buff: buffer to store the formatting coordinates in
59 * int start: starting segment for this buffer.
60 * int spt: segments per track
61 *
62 * Note: segment ids are relative to the start of the track here.
63 */
64static void setup_format_buffer(buffer_struct *buff, int start, int spt,
65 __u8 gap3)
66{
67 int to_do = spt - start;
68 TRACE_FUN(ft_t_flow);
69
70 if (to_do > FT_FMT_SEGS_PER_BUF) {
71 to_do = FT_FMT_SEGS_PER_BUF;
72 }
73 buff->ptr = buff->address;
74 buff->remaining = to_do * FT_SECTORS_PER_SEGMENT; /* # sectors */
75 buff->bytes = buff->remaining * 4; /* need 4 bytes per sector */
76 buff->gap3 = gap3;
77 buff->segment_id = start;
78 buff->next_segment = start + to_do;
79 if (buff->next_segment >= spt) {
80 buff->next_segment = 0; /* 0 means: stop runner */
81 }
82 buff->status = waiting; /* tells the isr that it can use
83 * this buffer
84 */
85 TRACE_EXIT;
86}
87
88
89/*
90 * start formatting a new track.
91 */
92int ftape_format_track(const unsigned int track, const __u8 gap3)
93{
94 unsigned long flags;
95 buffer_struct *tail, *head;
96 int status;
97 TRACE_FUN(ft_t_flow);
98
99 TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
100 if (track & 1) {
101 if (!(status & QIC_STATUS_AT_EOT)) {
102 TRACE_CATCH(ftape_seek_to_eot(),);
103 }
104 } else {
105 if (!(status & QIC_STATUS_AT_BOT)) {
106 TRACE_CATCH(ftape_seek_to_bot(),);
107 }
108 }
109 ftape_abort_operation(); /* this sets ft_head = ft_tail = 0 */
110 ftape_set_state(formatting);
111
112 TRACE(ft_t_noise,
113 "Formatting track %d, logical: from segment %d to %d",
114 track, track * ft_segments_per_track,
115 (track + 1) * ft_segments_per_track - 1);
116
117 /*
118 * initialize the buffer switching protocol for this track
119 */
120 head = ftape_get_buffer(ft_queue_head); /* tape isn't running yet */
121 tail = ftape_get_buffer(ft_queue_tail); /* tape isn't running yet */
122 switch_segment = 0;
123 do {
124 FT_SIGNAL_EXIT(_DONT_BLOCK);
125 setup_format_buffer(tail, switch_segment,
126 ft_segments_per_track, gap3);
127 switch_segment = tail->next_segment;
128 } while ((switch_segment != 0) &&
129 ((tail = ftape_next_buffer(ft_queue_tail)) != head));
130 /* go */
131 head->status = formatting;
132 TRACE_CATCH(ftape_seek_head_to_track(track),);
133 TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD),);
134 spin_lock_irqsave(&ftape_format_lock, flags);
135 TRACE_CATCH(fdc_setup_formatting(head), restore_flags(flags));
136 spin_unlock_irqrestore(&ftape_format_lock, flags);
137 TRACE_EXIT 0;
138}
139
140/* return segment id of segment currently being formatted and do the
141 * buffer switching stuff.
142 */
143int ftape_format_status(unsigned int *segment_id)
144{
145 buffer_struct *tail = ftape_get_buffer(ft_queue_tail);
146 int result;
147 TRACE_FUN(ft_t_flow);
148
149 while (switch_segment != 0 &&
150 ftape_get_buffer(ft_queue_head) != tail) {
151 FT_SIGNAL_EXIT(_DONT_BLOCK);
152 /* need more buffers, first wait for empty buffer
153 */
154 TRACE_CATCH(ftape_wait_segment(formatting),);
155 /* don't worry for gap3. If we ever hit this piece of code,
156 * then all buffer already have the correct gap3 set!
157 */
158 setup_format_buffer(tail, switch_segment,
159 ft_segments_per_track, tail->gap3);
160 switch_segment = tail->next_segment;
161 if (switch_segment != 0) {
162 tail = ftape_next_buffer(ft_queue_tail);
163 }
164 }
165 /* should runner stop ?
166 */
167 if (ft_runner_status == aborting || ft_runner_status == do_abort) {
168 buffer_struct *head = ftape_get_buffer(ft_queue_head);
169 TRACE(ft_t_warn, "Error formatting segment %d",
170 ftape_get_buffer(ft_queue_head)->segment_id);
171 (void)ftape_abort_operation();
172 TRACE_EXIT (head->status != error) ? -EAGAIN : -EIO;
173 }
174 /*
175 * don't care if the timer expires, this is just kind of a
176 * "select" operation that lets the calling process sleep
177 * until something has happened
178 */
179 if (fdc_interrupt_wait(5 * FT_SECOND) < 0) {
180 TRACE(ft_t_noise, "End of track %d at segment %d",
181 ft_location.track,
182 ftape_get_buffer(ft_queue_head)->segment_id);
183 result = 1; /* end of track, unlock module */
184 } else {
185 result = 0;
186 }
187 /*
188 * the calling process should use the seg id to determine
189 * which parts of the dma buffers can be safely overwritten
190 * with new data.
191 */
192 *segment_id = ftape_get_buffer(ft_queue_head)->segment_id;
193 /*
194 * Internally we start counting segment ids from the start of
195 * each track when formatting, but externally we keep them
196 * relative to the start of the tape:
197 */
198 *segment_id += ft_location.track * ft_segments_per_track;
199 TRACE_EXIT result;
200}
201
202/*
203 * The segment id is relative to the start of the tape
204 */
205int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm)
206{
207 int result;
208 int verify_done = 0;
209 TRACE_FUN(ft_t_flow);
210
211 TRACE(ft_t_noise, "Verifying segment %d", segment_id);
212
213 if (ft_driver_state != verifying) {
214 TRACE(ft_t_noise, "calling ftape_abort_operation");
215 if (ftape_abort_operation() < 0) {
216 TRACE(ft_t_err, "ftape_abort_operation failed");
217 TRACE_EXIT -EIO;
218 }
219 }
220 *bsm = 0x00000000;
221 ftape_set_state(verifying);
222 for (;;) {
223 buffer_struct *tail;
224 /*
225 * Allow escape from this loop on signal
226 */
227 FT_SIGNAL_EXIT(_DONT_BLOCK);
228 /*
229 * Search all full buffers for the first matching the
230 * wanted segment. Clear other buffers on the fly.
231 */
232 tail = ftape_get_buffer(ft_queue_tail);
233 while (!verify_done && tail->status == done) {
234 /*
235 * Allow escape from this loop on signal !
236 */
237 FT_SIGNAL_EXIT(_DONT_BLOCK);
238 if (tail->segment_id == segment_id) {
239 /* If out buffer is already full,
240 * return its contents.
241 */
242 TRACE(ft_t_flow, "found segment in cache: %d",
243 segment_id);
244 if ((tail->soft_error_map |
245 tail->hard_error_map) != 0) {
246 TRACE(ft_t_info,"bsm[%d] = 0x%08lx",
247 segment_id,
248 (unsigned long)
249 (tail->soft_error_map |
250 tail->hard_error_map));
251 *bsm = (tail->soft_error_map |
252 tail->hard_error_map);
253 }
254 verify_done = 1;
255 } else {
256 TRACE(ft_t_flow,"zapping segment in cache: %d",
257 tail->segment_id);
258 }
259 tail->status = waiting;
260 tail = ftape_next_buffer(ft_queue_tail);
261 }
262 if (!verify_done && tail->status == verifying) {
263 if (tail->segment_id == segment_id) {
264 switch(ftape_wait_segment(verifying)) {
265 case 0:
266 break;
267 case -EINTR:
268 TRACE_ABORT(-EINTR, ft_t_warn,
269 "interrupted by "
270 "non-blockable signal");
271 break;
272 default:
273 ftape_abort_operation();
274 ftape_set_state(verifying);
275 /* be picky */
276 TRACE_ABORT(-EIO, ft_t_warn,
277 "wait_segment failed");
278 }
279 } else {
280 /* We're reading the wrong segment,
281 * stop runner.
282 */
283 TRACE(ft_t_noise, "verifying wrong segment");
284 ftape_abort_operation();
285 ftape_set_state(verifying);
286 }
287 }
288 /* should runner stop ?
289 */
290 if (ft_runner_status == aborting) {
291 buffer_struct *head = ftape_get_buffer(ft_queue_head);
292 if (head->status == error ||
293 head->status == verifying) {
294 /* no data or overrun error */
295 head->status = waiting;
296 }
297 TRACE_CATCH(ftape_dumb_stop(),);
298 } else {
299 /* If just passed last segment on tape: wait
300 * for BOT or EOT mark. Sets ft_runner_status to
301 * idle if at lEOT and successful
302 */
303 TRACE_CATCH(ftape_handle_logical_eot(),);
304 }
305 if (verify_done) {
306 TRACE_EXIT 0;
307 }
308 /* Now at least one buffer is idle!
309 * Restart runner & tape if needed.
310 */
311 /* We could optimize the following a little bit. We know that
312 * the bad sector map is empty.
313 */
314 tail = ftape_get_buffer(ft_queue_tail);
315 if (tail->status == waiting) {
316 buffer_struct *head = ftape_get_buffer(ft_queue_head);
317
318 ftape_setup_new_segment(head, segment_id, -1);
319 ftape_calc_next_cluster(head);
320 if (ft_runner_status == idle) {
321 result = ftape_start_tape(segment_id,
322 head->sector_offset);
323 switch(result) {
324 case 0:
325 break;
326 case -ETIME:
327 case -EINTR:
328 TRACE_ABORT(result, ft_t_err, "Error: "
329 "segment %d unreachable",
330 segment_id);
331 break;
332 default:
333 *bsm = EMPTY_SEGMENT;
334 TRACE_EXIT 0;
335 break;
336 }
337 }
338 head->status = verifying;
339 fdc_setup_read_write(head, FDC_VERIFY);
340 }
341 }
342 /* not reached */
343 TRACE_EXIT -EIO;
344}
diff --git a/drivers/char/ftape/lowlevel/ftape-format.h b/drivers/char/ftape/lowlevel/ftape-format.h
deleted file mode 100644
index f15161566643..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-format.h
+++ /dev/null
@@ -1,37 +0,0 @@
1#ifndef _FTAPE_FORMAT_H
2#define _FTAPE_FORMAT_H
3
4/*
5 * Copyright (C) 1996-1997 Claus-Justus Heine.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:18:13 $
25 *
26 * This file contains the low level definitions for the
27 * formatting support for the QIC-40/80/3010/3020 floppy-tape
28 * driver "ftape" for Linux.
29 */
30
31#ifdef __KERNEL__
32extern int ftape_format_track(const unsigned int track, const __u8 gap3);
33extern int ftape_format_status(unsigned int *segment_id);
34extern int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm);
35#endif /* __KERNEL__ */
36
37#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c
deleted file mode 100644
index 4998132a81d1..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-init.c
+++ /dev/null
@@ -1,160 +0,0 @@
1/*
2 * Copyright (C) 1993-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 * This file contains the code that interfaces the kernel
21 * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.
22 */
23
24#include <linux/module.h>
25#include <linux/errno.h>
26#include <linux/fs.h>
27#include <linux/kernel.h>
28#include <linux/signal.h>
29#include <linux/major.h>
30
31#include <linux/ftape.h>
32#include <linux/init.h>
33#include <linux/qic117.h>
34#ifdef CONFIG_ZFTAPE
35#include <linux/zftape.h>
36#endif
37
38#include "../lowlevel/ftape-init.h"
39#include "../lowlevel/ftape-io.h"
40#include "../lowlevel/ftape-read.h"
41#include "../lowlevel/ftape-write.h"
42#include "../lowlevel/ftape-ctl.h"
43#include "../lowlevel/ftape-rw.h"
44#include "../lowlevel/fdc-io.h"
45#include "../lowlevel/ftape-buffer.h"
46#include "../lowlevel/ftape-proc.h"
47#include "../lowlevel/ftape-tracing.h"
48
49
50#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)
51static int ft_tracing = -1;
52#endif
53
54
55/* Called by modules package when installing the driver
56 * or by kernel during the initialization phase
57 */
58static int __init ftape_init(void)
59{
60 TRACE_FUN(ft_t_flow);
61
62#ifdef MODULE
63#ifndef CONFIG_FT_NO_TRACE_AT_ALL
64 if (ft_tracing != -1) {
65 ftape_tracing = ft_tracing;
66 }
67#endif
68 printk(KERN_INFO FTAPE_VERSION "\n");
69 if (TRACE_LEVEL >= ft_t_info) {
70 printk(
71KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n"
72KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n"
73KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
74KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n");
75 }
76#else /* !MODULE */
77 /* print a short no-nonsense boot message */
78 printk(KERN_INFO FTAPE_VERSION "\n");
79#endif /* MODULE */
80 TRACE(ft_t_info, "installing QIC-117 floppy tape hardware drive ... ");
81 TRACE(ft_t_info, "ftape_init @ 0x%p", ftape_init);
82 /* Allocate the DMA buffers. They are deallocated at cleanup() time.
83 */
84#ifdef TESTING
85#ifdef MODULE
86 while (ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS) < 0) {
87 ftape_sleep(FT_SECOND/20);
88 if (signal_pending(current)) {
89 (void)ftape_set_nr_buffers(0);
90 TRACE(ft_t_bug,
91 "Killed by signal while allocating buffers.");
92 TRACE_ABORT(-EINTR,
93 ft_t_bug, "Free up memory and retry");
94 }
95 }
96#else
97 TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),
98 (void)ftape_set_nr_buffers(0));
99#endif
100#else
101 TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),
102 (void)ftape_set_nr_buffers(0));
103#endif
104 ft_drive_sel = -1;
105 ft_failure = 1; /* inhibit any operation but open */
106 ftape_udelay_calibrate(); /* must be before fdc_wait_calibrate ! */
107 fdc_wait_calibrate();
108#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
109 (void)ftape_proc_init();
110#endif
111#ifdef CONFIG_ZFTAPE
112 (void)zft_init();
113#endif
114 TRACE_EXIT 0;
115}
116
117module_param(ft_fdc_base, uint, 0);
118MODULE_PARM_DESC(ft_fdc_base, "Base address of FDC controller.");
119module_param(ft_fdc_irq, uint, 0);
120MODULE_PARM_DESC(ft_fdc_irq, "IRQ (interrupt channel) to use.");
121module_param(ft_fdc_dma, uint, 0);
122MODULE_PARM_DESC(ft_fdc_dma, "DMA channel to use.");
123module_param(ft_fdc_threshold, uint, 0);
124MODULE_PARM_DESC(ft_fdc_threshold, "Threshold of the FDC Fifo.");
125module_param(ft_fdc_rate_limit, uint, 0);
126MODULE_PARM_DESC(ft_fdc_rate_limit, "Maximal data rate for FDC.");
127module_param(ft_probe_fc10, bool, 0);
128MODULE_PARM_DESC(ft_probe_fc10,
129 "If non-zero, probe for a Colorado FC-10/FC-20 controller.");
130module_param(ft_mach2, bool, 0);
131MODULE_PARM_DESC(ft_mach2,
132 "If non-zero, probe for a Mountain MACH-2 controller.");
133#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)
134module_param(ft_tracing, int, 0644);
135MODULE_PARM_DESC(ft_tracing,
136 "Amount of debugging output, 0 <= tracing <= 8, default 3.");
137#endif
138
139MODULE_AUTHOR(
140 "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl), "
141 "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no), "
142 "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)");
143MODULE_DESCRIPTION(
144 "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives.");
145MODULE_LICENSE("GPL");
146
147static void __exit ftape_exit(void)
148{
149 TRACE_FUN(ft_t_flow);
150
151#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
152 ftape_proc_destroy();
153#endif
154 (void)ftape_set_nr_buffers(0);
155 printk(KERN_INFO "ftape: unloaded.\n");
156 TRACE_EXIT;
157}
158
159module_init(ftape_init);
160module_exit(ftape_exit);
diff --git a/drivers/char/ftape/lowlevel/ftape-init.h b/drivers/char/ftape/lowlevel/ftape-init.h
deleted file mode 100644
index 99a7b8ab086f..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-init.h
+++ /dev/null
@@ -1,43 +0,0 @@
1#ifndef _FTAPE_INIT_H
2#define _FTAPE_INIT_H
3
4/*
5 * Copyright (C) 1993-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-init.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:16 $
26 *
27 * This file contains the definitions for the interface to
28 * the Linux kernel for floppy tape driver ftape.
29 *
30 */
31
32#include <linux/linkage.h>
33#include <linux/signal.h>
34
35#define _NEVER_BLOCK (sigmask(SIGKILL) | sigmask(SIGSTOP))
36#define _DONT_BLOCK (_NEVER_BLOCK | sigmask(SIGINT))
37#define _DO_BLOCK (sigmask(SIGPIPE))
38
39#ifndef QIC117_TAPE_MAJOR
40#define QIC117_TAPE_MAJOR 27
41#endif
42
43#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-io.c b/drivers/char/ftape/lowlevel/ftape-io.c
deleted file mode 100644
index 259015aeff55..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-io.c
+++ /dev/null
@@ -1,992 +0,0 @@
1/*
2 * Copyright (C) 1993-1996 Bas Laarhoven,
3 * (C) 1996 Kai Harrekilde-Petersen,
4 * (C) 1997 Claus-Justus Heine.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 *
21 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.c,v $
22 * $Revision: 1.4 $
23 * $Date: 1997/11/11 14:02:36 $
24 *
25 * This file contains the general control functions for the
26 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
27 */
28
29#include <linux/errno.h>
30#include <linux/sched.h>
31#include <linux/mm.h>
32#include <asm/system.h>
33#include <linux/ioctl.h>
34#include <linux/mtio.h>
35#include <linux/delay.h>
36
37#include <linux/ftape.h>
38#include <linux/qic117.h>
39#include "../lowlevel/ftape-tracing.h"
40#include "../lowlevel/fdc-io.h"
41#include "../lowlevel/ftape-io.h"
42#include "../lowlevel/ftape-ctl.h"
43#include "../lowlevel/ftape-rw.h"
44#include "../lowlevel/ftape-write.h"
45#include "../lowlevel/ftape-read.h"
46#include "../lowlevel/ftape-init.h"
47#include "../lowlevel/ftape-calibr.h"
48
49/* Global vars.
50 */
51/* NOTE: sectors start numbering at 1, all others at 0 ! */
52ft_timeout_table ftape_timeout;
53unsigned int ftape_tape_len;
54volatile qic117_cmd_t ftape_current_command;
55const struct qic117_command_table qic117_cmds[] = QIC117_COMMANDS;
56int ftape_might_be_off_track;
57
58/* Local vars.
59 */
60static int diagnostic_mode;
61static unsigned int ftape_udelay_count;
62static unsigned int ftape_udelay_time;
63
64void ftape_udelay(unsigned int usecs)
65{
66 volatile int count = (ftape_udelay_count * usecs +
67 ftape_udelay_count - 1) / ftape_udelay_time;
68 volatile int i;
69
70 while (count-- > 0) {
71 for (i = 0; i < 20; ++i);
72 }
73}
74
75void ftape_udelay_calibrate(void)
76{
77 ftape_calibrate("ftape_udelay",
78 ftape_udelay, &ftape_udelay_count, &ftape_udelay_time);
79}
80
81/* Delay (msec) routine.
82 */
83void ftape_sleep(unsigned int time)
84{
85 TRACE_FUN(ft_t_any);
86
87 time *= 1000; /* msecs -> usecs */
88 if (time < FT_USPT) {
89 /* Time too small for scheduler, do a busy wait ! */
90 ftape_udelay(time);
91 } else {
92 long timeout;
93 unsigned long flags;
94 unsigned int ticks = (time + FT_USPT - 1) / FT_USPT;
95
96 TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks);
97 timeout = ticks;
98 save_flags(flags);
99 sti();
100 msleep_interruptible(jiffies_to_msecs(timeout));
101 /* Mmm. Isn't current->blocked == 0xffffffff ?
102 */
103 if (signal_pending(current)) {
104 TRACE(ft_t_err, "awoken by non-blocked signal :-(");
105 }
106 restore_flags(flags);
107 }
108 TRACE_EXIT;
109}
110
111/* send a command or parameter to the drive
112 * Generates # of step pulses.
113 */
114static inline int ft_send_to_drive(int arg)
115{
116 /* Always wait for a command_timeout period to separate
117 * individuals commands and/or parameters.
118 */
119 ftape_sleep(3 * FT_MILLISECOND);
120 /* Keep cylinder nr within range, step towards home if possible.
121 */
122 if (ftape_current_cylinder >= arg) {
123 return fdc_seek(ftape_current_cylinder - arg);
124 } else {
125 return fdc_seek(ftape_current_cylinder + arg);
126 }
127}
128
129/* forward */ int ftape_report_raw_drive_status(int *status);
130
131static int ft_check_cmd_restrictions(qic117_cmd_t command)
132{
133 int status = -1;
134 TRACE_FUN(ft_t_any);
135
136 TRACE(ft_t_flow, "%s", qic117_cmds[command].name);
137 /* A new motion command during an uninterruptible (motion)
138 * command requires a ready status before the new command can
139 * be issued. Otherwise a new motion command needs to be
140 * checked against required status.
141 */
142 if (qic117_cmds[command].cmd_type == motion &&
143 qic117_cmds[ftape_current_command].non_intr) {
144 ftape_report_raw_drive_status(&status);
145 if ((status & QIC_STATUS_READY) == 0) {
146 TRACE(ft_t_noise,
147 "motion cmd (%d) during non-intr cmd (%d)",
148 command, ftape_current_command);
149 TRACE(ft_t_noise, "waiting until drive gets ready");
150 ftape_ready_wait(ftape_timeout.seek,
151 &status);
152 }
153 }
154 if (qic117_cmds[command].mask != 0) {
155 __u8 difference;
156 /* Some commands do require a certain status:
157 */
158 if (status == -1) { /* not yet set */
159 ftape_report_raw_drive_status(&status);
160 }
161 difference = ((status ^ qic117_cmds[command].state) &
162 qic117_cmds[command].mask);
163 /* Wait until the drive gets
164 * ready. This may last forever if
165 * the drive never gets ready...
166 */
167 while ((difference & QIC_STATUS_READY) != 0) {
168 TRACE(ft_t_noise, "command %d issued while not ready",
169 command);
170 TRACE(ft_t_noise, "waiting until drive gets ready");
171 if (ftape_ready_wait(ftape_timeout.seek,
172 &status) == -EINTR) {
173 /* Bail out on signal !
174 */
175 TRACE_ABORT(-EINTR, ft_t_warn,
176 "interrupted by non-blockable signal");
177 }
178 difference = ((status ^ qic117_cmds[command].state) &
179 qic117_cmds[command].mask);
180 }
181 while ((difference & QIC_STATUS_ERROR) != 0) {
182 int err;
183 qic117_cmd_t cmd;
184
185 TRACE(ft_t_noise,
186 "command %d issued while error pending",
187 command);
188 TRACE(ft_t_noise, "clearing error status");
189 ftape_report_error(&err, &cmd, 1);
190 ftape_report_raw_drive_status(&status);
191 difference = ((status ^ qic117_cmds[command].state) &
192 qic117_cmds[command].mask);
193 if ((difference & QIC_STATUS_ERROR) != 0) {
194 /* Bail out on fatal signal !
195 */
196 FT_SIGNAL_EXIT(_NEVER_BLOCK);
197 }
198 }
199 if (difference) {
200 /* Any remaining difference can't be solved
201 * here.
202 */
203 if (difference & (QIC_STATUS_CARTRIDGE_PRESENT |
204 QIC_STATUS_NEW_CARTRIDGE |
205 QIC_STATUS_REFERENCED)) {
206 TRACE(ft_t_warn,
207 "Fatal: tape removed or reinserted !");
208 ft_failure = 1;
209 } else {
210 TRACE(ft_t_err, "wrong state: 0x%02x should be: 0x%02x",
211 status & qic117_cmds[command].mask,
212 qic117_cmds[command].state);
213 }
214 TRACE_EXIT -EIO;
215 }
216 if (~status & QIC_STATUS_READY & qic117_cmds[command].mask) {
217 TRACE_ABORT(-EBUSY, ft_t_err, "Bad: still busy!");
218 }
219 }
220 TRACE_EXIT 0;
221}
222
223/* Issue a tape command:
224 */
225int ftape_command(qic117_cmd_t command)
226{
227 int result = 0;
228 static int level;
229 TRACE_FUN(ft_t_any);
230
231 if ((unsigned int)command > NR_ITEMS(qic117_cmds)) {
232 /* This is a bug we'll want to know about too.
233 */
234 TRACE_ABORT(-EIO, ft_t_bug, "bug - bad command: %d", command);
235 }
236 if (++level > 5) { /* This is a bug we'll want to know about. */
237 --level;
238 TRACE_ABORT(-EIO, ft_t_bug, "bug - recursion for command: %d",
239 command);
240 }
241 /* disable logging and restriction check for some commands,
242 * check all other commands that have a prescribed starting
243 * status.
244 */
245 if (diagnostic_mode) {
246 TRACE(ft_t_flow, "diagnostic command %d", command);
247 } else if (command == QIC_REPORT_DRIVE_STATUS ||
248 command == QIC_REPORT_NEXT_BIT) {
249 TRACE(ft_t_any, "%s", qic117_cmds[command].name);
250 } else {
251 TRACE_CATCH(ft_check_cmd_restrictions(command), --level);
252 }
253 /* Now all conditions are met or result was < 0.
254 */
255 result = ft_send_to_drive((unsigned int)command);
256 if (qic117_cmds[command].cmd_type == motion &&
257 command != QIC_LOGICAL_FORWARD && command != QIC_STOP_TAPE) {
258 ft_location.known = 0;
259 }
260 ftape_current_command = command;
261 --level;
262 TRACE_EXIT result;
263}
264
265/* Send a tape command parameter:
266 * Generates command # of step pulses.
267 * Skips tape-status call !
268 */
269int ftape_parameter(unsigned int parameter)
270{
271 TRACE_FUN(ft_t_any);
272
273 TRACE(ft_t_flow, "called with parameter = %d", parameter);
274 TRACE_EXIT ft_send_to_drive(parameter + 2);
275}
276
277/* Wait for the drive to get ready.
278 * timeout time in milli-seconds
279 * Returned status is valid if result != -EIO
280 *
281 * Should we allow to be killed by SIGINT? (^C)
282 * Would be nice at least for large timeouts.
283 */
284int ftape_ready_wait(unsigned int timeout, int *status)
285{
286 unsigned long t0;
287 unsigned int poll_delay;
288 int signal_retries;
289 TRACE_FUN(ft_t_any);
290
291 /* the following ** REALLY ** reduces the system load when
292 * e.g. one simply rewinds or retensions. The tape is slow
293 * anyway. It is really not necessary to detect error
294 * conditions with 1/10 seconds granularity
295 *
296 * On my AMD 133MHZ 486: 100 ms: 23% system load
297 * 1 sec: 5%
298 * 5 sec: 0.6%, yeah
299 */
300 if (timeout <= FT_SECOND) {
301 poll_delay = 100 * FT_MILLISECOND;
302 signal_retries = 20; /* two seconds */
303 } else if (timeout < 20 * FT_SECOND) {
304 TRACE(ft_t_flow, "setting poll delay to 1 second");
305 poll_delay = FT_SECOND;
306 signal_retries = 2; /* two seconds */
307 } else {
308 TRACE(ft_t_flow, "setting poll delay to 5 seconds");
309 poll_delay = 5 * FT_SECOND;
310 signal_retries = 1; /* five seconds */
311 }
312 for (;;) {
313 t0 = jiffies;
314 TRACE_CATCH(ftape_report_raw_drive_status(status),);
315 if (*status & QIC_STATUS_READY) {
316 TRACE_EXIT 0;
317 }
318 if (!signal_retries--) {
319 FT_SIGNAL_EXIT(_NEVER_BLOCK);
320 }
321 if ((int)timeout >= 0) {
322 /* this will fail when jiffies wraps around about
323 * once every year :-)
324 */
325 timeout -= ((jiffies - t0) * FT_SECOND) / HZ;
326 if (timeout <= 0) {
327 TRACE_ABORT(-ETIME, ft_t_err, "timeout");
328 }
329 ftape_sleep(poll_delay);
330 timeout -= poll_delay;
331 } else {
332 ftape_sleep(poll_delay);
333 }
334 }
335 TRACE_EXIT -ETIME;
336}
337
338/* Issue command and wait up to timeout milli seconds for drive ready
339 */
340int ftape_command_wait(qic117_cmd_t command, unsigned int timeout, int *status)
341{
342 int result;
343
344 /* Drive should be ready, issue command
345 */
346 result = ftape_command(command);
347 if (result >= 0) {
348 result = ftape_ready_wait(timeout, status);
349 }
350 return result;
351}
352
353static int ftape_parameter_wait(unsigned int parm, unsigned int timeout, int *status)
354{
355 int result;
356
357 /* Drive should be ready, issue command
358 */
359 result = ftape_parameter(parm);
360 if (result >= 0) {
361 result = ftape_ready_wait(timeout, status);
362 }
363 return result;
364}
365
366/*--------------------------------------------------------------------------
367 * Report operations
368 */
369
370/* Query the drive about its status. The command is sent and
371 result_length bits of status are returned (2 extra bits are read
372 for start and stop). */
373
374int ftape_report_operation(int *status,
375 qic117_cmd_t command,
376 int result_length)
377{
378 int i, st3;
379 unsigned int t0;
380 unsigned int dt;
381 TRACE_FUN(ft_t_any);
382
383 TRACE_CATCH(ftape_command(command),);
384 t0 = ftape_timestamp();
385 i = 0;
386 do {
387 ++i;
388 ftape_sleep(3 * FT_MILLISECOND); /* see remark below */
389 TRACE_CATCH(fdc_sense_drive_status(&st3),);
390 dt = ftape_timediff(t0, ftape_timestamp());
391 /* Ack should be asserted within Ttimout + Tack = 6 msec.
392 * Looks like some drives fail to do this so extend this
393 * period to 300 msec.
394 */
395 } while (!(st3 & ST3_TRACK_0) && dt < 300000);
396 if (!(st3 & ST3_TRACK_0)) {
397 TRACE(ft_t_err,
398 "No acknowledge after %u msec. (%i iter)", dt / 1000, i);
399 TRACE_ABORT(-EIO, ft_t_err, "timeout on Acknowledge");
400 }
401 /* dt may be larger than expected because of other tasks
402 * scheduled while we were sleeping.
403 */
404 if (i > 1 && dt > 6000) {
405 TRACE(ft_t_err, "Acknowledge after %u msec. (%i iter)",
406 dt / 1000, i);
407 }
408 *status = 0;
409 for (i = 0; i < result_length + 1; i++) {
410 TRACE_CATCH(ftape_command(QIC_REPORT_NEXT_BIT),);
411 TRACE_CATCH(fdc_sense_drive_status(&st3),);
412 if (i < result_length) {
413 *status |= ((st3 & ST3_TRACK_0) ? 1 : 0) << i;
414 } else if ((st3 & ST3_TRACK_0) == 0) {
415 TRACE_ABORT(-EIO, ft_t_err, "missing status stop bit");
416 }
417 }
418 /* this command will put track zero and index back into normal state */
419 (void)ftape_command(QIC_REPORT_NEXT_BIT);
420 TRACE_EXIT 0;
421}
422
423/* Report the current drive status. */
424
425int ftape_report_raw_drive_status(int *status)
426{
427 int result;
428 int count = 0;
429 TRACE_FUN(ft_t_any);
430
431 do {
432 result = ftape_report_operation(status,
433 QIC_REPORT_DRIVE_STATUS, 8);
434 } while (result < 0 && ++count <= 3);
435 if (result < 0) {
436 TRACE_ABORT(-EIO, ft_t_err,
437 "report_operation failed after %d trials", count);
438 }
439 if ((*status & 0xff) == 0xff) {
440 TRACE_ABORT(-EIO, ft_t_err,
441 "impossible drive status 0xff");
442 }
443 if (*status & QIC_STATUS_READY) {
444 ftape_current_command = QIC_NO_COMMAND; /* completed */
445 }
446 ft_last_status.status.drive_status = (__u8)(*status & 0xff);
447 TRACE_EXIT 0;
448}
449
450int ftape_report_drive_status(int *status)
451{
452 TRACE_FUN(ft_t_any);
453
454 TRACE_CATCH(ftape_report_raw_drive_status(status),);
455 if (*status & QIC_STATUS_NEW_CARTRIDGE ||
456 !(*status & QIC_STATUS_CARTRIDGE_PRESENT)) {
457 ft_failure = 1; /* will inhibit further operations */
458 TRACE_EXIT -EIO;
459 }
460 if (*status & QIC_STATUS_READY && *status & QIC_STATUS_ERROR) {
461 /* Let caller handle all errors */
462 TRACE_ABORT(1, ft_t_warn, "warning: error status set!");
463 }
464 TRACE_EXIT 0;
465}
466
467int ftape_report_error(unsigned int *error,
468 qic117_cmd_t *command, int report)
469{
470 static const ftape_error ftape_errors[] = QIC117_ERRORS;
471 int code;
472 TRACE_FUN(ft_t_any);
473
474 TRACE_CATCH(ftape_report_operation(&code, QIC_REPORT_ERROR_CODE, 16),);
475 *error = (unsigned int)(code & 0xff);
476 *command = (qic117_cmd_t)((code>>8)&0xff);
477 /* remember hardware status, maybe useful for status ioctls
478 */
479 ft_last_error.error.command = (__u8)*command;
480 ft_last_error.error.error = (__u8)*error;
481 if (!report) {
482 TRACE_EXIT 0;
483 }
484 if (*error == 0) {
485 TRACE_ABORT(0, ft_t_info, "No error");
486 }
487 TRACE(ft_t_info, "errorcode: %d", *error);
488 if (*error < NR_ITEMS(ftape_errors)) {
489 TRACE(ft_t_noise, "%sFatal ERROR:",
490 (ftape_errors[*error].fatal ? "" : "Non-"));
491 TRACE(ft_t_noise, "%s ...", ftape_errors[*error].message);
492 } else {
493 TRACE(ft_t_noise, "Unknown ERROR !");
494 }
495 if ((unsigned int)*command < NR_ITEMS(qic117_cmds) &&
496 qic117_cmds[*command].name != NULL) {
497 TRACE(ft_t_noise, "... caused by command \'%s\'",
498 qic117_cmds[*command].name);
499 } else {
500 TRACE(ft_t_noise, "... caused by unknown command %d",
501 *command);
502 }
503 TRACE_EXIT 0;
504}
505
506int ftape_report_configuration(qic_model *model,
507 unsigned int *rate,
508 int *qic_std,
509 int *tape_len)
510{
511 int result;
512 int config;
513 int status;
514 static const unsigned int qic_rates[ 4] = { 250, 2000, 500, 1000 };
515 TRACE_FUN(ft_t_any);
516
517 result = ftape_report_operation(&config,
518 QIC_REPORT_DRIVE_CONFIGURATION, 8);
519 if (result < 0) {
520 ft_last_status.status.drive_config = (__u8)0x00;
521 *model = prehistoric;
522 *rate = 500;
523 *qic_std = QIC_TAPE_QIC40;
524 *tape_len = 205;
525 TRACE_EXIT 0;
526 } else {
527 ft_last_status.status.drive_config = (__u8)(config & 0xff);
528 }
529 *rate = qic_rates[(config & QIC_CONFIG_RATE_MASK) >> QIC_CONFIG_RATE_SHIFT];
530 result = ftape_report_operation(&status, QIC_REPORT_TAPE_STATUS, 8);
531 if (result < 0) {
532 ft_last_status.status.tape_status = (__u8)0x00;
533 /* pre- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is valid.
534 */
535 *qic_std = (config & QIC_CONFIG_80) ?
536 QIC_TAPE_QIC80 : QIC_TAPE_QIC40;
537 /* ?? how's about 425ft tapes? */
538 *tape_len = (config & QIC_CONFIG_LONG) ? 307 : 0;
539 *model = pre_qic117c;
540 result = 0;
541 } else {
542 ft_last_status.status.tape_status = (__u8)(status & 0xff);
543 *model = post_qic117b;
544 TRACE(ft_t_any, "report tape status result = %02x", status);
545 /* post- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is
546 * invalid.
547 */
548 switch (status & QIC_TAPE_STD_MASK) {
549 case QIC_TAPE_QIC40:
550 case QIC_TAPE_QIC80:
551 case QIC_TAPE_QIC3020:
552 case QIC_TAPE_QIC3010:
553 *qic_std = status & QIC_TAPE_STD_MASK;
554 break;
555 default:
556 *qic_std = -1;
557 break;
558 }
559 switch (status & QIC_TAPE_LEN_MASK) {
560 case QIC_TAPE_205FT:
561 /* 205 or 425+ ft 550 Oe tape */
562 *tape_len = 0;
563 break;
564 case QIC_TAPE_307FT:
565 /* 307.5 ft 550 Oe Extended Length (XL) tape */
566 *tape_len = 307;
567 break;
568 case QIC_TAPE_VARIABLE:
569 /* Variable length 550 Oe tape */
570 *tape_len = 0;
571 break;
572 case QIC_TAPE_1100FT:
573 /* 1100 ft 550 Oe tape */
574 *tape_len = 1100;
575 break;
576 case QIC_TAPE_FLEX:
577 /* Variable length 900 Oe tape */
578 *tape_len = 0;
579 break;
580 default:
581 *tape_len = -1;
582 break;
583 }
584 if (*qic_std == -1 || *tape_len == -1) {
585 TRACE(ft_t_any,
586 "post qic-117b spec drive with unknown tape");
587 }
588 result = *tape_len == -1 ? -EIO : 0;
589 if (status & QIC_TAPE_WIDE) {
590 switch (*qic_std) {
591 case QIC_TAPE_QIC80:
592 TRACE(ft_t_info, "TR-1 tape detected");
593 break;
594 case QIC_TAPE_QIC3010:
595 TRACE(ft_t_info, "TR-2 tape detected");
596 break;
597 case QIC_TAPE_QIC3020:
598 TRACE(ft_t_info, "TR-3 tape detected");
599 break;
600 default:
601 TRACE(ft_t_warn,
602 "Unknown Travan tape type detected");
603 break;
604 }
605 }
606 }
607 TRACE_EXIT (result < 0) ? -EIO : 0;
608}
609
610static int ftape_report_rom_version(int *version)
611{
612
613 if (ftape_report_operation(version, QIC_REPORT_ROM_VERSION, 8) < 0) {
614 return -EIO;
615 } else {
616 return 0;
617 }
618}
619
620void ftape_report_vendor_id(unsigned int *id)
621{
622 int result;
623 TRACE_FUN(ft_t_any);
624
625 /* We'll try to get a vendor id from the drive. First
626 * according to the QIC-117 spec, a 16-bit id is requested.
627 * If that fails we'll try an 8-bit version, otherwise we'll
628 * try an undocumented query.
629 */
630 result = ftape_report_operation((int *) id, QIC_REPORT_VENDOR_ID, 16);
631 if (result < 0) {
632 result = ftape_report_operation((int *) id,
633 QIC_REPORT_VENDOR_ID, 8);
634 if (result < 0) {
635 /* The following is an undocumented call found
636 * in the CMS code.
637 */
638 result = ftape_report_operation((int *) id, 24, 8);
639 if (result < 0) {
640 *id = UNKNOWN_VENDOR;
641 } else {
642 TRACE(ft_t_noise, "got old 8 bit id: %04x",
643 *id);
644 *id |= 0x20000;
645 }
646 } else {
647 TRACE(ft_t_noise, "got 8 bit id: %04x", *id);
648 *id |= 0x10000;
649 }
650 } else {
651 TRACE(ft_t_noise, "got 16 bit id: %04x", *id);
652 }
653 if (*id == 0x0047) {
654 int version;
655 int sign;
656
657 if (ftape_report_rom_version(&version) < 0) {
658 TRACE(ft_t_bug, "report rom version failed");
659 TRACE_EXIT;
660 }
661 TRACE(ft_t_noise, "CMS rom version: %d", version);
662 ftape_command(QIC_ENTER_DIAGNOSTIC_1);
663 ftape_command(QIC_ENTER_DIAGNOSTIC_1);
664 diagnostic_mode = 1;
665 if (ftape_report_operation(&sign, 9, 8) < 0) {
666 unsigned int error;
667 qic117_cmd_t command;
668
669 ftape_report_error(&error, &command, 1);
670 ftape_command(QIC_ENTER_PRIMARY_MODE);
671 diagnostic_mode = 0;
672 TRACE_EXIT; /* failure ! */
673 } else {
674 TRACE(ft_t_noise, "CMS signature: %02x", sign);
675 }
676 if (sign == 0xa5) {
677 result = ftape_report_operation(&sign, 37, 8);
678 if (result < 0) {
679 if (version >= 63) {
680 *id = 0x8880;
681 TRACE(ft_t_noise,
682 "This is an Iomega drive !");
683 } else {
684 *id = 0x0047;
685 TRACE(ft_t_noise,
686 "This is a real CMS drive !");
687 }
688 } else {
689 *id = 0x0047;
690 TRACE(ft_t_noise, "CMS status: %d", sign);
691 }
692 } else {
693 *id = UNKNOWN_VENDOR;
694 }
695 ftape_command(QIC_ENTER_PRIMARY_MODE);
696 diagnostic_mode = 0;
697 }
698 TRACE_EXIT;
699}
700
701static int qic_rate_code(unsigned int rate)
702{
703 switch (rate) {
704 case 250:
705 return QIC_CONFIG_RATE_250;
706 case 500:
707 return QIC_CONFIG_RATE_500;
708 case 1000:
709 return QIC_CONFIG_RATE_1000;
710 case 2000:
711 return QIC_CONFIG_RATE_2000;
712 default:
713 return QIC_CONFIG_RATE_500;
714 }
715}
716
717static int ftape_set_rate_test(unsigned int *max_rate)
718{
719 unsigned int error;
720 qic117_cmd_t command;
721 int status;
722 int supported = 0;
723 TRACE_FUN(ft_t_any);
724
725 /* Check if the drive does support the select rate command
726 * by testing all different settings. If any one is accepted
727 * we assume the command is supported, else not.
728 */
729 for (*max_rate = 2000; *max_rate >= 250; *max_rate /= 2) {
730 if (ftape_command(QIC_SELECT_RATE) < 0) {
731 continue;
732 }
733 if (ftape_parameter_wait(qic_rate_code(*max_rate),
734 1 * FT_SECOND, &status) < 0) {
735 continue;
736 }
737 if (status & QIC_STATUS_ERROR) {
738 ftape_report_error(&error, &command, 0);
739 continue;
740 }
741 supported = 1; /* did accept a request */
742 break;
743 }
744 TRACE(ft_t_noise, "Select Rate command is%s supported",
745 supported ? "" : " not");
746 TRACE_EXIT supported;
747}
748
749int ftape_set_data_rate(unsigned int new_rate /* Kbps */, unsigned int qic_std)
750{
751 int status;
752 int result = 0;
753 unsigned int data_rate = new_rate;
754 static int supported;
755 int rate_changed = 0;
756 qic_model dummy_model;
757 unsigned int dummy_qic_std, dummy_tape_len;
758 TRACE_FUN(ft_t_any);
759
760 if (ft_drive_max_rate == 0) { /* first time */
761 supported = ftape_set_rate_test(&ft_drive_max_rate);
762 }
763 if (supported) {
764 ftape_command(QIC_SELECT_RATE);
765 result = ftape_parameter_wait(qic_rate_code(new_rate),
766 1 * FT_SECOND, &status);
767 if (result >= 0 && !(status & QIC_STATUS_ERROR)) {
768 rate_changed = 1;
769 }
770 }
771 TRACE_CATCH(result = ftape_report_configuration(&dummy_model,
772 &data_rate,
773 &dummy_qic_std,
774 &dummy_tape_len),);
775 if (data_rate != new_rate) {
776 if (!supported) {
777 TRACE(ft_t_warn, "Rate change not supported!");
778 } else if (rate_changed) {
779 TRACE(ft_t_warn, "Requested: %d, got %d",
780 new_rate, data_rate);
781 } else {
782 TRACE(ft_t_warn, "Rate change failed!");
783 }
784 result = -EINVAL;
785 }
786 /*
787 * Set data rate and write precompensation as specified:
788 *
789 * | QIC-40/80 | QIC-3010/3020
790 * rate | precomp | precomp
791 * ----------+-------------+--------------
792 * 250 Kbps. | 250 ns. | 0 ns.
793 * 500 Kbps. | 125 ns. | 0 ns.
794 * 1 Mbps. | 42 ns. | 0 ns.
795 * 2 Mbps | N/A | 0 ns.
796 */
797 if ((qic_std == QIC_TAPE_QIC40 && data_rate > 500) ||
798 (qic_std == QIC_TAPE_QIC80 && data_rate > 1000)) {
799 TRACE_ABORT(-EINVAL,
800 ft_t_warn, "Datarate too high for QIC-mode");
801 }
802 TRACE_CATCH(fdc_set_data_rate(data_rate),_res = -EINVAL);
803 ft_data_rate = data_rate;
804 if (qic_std == QIC_TAPE_QIC40 || qic_std == QIC_TAPE_QIC80) {
805 switch (data_rate) {
806 case 250:
807 fdc_set_write_precomp(250);
808 break;
809 default:
810 case 500:
811 fdc_set_write_precomp(125);
812 break;
813 case 1000:
814 fdc_set_write_precomp(42);
815 break;
816 }
817 } else {
818 fdc_set_write_precomp(0);
819 }
820 TRACE_EXIT result;
821}
822
823/* The next two functions are used to cope with excessive overrun errors
824 */
825int ftape_increase_threshold(void)
826{
827 TRACE_FUN(ft_t_flow);
828
829 if (fdc.type < i82077 || ft_fdc_threshold >= 12) {
830 TRACE_ABORT(-EIO, ft_t_err, "cannot increase fifo threshold");
831 }
832 if (fdc_fifo_threshold(++ft_fdc_threshold, NULL, NULL, NULL) < 0) {
833 TRACE(ft_t_err, "cannot increase fifo threshold");
834 ft_fdc_threshold --;
835 fdc_reset();
836 }
837 TRACE(ft_t_info, "New FIFO threshold: %d", ft_fdc_threshold);
838 TRACE_EXIT 0;
839}
840
841int ftape_half_data_rate(void)
842{
843 if (ft_data_rate < 500) {
844 return -1;
845 }
846 if (ftape_set_data_rate(ft_data_rate / 2, ft_qic_std) < 0) {
847 return -EIO;
848 }
849 ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
850 return 0;
851}
852
853/* Seek the head to the specified track.
854 */
855int ftape_seek_head_to_track(unsigned int track)
856{
857 int status;
858 TRACE_FUN(ft_t_any);
859
860 ft_location.track = -1; /* remains set in case of error */
861 if (track >= ft_tracks_per_tape) {
862 TRACE_ABORT(-EINVAL, ft_t_bug, "track out of bounds");
863 }
864 TRACE(ft_t_flow, "seeking track %d", track);
865 TRACE_CATCH(ftape_command(QIC_SEEK_HEAD_TO_TRACK),);
866 TRACE_CATCH(ftape_parameter_wait(track, ftape_timeout.head_seek,
867 &status),);
868 ft_location.track = track;
869 ftape_might_be_off_track = 0;
870 TRACE_EXIT 0;
871}
872
873int ftape_wakeup_drive(wake_up_types method)
874{
875 int status;
876 int motor_on = 0;
877 TRACE_FUN(ft_t_any);
878
879 switch (method) {
880 case wake_up_colorado:
881 TRACE_CATCH(ftape_command(QIC_PHANTOM_SELECT),);
882 TRACE_CATCH(ftape_parameter(0 /* ft_drive_sel ?? */),);
883 break;
884 case wake_up_mountain:
885 TRACE_CATCH(ftape_command(QIC_SOFT_SELECT),);
886 ftape_sleep(FT_MILLISECOND); /* NEEDED */
887 TRACE_CATCH(ftape_parameter(18),);
888 break;
889 case wake_up_insight:
890 ftape_sleep(100 * FT_MILLISECOND);
891 motor_on = 1;
892 fdc_motor(motor_on); /* enable is done by motor-on */
893 case no_wake_up:
894 break;
895 default:
896 TRACE_EXIT -ENODEV; /* unknown wakeup method */
897 break;
898 }
899 /* If wakeup succeeded we shouldn't get an error here..
900 */
901 TRACE_CATCH(ftape_report_raw_drive_status(&status),
902 if (motor_on) {
903 fdc_motor(0);
904 });
905 TRACE_EXIT 0;
906}
907
908int ftape_put_drive_to_sleep(wake_up_types method)
909{
910 TRACE_FUN(ft_t_any);
911
912 switch (method) {
913 case wake_up_colorado:
914 TRACE_CATCH(ftape_command(QIC_PHANTOM_DESELECT),);
915 break;
916 case wake_up_mountain:
917 TRACE_CATCH(ftape_command(QIC_SOFT_DESELECT),);
918 break;
919 case wake_up_insight:
920 fdc_motor(0); /* enable is done by motor-on */
921 case no_wake_up: /* no wakeup / no sleep ! */
922 break;
923 default:
924 TRACE_EXIT -ENODEV; /* unknown wakeup method */
925 }
926 TRACE_EXIT 0;
927}
928
929int ftape_reset_drive(void)
930{
931 int result = 0;
932 int status;
933 unsigned int err_code;
934 qic117_cmd_t err_command;
935 int i;
936 TRACE_FUN(ft_t_any);
937
938 /* We want to re-establish contact with our drive. Fire a
939 * number of reset commands (single step pulses) and pray for
940 * success.
941 */
942 for (i = 0; i < 2; ++i) {
943 TRACE(ft_t_flow, "Resetting fdc");
944 fdc_reset();
945 ftape_sleep(10 * FT_MILLISECOND);
946 TRACE(ft_t_flow, "Reset command to drive");
947 result = ftape_command(QIC_RESET);
948 if (result == 0) {
949 ftape_sleep(1 * FT_SECOND); /* drive not
950 * accessible
951 * during 1 second
952 */
953 TRACE(ft_t_flow, "Re-selecting drive");
954
955 /* Strange, the QIC-117 specs don't mention
956 * this but the drive gets deselected after a
957 * soft reset ! So we need to enable it
958 * again.
959 */
960 if (ftape_wakeup_drive(ft_drive_type.wake_up) < 0) {
961 TRACE(ft_t_err, "Wakeup failed !");
962 }
963 TRACE(ft_t_flow, "Waiting until drive gets ready");
964 result= ftape_ready_wait(ftape_timeout.reset, &status);
965 if (result == 0 && (status & QIC_STATUS_ERROR)) {
966 result = ftape_report_error(&err_code,
967 &err_command, 1);
968 if (result == 0 && err_code == 27) {
969 /* Okay, drive saw reset
970 * command and responded as it
971 * should
972 */
973 break;
974 } else {
975 result = -EIO;
976 }
977 } else {
978 result = -EIO;
979 }
980 }
981 FT_SIGNAL_EXIT(_DONT_BLOCK);
982 }
983 if (result != 0) {
984 TRACE(ft_t_err, "General failure to reset tape drive");
985 } else {
986 /* Restore correct settings: keep original rate
987 */
988 ftape_set_data_rate(ft_data_rate, ft_qic_std);
989 }
990 ftape_init_drive_needed = 1;
991 TRACE_EXIT result;
992}
diff --git a/drivers/char/ftape/lowlevel/ftape-io.h b/drivers/char/ftape/lowlevel/ftape-io.h
deleted file mode 100644
index 26a7baad8717..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-io.h
+++ /dev/null
@@ -1,90 +0,0 @@
1#ifndef _FTAPE_IO_H
2#define _FTAPE_IO_H
3
4/*
5 * Copyright (C) 1993-1996 Bas Laarhoven,
6 * (C) 1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:18 $
26 *
27 * This file contains definitions for the glue part of the
28 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
29 */
30
31#include <linux/qic117.h>
32#include <linux/ftape-vendors.h>
33
34typedef struct {
35 unsigned int seek;
36 unsigned int reset;
37 unsigned int rewind;
38 unsigned int head_seek;
39 unsigned int stop;
40 unsigned int pause;
41} ft_timeout_table;
42
43typedef enum {
44 prehistoric, pre_qic117c, post_qic117b, post_qic117d
45} qic_model;
46
47/*
48 * ftape-io.c defined global vars.
49 */
50extern ft_timeout_table ftape_timeout;
51extern unsigned int ftape_tape_len;
52extern volatile qic117_cmd_t ftape_current_command;
53extern const struct qic117_command_table qic117_cmds[];
54extern int ftape_might_be_off_track;
55
56/*
57 * ftape-io.c defined global functions.
58 */
59extern void ftape_udelay(unsigned int usecs);
60extern void ftape_udelay_calibrate(void);
61extern void ftape_sleep(unsigned int time);
62extern void ftape_report_vendor_id(unsigned int *id);
63extern int ftape_command(qic117_cmd_t command);
64extern int ftape_command_wait(qic117_cmd_t command,
65 unsigned int timeout,
66 int *status);
67extern int ftape_parameter(unsigned int parameter);
68extern int ftape_report_operation(int *status,
69 qic117_cmd_t command,
70 int result_length);
71extern int ftape_report_configuration(qic_model *model,
72 unsigned int *rate,
73 int *qic_std,
74 int *tape_len);
75extern int ftape_report_drive_status(int *status);
76extern int ftape_report_raw_drive_status(int *status);
77extern int ftape_report_status(int *status);
78extern int ftape_ready_wait(unsigned int timeout, int *status);
79extern int ftape_seek_head_to_track(unsigned int track);
80extern int ftape_set_data_rate(unsigned int new_rate, unsigned int qic_std);
81extern int ftape_report_error(unsigned int *error,
82 qic117_cmd_t *command,
83 int report);
84extern int ftape_reset_drive(void);
85extern int ftape_put_drive_to_sleep(wake_up_types method);
86extern int ftape_wakeup_drive(wake_up_types method);
87extern int ftape_increase_threshold(void);
88extern int ftape_half_data_rate(void);
89
90#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-proc.c b/drivers/char/ftape/lowlevel/ftape-proc.c
deleted file mode 100644
index e805b15e0a12..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-proc.c
+++ /dev/null
@@ -1,214 +0,0 @@
1/*
2 * Copyright (C) 1997 Claus-Justus Heine
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 *
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.c,v $
20 * $Revision: 1.11 $
21 * $Date: 1997/10/24 14:47:37 $
22 *
23 * This file contains the procfs interface for the
24 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
25
26 * Old code removed, switched to dynamic proc entry.
27 */
28
29
30#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
31
32#include <linux/proc_fs.h>
33
34#include <linux/ftape.h>
35#include <linux/init.h>
36#include <linux/qic117.h>
37
38#include "../lowlevel/ftape-io.h"
39#include "../lowlevel/ftape-ctl.h"
40#include "../lowlevel/ftape-proc.h"
41#include "../lowlevel/ftape-tracing.h"
42
43static size_t get_driver_info(char *buf)
44{
45 const char *debug_level[] = { "bugs" ,
46 "errors",
47 "warnings",
48 "informational",
49 "noisy",
50 "program flow",
51 "fdc and dma",
52 "data flow",
53 "anything" };
54
55 return sprintf(buf,
56 "version : %s\n"
57 "used data rate: %d kbit/sec\n"
58 "dma memory : %d kb\n"
59 "debug messages: %s\n",
60 FTAPE_VERSION,
61 ft_data_rate,
62 FT_BUFF_SIZE * ft_nr_buffers >> 10,
63 debug_level[TRACE_LEVEL]);
64}
65
66static size_t get_tapedrive_info(char *buf)
67{
68 return sprintf(buf,
69 "vendor id : 0x%04x\n"
70 "drive name: %s\n"
71 "wind speed: %d ips\n"
72 "wakeup : %s\n"
73 "max. rate : %d kbit/sec\n",
74 ft_drive_type.vendor_id,
75 ft_drive_type.name,
76 ft_drive_type.speed,
77 ((ft_drive_type.wake_up == no_wake_up)
78 ? "No wakeup needed" :
79 ((ft_drive_type.wake_up == wake_up_colorado)
80 ? "Colorado" :
81 ((ft_drive_type.wake_up == wake_up_mountain)
82 ? "Mountain" :
83 ((ft_drive_type.wake_up == wake_up_insight)
84 ? "Motor on" :
85 "Unknown")))),
86 ft_drive_max_rate);
87}
88
89static size_t get_cartridge_info(char *buf)
90{
91 if (ftape_init_drive_needed) {
92 return sprintf(buf, "uninitialized\n");
93 }
94 if (ft_no_tape) {
95 return sprintf(buf, "no cartridge inserted\n");
96 }
97 return sprintf(buf,
98 "segments : %5d\n"
99 "tracks : %5d\n"
100 "length : %5dft\n"
101 "formatted : %3s\n"
102 "writable : %3s\n"
103 "QIC spec. : QIC-%s\n"
104 "fmt-code : %1d\n",
105 ft_segments_per_track,
106 ft_tracks_per_tape,
107 ftape_tape_len,
108 (ft_formatted == 1) ? "yes" : "no",
109 (ft_write_protected == 1) ? "no" : "yes",
110 ((ft_qic_std == QIC_TAPE_QIC40) ? "40" :
111 ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
112 ((ft_qic_std == QIC_TAPE_QIC3010) ? "3010" :
113 ((ft_qic_std == QIC_TAPE_QIC3020) ? "3020" :
114 "???")))),
115 ft_format_code);
116}
117
118static size_t get_controller_info(char *buf)
119{
120 const char *fdc_name[] = { "no fdc",
121 "i8272",
122 "i82077",
123 "i82077AA",
124 "Colorado FC-10 or FC-20",
125 "i82078",
126 "i82078_1" };
127
128 return sprintf(buf,
129 "FDC type : %s\n"
130 "FDC base : 0x%03x\n"
131 "FDC irq : %d\n"
132 "FDC dma : %d\n"
133 "FDC thr. : %d\n"
134 "max. rate : %d kbit/sec\n",
135 ft_mach2 ? "Mountain MACH-2" : fdc_name[fdc.type],
136 fdc.sra, fdc.irq, fdc.dma,
137 ft_fdc_threshold, ft_fdc_max_rate);
138}
139
140static size_t get_history_info(char *buf)
141{
142 size_t len;
143
144 len = sprintf(buf,
145 "\nFDC isr statistics\n"
146 " id_am_errors : %3d\n"
147 " id_crc_errors : %3d\n"
148 " data_am_errors : %3d\n"
149 " data_crc_errors : %3d\n"
150 " overrun_errors : %3d\n"
151 " no_data_errors : %3d\n"
152 " retries : %3d\n",
153 ft_history.id_am_errors, ft_history.id_crc_errors,
154 ft_history.data_am_errors, ft_history.data_crc_errors,
155 ft_history.overrun_errors, ft_history.no_data_errors,
156 ft_history.retries);
157 len += sprintf(buf + len,
158 "\nECC statistics\n"
159 " crc_errors : %3d\n"
160 " crc_failures : %3d\n"
161 " ecc_failures : %3d\n"
162 " sectors corrected: %3d\n",
163 ft_history.crc_errors, ft_history.crc_failures,
164 ft_history.ecc_failures, ft_history.corrected);
165 len += sprintf(buf + len,
166 "\ntape quality statistics\n"
167 " media defects : %3d\n",
168 ft_history.defects);
169 len += sprintf(buf + len,
170 "\ntape motion statistics\n"
171 " repositions : %3d\n",
172 ft_history.rewinds);
173 return len;
174}
175
176static int ftape_read_proc(char *page, char **start, off_t off,
177 int count, int *eof, void *data)
178{
179 char *ptr = page;
180 size_t len;
181
182 ptr += sprintf(ptr, "Kernel Driver\n\n");
183 ptr += get_driver_info(ptr);
184 ptr += sprintf(ptr, "\nTape Drive\n\n");
185 ptr += get_tapedrive_info(ptr);
186 ptr += sprintf(ptr, "\nFDC Controller\n\n");
187 ptr += get_controller_info(ptr);
188 ptr += sprintf(ptr, "\nTape Cartridge\n\n");
189 ptr += get_cartridge_info(ptr);
190 ptr += sprintf(ptr, "\nHistory Record\n\n");
191 ptr += get_history_info(ptr);
192
193 len = strlen(page);
194 *start = NULL;
195 if (off+count >= len) {
196 *eof = 1;
197 } else {
198 *eof = 0;
199 }
200 return len;
201}
202
203int __init ftape_proc_init(void)
204{
205 return create_proc_read_entry("ftape", 0, &proc_root,
206 ftape_read_proc, NULL) != NULL;
207}
208
209void ftape_proc_destroy(void)
210{
211 remove_proc_entry("ftape", &proc_root);
212}
213
214#endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */
diff --git a/drivers/char/ftape/lowlevel/ftape-proc.h b/drivers/char/ftape/lowlevel/ftape-proc.h
deleted file mode 100644
index 264dfcc1d22d..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-proc.h
+++ /dev/null
@@ -1,35 +0,0 @@
1#ifndef _FTAPE_PROC_H
2#define _FTAPE_PROC_H
3
4/*
5 * Copyright (C) 1997 Claus-Justus Heine
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:18:20 $
25 *
26 * This file contains definitions for the procfs interface of the
27 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
28 */
29
30#include <linux/proc_fs.h>
31
32extern int ftape_proc_init(void);
33extern void ftape_proc_destroy(void);
34
35#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-read.c b/drivers/char/ftape/lowlevel/ftape-read.c
deleted file mode 100644
index d967d8cd86dc..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-read.c
+++ /dev/null
@@ -1,621 +0,0 @@
1/*
2 * Copyright (C) 1993-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/ftape-read.c,v $
21 * $Revision: 1.6 $
22 * $Date: 1997/10/21 14:39:22 $
23 *
24 * This file contains the reading code
25 * for the QIC-117 floppy-tape driver for Linux.
26 *
27 */
28
29#include <linux/string.h>
30#include <linux/errno.h>
31#include <linux/mm.h>
32
33#include <linux/ftape.h>
34#include <linux/qic117.h>
35#include "../lowlevel/ftape-tracing.h"
36#include "../lowlevel/ftape-read.h"
37#include "../lowlevel/ftape-io.h"
38#include "../lowlevel/ftape-ctl.h"
39#include "../lowlevel/ftape-rw.h"
40#include "../lowlevel/ftape-write.h"
41#include "../lowlevel/ftape-ecc.h"
42#include "../lowlevel/ftape-bsm.h"
43
44/* Global vars.
45 */
46
47/* Local vars.
48 */
49
50void ftape_zap_read_buffers(void)
51{
52 int i;
53
54 for (i = 0; i < ft_nr_buffers; ++i) {
55/* changed to "fit" with dynamic allocation of tape_buffer. --khp */
56 ft_buffer[i]->status = waiting;
57 ft_buffer[i]->bytes = 0;
58 ft_buffer[i]->skip = 0;
59 ft_buffer[i]->retry = 0;
60 }
61/* ftape_reset_buffer(); */
62}
63
64static SectorMap convert_sector_map(buffer_struct * buff)
65{
66 int i = 0;
67 SectorMap bad_map = ftape_get_bad_sector_entry(buff->segment_id);
68 SectorMap src_map = buff->soft_error_map | buff->hard_error_map;
69 SectorMap dst_map = 0;
70 TRACE_FUN(ft_t_any);
71
72 if (bad_map || src_map) {
73 TRACE(ft_t_flow, "bad_map = 0x%08lx", (long) bad_map);
74 TRACE(ft_t_flow, "src_map = 0x%08lx", (long) src_map);
75 }
76 while (bad_map) {
77 while ((bad_map & 1) == 0) {
78 if (src_map & 1) {
79 dst_map |= (1 << i);
80 }
81 src_map >>= 1;
82 bad_map >>= 1;
83 ++i;
84 }
85 /* (bad_map & 1) == 1 */
86 src_map >>= 1;
87 bad_map >>= 1;
88 }
89 if (src_map) {
90 dst_map |= (src_map << i);
91 }
92 if (dst_map) {
93 TRACE(ft_t_flow, "dst_map = 0x%08lx", (long) dst_map);
94 }
95 TRACE_EXIT dst_map;
96}
97
98static int correct_and_copy_fraction(buffer_struct *buff, __u8 * destination,
99 int start, int size)
100{
101 struct memory_segment mseg;
102 int result;
103 SectorMap read_bad;
104 TRACE_FUN(ft_t_any);
105
106 mseg.read_bad = convert_sector_map(buff);
107 mseg.marked_bad = 0; /* not used... */
108 mseg.blocks = buff->bytes / FT_SECTOR_SIZE;
109 mseg.data = buff->address;
110 /* If there are no data sectors we can skip this segment.
111 */
112 if (mseg.blocks <= 3) {
113 TRACE_ABORT(0, ft_t_noise, "empty segment");
114 }
115 read_bad = mseg.read_bad;
116 ft_history.crc_errors += count_ones(read_bad);
117 result = ftape_ecc_correct_data(&mseg);
118 if (read_bad != 0 || mseg.corrected != 0) {
119 TRACE(ft_t_noise, "crc error map: 0x%08lx", (unsigned long)read_bad);
120 TRACE(ft_t_noise, "corrected map: 0x%08lx", (unsigned long)mseg.corrected);
121 ft_history.corrected += count_ones(mseg.corrected);
122 }
123 if (result == ECC_CORRECTED || result == ECC_OK) {
124 if (result == ECC_CORRECTED) {
125 TRACE(ft_t_info, "ecc corrected segment: %d", buff->segment_id);
126 }
127 if(start < 0) {
128 start= 0;
129 }
130 if((start+size) > ((mseg.blocks - 3) * FT_SECTOR_SIZE)) {
131 size = (mseg.blocks - 3) * FT_SECTOR_SIZE - start;
132 }
133 if (size < 0) {
134 size= 0;
135 }
136 if(size > 0) {
137 memcpy(destination + start, mseg.data + start, size);
138 }
139 if ((read_bad ^ mseg.corrected) & mseg.corrected) {
140 /* sectors corrected without crc errors set */
141 ft_history.crc_failures++;
142 }
143 TRACE_EXIT size; /* (mseg.blocks - 3) * FT_SECTOR_SIZE; */
144 } else {
145 ft_history.ecc_failures++;
146 TRACE_ABORT(-EAGAIN,
147 ft_t_err, "ecc failure on segment %d",
148 buff->segment_id);
149 }
150 TRACE_EXIT 0;
151}
152
153/* Read given segment into buffer at address.
154 */
155int ftape_read_segment_fraction(const int segment_id,
156 void *address,
157 const ft_read_mode_t read_mode,
158 const int start,
159 const int size)
160{
161 int result = 0;
162 int retry = 0;
163 int bytes_read = 0;
164 int read_done = 0;
165 TRACE_FUN(ft_t_flow);
166
167 ft_history.used |= 1;
168 TRACE(ft_t_data_flow, "segment_id = %d", segment_id);
169 if (ft_driver_state != reading) {
170 TRACE(ft_t_noise, "calling ftape_abort_operation");
171 TRACE_CATCH(ftape_abort_operation(),);
172 ftape_set_state(reading);
173 }
174 for(;;) {
175 buffer_struct *tail;
176 /* Allow escape from this loop on signal !
177 */
178 FT_SIGNAL_EXIT(_DONT_BLOCK);
179 /* Search all full buffers for the first matching the
180 * wanted segment. Clear other buffers on the fly.
181 */
182 tail = ftape_get_buffer(ft_queue_tail);
183 while (!read_done && tail->status == done) {
184 /* Allow escape from this loop on signal !
185 */
186 FT_SIGNAL_EXIT(_DONT_BLOCK);
187 if (tail->segment_id == segment_id) {
188 /* If out buffer is already full,
189 * return its contents.
190 */
191 TRACE(ft_t_flow, "found segment in cache: %d",
192 segment_id);
193 if (tail->deleted) {
194 /* Return a value that
195 * read_header_segment
196 * understands. As this
197 * should only occur when
198 * searching for the header
199 * segments it shouldn't be
200 * misinterpreted elsewhere.
201 */
202 TRACE_EXIT 0;
203 }
204 result = correct_and_copy_fraction(
205 tail,
206 address,
207 start,
208 size);
209 TRACE(ft_t_flow, "segment contains (bytes): %d",
210 result);
211 if (result < 0) {
212 if (result != -EAGAIN) {
213 TRACE_EXIT result;
214 }
215 /* keep read_done == 0, will
216 * trigger
217 * ftape_abort_operation
218 * because reading wrong
219 * segment.
220 */
221 TRACE(ft_t_err, "ecc failed, retry");
222 ++retry;
223 } else {
224 read_done = 1;
225 bytes_read = result;
226 }
227 } else {
228 TRACE(ft_t_flow,"zapping segment in cache: %d",
229 tail->segment_id);
230 }
231 tail->status = waiting;
232 tail = ftape_next_buffer(ft_queue_tail);
233 }
234 if (!read_done && tail->status == reading) {
235 if (tail->segment_id == segment_id) {
236 switch(ftape_wait_segment(reading)) {
237 case 0:
238 break;
239 case -EINTR:
240 TRACE_ABORT(-EINTR, ft_t_warn,
241 "interrupted by "
242 "non-blockable signal");
243 break;
244 default:
245 TRACE(ft_t_noise,
246 "wait_segment failed");
247 ftape_abort_operation();
248 ftape_set_state(reading);
249 break;
250 }
251 } else {
252 /* We're reading the wrong segment,
253 * stop runner.
254 */
255 TRACE(ft_t_noise, "reading wrong segment");
256 ftape_abort_operation();
257 ftape_set_state(reading);
258 }
259 }
260 /* should runner stop ?
261 */
262 if (ft_runner_status == aborting) {
263 buffer_struct *head = ftape_get_buffer(ft_queue_head);
264 switch(head->status) {
265 case error:
266 ft_history.defects +=
267 count_ones(head->hard_error_map);
268 case reading:
269 head->status = waiting;
270 break;
271 default:
272 break;
273 }
274 TRACE_CATCH(ftape_dumb_stop(),);
275 } else {
276 /* If just passed last segment on tape: wait
277 * for BOT or EOT mark. Sets ft_runner_status to
278 * idle if at lEOT and successful
279 */
280 TRACE_CATCH(ftape_handle_logical_eot(),);
281 }
282 /* If we got a segment: quit, or else retry up to limit.
283 *
284 * If segment to read is empty, do not start runner for it,
285 * but wait for next read call.
286 */
287 if (read_done ||
288 ftape_get_bad_sector_entry(segment_id) == EMPTY_SEGMENT ) {
289 /* bytes_read = 0; should still be zero */
290 TRACE_EXIT bytes_read;
291
292 }
293 if (retry > FT_RETRIES_ON_ECC_ERROR) {
294 ft_history.defects++;
295 TRACE_ABORT(-ENODATA, ft_t_err,
296 "too many retries on ecc failure");
297 }
298 /* Now at least one buffer is empty !
299 * Restart runner & tape if needed.
300 */
301 TRACE(ft_t_any, "head: %d, tail: %d, ft_runner_status: %d",
302 ftape_buffer_id(ft_queue_head),
303 ftape_buffer_id(ft_queue_tail),
304 ft_runner_status);
305 TRACE(ft_t_any, "buffer[].status, [head]: %d, [tail]: %d",
306 ftape_get_buffer(ft_queue_head)->status,
307 ftape_get_buffer(ft_queue_tail)->status);
308 tail = ftape_get_buffer(ft_queue_tail);
309 if (tail->status == waiting) {
310 buffer_struct *head = ftape_get_buffer(ft_queue_head);
311
312 ftape_setup_new_segment(head, segment_id, -1);
313 if (read_mode == FT_RD_SINGLE) {
314 /* disable read-ahead */
315 head->next_segment = 0;
316 }
317 ftape_calc_next_cluster(head);
318 if (ft_runner_status == idle) {
319 result = ftape_start_tape(segment_id,
320 head->sector_offset);
321 if (result < 0) {
322 TRACE_ABORT(result, ft_t_err, "Error: "
323 "segment %d unreachable",
324 segment_id);
325 }
326 }
327 head->status = reading;
328 fdc_setup_read_write(head, FDC_READ);
329 }
330 }
331 /* not reached */
332 TRACE_EXIT -EIO;
333}
334
335int ftape_read_header_segment(__u8 *address)
336{
337 int result;
338 int header_segment;
339 int first_failed = 0;
340 int status;
341 TRACE_FUN(ft_t_flow);
342
343 ft_used_header_segment = -1;
344 TRACE_CATCH(ftape_report_drive_status(&status),);
345 TRACE(ft_t_flow, "reading...");
346 /* We're looking for the first header segment.
347 * A header segment cannot contain bad sectors, therefor at the
348 * tape start, segments with bad sectors are (according to QIC-40/80)
349 * written with deleted data marks and must be skipped.
350 */
351 memset(address, '\0', (FT_SECTORS_PER_SEGMENT - 3) * FT_SECTOR_SIZE);
352 result = 0;
353#define HEADER_SEGMENT_BOUNDARY 68 /* why not 42? */
354 for (header_segment = 0;
355 header_segment < HEADER_SEGMENT_BOUNDARY && result == 0;
356 ++header_segment) {
357 /* Set no read-ahead, the isr will force read-ahead whenever
358 * it encounters deleted data !
359 */
360 result = ftape_read_segment(header_segment,
361 address,
362 FT_RD_SINGLE);
363 if (result < 0 && !first_failed) {
364 TRACE(ft_t_err, "header segment damaged, trying backup");
365 first_failed = 1;
366 result = 0; /* force read of next (backup) segment */
367 }
368 }
369 if (result < 0 || header_segment >= HEADER_SEGMENT_BOUNDARY) {
370 TRACE_ABORT(-EIO, ft_t_err,
371 "no readable header segment found");
372 }
373 TRACE_CATCH(ftape_abort_operation(),);
374 ft_used_header_segment = header_segment;
375 result = ftape_decode_header_segment(address);
376 TRACE_EXIT result;
377}
378
379int ftape_decode_header_segment(__u8 *address)
380{
381 unsigned int max_floppy_side;
382 unsigned int max_floppy_track;
383 unsigned int max_floppy_sector;
384 unsigned int new_tape_len;
385 TRACE_FUN(ft_t_flow);
386
387 if (GET4(address, FT_SIGNATURE) == FT_D2G_MAGIC) {
388 /* Ditto 2GB header segment. They encrypt the bad sector map.
389 * We decrypt it and store them in normal format.
390 * I hope this is correct.
391 */
392 int i;
393 TRACE(ft_t_warn,
394 "Found Ditto 2GB tape, "
395 "trying to decrypt bad sector map");
396 for (i=256; i < 29 * FT_SECTOR_SIZE; i++) {
397 address[i] = ~(address[i] - (i&0xff));
398 }
399 PUT4(address, 0,FT_HSEG_MAGIC);
400 } else if (GET4(address, FT_SIGNATURE) != FT_HSEG_MAGIC) {
401 TRACE_ABORT(-EIO, ft_t_err,
402 "wrong signature in header segment");
403 }
404 ft_format_code = (ft_format_type) address[FT_FMT_CODE];
405 if (ft_format_code != fmt_big) {
406 ft_header_segment_1 = GET2(address, FT_HSEG_1);
407 ft_header_segment_2 = GET2(address, FT_HSEG_2);
408 ft_first_data_segment = GET2(address, FT_FRST_SEG);
409 ft_last_data_segment = GET2(address, FT_LAST_SEG);
410 } else {
411 ft_header_segment_1 = GET4(address, FT_6_HSEG_1);
412 ft_header_segment_2 = GET4(address, FT_6_HSEG_2);
413 ft_first_data_segment = GET4(address, FT_6_FRST_SEG);
414 ft_last_data_segment = GET4(address, FT_6_LAST_SEG);
415 }
416 TRACE(ft_t_noise, "first data segment: %d", ft_first_data_segment);
417 TRACE(ft_t_noise, "last data segment: %d", ft_last_data_segment);
418 TRACE(ft_t_noise, "header segments are %d and %d",
419 ft_header_segment_1, ft_header_segment_2);
420
421 /* Verify tape parameters...
422 * QIC-40/80 spec: tape_parameters:
423 *
424 * segments-per-track segments_per_track
425 * tracks-per-cartridge tracks_per_tape
426 * max-floppy-side (segments_per_track *
427 * tracks_per_tape - 1) /
428 * ftape_segments_per_head
429 * max-floppy-track ftape_segments_per_head /
430 * ftape_segments_per_cylinder - 1
431 * max-floppy-sector ftape_segments_per_cylinder *
432 * FT_SECTORS_PER_SEGMENT
433 */
434 ft_segments_per_track = GET2(address, FT_SPT);
435 ft_tracks_per_tape = address[FT_TPC];
436 max_floppy_side = address[FT_FHM];
437 max_floppy_track = address[FT_FTM];
438 max_floppy_sector = address[FT_FSM];
439 TRACE(ft_t_noise, "(fmt/spt/tpc/fhm/ftm/fsm) = %d/%d/%d/%d/%d/%d",
440 ft_format_code, ft_segments_per_track, ft_tracks_per_tape,
441 max_floppy_side, max_floppy_track, max_floppy_sector);
442 new_tape_len = ftape_tape_len;
443 switch (ft_format_code) {
444 case fmt_425ft:
445 new_tape_len = 425;
446 break;
447 case fmt_normal:
448 if (ftape_tape_len == 0) { /* otherwise 307 ft */
449 new_tape_len = 205;
450 }
451 break;
452 case fmt_1100ft:
453 new_tape_len = 1100;
454 break;
455 case fmt_var:{
456 int segments_per_1000_inch = 1; /* non-zero default for switch */
457 switch (ft_qic_std) {
458 case QIC_TAPE_QIC40:
459 segments_per_1000_inch = 332;
460 break;
461 case QIC_TAPE_QIC80:
462 segments_per_1000_inch = 488;
463 break;
464 case QIC_TAPE_QIC3010:
465 segments_per_1000_inch = 730;
466 break;
467 case QIC_TAPE_QIC3020:
468 segments_per_1000_inch = 1430;
469 break;
470 }
471 new_tape_len = (1000 * ft_segments_per_track +
472 (segments_per_1000_inch - 1)) / segments_per_1000_inch;
473 break;
474 }
475 case fmt_big:{
476 int segments_per_1000_inch = 1; /* non-zero default for switch */
477 switch (ft_qic_std) {
478 case QIC_TAPE_QIC40:
479 segments_per_1000_inch = 332;
480 break;
481 case QIC_TAPE_QIC80:
482 segments_per_1000_inch = 488;
483 break;
484 case QIC_TAPE_QIC3010:
485 segments_per_1000_inch = 730;
486 break;
487 case QIC_TAPE_QIC3020:
488 segments_per_1000_inch = 1430;
489 break;
490 default:
491 TRACE_ABORT(-EIO, ft_t_bug,
492 "%x QIC-standard with fmt-code %d, please report",
493 ft_qic_std, ft_format_code);
494 }
495 new_tape_len = ((1000 * ft_segments_per_track +
496 (segments_per_1000_inch - 1)) /
497 segments_per_1000_inch);
498 break;
499 }
500 default:
501 TRACE_ABORT(-EIO, ft_t_err,
502 "unknown tape format, please report !");
503 }
504 if (new_tape_len != ftape_tape_len) {
505 ftape_tape_len = new_tape_len;
506 TRACE(ft_t_info, "calculated tape length is %d ft",
507 ftape_tape_len);
508 ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
509 }
510 if (ft_segments_per_track == 0 && ft_tracks_per_tape == 0 &&
511 max_floppy_side == 0 && max_floppy_track == 0 &&
512 max_floppy_sector == 0) {
513 /* QIC-40 Rev E and earlier has no values in the header.
514 */
515 ft_segments_per_track = 68;
516 ft_tracks_per_tape = 20;
517 max_floppy_side = 1;
518 max_floppy_track = 169;
519 max_floppy_sector = 128;
520 }
521 /* This test will compensate for the wrong parameter on tapes
522 * formatted by Conner software.
523 */
524 if (ft_segments_per_track == 150 &&
525 ft_tracks_per_tape == 28 &&
526 max_floppy_side == 7 &&
527 max_floppy_track == 149 &&
528 max_floppy_sector == 128) {
529TRACE(ft_t_info, "the famous CONNER bug: max_floppy_side off by one !");
530 max_floppy_side = 6;
531 }
532 /* These tests will compensate for the wrong parameter on tapes
533 * formatted by ComByte Windows software.
534 *
535 * First, for 205 foot tapes
536 */
537 if (ft_segments_per_track == 100 &&
538 ft_tracks_per_tape == 28 &&
539 max_floppy_side == 9 &&
540 max_floppy_track == 149 &&
541 max_floppy_sector == 128) {
542TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");
543 max_floppy_side = 4;
544 }
545 /* Next, for 307 foot tapes. */
546 if (ft_segments_per_track == 150 &&
547 ft_tracks_per_tape == 28 &&
548 max_floppy_side == 9 &&
549 max_floppy_track == 149 &&
550 max_floppy_sector == 128) {
551TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");
552 max_floppy_side = 6;
553 }
554 /* This test will compensate for the wrong parameter on tapes
555 * formatted by Colorado Windows software.
556 */
557 if (ft_segments_per_track == 150 &&
558 ft_tracks_per_tape == 28 &&
559 max_floppy_side == 6 &&
560 max_floppy_track == 150 &&
561 max_floppy_sector == 128) {
562TRACE(ft_t_info, "the famous Colorado bug: max_floppy_track off by one !");
563 max_floppy_track = 149;
564 }
565 ftape_segments_per_head = ((max_floppy_sector/FT_SECTORS_PER_SEGMENT) *
566 (max_floppy_track + 1));
567 /* This test will compensate for some bug reported by Dima
568 * Brodsky. Seems to be a Colorado bug, either. (freebee
569 * Imation tape shipped together with Colorado T3000
570 */
571 if ((ft_format_code == fmt_var || ft_format_code == fmt_big) &&
572 ft_tracks_per_tape == 50 &&
573 max_floppy_side == 54 &&
574 max_floppy_track == 255 &&
575 max_floppy_sector == 128) {
576TRACE(ft_t_info, "the famous ??? bug: max_floppy_track off by one !");
577 max_floppy_track = 254;
578 }
579 /*
580 * Verify drive_configuration with tape parameters
581 */
582 if (ftape_segments_per_head == 0 || ftape_segments_per_cylinder == 0 ||
583 ((ft_segments_per_track * ft_tracks_per_tape - 1) / ftape_segments_per_head
584 != max_floppy_side) ||
585 (ftape_segments_per_head / ftape_segments_per_cylinder - 1 != max_floppy_track) ||
586 (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT != max_floppy_sector)
587#ifdef TESTING
588 || ((ft_format_code == fmt_var || ft_format_code == fmt_big) &&
589 (max_floppy_track != 254 || max_floppy_sector != 128))
590#endif
591 ) {
592 char segperheadz = ftape_segments_per_head ? ' ' : '?';
593 char segpercylz = ftape_segments_per_cylinder ? ' ' : '?';
594 TRACE(ft_t_err,"Tape parameters inconsistency, please report");
595 TRACE(ft_t_err, "reported = %d/%d/%d/%d/%d/%d",
596 ft_format_code,
597 ft_segments_per_track,
598 ft_tracks_per_tape,
599 max_floppy_side,
600 max_floppy_track,
601 max_floppy_sector);
602 TRACE(ft_t_err, "required = %d/%d/%d/%d%c/%d%c/%d",
603 ft_format_code,
604 ft_segments_per_track,
605 ft_tracks_per_tape,
606 ftape_segments_per_head ?
607 ((ft_segments_per_track * ft_tracks_per_tape -1) /
608 ftape_segments_per_head ) :
609 (ft_segments_per_track * ft_tracks_per_tape -1),
610 segperheadz,
611 ftape_segments_per_cylinder ?
612 (ftape_segments_per_head /
613 ftape_segments_per_cylinder - 1 ) :
614 ftape_segments_per_head - 1,
615 segpercylz,
616 (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT));
617 TRACE_EXIT -EIO;
618 }
619 ftape_extract_bad_sector_map(address);
620 TRACE_EXIT 0;
621}
diff --git a/drivers/char/ftape/lowlevel/ftape-read.h b/drivers/char/ftape/lowlevel/ftape-read.h
deleted file mode 100644
index 069f99f2a984..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-read.h
+++ /dev/null
@@ -1,51 +0,0 @@
1#ifndef _FTAPE_READ_H
2#define _FTAPE_READ_H
3
4/*
5 * Copyright (C) 1994-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:22 $
26 *
27 * This file contains the definitions for the read functions
28 * for the QIC-117 floppy-tape driver for Linux.
29 *
30 */
31
32/* ftape-read.c defined global functions.
33 */
34typedef enum {
35 FT_RD_SINGLE = 0,
36 FT_RD_AHEAD = 1,
37} ft_read_mode_t;
38
39extern int ftape_read_header_segment(__u8 *address);
40extern int ftape_decode_header_segment(__u8 *address);
41extern int ftape_read_segment_fraction(const int segment,
42 void *address,
43 const ft_read_mode_t read_mode,
44 const int start,
45 const int size);
46#define ftape_read_segment(segment, address, read_mode) \
47 ftape_read_segment_fraction(segment, address, read_mode, \
48 0, FT_SEGMENT_SIZE)
49extern void ftape_zap_read_buffers(void);
50
51#endif /* _FTAPE_READ_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-rw.c b/drivers/char/ftape/lowlevel/ftape-rw.c
deleted file mode 100644
index c0d6dc2cbfd3..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-rw.c
+++ /dev/null
@@ -1,1092 +0,0 @@
1/*
2 * Copyright (C) 1993-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/ftape-rw.c,v $
21 * $Revision: 1.7 $
22 * $Date: 1997/10/28 14:26:49 $
23 *
24 * This file contains some common code for the segment read and
25 * segment write routines for the QIC-117 floppy-tape driver for
26 * Linux.
27 */
28
29#include <linux/string.h>
30#include <linux/errno.h>
31
32#include <linux/ftape.h>
33#include <linux/qic117.h>
34#include "../lowlevel/ftape-tracing.h"
35#include "../lowlevel/ftape-rw.h"
36#include "../lowlevel/fdc-io.h"
37#include "../lowlevel/ftape-init.h"
38#include "../lowlevel/ftape-io.h"
39#include "../lowlevel/ftape-ctl.h"
40#include "../lowlevel/ftape-read.h"
41#include "../lowlevel/ftape-ecc.h"
42#include "../lowlevel/ftape-bsm.h"
43
44/* Global vars.
45 */
46int ft_nr_buffers;
47buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS];
48static volatile int ft_head;
49static volatile int ft_tail; /* not volatile but need same type as head */
50int fdc_setup_error;
51location_record ft_location = {-1, 0};
52volatile int ftape_tape_running;
53
54/* Local vars.
55 */
56static int overrun_count_offset;
57static int inhibit_correction;
58
59/* maxmimal allowed overshoot when fast seeking
60 */
61#define OVERSHOOT_LIMIT 10
62
63/* Increment cyclic buffer nr.
64 */
65buffer_struct *ftape_next_buffer(ft_buffer_queue_t pos)
66{
67 switch (pos) {
68 case ft_queue_head:
69 if (++ft_head >= ft_nr_buffers) {
70 ft_head = 0;
71 }
72 return ft_buffer[ft_head];
73 case ft_queue_tail:
74 if (++ft_tail >= ft_nr_buffers) {
75 ft_tail = 0;
76 }
77 return ft_buffer[ft_tail];
78 default:
79 return NULL;
80 }
81}
82int ftape_buffer_id(ft_buffer_queue_t pos)
83{
84 switch(pos) {
85 case ft_queue_head: return ft_head;
86 case ft_queue_tail: return ft_tail;
87 default: return -1;
88 }
89}
90buffer_struct *ftape_get_buffer(ft_buffer_queue_t pos)
91{
92 switch(pos) {
93 case ft_queue_head: return ft_buffer[ft_head];
94 case ft_queue_tail: return ft_buffer[ft_tail];
95 default: return NULL;
96 }
97}
98void ftape_reset_buffer(void)
99{
100 ft_head = ft_tail = 0;
101}
102
103buffer_state_enum ftape_set_state(buffer_state_enum new_state)
104{
105 buffer_state_enum old_state = ft_driver_state;
106
107 ft_driver_state = new_state;
108 return old_state;
109}
110/* Calculate Floppy Disk Controller and DMA parameters for a segment.
111 * head: selects buffer struct in array.
112 * offset: number of physical sectors to skip (including bad ones).
113 * count: number of physical sectors to handle (including bad ones).
114 */
115static int setup_segment(buffer_struct * buff,
116 int segment_id,
117 unsigned int sector_offset,
118 unsigned int sector_count,
119 int retry)
120{
121 SectorMap offset_mask;
122 SectorMap mask;
123 TRACE_FUN(ft_t_any);
124
125 buff->segment_id = segment_id;
126 buff->sector_offset = sector_offset;
127 buff->remaining = sector_count;
128 buff->head = segment_id / ftape_segments_per_head;
129 buff->cyl = (segment_id % ftape_segments_per_head) / ftape_segments_per_cylinder;
130 buff->sect = (segment_id % ftape_segments_per_cylinder) * FT_SECTORS_PER_SEGMENT + 1;
131 buff->deleted = 0;
132 offset_mask = (1 << buff->sector_offset) - 1;
133 mask = ftape_get_bad_sector_entry(segment_id) & offset_mask;
134 while (mask) {
135 if (mask & 1) {
136 offset_mask >>= 1; /* don't count bad sector */
137 }
138 mask >>= 1;
139 }
140 buff->data_offset = count_ones(offset_mask); /* good sectors to skip */
141 buff->ptr = buff->address + buff->data_offset * FT_SECTOR_SIZE;
142 TRACE(ft_t_flow, "data offset = %d sectors", buff->data_offset);
143 if (retry) {
144 buff->soft_error_map &= offset_mask; /* keep skipped part */
145 } else {
146 buff->hard_error_map = buff->soft_error_map = 0;
147 }
148 buff->bad_sector_map = ftape_get_bad_sector_entry(buff->segment_id);
149 if (buff->bad_sector_map != 0) {
150 TRACE(ft_t_noise, "segment: %d, bad sector map: %08lx",
151 buff->segment_id, (long)buff->bad_sector_map);
152 } else {
153 TRACE(ft_t_flow, "segment: %d", buff->segment_id);
154 }
155 if (buff->sector_offset > 0) {
156 buff->bad_sector_map >>= buff->sector_offset;
157 }
158 if (buff->sector_offset != 0 || buff->remaining != FT_SECTORS_PER_SEGMENT) {
159 TRACE(ft_t_flow, "sector offset = %d, count = %d",
160 buff->sector_offset, buff->remaining);
161 }
162 /* Segments with 3 or less sectors are not written with valid
163 * data because there is no space left for the ecc. The
164 * data written is whatever happens to be in the buffer.
165 * Reading such a segment will return a zero byte-count.
166 * To allow us to read/write segments with all bad sectors
167 * we fake one readable sector in the segment. This
168 * prevents having to handle these segments in a very
169 * special way. It is not important if the reading of this
170 * bad sector fails or not (the data is ignored). It is
171 * only read to keep the driver running.
172 *
173 * The QIC-40/80 spec. has no information on how to handle
174 * this case, so this is my interpretation.
175 */
176 if (buff->bad_sector_map == EMPTY_SEGMENT) {
177 TRACE(ft_t_flow, "empty segment %d, fake first sector good",
178 buff->segment_id);
179 if (buff->ptr != buff->address) {
180 TRACE(ft_t_bug, "This is a bug: %p/%p",
181 buff->ptr, buff->address);
182 }
183 buff->bad_sector_map = FAKE_SEGMENT;
184 }
185 fdc_setup_error = 0;
186 buff->next_segment = segment_id + 1;
187 TRACE_EXIT 0;
188}
189
190/* Calculate Floppy Disk Controller and DMA parameters for a new segment.
191 */
192int ftape_setup_new_segment(buffer_struct * buff, int segment_id, int skip)
193{
194 int result = 0;
195 static int old_segment_id = -1;
196 static buffer_state_enum old_ft_driver_state = idle;
197 int retry = 0;
198 unsigned offset = 0;
199 int count = FT_SECTORS_PER_SEGMENT;
200 TRACE_FUN(ft_t_flow);
201
202 TRACE(ft_t_flow, "%s segment %d (old = %d)",
203 (ft_driver_state == reading || ft_driver_state == verifying)
204 ? "reading" : "writing",
205 segment_id, old_segment_id);
206 if (ft_driver_state != old_ft_driver_state) { /* when verifying */
207 old_segment_id = -1;
208 old_ft_driver_state = ft_driver_state;
209 }
210 if (segment_id == old_segment_id) {
211 ++buff->retry;
212 ++ft_history.retries;
213 TRACE(ft_t_flow, "setting up for retry nr %d", buff->retry);
214 retry = 1;
215 if (skip && buff->skip > 0) { /* allow skip on retry */
216 offset = buff->skip;
217 count -= offset;
218 TRACE(ft_t_flow, "skipping %d sectors", offset);
219 }
220 } else {
221 buff->retry = 0;
222 buff->skip = 0;
223 old_segment_id = segment_id;
224 }
225 result = setup_segment(buff, segment_id, offset, count, retry);
226 TRACE_EXIT result;
227}
228
229/* Determine size of next cluster of good sectors.
230 */
231int ftape_calc_next_cluster(buffer_struct * buff)
232{
233 /* Skip bad sectors.
234 */
235 while (buff->remaining > 0 && (buff->bad_sector_map & 1) != 0) {
236 buff->bad_sector_map >>= 1;
237 ++buff->sector_offset;
238 --buff->remaining;
239 }
240 /* Find next cluster of good sectors
241 */
242 if (buff->bad_sector_map == 0) { /* speed up */
243 buff->sector_count = buff->remaining;
244 } else {
245 SectorMap map = buff->bad_sector_map;
246
247 buff->sector_count = 0;
248 while (buff->sector_count < buff->remaining && (map & 1) == 0) {
249 ++buff->sector_count;
250 map >>= 1;
251 }
252 }
253 return buff->sector_count;
254}
255
256/* if just passed the last segment on a track, wait for BOT
257 * or EOT mark.
258 */
259int ftape_handle_logical_eot(void)
260{
261 TRACE_FUN(ft_t_flow);
262
263 if (ft_runner_status == logical_eot) {
264 int status;
265
266 TRACE(ft_t_noise, "tape at logical EOT");
267 TRACE_CATCH(ftape_ready_wait(ftape_timeout.seek, &status),);
268 if ((status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) {
269 TRACE_ABORT(-EIO, ft_t_err, "eot/bot not reached");
270 }
271 ft_runner_status = end_of_tape;
272 }
273 if (ft_runner_status == end_of_tape) {
274 TRACE(ft_t_noise, "runner stopped because of logical EOT");
275 ft_runner_status = idle;
276 }
277 TRACE_EXIT 0;
278}
279
280static int check_bot_eot(int status)
281{
282 TRACE_FUN(ft_t_flow);
283
284 if (status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) {
285 ft_location.bot = ((ft_location.track & 1) == 0 ?
286 (status & QIC_STATUS_AT_BOT) != 0:
287 (status & QIC_STATUS_AT_EOT) != 0);
288 ft_location.eot = !ft_location.bot;
289 ft_location.segment = (ft_location.track +
290 (ft_location.bot ? 0 : 1)) * ft_segments_per_track - 1;
291 ft_location.sector = -1;
292 ft_location.known = 1;
293 TRACE(ft_t_flow, "tape at logical %s",
294 ft_location.bot ? "bot" : "eot");
295 TRACE(ft_t_flow, "segment = %d", ft_location.segment);
296 } else {
297 ft_location.known = 0;
298 }
299 TRACE_EXIT ft_location.known;
300}
301
302/* Read Id of first sector passing tape head.
303 */
304static int ftape_read_id(void)
305{
306 int status;
307 __u8 out[2];
308 TRACE_FUN(ft_t_any);
309
310 /* Assume tape is running on entry, be able to handle
311 * situation where it stopped or is stopping.
312 */
313 ft_location.known = 0; /* default is location not known */
314 out[0] = FDC_READID;
315 out[1] = ft_drive_sel;
316 TRACE_CATCH(fdc_command(out, 2),);
317 switch (fdc_interrupt_wait(20 * FT_SECOND)) {
318 case 0:
319 if (fdc_sect == 0) {
320 if (ftape_report_drive_status(&status) >= 0 &&
321 (status & QIC_STATUS_READY)) {
322 ftape_tape_running = 0;
323 TRACE(ft_t_flow, "tape has stopped");
324 check_bot_eot(status);
325 }
326 } else {
327 ft_location.known = 1;
328 ft_location.segment = (ftape_segments_per_head
329 * fdc_head
330 + ftape_segments_per_cylinder
331 * fdc_cyl
332 + (fdc_sect - 1)
333 / FT_SECTORS_PER_SEGMENT);
334 ft_location.sector = ((fdc_sect - 1)
335 % FT_SECTORS_PER_SEGMENT);
336 ft_location.eot = ft_location.bot = 0;
337 }
338 break;
339 case -ETIME:
340 /* Didn't find id on tape, must be near end: Wait
341 * until stopped.
342 */
343 if (ftape_ready_wait(FT_FOREVER, &status) >= 0) {
344 ftape_tape_running = 0;
345 TRACE(ft_t_flow, "tape has stopped");
346 check_bot_eot(status);
347 }
348 break;
349 default:
350 /* Interrupted or otherwise failing
351 * fdc_interrupt_wait()
352 */
353 TRACE(ft_t_err, "fdc_interrupt_wait failed");
354 break;
355 }
356 if (!ft_location.known) {
357 TRACE_ABORT(-EIO, ft_t_flow, "no id found");
358 }
359 if (ft_location.sector == 0) {
360 TRACE(ft_t_flow, "passing segment %d/%d",
361 ft_location.segment, ft_location.sector);
362 } else {
363 TRACE(ft_t_fdc_dma, "passing segment %d/%d",
364 ft_location.segment, ft_location.sector);
365 }
366 TRACE_EXIT 0;
367}
368
369static int logical_forward(void)
370{
371 ftape_tape_running = 1;
372 return ftape_command(QIC_LOGICAL_FORWARD);
373}
374
375int ftape_stop_tape(int *pstatus)
376{
377 int retry = 0;
378 int result;
379 TRACE_FUN(ft_t_flow);
380
381 do {
382 result = ftape_command_wait(QIC_STOP_TAPE,
383 ftape_timeout.stop, pstatus);
384 if (result == 0) {
385 if ((*pstatus & QIC_STATUS_READY) == 0) {
386 result = -EIO;
387 } else {
388 ftape_tape_running = 0;
389 }
390 }
391 } while (result < 0 && ++retry <= 3);
392 if (result < 0) {
393 TRACE(ft_t_err, "failed ! (fatal)");
394 }
395 TRACE_EXIT result;
396}
397
398int ftape_dumb_stop(void)
399{
400 int result;
401 int status;
402 TRACE_FUN(ft_t_flow);
403
404 /* Abort current fdc operation if it's busy (probably read
405 * or write operation pending) with a reset.
406 */
407 if (fdc_ready_wait(100 /* usec */) < 0) {
408 TRACE(ft_t_noise, "aborting fdc operation");
409 fdc_reset();
410 }
411 /* Reading id's after the last segment on a track may fail
412 * but eventually the drive will become ready (logical eot).
413 */
414 result = ftape_report_drive_status(&status);
415 ft_location.known = 0;
416 do {
417 if (result == 0 && status & QIC_STATUS_READY) {
418 /* Tape is not running any more.
419 */
420 TRACE(ft_t_noise, "tape already halted");
421 check_bot_eot(status);
422 ftape_tape_running = 0;
423 } else if (ftape_tape_running) {
424 /* Tape is (was) still moving.
425 */
426#ifdef TESTING
427 ftape_read_id();
428#endif
429 result = ftape_stop_tape(&status);
430 } else {
431 /* Tape not yet ready but stopped.
432 */
433 result = ftape_ready_wait(ftape_timeout.pause,&status);
434 }
435 } while (ftape_tape_running
436 && !(sigtestsetmask(&current->pending.signal, _NEVER_BLOCK)));
437#ifndef TESTING
438 ft_location.known = 0;
439#endif
440 if (ft_runner_status == aborting || ft_runner_status == do_abort) {
441 ft_runner_status = idle;
442 }
443 TRACE_EXIT result;
444}
445
446/* Wait until runner has finished tail buffer.
447 *
448 */
449int ftape_wait_segment(buffer_state_enum state)
450{
451 int status;
452 int result = 0;
453 TRACE_FUN(ft_t_flow);
454
455 while (ft_buffer[ft_tail]->status == state) {
456 TRACE(ft_t_flow, "state: %d", ft_buffer[ft_tail]->status);
457 /* First buffer still being worked on, wait up to timeout.
458 *
459 * Note: we check two times for being killed. 50
460 * seconds are quite long. Note that
461 * fdc_interrupt_wait() is not killable by any
462 * means. ftape_read_segment() wants us to return
463 * -EINTR in case of a signal.
464 */
465 FT_SIGNAL_EXIT(_DONT_BLOCK);
466 result = fdc_interrupt_wait(50 * FT_SECOND);
467 FT_SIGNAL_EXIT(_DONT_BLOCK);
468 if (result < 0) {
469 TRACE_ABORT(result,
470 ft_t_err, "fdc_interrupt_wait failed");
471 }
472 if (fdc_setup_error) {
473 /* recover... FIXME */
474 TRACE_ABORT(-EIO, ft_t_err, "setup error");
475 }
476 }
477 if (ft_buffer[ft_tail]->status != error) {
478 TRACE_EXIT 0;
479 }
480 TRACE_CATCH(ftape_report_drive_status(&status),);
481 TRACE(ft_t_noise, "ftape_report_drive_status: 0x%02x", status);
482 if ((status & QIC_STATUS_READY) &&
483 (status & QIC_STATUS_ERROR)) {
484 unsigned int error;
485 qic117_cmd_t command;
486
487 /* Report and clear error state.
488 * In case the drive can't operate at the selected
489 * rate, select the next lower data rate.
490 */
491 ftape_report_error(&error, &command, 1);
492 if (error == 31 && command == QIC_LOGICAL_FORWARD) {
493 /* drive does not accept this data rate */
494 if (ft_data_rate > 250) {
495 TRACE(ft_t_info,
496 "Probable data rate conflict");
497 TRACE(ft_t_info,
498 "Lowering data rate to %d Kbps",
499 ft_data_rate / 2);
500 ftape_half_data_rate();
501 if (ft_buffer[ft_tail]->retry > 0) {
502 /* give it a chance */
503 --ft_buffer[ft_tail]->retry;
504 }
505 } else {
506 /* no rate is accepted... */
507 TRACE(ft_t_err, "We're dead :(");
508 }
509 } else {
510 TRACE(ft_t_err, "Unknown error");
511 }
512 TRACE_EXIT -EIO; /* g.p. error */
513 }
514 TRACE_EXIT 0;
515}
516
517/* forward */ static int seek_forward(int segment_id, int fast);
518
519static int fast_seek(int count, int reverse)
520{
521 int result = 0;
522 int status;
523 TRACE_FUN(ft_t_flow);
524
525 if (count > 0) {
526 /* If positioned at begin or end of tape, fast seeking needs
527 * special treatment.
528 * Starting from logical bot needs a (slow) seek to the first
529 * segment before the high speed seek. Most drives do this
530 * automatically but some older don't, so we treat them
531 * all the same.
532 * Starting from logical eot is even more difficult because
533 * we cannot (slow) reverse seek to the last segment.
534 * TO BE IMPLEMENTED.
535 */
536 inhibit_correction = 0;
537 if (ft_location.known &&
538 ((ft_location.bot && !reverse) ||
539 (ft_location.eot && reverse))) {
540 if (!reverse) {
541 /* (slow) skip to first segment on a track
542 */
543 seek_forward(ft_location.track * ft_segments_per_track, 0);
544 --count;
545 } else {
546 /* When seeking backwards from
547 * end-of-tape the number of erased
548 * gaps found seems to be higher than
549 * expected. Therefor the drive must
550 * skip some more segments than
551 * calculated, but we don't know how
552 * many. Thus we will prevent the
553 * re-calculation of offset and
554 * overshoot when seeking backwards.
555 */
556 inhibit_correction = 1;
557 count += 3; /* best guess */
558 }
559 }
560 } else {
561 TRACE(ft_t_flow, "warning: zero or negative count: %d", count);
562 }
563 if (count > 0) {
564 int i;
565 int nibbles = count > 255 ? 3 : 2;
566
567 if (count > 4095) {
568 TRACE(ft_t_noise, "skipping clipped at 4095 segment");
569 count = 4095;
570 }
571 /* Issue this tape command first. */
572 if (!reverse) {
573 TRACE(ft_t_noise, "skipping %d segment(s)", count);
574 result = ftape_command(nibbles == 3 ?
575 QIC_SKIP_EXTENDED_FORWARD : QIC_SKIP_FORWARD);
576 } else {
577 TRACE(ft_t_noise, "backing up %d segment(s)", count);
578 result = ftape_command(nibbles == 3 ?
579 QIC_SKIP_EXTENDED_REVERSE : QIC_SKIP_REVERSE);
580 }
581 if (result < 0) {
582 TRACE(ft_t_noise, "Skip command failed");
583 } else {
584 --count; /* 0 means one gap etc. */
585 for (i = 0; i < nibbles; ++i) {
586 if (result >= 0) {
587 result = ftape_parameter(count & 15);
588 count /= 16;
589 }
590 }
591 result = ftape_ready_wait(ftape_timeout.rewind, &status);
592 if (result >= 0) {
593 ftape_tape_running = 0;
594 }
595 }
596 }
597 TRACE_EXIT result;
598}
599
600static int validate(int id)
601{
602 /* Check to see if position found is off-track as reported
603 * once. Because all tracks in one direction lie next to
604 * each other, if off-track the error will be approximately
605 * 2 * ft_segments_per_track.
606 */
607 if (ft_location.track == -1) {
608 return 1; /* unforseen situation, don't generate error */
609 } else {
610 /* Use margin of ft_segments_per_track on both sides
611 * because ftape needs some margin and the error we're
612 * looking for is much larger !
613 */
614 int lo = (ft_location.track - 1) * ft_segments_per_track;
615 int hi = (ft_location.track + 2) * ft_segments_per_track;
616
617 return (id >= lo && id < hi);
618 }
619}
620
621static int seek_forward(int segment_id, int fast)
622{
623 int failures = 0;
624 int count;
625 static int margin = 1; /* fixed: stop this before target */
626 static int overshoot = 1;
627 static int min_count = 8;
628 int expected = -1;
629 int target = segment_id - margin;
630 int fast_seeking;
631 int prev_segment = ft_location.segment;
632 TRACE_FUN(ft_t_flow);
633
634 if (!ft_location.known) {
635 TRACE_ABORT(-EIO, ft_t_err,
636 "fatal: cannot seek from unknown location");
637 }
638 if (!validate(segment_id)) {
639 ftape_sleep(1 * FT_SECOND);
640 ft_failure = 1;
641 TRACE_ABORT(-EIO, ft_t_err,
642 "fatal: head off track (bad hardware?)");
643 }
644 TRACE(ft_t_noise, "from %d/%d to %d/0 - %d",
645 ft_location.segment, ft_location.sector,segment_id,margin);
646 count = target - ft_location.segment - overshoot;
647 fast_seeking = (fast &&
648 count > (min_count + (ft_location.bot ? 1 : 0)));
649 if (fast_seeking) {
650 TRACE(ft_t_noise, "fast skipping %d segments", count);
651 expected = segment_id - margin;
652 fast_seek(count, 0);
653 }
654 if (!ftape_tape_running) {
655 logical_forward();
656 }
657 while (ft_location.segment < segment_id) {
658 /* This requires at least one sector in a (bad) segment to
659 * have a valid and readable sector id !
660 * It looks like this is not guaranteed, so we must try
661 * to find a way to skip an EMPTY_SEGMENT. !!! FIXME !!!
662 */
663 if (ftape_read_id() < 0 || !ft_location.known ||
664 sigtestsetmask(&current->pending.signal, _DONT_BLOCK)) {
665 ft_location.known = 0;
666 if (!ftape_tape_running ||
667 ++failures > FT_SECTORS_PER_SEGMENT) {
668 TRACE_ABORT(-EIO, ft_t_err,
669 "read_id failed completely");
670 }
671 FT_SIGNAL_EXIT(_DONT_BLOCK);
672 TRACE(ft_t_flow, "read_id failed, retry (%d)",
673 failures);
674 continue;
675 }
676 if (fast_seeking) {
677 TRACE(ft_t_noise, "ended at %d/%d (%d,%d)",
678 ft_location.segment, ft_location.sector,
679 overshoot, inhibit_correction);
680 if (!inhibit_correction &&
681 (ft_location.segment < expected ||
682 ft_location.segment > expected + margin)) {
683 int error = ft_location.segment - expected;
684 TRACE(ft_t_noise,
685 "adjusting overshoot from %d to %d",
686 overshoot, overshoot + error);
687 overshoot += error;
688 /* All overshoots have the same
689 * direction, so it should never
690 * become negative, but who knows.
691 */
692 if (overshoot < -5 ||
693 overshoot > OVERSHOOT_LIMIT) {
694 if (overshoot < 0) {
695 /* keep sane value */
696 overshoot = -5;
697 } else {
698 /* keep sane value */
699 overshoot = OVERSHOOT_LIMIT;
700 }
701 TRACE(ft_t_noise,
702 "clipped overshoot to %d",
703 overshoot);
704 }
705 }
706 fast_seeking = 0;
707 }
708 if (ft_location.known) {
709 if (ft_location.segment > prev_segment + 1) {
710 TRACE(ft_t_noise,
711 "missed segment %d while skipping",
712 prev_segment + 1);
713 }
714 prev_segment = ft_location.segment;
715 }
716 }
717 if (ft_location.segment > segment_id) {
718 TRACE_ABORT(-EIO,
719 ft_t_noise, "failed: skip ended at segment %d/%d",
720 ft_location.segment, ft_location.sector);
721 }
722 TRACE_EXIT 0;
723}
724
725static int skip_reverse(int segment_id, int *pstatus)
726{
727 int failures = 0;
728 static int overshoot = 1;
729 static int min_rewind = 2; /* 1 + overshoot */
730 static const int margin = 1; /* stop this before target */
731 int expected = 0;
732 int count = 1;
733 int short_seek;
734 int target = segment_id - margin;
735 TRACE_FUN(ft_t_flow);
736
737 if (ft_location.known && !validate(segment_id)) {
738 ftape_sleep(1 * FT_SECOND);
739 ft_failure = 1;
740 TRACE_ABORT(-EIO, ft_t_err,
741 "fatal: head off track (bad hardware?)");
742 }
743 do {
744 if (!ft_location.known) {
745 TRACE(ft_t_warn, "warning: location not known");
746 }
747 TRACE(ft_t_noise, "from %d/%d to %d/0 - %d",
748 ft_location.segment, ft_location.sector,
749 segment_id, margin);
750 /* min_rewind == 1 + overshoot_when_doing_minimum_rewind
751 * overshoot == overshoot_when_doing_larger_rewind
752 * Initially min_rewind == 1 + overshoot, optimization
753 * of both values will be done separately.
754 * overshoot and min_rewind can be negative as both are
755 * sums of three components:
756 * any_overshoot == rewind_overshoot -
757 * stop_overshoot -
758 * start_overshoot
759 */
760 if (ft_location.segment - target - (min_rewind - 1) < 1) {
761 short_seek = 1;
762 } else {
763 count = ft_location.segment - target - overshoot;
764 short_seek = (count < 1);
765 }
766 if (short_seek) {
767 count = 1; /* do shortest rewind */
768 expected = ft_location.segment - min_rewind;
769 if (expected/ft_segments_per_track != ft_location.track) {
770 expected = (ft_location.track *
771 ft_segments_per_track);
772 }
773 } else {
774 expected = target;
775 }
776 fast_seek(count, 1);
777 logical_forward();
778 if (ftape_read_id() < 0 || !ft_location.known ||
779 (sigtestsetmask(&current->pending.signal, _DONT_BLOCK))) {
780 if ((!ftape_tape_running && !ft_location.known) ||
781 ++failures > FT_SECTORS_PER_SEGMENT) {
782 TRACE_ABORT(-EIO, ft_t_err,
783 "read_id failed completely");
784 }
785 FT_SIGNAL_EXIT(_DONT_BLOCK);
786 TRACE_CATCH(ftape_report_drive_status(pstatus),);
787 TRACE(ft_t_noise, "ftape_read_id failed, retry (%d)",
788 failures);
789 continue;
790 }
791 TRACE(ft_t_noise, "ended at %d/%d (%d,%d,%d)",
792 ft_location.segment, ft_location.sector,
793 min_rewind, overshoot, inhibit_correction);
794 if (!inhibit_correction &&
795 (ft_location.segment < expected ||
796 ft_location.segment > expected + margin)) {
797 int error = expected - ft_location.segment;
798 if (short_seek) {
799 TRACE(ft_t_noise,
800 "adjusting min_rewind from %d to %d",
801 min_rewind, min_rewind + error);
802 min_rewind += error;
803 if (min_rewind < -5) {
804 /* is this right ? FIXME ! */
805 /* keep sane value */
806 min_rewind = -5;
807 TRACE(ft_t_noise,
808 "clipped min_rewind to %d",
809 min_rewind);
810 }
811 } else {
812 TRACE(ft_t_noise,
813 "adjusting overshoot from %d to %d",
814 overshoot, overshoot + error);
815 overshoot += error;
816 if (overshoot < -5 ||
817 overshoot > OVERSHOOT_LIMIT) {
818 if (overshoot < 0) {
819 /* keep sane value */
820 overshoot = -5;
821 } else {
822 /* keep sane value */
823 overshoot = OVERSHOOT_LIMIT;
824 }
825 TRACE(ft_t_noise,
826 "clipped overshoot to %d",
827 overshoot);
828 }
829 }
830 }
831 } while (ft_location.segment > segment_id);
832 if (ft_location.known) {
833 TRACE(ft_t_noise, "current location: %d/%d",
834 ft_location.segment, ft_location.sector);
835 }
836 TRACE_EXIT 0;
837}
838
839static int determine_position(void)
840{
841 int retry = 0;
842 int status;
843 int result;
844 TRACE_FUN(ft_t_flow);
845
846 if (!ftape_tape_running) {
847 /* This should only happen if tape is stopped by isr.
848 */
849 TRACE(ft_t_flow, "waiting for tape stop");
850 if (ftape_ready_wait(ftape_timeout.pause, &status) < 0) {
851 TRACE(ft_t_flow, "drive still running (fatal)");
852 ftape_tape_running = 1; /* ? */
853 }
854 } else {
855 ftape_report_drive_status(&status);
856 }
857 if (status & QIC_STATUS_READY) {
858 /* Drive must be ready to check error state !
859 */
860 TRACE(ft_t_flow, "drive is ready");
861 if (status & QIC_STATUS_ERROR) {
862 unsigned int error;
863 qic117_cmd_t command;
864
865 /* Report and clear error state, try to continue.
866 */
867 TRACE(ft_t_flow, "error status set");
868 ftape_report_error(&error, &command, 1);
869 ftape_ready_wait(ftape_timeout.reset, &status);
870 ftape_tape_running = 0; /* ? */
871 }
872 if (check_bot_eot(status)) {
873 if (ft_location.bot) {
874 if ((status & QIC_STATUS_READY) == 0) {
875 /* tape moving away from
876 * bot/eot, let's see if we
877 * can catch up with the first
878 * segment on this track.
879 */
880 } else {
881 TRACE(ft_t_flow,
882 "start tape from logical bot");
883 logical_forward(); /* start moving */
884 }
885 } else {
886 if ((status & QIC_STATUS_READY) == 0) {
887 TRACE(ft_t_noise, "waiting for logical end of track");
888 result = ftape_ready_wait(ftape_timeout.reset, &status);
889 /* error handling needed ? */
890 } else {
891 TRACE(ft_t_noise,
892 "tape at logical end of track");
893 }
894 }
895 } else {
896 TRACE(ft_t_flow, "start tape");
897 logical_forward(); /* start moving */
898 ft_location.known = 0; /* not cleared by logical forward ! */
899 }
900 }
901 /* tape should be moving now, start reading id's
902 */
903 while (!ft_location.known &&
904 retry++ < FT_SECTORS_PER_SEGMENT &&
905 (result = ftape_read_id()) < 0) {
906
907 TRACE(ft_t_flow, "location unknown");
908
909 /* exit on signal
910 */
911 FT_SIGNAL_EXIT(_DONT_BLOCK);
912
913 /* read-id somehow failed, tape may
914 * have reached end or some other
915 * error happened.
916 */
917 TRACE(ft_t_flow, "read-id failed");
918 TRACE_CATCH(ftape_report_drive_status(&status),);
919 TRACE(ft_t_err, "ftape_report_drive_status: 0x%02x", status);
920 if (status & QIC_STATUS_READY) {
921 ftape_tape_running = 0;
922 TRACE(ft_t_noise, "tape stopped for unknown reason! "
923 "status = 0x%02x", status);
924 if (status & QIC_STATUS_ERROR ||
925 !check_bot_eot(status)) {
926 /* oops, tape stopped but not at end!
927 */
928 TRACE_EXIT -EIO;
929 }
930 }
931 }
932 TRACE(ft_t_flow,
933 "tape is positioned at segment %d", ft_location.segment);
934 TRACE_EXIT ft_location.known ? 0 : -EIO;
935}
936
937/* Get the tape running and position it just before the
938 * requested segment.
939 * Seek tape-track and reposition as needed.
940 */
941int ftape_start_tape(int segment_id, int sector_offset)
942{
943 int track = segment_id / ft_segments_per_track;
944 int result = -EIO;
945 int status;
946 static int last_segment = -1;
947 static int bad_bus_timing = 0;
948 /* number of segments passing the head between starting the tape
949 * and being able to access the first sector.
950 */
951 static int start_offset = 1;
952 int retry;
953 TRACE_FUN(ft_t_flow);
954
955 /* If sector_offset > 0, seek into wanted segment instead of
956 * into previous.
957 * This allows error recovery if a part of the segment is bad
958 * (erased) causing the tape drive to generate an index pulse
959 * thus causing a no-data error before the requested sector
960 * is reached.
961 */
962 ftape_tape_running = 0;
963 TRACE(ft_t_noise, "target segment: %d/%d%s", segment_id, sector_offset,
964 ft_buffer[ft_head]->retry > 0 ? " retry" : "");
965 if (ft_buffer[ft_head]->retry > 0) { /* this is a retry */
966 int dist = segment_id - last_segment;
967
968 if ((int)ft_history.overrun_errors < overrun_count_offset) {
969 overrun_count_offset = ft_history.overrun_errors;
970 } else if (dist < 0 || dist > 50) {
971 overrun_count_offset = ft_history.overrun_errors;
972 } else if ((ft_history.overrun_errors -
973 overrun_count_offset) >= 8) {
974 if (ftape_increase_threshold() >= 0) {
975 --ft_buffer[ft_head]->retry;
976 overrun_count_offset =
977 ft_history.overrun_errors;
978 TRACE(ft_t_warn, "increased threshold because "
979 "of excessive overrun errors");
980 } else if (!bad_bus_timing && ft_data_rate >= 1000) {
981 ftape_half_data_rate();
982 --ft_buffer[ft_head]->retry;
983 bad_bus_timing = 1;
984 overrun_count_offset =
985 ft_history.overrun_errors;
986 TRACE(ft_t_warn, "reduced datarate because "
987 "of excessive overrun errors");
988 }
989 }
990 }
991 last_segment = segment_id;
992 if (ft_location.track != track ||
993 (ftape_might_be_off_track && ft_buffer[ft_head]->retry== 0)) {
994 /* current track unknown or not equal to destination
995 */
996 ftape_ready_wait(ftape_timeout.seek, &status);
997 ftape_seek_head_to_track(track);
998 /* overrun_count_offset = ft_history.overrun_errors; */
999 }
1000 result = -EIO;
1001 retry = 0;
1002 while (result < 0 &&
1003 retry++ <= 5 &&
1004 !ft_failure &&
1005 !(sigtestsetmask(&current->pending.signal, _DONT_BLOCK))) {
1006
1007 if (retry && start_offset < 5) {
1008 start_offset ++;
1009 }
1010 /* Check if we are able to catch the requested
1011 * segment in time.
1012 */
1013 if ((ft_location.known || (determine_position() == 0)) &&
1014 ft_location.segment >=
1015 (segment_id -
1016 ((ftape_tape_running || ft_location.bot)
1017 ? 0 : start_offset))) {
1018 /* Too far ahead (in or past target segment).
1019 */
1020 if (ftape_tape_running) {
1021 if ((result = ftape_stop_tape(&status)) < 0) {
1022 TRACE(ft_t_err,
1023 "stop tape failed with code %d",
1024 result);
1025 break;
1026 }
1027 TRACE(ft_t_noise, "tape stopped");
1028 ftape_tape_running = 0;
1029 }
1030 TRACE(ft_t_noise, "repositioning");
1031 ++ft_history.rewinds;
1032 if (segment_id % ft_segments_per_track < start_offset){
1033 TRACE(ft_t_noise, "end of track condition\n"
1034 KERN_INFO "segment_id : %d\n"
1035 KERN_INFO "ft_segments_per_track: %d\n"
1036 KERN_INFO "start_offset : %d",
1037 segment_id, ft_segments_per_track,
1038 start_offset);
1039
1040 /* If seeking to first segments on
1041 * track better do a complete rewind
1042 * to logical begin of track to get a
1043 * more steady tape motion.
1044 */
1045 result = ftape_command_wait(
1046 (ft_location.track & 1)
1047 ? QIC_PHYSICAL_FORWARD
1048 : QIC_PHYSICAL_REVERSE,
1049 ftape_timeout.rewind, &status);
1050 check_bot_eot(status); /* update location */
1051 } else {
1052 result= skip_reverse(segment_id - start_offset,
1053 &status);
1054 }
1055 }
1056 if (!ft_location.known) {
1057 TRACE(ft_t_bug, "panic: location not known");
1058 result = -EIO;
1059 continue; /* while() will check for failure */
1060 }
1061 TRACE(ft_t_noise, "current segment: %d/%d",
1062 ft_location.segment, ft_location.sector);
1063 /* We're on the right track somewhere before the
1064 * wanted segment. Start tape movement if needed and
1065 * skip to just before or inside the requested
1066 * segment. Keep tape running.
1067 */
1068 result = 0;
1069 if (ft_location.segment <
1070 (segment_id - ((ftape_tape_running || ft_location.bot)
1071 ? 0 : start_offset))) {
1072 if (sector_offset > 0) {
1073 result = seek_forward(segment_id,
1074 retry <= 3);
1075 } else {
1076 result = seek_forward(segment_id - 1,
1077 retry <= 3);
1078 }
1079 }
1080 if (result == 0 &&
1081 ft_location.segment !=
1082 (segment_id - (sector_offset > 0 ? 0 : 1))) {
1083 result = -EIO;
1084 }
1085 }
1086 if (result < 0) {
1087 TRACE(ft_t_err, "failed to reposition");
1088 } else {
1089 ft_runner_status = running;
1090 }
1091 TRACE_EXIT result;
1092}
diff --git a/drivers/char/ftape/lowlevel/ftape-rw.h b/drivers/char/ftape/lowlevel/ftape-rw.h
deleted file mode 100644
index 32f4feeb887c..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-rw.h
+++ /dev/null
@@ -1,111 +0,0 @@
1#ifndef _FTAPE_RW_H
2#define _FTAPE_RW_H
3
4/*
5 * Copyright (C) 1993-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-rw.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:25 $
26 *
27 * This file contains the definitions for the read and write
28 * functions for the QIC-117 floppy-tape driver for Linux.
29 *
30 * Claus-Justus Heine (1996/09/20): Add definition of format code 6
31 * Claus-Justus Heine (1996/10/04): Changed GET/PUT macros to cast to (__u8 *)
32 *
33 */
34
35#include "../lowlevel/fdc-io.h"
36#include "../lowlevel/ftape-init.h"
37#include "../lowlevel/ftape-bsm.h"
38
39#include <asm/unaligned.h>
40
41#define GET2(address, offset) get_unaligned((__u16*)((__u8 *)address + offset))
42#define GET4(address, offset) get_unaligned((__u32*)((__u8 *)address + offset))
43#define GET8(address, offset) get_unaligned((__u64*)((__u8 *)address + offset))
44#define PUT2(address, offset , value) put_unaligned((value), (__u16*)((__u8 *)address + offset))
45#define PUT4(address, offset , value) put_unaligned((value), (__u32*)((__u8 *)address + offset))
46#define PUT8(address, offset , value) put_unaligned((value), (__u64*)((__u8 *)address + offset))
47
48enum runner_status_enum {
49 idle = 0,
50 running,
51 do_abort,
52 aborting,
53 logical_eot,
54 end_of_tape,
55};
56
57typedef enum ft_buffer_queue {
58 ft_queue_head = 0,
59 ft_queue_tail = 1
60} ft_buffer_queue_t;
61
62
63typedef struct {
64 int track; /* tape head position */
65 volatile int segment; /* current segment */
66 volatile int sector; /* sector offset within current segment */
67 volatile unsigned int bot; /* logical begin of track */
68 volatile unsigned int eot; /* logical end of track */
69 volatile unsigned int known; /* validates bot, segment, sector */
70} location_record;
71
72/* Count nr of 1's in pattern.
73 */
74static inline int count_ones(unsigned long mask)
75{
76 int bits;
77
78 for (bits = 0; mask != 0; mask >>= 1) {
79 if (mask & 1) {
80 ++bits;
81 }
82 }
83 return bits;
84}
85
86#define FT_MAX_NR_BUFFERS 16 /* arbitrary value */
87/* ftape-rw.c defined global vars.
88 */
89extern buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS];
90extern int ft_nr_buffers;
91extern location_record ft_location;
92extern volatile int ftape_tape_running;
93
94/* ftape-rw.c defined global functions.
95 */
96extern int ftape_setup_new_segment(buffer_struct * buff,
97 int segment_id,
98 int offset);
99extern int ftape_calc_next_cluster(buffer_struct * buff);
100extern buffer_struct *ftape_next_buffer (ft_buffer_queue_t pos);
101extern buffer_struct *ftape_get_buffer (ft_buffer_queue_t pos);
102extern int ftape_buffer_id (ft_buffer_queue_t pos);
103extern void ftape_reset_buffer(void);
104extern void ftape_tape_parameters(__u8 drive_configuration);
105extern int ftape_wait_segment(buffer_state_enum state);
106extern int ftape_dumb_stop(void);
107extern int ftape_start_tape(int segment_id, int offset);
108extern int ftape_stop_tape(int *pstatus);
109extern int ftape_handle_logical_eot(void);
110extern buffer_state_enum ftape_set_state(buffer_state_enum new_state);
111#endif /* _FTAPE_RW_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-setup.c b/drivers/char/ftape/lowlevel/ftape-setup.c
deleted file mode 100644
index 678340acd0b7..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-setup.c
+++ /dev/null
@@ -1,104 +0,0 @@
1/*
2 * Copyright (C) 1996, 1997 Claus-Justus Heine.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 *
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-setup.c,v $
20 * $Revision: 1.7 $
21 * $Date: 1997/10/10 09:57:06 $
22 *
23 * This file contains the code for processing the kernel command
24 * line options for the QIC-40/80/3010/3020 floppy-tape driver
25 * "ftape" for Linux.
26 */
27
28#include <linux/string.h>
29#include <linux/errno.h>
30#include <linux/mm.h>
31
32#include <linux/ftape.h>
33#include <linux/init.h>
34#include "../lowlevel/ftape-tracing.h"
35#include "../lowlevel/fdc-io.h"
36
37static struct param_table {
38 const char *name;
39 int *var;
40 int def_param;
41 int min;
42 int max;
43} config_params[] __initdata = {
44#ifndef CONFIG_FT_NO_TRACE_AT_ALL
45 { "tracing", &ftape_tracing, 3, ft_t_bug, ft_t_any},
46#endif
47 { "ioport", &ft_fdc_base, CONFIG_FT_FDC_BASE, 0x0, 0xfff},
48 { "irq", &ft_fdc_irq, CONFIG_FT_FDC_IRQ, 2, 15},
49 { "dma", &ft_fdc_dma, CONFIG_FT_FDC_DMA, 0, 3},
50 { "threshold", &ft_fdc_threshold, CONFIG_FT_FDC_THR, 1, 16},
51 { "datarate", &ft_fdc_rate_limit, CONFIG_FT_FDC_MAX_RATE, 500, 2000},
52 { "fc10", &ft_probe_fc10, CONFIG_FT_PROBE_FC10, 0, 1},
53 { "mach2", &ft_mach2, CONFIG_FT_MACH2, 0, 1}
54};
55
56static int __init ftape_setup(char *str)
57{
58 int i;
59 int param;
60 int ints[2];
61
62 TRACE_FUN(ft_t_flow);
63
64 str = get_options(str, ARRAY_SIZE(ints), ints);
65 if (str) {
66 for (i=0; i < NR_ITEMS(config_params); i++) {
67 if (strcmp(str,config_params[i].name) == 0){
68 if (ints[0]) {
69 param = ints[1];
70 } else {
71 param = config_params[i].def_param;
72 }
73 if (param < config_params[i].min ||
74 param > config_params[i].max) {
75 TRACE(ft_t_err,
76 "parameter %s out of range %d ... %d",
77 config_params[i].name,
78 config_params[i].min,
79 config_params[i].max);
80 goto out;
81 }
82 if(config_params[i].var) {
83 TRACE(ft_t_info, "%s=%d", str, param);
84 *config_params[i].var = param;
85 }
86 goto out;
87 }
88 }
89 }
90 if (str) {
91 TRACE(ft_t_err, "unknown ftape option [%s]", str);
92
93 TRACE(ft_t_err, "allowed options are:");
94 for (i=0; i < NR_ITEMS(config_params); i++) {
95 TRACE(ft_t_err, " %s",config_params[i].name);
96 }
97 } else {
98 TRACE(ft_t_err, "botched ftape option");
99 }
100 out:
101 TRACE_EXIT 1;
102}
103
104__setup("ftape=", ftape_setup);
diff --git a/drivers/char/ftape/lowlevel/ftape-tracing.c b/drivers/char/ftape/lowlevel/ftape-tracing.c
deleted file mode 100644
index 7fdc6567440b..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-tracing.c
+++ /dev/null
@@ -1,118 +0,0 @@
1/*
2 * Copyright (C) 1993-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/ftape-tracing.c,v $
21 * $Revision: 1.2 $
22 * $Date: 1997/10/05 19:18:27 $
23 *
24 * This file contains the reading code
25 * for the QIC-117 floppy-tape driver for Linux.
26 */
27
28#include <linux/ftape.h>
29#include "../lowlevel/ftape-tracing.h"
30
31/* Global vars.
32 */
33/* tracing
34 * set it to: to log :
35 * 0 bugs
36 * 1 + errors
37 * 2 + warnings
38 * 3 + information
39 * 4 + more information
40 * 5 + program flow
41 * 6 + fdc/dma info
42 * 7 + data flow
43 * 8 + everything else
44 */
45ft_trace_t ftape_tracing = ft_t_info; /* Default level: information and up */
46int ftape_function_nest_level;
47
48/* Local vars.
49 */
50static __u8 trace_id;
51static char spacing[] = "* ";
52
53void ftape_trace_call(const char *file, const char *name)
54{
55 char *indent;
56
57 /* Since printk seems not to work with "%*s" format
58 * we'll use this work-around.
59 */
60 if (ftape_function_nest_level < 0) {
61 printk(KERN_INFO "function nest level (%d) < 0\n",
62 ftape_function_nest_level);
63 ftape_function_nest_level = 0;
64 }
65 if (ftape_function_nest_level < sizeof(spacing)) {
66 indent = (spacing +
67 sizeof(spacing) - 1 -
68 ftape_function_nest_level);
69 } else {
70 indent = spacing;
71 }
72 printk(KERN_INFO "[%03d]%s+%s (%s)\n",
73 (int) trace_id++, indent, file, name);
74}
75
76void ftape_trace_exit(const char *file, const char *name)
77{
78 char *indent;
79
80 /* Since printk seems not to work with "%*s" format
81 * we'll use this work-around.
82 */
83 if (ftape_function_nest_level < 0) {
84 printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level);
85 ftape_function_nest_level = 0;
86 }
87 if (ftape_function_nest_level < sizeof(spacing)) {
88 indent = (spacing +
89 sizeof(spacing) - 1 -
90 ftape_function_nest_level);
91 } else {
92 indent = spacing;
93 }
94 printk(KERN_INFO "[%03d]%s-%s (%s)\n",
95 (int) trace_id++, indent, file, name);
96}
97
98void ftape_trace_log(const char *file, const char *function)
99{
100 char *indent;
101
102 /* Since printk seems not to work with "%*s" format
103 * we'll use this work-around.
104 */
105 if (ftape_function_nest_level < 0) {
106 printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level);
107 ftape_function_nest_level = 0;
108 }
109 if (ftape_function_nest_level < sizeof(spacing)) {
110 indent = (spacing +
111 sizeof(spacing) - 1 -
112 ftape_function_nest_level);
113 } else {
114 indent = spacing;
115 }
116 printk(KERN_INFO "[%03d]%s%s (%s) - ",
117 (int) trace_id++, indent, file, function);
118}
diff --git a/drivers/char/ftape/lowlevel/ftape-tracing.h b/drivers/char/ftape/lowlevel/ftape-tracing.h
deleted file mode 100644
index 2950810c7085..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-tracing.h
+++ /dev/null
@@ -1,179 +0,0 @@
1#ifndef _FTAPE_TRACING_H
2#define _FTAPE_TRACING_H
3
4/*
5 * Copyright (C) 1994-1996 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-tracing.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:18:28 $
26 *
27 * This file contains definitions that eases the debugging of the
28 * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
29 */
30
31#include <linux/kernel.h>
32
33/*
34 * Be very careful with TRACE_EXIT and TRACE_ABORT.
35 *
36 * if (something) TRACE_EXIT error;
37 *
38 * will NOT work. Use
39 *
40 * if (something) {
41 * TRACE_EXIT error;
42 * }
43 *
44 * instead. Maybe a bit dangerous, but save lots of lines of code.
45 */
46
47#define LL_X "%d/%d KB"
48#define LL(x) (unsigned int)((__u64)(x)>>10), (unsigned int)((x)&1023)
49
50typedef enum {
51 ft_t_nil = -1,
52 ft_t_bug,
53 ft_t_err,
54 ft_t_warn,
55 ft_t_info,
56 ft_t_noise,
57 ft_t_flow,
58 ft_t_fdc_dma,
59 ft_t_data_flow,
60 ft_t_any
61} ft_trace_t;
62
63#ifdef CONFIG_FT_NO_TRACE_AT_ALL
64/* the compiler will optimize away most TRACE() macros
65 */
66#define FT_TRACE_TOP_LEVEL ft_t_bug
67#define TRACE_FUN(level) do {} while(0)
68#define TRACE_EXIT return
69#define TRACE(l, m, i...) \
70{ \
71 if ((ft_trace_t)(l) == FT_TRACE_TOP_LEVEL) { \
72 printk(KERN_INFO"ftape%s(%s):\n" \
73 KERN_INFO m".\n" ,__FILE__, __FUNCTION__ , ##i); \
74 } \
75}
76#define SET_TRACE_LEVEL(l) if ((l) == (l)) do {} while(0)
77#define TRACE_LEVEL FT_TRACE_TOP_LEVEL
78
79#else
80
81#ifdef CONFIG_FT_NO_TRACE
82/* the compiler will optimize away many TRACE() macros
83 * the ftape_simple_trace_call() function simply increments
84 * the function nest level.
85 */
86#define FT_TRACE_TOP_LEVEL ft_t_warn
87#define TRACE_FUN(level) ftape_function_nest_level++
88#define TRACE_EXIT ftape_function_nest_level--; return
89
90#else
91#ifdef CONFIG_FT_FULL_DEBUG
92#define FT_TRACE_TOP_LEVEL ft_t_any
93#else
94#define FT_TRACE_TOP_LEVEL ft_t_flow
95#endif
96#define TRACE_FUN(level) \
97 const ft_trace_t _tracing = level; \
98 if (ftape_tracing >= (ft_trace_t)(level) && \
99 (ft_trace_t)(level) <= FT_TRACE_TOP_LEVEL) \
100 ftape_trace_call(__FILE__, __FUNCTION__); \
101 ftape_function_nest_level ++;
102
103#define TRACE_EXIT \
104 --ftape_function_nest_level; \
105 if (ftape_tracing >= (ft_trace_t)(_tracing) && \
106 (ft_trace_t)(_tracing) <= FT_TRACE_TOP_LEVEL) \
107 ftape_trace_exit(__FILE__, __FUNCTION__); \
108 return
109
110#endif
111
112#define TRACE(l, m, i...) \
113{ \
114 if (ftape_tracing >= (ft_trace_t)(l) && \
115 (ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \
116 ftape_trace_log(__FILE__, __FUNCTION__); \
117 printk(m".\n" ,##i); \
118 } \
119}
120
121#define SET_TRACE_LEVEL(l) \
122{ \
123 if ((ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \
124 ftape_tracing = (ft_trace_t)(l); \
125 } else { \
126 ftape_tracing = FT_TRACE_TOP_LEVEL; \
127 } \
128}
129#define TRACE_LEVEL \
130((ftape_tracing <= FT_TRACE_TOP_LEVEL) ? ftape_tracing : FT_TRACE_TOP_LEVEL)
131
132
133/* Global variables declared in tracing.c
134 */
135extern ft_trace_t ftape_tracing; /* sets default level */
136extern int ftape_function_nest_level;
137
138/* Global functions declared in tracing.c
139 */
140extern void ftape_trace_call(const char *file, const char *name);
141extern void ftape_trace_exit(const char *file, const char *name);
142extern void ftape_trace_log (const char *file, const char *name);
143
144#endif /* !defined(CONFIG_FT_NO_TRACE_AT_ALL) */
145
146/*
147 * Abort with a message.
148 */
149#define TRACE_ABORT(res, i...) \
150{ \
151 TRACE(i); \
152 TRACE_EXIT res; \
153}
154
155/* The following transforms the common "if(result < 0) ... " into a
156 * one-liner.
157 */
158#define _TRACE_CATCH(level, fun, action) \
159{ \
160 int _res = (fun); \
161 if (_res < 0) { \
162 do { action /* */ ; } while(0); \
163 TRACE_ABORT(_res, level, "%s failed: %d", #fun, _res); \
164 } \
165}
166
167#define TRACE_CATCH(fun, fail) _TRACE_CATCH(ft_t_err, fun, fail)
168
169/* Abort the current function when signalled. This doesn't belong here,
170 * but rather into ftape-rw.h (maybe)
171 */
172#define FT_SIGNAL_EXIT(sig_mask) \
173 if (sigtestsetmask(&current->pending.signal, sig_mask)) { \
174 TRACE_ABORT(-EINTR, \
175 ft_t_warn, \
176 "interrupted by non-blockable signal"); \
177 }
178
179#endif /* _FTAPE_TRACING_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-write.c b/drivers/char/ftape/lowlevel/ftape-write.c
deleted file mode 100644
index 45601ec801ee..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-write.c
+++ /dev/null
@@ -1,336 +0,0 @@
1/*
2 * Copyright (C) 1993-1995 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/ftape-write.c,v $
21 * $Revision: 1.3.4.1 $
22 * $Date: 1997/11/14 18:07:04 $
23 *
24 * This file contains the writing code
25 * for the QIC-117 floppy-tape driver for Linux.
26 */
27
28#include <linux/string.h>
29#include <linux/errno.h>
30#include <linux/mm.h>
31
32#include <linux/ftape.h>
33#include <linux/qic117.h>
34#include "../lowlevel/ftape-tracing.h"
35#include "../lowlevel/ftape-write.h"
36#include "../lowlevel/ftape-read.h"
37#include "../lowlevel/ftape-io.h"
38#include "../lowlevel/ftape-ctl.h"
39#include "../lowlevel/ftape-rw.h"
40#include "../lowlevel/ftape-ecc.h"
41#include "../lowlevel/ftape-bsm.h"
42#include "../lowlevel/fdc-isr.h"
43
44/* Global vars.
45 */
46
47/* Local vars.
48 */
49static int last_write_failed;
50
51void ftape_zap_write_buffers(void)
52{
53 int i;
54
55 for (i = 0; i < ft_nr_buffers; ++i) {
56 ft_buffer[i]->status = done;
57 }
58 ftape_reset_buffer();
59}
60
61static int copy_and_gen_ecc(void *destination,
62 const void *source,
63 const SectorMap bad_sector_map)
64{
65 int result;
66 struct memory_segment mseg;
67 int bads = count_ones(bad_sector_map);
68 TRACE_FUN(ft_t_any);
69
70 if (bads > 0) {
71 TRACE(ft_t_noise, "bad sectors in map: %d", bads);
72 }
73 if (bads + 3 >= FT_SECTORS_PER_SEGMENT) {
74 TRACE(ft_t_noise, "empty segment");
75 mseg.blocks = 0; /* skip entire segment */
76 result = 0; /* nothing written */
77 } else {
78 mseg.blocks = FT_SECTORS_PER_SEGMENT - bads;
79 mseg.data = destination;
80 memcpy(mseg.data, source, (mseg.blocks - 3) * FT_SECTOR_SIZE);
81 result = ftape_ecc_set_segment_parity(&mseg);
82 if (result < 0) {
83 TRACE(ft_t_err, "ecc_set_segment_parity failed");
84 } else {
85 result = (mseg.blocks - 3) * FT_SECTOR_SIZE;
86 }
87 }
88 TRACE_EXIT result;
89}
90
91
92int ftape_start_writing(const ft_write_mode_t mode)
93{
94 buffer_struct *head = ftape_get_buffer(ft_queue_head);
95 int segment_id = head->segment_id;
96 int result;
97 buffer_state_enum wanted_state = (mode == FT_WR_DELETE
98 ? deleting
99 : writing);
100 TRACE_FUN(ft_t_flow);
101
102 if ((ft_driver_state != wanted_state) || head->status != waiting) {
103 TRACE_EXIT 0;
104 }
105 ftape_setup_new_segment(head, segment_id, 1);
106 if (mode == FT_WR_SINGLE) {
107 /* stop tape instead of pause */
108 head->next_segment = 0;
109 }
110 ftape_calc_next_cluster(head); /* prepare */
111 head->status = ft_driver_state; /* either writing or deleting */
112 if (ft_runner_status == idle) {
113 TRACE(ft_t_noise,
114 "starting runner for segment %d", segment_id);
115 TRACE_CATCH(ftape_start_tape(segment_id,head->sector_offset),);
116 } else {
117 TRACE(ft_t_noise, "runner not idle, not starting tape");
118 }
119 /* go */
120 result = fdc_setup_read_write(head, (mode == FT_WR_DELETE
121 ? FDC_WRITE_DELETED : FDC_WRITE));
122 ftape_set_state(wanted_state); /* should not be necessary */
123 TRACE_EXIT result;
124}
125
126/* Wait until all data is actually written to tape.
127 *
128 * There is a problem: when the tape runs into logical EOT, then this
129 * failes. We need to restart the runner in this case.
130 */
131int ftape_loop_until_writes_done(void)
132{
133 buffer_struct *head;
134 TRACE_FUN(ft_t_flow);
135
136 while ((ft_driver_state == writing || ft_driver_state == deleting) &&
137 ftape_get_buffer(ft_queue_head)->status != done) {
138 /* set the runner status to idle if at lEOT */
139 TRACE_CATCH(ftape_handle_logical_eot(), last_write_failed = 1);
140 /* restart the tape if necessary */
141 if (ft_runner_status == idle) {
142 TRACE(ft_t_noise, "runner is idle, restarting");
143 if (ft_driver_state == deleting) {
144 TRACE_CATCH(ftape_start_writing(FT_WR_DELETE),
145 last_write_failed = 1);
146 } else {
147 TRACE_CATCH(ftape_start_writing(FT_WR_MULTI),
148 last_write_failed = 1);
149 }
150 }
151 TRACE(ft_t_noise, "tail: %d, head: %d",
152 ftape_buffer_id(ft_queue_tail),
153 ftape_buffer_id(ft_queue_head));
154 TRACE_CATCH(fdc_interrupt_wait(5 * FT_SECOND),
155 last_write_failed = 1);
156 head = ftape_get_buffer(ft_queue_head);
157 if (head->status == error) {
158 /* Allow escape from loop when signaled !
159 */
160 FT_SIGNAL_EXIT(_DONT_BLOCK);
161 if (head->hard_error_map != 0) {
162 /* Implement hard write error recovery here
163 */
164 }
165 /* retry this one */
166 head->status = waiting;
167 if (ft_runner_status == aborting) {
168 ftape_dumb_stop();
169 }
170 if (ft_runner_status != idle) {
171 TRACE_ABORT(-EIO, ft_t_err,
172 "unexpected state: "
173 "ft_runner_status != idle");
174 }
175 ftape_start_writing(ft_driver_state == deleting
176 ? FT_WR_MULTI : FT_WR_DELETE);
177 }
178 TRACE(ft_t_noise, "looping until writes done");
179 }
180 ftape_set_state(idle);
181 TRACE_EXIT 0;
182}
183
184/* Write given segment from buffer at address to tape.
185 */
186static int write_segment(const int segment_id,
187 const void *address,
188 const ft_write_mode_t write_mode)
189{
190 int bytes_written = 0;
191 buffer_struct *tail;
192 buffer_state_enum wanted_state = (write_mode == FT_WR_DELETE
193 ? deleting : writing);
194 TRACE_FUN(ft_t_flow);
195
196 TRACE(ft_t_noise, "segment_id = %d", segment_id);
197 if (ft_driver_state != wanted_state) {
198 if (ft_driver_state == deleting ||
199 wanted_state == deleting) {
200 TRACE_CATCH(ftape_loop_until_writes_done(),);
201 }
202 TRACE(ft_t_noise, "calling ftape_abort_operation");
203 TRACE_CATCH(ftape_abort_operation(),);
204 ftape_zap_write_buffers();
205 ftape_set_state(wanted_state);
206 }
207 /* if all buffers full we'll have to wait...
208 */
209 ftape_wait_segment(wanted_state);
210 tail = ftape_get_buffer(ft_queue_tail);
211 switch(tail->status) {
212 case done:
213 ft_history.defects += count_ones(tail->hard_error_map);
214 break;
215 case waiting:
216 /* this could happen with multiple EMPTY_SEGMENTs, but
217 * shouldn't happen any more as we re-start the runner even
218 * with an empty segment.
219 */
220 bytes_written = -EAGAIN;
221 break;
222 case error:
223 /* setup for a retry
224 */
225 tail->status = waiting;
226 bytes_written = -EAGAIN; /* force retry */
227 if (tail->hard_error_map != 0) {
228 TRACE(ft_t_warn,
229 "warning: %d hard error(s) in written segment",
230 count_ones(tail->hard_error_map));
231 TRACE(ft_t_noise, "hard_error_map = 0x%08lx",
232 (long)tail->hard_error_map);
233 /* Implement hard write error recovery here
234 */
235 }
236 break;
237 default:
238 TRACE_ABORT(-EIO, ft_t_err,
239 "wait for empty segment failed, tail status: %d",
240 tail->status);
241 }
242 /* should runner stop ?
243 */
244 if (ft_runner_status == aborting) {
245 buffer_struct *head = ftape_get_buffer(ft_queue_head);
246 if (head->status == wanted_state) {
247 head->status = done; /* ???? */
248 }
249 /* don't call abort_operation(), we don't want to zap
250 * the dma buffers
251 */
252 TRACE_CATCH(ftape_dumb_stop(),);
253 } else {
254 /* If just passed last segment on tape: wait for BOT
255 * or EOT mark. Sets ft_runner_status to idle if at lEOT
256 * and successful
257 */
258 TRACE_CATCH(ftape_handle_logical_eot(),);
259 }
260 if (tail->status == done) {
261 /* now at least one buffer is empty, fill it with our
262 * data. skip bad sectors and generate ecc.
263 * copy_and_gen_ecc return nr of bytes written, range
264 * 0..29 Kb inclusive!
265 *
266 * Empty segments are handled inside coyp_and_gen_ecc()
267 */
268 if (write_mode != FT_WR_DELETE) {
269 TRACE_CATCH(bytes_written = copy_and_gen_ecc(
270 tail->address, address,
271 ftape_get_bad_sector_entry(segment_id)),);
272 }
273 tail->segment_id = segment_id;
274 tail->status = waiting;
275 tail = ftape_next_buffer(ft_queue_tail);
276 }
277 /* Start tape only if all buffers full or flush mode.
278 * This will give higher probability of streaming.
279 */
280 if (ft_runner_status != running &&
281 ((tail->status == waiting &&
282 ftape_get_buffer(ft_queue_head) == tail) ||
283 write_mode != FT_WR_ASYNC)) {
284 TRACE_CATCH(ftape_start_writing(write_mode),);
285 }
286 TRACE_EXIT bytes_written;
287}
288
289/* Write as much as fits from buffer to the given segment on tape
290 * and handle retries.
291 * Return the number of bytes written (>= 0), or:
292 * -EIO write failed
293 * -EINTR interrupted by signal
294 * -ENOSPC device full
295 */
296int ftape_write_segment(const int segment_id,
297 const void *buffer,
298 const ft_write_mode_t flush)
299{
300 int retry = 0;
301 int result;
302 TRACE_FUN(ft_t_flow);
303
304 ft_history.used |= 2;
305 if (segment_id >= ft_tracks_per_tape*ft_segments_per_track) {
306 /* tape full */
307 TRACE_ABORT(-ENOSPC, ft_t_err,
308 "invalid segment id: %d (max %d)",
309 segment_id,
310 ft_tracks_per_tape * ft_segments_per_track -1);
311 }
312 for (;;) {
313 if ((result = write_segment(segment_id, buffer, flush)) >= 0) {
314 if (result == 0) { /* empty segment */
315 TRACE(ft_t_noise,
316 "empty segment, nothing written");
317 }
318 TRACE_EXIT result;
319 }
320 if (result == -EAGAIN) {
321 if (++retry > 100) { /* give up */
322 TRACE_ABORT(-EIO, ft_t_err,
323 "write failed, >100 retries in segment");
324 }
325 TRACE(ft_t_warn, "write error, retry %d (%d)",
326 retry,
327 ftape_get_buffer(ft_queue_tail)->segment_id);
328 } else {
329 TRACE_ABORT(result, ft_t_err,
330 "write_segment failed, error: %d", result);
331 }
332 /* Allow escape from loop when signaled !
333 */
334 FT_SIGNAL_EXIT(_DONT_BLOCK);
335 }
336}
diff --git a/drivers/char/ftape/lowlevel/ftape-write.h b/drivers/char/ftape/lowlevel/ftape-write.h
deleted file mode 100644
index 0e7f898b7af9..000000000000
--- a/drivers/char/ftape/lowlevel/ftape-write.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef _FTAPE_WRITE_H
2#define _FTAPE_WRITE_H
3
4/*
5 * Copyright (C) 1994-1995 Bas Laarhoven,
6 * (C) 1996-1997 Claus-Justus Heine.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.h,v $
24 $Author: claus $
25 *
26 $Revision: 1.2 $
27 $Date: 1997/10/05 19:18:30 $
28 $State: Exp $
29 *
30 * This file contains the definitions for the write functions
31 * for the QIC-117 floppy-tape driver for Linux.
32 *
33 */
34
35
36/* ftape-write.c defined global functions.
37 */
38typedef enum {
39 FT_WR_ASYNC = 0, /* start tape only when all buffers are full */
40 FT_WR_MULTI = 1, /* start tape, but don't necessarily stop */
41 FT_WR_SINGLE = 2, /* write a single segment and stop afterwards */
42 FT_WR_DELETE = 3 /* write deleted data marks */
43} ft_write_mode_t;
44
45extern int ftape_start_writing(const ft_write_mode_t mode);
46extern int ftape_write_segment(const int segment,
47 const void *address,
48 const ft_write_mode_t flushing);
49extern void ftape_zap_write_buffers(void);
50extern int ftape_loop_until_writes_done(void);
51
52#endif /* _FTAPE_WRITE_H */
53
diff --git a/drivers/char/ftape/lowlevel/ftape_syms.c b/drivers/char/ftape/lowlevel/ftape_syms.c
deleted file mode 100644
index 8e0dc4a07ca6..000000000000
--- a/drivers/char/ftape/lowlevel/ftape_syms.c
+++ /dev/null
@@ -1,87 +0,0 @@
1/*
2 * Copyright (C) 1996-1997 Claus-Justus Heine
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 *
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape_syms.c,v $
20 * $Revision: 1.4 $
21 * $Date: 1997/10/17 00:03:51 $
22 *
23 * This file contains the symbols that the ftape low level
24 * part of the QIC-40/80/3010/3020 floppy-tape driver "ftape"
25 * exports to its high level clients
26 */
27
28#include <linux/module.h>
29
30#include <linux/ftape.h>
31#include "../lowlevel/ftape-tracing.h"
32#include "../lowlevel/ftape-init.h"
33#include "../lowlevel/fdc-io.h"
34#include "../lowlevel/ftape-read.h"
35#include "../lowlevel/ftape-write.h"
36#include "../lowlevel/ftape-io.h"
37#include "../lowlevel/ftape-ctl.h"
38#include "../lowlevel/ftape-rw.h"
39#include "../lowlevel/ftape-bsm.h"
40#include "../lowlevel/ftape-buffer.h"
41#include "../lowlevel/ftape-format.h"
42
43/* bad sector handling from ftape-bsm.c */
44EXPORT_SYMBOL(ftape_get_bad_sector_entry);
45EXPORT_SYMBOL(ftape_find_end_of_bsm_list);
46/* from ftape-rw.c */
47EXPORT_SYMBOL(ftape_set_state);
48/* from ftape-ctl.c */
49EXPORT_SYMBOL(ftape_seek_to_bot);
50EXPORT_SYMBOL(ftape_seek_to_eot);
51EXPORT_SYMBOL(ftape_abort_operation);
52EXPORT_SYMBOL(ftape_get_status);
53EXPORT_SYMBOL(ftape_enable);
54EXPORT_SYMBOL(ftape_disable);
55EXPORT_SYMBOL(ftape_mmap);
56EXPORT_SYMBOL(ftape_calibrate_data_rate);
57/* from ftape-io.c */
58EXPORT_SYMBOL(ftape_reset_drive);
59EXPORT_SYMBOL(ftape_command);
60EXPORT_SYMBOL(ftape_parameter);
61EXPORT_SYMBOL(ftape_ready_wait);
62EXPORT_SYMBOL(ftape_report_operation);
63EXPORT_SYMBOL(ftape_report_error);
64/* from ftape-read.c */
65EXPORT_SYMBOL(ftape_read_segment_fraction);
66EXPORT_SYMBOL(ftape_zap_read_buffers);
67EXPORT_SYMBOL(ftape_read_header_segment);
68EXPORT_SYMBOL(ftape_decode_header_segment);
69/* from ftape-write.c */
70EXPORT_SYMBOL(ftape_write_segment);
71EXPORT_SYMBOL(ftape_start_writing);
72EXPORT_SYMBOL(ftape_loop_until_writes_done);
73/* from ftape-buffer.h */
74EXPORT_SYMBOL(ftape_set_nr_buffers);
75/* from ftape-format.h */
76EXPORT_SYMBOL(ftape_format_track);
77EXPORT_SYMBOL(ftape_format_status);
78EXPORT_SYMBOL(ftape_verify_segment);
79/* from tracing.c */
80#ifndef CONFIG_FT_NO_TRACE_AT_ALL
81EXPORT_SYMBOL(ftape_tracing);
82EXPORT_SYMBOL(ftape_function_nest_level);
83EXPORT_SYMBOL(ftape_trace_call);
84EXPORT_SYMBOL(ftape_trace_exit);
85EXPORT_SYMBOL(ftape_trace_log);
86#endif
87