aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ftape
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-12-03 22:22:41 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-03 22:22:41 -0500
commitd916faace3efc0bf19fe9a615a1ab8fa1a24cd93 (patch)
treee6adbc42541498306728490a4978afe116131299 /drivers/char/ftape
parent2b5f6dcce5bf94b9b119e9ed8d537098ec61c3d2 (diff)
Remove long-unmaintained ftape driver subsystem.
It's bitrotten, long unmaintained, long hidden under BROKEN_ON_SMP, etc. As scheduled in feature-removal-schedule.txt, and ack'd several times on lkml. Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/char/ftape')
-rw-r--r--drivers/char/ftape/Kconfig330
-rw-r--r--drivers/char/ftape/Makefile28
-rw-r--r--drivers/char/ftape/README.PCI81
-rw-r--r--drivers/char/ftape/RELEASE-NOTES966
-rw-r--r--drivers/char/ftape/compressor/Makefile31
-rw-r--r--drivers/char/ftape/compressor/lzrw3.c743
-rw-r--r--drivers/char/ftape/compressor/lzrw3.h253
-rw-r--r--drivers/char/ftape/compressor/zftape-compress.c1203
-rw-r--r--drivers/char/ftape/compressor/zftape-compress.h83
-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
-rw-r--r--drivers/char/ftape/zftape/Makefile36
-rw-r--r--drivers/char/ftape/zftape/zftape-buffers.c149
-rw-r--r--drivers/char/ftape/zftape/zftape-buffers.h55
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.c1417
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.h58
-rw-r--r--drivers/char/ftape/zftape/zftape-eof.c199
-rw-r--r--drivers/char/ftape/zftape/zftape-eof.h52
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c377
-rw-r--r--drivers/char/ftape/zftape/zftape-init.h77
-rw-r--r--drivers/char/ftape/zftape/zftape-read.c377
-rw-r--r--drivers/char/ftape/zftape/zftape-read.h53
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.c375
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.h101
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.c757
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.h227
-rw-r--r--drivers/char/ftape/zftape/zftape-write.c483
-rw-r--r--drivers/char/ftape/zftape/zftape-write.h38
-rw-r--r--drivers/char/ftape/zftape/zftape_syms.c43
62 files changed, 0 insertions, 19368 deletions
diff --git a/drivers/char/ftape/Kconfig b/drivers/char/ftape/Kconfig
deleted file mode 100644
index 0d65189a7ae8..000000000000
--- a/drivers/char/ftape/Kconfig
+++ /dev/null
@@ -1,330 +0,0 @@
1#
2# Ftape configuration
3#
4config ZFTAPE
5 tristate "Zftape, the VFS interface"
6 depends on FTAPE
7 ---help---
8 Normally, you want to say Y or M. DON'T say N here or you
9 WON'T BE ABLE TO USE YOUR FLOPPY TAPE DRIVE.
10
11 The ftape module itself no longer contains the routines necessary
12 to interface with the kernel VFS layer (i.e. to actually write data
13 to and read data from the tape drive). Instead the file system
14 interface (i.e. the hardware independent part of the driver) has
15 been moved to a separate module.
16
17 To compile this driver as a module, choose M here: the
18 module will be called zftape.
19
20 Regardless of whether you say Y or M here, an additional runtime
21 loadable module called `zft-compressor' which contains code to
22 support user transparent on-the-fly compression based on Ross
23 William's lzrw3 algorithm will be produced. If you have enabled the
24 kernel module loader (i.e. have said Y to "Kernel module loader
25 support", above) then `zft-compressor' will be loaded
26 automatically by zftape when needed.
27
28 Despite its name, zftape does NOT use compression by default.
29
30config ZFT_DFLT_BLK_SZ
31 int "Default block size"
32 depends on ZFTAPE
33 default "10240"
34 ---help---
35 If unsure leave this at its default value, i.e. 10240. Note that
36 you specify only the default block size here. The block size can be
37 changed at run time using the MTSETBLK tape operation with the
38 MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the
39 shell command line).
40
41 The probably most striking difference between zftape and previous
42 versions of ftape is the fact that all data must be written or read
43 in multiples of a fixed block size. The block size defaults to
44 10240 which is what GNU tar uses. The values for the block size
45 should be either 1 or multiples of 1024 up to a maximum value of
46 63488 (i.e. 62 K). If you specify `1' then zftape's builtin
47 compression will be disabled.
48
49 Reasonable values are `10240' (GNU tar's default block size),
50 `5120' (afio's default block size), `32768' (default block size some
51 backup programs assume for SCSI tape drives) or `1' (no restriction
52 on block size, but disables builtin compression).
53
54comment "The compressor will be built as a module only!"
55 depends on FTAPE && ZFTAPE
56
57config ZFT_COMPRESSOR
58 tristate
59 depends on FTAPE!=n && ZFTAPE!=n
60 default m
61
62config FT_NR_BUFFERS
63 int "Number of ftape buffers (EXPERIMENTAL)"
64 depends on FTAPE && EXPERIMENTAL
65 default "3"
66 help
67 Please leave this at `3' unless you REALLY know what you are doing.
68 It is not necessary to change this value. Values below 3 make the
69 proper use of ftape impossible, values greater than 3 are a waste of
70 memory. You can change the amount of DMA memory used by ftape at
71 runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer
72 wastes 32 KB of memory. Please note that this memory cannot be
73 swapped out.
74
75config FT_PROC_FS
76 bool "Enable procfs status report (+2kb)"
77 depends on FTAPE && PROC_FS
78 ---help---
79 Optional. Saying Y will result in creation of a directory
80 `/proc/ftape' under the /proc file system. The files can be viewed
81 with your favorite pager (i.e. use "more /proc/ftape/history" or
82 "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The
83 file will contain some status information about the inserted
84 cartridge, the kernel driver, your tape drive, the floppy disk
85 controller and the error history for the most recent use of the
86 kernel driver. Saying Y will enlarge the size of the ftape driver
87 by approximately 2 KB.
88
89 WARNING: When compiling ftape as a module (i.e. saying M to "Floppy
90 tape drive") it is dangerous to use ftape's /proc file system
91 interface. Accessing `/proc/ftape' while the module is unloaded will
92 result in a kernel Oops. This cannot be fixed from inside ftape.
93
94choice
95 prompt "Debugging output"
96 depends on FTAPE
97 default FT_NORMAL_DEBUG
98
99config FT_NORMAL_DEBUG
100 bool "Normal"
101 ---help---
102 This option controls the amount of debugging output the ftape driver
103 is ABLE to produce; it does not increase or diminish the debugging
104 level itself. If unsure, leave this at its default setting,
105 i.e. choose "Normal".
106
107 Ftape can print lots of debugging messages to the system console
108 resp. kernel log files. Reducing the amount of possible debugging
109 output reduces the size of the kernel module by some KB, so it might
110 be a good idea to use "None" for emergency boot floppies.
111
112 If you want to save memory then the following strategy is
113 recommended: leave this option at its default setting "Normal" until
114 you know that the driver works as expected, afterwards reconfigure
115 the kernel, this time specifying "Reduced" or "None" and recompile
116 and install the kernel as usual. Note that choosing "Excessive"
117 debugging output does not increase the amount of debugging output
118 printed to the console but only makes it possible to produce
119 "Excessive" debugging output.
120
121 Please read <file:Documentation/ftape.txt> for a short description
122 how to control the amount of debugging output.
123
124config FT_FULL_DEBUG
125 bool "Excessive"
126 help
127 Extremely verbose output for driver debugging purposes.
128
129config FT_NO_TRACE
130 bool "Reduced"
131 help
132 Reduced tape driver debugging output.
133
134config FT_NO_TRACE_AT_ALL
135 bool "None"
136 help
137 Suppress all debugging output from the tape drive.
138
139endchoice
140
141comment "Hardware configuration"
142 depends on FTAPE
143
144choice
145 prompt "Floppy tape controllers"
146 depends on FTAPE
147 default FT_STD_FDC
148
149config FT_STD_FDC
150 bool "Standard"
151 ---help---
152 Only change this setting if you have a special controller. If you
153 didn't plug any add-on card into your computer system but just
154 plugged the floppy tape cable into the already existing floppy drive
155 controller then you don't want to change the default setting,
156 i.e. choose "Standard".
157
158 Choose "MACH-2" if you have a Mountain Mach-2 controller.
159 Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20
160 controller.
161 Choose "Alt/82078" if you have another controller that is located at
162 an IO base address different from the standard floppy drive
163 controller's base address of `0x3f0', or uses an IRQ (interrupt)
164 channel different from `6', or a DMA channel different from
165 `2'. This is necessary for any controller card that is based on
166 Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high
167 speed" controllers.
168
169 If you choose something other than "Standard" then please make
170 sure that the settings for the IO base address and the IRQ and DMA
171 channel in the configuration menus below are correct. Use the manual
172 of your tape drive to determine the correct settings!
173
174 If you are already successfully using your tape drive with another
175 operating system then you definitely should use the same settings
176 for the IO base, the IRQ and DMA channel that have proven to work
177 with that other OS.
178
179 Note that this menu lets you specify only the default setting for
180 the hardware setup. The hardware configuration can be changed at
181 boot time (when ftape is compiled into the kernel, i.e. if you
182 have said Y to "Floppy tape drive") or module load time (i.e. if you
183 have said M to "Floppy tape drive").
184
185 Please read also the file <file:Documentation/ftape.txt> which
186 contains a short description of the parameters that can be set at
187 boot or load time. If you want to use your floppy tape drive on a
188 PCI-bus based system, please read the file
189 <file:drivers/char/ftape/README.PCI>.
190
191config FT_MACH2
192 bool "MACH-2"
193
194config FT_PROBE_FC10
195 bool "FC-10/FC-20"
196
197config FT_ALT_FDC
198 bool "Alt/82078"
199
200endchoice
201
202comment "Consult the manuals of your tape drive for the correct settings!"
203 depends on FTAPE && !FT_STD_FDC
204
205config FT_FDC_BASE
206 hex "IO base of the floppy disk controller"
207 depends on FTAPE && !FT_STD_FDC
208 default "0"
209 ---help---
210 You don't need to specify a value if the following default
211 settings for the base IO address are correct:
212 <<< MACH-2 : 0x1E0 >>>
213 <<< FC-10/FC-20: 0x180 >>>
214 <<< Secondary : 0x370 >>>
215 Secondary refers to a secondary FDC controller like the "high speed"
216 controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
217 Please make sure that the setting for the IO base address
218 specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
219 CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
220 successfully using the tape drive with another operating system then
221 you definitely should use the same settings for the IO base that has
222 proven to work with that other OS.
223
224 Note that this menu lets you specify only the default setting for
225 the IO base. The hardware configuration can be changed at boot time
226 (when ftape is compiled into the kernel, i.e. if you specified Y to
227 "Floppy tape drive") or module load time (i.e. if you have said M to
228 "Floppy tape drive").
229
230 Please read also the file <file:Documentation/ftape.txt> which
231 contains a short description of the parameters that can be set at
232 boot or load time.
233
234config FT_FDC_IRQ
235 int "IRQ channel of the floppy disk controller"
236 depends on FTAPE && !FT_STD_FDC
237 default "0"
238 ---help---
239 You don't need to specify a value if the following default
240 settings for the interrupt channel are correct:
241 <<< MACH-2 : 6 >>>
242 <<< FC-10/FC-20: 9 >>>
243 <<< Secondary : 6 >>>
244 Secondary refers to secondary a FDC controller like the "high speed"
245 controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
246 Please make sure that the setting for the IO base address
247 specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
248 CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
249 successfully using the tape drive with another operating system then
250 you definitely should use the same settings for the IO base that has
251 proven to work with that other OS.
252
253 Note that this menu lets you specify only the default setting for
254 the IRQ channel. The hardware configuration can be changed at boot
255 time (when ftape is compiled into the kernel, i.e. if you said Y to
256 "Floppy tape drive") or module load time (i.e. if you said M to
257 "Floppy tape drive").
258
259 Please read also the file <file:Documentation/ftape.txt> which
260 contains a short description of the parameters that can be set at
261 boot or load time.
262
263config FT_FDC_DMA
264 int "DMA channel of the floppy disk controller"
265 depends on FTAPE && !FT_STD_FDC
266 default "0"
267 ---help---
268 You don't need to specify a value if the following default
269 settings for the DMA channel are correct:
270 <<< MACH-2 : 2 >>>
271 <<< FC-10/FC-20: 3 >>>
272 <<< Secondary : 2 >>>
273 Secondary refers to a secondary FDC controller like the "high speed"
274 controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
275 Please make sure that the setting for the IO base address
276 specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
277 CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
278 successfully using the tape drive with another operating system then
279 you definitely should use the same settings for the IO base that has
280 proven to work with that other OS.
281
282 Note that this menu lets you specify only the default setting for
283 the DMA channel. The hardware configuration can be changed at boot
284 time (when ftape is compiled into the kernel, i.e. if you said Y to
285 "Floppy tape drive") or module load time (i.e. if you said M to
286 "Floppy tape drive").
287
288 Please read also the file <file:Documentation/ftape.txt> which
289 contains a short description of the parameters that can be set at
290 boot or load time.
291
292config FT_FDC_THR
293 int "Default FIFO threshold (EXPERIMENTAL)"
294 depends on FTAPE && EXPERIMENTAL
295 default "8"
296 help
297 Set the FIFO threshold of the FDC. If this is higher the DMA
298 controller may serve the FDC after a higher latency time. If this is
299 lower, fewer DMA transfers occur leading to less bus contention.
300 You may try to tune this if ftape annoys you with "reduced data
301 rate because of excessive overrun errors" messages. However, this
302 doesn't seem to have too much effect.
303
304 If unsure, don't touch the initial value, i.e. leave it at "8".
305
306config FT_FDC_MAX_RATE
307 int "Maximal data rate to use (EXPERIMENTAL)"
308 depends on FTAPE && EXPERIMENTAL
309 default "2000"
310 ---help---
311 With some motherboard/FDC combinations ftape will not be able to
312 run your FDC/tape drive combination at the highest available
313 speed. If this is the case you'll encounter "reduced data rate
314 because of excessive overrun errors" messages and lots of retries
315 before ftape finally decides to reduce the data rate.
316
317 In this case it might be desirable to tell ftape beforehand that
318 it need not try to run the tape drive at the highest available
319 speed. If unsure, leave this disabled, i.e. leave it at 2000
320 bits/sec.
321
322config FT_ALPHA_CLOCK
323 int "CPU clock frequency of your DEC Alpha" if ALPHA
324 depends on FTAPE
325 default "0"
326 help
327 On some DEC Alpha machines the CPU clock frequency cannot be
328 determined automatically, so you need to specify it here ONLY if
329 running a DEC Alpha, otherwise this setting has no effect.
330
diff --git a/drivers/char/ftape/Makefile b/drivers/char/ftape/Makefile
deleted file mode 100644
index 0e67d2f8b7ec..000000000000
--- a/drivers/char/ftape/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
1#
2# Copyright (C) 1997 Claus 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/Makefile,v $
19# $Revision: 1.4 $
20# $Date: 1997/10/05 19:17:56 $
21#
22# Makefile for the QIC-40/80/3010/3020 floppy-tape driver for
23# Linux.
24#
25
26obj-$(CONFIG_FTAPE) += lowlevel/
27obj-$(CONFIG_ZFTAPE) += zftape/
28obj-$(CONFIG_ZFT_COMPRESSOR) += compressor/
diff --git a/drivers/char/ftape/README.PCI b/drivers/char/ftape/README.PCI
deleted file mode 100644
index 18de159d36e0..000000000000
--- a/drivers/char/ftape/README.PCI
+++ /dev/null
@@ -1,81 +0,0 @@
1Some notes for ftape users with PCI motherboards:
2=================================================
3
4The problem:
5------------
6
7There have been some problem reports from people using PCI-bus based
8systems getting overrun errors.
9I wasn't able to reproduce these until I ran ftape on a Intel Plato
10(Premiere PCI II) motherboard with bios version 1.00.08AX1.
11It turned out that if GAT (Guaranteed Access Timing) is enabled (?)
12ftape gets a lot of overrun errors.
13The problem disappears when disabling GAT in the bios.
14Note that Intel removed this setting (permanently disabled) from the
151.00.10AX1 bios !
16
17It looks like that if GAT is enabled there are often large periods
18(greater than 120 us !??) on the ISA bus that the DMA controller cannot
19service the floppy disk controller.
20I cannot imagine this being acceptable in a decent PCI implementation.
21Maybe this is a `feature' of the chipset. I can only speculate why
22Intel choose to remove the option from the latest Bios...
23
24The lesson of this all is that there may be other motherboard
25implementations having the same of similar problems.
26If you experience a lot of overrun errors during a backup to tape,
27see if there is some setting in the Bios that may influence the
28bus timing.
29
30I judge this a hardware problem and not a limitation of ftape ;-)
31My DOS backup software seems to be suffering from the same problems
32and even refuses to run at 1 Mbps !
33Ftape will reduce the data-rate from 1 Mbps to 500 Kbps if the number
34of overrun errors on a track exceeds a threshold.
35
36
37Possible solutions:
38-------------------
39
40Some of the problems were solved by upgrading the (flash) bios.
41Other suggest that it has to do with the FDC being on the PCI
42bus, but that is not the case with the Intel Premiere II boards.
43[If upgrading the bios doesn't solve the problem you could try
44a floppy disk controller on the isa-bus].
45
46Here is a list of systems and recommended BIOS settings:
47
48
49 Intel Premiere PCI (Revenge):
50
51Bios version 1.00.09.AF2 is reported to work.
52
53
54
55 Intel Premiere PCI II (Plato):
56
57Bios version 1.00.10.AX1 and version 11 beta are ok.
58If using version 1.00.08.AX1, GAT must be disabled !
59
60
61
62 ASUS PCI/I-SP3G:
63
64Preferred settings: ISA-GAT-mode : disabled
65 DMA-linebuffer-mode : standard
66 ISA-masterbuffer-mode : standard
67
68
69 DELL Dimension XPS P90
70
71Bios version A2 is reported to be broken, while bios version A5 works.
72You can get a flash bios upgrade from http://www.dell.com
73
74
75To see if you're having the GAT problem, try making a backup
76under DOS. If it's very slow and often repositions you're
77probably having this problem.
78
79 --//--
80 LocalWords: ftape PCI bios GAT ISA DMA chipset Mbps Kbps FDC isa AF ok ASUS
81 LocalWords: SP linebuffer masterbuffer XPS http www com
diff --git a/drivers/char/ftape/RELEASE-NOTES b/drivers/char/ftape/RELEASE-NOTES
deleted file mode 100644
index 03799dbc05a4..000000000000
--- a/drivers/char/ftape/RELEASE-NOTES
+++ /dev/null
@@ -1,966 +0,0 @@
1Hey, Emacs, we're -*-Text-*- mode!
2
3===== Release notes for ftape-3.04d 25/11/97 =====
4- The correct pre-processor statement for "else if" is "#elif" not
5 "elsif".
6- Need to call zft_reset_position() when overwriting cartridges
7 previously written with ftape-2.x, sftape, or ancient
8 (pre-ftape-3.x) versions of zftape.
9
10===== Release notes for ftape-3.04c 16/11/97 =====
11- fdc_probe() was calling DUMPREGS with a result length of "1" which
12 was just fine. Undo previous change.
13
14===== Release notes for ftape-3.04b 14/11/97 =====
15
16- patches/2.x.x/floppy.c.diff was somewhat broken, releasing i/o
17 regions it never had allocated.
18- fdc_probe() was calling DUMPREGS with a result length of "1" instead
19 of "10"
20- Writing deleted data marks if the first segents on track zero are
21 should work now.
22- ftformat should now be able to handle those cases where the tape
23 drive sets the read only status bit (QIC-40/80 cartridges with
24 QIC-3010/3020 tape drives) because the header segment is damaged.
25- the MTIOCFTCMD ioctl may now be issued by the superuser ONLY.
26
27===== Release notes for ftape-3.04a 12/11/97 =====
28- Fix an "infinite loop can't be killed by signal" bug in
29 ftape_get_drive_status(). Only relevant when trying to access
30 buggy/misconfigured hardware
31- Try to compensate a bug in the HP Colorado T3000's firmware: it
32 doesn't set the write protect bit for QIC80/QIC40 cartridges.
33
34===== Release notes for ftape-3.04 06/11/97 =====
35- If positioning with fast seeking fails fall back to a slow seek
36 before giving up.
37- (nearly) no retries on "no data errors" when verifying after
38 formatting. Improved tuning of the bad sector map after formatting.
39- the directory layout has changed again to allow for easier kernel
40 integration
41- Module parameter "ftape_tracing" now is called "ft_tracing" because
42 the "ftape_tracing" variable has the version checksum attached to it.
43- `/proc/ftape' interface for 2.0.* kernels. `/proc/ftape' no longer
44 is a directory but a file that contains all the information formerly
45 provided in separate files under the `/proc/ftape/' directory.
46- Most of the configuration options have been prefixed by "CONFIG_FT_"
47 in preparation of the kernel inclusion. The Makefiles under
48 "./ftape/" should be directly usable by the kernel.
49- The MODVERSIONS stuff is now auto-detected.
50- Broke backslashed multi line options in MCONFIG into separate lines
51 using GNU-make's "+=" feature.
52- The html and dvi version of the manual is now installed under
53 '/usr/doc/ftape` with 'make install`
54- New SMP define in MCONFIG. ftape works with SMP if this is defined.
55- attempt to cope with "excessive overrun errors" by gradually
56 increasing FDC FIFO threshold. But this doesn't seem to have too
57 much an effect.
58- New load time configuration parameter "ft_fdc_rate_limit". If you
59 encounter too many overrun errors with a 2Mb controller then you
60 might want to set this to 1000.
61- overrun errors on the last sector in a segment sometimes result in
62 a zero DMA residue. Dunno why, but compensate for it.
63- there were still fdc_read() timeout errors. I think I have fixed it
64 now, please FIXME.
65- Sometimes ftape_write() failed to re-start the tape drive when a
66 segment without a good sector was reached ("wait for empty segment
67 failed"). This is fixed. Especially important for > QIC-3010.
68- sftape (aka ftape-2.x) has vanished. I didn't work on it for
69 ages. It is probably still possible to use the old code with
70 ftape-3.04, if one really needs it (BUT RECOMPILE IT)
71- zftape no longer alters the contents of already existing volume
72 table entries, which makes it possible to fill in missing fields,
73 like time stamps using some user space program.
74- ./contrib/vtblc/ contains such a program.
75- new perl script ./contrib/scripts/listtape that list the contents of a
76 floppy tape cartridge parsing the output of "mt volinfo" + "mt fsf"
77- the MTWEOF implementation has changed a little bit (after I had a
78 look at amanda). Calling MTWEOF while the tape is still held open
79 after writing something to the tape now will terminate the current
80 volume, and start a new one at the current position.
81- the volume table maintained by zftape now is a doubly linked list
82 that grows dynamically as needed.
83
84 formatting floppy tape cartridges
85 ---------------------------------
86 * there is a new user space formatting program that does most of the
87 dirty work in user space (auto-detect, computing the sector
88 coordinates, adjusting time stamps and statistics). It has a
89 simple command line interface.
90 * ftape-format.o has vanished, it has been folded into the low level
91 ftape.o module, and the ioctl interface into zftape.o. Most of the
92 complicated stuff has been moved to user space, so there was no
93 need for a separate module anymore.
94 * there is a new ioctl MTIOCFTCMD that sends a bare QIC-117 command
95 to the tape drive.
96 * there is a new mmap() feature to map the dma buffers into user
97 space to be used by the user level formatting program.
98 * Formatting of yet unformatted or totally degaussed cartridges
99 should be possible now. FIXME.
100
101===== Release notes for ftape-3.03b, <forgot the exact date> ====
102
103ftape-3.03b was released as a beta release only. Its main new feature
104was support of the DITTO-2GB drive. This was made possible by reverse
105engineering done by <fill in his name> after Iomega failed to support
106ftape. Although they had promised to do so (this makes me feel a bit
107sad and uncomfortable about Iomega).
108
109===== Release notes for ftape-3.03a, 22/05/97 ====
110
111- Finally fixed auto-un-loading of modules for kernels > 2.1.18
112- Add an "uninstall" target to the Makefile
113- removed the kdtime hack
114- texi2www didn't properly set the back-reference from a footnote back
115 to the regular text.
116
117 zftape specific
118 ---------------
119 * hide the old compression map volume. Taper doesn't accept the
120 presence of non-Taper volumes and Taper-written volume on the same
121 tape.
122 * EOD (End Of Data) handling was still broken: the expected behavior
123 is to return a zero byte count at the first attempt to read past
124 EOD, return a zero byte count at the second attempt to read past
125 EOD and THEN return -EIO.
126
127 ftape-format specific
128 ---------------------
129 * Detection of QIC-40 cartridges in select_tape_format() was broken
130 and made it impossible to format QIC-3010/3020 cartridges.
131 * There are strange "TR-1 Extra" cartridges out there which weren't
132 detected properly because the don't strictly conform to the
133 QIC-80, Rev. N, spec.
134
135===== Release notes for ftape-3.03, 30/04/97 =====
136
137- Removed kernel integration code from the package. I plan to provide
138 a package that can be integrated into the stock kernel separately
139 (hopefully soon).
140 As a result, a simple `make' command now will build everything.
141- ALL compile time configuration options have been moved to the file
142 `MCONFIG'.
143- Quite a few `low level' changes to allow formatting of cartridges.
144- formatting is implemented as a separate module `ftape-format.o'. The
145 modified `mt' program contains sample code that shows how to use it.
146- The VFS interface has been moved from the `ftape.o' module to the
147 high level modules `zftape.o' resp. `sftape.o'. `ftape.o' contains
148 the hardware support only.
149- A bit of /proc support for kernels > 2.1.28
150- Moved documentation to Doc subdir. INSTALL now contains some real
151 installation notes.
152- `install' target in Makefile.
153
154zftape specific:
155----------------
156
157- zftape works for large cartridges now ( > 2^31 bytes)
158- MTIOCVOLINFO and MTIOCGETSIZE now return the size in KILOBYTES,
159 NO LONGER in bytes.
160
161- permissions for write access to a cartridge have changed:
162 * zftape now also takes the file access mode into account
163 * zftape no longer allows writing in the middle of the recorded
164 media. The tape has to be positioned at BOT or EOD for write
165 access.
166
167- MTBSF has changed. It used to position at the beginning of the
168 previous file when called with count 1. This was different from the
169 expected behavior for other Un*x tape drivers (i.e. SCSI). MTBSF
170 with count 1 should merely position at the beginning of the current
171 volume. Fixed. As a result, `tar --verify' now produces the desired
172 result: it verifies the last written volume, not the pre-last
173 written volume.
174
175- The compression map has vanished --> no need for `mt erase' any
176 more. Fast seeking in a compressed volume is still be possible, but
177 takes slightly longer. As a side effect, you may experience an
178 additional volume showing up in front of all others for old
179 cartridges. This is the tape volume that holds the compression map.
180
181- The compression support for zftape has been moved to a separate
182 module `zft-compressor'. DON'T forget to load it before trying to
183 read back compressed volumes. The stock `zftape.o' module probes for
184 the module `zft-compressor' using the kerneld message channel; you
185 have to install `zft-compressor.o' in a place where modprobe can
186 find it if you want to use this.
187
188- New experimental feature that tries to get the broken down GMT time
189 from user space via a kernel daemon message channel. You need to
190 compile and start the `kdtime' daemon contained in the contrib
191 directory to use it. Needed (?) for time stamps in the header
192 segments and the volume table.
193
194- variable block size mode via MTSETBLK 0
195
196- keep modules locked in memory after the block size has been changed
197
198sftape specific:
199----------------
200
201- end of tape handling should be fixed, i.e. multi volume archives
202 written with `afio' can be read back now.
203
204
205===== Release notes for ftape-3.02a, 09/01/97 =====
206
207No big news:
208- call zft_init() resp. sft_init() when compiling the entire stuff
209 into the kernel image.
210- fix bug in ftape-setup.c when NO_TRACE_AT_ALL was defined.
211- fix bug in sftape-eof.c/zftape-eof.c for old kernels (1.2.*)
212- add support for new module interface for recent kernels
213
214===== Release notes for ftape-3.02, 16/12/96 =====
215- Fixed the `FDC unlock command failed' bug in fdc-io.c. When the FIFO
216 was already locked when ftape was loaded, ftape failed to unlock it.
217- Fixed compilation of `contrib/gnumt'. It now finds `mtio.h' even if
218 ftape is NOT included into the kernel source tree.
219- fc-10.c: include <asm/io.h> for inb() and outb().
220- ftape/sftape/zftape: all global variable now have either a `ftape_',
221 a `ft_', `sft_', `zft_' or `qic_' prefix to prevent name clashes
222 with other parts of the kernel when including ftape into the kernel
223 source tree.
224- Kerneld support has changed. `ftape' now searches for a module
225 `ftape-frontend' when none of the frontend (`sftape' or `zftape') is
226 loaded. Please refer to the `Installation/Loading ftape' section of
227 the TeXinfo manual.
228- Add load resp. boot-time configuration of ftape. There are now
229 variables ft_fdc_base, ft_fdc_dma and ft_fdc_irq corresponding to
230 the former FDC_BASE etc. compile time definitions. One can also use
231 the kernel command line parameters to configure the driver if it is
232 compiled into the kernel. Also, the FC-10/FC-20 support is load-time
233 configurable now as well as the MACH-II hack (ft_probe_fc10,
234 resp. ft_mach2). Please refer to the section `Installation/Configure
235 ftape' of the TeXinfo manual.
236- I removed the MODVERSIONS option from `Makefile.module'. Let me alone
237 with ftape and MODVERSIONS unless you include the ftape sources into
238 the kernel source tree.
239- new vendors in `vendors.h':
240 * HP Colorado T3000
241 * ComByte DoublePlay (including a bug fix for their broken
242 formatting software, thanks to whraven@njackn.com)
243 * Iomega DITTO 2GIG. NOTE: this drive cannot work with ftape because
244 the logical data layout of the cartridges used by this drive does
245 NOT conform to the QIC standards, it is a special Iomega specific
246 format. I've sent mail to Iomega but didn't receive an answer
247 yet. If you want this drive to be supported by ftape, ask Iomega
248 to give me information about it.
249- zftape:
250 * re-introduced the MTIOC_ZFTAPE_GETBLKSZ ioctl for compatibility
251 with zftape 1.06a and earlier. Please don't use it when writing
252 new software, use the MTIOCVOLINFO ioctl instead.
253 * Major overhaul of the code that updates the header segments. Never
254 change the tape label unless erasing the tape. Thus we almost
255 never need to write the header segments, unless we would modify
256 the bad sector map which isn't done yet. Updating of volume table
257 and compression map more secure now although it takes a bit
258 longer.
259 * Fixed bug when aborting a write operation with a signal: zftape
260 now finishes the current volume (i.e. writes an eof marker) at the
261 current position. It didn't before which led to somehow *strange*
262 behavior in this cases.
263 * Keep module locked in memory when using it with the non-rewinding
264 devices and the tape is not logical at BOT. Needed for kerneld
265 support.
266- sftape:
267 * Keep module locked in memory when using it with the non-rewinding
268 devices and the tape is not logical at BOT. Needed for kerneld
269 support.
270
271===== Release notes for ftape-3.01, 14/11/96 =====
272
273- Fixed silly bugs in ftape-3.00:
274 * MAKEDEV.ftape: major device number must be 27, not 23
275 * sftape/sftape-read.c: sftape_read_header_segments() called
276 itself recursively instead of calling ftape_read_header_segment()
277 * zftape/qic-vtbl.h: conversion of ftape's file marks to zftape's
278 internal volume table was broken.
279 * patches/2.x.x/linux-2.0.21.dif: my RCS (resp. CVS) system replaced
280 the `$Revison:' etc. macros in the `ftape.h' concerning part of the
281 patch :-( Fixed.
282 * info/ftape.info: Fixed misspellings (`cp' <-> `cp -r' etc.)
283 * when ftape/sftape or ftape/zftape was compiled into the kernel the
284 variable ftape_status was declared twice. Fixed.
285 * removed reference to undeclared variable kernel_version when not
286 compiling as module
287 * fixed a bug introduced by the use of bit-fields for some flags
288 (i.e. write_protected, no_cartridge, formatted)
289 * flag `header_read' is now reset correctly to zero when tape is
290 removed.
291- fixed a bug in sftape/sftape-eof.c that was already in the original
292 ftape code. MTFSF/BSF was not handled correctly when positioned
293 right before the file mark (think of tar)
294- Changed TRACE macros (following a suggestion of Marcin Dalecki) to use
295 the predefined __FUNCTION__ macro of GCC. Spares about 4k of code.
296- added new vendor id for Iomega DITTO 2GIG
297- fixed a bug already present in zftape-1.06 when aborting a write
298 with a signal: we now finish the current volume at that
299 position. Header segments remain NOT up to date until an explicit call
300 to MTREW or MTOFFL is done.
301
302===== Release notes for ftape-3.00, 14/10/96 =====
303
304- Merged ftape with zftape. There are three modules now:
305 ftape for the hardware support, sftape for the implementation of the
306 original ftape eof mark stuff and zftape that implements zftape's way
307 of handling things (compression, volume table, tape blocks of
308 constant length)
309- Documentation in TeXinfo format in the `info' subdirectory.
310- New ioctls for zftape. See zftape/zftape.h
311- Dummy formatting ioctl for ftape. See ftape.h
312- Kernel patch files for the 2.*.* series to include ftape-3.00 in the
313 kernel source tree. These includes a kernel compatible Config.in
314 script and fairly large online information for the kernel configure
315 script.
316- Support for compiling with Linux-1.2.13.
317- Modified GNU mt from their cpio package that can handle the new
318 ioctls.
319- ftape/sftape/zftape is kerneld save now!
320
321Notes on sftape:
322- sftape implements the eof handling code of the original ftape. If
323 you like to stick with the original ftape stuff, you have to use
324 this module, not zftape.
325- sftape is kerneld save, unlike the original ftape.
326- we keep the entire header segment now in memory, so no need to read
327 it before updating the header segments. Additional memory
328 consumption: 256 bytes.
329
330Notes for zftape:
331- zftape has support for tapes with format code 6 now, which use a
332 slightly different volume table format compared with other floppy
333 tapes.
334- new ioctls for zftape. Have a look at zftape/zftape.h
335- The internal volume table representation has changed for zftape. Old
336 cartridges are converted automatically.
337- zftape no longer uses compression map segments, which have vanished
338 from the QIC specs, but creates volume table entry that reserves
339 enough space for the compression map.
340- zftape is kerneld save now.
341- we keep the entire header segment now in memory, so no need to read
342 it before updating the header segments. Additional memory
343 consumption: 256 bytes.
344
345Notes for contrib/gnumt:
346- modified mt from the GNU cpio package that supports all the new
347 ioctls of zftape.
348Notes for contrib/swapout:
349- This contains the swapout.c program that was written by Kai
350 Harrekilde-Pederson. I simply added a Makefile.
351
352===== Release notes for ftape-2.10, 14/10/96 =====
353
354The ftape maintainer has changed.
355Kai Harrekilde-Petersen <khp@dolphinics.no>
356has resigned from maintaining ftape, and I,
357Claus-Justus Heine <claus@momo.math.rwth-aachen.de>,
358have taken over.
359
360- Added support for tapes with `format code 6', i.e. QIC-3020 tapes
361 with more than 2^16 segments.
362- merged changes made by Bas Laarhoven with ftape-2.09. Refer
363 to his release notes below. I've included them into this
364 file unchanged for your reference.
365- disabled call stack back trace for now. This new feature
366 introduced by the interim release 2.0.x still seems to
367 be buggy.
368- Tried to minimize differences between the ftape version
369 to be included into the kernel source tree and the standalone
370 module version.
371- Reintroduced support for Linux-1.2.13. Please refer to the
372 Install-guide.
373
374===== Release notes for ftape-2.09, 16/06/96 =====
375
376There aren't any really big news in this release, mostly just that I
377(the maintainer) have changed my email address (due to a new job). My
378new address is <khp@dolphinics.no>
379
380- The CLK_48MHZ and FDC_82078SL options has gone (all 2Mbps cards seem
381 to use a 48MHz oscillator anyway and I haven't heard of an 'SL
382 chip out there).
383- The S82078B has been `downgraded' to i82077AA compability.
384- TESTING option revived. Right now, it'll enable the (seriously broken)
385 2Mbps code. If you enable it, you'll experience a tape drive that's
386 *really* out to lunch!
387- Some (bold) changes in the init code. Please notify me if they
388 break things for you.
389
390===== Release notes for ftape-2.08, 14/03/96 =====
391
392If you correct a problem with ftape, please send your patch to
393khp@dolphinics.no too.
394
395- Updated to reflect that NR_MEM_LISTS is gone in 1.3.74
396- Teac 700 added to list of known drives.
397- The registered device name is now "ft" rather than "ftape".
398
399===== Release notes for ftape-2.07a, 14/03/96 =====
400
401Bugfixes by Marcin Dalecki <dalecki@namu03.gwdg.de>:
402- In the last release it just compiled against 1.3.70;
403 now the params to request_irq() and free_irq are() are fixed, so it also
404 works in 1.3.73 :-)
405- Support for modules is now correct for newer kernels.
406
407===== Release notes for ftape-2.07, 04/03/96 =====
408
409
410- ftape updated to compile against 1.3.70.
411- Iomega 700 and Wangtek 3200 recognised.
412
413
414===== Release notes for ftape-2.06b, 13/02/96 =====
415
416Another simple bugfix version.
417
418- Jumbo 700 recognised.
419- Typo in vendors.h fixed.
420
421
422===== Release notes for ftape-2.06a, 10/02/96 =====
423
424This release is a simple bugfix version.
425
426- Linux/SMP: ftape *should* work.
427- FC-10/20: Only accepts IRQs 3-7, or 9. If IRQ 9, properly tell the card
428 to use IRQ 2. Thanks to Greg Crider (gcrider@iclnet.org) for finding and
429 locating this bug and testing the patch.
430- Insight drive recognised correctly again.
431- Motor-on wakeup version of the Iomega 250 drive added
432
433
434===== Release notes for ftape-2.06, 28/01/96 =====
435
436Special thanks go to Neal Friedman and Steven Sorbom for their
437help in producing and testing this release.
438
439I have continued to clean up the code, with an eye towards inclusion
440of ftape in Linus' official kernel (In fact, as I type this, I am
441running on a kernel with ftape support statically linked). I have
442test-compiled ftape against my 1.2.13 tree without problems.
443Hopefully, everything should be OK for the v1.2.x people.
444
445WARNING! Alan Cox has mailed me that ftape does *NOT* work with
446Linux/SMP. If you try to run ftape under Linux/SMP, it will cause a
447kernel deadlock (which is worse than a panic).
448
449- QIC-3020/TR-3: 1Mbps support works. Neal is capable of reading and
450 writing data to a tape. ftape will automatically detect the type of
451 tape (e.g. TR-3 vs QIC-80) and move the fdc in and out of
452 "perpendicular mode" as necessary.
453- 2Mbps support is disabled by default, since it is not fully
454 debugged. If you are adventurous, remove -DFDC_82078SL in the
455 Makefile and see what happens :-)
456- fdc detection: silly bugs removed (Only 2Mbps fdcs were affected)
457 and added detection of the National Semiconductors PC8744 fdc chip
458 (used in the PC873xx "super-IO" chips).
459- Removed warning about incompatible types when compiling with Linux
460 1.2.x.
461- README.PCI updated with info about the DELL Dimension XPS P90.
462- Connor TST3200R added to detected drives.
463- `swapout' utility added to distribution. It will dirty 5Meg of
464 memory, trying to swap out other programs. Just say `make swapout'
465 to build it. ftape will do this automatically Real Soon Now (ie:
466 when I have found out which kernel memory alloc function to call).
467
468
469===== Release notes for ftape-2.05, 08/01/96 =====
470
471- For v1.2.x Kernels, you must apply the patch linux-1.2/ksyms.patch to
472 the kernel and rebuild it (it adds the __get_dma_pages symbol to
473 ksyms.c).
474- Included new asm-i386/io.h file from v1.3.x kernel series, to enable
475 gcc v.2.7.[12] to compile v1.2.x kernels (linux-1.2/io.h).
476- Module versions: If you wish to compile ftape as a versioned module,
477 you must first compile your kernel with CONFIG_MODVERSIONS=y.
478 Otherwise, you will get complaints that <linux/modversions.h> does not
479 exist (if that happens, a `touch modversions.h' will help you out).
480- CLK_48MHZ: new define in the Makefile (default: non-zero). If you have
481 a tape controller card that uses the i82078(-1) chip, but cannot get
482 it to work with ftape, try set it to 0 (and please report this).
483- QIC-3010/3020: Complete support is still missing, but will hopefully
484 come soon. Steven Sorbom has kindly provided me with hints about
485 this. Writing of QIC-3020 tapes definitely does NOT work (do not try
486 it! - the drive will not be in "perpendicular mode" and this will ruin
487 the formatting info on the tape).
488- ftape_num_buffers is out of fashion: use NR_BUFFERS instead (and
489 recompile if you want to change it :-).
490
491
492===== Release notes for ftape-2.04, 01/01/96 =====
493
494This version by Kai Harrekilde-Petersen <khp@dolphinics.no>
495
496- ALERT! Support for Kernels earlier then v1.1.85 is about to go away.
497 I intend to clean up some of the code (getting rid of an annoyingly
498 large numbers of #ifdef mostly), which means that support for
499 pre-1.1.85 kernels must go as well.
500- NR_FTAPE_BUFFERS is gone; You can instead select the number of dma
501 buffers by saying `insmod ftape.o ftape_num_buffer=<n>' instead.
502- Configure script gone. ftape will now automagically determine your
503 kernel version by /usr/include/linux/version.h instead.
504- CONFIG_MODVERSIONS now work. All combinations of versioned /
505 unversioned kernel and ftape module works (at least with my 1.3.52
506 kernel).
507- If you have problems with inserting ftape into an old (1.2.x)
508 kernel (e.g. insmod says "1.2.8 does not match 1.2.8), recompile
509 your modules utilities with your new compiler.
510- Reveal TB1400 drive added to vendors.h
511- Support for the i82078-1 (2Mbps) chip is coming along. The
512 biggest problem is that I don't have such a card, which makes
513 testing / debugging somewhat problematic. The second biggest
514 problem is that I do not have the QIC-3010/3020 standards either.
515 Status right now is that the chip is detected, and it should be
516 possible to put it into 2Mbps mode. However, I do not know what
517 "extras" are needed to complete the support. Although putting the
518 i82078 into 1Mbps mode ought to work out of the box, it doesn't
519 (right now, ftape complains about id am errors).
520
521
522===== Release notes for ftape-2.04beta5, 29/12/95 =====
523
524Bas offline linux-tape
525----------------------
526For reasons only known to the majordomo mail list processor, Bas was
527kicked off the linux-tape list sometime during the summer. Being
528overworked at his for-pay job, he didn't notice it much. Instead I
529(Kai, khp@dolphinics.no) has worked on ftape to produce the 2.04(beta)
530version.
531
532zftape
533------
534Note that there exists a much improved version of ftape, written by
535Claus-Justus Heine <claus@willi.math.rwth-aachen.de> which is named
536zftape, which conforms to the QIC-80 specs on how to mark backups, and
537is capable of doing automatic compression. However, zftape makes
538substantial changes to ftape, and I (Kai) have therefore declined to
539integrate zftape into ftape. Hopefully, this will happen soon.
540
541CONFIG_QIC117 removed from the kernel
542-------------------------------------
543The biggest change of all is that ftape now will allocate its dma
544buffers when it is inserted. The means that the CONFIG_QIC117 option
545has disappeared from the Linux kernel as of v1.3.34. If you have an
546earlier kernel, simply answer 'no' to the question will do the trick
547(if you get complains about __get_free_pages() missing, contact the
548linux-tape mailing list).
549
550Note that ftape-2.04beta will work equally well on kernels with and
551without `ftape support'. The only catch is, that you will waste
552around 96-128Kb of precious DMA'able memory on a box that has ftape
553support compiled in.
554
555Now for the real changes:
556
557- FC-20 can now use DMA channels 1, 2, and 3. Thanks to Daniel
558 Cohen, catman@wpi.edu.
559- ftape no longer requires a (gigantic) 96Kb buffer to be statically
560 allocated by the kernel.
561- Added new Iomega drive (8882) to vendors.h
562- -fno-strength-reduce added to Makefile, since GCC is broken.
563- i82078-1 (2Mbps) FDC support started.
564
565
566===== Release notes for ftape-2.03b, 27/05/95 =====
567
568- Prevented verify_area to return error if called with zero length.
569- Fixed a bug in flush_buffers that caused too much padding to be
570 written when a final segment had bad sectors.
571- Increased maximum fast-seek overshoot value from 5 to 10 segments.
572- Breaking loop after 5 retries when positioning fails.
573- Fixed wrong calculation of tape length for QIC-3010 and QIC-3020
574 tapes (densities were swapped).
575- Fixed wrong calculation of overshoot on seek_forward: Wrong sign
576 of error.
577- Suppress (false) error message due to new tape loaded.
578- Added two new CMS drives (11c3 and 11c5) to vendors.h.
579
580
581===== Release notes for ftape-2.03a, 09/05/95 =====
582
583- Fixed display of old error (even if already cleared) in ftape_open.
584- Improved tape length detection, ioctls would fail for 425 ft tapes.
585 Until the tape length is calculated with data from the header
586 segment, we'll use worst-case values.
587- Clear eof_mark after rewinding ioctls.
588- Fixed wrong version message (2.03 had 2.02g id).
589- Fixed bug that caused the fdc to be reset very frequently.
590 This shouldn't affect normal operation but the timing of the
591 report routines has changed again and that may cause problems.
592 We'll just have to find out....
593- Implemented correct write precompensation setting for QIC-3010/3020.
594- Cleaned up fdc_interrupt_wait routine. Hope it still works :-)
595- Finally removed (already disabled) special eof mark handling for
596 gnu tar.
597- Changed order of get_dma_residue and disable_dma in fdc-isr.c
598 because the current order would fail on at least one system.
599 We're back to the original order again, hope (and expect) this
600 doesn't break any other system.
601
602
603===== Release notes for ftape-2.03, 07/05/95 =====
604
605(Changes refer to the first ftape-2.02 release)
606
607Support for wide and extended length tapes
608------------------------------------------
609The Conner TSM 420 and 850 drives are reported to be working.
610I haven't received any reports about other brands; the TSM 420
611and 850 seem to be the most widely used wide drives.
612Extended length tapes (425 ft) with normal QIC-80 drives
613are operating too (At least I've had no reports stating otherwise).
614_Not_ yet completely supported (although they may work) are
615QIC-3020 drives and 2 Mbps floppy disk controllers won't work at
616the highest speed.
617If someone is kind enough to send me one of these, I'll include
618support for it too ;-)
619
620Easier configuration
621--------------------
622Problems due to wrong settings in the Makefile are prevented
623by using a configuration script that sets the necessary (kernel
624version dependent) compile time options.
625This kernel version is now determined from the sources found
626at /usr/src/linux, or if not found, the old way using
627/proc/version.
628Versioned modules will be used automatically when supported
629by- and configured in- the kernel.
630Note that the current modules code (1.1.87) is still broken
631and _needs_ the fix included in the insmod directory.
632Please don't send me any more Oops reports caused by insmod :-(
633
634Reduced module size
635-------------------
636The standard module size is much reduced and some compile time
637options can even reduce it further. (I don't recommend this
638for normal use but it can be handy for rescue diskettes)
639
640Option: Approx. module size:
641
642<standard> 150 Kb
643NO_TRACE 125 Kb
644NO_TRACE_AT_ALL 67 Kb
645
646
647Much improved driver interruption
648---------------------------------
649Most possible loops have been broken and signal detection
650has been improved.
651In most cases the driver can be aborted by ^C (SIGINT) and
652SIGKILL (kill -9) will generate be a sure kill.
653(Note that aborting a tape operation may damage the last
654data written to tape)
655
656Improved error recovery
657-----------------------
658Ftape now returns an error (ENODATA) to the application if
659a segment proves to be unrecoverable and then skips the
660bad segment.
661This causes most applications to continue to work (tar
662and afio) loosing only a small amount (up to 29 Kb) of data.
663Retried read operations will now be done slightly off-track
664to improve the chance of success. Serious head off-track
665errors will be detected.
666
667FC-10 and FC-20 controllers
668---------------------------
669Ftape now supports both the old CMS FC-10 and the newer FC-20
670controllers.
671Because the operation of these cards is still undocumented,
672thus far they will only work with the default settings (See
673Makefile). Any feed-back on how to use them with other settings
674will be welcome !
675Compilation will fail if one changes the settings to illegal
676values.
677
678Kernels and compilers
679---------------------
680Ftape is currently being developed using the 2.5.8 compiler.
681The older 2.4.5 probably works too (Set option in Makefile!).
682I have no experience with any later compilers nor Elf support.
683Any information on this is welcome.
684The latest kernel I have tested ftape with is 1.2.6.
685
686Compression
687-----------
688An impressive collection of changes for ftape including
689on-the-fly compression is still lying on my desk.
690If 2.03 proves to be reliable I might start integrating these
691but as usual, I'm short in time :-(
692
693Formatting
694----------
695There is still no way to format tapes under Linux. As far as
696I know all attempts to write such a program have died now.
697Since formatted tapes are rather common now, I think all we
698need is a utility that writes a worst case pattern and verifies
699that with the drive put in verify mode, reducing margins.
700Any takers ?
701
702Furthermore
703-----------
704Cleaned up messages.
705Prepared to support multiple tape drives on one fdc.
706Thanks to all the people who sent bug reports and helped me
707improve the driver. Without trying to be complete I'll mention
708Gary Anderson (without his accurate reports and unreliable
709hardware there wouldn't be a 2.03), Stefan Kneifel (FC-20),
710Robert Broughton (FC-20, you were almost there ;-), Bjorn
711Ekwall (for the versioned modules and buggy insmod ;-), Peter
712Fox, Christopher Oliver, Ralph Whittaker and not the least
713Linus Torvalds (for Linux and keeping me busy because of
714changes to the kernel ;-)
715Thanks to anyone I forgot, for the bug reports, the ftape
716bashing and the mental support...
717
718
719That's it for now. Have Fun,
720
721Bas.
722
723
724===== Release notes for ftape-2.02g, 06/05/95 =====
725
726- Added extra test to break read-id loop with signal.
727- Changed rewind code to handle negative overshoot for drives
728 that take very long to start or stop.
729- Let use of get/set i/o-regions depend on kernel version.
730- Changed code to use a more general test for conditional
731 compilations depending on kernel version.
732- Improved micro-step functionality to go off-track only
733 while reading (id & data).
734- Added failure on tape-not-referenced bit in ftape_command.
735- Added FOREVER option to read-wait routine.
736- Changed read-id to use shorter timeout causing smaller
737 rewinds on timeout.
738- Made kernel-interface functions static.
739
740
741===== Release notes for ftape-2.02f, 03/05/95 =====
742
743- Added support for dual tape drives on my system, extended Configure
744 script to detect host 'dodo'.
745- Log media defect in history if ecc failed and no data was returned.
746- Fixed Configure script that was failing for kernel versions with
747 double digit version or revision numbers.
748
749
750===== Release notes for ftape-2.02e, 01/05/95 =====
751
752- Fixed reposition loop at logical eot (failing read_id).
753- Fixed 34 segment offset when rewinding.
754- Added fast seek capability for more than 255 segments.
755- Fixed wrong busy result from ftape_command causing reverse
756 seek to fail.
757- Added breakout from infinite rewind loop (if something fails).
758
759
760===== Release notes for ftape-2.02d, 30/04/95 =====
761
762- Improved abortion on signals: Interrupt will make a graceful
763 exit, Kill will be less nice and should be used if everything
764 else fails.
765- Included check for tape-head off track.
766- Implemented exit from tape-start loop.
767- Added kernel io-port registration.
768- Implemented skip of failing segment (ENODATA) on ecc failure.
769 This allows afio and tar to continue when the tape is damaged.
770- Made distinction between drive names with different codes.
771
772
773===== Release notes for ftape-2.02c, 22/04/95 =====
774
775- Fixed too tight command queueing after tape stop/pause command
776 issued from within interrupt service routine (Showed as timeout
777 on Acknowledge errors during retries on some systems)
778- Tried to fix timeouts when using 425 ft tape because the extended
779 length doesn't seem to be detected by the hardware.
780 We now use the format code from the header segment so adjust the
781 timing after reading the header segment.
782- Fixed some messages stating 'unexpected something...' being not
783 unexpected anymore.
784- Started preparations for merge of dynamic buffer allocation and
785 compression code.
786- Changed some debug messages to include relevant segment information
787 at level 4.
788- Included early bail-out when drive offline, preventing a lot of
789 false messages.
790- Moved ftape_parameter_xxx() offsets into function instead of in calls.
791- Removed 'weird, drive busy but no data' error when caused by
792 an error during a read-id.
793- Improved 'timeout on acknowledge' diagnostics.
794- Moved MODULE option into Configure.
795- Reduced code size when no tracing at all was set (Claus Heine).
796- No longer log error code 0 (no error) as an error.
797
798
799===== Release notes for ftape-2.02b, 09/04/95 =====
800
801- Relaxed timing for status operation and displaying
802 abnormal results. Hopefully this shows what's going
803 wrong with the Conner TSM850R drives.
804- Created script for configuration, using version number
805 of kernel source if available, otherwise /proc/version.
806- Fixed conditionals in kernel-interface.c.
807- Removed unavoidable TRACE output.
808
809
810===== Release notes for ftape-2.02a, 01/04/95 =====
811
812- Implemented `new-style' (versioned) modules support for new
813 kernels.
814- Reduced size of module by moving static data to bss.
815- Now using version number of kernel source instead of running
816 kernel for kernel versions >= 1.1.82
817- Added feedback on drive speeds to vendor information.
818- Included fixed insmod sources to distribution (Let's hope
819 the modules distribution get fixed soon :-/).
820
821Note that I haven't yet implemented any of the code extension I
822received. I hope to find some time to do this soon.
823
824
825===== Release notes for ftape-2.02, 15/01/95 =====
826
827
828- Fixed failing repositioning when overshoot was incremented.
829- Fixed rate selection: Because of a deficiency in the QIC-117
830 specification one cannot distinguish between a not implemented
831 and a failing command. Therefor we now try to find out if the
832 drive does support this command before usage.
833- Fixed error retry using wrong offset in fdc-isr.
834- Improved retry code to retry only once on a single no-data
835 error in a segment.
836- Validate sector number extracted from eof mark because an
837 invalid file mark (due to ???) could cause kernel panic.
838- Split ftape-io.c into ftape-io.c and ftape-ctl.c files.
839- Corrected too high media error count after writing to
840 a bad tape.
841- Added #include <asm/segment.h> again because old kernel versions
842 need it.
843- Fixed fdc not being disabled when open failed because no tape
844 drive was found.
845- Fixed problem with soft error in sector 32 (shift operator with
846 shiftcount 32 is not defined).
847
848
849===== Release notes for ftape-2.01, 08/01/95 =====
850
851
852- Removed TESTING setting from distributed Makefile.
853- Fixed `mt asf' failure: Rewind was deferred to close which
854 overruled the fsf ioctl.
855- Prevented non-interruptible commands being interrupted.
856- Added missing timeout.pause setting.
857- Maximum tape speed read from drive type information table.
858 If the information is not in the table (0) the drive will
859 determine the speed itself and put a message in the logfile.
860 This information should then be added to the table in the
861 vendors.h file (and reported to me).
862- Added call to ftape_init_drive after soft reset for those
863 (antique) drives that don't do an implicit seek_load_point
864 after a reset or power up.
865- Don't try to set data rate if reset failed.
866- Prevent update of seek variables when starting from the
867 beginning or the end of the tape.
868- Fixed wrong adjustment of overshoot in seek_forward().
869- Added sync to Makefile (again).
870- Added code to diagnose timer problems (calibr.c).
871- Replaced time differences by timediff calls.
872- Removed reference to do_floppy from object for recent kernels.
873- Fixed wrong display of 'failing dma controller' message.
874- Removed various no longer used #include statements.
875- Added max. tape speed value to vendor-struct.
876- Changed ftape-command to check pre-conditions and wait
877 if needed.
878- Further updated qic117.h to rev G.
879- Combined command name table and restrictions table to one.
880 Extended this table with some new fields.
881- Increased timeout on Ack timer value and included code to
882 report out of spec behaviour.
883- Increased rewind timeout margin to calculated + 20%.
884- Improved data rate selection so it won't fail on some
885 older (pre standard) drives.
886- Changed initialisation code so drive will be rewound if the
887 driver is reloaded and the tape is not at bot.
888- Moved some of the flush operations from close to the ioctls.
889- Added exit code value to failing verify area message.
890- Loop until tape halted in smart-stop.
891- Fast seek handled specially if located at bot or eot.
892- Being more conservative on overshoot value.
893
894
895===== Release notes for ftape-2.00, 31/12/94 =====
896
897 The Install-guide is completely rewritten and now also includes
898some information on how to use the driver. If you're either new
899to ftape or new to Unix tape devices make sure to read it !
900
901 If you own a pci system and experience problems with the
902ftape driver make sure to read the README.PCI file. It contains
903some hints on how to fix your hardware.
904
905 For anybody who hasn't noticed: The version number of the
906driver has been incremented (The latest released version has
907been version 1.14d).
908 This has been done for two major reasons:
909
910 o A new (better) error recovery scheme is implemented.
911 o Support for new drive types has been added.
912
913 All these improvements/changes will probably include a couple
914of new (and old?) bugs. If you encounter any problems that you think
915I'm not yet aware of, feel free to send a report to <bas@vimec.nl>.
916 I recommend keeping a version of ftape-1.14d available, just
917in case ;-)
918
919 This version should work with all kernel versions from 1.0.9 up
920to 1.1.72 (and probably earlier and later versions too).
921
922
923Major new features:
924
925- Better handling of tapes with defects: When a sector repeatedly
926 (SOFT_RETRIES in ftape.h) cannot be written to or read from it is
927 marked as an hard error and gets skipped.
928 The error correction code can handle up to three of these hard
929 errors provided there are no other errors in that segment (32 Kb).
930
931- Allows writing to tapes with defects (although the risk of loosing
932 data increases !)
933 Look for the media-defects entry printed with the statistics when
934 the tape is closed. A non-zero value here shows a bad tape.
935 [the actual count is wrong (too high), this is a known bug].
936
937- Use of backup header segment if first one is failing.
938
939- Support for extended length tapes with QIC-80: both 425 and 1100 ft.
940 0.25 inch tapes are now recognized and handled.
941
942- Support for new QIC-80 drives with 8 mm `wide' tapes (e.g. Conner
943 TSM 420).
944
945- Support for new QIC-3010 and QIC-3020 drives (experimental) with
946 both 0.25 inch and 8 mm tapes.
947
948Some minor features were added, a couple of small bugs were fixed and
949probably some new ones introduced ;-).
950
951[lseek() didn't make it into this version]
952
953Have fun,
954
955Bas.
956----
957 LocalWords: ftape MCONFIG mt VFS zftape resp sftape proc subdir MTIOCVOLINFO
958 LocalWords: MTIOCGETSIZE BOT EOD MTBSF zft kerneld modprobe kdtime contrib TR
959 LocalWords: MTSETBLK afio uninstall texi www EIO QIC init sft eof aka dma GB
960 LocalWords: SIGKILL MTIOCFTCMD mmap Iomega FDC fdc io gnumt mtio fc asm inb
961 LocalWords: outb ft qic frontend TeXinfo irq mach MODVERSIONS CONFIG html dvi
962 LocalWords: usr doc SMP Mb Dunno FIXME vtblc perl listtape volinfo fsf MTWEOF
963 LocalWords: amanda degaussed ComByte DoublePlay whraven njackn com MTIOC vtbl
964 LocalWords: GETBLKSZ MAKEDEV zftape's linux dif CVS Revison cp MTREW MTOFFL
965 LocalWords: MTFSF BSF Marcin Dalecki GCC Config cpio swapout Kai Harrekilde
966 LocalWords: Pederson khp dolphinics Justus claus momo rwth aachen Laarhoven
diff --git a/drivers/char/ftape/compressor/Makefile b/drivers/char/ftape/compressor/Makefile
deleted file mode 100644
index 1fbd6c4019db..000000000000
--- a/drivers/char/ftape/compressor/Makefile
+++ /dev/null
@@ -1,31 +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# $Source: /homes/cvs/ftape-stacked/ftape/compressor/Makefile,v $
19# $Revision: 1.1 $
20# $Date: 1997/10/05 19:12:28 $
21#
22# Makefile for the optional compressor for th zftape VFS
23# interface to the QIC-40/80/3010/3020 floppy-tape driver for
24# Linux.
25#
26
27obj-$(CONFIG_ZFT_COMPRESSOR) += zft-compressor.o
28
29zft-compressor-objs := zftape-compress.o lzrw3.o
30
31CFLAGS_lzrw3.o := -O6 -funroll-all-loops
diff --git a/drivers/char/ftape/compressor/lzrw3.c b/drivers/char/ftape/compressor/lzrw3.c
deleted file mode 100644
index a032a0ee2a99..000000000000
--- a/drivers/char/ftape/compressor/lzrw3.c
+++ /dev/null
@@ -1,743 +0,0 @@
1/*
2 * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.c,v $
3 * $Revision: 1.1 $
4 * $Date: 1997/10/05 19:12:29 $
5 *
6 * Implementation of Ross Williams lzrw3 algorithm. Adaption for zftape.
7 *
8 */
9
10#include "../compressor/lzrw3.h" /* Defines single exported function "compress". */
11
12/******************************************************************************/
13/* */
14/* LZRW3.C */
15/* */
16/******************************************************************************/
17/* */
18/* Author : Ross Williams. */
19/* Date : 30-Jun-1991. */
20/* Release : 1. */
21/* */
22/******************************************************************************/
23/* */
24/* This file contains an implementation of the LZRW3 data compression */
25/* algorithm in C. */
26/* */
27/* The algorithm is a general purpose compression algorithm that runs fast */
28/* and gives reasonable compression. The algorithm is a member of the Lempel */
29/* Ziv family of algorithms and bases its compression on the presence in the */
30/* data of repeated substrings. */
31/* */
32/* This algorithm is unpatented and the code is public domain. As the */
33/* algorithm is based on the LZ77 class of algorithms, it is unlikely to be */
34/* the subject of a patent challenge. */
35/* */
36/* Unlike the LZRW1 and LZRW1-A algorithms, the LZRW3 algorithm is */
37/* deterministic and is guaranteed to yield the same compressed */
38/* representation for a given file each time it is run. */
39/* */
40/* The LZRW3 algorithm was originally designed and implemented */
41/* by Ross Williams on 31-Dec-1990. */
42/* */
43/* Here are the results of applying this code, compiled under THINK C 4.0 */
44/* and running on a Mac-SE (8MHz 68000), to the standard calgary corpus. */
45/* */
46/* +----------------------------------------------------------------+ */
47/* | DATA COMPRESSION TEST | */
48/* | ===================== | */
49/* | Time of run : Sun 30-Jun-1991 09:31PM | */
50/* | Timing accuracy : One part in 100 | */
51/* | Context length : 262144 bytes (= 256.0000K) | */
52/* | Test suite : Calgary Corpus Suite | */
53/* | Files in suite : 14 | */
54/* | Algorithm : LZRW3 | */
55/* | Note: All averages are calculated from the un-rounded values. | */
56/* +----------------------------------------------------------------+ */
57/* | File Name Length CxB ComLen %Remn Bits Com K/s Dec K/s | */
58/* | ---------- ------ --- ------ ----- ---- ------- ------- | */
59/* | rpus:Bib.D 111261 1 55033 49.5 3.96 19.46 32.27 | */
60/* | us:Book1.D 768771 3 467962 60.9 4.87 17.03 31.07 | */
61/* | us:Book2.D 610856 3 317102 51.9 4.15 19.39 34.15 | */
62/* | rpus:Geo.D 102400 1 82424 80.5 6.44 11.65 18.18 | */
63/* | pus:News.D 377109 2 205670 54.5 4.36 17.14 27.47 | */
64/* | pus:Obj1.D 21504 1 13027 60.6 4.85 13.40 18.95 | */
65/* | pus:Obj2.D 246814 1 116286 47.1 3.77 19.31 30.10 | */
66/* | s:Paper1.D 53161 1 27522 51.8 4.14 18.60 31.15 | */
67/* | s:Paper2.D 82199 1 45160 54.9 4.40 18.45 32.84 | */
68/* | rpus:Pic.D 513216 2 122388 23.8 1.91 35.29 51.05 | */
69/* | us:Progc.D 39611 1 19669 49.7 3.97 18.87 30.64 | */
70/* | us:Progl.D 71646 1 28247 39.4 3.15 24.34 40.66 | */
71/* | us:Progp.D 49379 1 19377 39.2 3.14 23.91 39.23 | */
72/* | us:Trans.D 93695 1 33481 35.7 2.86 25.48 40.37 | */
73/* +----------------------------------------------------------------+ */
74/* | Average 224401 1 110953 50.0 4.00 20.17 32.72 | */
75/* +----------------------------------------------------------------+ */
76/* */
77/******************************************************************************/
78
79/******************************************************************************/
80
81/* The following structure is returned by the "compress" function below when */
82/* the user asks the function to return identifying information. */
83/* The most important field in the record is the working memory field which */
84/* tells the calling program how much working memory should be passed to */
85/* "compress" when it is called to perform a compression or decompression. */
86/* LZRW3 uses the same amount of memory during compression and decompression. */
87/* For more information on this structure see "compress.h". */
88
89#define U(X) ((ULONG) X)
90#define SIZE_P_BYTE (U(sizeof(UBYTE *)))
91#define SIZE_WORD (U(sizeof(UWORD )))
92#define ALIGNMENT_FUDGE (U(16))
93#define MEM_REQ ( U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE )
94
95static struct compress_identity identity =
96{
97 U(0x032DDEA8), /* Algorithm identification number. */
98 MEM_REQ, /* Working memory (bytes) required. */
99 "LZRW3", /* Name of algorithm. */
100 "1.0", /* Version number of algorithm. */
101 "31-Dec-1990", /* Date of algorithm. */
102 "Public Domain", /* Copyright notice. */
103 "Ross N. Williams", /* Author of algorithm. */
104 "Renaissance Software", /* Affiliation of author. */
105 "Public Domain" /* Vendor of algorithm. */
106};
107
108LOCAL void compress_compress (UBYTE *,UBYTE *,ULONG,UBYTE *, LONG *);
109LOCAL void compress_decompress(UBYTE *,UBYTE *,LONG, UBYTE *, ULONG *);
110
111/******************************************************************************/
112
113/* This function is the only function exported by this module. */
114/* Depending on its first parameter, the function can be requested to */
115/* compress a block of memory, decompress a block of memory, or to identify */
116/* itself. For more information, see the specification file "compress.h". */
117
118EXPORT void lzrw3_compress(
119 UWORD action, /* Action to be performed. */
120 UBYTE *wrk_mem, /* Address of working memory we can use.*/
121 UBYTE *src_adr, /* Address of input data. */
122 LONG src_len, /* Length of input data. */
123 UBYTE *dst_adr, /* Address to put output data. */
124 void *p_dst_len /* Address of longword for length of output data.*/
125)
126{
127 switch (action)
128 {
129 case COMPRESS_ACTION_IDENTITY:
130 *((struct compress_identity **)p_dst_len)= &identity;
131 break;
132 case COMPRESS_ACTION_COMPRESS:
133 compress_compress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len);
134 break;
135 case COMPRESS_ACTION_DECOMPRESS:
136 compress_decompress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len);
137 break;
138 }
139}
140
141/******************************************************************************/
142/* */
143/* BRIEF DESCRIPTION OF THE LZRW3 ALGORITHM */
144/* ======================================== */
145/* The LZRW3 algorithm is identical to the LZRW1-A algorithm except that */
146/* instead of transmitting history offsets, it transmits hash table indexes. */
147/* In order to decode the indexes, the decompressor must maintain an */
148/* identical hash table. Copy items are straightforward:when the decompressor */
149/* receives a copy item, it simply looks up the hash table to translate the */
150/* index into a pointer into the data already decompressed. To update the */
151/* hash table, it replaces the same table entry with a pointer to the start */
152/* of the newly decoded phrase. The tricky part is with literal items, for at */
153/* the time that the decompressor receives a literal item the decompressor */
154/* does not have the three bytes in the Ziv (that the compressor has) to */
155/* perform the three-byte hash. To solve this problem, in LZRW3, both the */
156/* compressor and decompressor are wired up so that they "buffer" these */
157/* literals and update their hash tables only when three bytes are available. */
158/* This makes the maximum buffering 2 bytes. */
159/* */
160/* Replacement of offsets by hash table indexes yields a few percent extra */
161/* compression at the cost of some speed. LZRW3 is slower than LZRW1, LZRW1-A */
162/* and LZRW2, but yields better compression. */
163/* */
164/* Extra compression could be obtained by using a hash table of depth two. */
165/* However, increasing the depth above one incurs a significant decrease in */
166/* compression speed which was not considered worthwhile. Another reason for */
167/* keeping the depth down to one was to allow easy comparison with the */
168/* LZRW1-A and LZRW2 algorithms so as to demonstrate the exact effect of the */
169/* use of direct hash indexes. */
170/* */
171/* +---+ */
172/* |___|4095 */
173/* |___| */
174/* +---------------------*_|<---+ /----+---\ */
175/* | |___| +---|Hash | */
176/* | |___| |Function| */
177/* | |___| \--------/ */
178/* | |___|0 ^ */
179/* | +---+ | */
180/* | Hash +-----+ */
181/* | Table | */
182/* | --- */
183/* v ^^^ */
184/* +-------------------------------------|----------------+ */
185/* |||||||||||||||||||||||||||||||||||||||||||||||||||||||| */
186/* +-------------------------------------|----------------+ */
187/* | |1......18| | */
188/* |<------- Lempel=History ------------>|<--Ziv-->| | */
189/* | (=bytes already processed) |<-Still to go-->| */
190/* |<-------------------- INPUT BLOCK ------------------->| */
191/* */
192/* The diagram above for LZRW3 looks almost identical to the diagram for */
193/* LZRW1. The difference is that in LZRW3, the compressor transmits hash */
194/* table indices instead of Lempel offsets. For this to work, the */
195/* decompressor must maintain a hash table as well as the compressor and both */
196/* compressor and decompressor must "buffer" literals, as the decompressor */
197/* cannot hash phrases commencing with a literal until another two bytes have */
198/* arrived. */
199/* */
200/* LZRW3 Algorithm Execution Summary */
201/* --------------------------------- */
202/* 1. Hash the first three bytes of the Ziv to yield a hash table index h. */
203/* 2. Look up the hash table yielding history pointer p. */
204/* 3. Match where p points with the Ziv. If there is a match of three or */
205/* more bytes, code those bytes (in the Ziv) as a copy item, otherwise */
206/* code the next byte in the Ziv as a literal item. */
207/* 4. Update the hash table as possible subject to the constraint that only */
208/* phrases commencing three bytes back from the Ziv can be hashed and */
209/* entered into the hash table. (This enables the decompressor to keep */
210/* pace). See the description and code for more details. */
211/* */
212/******************************************************************************/
213/* */
214/* DEFINITION OF COMPRESSED FILE FORMAT */
215/* ==================================== */
216/* * A compressed file consists of a COPY FLAG followed by a REMAINDER. */
217/* * The copy flag CF uses up four bytes with the first byte being the */
218/* least significant. */
219/* * If CF=1, then the compressed file represents the remainder of the file */
220/* exactly. Otherwise CF=0 and the remainder of the file consists of zero */
221/* or more GROUPS, each of which represents one or more bytes. */
222/* * Each group consists of two bytes of CONTROL information followed by */
223/* sixteen ITEMs except for the last group which can contain from one */
224/* to sixteen items. */
225/* * An item can be either a LITERAL item or a COPY item. */
226/* * Each item corresponds to a bit in the control bytes. */
227/* * The first control byte corresponds to the first 8 items in the group */
228/* with bit 0 corresponding to the first item in the group and bit 7 to */
229/* the eighth item in the group. */
230/* * The second control byte corresponds to the second 8 items in the group */
231/* with bit 0 corresponding to the ninth item in the group and bit 7 to */
232/* the sixteenth item in the group. */
233/* * A zero bit in a control word means that the corresponding item is a */
234/* literal item. A one bit corresponds to a copy item. */
235/* * A literal item consists of a single byte which represents itself. */
236/* * A copy item consists of two bytes that represent from 3 to 18 bytes. */
237/* * The first byte in a copy item will be denoted C1. */
238/* * The second byte in a copy item will be denoted C2. */
239/* * Bits will be selected using square brackets. */
240/* For example: C1[0..3] is the low nibble of the first control byte. */
241/* of copy item C1. */
242/* * The LENGTH of a copy item is defined to be C1[0..3]+3 which is a number */
243/* in the range [3,18]. */
244/* * The INDEX of a copy item is defined to be C1[4..7]*256+C2[0..8] which */
245/* is a number in the range [0,4095]. */
246/* * A copy item represents the sequence of bytes */
247/* text[POS-OFFSET..POS-OFFSET+LENGTH-1] where */
248/* text is the entire text of the uncompressed string. */
249/* POS is the index in the text of the character following the */
250/* string represented by all the items preceeding the item */
251/* being defined. */
252/* OFFSET is obtained from INDEX by looking up the hash table. */
253/* */
254/******************************************************************************/
255
256/* The following #define defines the length of the copy flag that appears at */
257/* the start of the compressed file. The value of four bytes was chosen */
258/* because the fast_copy routine on my Macintosh runs faster if the source */
259/* and destination blocks are relatively longword aligned. */
260/* The actual flag data appears in the first byte. The rest are zeroed so as */
261/* to normalize the compressed representation (i.e. not non-deterministic). */
262#define FLAG_BYTES 4
263
264/* The following #defines define the meaning of the values of the copy */
265/* flag at the start of the compressed file. */
266#define FLAG_COMPRESS 0 /* Signals that output was result of compression. */
267#define FLAG_COPY 1 /* Signals that output was simply copied over. */
268
269/* The 68000 microprocessor (on which this algorithm was originally developed */
270/* is fussy about non-aligned arrays of words. To avoid these problems the */
271/* following macro can be used to "waste" from 0 to 3 bytes so as to align */
272/* the argument pointer. */
273#define ULONG_ALIGN_UP(X) ((((ULONG)X)+sizeof(ULONG)-1)&~(sizeof(ULONG)-1))
274
275
276/* The following constant defines the maximum length of an uncompressed item. */
277/* This definition must not be changed; its value is hardwired into the code. */
278/* The longest number of bytes that can be spanned by a single item is 18 */
279/* for the longest copy item. */
280#define MAX_RAW_ITEM (18)
281
282/* The following constant defines the maximum length of an uncompressed group.*/
283/* This definition must not be changed; its value is hardwired into the code. */
284/* A group contains at most 16 items which explains this definition. */
285#define MAX_RAW_GROUP (16*MAX_RAW_ITEM)
286
287/* The following constant defines the maximum length of a compressed group. */
288/* This definition must not be changed; its value is hardwired into the code. */
289/* A compressed group consists of two control bytes followed by up to 16 */
290/* compressed items each of which can have a maximum length of two bytes. */
291#define MAX_CMP_GROUP (2+16*2)
292
293/* The following constant defines the number of entries in the hash table. */
294/* This definition must not be changed; its value is hardwired into the code. */
295#define HASH_TABLE_LENGTH (4096)
296
297/* LZRW3, unlike LZRW1(-A), must initialize its hash table so as to enable */
298/* the compressor and decompressor to stay in step maintaining identical hash */
299/* tables. In an early version of the algorithm, the tables were simply */
300/* initialized to zero and a check for zero was included just before the */
301/* matching code. However, this test costs time. A better solution is to */
302/* initialize all the entries in the hash table to point to a constant */
303/* string. The decompressor does the same. This solution requires no extra */
304/* test. The contents of the string do not matter so long as the string is */
305/* the same for the compressor and decompressor and contains at least */
306/* MAX_RAW_ITEM bytes. I chose consecutive decimal digits because they do not */
307/* have white space problems (e.g. there is no chance that the compiler will */
308/* replace more than one space by a TAB) and because they make the length of */
309/* the string obvious by inspection. */
310#define START_STRING_18 ((UBYTE *) "123456789012345678")
311
312/* In this algorithm, hash values have to be calculated at more than one */
313/* point. The following macro neatens the code up for this. */
314#define HASH(PTR) \
315 (((40543*(((*(PTR))<<8)^((*((PTR)+1))<<4)^(*((PTR)+2))))>>4) & 0xFFF)
316
317/******************************************************************************/
318
319/* Input : Hand over the required amount of working memory in p_wrk_mem. */
320/* Input : Specify input block using p_src_first and src_len. */
321/* Input : Point p_dst_first to the start of the output zone (OZ). */
322/* Input : Point p_dst_len to a ULONG to receive the output length. */
323/* Input : Input block and output zone must not overlap. */
324/* Output : Length of output block written to *p_dst_len. */
325/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. May */
326/* Output : write in OZ=Mem[p_dst_first..p_dst_first+src_len+MAX_CMP_GROUP-1].*/
327/* Output : Upon completion guaranteed *p_dst_len<=src_len+FLAG_BYTES. */
328LOCAL void compress_compress(UBYTE *p_wrk_mem,
329 UBYTE *p_src_first, ULONG src_len,
330 UBYTE *p_dst_first, LONG *p_dst_len)
331{
332 /* p_src and p_dst step through the source and destination blocks. */
333 register UBYTE *p_src = p_src_first;
334 register UBYTE *p_dst = p_dst_first;
335
336 /* The following variables are never modified and are used in the */
337 /* calculations that determine when the main loop terminates. */
338 UBYTE *p_src_post = p_src_first+src_len;
339 UBYTE *p_dst_post = p_dst_first+src_len;
340 UBYTE *p_src_max1 = p_src_first+src_len-MAX_RAW_ITEM;
341 UBYTE *p_src_max16 = p_src_first+src_len-MAX_RAW_ITEM*16;
342
343 /* The variables 'p_control' and 'control' are used to buffer control bits. */
344 /* Before each group is processed, the next two bytes of the output block */
345 /* are set aside for the control word for the group about to be processed. */
346 /* 'p_control' is set to point to the first byte of that word. Meanwhile, */
347 /* 'control' buffers the control bits being generated during the processing */
348 /* of the group. Instead of having a counter to keep track of how many items */
349 /* have been processed (=the number of bits in the control word), at the */
350 /* start of each group, the top word of 'control' is filled with 1 bits. */
351 /* As 'control' is shifted for each item, the 1 bits in the top word are */
352 /* absorbed or destroyed. When they all run out (i.e. when the top word is */
353 /* all zero bits, we know that we are at the end of a group. */
354# define TOPWORD 0xFFFF0000
355 UBYTE *p_control;
356 register ULONG control=TOPWORD;
357
358 /* THe variable 'hash' always points to the first element of the hash table. */
359 UBYTE **hash= (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem);
360
361 /* The following two variables represent the literal buffer. p_h1 points to */
362 /* the hash table entry corresponding to the youngest literal. p_h2 points */
363 /* to the hash table entry corresponding to the second youngest literal. */
364 /* Note: p_h1=0=>p_h2=0 because zero values denote absence of a pending */
365 /* literal. The variables are initialized to zero meaning an empty "buffer". */
366 UBYTE **p_h1=NULL;
367 UBYTE **p_h2=NULL;
368
369 /* To start, we write the flag bytes. Being optimistic, we set the flag to */
370 /* FLAG_COMPRESS. The remaining flag bytes are zeroed so as to keep the */
371 /* algorithm deterministic. */
372 *p_dst++=FLAG_COMPRESS;
373 {UWORD i; for (i=2;i<=FLAG_BYTES;i++) *p_dst++=0;}
374
375 /* Reserve the first word of output as the control word for the first group. */
376 /* Note: This is undone at the end if the input block is empty. */
377 p_control=p_dst; p_dst+=2;
378
379 /* Initialize all elements of the hash table to point to a constant string. */
380 /* Use of an unrolled loop speeds this up considerably. */
381 {UWORD i; UBYTE **p_h=hash;
382# define ZH *p_h++=START_STRING_18
383 for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */
384 {ZH;ZH;ZH;ZH;
385 ZH;ZH;ZH;ZH;
386 ZH;ZH;ZH;ZH;
387 ZH;ZH;ZH;ZH;}
388 }
389
390 /* The main loop processes either 1 or 16 items per iteration. As its */
391 /* termination logic is complicated, I have opted for an infinite loop */
392 /* structure containing 'break' and 'goto' statements. */
393 while (TRUE)
394 {/* Begin main processing loop. */
395
396 /* Note: All the variables here except unroll should be defined within */
397 /* the inner loop. Unfortunately the loop hasn't got a block. */
398 register UBYTE *p; /* Scans through targ phrase during matching. */
399 register UBYTE *p_ziv= NULL ; /* Points to first byte of current Ziv. */
400 register UWORD unroll; /* Loop counter for unrolled inner loop. */
401 register UWORD index; /* Index of current hash table entry. */
402 register UBYTE **p_h0 = NULL ; /* Pointer to current hash table entry. */
403
404 /* Test for overrun and jump to overrun code if necessary. */
405 if (p_dst>p_dst_post)
406 goto overrun;
407
408 /* The following cascade of if statements efficiently catches and deals */
409 /* with varying degrees of closeness to the end of the input block. */
410 /* When we get very close to the end, we stop updating the table and */
411 /* code the remaining bytes as literals. This makes the code simpler. */
412 unroll=16;
413 if (p_src>p_src_max16)
414 {
415 unroll=1;
416 if (p_src>p_src_max1)
417 {
418 if (p_src==p_src_post)
419 break;
420 else
421 goto literal;
422 }
423 }
424
425 /* This inner unrolled loop processes 'unroll' (whose value is either 1 */
426 /* or 16) items. I have chosen to implement this loop with labels and */
427 /* gotos to heighten the ease with which the loop may be implemented with */
428 /* a single decrement and branch instruction in assembly language and */
429 /* also because the labels act as highly readable place markers. */
430 /* (Also because we jump into the loop for endgame literals (see above)). */
431
432 begin_unrolled_loop:
433
434 /* To process the next phrase, we hash the next three bytes and use */
435 /* the resultant hash table index to look up the hash table. A pointer */
436 /* to the entry is stored in p_h0 so as to avoid an array lookup. The */
437 /* hash table entry *p_h0 is looked up yielding a pointer p to a */
438 /* potential match of the Ziv in the history. */
439 index=HASH(p_src);
440 p_h0=&hash[index];
441 p=*p_h0;
442
443 /* Having looked up the candidate position, we are in a position to */
444 /* attempt a match. The match loop has been unrolled using the PS */
445 /* macro so that failure within the first three bytes automatically */
446 /* results in the literal branch being taken. The coding is simple. */
447 /* p_ziv saves p_src so we can let p_src wander. */
448# define PS *p++!=*p_src++
449 p_ziv=p_src;
450 if (PS || PS || PS)
451 {
452 /* Literal. */
453
454 /* Code the literal byte as itself and a zero control bit. */
455 p_src=p_ziv; literal: *p_dst++=*p_src++; control&=0xFFFEFFFF;
456
457 /* We have just coded a literal. If we had two pending ones, that */
458 /* makes three and we can update the hash table. */
459 if (p_h2!=0)
460 {*p_h2=p_ziv-2;}
461
462 /* In any case, rotate the hash table pointers for next time. */
463 p_h2=p_h1; p_h1=p_h0;
464
465 }
466 else
467 {
468 /* Copy */
469
470 /* Match up to 15 remaining bytes using an unrolled loop and code. */
471#if 0
472 PS || PS || PS || PS || PS || PS || PS || PS ||
473 PS || PS || PS || PS || PS || PS || PS || p_src++;
474#else
475 if (
476 !( PS || PS || PS || PS || PS || PS || PS || PS ||
477 PS || PS || PS || PS || PS || PS || PS )
478 ) p_src++;
479#endif
480 *p_dst++=((index&0xF00)>>4)|(--p_src-p_ziv-3);
481 *p_dst++=index&0xFF;
482
483 /* As we have just coded three bytes, we are now in a position to */
484 /* update the hash table with the literal bytes that were pending */
485 /* upon the arrival of extra context bytes. */
486 if (p_h1!=0)
487 {
488 if (p_h2)
489 {*p_h2=p_ziv-2; p_h2=NULL;}
490 *p_h1=p_ziv-1; p_h1=NULL;
491 }
492
493 /* In any case, we can update the hash table based on the current */
494 /* position as we just coded at least three bytes in a copy items. */
495 *p_h0=p_ziv;
496
497 }
498 control>>=1;
499
500 /* This loop is all set up for a decrement and jump instruction! */
501#ifndef linux
502` end_unrolled_loop: if (--unroll) goto begin_unrolled_loop;
503#else
504 /* end_unrolled_loop: */ if (--unroll) goto begin_unrolled_loop;
505#endif
506
507 /* At this point it will nearly always be the end of a group in which */
508 /* case, we have to do some control-word processing. However, near the */
509 /* end of the input block, the inner unrolled loop is only executed once. */
510 /* This necessitates the 'if' test. */
511 if ((control&TOPWORD)==0)
512 {
513 /* Write the control word to the place we saved for it in the output. */
514 *p_control++= control &0xFF;
515 *p_control = (control>>8) &0xFF;
516
517 /* Reserve the next word in the output block for the control word */
518 /* for the group about to be processed. */
519 p_control=p_dst; p_dst+=2;
520
521 /* Reset the control bits buffer. */
522 control=TOPWORD;
523 }
524
525 } /* End main processing loop. */
526
527 /* After the main processing loop has executed, all the input bytes have */
528 /* been processed. However, the control word has still to be written to the */
529 /* word reserved for it in the output at the start of the most recent group. */
530 /* Before writing, the control word has to be shifted so that all the bits */
531 /* are in the right place. The "empty" bit positions are filled with 1s */
532 /* which partially fill the top word. */
533 while(control&TOPWORD) control>>=1;
534 *p_control++= control &0xFF;
535 *p_control++=(control>>8) &0xFF;
536
537 /* If the last group contained no items, delete the control word too. */
538 if (p_control==p_dst) p_dst-=2;
539
540 /* Write the length of the output block to the dst_len parameter and return. */
541 *p_dst_len=p_dst-p_dst_first;
542 return;
543
544 /* Jump here as soon as an overrun is detected. An overrun is defined to */
545 /* have occurred if p_dst>p_dst_first+src_len. That is, the moment the */
546 /* length of the output written so far exceeds the length of the input block.*/
547 /* The algorithm checks for overruns at least at the end of each group */
548 /* which means that the maximum overrun is MAX_CMP_GROUP bytes. */
549 /* Once an overrun occurs, the only thing to do is to set the copy flag and */
550 /* copy the input over. */
551 overrun:
552#if 0
553 *p_dst_first=FLAG_COPY;
554 fast_copy(p_src_first,p_dst_first+FLAG_BYTES,src_len);
555 *p_dst_len=src_len+FLAG_BYTES;
556#else
557 fast_copy(p_src_first,p_dst_first,src_len);
558 *p_dst_len= -src_len; /* return a negative number to indicate uncompressed data */
559#endif
560}
561
562/******************************************************************************/
563
564/* Input : Hand over the required amount of working memory in p_wrk_mem. */
565/* Input : Specify input block using p_src_first and src_len. */
566/* Input : Point p_dst_first to the start of the output zone. */
567/* Input : Point p_dst_len to a ULONG to receive the output length. */
568/* Input : Input block and output zone must not overlap. User knows */
569/* Input : upperbound on output block length from earlier compression. */
570/* Input : In any case, maximum expansion possible is nine times. */
571/* Output : Length of output block written to *p_dst_len. */
572/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */
573/* Output : Writes only in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */
574LOCAL void compress_decompress( UBYTE *p_wrk_mem,
575 UBYTE *p_src_first, LONG src_len,
576 UBYTE *p_dst_first, ULONG *p_dst_len)
577{
578 /* Byte pointers p_src and p_dst scan through the input and output blocks. */
579 register UBYTE *p_src = p_src_first+FLAG_BYTES;
580 register UBYTE *p_dst = p_dst_first;
581 /* we need to avoid a SEGV when trying to uncompress corrupt data */
582 register UBYTE *p_dst_post = p_dst_first + *p_dst_len;
583
584 /* The following two variables are never modified and are used to control */
585 /* the main loop. */
586 UBYTE *p_src_post = p_src_first+src_len;
587 UBYTE *p_src_max16 = p_src_first+src_len-(MAX_CMP_GROUP-2);
588
589 /* The hash table is the only resident of the working memory. The hash table */
590 /* contains HASH_TABLE_LENGTH=4096 pointers to positions in the history. To */
591 /* keep Macintoshes happy, it is longword aligned. */
592 UBYTE **hash = (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem);
593
594 /* The variable 'control' is used to buffer the control bits which appear in */
595 /* groups of 16 bits (control words) at the start of each compressed group. */
596 /* When each group is read, bit 16 of the register is set to one. Whenever */
597 /* a new bit is needed, the register is shifted right. When the value of the */
598 /* register becomes 1, we know that we have reached the end of a group. */
599 /* Initializing the register to 1 thus instructs the code to follow that it */
600 /* should read a new control word immediately. */
601 register ULONG control=1;
602
603 /* The value of 'literals' is always in the range 0..3. It is the number of */
604 /* consecutive literal items just seen. We have to record this number so as */
605 /* to know when to update the hash table. When literals gets to 3, there */
606 /* have been three consecutive literals and we can update at the position of */
607 /* the oldest of the three. */
608 register UWORD literals=0;
609
610 /* Check the leading copy flag to see if the compressor chose to use a copy */
611 /* operation instead of a compression operation. If a copy operation was */
612 /* used, then all we need to do is copy the data over, set the output length */
613 /* and return. */
614#if 0
615 if (*p_src_first==FLAG_COPY)
616 {
617 fast_copy(p_src_first+FLAG_BYTES,p_dst_first,src_len-FLAG_BYTES);
618 *p_dst_len=src_len-FLAG_BYTES;
619 return;
620 }
621#else
622 if ( src_len < 0 )
623 {
624 fast_copy(p_src_first,p_dst_first,-src_len );
625 *p_dst_len = (ULONG)-src_len;
626 return;
627 }
628#endif
629
630 /* Initialize all elements of the hash table to point to a constant string. */
631 /* Use of an unrolled loop speeds this up considerably. */
632 {UWORD i; UBYTE **p_h=hash;
633# define ZJ *p_h++=START_STRING_18
634 for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */
635 {ZJ;ZJ;ZJ;ZJ;
636 ZJ;ZJ;ZJ;ZJ;
637 ZJ;ZJ;ZJ;ZJ;
638 ZJ;ZJ;ZJ;ZJ;}
639 }
640
641 /* The outer loop processes either 1 or 16 items per iteration depending on */
642 /* how close p_src is to the end of the input block. */
643 while (p_src!=p_src_post)
644 {/* Start of outer loop */
645
646 register UWORD unroll; /* Counts unrolled loop executions. */
647
648 /* When 'control' has the value 1, it means that the 16 buffered control */
649 /* bits that were read in at the start of the current group have all been */
650 /* shifted out and that all that is left is the 1 bit that was injected */
651 /* into bit 16 at the start of the current group. When we reach the end */
652 /* of a group, we have to load a new control word and inject a new 1 bit. */
653 if (control==1)
654 {
655 control=0x10000|*p_src++;
656 control|=(*p_src++)<<8;
657 }
658
659 /* If it is possible that we are within 16 groups from the end of the */
660 /* input, execute the unrolled loop only once, else process a whole group */
661 /* of 16 items by looping 16 times. */
662 unroll= p_src<=p_src_max16 ? 16 : 1;
663
664 /* This inner loop processes one phrase (item) per iteration. */
665 while (unroll--)
666 { /* Begin unrolled inner loop. */
667
668 /* Process a literal or copy item depending on the next control bit. */
669 if (control&1)
670 {
671 /* Copy item. */
672
673 register UBYTE *p; /* Points to place from which to copy. */
674 register UWORD lenmt; /* Length of copy item minus three. */
675 register UBYTE **p_hte; /* Pointer to current hash table entry.*/
676 register UBYTE *p_ziv=p_dst; /* Pointer to start of current Ziv. */
677
678 /* Read and dismantle the copy word. Work out from where to copy. */
679 lenmt=*p_src++;
680 p_hte=&hash[((lenmt&0xF0)<<4)|*p_src++];
681 p=*p_hte;
682 lenmt&=0xF;
683
684 /* Now perform the copy using a half unrolled loop. */
685 *p_dst++=*p++;
686 *p_dst++=*p++;
687 *p_dst++=*p++;
688 while (lenmt--)
689 *p_dst++=*p++;
690
691 /* Because we have just received 3 or more bytes in a copy item */
692 /* (whose bytes we have just installed in the output), we are now */
693 /* in a position to flush all the pending literal hashings that had */
694 /* been postponed for lack of bytes. */
695 if (literals>0)
696 {
697 register UBYTE *r=p_ziv-literals;
698 hash[HASH(r)]=r;
699 if (literals==2)
700 {r++; hash[HASH(r)]=r;}
701 literals=0;
702 }
703
704 /* In any case, we can immediately update the hash table with the */
705 /* current position. We don't need to do a HASH(...) to work out */
706 /* where to put the pointer, as the compressor just told us!!! */
707 *p_hte=p_ziv;
708
709 }
710 else
711 {
712 /* Literal item. */
713
714 /* Copy over the literal byte. */
715 *p_dst++=*p_src++;
716
717 /* If we now have three literals waiting to be hashed into the hash */
718 /* table, we can do one of them now (because there are three). */
719 if (++literals == 3)
720 {register UBYTE *p=p_dst-3; hash[HASH(p)]=p; literals=2;}
721 }
722
723 /* Shift the control buffer so the next control bit is in bit 0. */
724 control>>=1;
725#if 1
726 if (p_dst > p_dst_post)
727 {
728 /* Shit: we tried to decompress corrupt data */
729 *p_dst_len = 0;
730 return;
731 }
732#endif
733 } /* End unrolled inner loop. */
734
735 } /* End of outer loop */
736
737 /* Write the length of the decompressed data before returning. */
738 *p_dst_len=p_dst-p_dst_first;
739}
740
741/******************************************************************************/
742/* End of LZRW3.C */
743/******************************************************************************/
diff --git a/drivers/char/ftape/compressor/lzrw3.h b/drivers/char/ftape/compressor/lzrw3.h
deleted file mode 100644
index 533feba47526..000000000000
--- a/drivers/char/ftape/compressor/lzrw3.h
+++ /dev/null
@@ -1,253 +0,0 @@
1#ifndef _LZRW3_H
2#define _LZRW3_H
3/*
4 * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.h,v $
5 * $Revision: 1.1 $
6 * $Date: 1997/10/05 19:12:30 $
7 *
8 * include files for lzrw3. Only slighty modified from the original
9 * version. Assembles the three include files compress.h, port.h and
10 * fastcopy.h from the original lzrw3 package.
11 *
12 */
13
14#include <linux/types.h>
15#include <linux/string.h>
16
17/******************************************************************************/
18/* */
19/* COMPRESS.H */
20/* */
21/******************************************************************************/
22/* */
23/* Author : Ross Williams. */
24/* Date : December 1989. */
25/* */
26/* This header file defines the interface to a set of functions called */
27/* 'compress', each member of which implements a particular data compression */
28/* algorithm. */
29/* */
30/* Normally in C programming, for each .H file, there is a corresponding .C */
31/* file that implements the functions promised in the .H file. */
32/* Here, there are many .C files corresponding to this header file. */
33/* Each comforming implementation file contains a single function */
34/* called 'compress' that implements a single data compression */
35/* algorithm that conforms with the interface specified in this header file. */
36/* Only one algorithm can be linked in at a time in this organization. */
37/* */
38/******************************************************************************/
39/* */
40/* DEFINITION OF FUNCTION COMPRESS */
41/* =============================== */
42/* */
43/* Summary of Function Compress */
44/* ---------------------------- */
45/* The action that 'compress' takes depends on its first argument called */
46/* 'action'. The function provides three actions: */
47/* */
48/* - Return information about the algorithm. */
49/* - Compress a block of memory. */
50/* - Decompress a block of memory. */
51/* */
52/* Parameters */
53/* ---------- */
54/* See the formal C definition later for a description of the parameters. */
55/* */
56/* Constants */
57/* --------- */
58/* COMPRESS_OVERRUN: The constant COMPRESS_OVERRUN defines by how many bytes */
59/* an algorithm is allowed to expand a block during a compression operation. */
60/* */
61/* Although compression algorithms usually compress data, there will always */
62/* be data that a given compressor will expand (this can be proven). */
63/* Fortunately, the degree of expansion can be limited to a single bit, by */
64/* copying over the input data if the data gets bigger during compression. */
65/* To allow for this possibility, the first bit of a compressed */
66/* representation can be used as a flag indicating whether the */
67/* input data was copied over, or truly compressed. In practice, the first */
68/* byte would be used to store this bit so as to maintain byte alignment. */
69/* */
70/* Unfortunately, in general, the only way to tell if an algorithm will */
71/* expand a particular block of data is to run the algorithm on the data. */
72/* If the algorithm does not continuously monitor how many output bytes it */
73/* has written, it might write an output block far larger than the input */
74/* block before realizing that it has done so. */
75/* On the other hand, continuous checks on output length are inefficient. */
76/* */
77/* To cater for all these problems, this interface definition: */
78/* > Allows a compression algorithm to return an output block that is up to */
79/* COMPRESS_OVERRUN bytes longer than the input block. */
80/* > Allows a compression algorithm to write up to COMPRESS_OVERRUN bytes */
81/* more than the length of the input block to the memory of the output */
82/* block regardless of the length of the output block eventually returned. */
83/* This allows an algorithm to overrun the length of the input block in the */
84/* output block by up to COMPRESS_OVERRUN bytes between expansion checks. */
85/* */
86/* The problem does not arise for decompression. */
87/* */
88/* Identity Action */
89/* --------------- */
90/* > action must be COMPRESS_ACTION_IDENTITY. */
91/* > p_dst_len must point to a longword to receive a longword address. */
92/* > The value of the other parameters does not matter. */
93/* > After execution, the longword that p_dst_len points to will be a pointer */
94/* to a structure of type compress_identity. */
95/* Thus, for example, after the call, (*p_dst_len)->memory will return the */
96/* number of bytes of working memory that the algorithm requires to run. */
97/* > The values of the identity structure returned are fixed constant */
98/* attributes of the algorithm and must not vary from call to call. */
99/* */
100/* Common Requirements for Compression and Decompression Actions */
101/* ------------------------------------------------------------- */
102/* > wrk_mem must point to an unused block of memory of a length specified in */
103/* the algorithm's identity block. The identity block can be obtained by */
104/* making a separate call to compress, specifying the identity action. */
105/* > The INPUT BLOCK is defined to be Memory[src_addr,src_addr+src_len-1]. */
106/* > dst_len will be used to denote *p_dst_len. */
107/* > dst_len is not read by compress, only written. */
108/* > The value of dst_len is defined only upon termination. */
109/* > The OUTPUT BLOCK is defined to be Memory[dst_addr,dst_addr+dst_len-1]. */
110/* */
111/* Compression Action */
112/* ------------------ */
113/* > action must be COMPRESS_ACTION_COMPRESS. */
114/* > src_len must be in the range [0,COMPRESS_MAX_ORG]. */
115/* > The OUTPUT ZONE is defined to be */
116/* Memory[dst_addr,dst_addr+src_len-1+COMPRESS_OVERRUN]. */
117/* > The function can modify any part of the output zone regardless of the */
118/* final length of the output block. */
119/* > The input block and the output zone must not overlap. */
120/* > dst_len will be in the range [0,src_len+COMPRESS_OVERRUN]. */
121/* > dst_len will be in the range [0,COMPRESS_MAX_COM] (from prev fact). */
122/* > The output block will consist of a representation of the input block. */
123/* */
124/* Decompression Action */
125/* -------------------- */
126/* > action must be COMPRESS_ACTION_DECOMPRESS. */
127/* > The input block must be the result of an earlier compression operation. */
128/* > If the previous fact is true, the following facts must also be true: */
129/* > src_len will be in the range [0,COMPRESS_MAX_COM]. */
130/* > dst_len will be in the range [0,COMPRESS_MAX_ORG]. */
131/* > The input and output blocks must not overlap. */
132/* > Only the output block is modified. */
133/* > Upon termination, the output block will consist of the bytes contained */
134/* in the input block passed to the earlier compression operation. */
135/* */
136/******************************************************************************/
137
138/******************************************************************************/
139/* */
140/* PORT.H */
141/* */
142/******************************************************************************/
143/* */
144/* This module contains macro definitions and types that are likely to */
145/* change between computers. */
146/* */
147/******************************************************************************/
148
149#ifndef DONE_PORT /* Only do this if not previously done. */
150
151 #ifdef THINK_C
152 #define UBYTE unsigned char /* Unsigned byte */
153 #define UWORD unsigned int /* Unsigned word (2 bytes) */
154 #define ULONG unsigned long /* Unsigned word (4 bytes) */
155 #define BOOL unsigned char /* Boolean */
156 #define FOPEN_BINARY_READ "rb" /* Mode string for binary reading. */
157 #define FOPEN_BINARY_WRITE "wb" /* Mode string for binary writing. */
158 #define FOPEN_TEXT_APPEND "a" /* Mode string for text appending. */
159 #define REAL double /* USed for floating point stuff. */
160 #endif
161 #if defined(LINUX) || defined(linux)
162 #define UBYTE __u8 /* Unsigned byte */
163 #define UWORD __u16 /* Unsigned word (2 bytes) */
164 #define ULONG __u32 /* Unsigned word (4 bytes) */
165 #define LONG __s32 /* Signed word (4 bytes) */
166 #define BOOL is not used here /* Boolean */
167 #define FOPEN_BINARY_READ not used /* Mode string for binary reading. */
168 #define FOPEN_BINARY_WRITE not used /* Mode string for binary writing. */
169 #define FOPEN_TEXT_APPEND not used /* Mode string for text appending. */
170 #define REAL not used /* USed for floating point stuff. */
171 #ifndef TRUE
172 #define TRUE 1
173 #endif
174 #endif
175
176 #define DONE_PORT /* Don't do all this again. */
177 #define MALLOC_FAIL NULL /* Failure status from malloc() */
178 #define LOCAL static /* For non-exported routines. */
179 #define EXPORT /* Signals exported function. */
180 #define then /* Useful for aligning ifs. */
181
182#endif
183
184/******************************************************************************/
185/* End of PORT.H */
186/******************************************************************************/
187
188#define COMPRESS_ACTION_IDENTITY 0
189#define COMPRESS_ACTION_COMPRESS 1
190#define COMPRESS_ACTION_DECOMPRESS 2
191
192#define COMPRESS_OVERRUN 1024
193#define COMPRESS_MAX_COM 0x70000000
194#define COMPRESS_MAX_ORG (COMPRESS_MAX_COM-COMPRESS_OVERRUN)
195
196#define COMPRESS_MAX_STRLEN 255
197
198/* The following structure provides information about the algorithm. */
199/* > The top bit of id must be zero. The remaining bits must be chosen by */
200/* the author of the algorithm by tossing a coin 31 times. */
201/* > The amount of memory requested by the algorithm is specified in bytes */
202/* and must be in the range [0,0x70000000]. */
203/* > All strings s must be such that strlen(s)<=COMPRESS_MAX_STRLEN. */
204struct compress_identity
205 {
206 ULONG id; /* Identifying number of algorithm. */
207 ULONG memory; /* Number of bytes of working memory required. */
208
209 char *name; /* Name of algorithm. */
210 char *version; /* Version number. */
211 char *date; /* Date of release of this version. */
212 char *copyright; /* Copyright message. */
213
214 char *author; /* Author of algorithm. */
215 char *affiliation; /* Affiliation of author. */
216 char *vendor; /* Where the algorithm can be obtained. */
217 };
218
219void lzrw3_compress( /* Single function interface to compression algorithm. */
220UWORD action, /* Action to be performed. */
221UBYTE *wrk_mem, /* Working memory temporarily given to routine to use. */
222UBYTE *src_adr, /* Address of input data. */
223LONG src_len, /* Length of input data. */
224UBYTE *dst_adr, /* Address of output data. */
225void *p_dst_len /* Pointer to a longword where routine will write: */
226 /* If action=..IDENTITY => Adr of id structure. */
227 /* If action=..COMPRESS => Length of output data. */
228 /* If action=..DECOMPRESS => Length of output data. */
229);
230
231/******************************************************************************/
232/* End of COMPRESS.H */
233/******************************************************************************/
234
235
236/******************************************************************************/
237/* fast_copy.h */
238/******************************************************************************/
239
240/* This function copies a block of memory very quickly. */
241/* The exact speed depends on the relative alignment of the blocks of memory. */
242/* PRE : 0<=src_len<=(2^32)-1 . */
243/* PRE : Source and destination blocks must not overlap. */
244/* POST : MEM[dst_adr,dst_adr+src_len-1]=MEM[src_adr,src_adr+src_len-1]. */
245/* POST : MEM[dst_adr,dst_adr+src_len-1] is the only memory changed. */
246
247#define fast_copy(src,dst,len) memcpy(dst,src,len)
248
249/******************************************************************************/
250/* End of fast_copy.h */
251/******************************************************************************/
252
253#endif
diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c
deleted file mode 100644
index 65ffc0be3df9..000000000000
--- a/drivers/char/ftape/compressor/zftape-compress.c
+++ /dev/null
@@ -1,1203 +0,0 @@
1/*
2 * Copyright (C) 1994-1997 Claus-Justus Heine
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2, or (at
7 your option) any later version.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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,
17 USA.
18
19 *
20 * This file implements a "generic" interface between the *
21 * zftape-driver and a compression-algorithm. The *
22 * compression-algorithm currently used is a LZ77. I use the *
23 * implementation lzrw3 by Ross N. Williams (Renaissance *
24 * Software). The compression program itself is in the file
25 * lzrw3.c * and lzrw3.h. To adopt another compression algorithm
26 * the functions * zft_compress() and zft_uncompress() must be
27 * changed * appropriately. See below.
28 */
29
30#include <linux/errno.h>
31#include <linux/mm.h>
32#include <linux/module.h>
33
34#include <linux/zftape.h>
35
36#include <asm/uaccess.h>
37
38#include "../zftape/zftape-init.h"
39#include "../zftape/zftape-eof.h"
40#include "../zftape/zftape-ctl.h"
41#include "../zftape/zftape-write.h"
42#include "../zftape/zftape-read.h"
43#include "../zftape/zftape-rw.h"
44#include "../compressor/zftape-compress.h"
45#include "../zftape/zftape-vtbl.h"
46#include "../compressor/lzrw3.h"
47
48/*
49 * global variables
50 */
51
52/* I handle the allocation of this buffer as a special case, because
53 * it's size varies depending on the tape length inserted.
54 */
55
56/* local variables
57 */
58static void *zftc_wrk_mem = NULL;
59static __u8 *zftc_buf = NULL;
60static void *zftc_scratch_buf = NULL;
61
62/* compression statistics
63 */
64static unsigned int zftc_wr_uncompressed = 0;
65static unsigned int zftc_wr_compressed = 0;
66static unsigned int zftc_rd_uncompressed = 0;
67static unsigned int zftc_rd_compressed = 0;
68
69/* forward */
70static int zftc_write(int *write_cnt,
71 __u8 *dst_buf, const int seg_sz,
72 const __u8 __user *src_buf, const int req_len,
73 const zft_position *pos, const zft_volinfo *volume);
74static int zftc_read(int *read_cnt,
75 __u8 __user *dst_buf, const int to_do,
76 const __u8 *src_buf, const int seg_sz,
77 const zft_position *pos, const zft_volinfo *volume);
78static int zftc_seek(unsigned int new_block_pos,
79 zft_position *pos, const zft_volinfo *volume,
80 __u8 *buffer);
81static void zftc_lock (void);
82static void zftc_reset (void);
83static void zftc_cleanup(void);
84static void zftc_stats (void);
85
86/* compressed segment. This conforms to QIC-80-MC, Revision K.
87 *
88 * Rev. K applies to tapes with `fixed length format' which is
89 * indicated by format code 2,3 and 5. See below for format code 4 and 6
90 *
91 * 2 bytes: offset of compression segment structure
92 * 29k > offset >= 29k-18: data from previous segment ens in this
93 * segment and no compressed block starts
94 * in this segment
95 * offset == 0: data from previous segment occupies entire
96 * segment and continues in next segment
97 * n bytes: remainder from previous segment
98 *
99 * Rev. K:
100 * 4 bytes: 4 bytes: files set byte offset
101 * Post Rev. K and QIC-3020/3020:
102 * 8 bytes: 8 bytes: files set byte offset
103 * 2 bytes: byte count N (amount of data following)
104 * bit 15 is set if data is compressed, bit 15 is not
105 * set if data is uncompressed
106 * N bytes: data (as much as specified in the byte count)
107 * 2 bytes: byte count N_1 of next cluster
108 * N_1 bytes: data of next cluset
109 * 2 bytes: byte count N_2 of next cluster
110 * N_2 bytes: ...
111 *
112 * Note that the `N' byte count accounts only for the bytes that in the
113 * current segment if the cluster spans to the next segment.
114 */
115
116typedef struct
117{
118 int cmpr_pos; /* actual position in compression buffer */
119 int cmpr_sz; /* what is left in the compression buffer
120 * when copying the compressed data to the
121 * deblock buffer
122 */
123 unsigned int first_block; /* location of header information in
124 * this segment
125 */
126 unsigned int count; /* amount of data of current block
127 * contained in current segment
128 */
129 unsigned int offset; /* offset in current segment */
130 unsigned int spans:1; /* might continue in next segment */
131 unsigned int uncmpr; /* 0x8000 if this block contains
132 * uncompressed data
133 */
134 __s64 foffs; /* file set byte offset, same as in
135 * compression map segment
136 */
137} cmpr_info;
138
139static cmpr_info cseg; /* static data. Must be kept uptodate and shared by
140 * read, write and seek functions
141 */
142
143#define DUMP_CMPR_INFO(level, msg, info) \
144 TRACE(level, msg "\n" \
145 KERN_INFO "cmpr_pos : %d\n" \
146 KERN_INFO "cmpr_sz : %d\n" \
147 KERN_INFO "first_block: %d\n" \
148 KERN_INFO "count : %d\n" \
149 KERN_INFO "offset : %d\n" \
150 KERN_INFO "spans : %d\n" \
151 KERN_INFO "uncmpr : 0x%04x\n" \
152 KERN_INFO "foffs : " LL_X, \
153 (info)->cmpr_pos, (info)->cmpr_sz, (info)->first_block, \
154 (info)->count, (info)->offset, (info)->spans == 1, \
155 (info)->uncmpr, LL((info)->foffs))
156
157/* dispatch compression segment info, return error code
158 *
159 * afterwards, cseg->offset points to start of data of the NEXT
160 * compressed block, and cseg->count contains the amount of data
161 * left in the actual compressed block. cseg->spans is set to 1 if
162 * the block is continued in the following segment. Otherwise it is
163 * set to 0.
164 */
165static int get_cseg (cmpr_info *cinfo, const __u8 *buff,
166 const unsigned int seg_sz,
167 const zft_volinfo *volume)
168{
169 TRACE_FUN(ft_t_flow);
170
171 cinfo->first_block = GET2(buff, 0);
172 if (cinfo->first_block == 0) { /* data spans to next segment */
173 cinfo->count = seg_sz - sizeof(__u16);
174 cinfo->offset = seg_sz;
175 cinfo->spans = 1;
176 } else { /* cluster definetely ends in this segment */
177 if (cinfo->first_block > seg_sz) {
178 /* data corrupted */
179 TRACE_ABORT(-EIO, ft_t_err, "corrupted data:\n"
180 KERN_INFO "segment size: %d\n"
181 KERN_INFO "first block : %d",
182 seg_sz, cinfo->first_block);
183 }
184 cinfo->count = cinfo->first_block - sizeof(__u16);
185 cinfo->offset = cinfo->first_block;
186 cinfo->spans = 0;
187 }
188 /* now get the offset the first block should have in the
189 * uncompressed data stream.
190 *
191 * For this magic `18' refer to CRF-3 standard or QIC-80MC,
192 * Rev. K.
193 */
194 if ((seg_sz - cinfo->offset) > 18) {
195 if (volume->qic113) { /* > revision K */
196 TRACE(ft_t_data_flow, "New QIC-113 compliance");
197 cinfo->foffs = GET8(buff, cinfo->offset);
198 cinfo->offset += sizeof(__s64);
199 } else {
200 TRACE(/* ft_t_data_flow */ ft_t_noise, "pre QIC-113 version");
201 cinfo->foffs = (__s64)GET4(buff, cinfo->offset);
202 cinfo->offset += sizeof(__u32);
203 }
204 }
205 if (cinfo->foffs > volume->size) {
206 TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n"
207 KERN_INFO "offset in current volume: %d\n"
208 KERN_INFO "size of current volume : %d",
209 (int)(cinfo->foffs>>10), (int)(volume->size>>10));
210 }
211 if (cinfo->cmpr_pos + cinfo->count > volume->blk_sz) {
212 TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n"
213 KERN_INFO "block size : %d\n"
214 KERN_INFO "data record: %d",
215 volume->blk_sz, cinfo->cmpr_pos + cinfo->count);
216 }
217 DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", cinfo);
218 TRACE_EXIT 0;
219}
220
221/* This one is called, when a new cluster starts in same segment.
222 *
223 * Note: if this is the first cluster in the current segment, we must
224 * not check whether there are more than 18 bytes available because
225 * this have already been done in get_cseg() and there may be less
226 * than 18 bytes available due to header information.
227 *
228 */
229static void get_next_cluster(cmpr_info *cluster, const __u8 *buff,
230 const int seg_sz, const int finish)
231{
232 TRACE_FUN(ft_t_flow);
233
234 if (seg_sz - cluster->offset > 18 || cluster->foffs != 0) {
235 cluster->count = GET2(buff, cluster->offset);
236 cluster->uncmpr = cluster->count & 0x8000;
237 cluster->count -= cluster->uncmpr;
238 cluster->offset += sizeof(__u16);
239 cluster->foffs = 0;
240 if ((cluster->offset + cluster->count) < seg_sz) {
241 cluster->spans = 0;
242 } else if (cluster->offset + cluster->count == seg_sz) {
243 cluster->spans = !finish;
244 } else {
245 /* either an error or a volume written by an
246 * old version. If this is a data error, then we'll
247 * catch it later.
248 */
249 TRACE(ft_t_data_flow, "Either error or old volume");
250 cluster->spans = 1;
251 cluster->count = seg_sz - cluster->offset;
252 }
253 } else {
254 cluster->count = 0;
255 cluster->spans = 0;
256 cluster->foffs = 0;
257 }
258 DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */ , "", cluster);
259 TRACE_EXIT;
260}
261
262static void zftc_lock(void)
263{
264}
265
266/* this function is needed for zftape_reset_position in zftape-io.c
267 */
268static void zftc_reset(void)
269{
270 TRACE_FUN(ft_t_flow);
271
272 memset((void *)&cseg, '\0', sizeof(cseg));
273 zftc_stats();
274 TRACE_EXIT;
275}
276
277static int cmpr_mem_initialized = 0;
278static unsigned int alloc_blksz = 0;
279
280static int zft_allocate_cmpr_mem(unsigned int blksz)
281{
282 TRACE_FUN(ft_t_flow);
283
284 if (cmpr_mem_initialized && blksz == alloc_blksz) {
285 TRACE_EXIT 0;
286 }
287 TRACE_CATCH(zft_vmalloc_once(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE),
288 zftc_cleanup());
289 TRACE_CATCH(zft_vmalloc_always(&zftc_buf, blksz + CMPR_OVERRUN),
290 zftc_cleanup());
291 alloc_blksz = blksz;
292 TRACE_CATCH(zft_vmalloc_always(&zftc_scratch_buf, blksz+CMPR_OVERRUN),
293 zftc_cleanup());
294 cmpr_mem_initialized = 1;
295 TRACE_EXIT 0;
296}
297
298static void zftc_cleanup(void)
299{
300 TRACE_FUN(ft_t_flow);
301
302 zft_vfree(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE);
303 zft_vfree(&zftc_buf, alloc_blksz + CMPR_OVERRUN);
304 zft_vfree(&zftc_scratch_buf, alloc_blksz + CMPR_OVERRUN);
305 cmpr_mem_initialized = alloc_blksz = 0;
306 TRACE_EXIT;
307}
308
309/*****************************************************************************
310 * *
311 * The following two functions "ftape_compress()" and *
312 * "ftape_uncompress()" are the interface to the actual compression *
313 * algorithm (i.e. they are calling the "compress()" function from *
314 * the lzrw3 package for now). These routines could quite easily be *
315 * changed to adopt another compression algorithm instead of lzrw3, *
316 * which currently is used. *
317 * *
318 *****************************************************************************/
319
320/* called by zft_compress_write() to perform the compression. Must
321 * return the size of the compressed data.
322 *
323 * NOTE: The size of the compressed data should not exceed the size of
324 * the uncompressed data. Most compression algorithms have means
325 * to store data unchanged if the "compressed" data amount would
326 * exceed the original one. Mostly this is done by storing some
327 * flag-bytes in front of the compressed data to indicate if it
328 * is compressed or not. Thus the worst compression result
329 * length is the original length plus those flag-bytes.
330 *
331 * We don't want that, as the QIC-80 standard provides a means
332 * of marking uncompressed blocks by simply setting bit 15 of
333 * the compressed block's length. Thus a compessed block can
334 * have at most a length of 2^15-1 bytes. The QIC-80 standard
335 * restricts the block-length even further, allowing only 29k -
336 * 6 bytes.
337 *
338 * Currently, the maximum blocksize used by zftape is 28k.
339 *
340 * In short: don't exceed the length of the input-package, set
341 * bit 15 of the compressed size to 1 if you have copied data
342 * instead of compressing it.
343 */
344static int zft_compress(__u8 *in_buffer, unsigned int in_sz, __u8 *out_buffer)
345{
346 __s32 compressed_sz;
347 TRACE_FUN(ft_t_flow);
348
349
350 lzrw3_compress(COMPRESS_ACTION_COMPRESS, zftc_wrk_mem,
351 in_buffer, in_sz, out_buffer, &compressed_sz);
352 if (TRACE_LEVEL >= ft_t_info) {
353 /* the compiler will optimize this away when
354 * compiled with NO_TRACE_AT_ALL option
355 */
356 TRACE(ft_t_data_flow, "\n"
357 KERN_INFO "before compression: %d bytes\n"
358 KERN_INFO "after compresison : %d bytes",
359 in_sz,
360 (int)(compressed_sz < 0
361 ? -compressed_sz : compressed_sz));
362 /* for statistical purposes
363 */
364 zftc_wr_compressed += (compressed_sz < 0
365 ? -compressed_sz : compressed_sz);
366 zftc_wr_uncompressed += in_sz;
367 }
368 TRACE_EXIT (int)compressed_sz;
369}
370
371/* called by zft_compress_read() to decompress the data. Must
372 * return the size of the decompressed data for sanity checks
373 * (compared with zft_blk_sz)
374 *
375 * NOTE: Read the note for zft_compress() above! If bit 15 of the
376 * parameter in_sz is set, then the data in in_buffer isn't
377 * compressed, which must be handled by the un-compression
378 * algorithm. (I changed lzrw3 to handle this.)
379 *
380 * The parameter max_out_sz is needed to prevent buffer overruns when
381 * uncompressing corrupt data.
382 */
383static unsigned int zft_uncompress(__u8 *in_buffer,
384 int in_sz,
385 __u8 *out_buffer,
386 unsigned int max_out_sz)
387{
388 TRACE_FUN(ft_t_flow);
389
390 lzrw3_compress(COMPRESS_ACTION_DECOMPRESS, zftc_wrk_mem,
391 in_buffer, (__s32)in_sz,
392 out_buffer, (__u32 *)&max_out_sz);
393
394 if (TRACE_LEVEL >= ft_t_info) {
395 TRACE(ft_t_data_flow, "\n"
396 KERN_INFO "before decompression: %d bytes\n"
397 KERN_INFO "after decompression : %d bytes",
398 in_sz < 0 ? -in_sz : in_sz,(int)max_out_sz);
399 /* for statistical purposes
400 */
401 zftc_rd_compressed += in_sz < 0 ? -in_sz : in_sz;
402 zftc_rd_uncompressed += max_out_sz;
403 }
404 TRACE_EXIT (unsigned int)max_out_sz;
405}
406
407/* print some statistics about the efficiency of the compression to
408 * the kernel log
409 */
410static void zftc_stats(void)
411{
412 TRACE_FUN(ft_t_flow);
413
414 if (TRACE_LEVEL < ft_t_info) {
415 TRACE_EXIT;
416 }
417 if (zftc_wr_uncompressed != 0) {
418 if (zftc_wr_compressed > (1<<14)) {
419 TRACE(ft_t_info, "compression statistics (writing):\n"
420 KERN_INFO " compr./uncmpr. : %3d %%",
421 (((zftc_wr_compressed>>10) * 100)
422 / (zftc_wr_uncompressed>>10)));
423 } else {
424 TRACE(ft_t_info, "compression statistics (writing):\n"
425 KERN_INFO " compr./uncmpr. : %3d %%",
426 ((zftc_wr_compressed * 100)
427 / zftc_wr_uncompressed));
428 }
429 }
430 if (zftc_rd_uncompressed != 0) {
431 if (zftc_rd_compressed > (1<<14)) {
432 TRACE(ft_t_info, "compression statistics (reading):\n"
433 KERN_INFO " compr./uncmpr. : %3d %%",
434 (((zftc_rd_compressed>>10) * 100)
435 / (zftc_rd_uncompressed>>10)));
436 } else {
437 TRACE(ft_t_info, "compression statistics (reading):\n"
438 KERN_INFO " compr./uncmpr. : %3d %%",
439 ((zftc_rd_compressed * 100)
440 / zftc_rd_uncompressed));
441 }
442 }
443 /* only print it once: */
444 zftc_wr_uncompressed =
445 zftc_wr_compressed =
446 zftc_rd_uncompressed =
447 zftc_rd_compressed = 0;
448 TRACE_EXIT;
449}
450
451/* start new compressed block
452 */
453static int start_new_cseg(cmpr_info *cluster,
454 char *dst_buf,
455 const zft_position *pos,
456 const unsigned int blk_sz,
457 const char *src_buf,
458 const int this_segs_sz,
459 const int qic113)
460{
461 int size_left;
462 int cp_cnt;
463 int buf_pos;
464 TRACE_FUN(ft_t_flow);
465
466 size_left = this_segs_sz - sizeof(__u16) - cluster->cmpr_sz;
467 TRACE(ft_t_data_flow,"\n"
468 KERN_INFO "segment size : %d\n"
469 KERN_INFO "compressed_sz: %d\n"
470 KERN_INFO "size_left : %d",
471 this_segs_sz, cluster->cmpr_sz, size_left);
472 if (size_left > 18) { /* start a new cluseter */
473 cp_cnt = cluster->cmpr_sz;
474 cluster->cmpr_sz = 0;
475 buf_pos = cp_cnt + sizeof(__u16);
476 PUT2(dst_buf, 0, buf_pos);
477
478 if (qic113) {
479 __s64 foffs = pos->volume_pos;
480 if (cp_cnt) foffs += (__s64)blk_sz;
481
482 TRACE(ft_t_data_flow, "new style QIC-113 header");
483 PUT8(dst_buf, buf_pos, foffs);
484 buf_pos += sizeof(__s64);
485 } else {
486 __u32 foffs = (__u32)pos->volume_pos;
487 if (cp_cnt) foffs += (__u32)blk_sz;
488
489 TRACE(ft_t_data_flow, "old style QIC-80MC header");
490 PUT4(dst_buf, buf_pos, foffs);
491 buf_pos += sizeof(__u32);
492 }
493 } else if (size_left >= 0) {
494 cp_cnt = cluster->cmpr_sz;
495 cluster->cmpr_sz = 0;
496 buf_pos = cp_cnt + sizeof(__u16);
497 PUT2(dst_buf, 0, buf_pos);
498 /* zero unused part of segment. */
499 memset(dst_buf + buf_pos, '\0', size_left);
500 buf_pos = this_segs_sz;
501 } else { /* need entire segment and more space */
502 PUT2(dst_buf, 0, 0);
503 cp_cnt = this_segs_sz - sizeof(__u16);
504 cluster->cmpr_sz -= cp_cnt;
505 buf_pos = this_segs_sz;
506 }
507 memcpy(dst_buf + sizeof(__u16), src_buf + cluster->cmpr_pos, cp_cnt);
508 cluster->cmpr_pos += cp_cnt;
509 TRACE_EXIT buf_pos;
510}
511
512/* return-value: the number of bytes removed from the user-buffer
513 * `src_buf' or error code
514 *
515 * int *write_cnt : how much actually has been moved to the
516 * dst_buf. Need not be initialized when
517 * function returns with an error code
518 * (negativ return value)
519 * __u8 *dst_buf : kernel space buffer where the has to be
520 * copied to. The contents of this buffers
521 * goes to a specific segment.
522 * const int seg_sz : the size of the segment dst_buf will be
523 * copied to.
524 * const zft_position *pos : struct containing the coordinates in
525 * the current volume (byte position,
526 * segment id of current segment etc)
527 * const zft_volinfo *volume: information about the current volume,
528 * size etc.
529 * const __u8 *src_buf : user space buffer that contains the
530 * data the user wants to be written to
531 * tape.
532 * const int req_len : the amount of data the user wants to be
533 * written to tape.
534 */
535static int zftc_write(int *write_cnt,
536 __u8 *dst_buf, const int seg_sz,
537 const __u8 __user *src_buf, const int req_len,
538 const zft_position *pos, const zft_volinfo *volume)
539{
540 int req_len_left = req_len;
541 int result;
542 int len_left;
543 int buf_pos_write = pos->seg_byte_pos;
544 TRACE_FUN(ft_t_flow);
545
546 /* Note: we do not unlock the module because
547 * there are some values cached in that `cseg' variable. We
548 * don't don't want to use this information when being
549 * unloaded by kerneld even when the tape is full or when we
550 * cannot allocate enough memory.
551 */
552 if (pos->tape_pos > (volume->size-volume->blk_sz-ZFT_CMPR_OVERHEAD)) {
553 TRACE_EXIT -ENOSPC;
554 }
555 if (zft_allocate_cmpr_mem(volume->blk_sz) < 0) {
556 /* should we unlock the module? But it shouldn't
557 * be locked anyway ...
558 */
559 TRACE_EXIT -ENOMEM;
560 }
561 if (buf_pos_write == 0) { /* fill a new segment */
562 *write_cnt = buf_pos_write = start_new_cseg(&cseg,
563 dst_buf,
564 pos,
565 volume->blk_sz,
566 zftc_buf,
567 seg_sz,
568 volume->qic113);
569 if (cseg.cmpr_sz == 0 && cseg.cmpr_pos != 0) {
570 req_len_left -= result = volume->blk_sz;
571 cseg.cmpr_pos = 0;
572 } else {
573 result = 0;
574 }
575 } else {
576 *write_cnt = result = 0;
577 }
578
579 len_left = seg_sz - buf_pos_write;
580 while ((req_len_left > 0) && (len_left > 18)) {
581 /* now we have some size left for a new compressed
582 * block. We know, that the compression buffer is
583 * empty (else there wouldn't be any space left).
584 */
585 if (copy_from_user(zftc_scratch_buf, src_buf + result,
586 volume->blk_sz) != 0) {
587 TRACE_EXIT -EFAULT;
588 }
589 req_len_left -= volume->blk_sz;
590 cseg.cmpr_sz = zft_compress(zftc_scratch_buf, volume->blk_sz,
591 zftc_buf);
592 if (cseg.cmpr_sz < 0) {
593 cseg.uncmpr = 0x8000;
594 cseg.cmpr_sz = -cseg.cmpr_sz;
595 } else {
596 cseg.uncmpr = 0;
597 }
598 /* increment "result" iff we copied the entire
599 * compressed block to the zft_deblock_buf
600 */
601 len_left -= sizeof(__u16);
602 if (len_left >= cseg.cmpr_sz) {
603 len_left -= cseg.count = cseg.cmpr_sz;
604 cseg.cmpr_pos = cseg.cmpr_sz = 0;
605 result += volume->blk_sz;
606 } else {
607 cseg.cmpr_sz -=
608 cseg.cmpr_pos =
609 cseg.count = len_left;
610 len_left = 0;
611 }
612 PUT2(dst_buf, buf_pos_write, cseg.uncmpr | cseg.count);
613 buf_pos_write += sizeof(__u16);
614 memcpy(dst_buf + buf_pos_write, zftc_buf, cseg.count);
615 buf_pos_write += cseg.count;
616 *write_cnt += cseg.count + sizeof(__u16);
617 FT_SIGNAL_EXIT(_DONT_BLOCK);
618 }
619 /* erase the remainder of the segment if less than 18 bytes
620 * left (18 bytes is due to the QIC-80 standard)
621 */
622 if (len_left <= 18) {
623 memset(dst_buf + buf_pos_write, '\0', len_left);
624 (*write_cnt) += len_left;
625 }
626 TRACE(ft_t_data_flow, "returning %d", result);
627 TRACE_EXIT result;
628}
629
630/* out:
631 *
632 * int *read_cnt: the number of bytes we removed from the zft_deblock_buf
633 * (result)
634 * int *to_do : the remaining size of the read-request.
635 *
636 * in:
637 *
638 * char *buff : buff is the address of the upper part of the user
639 * buffer, that hasn't been filled with data yet.
640
641 * int buf_pos_read : copy of from _ftape_read()
642 * int buf_len_read : copy of buf_len_rd from _ftape_read()
643 * char *zft_deblock_buf: zft_deblock_buf
644 * unsigned short blk_sz: the block size valid for this volume, may differ
645 * from zft_blk_sz.
646 * int finish: if != 0 means that this is the last segment belonging
647 * to this volume
648 * returns the amount of data actually copied to the user-buffer
649 *
650 * to_do MUST NOT SHRINK except to indicate an EOF. In this case *to_do has to
651 * be set to 0
652 */
653static int zftc_read (int *read_cnt,
654 __u8 __user *dst_buf, const int to_do,
655 const __u8 *src_buf, const int seg_sz,
656 const zft_position *pos, const zft_volinfo *volume)
657{
658 int uncompressed_sz;
659 int result = 0;
660 int remaining = to_do;
661 TRACE_FUN(ft_t_flow);
662
663 TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),);
664 if (pos->seg_byte_pos == 0) {
665 /* new segment just read
666 */
667 TRACE_CATCH(get_cseg(&cseg, src_buf, seg_sz, volume),
668 *read_cnt = 0);
669 memcpy(zftc_buf + cseg.cmpr_pos, src_buf + sizeof(__u16),
670 cseg.count);
671 cseg.cmpr_pos += cseg.count;
672 *read_cnt = cseg.offset;
673 DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", &cseg);
674 } else {
675 *read_cnt = 0;
676 }
677 /* loop and uncompress until user buffer full or
678 * deblock-buffer empty
679 */
680 TRACE(ft_t_data_flow, "compressed_sz: %d, compos : %d, *read_cnt: %d",
681 cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);
682 while ((cseg.spans == 0) && (remaining > 0)) {
683 if (cseg.cmpr_pos != 0) { /* cmpr buf is not empty */
684 uncompressed_sz =
685 zft_uncompress(zftc_buf,
686 cseg.uncmpr == 0x8000 ?
687 -cseg.cmpr_pos : cseg.cmpr_pos,
688 zftc_scratch_buf,
689 volume->blk_sz);
690 if (uncompressed_sz != volume->blk_sz) {
691 *read_cnt = 0;
692 TRACE_ABORT(-EIO, ft_t_warn,
693 "Uncompressed blk (%d) != blk size (%d)",
694 uncompressed_sz, volume->blk_sz);
695 }
696 if (copy_to_user(dst_buf + result,
697 zftc_scratch_buf,
698 uncompressed_sz) != 0 ) {
699 TRACE_EXIT -EFAULT;
700 }
701 remaining -= uncompressed_sz;
702 result += uncompressed_sz;
703 cseg.cmpr_pos = 0;
704 }
705 if (remaining > 0) {
706 get_next_cluster(&cseg, src_buf, seg_sz,
707 volume->end_seg == pos->seg_pos);
708 if (cseg.count != 0) {
709 memcpy(zftc_buf, src_buf + cseg.offset,
710 cseg.count);
711 cseg.cmpr_pos = cseg.count;
712 cseg.offset += cseg.count;
713 *read_cnt += cseg.count + sizeof(__u16);
714 } else {
715 remaining = 0;
716 }
717 }
718 TRACE(ft_t_data_flow, "\n"
719 KERN_INFO "compressed_sz: %d\n"
720 KERN_INFO "compos : %d\n"
721 KERN_INFO "*read_cnt : %d",
722 cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);
723 }
724 if (seg_sz - cseg.offset <= 18) {
725 *read_cnt += seg_sz - cseg.offset;
726 TRACE(ft_t_data_flow, "expanding read cnt to: %d", *read_cnt);
727 }
728 TRACE(ft_t_data_flow, "\n"
729 KERN_INFO "segment size : %d\n"
730 KERN_INFO "read count : %d\n"
731 KERN_INFO "buf_pos_read : %d\n"
732 KERN_INFO "remaining : %d",
733 seg_sz, *read_cnt, pos->seg_byte_pos,
734 seg_sz - *read_cnt - pos->seg_byte_pos);
735 TRACE(ft_t_data_flow, "returning: %d", result);
736 TRACE_EXIT result;
737}
738
739/* seeks to the new data-position. Reads sometimes a segment.
740 *
741 * start_seg and end_seg give the boundaries of the current volume
742 * blk_sz is the blk_sz of the current volume as stored in the
743 * volume label
744 *
745 * We don't allow blocksizes less than 1024 bytes, therefore we don't need
746 * a 64 bit argument for new_block_pos.
747 */
748
749static int seek_in_segment(const unsigned int to_do, cmpr_info *c_info,
750 const char *src_buf, const int seg_sz,
751 const int seg_pos, const zft_volinfo *volume);
752static int slow_seek_forward_until_error(const unsigned int distance,
753 cmpr_info *c_info, zft_position *pos,
754 const zft_volinfo *volume, __u8 *buf);
755static int search_valid_segment(unsigned int segment,
756 const unsigned int end_seg,
757 const unsigned int max_foffs,
758 zft_position *pos, cmpr_info *c_info,
759 const zft_volinfo *volume, __u8 *buf);
760static int slow_seek_forward(unsigned int dest, cmpr_info *c_info,
761 zft_position *pos, const zft_volinfo *volume,
762 __u8 *buf);
763static int compute_seg_pos(unsigned int dest, zft_position *pos,
764 const zft_volinfo *volume);
765
766#define ZFT_SLOW_SEEK_THRESHOLD 10 /* segments */
767#define ZFT_FAST_SEEK_MAX_TRIALS 10 /* times */
768#define ZFT_FAST_SEEK_BACKUP 10 /* segments */
769
770static int zftc_seek(unsigned int new_block_pos,
771 zft_position *pos, const zft_volinfo *volume, __u8 *buf)
772{
773 unsigned int dest;
774 int limit;
775 int distance;
776 int result = 0;
777 int seg_dist;
778 int new_seg;
779 int old_seg = 0;
780 int fast_seek_trials = 0;
781 TRACE_FUN(ft_t_flow);
782
783 if (new_block_pos == 0) {
784 pos->seg_pos = volume->start_seg;
785 pos->seg_byte_pos = 0;
786 pos->volume_pos = 0;
787 zftc_reset();
788 TRACE_EXIT 0;
789 }
790 dest = new_block_pos * (volume->blk_sz >> 10);
791 distance = dest - (pos->volume_pos >> 10);
792 while (distance != 0) {
793 seg_dist = compute_seg_pos(dest, pos, volume);
794 TRACE(ft_t_noise, "\n"
795 KERN_INFO "seg_dist: %d\n"
796 KERN_INFO "distance: %d\n"
797 KERN_INFO "dest : %d\n"
798 KERN_INFO "vpos : %d\n"
799 KERN_INFO "seg_pos : %d\n"
800 KERN_INFO "trials : %d",
801 seg_dist, distance, dest,
802 (unsigned int)(pos->volume_pos>>10), pos->seg_pos,
803 fast_seek_trials);
804 if (distance > 0) {
805 if (seg_dist < 0) {
806 TRACE(ft_t_bug, "BUG: distance %d > 0, "
807 "segment difference %d < 0",
808 distance, seg_dist);
809 result = -EIO;
810 break;
811 }
812 new_seg = pos->seg_pos + seg_dist;
813 if (new_seg > volume->end_seg) {
814 new_seg = volume->end_seg;
815 }
816 if (old_seg == new_seg || /* loop */
817 seg_dist <= ZFT_SLOW_SEEK_THRESHOLD ||
818 fast_seek_trials >= ZFT_FAST_SEEK_MAX_TRIALS) {
819 TRACE(ft_t_noise, "starting slow seek:\n"
820 KERN_INFO "fast seek failed too often: %s\n"
821 KERN_INFO "near target position : %s\n"
822 KERN_INFO "looping between two segs : %s",
823 (fast_seek_trials >=
824 ZFT_FAST_SEEK_MAX_TRIALS)
825 ? "yes" : "no",
826 (seg_dist <= ZFT_SLOW_SEEK_THRESHOLD)
827 ? "yes" : "no",
828 (old_seg == new_seg)
829 ? "yes" : "no");
830 result = slow_seek_forward(dest, &cseg,
831 pos, volume, buf);
832 break;
833 }
834 old_seg = new_seg;
835 limit = volume->end_seg;
836 fast_seek_trials ++;
837 for (;;) {
838 result = search_valid_segment(new_seg, limit,
839 volume->size,
840 pos, &cseg,
841 volume, buf);
842 if (result == 0 || result == -EINTR) {
843 break;
844 }
845 if (new_seg == volume->start_seg) {
846 result = -EIO; /* set errror
847 * condition
848 */
849 break;
850 }
851 limit = new_seg;
852 new_seg -= ZFT_FAST_SEEK_BACKUP;
853 if (new_seg < volume->start_seg) {
854 new_seg = volume->start_seg;
855 }
856 }
857 if (result < 0) {
858 TRACE(ft_t_warn,
859 "Couldn't find a readable segment");
860 break;
861 }
862 } else /* if (distance < 0) */ {
863 if (seg_dist > 0) {
864 TRACE(ft_t_bug, "BUG: distance %d < 0, "
865 "segment difference %d >0",
866 distance, seg_dist);
867 result = -EIO;
868 break;
869 }
870 new_seg = pos->seg_pos + seg_dist;
871 if (fast_seek_trials > 0 && seg_dist == 0) {
872 /* this avoids sticking to the same
873 * segment all the time. On the other hand:
874 * if we got here for the first time, and the
875 * deblock_buffer still contains a valid
876 * segment, then there is no need to skip to
877 * the previous segment if the desired position
878 * is inside this segment.
879 */
880 new_seg --;
881 }
882 if (new_seg < volume->start_seg) {
883 new_seg = volume->start_seg;
884 }
885 limit = pos->seg_pos;
886 fast_seek_trials ++;
887 for (;;) {
888 result = search_valid_segment(new_seg, limit,
889 pos->volume_pos,
890 pos, &cseg,
891 volume, buf);
892 if (result == 0 || result == -EINTR) {
893 break;
894 }
895 if (new_seg == volume->start_seg) {
896 result = -EIO; /* set errror
897 * condition
898 */
899 break;
900 }
901 limit = new_seg;
902 new_seg -= ZFT_FAST_SEEK_BACKUP;
903 if (new_seg < volume->start_seg) {
904 new_seg = volume->start_seg;
905 }
906 }
907 if (result < 0) {
908 TRACE(ft_t_warn,
909 "Couldn't find a readable segment");
910 break;
911 }
912 }
913 distance = dest - (pos->volume_pos >> 10);
914 }
915 TRACE_EXIT result;
916}
917
918
919/* advance inside the given segment at most to_do bytes.
920 * of kilobytes moved
921 */
922
923static int seek_in_segment(const unsigned int to_do,
924 cmpr_info *c_info,
925 const char *src_buf,
926 const int seg_sz,
927 const int seg_pos,
928 const zft_volinfo *volume)
929{
930 int result = 0;
931 int blk_sz = volume->blk_sz >> 10;
932 int remaining = to_do;
933 TRACE_FUN(ft_t_flow);
934
935 if (c_info->offset == 0) {
936 /* new segment just read
937 */
938 TRACE_CATCH(get_cseg(c_info, src_buf, seg_sz, volume),);
939 c_info->cmpr_pos += c_info->count;
940 DUMP_CMPR_INFO(ft_t_noise, "", c_info);
941 }
942 /* loop and uncompress until user buffer full or
943 * deblock-buffer empty
944 */
945 TRACE(ft_t_noise, "compressed_sz: %d, compos : %d",
946 c_info->cmpr_sz, c_info->cmpr_pos);
947 while (c_info->spans == 0 && remaining > 0) {
948 if (c_info->cmpr_pos != 0) { /* cmpr buf is not empty */
949 result += blk_sz;
950 remaining -= blk_sz;
951 c_info->cmpr_pos = 0;
952 }
953 if (remaining > 0) {
954 get_next_cluster(c_info, src_buf, seg_sz,
955 volume->end_seg == seg_pos);
956 if (c_info->count != 0) {
957 c_info->cmpr_pos = c_info->count;
958 c_info->offset += c_info->count;
959 } else {
960 break;
961 }
962 }
963 /* Allow escape from this loop on signal!
964 */
965 FT_SIGNAL_EXIT(_DONT_BLOCK);
966 DUMP_CMPR_INFO(ft_t_noise, "", c_info);
967 TRACE(ft_t_noise, "to_do: %d", remaining);
968 }
969 if (seg_sz - c_info->offset <= 18) {
970 c_info->offset = seg_sz;
971 }
972 TRACE(ft_t_noise, "\n"
973 KERN_INFO "segment size : %d\n"
974 KERN_INFO "buf_pos_read : %d\n"
975 KERN_INFO "remaining : %d",
976 seg_sz, c_info->offset,
977 seg_sz - c_info->offset);
978 TRACE_EXIT result;
979}
980
981static int slow_seek_forward_until_error(const unsigned int distance,
982 cmpr_info *c_info,
983 zft_position *pos,
984 const zft_volinfo *volume,
985 __u8 *buf)
986{
987 unsigned int remaining = distance;
988 int seg_sz;
989 int seg_pos;
990 int result;
991 TRACE_FUN(ft_t_flow);
992
993 seg_pos = pos->seg_pos;
994 do {
995 TRACE_CATCH(seg_sz = zft_fetch_segment(seg_pos, buf,
996 FT_RD_AHEAD),);
997 /* now we have the contents of the actual segment in
998 * the deblock buffer
999 */
1000 TRACE_CATCH(result = seek_in_segment(remaining, c_info, buf,
1001 seg_sz, seg_pos,volume),);
1002 remaining -= result;
1003 pos->volume_pos += result<<10;
1004 pos->seg_pos = seg_pos;
1005 pos->seg_byte_pos = c_info->offset;
1006 seg_pos ++;
1007 if (seg_pos <= volume->end_seg && c_info->offset == seg_sz) {
1008 pos->seg_pos ++;
1009 pos->seg_byte_pos = 0;
1010 c_info->offset = 0;
1011 }
1012 /* Allow escape from this loop on signal!
1013 */
1014 FT_SIGNAL_EXIT(_DONT_BLOCK);
1015 TRACE(ft_t_noise, "\n"
1016 KERN_INFO "remaining: %d\n"
1017 KERN_INFO "seg_pos: %d\n"
1018 KERN_INFO "end_seg: %d\n"
1019 KERN_INFO "result: %d",
1020 remaining, seg_pos, volume->end_seg, result);
1021 } while (remaining > 0 && seg_pos <= volume->end_seg);
1022 TRACE_EXIT 0;
1023}
1024
1025/* return segment id of next segment containing valid data, -EIO otherwise
1026 */
1027static int search_valid_segment(unsigned int segment,
1028 const unsigned int end_seg,
1029 const unsigned int max_foffs,
1030 zft_position *pos,
1031 cmpr_info *c_info,
1032 const zft_volinfo *volume,
1033 __u8 *buf)
1034{
1035 cmpr_info tmp_info;
1036 int seg_sz;
1037 TRACE_FUN(ft_t_flow);
1038
1039 memset(&tmp_info, 0, sizeof(cmpr_info));
1040 while (segment <= end_seg) {
1041 FT_SIGNAL_EXIT(_DONT_BLOCK);
1042 TRACE(ft_t_noise,
1043 "Searching readable segment between %d and %d",
1044 segment, end_seg);
1045 seg_sz = zft_fetch_segment(segment, buf, FT_RD_AHEAD);
1046 if ((seg_sz > 0) &&
1047 (get_cseg (&tmp_info, buf, seg_sz, volume) >= 0) &&
1048 (tmp_info.foffs != 0 || segment == volume->start_seg)) {
1049 if ((tmp_info.foffs>>10) > max_foffs) {
1050 TRACE_ABORT(-EIO, ft_t_noise, "\n"
1051 KERN_INFO "cseg.foff: %d\n"
1052 KERN_INFO "dest : %d",
1053 (int)(tmp_info.foffs >> 10),
1054 max_foffs);
1055 }
1056 DUMP_CMPR_INFO(ft_t_noise, "", &tmp_info);
1057 *c_info = tmp_info;
1058 pos->seg_pos = segment;
1059 pos->volume_pos = c_info->foffs;
1060 pos->seg_byte_pos = c_info->offset;
1061 TRACE(ft_t_noise, "found segment at %d", segment);
1062 TRACE_EXIT 0;
1063 }
1064 segment++;
1065 }
1066 TRACE_EXIT -EIO;
1067}
1068
1069static int slow_seek_forward(unsigned int dest,
1070 cmpr_info *c_info,
1071 zft_position *pos,
1072 const zft_volinfo *volume,
1073 __u8 *buf)
1074{
1075 unsigned int distance;
1076 int result = 0;
1077 TRACE_FUN(ft_t_flow);
1078
1079 distance = dest - (pos->volume_pos >> 10);
1080 while ((distance > 0) &&
1081 (result = slow_seek_forward_until_error(distance,
1082 c_info,
1083 pos,
1084 volume,
1085 buf)) < 0) {
1086 if (result == -EINTR) {
1087 break;
1088 }
1089 TRACE(ft_t_noise, "seg_pos: %d", pos->seg_pos);
1090 /* the failing segment is either pos->seg_pos or
1091 * pos->seg_pos + 1. There is no need to further try
1092 * that segment, because ftape_read_segment() already
1093 * has tried very much to read it. So we start with
1094 * following segment, which is pos->seg_pos + 1
1095 */
1096 if(search_valid_segment(pos->seg_pos+1, volume->end_seg, dest,
1097 pos, c_info,
1098 volume, buf) < 0) {
1099 TRACE(ft_t_noise, "search_valid_segment() failed");
1100 result = -EIO;
1101 break;
1102 }
1103 distance = dest - (pos->volume_pos >> 10);
1104 result = 0;
1105 TRACE(ft_t_noise, "segment: %d", pos->seg_pos);
1106 /* found valid segment, retry the seek */
1107 }
1108 TRACE_EXIT result;
1109}
1110
1111static int compute_seg_pos(const unsigned int dest,
1112 zft_position *pos,
1113 const zft_volinfo *volume)
1114{
1115 int segment;
1116 int distance = dest - (pos->volume_pos >> 10);
1117 unsigned int raw_size;
1118 unsigned int virt_size;
1119 unsigned int factor;
1120 TRACE_FUN(ft_t_flow);
1121
1122 if (distance >= 0) {
1123 raw_size = volume->end_seg - pos->seg_pos + 1;
1124 virt_size = ((unsigned int)(volume->size>>10)
1125 - (unsigned int)(pos->volume_pos>>10)
1126 + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);
1127 virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;
1128 if (virt_size == 0 || raw_size == 0) {
1129 TRACE_EXIT 0;
1130 }
1131 if (raw_size >= (1<<25)) {
1132 factor = raw_size/(virt_size>>7);
1133 } else {
1134 factor = (raw_size<<7)/virt_size;
1135 }
1136 segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);
1137 segment = (segment * factor)>>7;
1138 } else {
1139 raw_size = pos->seg_pos - volume->start_seg + 1;
1140 virt_size = ((unsigned int)(pos->volume_pos>>10)
1141 + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);
1142 virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;
1143 if (virt_size == 0 || raw_size == 0) {
1144 TRACE_EXIT 0;
1145 }
1146 if (raw_size >= (1<<25)) {
1147 factor = raw_size/(virt_size>>7);
1148 } else {
1149 factor = (raw_size<<7)/virt_size;
1150 }
1151 segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);
1152 }
1153 TRACE(ft_t_noise, "factor: %d/%d", factor, 1<<7);
1154 TRACE_EXIT segment;
1155}
1156
1157static struct zft_cmpr_ops cmpr_ops = {
1158 zftc_write,
1159 zftc_read,
1160 zftc_seek,
1161 zftc_lock,
1162 zftc_reset,
1163 zftc_cleanup
1164};
1165
1166int zft_compressor_init(void)
1167{
1168 TRACE_FUN(ft_t_flow);
1169
1170#ifdef MODULE
1171 printk(KERN_INFO "zftape compressor v1.00a 970514 for " FTAPE_VERSION "\n");
1172 if (TRACE_LEVEL >= ft_t_info) {
1173 printk(
1174KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
1175KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n");
1176 }
1177#else /* !MODULE */
1178 /* print a short no-nonsense boot message */
1179 printk(KERN_INFO "zftape compressor v1.00a 970514\n");
1180 printk(KERN_INFO "For use with " FTAPE_VERSION "\n");
1181#endif /* MODULE */
1182 TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);
1183 TRACE(ft_t_info, "installing compressor for zftape ...");
1184 TRACE_CATCH(zft_cmpr_register(&cmpr_ops),);
1185 TRACE_EXIT 0;
1186}
1187
1188#ifdef MODULE
1189
1190MODULE_AUTHOR(
1191 "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de");
1192MODULE_DESCRIPTION(
1193"Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams");
1194MODULE_LICENSE("GPL");
1195
1196/* Called by modules package when installing the driver
1197 */
1198int init_module(void)
1199{
1200 return zft_compressor_init();
1201}
1202
1203#endif /* MODULE */
diff --git a/drivers/char/ftape/compressor/zftape-compress.h b/drivers/char/ftape/compressor/zftape-compress.h
deleted file mode 100644
index f200741e33bf..000000000000
--- a/drivers/char/ftape/compressor/zftape-compress.h
+++ /dev/null
@@ -1,83 +0,0 @@
1#ifndef _ZFTAPE_COMPRESS_H
2#define _ZFTAPE_COMPRESS_H
3/*
4 * Copyright (c) 1994-1997 Claus-Justus Heine
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2, or (at
9 your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 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,
19 USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/compressor/zftape-compress.h,v $
23 * $Revision: 1.1 $
24 * $Date: 1997/10/05 19:12:32 $
25 *
26 * This file contains macros and definitions for zftape's
27 * builtin compression code.
28 *
29 */
30
31#include "../zftape/zftape-buffers.h"
32#include "../zftape/zftape-vtbl.h"
33#include "../compressor/lzrw3.h"
34
35/* CMPR_WRK_MEM_SIZE gives the size of the compression wrk_mem */
36/* I got these out of lzrw3.c */
37#define U(X) ((__u32) X)
38#define SIZE_P_BYTE (U(sizeof(__u8 *)))
39#define ALIGNMENT_FUDGE (U(16))
40
41#define CMPR_WRK_MEM_SIZE (U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE)
42
43/* the maximum number of bytes the size of the "compressed" data can
44 * exceed the uncompressed data. As it is quite useless to compress
45 * data twice it is sometimes the case that it is more efficient to
46 * copy a block of data but to feed it to the "compression"
47 * algorithm. In this case there are some flag bytes or the like
48 * proceding the "compressed" data. THAT MUST NOT BE THE CASE for the
49 * algorithm we use for this driver. Instead, the high bit 15 of
50 * compressed_size:
51 *
52 * compressed_size = ftape_compress()
53 *
54 * must be set in such a case.
55 *
56 * Nevertheless, it might also be as for lzrw3 that there is an
57 * "intermediate" overrun that exceeds the amount of the compressed
58 * data that is actually produced. During the algorithm we need in the
59 * worst case MAX_CMP_GROUP bytes more than the input-size.
60 */
61#define MAX_CMP_GROUP (2+16*2) /* from lzrw3.c */
62
63#define CMPR_OVERRUN MAX_CMP_GROUP /* during compression */
64
65/****************************************************/
66
67#define CMPR_BUFFER_SIZE (MAX_BLOCK_SIZE + CMPR_OVERRUN)
68
69/* the compression map stores the byte offset compressed blocks within
70 * the current volume for catridges with format code 2,3 and 5
71 * (and old versions of zftape) and the offset measured in kilobytes for
72 * format code 4 and 6. This gives us a possible max. size of a
73 * compressed volume of 1024*4GIG which should be enough.
74 */
75typedef __u32 CmprMap;
76
77/* globals
78 */
79
80/* exported functions
81 */
82
83#endif /* _ZFTAPE_COMPRESS_H */
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
diff --git a/drivers/char/ftape/zftape/Makefile b/drivers/char/ftape/zftape/Makefile
deleted file mode 100644
index 6d91c1f77c05..000000000000
--- a/drivers/char/ftape/zftape/Makefile
+++ /dev/null
@@ -1,36 +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# $Source: /homes/cvs/ftape-stacked/ftape/zftape/Makefile,v $
19# $Revision: 1.4 $
20# $Date: 1997/10/05 19:18:58 $
21#
22# Makefile for the QIC-40/80/3010/3020 zftape interface VFS to
23# ftape
24#
25
26
27# ZFT_OBSOLETE - enable the MTIOC_ZFTAPE_GETBLKSZ ioctl. You should
28# leave this enabled for compatibility with taper.
29
30obj-$(CONFIG_ZFTAPE) += zftape.o
31
32zftape-objs := zftape-rw.o zftape-ctl.o zftape-read.o \
33 zftape-write.o zftape-vtbl.o zftape-eof.o \
34 zftape-init.o zftape-buffers.o zftape_syms.o
35
36EXTRA_CFLAGS := -DZFT_OBSOLETE
diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c
deleted file mode 100644
index 7ebce2ec7897..000000000000
--- a/drivers/char/ftape/zftape/zftape-buffers.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/*
2 * Copyright (C) 1995-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/zftape/zftape-buffers.c,v $
20 * $Revision: 1.2 $
21 * $Date: 1997/10/05 19:18:59 $
22 *
23 * This file contains the dynamic buffer allocation routines
24 * of zftape
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
31
32#include <linux/zftape.h>
33
34#include <linux/vmalloc.h>
35
36#include "../zftape/zftape-init.h"
37#include "../zftape/zftape-eof.h"
38#include "../zftape/zftape-ctl.h"
39#include "../zftape/zftape-write.h"
40#include "../zftape/zftape-read.h"
41#include "../zftape/zftape-rw.h"
42#include "../zftape/zftape-vtbl.h"
43
44/* global variables
45 */
46
47/* local varibales
48 */
49static unsigned int used_memory;
50static unsigned int peak_memory;
51
52void zft_memory_stats(void)
53{
54 TRACE_FUN(ft_t_flow);
55
56 TRACE(ft_t_noise, "Memory usage (vmalloc allocations):\n"
57 KERN_INFO "total allocated: %d\n"
58 KERN_INFO "peak allocation: %d",
59 used_memory, peak_memory);
60 peak_memory = used_memory;
61 TRACE_EXIT;
62}
63
64int zft_vcalloc_once(void *new, size_t size)
65{
66 TRACE_FUN(ft_t_flow);
67 if (zft_vmalloc_once(new, size) < 0) {
68 TRACE_EXIT -ENOMEM;
69 }
70 memset(*(void **)new, '\0', size);
71 TRACE_EXIT 0;
72}
73int zft_vmalloc_once(void *new, size_t size)
74{
75 TRACE_FUN(ft_t_flow);
76
77 if (*(void **)new != NULL || size == 0) {
78 TRACE_EXIT 0;
79 }
80 if ((*(void **)new = vmalloc(size)) == NULL) {
81 TRACE_EXIT -ENOMEM;
82 }
83 used_memory += size;
84 if (peak_memory < used_memory) {
85 peak_memory = used_memory;
86 }
87 TRACE_ABORT(0, ft_t_noise,
88 "allocated buffer @ %p, %zd bytes", *(void **)new, size);
89}
90int zft_vmalloc_always(void *new, size_t size)
91{
92 TRACE_FUN(ft_t_flow);
93
94 zft_vfree(new, size);
95 TRACE_EXIT zft_vmalloc_once(new, size);
96}
97void zft_vfree(void *old, size_t size)
98{
99 TRACE_FUN(ft_t_flow);
100
101 if (*(void **)old) {
102 vfree(*(void **)old);
103 used_memory -= size;
104 TRACE(ft_t_noise, "released buffer @ %p, %zd bytes",
105 *(void **)old, size);
106 *(void **)old = NULL;
107 }
108 TRACE_EXIT;
109}
110
111void *zft_kmalloc(size_t size)
112{
113 void *new;
114
115 while ((new = kmalloc(size, GFP_KERNEL)) == NULL) {
116 msleep_interruptible(100);
117 }
118 memset(new, 0, size);
119 used_memory += size;
120 if (peak_memory < used_memory) {
121 peak_memory = used_memory;
122 }
123 return new;
124}
125
126void zft_kfree(void *old, size_t size)
127{
128 kfree(old);
129 used_memory -= size;
130}
131
132/* there are some more buffers that are allocated on demand.
133 * cleanup_module() calles this function to be sure to have released
134 * them
135 */
136void zft_uninit_mem(void)
137{
138 TRACE_FUN(ft_t_flow);
139
140 zft_vfree(&zft_hseg_buf, FT_SEGMENT_SIZE);
141 zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); zft_deblock_segment = -1;
142 zft_free_vtbl();
143 if (zft_cmpr_lock(0 /* don't load */) == 0) {
144 (*zft_cmpr_ops->cleanup)();
145 (*zft_cmpr_ops->reset)(); /* unlock it again */
146 }
147 zft_memory_stats();
148 TRACE_EXIT;
149}
diff --git a/drivers/char/ftape/zftape/zftape-buffers.h b/drivers/char/ftape/zftape/zftape-buffers.h
deleted file mode 100644
index 798e3128c682..000000000000
--- a/drivers/char/ftape/zftape/zftape-buffers.h
+++ /dev/null
@@ -1,55 +0,0 @@
1#ifndef _FTAPE_DYNMEM_H
2#define _FTAPE_DYNMEM_H
3
4/*
5 * Copyright (C) 1995-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/zftape/zftape-buffers.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:18:59 $
25 *
26 * memory allocation routines.
27 *
28 */
29
30/* we do not allocate all of the really large buffer memory before
31 * someone tries to open the drive. ftape_open() may fail with
32 * -ENOMEM, but that's better having 200k of vmalloced memory which
33 * cannot be swapped out.
34 */
35
36extern void zft_memory_stats(void);
37extern int zft_vmalloc_once(void *new, size_t size);
38extern int zft_vcalloc_once(void *new, size_t size);
39extern int zft_vmalloc_always(void *new, size_t size);
40extern void zft_vfree(void *old, size_t size);
41extern void *zft_kmalloc(size_t size);
42extern void zft_kfree(void *old, size_t size);
43
44/* called by cleanup_module()
45 */
46extern void zft_uninit_mem(void);
47
48#endif
49
50
51
52
53
54
55
diff --git a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c
deleted file mode 100644
index 22ba0f5d00cf..000000000000
--- a/drivers/char/ftape/zftape/zftape-ctl.c
+++ /dev/null
@@ -1,1417 +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/zftape/zftape-ctl.c,v $
20 * $Revision: 1.2.6.2 $
21 * $Date: 1997/11/14 18:07:33 $
22 *
23 * This file contains the non-read/write zftape functions
24 * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30#include <linux/fcntl.h>
31
32#include <linux/zftape.h>
33
34#include <asm/uaccess.h>
35
36#include "../zftape/zftape-init.h"
37#include "../zftape/zftape-eof.h"
38#include "../zftape/zftape-ctl.h"
39#include "../zftape/zftape-write.h"
40#include "../zftape/zftape-read.h"
41#include "../zftape/zftape-rw.h"
42#include "../zftape/zftape-vtbl.h"
43
44/* Global vars.
45 */
46int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */
47int zft_header_read;
48int zft_offline;
49unsigned int zft_unit;
50int zft_resid;
51int zft_mt_compression;
52
53/* Local vars.
54 */
55static int going_offline;
56
57typedef int (mt_fun)(int *argptr);
58typedef int (*mt_funp)(int *argptr);
59typedef struct
60{
61 mt_funp function;
62 unsigned offline : 1; /* op permitted if offline or no_tape */
63 unsigned write_protected : 1; /* op permitted if write-protected */
64 unsigned not_formatted : 1; /* op permitted if tape not formatted */
65 unsigned raw_mode : 1; /* op permitted if zft_mode == 0 */
66 unsigned need_idle_state : 1; /* need to call def_idle_state */
67 char *name;
68} fun_entry;
69
70static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop,
71 mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity,
72 mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf,
73 mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression;
74
75static fun_entry mt_funs[]=
76{
77 {mt_reset , 1, 1, 1, 1, 0, "MT_RESET" }, /* 0 */
78 {mt_fsf , 0, 1, 0, 0, 1, "MT_FSF" },
79 {mt_bsf , 0, 1, 0, 0, 1, "MT_BSF" },
80 {mt_fsr , 0, 1, 0, 1, 1, "MT_FSR" },
81 {mt_bsr , 0, 1, 0, 1, 1, "MT_BSR" },
82 {mt_weof , 0, 0, 0, 0, 0, "MT_WEOF" }, /* 5 */
83 {mt_rew , 0, 1, 1, 1, 0, "MT_REW" },
84 {mt_offl , 0, 1, 1, 1, 0, "MT_OFFL" },
85 {mt_nop , 1, 1, 1, 1, 0, "MT_NOP" },
86 {mt_reten , 0, 1, 1, 1, 0, "MT_RETEN" },
87 {mt_bsfm , 0, 1, 0, 0, 1, "MT_BSFM" }, /* 10 */
88 {mt_fsfm , 0, 1, 0, 0, 1, "MT_FSFM" },
89 {mt_eom , 0, 1, 0, 0, 1, "MT_EOM" },
90 {mt_erase , 0, 0, 0, 1, 0, "MT_ERASE" },
91 {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS1" },
92 {mt_ras2 , 0, 0, 0, 1, 0, "MT_RAS2" },
93 {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS3" },
94 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
95 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
96 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
97 {mt_setblk , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */
98 {mt_setdensity , 1, 1, 1, 1, 0, "MT_SETDENSITY"},
99 {mt_seek , 0, 1, 0, 1, 1, "MT_SEEK" },
100 {mt_dummy , 0, 1, 0, 1, 1, "MT_TELL" }, /* wr-only ?! */
101 {mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" },
102 {mt_dummy , 1, 1, 1, 1, 0, "MT_FSS" }, /* 25 */
103 {mt_dummy , 1, 1, 1, 1, 0, "MT_BSS" },
104 {mt_dummy , 1, 1, 1, 1, 0, "MT_WSM" },
105 {mt_dummy , 1, 1, 1, 1, 0, "MT_LOCK" },
106 {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOCK"},
107 {mt_dummy , 1, 1, 1, 1, 0, "MT_LOAD" }, /* 30 */
108 {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOAD"},
109 {mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"},
110 {mt_dummy , 1, 1, 1, 1, 0, "MT_SETPART"},
111 {mt_dummy , 1, 1, 1, 1, 0, "MT_MKPART"}
112};
113
114#define NR_MT_CMDS NR_ITEMS(mt_funs)
115
116void zft_reset_position(zft_position *pos)
117{
118 TRACE_FUN(ft_t_flow);
119
120 pos->seg_byte_pos =
121 pos->volume_pos = 0;
122 if (zft_header_read) {
123 /* need to keep track of the volume table and
124 * compression map. We therefor simply
125 * position at the beginning of the first
126 * volume. This covers old ftape archives as
127 * well has various flavours of the
128 * compression map segments. The worst case is
129 * that the compression map shows up as a
130 * additional volume in front of all others.
131 */
132 pos->seg_pos = zft_find_volume(0)->start_seg;
133 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
134 } else {
135 pos->tape_pos = 0;
136 pos->seg_pos = -1;
137 }
138 zft_just_before_eof = 0;
139 zft_deblock_segment = -1;
140 zft_io_state = zft_idle;
141 zft_zap_read_buffers();
142 zft_prevent_flush();
143 /* unlock the compresison module if it is loaded.
144 * The zero arg means not to try to load the module.
145 */
146 if (zft_cmpr_lock(0) == 0) {
147 (*zft_cmpr_ops->reset)(); /* unlock */
148 }
149 TRACE_EXIT;
150}
151
152static void zft_init_driver(void)
153{
154 TRACE_FUN(ft_t_flow);
155
156 zft_resid =
157 zft_header_read =
158 zft_old_ftape =
159 zft_offline =
160 zft_write_protected =
161 going_offline =
162 zft_mt_compression =
163 zft_header_changed =
164 zft_volume_table_changed =
165 zft_written_segments = 0;
166 zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
167 zft_reset_position(&zft_pos); /* does most of the stuff */
168 ftape_zap_read_buffers();
169 ftape_set_state(idle);
170 TRACE_EXIT;
171}
172
173int zft_def_idle_state(void)
174{
175 int result = 0;
176 TRACE_FUN(ft_t_flow);
177
178 if (!zft_header_read) {
179 result = zft_read_header_segments();
180 } else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) {
181 /* don't move past eof
182 */
183 (void)zft_close_volume(&zft_pos);
184 }
185 if (ftape_abort_operation() < 0) {
186 TRACE(ft_t_warn, "ftape_abort_operation() failed");
187 result = -EIO;
188 }
189 /* clear remaining read buffers */
190 zft_zap_read_buffers();
191 zft_io_state = zft_idle;
192 TRACE_EXIT result;
193}
194
195/*****************************************************************************
196 * *
197 * functions for the MTIOCTOP commands *
198 * *
199 *****************************************************************************/
200
201static int mt_dummy(int *dummy)
202{
203 TRACE_FUN(ft_t_flow);
204
205 TRACE_EXIT -ENOSYS;
206}
207
208static int mt_reset(int *dummy)
209{
210 TRACE_FUN(ft_t_flow);
211
212 (void)ftape_seek_to_bot();
213 TRACE_CATCH(ftape_reset_drive(),
214 zft_init_driver(); zft_uninit_mem(); zft_offline = 1);
215 /* fake a re-open of the device. This will set all flage and
216 * allocate buffers as appropriate. The new tape condition will
217 * force the open routine to do anything we need.
218 */
219 TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),);
220 TRACE_EXIT 0;
221}
222
223static int mt_fsf(int *arg)
224{
225 int result;
226 TRACE_FUN(ft_t_flow);
227
228 result = zft_skip_volumes(*arg, &zft_pos);
229 zft_just_before_eof = 0;
230 TRACE_EXIT result;
231}
232
233static int mt_bsf(int *arg)
234{
235 int result = 0;
236 TRACE_FUN(ft_t_flow);
237
238 if (*arg != 0) {
239 result = zft_skip_volumes(-*arg + 1, &zft_pos);
240 }
241 TRACE_EXIT result;
242}
243
244static int seek_block(__s64 data_offset,
245 __s64 block_increment,
246 zft_position *pos)
247{
248 int result = 0;
249 __s64 new_block_pos;
250 __s64 vol_block_count;
251 const zft_volinfo *volume;
252 int exceed;
253 TRACE_FUN(ft_t_flow);
254
255 volume = zft_find_volume(pos->seg_pos);
256 if (volume->start_seg == 0 || volume->end_seg == 0) {
257 TRACE_EXIT -EIO;
258 }
259 new_block_pos = (zft_div_blksz(data_offset, volume->blk_sz)
260 + block_increment);
261 vol_block_count = zft_div_blksz(volume->size, volume->blk_sz);
262 if (new_block_pos < 0) {
263 TRACE(ft_t_noise,
264 "new_block_pos " LL_X " < 0", LL(new_block_pos));
265 zft_resid = (int)new_block_pos;
266 new_block_pos = 0;
267 exceed = 1;
268 } else if (new_block_pos > vol_block_count) {
269 TRACE(ft_t_noise,
270 "new_block_pos " LL_X " exceeds size of volume " LL_X,
271 LL(new_block_pos), LL(vol_block_count));
272 zft_resid = (int)(vol_block_count - new_block_pos);
273 new_block_pos = vol_block_count;
274 exceed = 1;
275 } else {
276 exceed = 0;
277 }
278 if (zft_use_compression && volume->use_compression) {
279 TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
280 result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume,
281 zft_deblock_buf);
282 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
283 pos->tape_pos += pos->seg_byte_pos;
284 } else {
285 pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz);
286 pos->tape_pos = zft_calc_tape_pos(volume->start_seg);
287 pos->tape_pos += pos->volume_pos;
288 pos->seg_pos = zft_calc_seg_byte_coord(&pos->seg_byte_pos,
289 pos->tape_pos);
290 }
291 zft_just_before_eof = volume->size == pos->volume_pos;
292 if (zft_just_before_eof) {
293 /* why this? because zft_file_no checks agains start
294 * and end segment of a volume. We do not want to
295 * advance to the next volume with this function.
296 */
297 TRACE(ft_t_noise, "set zft_just_before_eof");
298 zft_position_before_eof(pos, volume);
299 }
300 TRACE(ft_t_noise, "\n"
301 KERN_INFO "new_seg_pos : %d\n"
302 KERN_INFO "new_tape_pos: " LL_X "\n"
303 KERN_INFO "vol_size : " LL_X "\n"
304 KERN_INFO "seg_byte_pos: %d\n"
305 KERN_INFO "blk_sz : %d",
306 pos->seg_pos, LL(pos->tape_pos),
307 LL(volume->size), pos->seg_byte_pos,
308 volume->blk_sz);
309 if (!exceed) {
310 zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos,
311 volume->blk_sz);
312 }
313 if (zft_resid < 0) {
314 zft_resid = -zft_resid;
315 }
316 TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result;
317}
318
319static int mt_fsr(int *arg)
320{
321 int result;
322 TRACE_FUN(ft_t_flow);
323
324 result = seek_block(zft_pos.volume_pos, *arg, &zft_pos);
325 TRACE_EXIT result;
326}
327
328static int mt_bsr(int *arg)
329{
330 int result;
331 TRACE_FUN(ft_t_flow);
332
333 result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos);
334 TRACE_EXIT result;
335}
336
337static int mt_weof(int *arg)
338{
339 int result;
340 TRACE_FUN(ft_t_flow);
341
342 TRACE_CATCH(zft_flush_buffers(),);
343 result = zft_weof(*arg, &zft_pos);
344 TRACE_EXIT result;
345}
346
347static int mt_rew(int *dummy)
348{
349 int result;
350 TRACE_FUN(ft_t_flow);
351
352 if(zft_header_read) {
353 (void)zft_def_idle_state();
354 }
355 result = ftape_seek_to_bot();
356 zft_reset_position(&zft_pos);
357 TRACE_EXIT result;
358}
359
360static int mt_offl(int *dummy)
361{
362 int result;
363 TRACE_FUN(ft_t_flow);
364
365 going_offline= 1;
366 result = mt_rew(NULL);
367 TRACE_EXIT result;
368}
369
370static int mt_nop(int *dummy)
371{
372 TRACE_FUN(ft_t_flow);
373 /* should we set tape status?
374 */
375 if (!zft_offline) { /* offline includes no_tape */
376 (void)zft_def_idle_state();
377 }
378 TRACE_EXIT 0;
379}
380
381static int mt_reten(int *dummy)
382{
383 int result;
384 TRACE_FUN(ft_t_flow);
385
386 if(zft_header_read) {
387 (void)zft_def_idle_state();
388 }
389 result = ftape_seek_to_eot();
390 if (result >= 0) {
391 result = ftape_seek_to_bot();
392 }
393 TRACE_EXIT(result);
394}
395
396static int fsfbsfm(int arg, zft_position *pos)
397{
398 const zft_volinfo *vtbl;
399 __s64 block_pos;
400 TRACE_FUN(ft_t_flow);
401
402 /* What to do? This should seek to the next file-mark and
403 * position BEFORE. That is, a next write would just extend
404 * the current file. Well. Let's just seek to the end of the
405 * current file, if count == 1. If count > 1, then do a
406 * "mt_fsf(count - 1)", and then seek to the end of that file.
407 * If count == 0, do nothing
408 */
409 if (arg == 0) {
410 TRACE_EXIT 0;
411 }
412 zft_just_before_eof = 0;
413 TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos),
414 if (arg > 0) {
415 zft_resid ++;
416 });
417 vtbl = zft_find_volume(pos->seg_pos);
418 block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz);
419 (void)seek_block(0, block_pos, pos);
420 if (pos->volume_pos != vtbl->size) {
421 zft_just_before_eof = 0;
422 zft_resid = 1;
423 /* we didn't managed to go there */
424 TRACE_ABORT(-EIO, ft_t_err,
425 "wanted file position " LL_X ", arrived at " LL_X,
426 LL(vtbl->size), LL(pos->volume_pos));
427 }
428 zft_just_before_eof = 1;
429 TRACE_EXIT 0;
430}
431
432static int mt_bsfm(int *arg)
433{
434 int result;
435 TRACE_FUN(ft_t_flow);
436
437 result = fsfbsfm(-*arg, &zft_pos);
438 TRACE_EXIT result;
439}
440
441static int mt_fsfm(int *arg)
442{
443 int result;
444 TRACE_FUN(ft_t_flow);
445
446 result = fsfbsfm(*arg, &zft_pos);
447 TRACE_EXIT result;
448}
449
450static int mt_eom(int *dummy)
451{
452 TRACE_FUN(ft_t_flow);
453
454 zft_skip_to_eom(&zft_pos);
455 TRACE_EXIT 0;
456}
457
458static int mt_erase(int *dummy)
459{
460 int result;
461 TRACE_FUN(ft_t_flow);
462
463 result = zft_erase();
464 TRACE_EXIT result;
465}
466
467static int mt_ras2(int *dummy)
468{
469 int result;
470 TRACE_FUN(ft_t_flow);
471
472 result = -ENOSYS;
473 TRACE_EXIT result;
474}
475
476/* Sets the new blocksize in BYTES
477 *
478 */
479static int mt_setblk(int *new_size)
480{
481 TRACE_FUN(ft_t_flow);
482
483 if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) {
484 TRACE_ABORT(-EINVAL, ft_t_info,
485 "desired blk_sz (%d) should be <= %d bytes",
486 *new_size, ZFT_MAX_BLK_SZ);
487 }
488 if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) {
489 TRACE_ABORT(-EINVAL, ft_t_info,
490 "desired blk_sz (%d) must be a multiple of %d bytes",
491 *new_size, FT_SECTOR_SIZE);
492 }
493 if (*new_size == 0) {
494 if (zft_use_compression) {
495 TRACE_ABORT(-EINVAL, ft_t_info,
496 "Variable block size not yet "
497 "supported with compression");
498 }
499 *new_size = 1;
500 }
501 zft_blk_sz = *new_size;
502 TRACE_EXIT 0;
503}
504
505static int mt_setdensity(int *arg)
506{
507 TRACE_FUN(ft_t_flow);
508
509 SET_TRACE_LEVEL(*arg);
510 TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL);
511 if ((int)TRACE_LEVEL != *arg) {
512 TRACE_EXIT -EINVAL;
513 }
514 TRACE_EXIT 0;
515}
516
517static int mt_seek(int *new_block_pos)
518{
519 int result= 0;
520 TRACE_FUN(ft_t_any);
521
522 result = seek_block(0, (__s64)*new_block_pos, &zft_pos);
523 TRACE_EXIT result;
524}
525
526/* OK, this is totally different from SCSI, but the worst thing that can
527 * happen is that there is not enough defragmentated memory that can be
528 * allocated. Also, there is a hardwired limit of 16 dma buffers in the
529 * stock ftape module. This shouldn't bring the system down.
530 *
531 * NOTE: the argument specifies the total number of dma buffers to use.
532 * The driver needs at least 3 buffers to function at all.
533 *
534 */
535static int mt_setdrvbuffer(int *cnt)
536{
537 TRACE_FUN(ft_t_flow);
538
539 if (*cnt < 3) {
540 TRACE_EXIT -EINVAL;
541 }
542 TRACE_CATCH(ftape_set_nr_buffers(*cnt),);
543 TRACE_EXIT 0;
544}
545/* return the block position from start of volume
546 */
547static int mt_tell(int *arg)
548{
549 TRACE_FUN(ft_t_flow);
550
551 *arg = zft_div_blksz(zft_pos.volume_pos,
552 zft_find_volume(zft_pos.seg_pos)->blk_sz);
553 TRACE_EXIT 0;
554}
555
556static int mt_compression(int *arg)
557{
558 TRACE_FUN(ft_t_flow);
559
560 /* Ok. We could also check whether compression is available at
561 * all by trying to load the compression module. We could
562 * also check for a block size of 1 byte which is illegal
563 * with compression. Instead of doing it here we rely on
564 * zftape_write() to do the proper checks.
565 */
566 if ((unsigned int)*arg > 1) {
567 TRACE_EXIT -EINVAL;
568 }
569 if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */
570 TRACE_ABORT(-EINVAL, ft_t_info,
571 "Compression not yet supported "
572 "with variable block size");
573 }
574 zft_mt_compression = *arg;
575 if ((zft_unit & ZFT_ZIP_MODE) == 0) {
576 zft_use_compression = zft_mt_compression;
577 }
578 TRACE_EXIT 0;
579}
580
581/* check whether write access is allowed. Write access is denied when
582 * + zft_write_protected == 1 -- this accounts for either hard write
583 * protection of the cartridge or for
584 * O_RDONLY access mode of the tape device
585 * + zft_offline == 1 -- this meany that there is either no tape
586 * or that the MTOFFLINE ioctl has been
587 * previously issued (`soft eject')
588 * + ft_formatted == 0 -- this means that the cartridge is not
589 * formatted
590 * Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try
591 * to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we
592 * deny writes when
593 * + zft_qic_mode ==1 &&
594 * (!zft_tape_at_lbot() && -- tape no at logical BOT
595 * !(zft_tape_at_eom() || -- tape not at logical EOM (or EOD)
596 * (zft_tape_at_eom() &&
597 * zft_old_ftape()))) -- we can't add new volume to tapes
598 * written by old ftape because ftape
599 * don't use the volume table
600 *
601 * when the drive is in true raw mode (aka /dev/rawft0) then we don't
602 * care about LBOT and EOM conditions. This device is intended for a
603 * user level program that wants to truly implement the QIC-80 compliance
604 * at the logical data layout level of the cartridge, i.e. implement all
605 * that volume table and volume directory stuff etc.<
606 */
607int zft_check_write_access(zft_position *pos)
608{
609 TRACE_FUN(ft_t_flow);
610
611 if (zft_offline) { /* offline includes no_tape */
612 TRACE_ABORT(-ENXIO,
613 ft_t_info, "tape is offline or no cartridge");
614 }
615 if (!ft_formatted) {
616 TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
617 }
618 if (zft_write_protected) {
619 TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected");
620 }
621 if (zft_qic_mode) {
622 /* check BOT condition */
623 if (!zft_tape_at_lbot(pos)) {
624 /* protect cartridges written by old ftape if
625 * not at BOT because they use the vtbl
626 * segment for storing data
627 */
628 if (zft_old_ftape) {
629 TRACE_ABORT(-EACCES, ft_t_warn,
630 "Cannot write to cartridges written by old ftape when not at BOT");
631 }
632 /* not at BOT, but allow writes at EOD, of course
633 */
634 if (!zft_tape_at_eod(pos)) {
635 TRACE_ABORT(-EACCES, ft_t_info,
636 "tape not at BOT and not at EOD");
637 }
638 }
639 /* fine. Now the tape is either at BOT or at EOD. */
640 }
641 /* or in raw mode in which case we don't care about BOT and EOD */
642 TRACE_EXIT 0;
643}
644
645/* OPEN routine called by kernel-interface code
646 *
647 * NOTE: this is also called by mt_reset() with dev_minor == -1
648 * to fake a reopen after a reset.
649 */
650int _zft_open(unsigned int dev_minor, unsigned int access_mode)
651{
652 static unsigned int tape_unit;
653 static unsigned int file_access_mode;
654 int result;
655 TRACE_FUN(ft_t_flow);
656
657 if ((int)dev_minor == -1) {
658 /* fake reopen */
659 zft_unit = tape_unit;
660 access_mode = file_access_mode;
661 zft_init_driver(); /* reset all static data to defaults */
662 } else {
663 tape_unit = dev_minor;
664 file_access_mode = access_mode;
665 if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) {
666 TRACE_ABORT(-ENXIO, ft_t_err,
667 "ftape_enable failed: %d", result);
668 }
669 if (ft_new_tape || ft_no_tape || !ft_formatted ||
670 (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) ||
671 (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) {
672 /* reset all static data to defaults,
673 */
674 zft_init_driver();
675 }
676 zft_unit = dev_minor;
677 }
678 zft_set_flags(zft_unit); /* decode the minor bits */
679 if (zft_blk_sz == 1 && zft_use_compression) {
680 ftape_disable(); /* resets ft_no_tape */
681 TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet "
682 "supported with compression");
683 }
684 /* no need for most of the buffers when no tape or not
685 * formatted. for the read/write operations, it is the
686 * regardless whether there is no tape, a not-formatted tape
687 * or the whether the driver is soft offline.
688 * Nevertheless we allow some ioctls with non-formatted tapes,
689 * like rewind and reset.
690 */
691 if (ft_no_tape || !ft_formatted) {
692 zft_uninit_mem();
693 }
694 if (ft_no_tape) {
695 zft_offline = 1; /* so we need not test two variables */
696 }
697 if ((access_mode == O_WRONLY || access_mode == O_RDWR) &&
698 (ft_write_protected || ft_no_tape)) {
699 ftape_disable(); /* resets ft_no_tape */
700 TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS,
701 ft_t_warn, "wrong access mode %s cartridge",
702 ft_no_tape ? "without a" : "with write protected");
703 }
704 zft_write_protected = (access_mode == O_RDONLY ||
705 ft_write_protected != 0);
706 if (zft_write_protected) {
707 TRACE(ft_t_noise,
708 "read only access mode: %d, "
709 "drive write protected: %d",
710 access_mode == O_RDONLY,
711 ft_write_protected != 0);
712 }
713 if (!zft_offline) {
714 TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE),
715 ftape_disable());
716 }
717 /* zft_seg_pos should be greater than the vtbl segpos but not
718 * if in compatibility mode and only after we read in the
719 * header segments
720 *
721 * might also be a problem if the user makes a backup with a
722 * *qft* device and rewinds it with a raw device.
723 */
724 if (zft_qic_mode &&
725 !zft_old_ftape &&
726 zft_pos.seg_pos >= 0 &&
727 zft_header_read &&
728 zft_pos.seg_pos <= ft_first_data_segment) {
729 TRACE(ft_t_noise, "you probably mixed up the zftape devices!");
730 zft_reset_position(&zft_pos);
731 }
732 TRACE_EXIT 0;
733}
734
735/* RELEASE routine called by kernel-interface code
736 */
737int _zft_close(void)
738{
739 int result = 0;
740 TRACE_FUN(ft_t_flow);
741
742 if (zft_offline) {
743 /* call the hardware release routine. Puts the drive offline */
744 ftape_disable();
745 TRACE_EXIT 0;
746 }
747 if (!(ft_write_protected || zft_old_ftape)) {
748 result = zft_flush_buffers();
749 TRACE(ft_t_noise, "writing file mark at current position");
750 if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) {
751 zft_move_past_eof(&zft_pos);
752 }
753 if ((zft_tape_at_lbot(&zft_pos) ||
754 !(zft_unit & FTAPE_NO_REWIND))) {
755 if (result >= 0) {
756 result = zft_update_header_segments();
757 } else {
758 TRACE(ft_t_err,
759 "Error: unable to update header segments");
760 }
761 }
762 }
763 ftape_abort_operation();
764 if (!(zft_unit & FTAPE_NO_REWIND)) {
765 TRACE(ft_t_noise, "rewinding tape");
766 if (ftape_seek_to_bot() < 0 && result >= 0) {
767 result = -EIO; /* keep old value */
768 }
769 zft_reset_position(&zft_pos);
770 }
771 zft_zap_read_buffers();
772 /* now free up memory as much as possible. We don't destroy
773 * the deblock buffer if it containes a valid segment.
774 */
775 if (zft_deblock_segment == -1) {
776 zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE);
777 }
778 /* high level driver status, forces creation of a new volume
779 * when calling ftape_write again and not zft_just_before_eof
780 */
781 zft_io_state = zft_idle;
782 if (going_offline) {
783 zft_init_driver();
784 zft_uninit_mem();
785 going_offline = 0;
786 zft_offline = 1;
787 } else if (zft_cmpr_lock(0 /* don't load */) == 0) {
788 (*zft_cmpr_ops->reset)(); /* unlock it again */
789 }
790 zft_memory_stats();
791 /* call the hardware release routine. Puts the drive offline */
792 ftape_disable();
793 TRACE_EXIT result;
794}
795
796/*
797 * the wrapper function around the wrapper MTIOCTOP ioctl
798 */
799static int mtioctop(struct mtop *mtop, int arg_size)
800{
801 int result = 0;
802 fun_entry *mt_fun_entry;
803 TRACE_FUN(ft_t_flow);
804
805 if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) {
806 TRACE_EXIT -EINVAL;
807 }
808 TRACE(ft_t_noise, "calling MTIOCTOP command: %s",
809 mt_funs[mtop->mt_op].name);
810 mt_fun_entry= &mt_funs[mtop->mt_op];
811 zft_resid = mtop->mt_count;
812 if (!mt_fun_entry->offline && zft_offline) {
813 if (ft_no_tape) {
814 TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
815 } else {
816 TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
817 }
818 }
819 if (!mt_fun_entry->not_formatted && !ft_formatted) {
820 TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
821 }
822 if (!mt_fun_entry->write_protected) {
823 TRACE_CATCH(zft_check_write_access(&zft_pos),);
824 }
825 if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) {
826 TRACE_CATCH(zft_def_idle_state(),);
827 }
828 if (!zft_qic_mode && !mt_fun_entry->raw_mode) {
829 TRACE_ABORT(-EACCES, ft_t_info,
830"Drive needs to be in QIC-80 compatibility mode for this command");
831 }
832 result = (mt_fun_entry->function)(&mtop->mt_count);
833 if (zft_tape_at_lbot(&zft_pos)) {
834 TRACE_CATCH(zft_update_header_segments(),);
835 }
836 if (result >= 0) {
837 zft_resid = 0;
838 }
839 TRACE_EXIT result;
840}
841
842/*
843 * standard MTIOCGET ioctl
844 */
845static int mtiocget(struct mtget *mtget, int arg_size)
846{
847 const zft_volinfo *volume;
848 __s64 max_tape_pos;
849 TRACE_FUN(ft_t_flow);
850
851 if (arg_size != sizeof(struct mtget)) {
852 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
853 arg_size);
854 }
855 mtget->mt_type = ft_drive_type.vendor_id + 0x800000;
856 mtget->mt_dsreg = ft_last_status.space;
857 mtget->mt_erreg = ft_last_error.space; /* error register */
858 mtget->mt_resid = zft_resid; /* residuum of writes, reads and
859 * MTIOCTOP commands
860 */
861 if (!zft_offline) { /* neither no_tape nor soft offline */
862 mtget->mt_gstat = GMT_ONLINE(~0UL);
863 /* should rather return the status of the cartridge
864 * than the access mode of the file, therefor use
865 * ft_write_protected, not zft_write_protected
866 */
867 if (ft_write_protected) {
868 mtget->mt_gstat |= GMT_WR_PROT(~0UL);
869 }
870 if(zft_header_read) { /* this catches non-formatted */
871 volume = zft_find_volume(zft_pos.seg_pos);
872 mtget->mt_fileno = volume->count;
873 max_tape_pos = zft_capacity - zft_blk_sz;
874 if (zft_use_compression) {
875 max_tape_pos -= ZFT_CMPR_OVERHEAD;
876 }
877 if (zft_tape_at_eod(&zft_pos)) {
878 mtget->mt_gstat |= GMT_EOD(~0UL);
879 }
880 if (zft_pos.tape_pos > max_tape_pos) {
881 mtget->mt_gstat |= GMT_EOT(~0UL);
882 }
883 mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos,
884 volume->blk_sz);
885 if (zft_just_before_eof) {
886 mtget->mt_gstat |= GMT_EOF(~0UL);
887 }
888 if (zft_tape_at_lbot(&zft_pos)) {
889 mtget->mt_gstat |= GMT_BOT(~0UL);
890 }
891 } else {
892 mtget->mt_fileno = mtget->mt_blkno = -1;
893 if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) {
894 mtget->mt_gstat |= GMT_BOT(~0UL);
895 }
896 }
897 } else {
898 if (ft_no_tape) {
899 mtget->mt_gstat = GMT_DR_OPEN(~0UL);
900 } else {
901 mtget->mt_gstat = 0UL;
902 }
903 mtget->mt_fileno = mtget->mt_blkno = -1;
904 }
905 TRACE_EXIT 0;
906}
907
908#ifdef MTIOCRDFTSEG
909/*
910 * Read a floppy tape segment. This is useful for manipulating the
911 * volume table, and read the old header segment before re-formatting
912 * the cartridge.
913 */
914static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size)
915{
916 TRACE_FUN(ft_t_flow);
917
918 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG");
919 if (zft_qic_mode) {
920 TRACE_ABORT(-EACCES, ft_t_info,
921 "driver needs to be in raw mode for this ioctl");
922 }
923 if (arg_size != sizeof(struct mtftseg)) {
924 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
925 arg_size);
926 }
927 if (zft_offline) {
928 TRACE_EXIT -ENXIO;
929 }
930 if (mtftseg->mt_mode != FT_RD_SINGLE &&
931 mtftseg->mt_mode != FT_RD_AHEAD) {
932 TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode");
933 }
934 if (!ft_formatted) {
935 TRACE_EXIT -EACCES; /* -ENXIO ? */
936
937 }
938 if (!zft_header_read) {
939 TRACE_CATCH(zft_def_idle_state(),);
940 }
941 if (mtftseg->mt_segno > ft_last_data_segment) {
942 TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large");
943 }
944 mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno,
945 zft_deblock_buf,
946 mtftseg->mt_mode);
947 if (mtftseg->mt_result < 0) {
948 /* a negativ result is not an ioctl error. if
949 * the user wants to read damaged tapes,
950 * it's up to her/him
951 */
952 TRACE_EXIT 0;
953 }
954 if (copy_to_user(mtftseg->mt_data,
955 zft_deblock_buf,
956 mtftseg->mt_result) != 0) {
957 TRACE_EXIT -EFAULT;
958 }
959 TRACE_EXIT 0;
960}
961#endif
962
963#ifdef MTIOCWRFTSEG
964/*
965 * write a floppy tape segment. This version features writing of
966 * deleted address marks, and gracefully ignores the (software)
967 * ft_formatted flag to support writing of header segments after
968 * formatting.
969 */
970static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size)
971{
972 int result;
973 TRACE_FUN(ft_t_flow);
974
975 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG");
976 if (zft_write_protected || zft_qic_mode) {
977 TRACE_EXIT -EACCES;
978 }
979 if (arg_size != sizeof(struct mtftseg)) {
980 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
981 arg_size);
982 }
983 if (zft_offline) {
984 TRACE_EXIT -ENXIO;
985 }
986 if (mtftseg->mt_mode != FT_WR_ASYNC &&
987 mtftseg->mt_mode != FT_WR_MULTI &&
988 mtftseg->mt_mode != FT_WR_SINGLE &&
989 mtftseg->mt_mode != FT_WR_DELETE) {
990 TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode");
991 }
992 /*
993 * We don't check for ft_formatted, because this gives
994 * only the software status of the driver.
995 *
996 * We assume that the user knows what it is
997 * doing. And rely on the low level stuff to fail
998 * when the tape isn't formatted. We only make sure
999 * that The header segment buffer is allocated,
1000 * because it holds the bad sector map.
1001 */
1002 if (zft_hseg_buf == NULL) {
1003 TRACE_EXIT -ENXIO;
1004 }
1005 if (mtftseg->mt_mode != FT_WR_DELETE) {
1006 if (copy_from_user(zft_deblock_buf,
1007 mtftseg->mt_data,
1008 FT_SEGMENT_SIZE) != 0) {
1009 TRACE_EXIT -EFAULT;
1010 }
1011 }
1012 mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno,
1013 zft_deblock_buf,
1014 mtftseg->mt_mode);
1015 if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) {
1016 /*
1017 * a negativ result is not an ioctl error. if
1018 * the user wants to write damaged tapes,
1019 * it's up to her/him
1020 */
1021 if ((result = ftape_loop_until_writes_done()) < 0) {
1022 mtftseg->mt_result = result;
1023 }
1024 }
1025 TRACE_EXIT 0;
1026}
1027#endif
1028
1029#ifdef MTIOCVOLINFO
1030/*
1031 * get information about volume positioned at.
1032 */
1033static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size)
1034{
1035 const zft_volinfo *volume;
1036 TRACE_FUN(ft_t_flow);
1037
1038 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO");
1039 if (arg_size != sizeof(struct mtvolinfo)) {
1040 TRACE_ABORT(-EINVAL,
1041 ft_t_info, "bad argument size: %d", arg_size);
1042 }
1043 if (zft_offline) {
1044 TRACE_EXIT -ENXIO;
1045 }
1046 if (!ft_formatted) {
1047 TRACE_EXIT -EACCES;
1048 }
1049 TRACE_CATCH(zft_def_idle_state(),);
1050 volume = zft_find_volume(zft_pos.seg_pos);
1051 volinfo->mt_volno = volume->count;
1052 volinfo->mt_blksz = volume->blk_sz == 1 ? 0 : volume->blk_sz;
1053 volinfo->mt_size = volume->size >> 10;
1054 volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) -
1055 (zft_calc_tape_pos(volume->start_seg) >> 10));
1056 volinfo->mt_cmpr = volume->use_compression;
1057 TRACE_EXIT 0;
1058}
1059#endif
1060
1061#ifdef ZFT_OBSOLETE
1062static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size)
1063{
1064 TRACE_FUN(ft_t_flow);
1065
1066 TRACE(ft_t_noise, "\n"
1067 KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n"
1068 KERN_INFO "This ioctl is here merely for compatibility.\n"
1069 KERN_INFO "Please use MTIOCVOLINFO instead");
1070 if (arg_size != sizeof(struct mtblksz)) {
1071 TRACE_ABORT(-EINVAL,
1072 ft_t_info, "bad argument size: %d", arg_size);
1073 }
1074 if (zft_offline) {
1075 TRACE_EXIT -ENXIO;
1076 }
1077 if (!ft_formatted) {
1078 TRACE_EXIT -EACCES;
1079 }
1080 TRACE_CATCH(zft_def_idle_state(),);
1081 blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz;
1082 TRACE_EXIT 0;
1083}
1084#endif
1085
1086#ifdef MTIOCGETSIZE
1087/*
1088 * get the capacity of the tape cartridge.
1089 */
1090static int mtiocgetsize(struct mttapesize *size, int arg_size)
1091{
1092 TRACE_FUN(ft_t_flow);
1093
1094 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE");
1095 if (arg_size != sizeof(struct mttapesize)) {
1096 TRACE_ABORT(-EINVAL,
1097 ft_t_info, "bad argument size: %d", arg_size);
1098 }
1099 if (zft_offline) {
1100 TRACE_EXIT -ENXIO;
1101 }
1102 if (!ft_formatted) {
1103 TRACE_EXIT -EACCES;
1104 }
1105 TRACE_CATCH(zft_def_idle_state(),);
1106 size->mt_capacity = (unsigned int)(zft_capacity>>10);
1107 size->mt_used = (unsigned int)(zft_get_eom_pos()>>10);
1108 TRACE_EXIT 0;
1109}
1110#endif
1111
1112static int mtiocpos(struct mtpos *mtpos, int arg_size)
1113{
1114 int result;
1115 TRACE_FUN(ft_t_flow);
1116
1117 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS");
1118 if (arg_size != sizeof(struct mtpos)) {
1119 TRACE_ABORT(-EINVAL,
1120 ft_t_info, "bad argument size: %d", arg_size);
1121 }
1122 result = mt_tell((int *)&mtpos->mt_blkno);
1123 TRACE_EXIT result;
1124}
1125
1126#ifdef MTIOCFTFORMAT
1127/*
1128 * formatting of floppy tape cartridges. This is intended to be used
1129 * together with the MTIOCFTCMD ioctl and the new mmap feature
1130 */
1131
1132/*
1133 * This function uses ftape_decode_header_segment() to inform the low
1134 * level ftape module about the new parameters.
1135 *
1136 * It erases the hseg_buf. The calling process must specify all
1137 * parameters to assure proper operation.
1138 *
1139 * return values: -EINVAL - wrong argument size
1140 * -EINVAL - if ftape_decode_header_segment() failed.
1141 */
1142static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf)
1143{
1144 ft_trace_t old_level = TRACE_LEVEL;
1145 TRACE_FUN(ft_t_flow);
1146
1147 TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS");
1148 memset(hseg_buf, 0, FT_SEGMENT_SIZE);
1149 PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC);
1150
1151 /* fill in user specified parameters
1152 */
1153 hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode;
1154 PUT2(hseg_buf, FT_SPT, p->ft_spt);
1155 hseg_buf[FT_TPC] = (__u8)p->ft_tpc;
1156 hseg_buf[FT_FHM] = (__u8)p->ft_fhm;
1157 hseg_buf[FT_FTM] = (__u8)p->ft_ftm;
1158
1159 /* fill in sane defaults to make ftape happy.
1160 */
1161 hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */
1162 if (p->ft_fmtcode == fmt_big) {
1163 PUT4(hseg_buf, FT_6_HSEG_1, 0);
1164 PUT4(hseg_buf, FT_6_HSEG_2, 1);
1165 PUT4(hseg_buf, FT_6_FRST_SEG, 2);
1166 PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1167 } else {
1168 PUT2(hseg_buf, FT_HSEG_1, 0);
1169 PUT2(hseg_buf, FT_HSEG_2, 1);
1170 PUT2(hseg_buf, FT_FRST_SEG, 2);
1171 PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1172 }
1173
1174 /* Synchronize with the low level module. This is particularly
1175 * needed for unformatted cartridges as the QIC std was previously
1176 * unknown BUT is needed to set data rate and to calculate timeouts.
1177 */
1178 TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK),
1179 _res = -EINVAL);
1180
1181 /* The following will also recalcualte the timeouts for the tape
1182 * length and QIC std we want to format to.
1183 * abort with -EINVAL rather than -EIO
1184 */
1185 SET_TRACE_LEVEL(ft_t_warn);
1186 TRACE_CATCH(ftape_decode_header_segment(hseg_buf),
1187 SET_TRACE_LEVEL(old_level); _res = -EINVAL);
1188 SET_TRACE_LEVEL(old_level);
1189 TRACE_EXIT 0;
1190}
1191
1192/*
1193 * Return the internal SOFTWARE status of the kernel driver. This does
1194 * NOT query the tape drive about its status.
1195 */
1196static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer)
1197{
1198 TRACE_FUN(ft_t_flow);
1199
1200 TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS");
1201 p->ft_qicstd = ft_qic_std;
1202 p->ft_fmtcode = ft_format_code;
1203 p->ft_fhm = hseg_buffer[FT_FHM];
1204 p->ft_ftm = hseg_buffer[FT_FTM];
1205 p->ft_spt = ft_segments_per_track;
1206 p->ft_tpc = ft_tracks_per_tape;
1207 TRACE_EXIT 0;
1208}
1209
1210static int mtiocftformat(struct mtftformat *mtftformat, int arg_size)
1211{
1212 int result;
1213 union fmt_arg *arg = &mtftformat->fmt_arg;
1214 TRACE_FUN(ft_t_flow);
1215
1216 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT");
1217 if (zft_offline) {
1218 if (ft_no_tape) {
1219 TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
1220 } else {
1221 TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
1222 }
1223 }
1224 if (zft_qic_mode) {
1225 TRACE_ABORT(-EACCES, ft_t_info,
1226 "driver needs to be in raw mode for this ioctl");
1227 }
1228 if (zft_hseg_buf == NULL) {
1229 TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
1230 }
1231 zft_header_read = 0;
1232 switch(mtftformat->fmt_op) {
1233 case FTFMT_SET_PARMS:
1234 TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1235 TRACE_EXIT 0;
1236 case FTFMT_GET_PARMS:
1237 TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1238 TRACE_EXIT 0;
1239 case FTFMT_FORMAT_TRACK:
1240 if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) ||
1241 (!ft_formatted && zft_write_protected)) {
1242 TRACE_ABORT(-EACCES, ft_t_info, "Write access denied");
1243 }
1244 TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track,
1245 arg->fmt_track.ft_gap3),);
1246 TRACE_EXIT 0;
1247 case FTFMT_STATUS:
1248 TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),);
1249 TRACE_EXIT 0;
1250 case FTFMT_VERIFY:
1251 TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment,
1252 (SectorMap *)&arg->fmt_verify.ft_bsm),);
1253 TRACE_EXIT 0;
1254 default:
1255 TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation");
1256 }
1257 TRACE_EXIT result;
1258}
1259#endif
1260
1261#ifdef MTIOCFTCMD
1262/*
1263 * send a QIC-117 command to the drive, with optional timeouts,
1264 * parameter and result bits. This is intended to be used together
1265 * with the formatting ioctl.
1266 */
1267static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)
1268{
1269 int i;
1270 TRACE_FUN(ft_t_flow);
1271
1272 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");
1273 if (!capable(CAP_SYS_ADMIN)) {
1274 TRACE_ABORT(-EPERM, ft_t_info,
1275 "need CAP_SYS_ADMIN capability to send raw qic-117 commands");
1276 }
1277 if (zft_qic_mode) {
1278 TRACE_ABORT(-EACCES, ft_t_info,
1279 "driver needs to be in raw mode for this ioctl");
1280 }
1281 if (arg_size != sizeof(struct mtftcmd)) {
1282 TRACE_ABORT(-EINVAL,
1283 ft_t_info, "bad argument size: %d", arg_size);
1284 }
1285 if (ftcmd->ft_wait_before) {
1286 TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before,
1287 &ftcmd->ft_status),);
1288 }
1289 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1290 goto ftmtcmd_error;
1291 if (ftcmd->ft_result_bits != 0) {
1292 TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result,
1293 ftcmd->ft_cmd,
1294 ftcmd->ft_result_bits),);
1295 } else {
1296 TRACE_CATCH(ftape_command(ftcmd->ft_cmd),);
1297 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1298 goto ftmtcmd_error;
1299 for (i = 0; i < ftcmd->ft_parm_cnt; i++) {
1300 TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),);
1301 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1302 goto ftmtcmd_error;
1303 }
1304 }
1305 if (ftcmd->ft_wait_after != 0) {
1306 TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after,
1307 &ftcmd->ft_status),);
1308 }
1309ftmtcmd_error:
1310 if (ftcmd->ft_status & QIC_STATUS_ERROR) {
1311 TRACE(ft_t_noise, "error status set");
1312 TRACE_CATCH(ftape_report_error(&ftcmd->ft_error,
1313 &ftcmd->ft_cmd, 1),);
1314 }
1315 TRACE_EXIT 0; /* this is not an i/o error */
1316}
1317#endif
1318
1319/* IOCTL routine called by kernel-interface code
1320 */
1321int _zft_ioctl(unsigned int command, void __user * arg)
1322{
1323 int result;
1324 union { struct mtop mtop;
1325 struct mtget mtget;
1326 struct mtpos mtpos;
1327#ifdef MTIOCRDFTSEG
1328 struct mtftseg mtftseg;
1329#endif
1330#ifdef MTIOCVOLINFO
1331 struct mtvolinfo mtvolinfo;
1332#endif
1333#ifdef MTIOCGETSIZE
1334 struct mttapesize mttapesize;
1335#endif
1336#ifdef MTIOCFTFORMAT
1337 struct mtftformat mtftformat;
1338#endif
1339#ifdef ZFT_OBSOLETE
1340 struct mtblksz mtblksz;
1341#endif
1342#ifdef MTIOCFTCMD
1343 struct mtftcmd mtftcmd;
1344#endif
1345 } krnl_arg;
1346 int arg_size = _IOC_SIZE(command);
1347 int dir = _IOC_DIR(command);
1348 TRACE_FUN(ft_t_flow);
1349
1350 /* This check will only catch arguments that are too large !
1351 */
1352 if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) {
1353 TRACE_ABORT(-EINVAL,
1354 ft_t_info, "bad argument size: %d", arg_size);
1355 }
1356 if (dir & _IOC_WRITE) {
1357 if (copy_from_user(&krnl_arg, arg, arg_size) != 0) {
1358 TRACE_EXIT -EFAULT;
1359 }
1360 }
1361 TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command);
1362 switch (command) {
1363 case MTIOCTOP:
1364 result = mtioctop(&krnl_arg.mtop, arg_size);
1365 break;
1366 case MTIOCGET:
1367 result = mtiocget(&krnl_arg.mtget, arg_size);
1368 break;
1369 case MTIOCPOS:
1370 result = mtiocpos(&krnl_arg.mtpos, arg_size);
1371 break;
1372#ifdef MTIOCVOLINFO
1373 case MTIOCVOLINFO:
1374 result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size);
1375 break;
1376#endif
1377#ifdef ZFT_OBSOLETE
1378 case MTIOC_ZFTAPE_GETBLKSZ:
1379 result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size);
1380 break;
1381#endif
1382#ifdef MTIOCRDFTSEG
1383 case MTIOCRDFTSEG: /* read a segment via ioctl */
1384 result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size);
1385 break;
1386#endif
1387#ifdef MTIOCWRFTSEG
1388 case MTIOCWRFTSEG: /* write a segment via ioctl */
1389 result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size);
1390 break;
1391#endif
1392#ifdef MTIOCGETSIZE
1393 case MTIOCGETSIZE:
1394 result = mtiocgetsize(&krnl_arg.mttapesize, arg_size);
1395 break;
1396#endif
1397#ifdef MTIOCFTFORMAT
1398 case MTIOCFTFORMAT:
1399 result = mtiocftformat(&krnl_arg.mtftformat, arg_size);
1400 break;
1401#endif
1402#ifdef MTIOCFTCMD
1403 case MTIOCFTCMD:
1404 result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size);
1405 break;
1406#endif
1407 default:
1408 result = -EINVAL;
1409 break;
1410 }
1411 if ((result >= 0) && (dir & _IOC_READ)) {
1412 if (copy_to_user(arg, &krnl_arg, arg_size) != 0) {
1413 TRACE_EXIT -EFAULT;
1414 }
1415 }
1416 TRACE_EXIT result;
1417}
diff --git a/drivers/char/ftape/zftape/zftape-ctl.h b/drivers/char/ftape/zftape/zftape-ctl.h
deleted file mode 100644
index 8e6f2d7ac74e..000000000000
--- a/drivers/char/ftape/zftape/zftape-ctl.h
+++ /dev/null
@@ -1,58 +0,0 @@
1#ifndef _ZFTAPE_CTL_H
2#define _ZFTAPE_CTL_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/zftape/zftape-ctl.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:02 $
25 *
26 * This file contains the non-standard IOCTL related definitions
27 * for the QIC-40/80 floppy-tape driver for Linux.
28 */
29
30#include <linux/ioctl.h>
31#include <linux/mtio.h>
32
33#include "../zftape/zftape-rw.h"
34
35#ifdef CONFIG_ZFTAPE_MODULE
36#define ftape_status (*zft_status)
37#endif
38
39extern int zft_offline;
40extern int zft_mt_compression;
41extern int zft_write_protected;
42extern int zft_header_read;
43extern unsigned int zft_unit;
44extern int zft_resid;
45
46extern void zft_reset_position(zft_position *pos);
47extern int zft_check_write_access(zft_position *pos);
48extern int zft_def_idle_state(void);
49
50/* hooks for the VFS interface
51 */
52extern int _zft_open(unsigned int dev_minor, unsigned int access_mode);
53extern int _zft_close(void);
54extern int _zft_ioctl(unsigned int command, void __user *arg);
55#endif
56
57
58
diff --git a/drivers/char/ftape/zftape/zftape-eof.c b/drivers/char/ftape/zftape/zftape-eof.c
deleted file mode 100644
index dcadcaee9ac1..000000000000
--- a/drivers/char/ftape/zftape/zftape-eof.c
+++ /dev/null
@@ -1,199 +0,0 @@
1/*
2 * I use these routines just to decide when I have to fake a
3 * volume-table to preserve compatibility to original ftape.
4 */
5/*
6 * Copyright (C) 1994-1995 Bas Laarhoven.
7 *
8 * Modified for zftape 1996, 1997 Claus Heine.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU 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, USA.
23
24 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.c,v $
25 * $Revision: 1.2 $
26 * $Date: 1997/10/05 19:19:02 $
27 *
28 * This file contains the eof mark handling code
29 * for the QIC-40/80 floppy-tape driver for Linux.
30 */
31
32#include <linux/string.h>
33#include <linux/errno.h>
34
35#include <linux/zftape.h>
36
37#include "../zftape/zftape-init.h"
38#include "../zftape/zftape-rw.h"
39#include "../zftape/zftape-eof.h"
40
41/* Global vars.
42 */
43
44/* a copy of the failed sector log from the header segment.
45 */
46eof_mark_union *zft_eof_map;
47
48/* number of eof marks (entries in bad sector log) on tape.
49 */
50int zft_nr_eof_marks = -1;
51
52
53/* Local vars.
54 */
55
56static char linux_tape_label[] = "Linux raw format V";
57enum {
58 min_fmt_version = 1, max_fmt_version = 2
59};
60static unsigned ftape_fmt_version = 0;
61
62
63/* Ftape (mis)uses the bad sector log to record end-of-file marks.
64 * Initially (when the tape is erased) all entries in the bad sector
65 * log are added to the tape's bad sector map. The bad sector log then
66 * is cleared.
67 *
68 * The bad sector log normally contains entries of the form:
69 * even 16-bit word: segment number of bad sector
70 * odd 16-bit word: encoded date
71 * There can be a total of 448 entries (1792 bytes).
72 *
73 * My guess is that no program is using this bad sector log (the *
74 * format seems useless as there is no indication of the bad sector
75 * itself, only the segment) However, if any program does use the bad
76 * sector log, the format used by ftape will let the program think
77 * there are some bad sectors and no harm is done.
78 *
79 * The eof mark entries that ftape stores in the bad sector log: even
80 * 16-bit word: segment number of eof mark odd 16-bit word: sector
81 * number of eof mark [1..32]
82 *
83 * The zft_eof_map as maintained is a sorted list of eof mark entries.
84 *
85 *
86 * The tape name field in the header segments is used to store a linux
87 * tape identification string and a version number. This way the tape
88 * can be recognized as a Linux raw format tape when using tools under
89 * other OS's.
90 *
91 * 'Wide' QIC tapes (format code 4) don't have a failed sector list
92 * anymore. That space is used for the (longer) bad sector map that
93 * now is a variable length list too. We now store our end-of-file
94 * marker list after the bad-sector-map on tape. The list is delimited
95 * by a (__u32) 0 entry.
96 */
97
98int zft_ftape_validate_label(char *label)
99{
100 static char tmp_label[45];
101 int result = 0;
102 TRACE_FUN(ft_t_any);
103
104 memcpy(tmp_label, label, FT_LABEL_SZ);
105 tmp_label[FT_LABEL_SZ] = '\0';
106 TRACE(ft_t_noise, "tape label = `%s'", tmp_label);
107 ftape_fmt_version = 0;
108 if (memcmp(label, linux_tape_label, strlen(linux_tape_label)) == 0) {
109 int pos = strlen(linux_tape_label);
110 while (label[pos] >= '0' && label[pos] <= '9') {
111 ftape_fmt_version *= 10;
112 ftape_fmt_version = label[ pos++] - '0';
113 }
114 result = (ftape_fmt_version >= min_fmt_version &&
115 ftape_fmt_version <= max_fmt_version);
116 }
117 TRACE(ft_t_noise, "format version = %d", ftape_fmt_version);
118 TRACE_EXIT result;
119}
120
121static __u8 * find_end_of_eof_list(__u8 * ptr, __u8 * limit)
122{
123 while (ptr + 3 < limit) {
124
125 if (get_unaligned((__u32*)ptr)) {
126 ptr += sizeof(__u32);
127 } else {
128 return ptr;
129 }
130 }
131 return NULL;
132}
133
134void zft_ftape_extract_file_marks(__u8* address)
135{
136 int i;
137 TRACE_FUN(ft_t_any);
138
139 zft_eof_map = NULL;
140 if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
141 __u8* end;
142 __u8* start = ftape_find_end_of_bsm_list(address);
143
144 zft_nr_eof_marks = 0;
145 if (start) {
146 start += 3; /* skip end of list mark */
147 end = find_end_of_eof_list(start,
148 address + FT_SEGMENT_SIZE);
149 if (end && end - start <= FT_FSL_SIZE) {
150 zft_nr_eof_marks = ((end - start) /
151 sizeof(eof_mark_union));
152 zft_eof_map = (eof_mark_union *)start;
153 } else {
154 TRACE(ft_t_err,
155 "EOF Mark List is too long or damaged!");
156 }
157 } else {
158 TRACE(ft_t_err,
159 "Bad Sector List is too long or damaged !");
160 }
161 } else {
162 zft_eof_map = (eof_mark_union *)&address[FT_FSL];
163 zft_nr_eof_marks = GET2(address, FT_FSL_CNT);
164 }
165 TRACE(ft_t_noise, "number of file marks: %d", zft_nr_eof_marks);
166 if (ftape_fmt_version == 1) {
167 TRACE(ft_t_info, "swapping version 1 fields");
168 /* version 1 format uses swapped sector and segment
169 * fields, correct that !
170 */
171 for (i = 0; i < zft_nr_eof_marks; ++i) {
172 __u16 tmp = GET2(&zft_eof_map[i].mark.segment,0);
173 PUT2(&zft_eof_map[i].mark.segment, 0,
174 GET2(&zft_eof_map[i].mark.date,0));
175 PUT2(&zft_eof_map[i].mark.date, 0, tmp);
176 }
177 }
178 for (i = 0; i < zft_nr_eof_marks; ++i) {
179 TRACE(ft_t_noise, "eof mark: %5d/%2d",
180 GET2(&zft_eof_map[i].mark.segment, 0),
181 GET2(&zft_eof_map[i].mark.date,0));
182 }
183 TRACE_EXIT;
184}
185
186void zft_clear_ftape_file_marks(void)
187{
188 TRACE_FUN(ft_t_flow);
189 /* Clear failed sector log: remove all tape marks. We
190 * don't use old ftape-style EOF-marks.
191 */
192 TRACE(ft_t_info, "Clearing old ftape's eof map");
193 memset(zft_eof_map, 0, zft_nr_eof_marks * sizeof(__u32));
194 zft_nr_eof_marks = 0;
195 PUT2(zft_hseg_buf, FT_FSL_CNT, 0); /* nr of eof-marks */
196 zft_header_changed = 1;
197 zft_update_label(zft_hseg_buf);
198 TRACE_EXIT;
199}
diff --git a/drivers/char/ftape/zftape/zftape-eof.h b/drivers/char/ftape/zftape/zftape-eof.h
deleted file mode 100644
index 26568c26c518..000000000000
--- a/drivers/char/ftape/zftape/zftape-eof.h
+++ /dev/null
@@ -1,52 +0,0 @@
1#ifndef _ZFTAPE_EOF_H
2#define _ZFTAPE_EOF_H
3
4/*
5 * Copyright (C) 1994-1995 Bas Laarhoven.
6 * adaptaed for zftape 1996, 1997 by Claus 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/zftape/zftape-eof.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:19:03 $
26 *
27 * Definitions and declarations for the end of file markers
28 * for the QIC-40/80 floppy-tape driver for Linux.
29 */
30
31#include <linux/ftape-header-segment.h>
32#include "../zftape/zftape-buffers.h"
33/* failed sector log size (only used if format code != 4).
34 */
35
36typedef union {
37 ft_fsl_entry mark;
38 __u32 entry;
39} eof_mark_union;
40
41/* ftape-eof.c defined global vars.
42 */
43extern int zft_nr_eof_marks;
44extern eof_mark_union *zft_eof_map;
45
46/* ftape-eof.c defined global functions.
47 */
48extern void zft_ftape_extract_file_marks(__u8* address);
49extern int zft_ftape_validate_label(char* label);
50extern void zft_clear_ftape_file_marks(void);
51
52#endif
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
deleted file mode 100644
index 164a1aa77a2f..000000000000
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ /dev/null
@@ -1,377 +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 * This file contains the code that registers the zftape frontend
20 * to the ftape floppy tape driver for Linux
21 */
22
23#include <linux/module.h>
24#include <linux/errno.h>
25#include <linux/fs.h>
26#include <linux/kernel.h>
27#include <linux/signal.h>
28#include <linux/major.h>
29#include <linux/slab.h>
30#ifdef CONFIG_KMOD
31#include <linux/kmod.h>
32#endif
33#include <linux/fcntl.h>
34#include <linux/smp_lock.h>
35
36#include <linux/zftape.h>
37#include <linux/init.h>
38#include <linux/device.h>
39
40#include "../zftape/zftape-init.h"
41#include "../zftape/zftape-read.h"
42#include "../zftape/zftape-write.h"
43#include "../zftape/zftape-ctl.h"
44#include "../zftape/zftape-buffers.h"
45
46MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine "
47 "(claus@momo.math.rwth-aachen.de)");
48MODULE_DESCRIPTION(ZFTAPE_VERSION " - "
49 "VFS interface for the Linux floppy tape driver. "
50 "Support for QIC-113 compatible volume table "
51 "and builtin compression (lzrw3 algorithm)");
52MODULE_SUPPORTED_DEVICE("char-major-27");
53MODULE_LICENSE("GPL");
54
55/* Global vars.
56 */
57struct zft_cmpr_ops *zft_cmpr_ops = NULL;
58const ftape_info *zft_status;
59
60/* Local vars.
61 */
62static unsigned long busy_flag;
63
64static sigset_t orig_sigmask;
65
66/* the interface to the kernel vfs layer
67 */
68
69/* Note about llseek():
70 *
71 * st.c and tpqic.c update fp->f_pos but don't implment llseek() and
72 * initialize the llseek component of the file_ops struct with NULL.
73 * This means that the user will get the default seek, but the tape
74 * device will not respect the new position, but happily read from the
75 * old position. Think a zftape specific llseek() function would be
76 * better, returning -ESPIPE. TODO.
77 */
78
79static int zft_open (struct inode *ino, struct file *filep);
80static int zft_close(struct inode *ino, struct file *filep);
81static int zft_ioctl(struct inode *ino, struct file *filep,
82 unsigned int command, unsigned long arg);
83static int zft_mmap(struct file *filep, struct vm_area_struct *vma);
84static ssize_t zft_read (struct file *fp, char __user *buff,
85 size_t req_len, loff_t *ppos);
86static ssize_t zft_write(struct file *fp, const char __user *buff,
87 size_t req_len, loff_t *ppos);
88
89static const struct file_operations zft_cdev =
90{
91 .owner = THIS_MODULE,
92 .read = zft_read,
93 .write = zft_write,
94 .ioctl = zft_ioctl,
95 .mmap = zft_mmap,
96 .open = zft_open,
97 .release = zft_close,
98};
99
100static struct class *zft_class;
101
102/* Open floppy tape device
103 */
104static int zft_open(struct inode *ino, struct file *filep)
105{
106 int result;
107 TRACE_FUN(ft_t_flow);
108
109 nonseekable_open(ino, filep);
110 TRACE(ft_t_flow, "called for minor %d", iminor(ino));
111 if ( test_and_set_bit(0,&busy_flag) ) {
112 TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
113 }
114 if ((iminor(ino) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
115 >
116 FTAPE_SEL_D) {
117 clear_bit(0,&busy_flag);
118 TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr");
119 }
120 orig_sigmask = current->blocked;
121 sigfillset(&current->blocked);
122 result = _zft_open(iminor(ino), filep->f_flags & O_ACCMODE);
123 if (result < 0) {
124 current->blocked = orig_sigmask; /* restore mask */
125 clear_bit(0,&busy_flag);
126 TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
127 } else {
128 /* Mask signals that will disturb proper operation of the
129 * program that is calling.
130 */
131 current->blocked = orig_sigmask;
132 sigaddsetmask (&current->blocked, _DO_BLOCK);
133 TRACE_EXIT 0;
134 }
135}
136
137/* Close floppy tape device
138 */
139static int zft_close(struct inode *ino, struct file *filep)
140{
141 int result;
142 TRACE_FUN(ft_t_flow);
143
144 if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit) {
145 TRACE(ft_t_err, "failed: not busy or wrong unit");
146 TRACE_EXIT 0;
147 }
148 sigfillset(&current->blocked);
149 result = _zft_close();
150 if (result < 0) {
151 TRACE(ft_t_err, "_zft_close failed");
152 }
153 current->blocked = orig_sigmask; /* restore before open state */
154 clear_bit(0,&busy_flag);
155 TRACE_EXIT 0;
156}
157
158/* Ioctl for floppy tape device
159 */
160static int zft_ioctl(struct inode *ino, struct file *filep,
161 unsigned int command, unsigned long arg)
162{
163 int result = -EIO;
164 sigset_t old_sigmask;
165 TRACE_FUN(ft_t_flow);
166
167 if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
168 TRACE_ABORT(-EIO, ft_t_err,
169 "failed: not busy, failure or wrong unit");
170 }
171 old_sigmask = current->blocked; /* save mask */
172 sigfillset(&current->blocked);
173 /* This will work as long as sizeof(void *) == sizeof(long) */
174 result = _zft_ioctl(command, (void __user *) arg);
175 current->blocked = old_sigmask; /* restore mask */
176 TRACE_EXIT result;
177}
178
179/* Ioctl for floppy tape device
180 */
181static int zft_mmap(struct file *filep, struct vm_area_struct *vma)
182{
183 int result = -EIO;
184 sigset_t old_sigmask;
185 TRACE_FUN(ft_t_flow);
186
187 if ( !test_bit(0,&busy_flag) ||
188 iminor(filep->f_dentry->d_inode) != zft_unit ||
189 ft_failure)
190 {
191 TRACE_ABORT(-EIO, ft_t_err,
192 "failed: not busy, failure or wrong unit");
193 }
194 old_sigmask = current->blocked; /* save mask */
195 sigfillset(&current->blocked);
196 if ((result = ftape_mmap(vma)) >= 0) {
197#ifndef MSYNC_BUG_WAS_FIXED
198 static struct vm_operations_struct dummy = { NULL, };
199 vma->vm_ops = &dummy;
200#endif
201 }
202 current->blocked = old_sigmask; /* restore mask */
203 TRACE_EXIT result;
204}
205
206/* Read from floppy tape device
207 */
208static ssize_t zft_read(struct file *fp, char __user *buff,
209 size_t req_len, loff_t *ppos)
210{
211 int result = -EIO;
212 sigset_t old_sigmask;
213 struct inode *ino = fp->f_dentry->d_inode;
214 TRACE_FUN(ft_t_flow);
215
216 TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
217 if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
218 TRACE_ABORT(-EIO, ft_t_err,
219 "failed: not busy, failure or wrong unit");
220 }
221 old_sigmask = current->blocked; /* save mask */
222 sigfillset(&current->blocked);
223 result = _zft_read(buff, req_len);
224 current->blocked = old_sigmask; /* restore mask */
225 TRACE(ft_t_data_flow, "return with count: %d", result);
226 TRACE_EXIT result;
227}
228
229/* Write to tape device
230 */
231static ssize_t zft_write(struct file *fp, const char __user *buff,
232 size_t req_len, loff_t *ppos)
233{
234 int result = -EIO;
235 sigset_t old_sigmask;
236 struct inode *ino = fp->f_dentry->d_inode;
237 TRACE_FUN(ft_t_flow);
238
239 TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
240 if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
241 TRACE_ABORT(-EIO, ft_t_err,
242 "failed: not busy, failure or wrong unit");
243 }
244 old_sigmask = current->blocked; /* save mask */
245 sigfillset(&current->blocked);
246 result = _zft_write(buff, req_len);
247 current->blocked = old_sigmask; /* restore mask */
248 TRACE(ft_t_data_flow, "return with count: %d", result);
249 TRACE_EXIT result;
250}
251
252/* END OF VFS INTERFACE
253 *
254 *****************************************************************************/
255
256/* driver/module initialization
257 */
258
259/* the compression module has to call this function to hook into the zftape
260 * code
261 */
262int zft_cmpr_register(struct zft_cmpr_ops *new_ops)
263{
264 TRACE_FUN(ft_t_flow);
265
266 if (zft_cmpr_ops != NULL) {
267 TRACE_EXIT -EBUSY;
268 } else {
269 zft_cmpr_ops = new_ops;
270 TRACE_EXIT 0;
271 }
272}
273
274/* lock the zft-compressor() module.
275 */
276int zft_cmpr_lock(int try_to_load)
277{
278 if (zft_cmpr_ops == NULL) {
279#ifdef CONFIG_KMOD
280 if (try_to_load) {
281 request_module("zft-compressor");
282 if (zft_cmpr_ops == NULL) {
283 return -ENOSYS;
284 }
285 } else {
286 return -ENOSYS;
287 }
288#else
289 return -ENOSYS;
290#endif
291 }
292 (*zft_cmpr_ops->lock)();
293 return 0;
294}
295
296#ifdef CONFIG_ZFT_COMPRESSOR
297extern int zft_compressor_init(void);
298#endif
299
300/* Called by modules package when installing the driver or by kernel
301 * during the initialization phase
302 */
303int __init zft_init(void)
304{
305 int i;
306 TRACE_FUN(ft_t_flow);
307
308#ifdef MODULE
309 printk(KERN_INFO ZFTAPE_VERSION "\n");
310 if (TRACE_LEVEL >= ft_t_info) {
311 printk(
312KERN_INFO
313"(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
314KERN_INFO
315"vfs interface for ftape floppy tape driver.\n"
316KERN_INFO
317"Support for QIC-113 compatible volume table, dynamic memory allocation\n"
318KERN_INFO
319"and builtin compression (lzrw3 algorithm).\n");
320 }
321#else /* !MODULE */
322 /* print a short no-nonsense boot message */
323 printk(KERN_INFO ZFTAPE_VERSION "\n");
324#endif /* MODULE */
325 TRACE(ft_t_info, "zft_init @ 0x%p", zft_init);
326 TRACE(ft_t_info,
327 "installing zftape VFS interface for ftape driver ...");
328 TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
329
330 zft_class = class_create(THIS_MODULE, "zft");
331 for (i = 0; i < 4; i++) {
332 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
333 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
334 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
335 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
336 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
337 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
338 }
339
340#ifdef CONFIG_ZFT_COMPRESSOR
341 (void)zft_compressor_init();
342#endif
343 zft_status = ftape_get_status(); /* fetch global data of ftape
344 * hardware driver
345 */
346 TRACE_EXIT 0;
347}
348
349
350/* Called by modules package when removing the driver
351 */
352static void zft_exit(void)
353{
354 int i;
355 TRACE_FUN(ft_t_flow);
356
357 if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
358 TRACE(ft_t_warn, "failed");
359 } else {
360 TRACE(ft_t_info, "successful");
361 }
362 for (i = 0; i < 4; i++) {
363 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
364 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
365 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
366 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
367 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
368 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
369 }
370 class_destroy(zft_class);
371 zft_uninit_mem(); /* release remaining memory, if any */
372 printk(KERN_INFO "zftape successfully unloaded.\n");
373 TRACE_EXIT;
374}
375
376module_init(zft_init);
377module_exit(zft_exit);
diff --git a/drivers/char/ftape/zftape/zftape-init.h b/drivers/char/ftape/zftape/zftape-init.h
deleted file mode 100644
index 937e5d48c20e..000000000000
--- a/drivers/char/ftape/zftape/zftape-init.h
+++ /dev/null
@@ -1,77 +0,0 @@
1#ifndef _ZFTAPE_INIT_H
2#define _ZFTAPE_INIT_H
3
4/*
5 * Copyright (C) 1996, 1997 Claus 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/zftape/zftape-init.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:05 $
25 *
26 * This file contains definitions and macro for the vfs
27 * interface defined by zftape
28 *
29 */
30
31#include <linux/ftape-header-segment.h>
32
33#include "../lowlevel/ftape-tracing.h"
34#include "../lowlevel/ftape-ctl.h"
35#include "../lowlevel/ftape-read.h"
36#include "../lowlevel/ftape-write.h"
37#include "../lowlevel/ftape-bsm.h"
38#include "../lowlevel/ftape-io.h"
39#include "../lowlevel/ftape-buffer.h"
40#include "../lowlevel/ftape-format.h"
41
42#include "../zftape/zftape-rw.h"
43
44#ifdef MODULE
45#define ftape_status (*zft_status)
46#endif
47
48extern const ftape_info *zft_status; /* needed for zftape-vtbl.h */
49
50#include "../zftape/zftape-vtbl.h"
51
52struct zft_cmpr_ops {
53 int (*write)(int *write_cnt,
54 __u8 *dst_buf, const int seg_sz,
55 const __u8 __user *src_buf, const int req_len,
56 const zft_position *pos, const zft_volinfo *volume);
57 int (*read)(int *read_cnt,
58 __u8 __user *dst_buf, const int req_len,
59 const __u8 *src_buf, const int seg_sz,
60 const zft_position *pos, const zft_volinfo *volume);
61 int (*seek)(unsigned int new_block_pos,
62 zft_position *pos, const zft_volinfo *volume,
63 __u8 *buffer);
64 void (*lock) (void);
65 void (*reset) (void);
66 void (*cleanup)(void);
67};
68
69extern struct zft_cmpr_ops *zft_cmpr_ops;
70/* zftape-init.c defined global functions.
71 */
72extern int zft_cmpr_register(struct zft_cmpr_ops *new_ops);
73extern int zft_cmpr_lock(int try_to_load);
74
75#endif
76
77
diff --git a/drivers/char/ftape/zftape/zftape-read.c b/drivers/char/ftape/zftape/zftape-read.c
deleted file mode 100644
index 214bf03dce68..000000000000
--- a/drivers/char/ftape/zftape/zftape-read.c
+++ /dev/null
@@ -1,377 +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/zftape/zftape-read.c,v $
20 * $Revision: 1.2 $
21 * $Date: 1997/10/05 19:19:06 $
22 *
23 * This file contains the high level reading code
24 * for the QIC-117 floppy-tape driver for Linux.
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29
30#include <linux/zftape.h>
31
32#include <asm/uaccess.h>
33
34#include "../zftape/zftape-init.h"
35#include "../zftape/zftape-eof.h"
36#include "../zftape/zftape-ctl.h"
37#include "../zftape/zftape-write.h"
38#include "../zftape/zftape-read.h"
39#include "../zftape/zftape-rw.h"
40#include "../zftape/zftape-vtbl.h"
41
42/* Global vars.
43 */
44int zft_just_before_eof;
45
46/* Local vars.
47 */
48static int buf_len_rd;
49
50void zft_zap_read_buffers(void)
51{
52 buf_len_rd = 0;
53}
54
55int zft_read_header_segments(void)
56{
57 TRACE_FUN(ft_t_flow);
58
59 zft_header_read = 0;
60 TRACE_CATCH(zft_vmalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
61 TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
62 TRACE(ft_t_info, "Segments written since first format: %d",
63 (int)GET4(zft_hseg_buf, FT_SEG_CNT));
64 zft_qic113 = (ft_format_code != fmt_normal &&
65 ft_format_code != fmt_1100ft &&
66 ft_format_code != fmt_425ft);
67 TRACE(ft_t_info, "ft_first_data_segment: %d, ft_last_data_segment: %d",
68 ft_first_data_segment, ft_last_data_segment);
69 zft_capacity = zft_get_capacity();
70 zft_old_ftape = zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]);
71 if (zft_old_ftape) {
72 TRACE(ft_t_info,
73"Found old ftaped tape, emulating eof marks, entering read-only mode");
74 zft_ftape_extract_file_marks(zft_hseg_buf);
75 TRACE_CATCH(zft_fake_volume_headers(zft_eof_map,
76 zft_nr_eof_marks),);
77 } else {
78 /* the specs say that the volume table must be
79 * initialized with zeroes during formatting, so it
80 * MUST be readable, i.e. contain vaid ECC
81 * information.
82 */
83 TRACE_CATCH(ftape_read_segment(ft_first_data_segment,
84 zft_deblock_buf,
85 FT_RD_SINGLE),);
86 TRACE_CATCH(zft_extract_volume_headers(zft_deblock_buf),);
87 }
88 zft_header_read = 1;
89 zft_set_flags(zft_unit);
90 zft_reset_position(&zft_pos);
91 TRACE_EXIT 0;
92}
93
94int zft_fetch_segment_fraction(const unsigned int segment, void *buffer,
95 const ft_read_mode_t read_mode,
96 const unsigned int start,
97 const unsigned int size)
98{
99 int seg_sz;
100 TRACE_FUN(ft_t_flow);
101
102 if (segment == zft_deblock_segment) {
103 TRACE(ft_t_data_flow,
104 "re-using segment %d already in deblock buffer",
105 segment);
106 seg_sz = zft_get_seg_sz(segment);
107 if (start > seg_sz) {
108 TRACE_ABORT(-EINVAL, ft_t_bug,
109 "trying to read beyond end of segment:\n"
110 KERN_INFO "seg_sz : %d\n"
111 KERN_INFO "start : %d\n"
112 KERN_INFO "segment: %d",
113 seg_sz, start, segment);
114 }
115 if ((start + size) > seg_sz) {
116 TRACE_EXIT seg_sz - start;
117 }
118 TRACE_EXIT size;
119 }
120 seg_sz = ftape_read_segment_fraction(segment, buffer, read_mode,
121 start, size);
122 TRACE(ft_t_data_flow, "segment %d, result %d", segment, seg_sz);
123 if ((int)seg_sz >= 0 && start == 0 && size == FT_SEGMENT_SIZE) {
124 /* this implicitly assumes that we are always called with
125 * buffer == zft_deblock_buf
126 */
127 zft_deblock_segment = segment;
128 } else {
129 zft_deblock_segment = -1;
130 }
131 TRACE_EXIT seg_sz;
132}
133
134/*
135 * out:
136 *
137 * int *read_cnt: the number of bytes we removed from the
138 * zft_deblock_buf (result)
139 *
140 * int *to_do : the remaining size of the read-request. Is changed.
141 *
142 * in:
143 *
144 * char *buff : buff is the address of the upper part of the user
145 * buffer, that hasn't been filled with data yet.
146 * int buf_pos_read: copy of buf_pos_rd
147 * int buf_len_read: copy of buf_len_rd
148 * char *zft_deblock_buf: ftape_zft_deblock_buf
149 *
150 * returns the amount of data actually copied to the user-buffer
151 *
152 * to_do MUST NOT SHRINK except to indicate an EOT. In this case to_do
153 * has to be set to 0. We cannot return -ENOSPC, because we return the
154 * amount of data actually * copied to the user-buffer
155 */
156static int zft_simple_read (int *read_cnt,
157 __u8 __user *dst_buf,
158 const int to_do,
159 const __u8 *src_buf,
160 const int seg_sz,
161 const zft_position *pos,
162 const zft_volinfo *volume)
163{
164 TRACE_FUN(ft_t_flow);
165
166 if (seg_sz - pos->seg_byte_pos < to_do) {
167 *read_cnt = seg_sz - pos->seg_byte_pos;
168 } else {
169 *read_cnt = to_do;
170 }
171 if (copy_to_user(dst_buf,
172 src_buf + pos->seg_byte_pos, *read_cnt) != 0) {
173 TRACE_EXIT -EFAULT;
174 }
175 TRACE(ft_t_noise, "nr bytes just read: %d", *read_cnt);
176 TRACE_EXIT *read_cnt;
177}
178
179/* req_len: gets clipped due to EOT of EOF.
180 * req_clipped: is a flag indicating whether req_len was clipped or not
181 * volume: contains information on current volume (blk_sz etc.)
182 */
183static int check_read_access(int *req_len,
184 const zft_volinfo **volume,
185 int *req_clipped,
186 const zft_position *pos)
187{
188 static __s64 remaining;
189 static int eod;
190 TRACE_FUN(ft_t_flow);
191
192 if (zft_io_state != zft_reading) {
193 if (zft_offline) { /* offline includes no_tape */
194 TRACE_ABORT(-ENXIO, ft_t_warn,
195 "tape is offline or no cartridge");
196 }
197 if (!ft_formatted) {
198 TRACE_ABORT(-EACCES,
199 ft_t_warn, "tape is not formatted");
200 }
201 /* now enter defined state, read header segment if not
202 * already done and flush write buffers
203 */
204 TRACE_CATCH(zft_def_idle_state(),);
205 zft_io_state = zft_reading;
206 if (zft_tape_at_eod(pos)) {
207 eod = 1;
208 TRACE_EXIT 1;
209 }
210 eod = 0;
211 *volume = zft_find_volume(pos->seg_pos);
212 /* get the space left until EOF */
213 remaining = zft_check_for_eof(*volume, pos);
214 buf_len_rd = 0;
215 TRACE(ft_t_noise, "remaining: " LL_X ", vol_no: %d",
216 LL(remaining), (*volume)->count);
217 } else if (zft_tape_at_eod(pos)) {
218 if (++eod > 2) {
219 TRACE_EXIT -EIO; /* st.c also returns -EIO */
220 } else {
221 TRACE_EXIT 1;
222 }
223 }
224 if ((*req_len % (*volume)->blk_sz) != 0) {
225 /* this message is informational only. The user gets the
226 * proper return value
227 */
228 TRACE_ABORT(-EINVAL, ft_t_info,
229 "req_len %d not a multiple of block size %d",
230 *req_len, (*volume)->blk_sz);
231 }
232 /* As GNU tar doesn't accept partial read counts when the
233 * multiple volume flag is set, we make sure to return the
234 * requested amount of data. Except, of course, at the end of
235 * the tape or file mark.
236 */
237 remaining -= *req_len;
238 if (remaining <= 0) {
239 TRACE(ft_t_noise,
240 "clipped request from %d to %d.",
241 *req_len, (int)(*req_len + remaining));
242 *req_len += remaining;
243 *req_clipped = 1;
244 } else {
245 *req_clipped = 0;
246 }
247 TRACE_EXIT 0;
248}
249
250/* this_segs_size: the current segment's size.
251 * buff: the USER-SPACE buffer provided by the calling function.
252 * req_len: how much data should be read at most.
253 * volume: contains information on current volume (blk_sz etc.)
254 */
255static int empty_deblock_buf(__u8 __user *usr_buf, const int req_len,
256 const __u8 *src_buf, const int seg_sz,
257 zft_position *pos,
258 const zft_volinfo *volume)
259{
260 int cnt;
261 int result = 0;
262 TRACE_FUN(ft_t_flow);
263
264 TRACE(ft_t_data_flow, "this_segs_size: %d", seg_sz);
265 if (zft_use_compression && volume->use_compression) {
266 TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
267 TRACE_CATCH(result= (*zft_cmpr_ops->read)(&cnt,
268 usr_buf, req_len,
269 src_buf, seg_sz,
270 pos, volume),);
271 } else {
272 TRACE_CATCH(result= zft_simple_read (&cnt,
273 usr_buf, req_len,
274 src_buf, seg_sz,
275 pos, volume),);
276 }
277 pos->volume_pos += result;
278 pos->tape_pos += cnt;
279 pos->seg_byte_pos += cnt;
280 buf_len_rd -= cnt; /* remaining bytes in buffer */
281 TRACE(ft_t_data_flow, "buf_len_rd: %d, cnt: %d", buf_len_rd, cnt);
282 if(pos->seg_byte_pos >= seg_sz) {
283 pos->seg_pos++;
284 pos->seg_byte_pos = 0;
285 }
286 TRACE(ft_t_data_flow, "bytes moved out of deblock-buffer: %d", cnt);
287 TRACE_EXIT result;
288}
289
290
291/* note: we store the segment id of the segment that is inside the
292 * deblock buffer. This spares a lot of ftape_read_segment()s when we
293 * use small block-sizes. The block-size may be 1kb (SECTOR_SIZE). In
294 * this case a MTFSR 28 maybe still inside the same segment.
295 */
296int _zft_read(char __user *buff, int req_len)
297{
298 int req_clipped;
299 int result = 0;
300 int bytes_read = 0;
301 static unsigned int seg_sz = 0;
302 static const zft_volinfo *volume = NULL;
303 TRACE_FUN(ft_t_flow);
304
305 zft_resid = req_len;
306 result = check_read_access(&req_len, &volume,
307 &req_clipped, &zft_pos);
308 switch(result) {
309 case 0:
310 break; /* nothing special */
311 case 1:
312 TRACE(ft_t_noise, "EOD reached");
313 TRACE_EXIT 0; /* EOD */
314 default:
315 TRACE_ABORT(result, ft_t_noise,
316 "check_read_access() failed with result %d",
317 result);
318 TRACE_EXIT result;
319 }
320 while (req_len > 0) {
321 /* Allow escape from this loop on signal !
322 */
323 FT_SIGNAL_EXIT(_DONT_BLOCK);
324 /* buf_len_rd == 0 means that we need to read a new
325 * segment.
326 */
327 if (buf_len_rd == 0) {
328 while((result = zft_fetch_segment(zft_pos.seg_pos,
329 zft_deblock_buf,
330 FT_RD_AHEAD)) == 0) {
331 zft_pos.seg_pos ++;
332 zft_pos.seg_byte_pos = 0;
333 }
334 if (result < 0) {
335 zft_resid -= bytes_read;
336 TRACE_ABORT(result, ft_t_noise,
337 "zft_fetch_segment(): %d",
338 result);
339 }
340 seg_sz = result;
341 buf_len_rd = seg_sz - zft_pos.seg_byte_pos;
342 }
343 TRACE_CATCH(result = empty_deblock_buf(buff,
344 req_len,
345 zft_deblock_buf,
346 seg_sz,
347 &zft_pos,
348 volume),
349 zft_resid -= bytes_read);
350 TRACE(ft_t_data_flow, "bytes just read: %d", result);
351 bytes_read += result; /* what we got so far */
352 buff += result; /* index in user-buffer */
353 req_len -= result; /* what's left from req_len */
354 } /* while (req_len > 0) */
355 if (req_clipped) {
356 TRACE(ft_t_data_flow,
357 "maybe partial count because of eof mark");
358 if (zft_just_before_eof && bytes_read == 0) {
359 /* req_len was > 0, but user didn't get
360 * anything the user has read in the eof-mark
361 */
362 zft_move_past_eof(&zft_pos);
363 ftape_abort_operation();
364 } else {
365 /* don't skip to the next file before the user
366 * tried to read a second time past EOF Just
367 * mark that we are at EOF and maybe decrement
368 * zft_seg_pos to stay in the same volume;
369 */
370 zft_just_before_eof = 1;
371 zft_position_before_eof(&zft_pos, volume);
372 TRACE(ft_t_noise, "just before eof");
373 }
374 }
375 zft_resid -= result; /* for MTSTATUS */
376 TRACE_EXIT bytes_read;
377}
diff --git a/drivers/char/ftape/zftape/zftape-read.h b/drivers/char/ftape/zftape/zftape-read.h
deleted file mode 100644
index 42941de0c23a..000000000000
--- a/drivers/char/ftape/zftape/zftape-read.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef _ZFTAPE_READ_H
2#define _ZFTAPE_READ_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/zftape/zftape-read.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:07 $
25 *
26 * This file contains the definitions for the read functions
27 * for the zftape driver for Linux.
28 *
29 */
30
31#include "../lowlevel/ftape-read.h"
32
33/* ftape-read.c defined global vars.
34 */
35extern int zft_just_before_eof;
36
37/* ftape-read.c defined global functions.
38 */
39extern void zft_zap_read_buffers(void);
40extern int zft_read_header_segments(void);
41extern int zft_fetch_segment_fraction(const unsigned int segment,
42 void *buffer,
43 const ft_read_mode_t read_mode,
44 const unsigned int start,
45 const unsigned int size);
46#define zft_fetch_segment(segment, address, read_mode) \
47 zft_fetch_segment_fraction(segment, address, read_mode, \
48 0, FT_SEGMENT_SIZE)
49/* hook for the VFS interface
50 */
51extern int _zft_read(char __user *buff, int req_len);
52
53#endif /* _ZFTAPE_READ_H */
diff --git a/drivers/char/ftape/zftape/zftape-rw.c b/drivers/char/ftape/zftape/zftape-rw.c
deleted file mode 100644
index dab634686885..000000000000
--- a/drivers/char/ftape/zftape/zftape-rw.c
+++ /dev/null
@@ -1,375 +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/zftape/zftape-rw.c,v $
20 * $Revision: 1.2 $
21 * $Date: 1997/10/05 19:19:08 $
22 *
23 * This file contains some common code for the r/w code for
24 * zftape.
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29
30#include <linux/zftape.h>
31#include "../zftape/zftape-init.h"
32#include "../zftape/zftape-eof.h"
33#include "../zftape/zftape-ctl.h"
34#include "../zftape/zftape-write.h"
35#include "../zftape/zftape-read.h"
36#include "../zftape/zftape-rw.h"
37#include "../zftape/zftape-vtbl.h"
38
39/* Global vars.
40 */
41
42__u8 *zft_deblock_buf;
43__u8 *zft_hseg_buf;
44int zft_deblock_segment = -1;
45zft_status_enum zft_io_state = zft_idle;
46int zft_header_changed;
47int zft_qic113; /* conform to old specs. and old zftape */
48int zft_use_compression;
49zft_position zft_pos = {
50 -1, /* seg_pos */
51 0, /* seg_byte_pos */
52 0, /* tape_pos */
53 0 /* volume_pos */
54};
55unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
56__s64 zft_capacity;
57
58unsigned int zft_written_segments;
59int zft_label_changed;
60
61/* Local vars.
62 */
63
64unsigned int zft_get_seg_sz(unsigned int segment)
65{
66 int size;
67 TRACE_FUN(ft_t_any);
68
69 size = FT_SEGMENT_SIZE -
70 count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;
71 if (size > 0) {
72 TRACE_EXIT (unsigned)size;
73 } else {
74 TRACE_EXIT 0;
75 }
76}
77
78/* ftape_set_flags(). Claus-Justus Heine, 1994/1995
79 */
80void zft_set_flags(unsigned minor_unit)
81{
82 TRACE_FUN(ft_t_flow);
83
84 zft_use_compression = zft_qic_mode = 0;
85 switch (minor_unit & ZFT_MINOR_OP_MASK) {
86 case (ZFT_Q80_MODE | ZFT_ZIP_MODE):
87 case ZFT_ZIP_MODE:
88 zft_use_compression = 1;
89 case 0:
90 case ZFT_Q80_MODE:
91 zft_qic_mode = 1;
92 if (zft_mt_compression) { /* override the default */
93 zft_use_compression = 1;
94 }
95 break;
96 case ZFT_RAW_MODE:
97 TRACE(ft_t_noise, "switching to raw mode");
98 break;
99 default:
100 TRACE(ft_t_warn, "Warning:\n"
101 KERN_INFO "Wrong combination of minor device bits.\n"
102 KERN_INFO "Switching to raw read-only mode.");
103 zft_write_protected = 1;
104 break;
105 }
106 TRACE_EXIT;
107}
108
109/* computes the segment and byte offset inside the segment
110 * corresponding to tape_pos.
111 *
112 * tape_pos gives the offset in bytes from the beginning of the
113 * ft_first_data_segment *seg_byte_pos is the offset in the current
114 * segment in bytes
115 *
116 * Of, if this routine was called often one should cache the last data
117 * pos it was called with, but actually this is only needed in
118 * ftape_seek_block(), that is, almost never.
119 */
120int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)
121{
122 int segment;
123 int seg_sz;
124 TRACE_FUN(ft_t_flow);
125
126 if (tape_pos == 0) {
127 *seg_byte_pos = 0;
128 segment = ft_first_data_segment;
129 } else {
130 seg_sz = 0;
131
132 for (segment = ft_first_data_segment;
133 ((tape_pos > 0) && (segment <= ft_last_data_segment));
134 segment++) {
135 seg_sz = zft_get_seg_sz(segment);
136 tape_pos -= seg_sz;
137 }
138 if(tape_pos >= 0) {
139 /* the case tape_pos > != 0 means that the
140 * argument tape_pos lies beyond the EOT.
141 */
142 *seg_byte_pos= 0;
143 } else { /* tape_pos < 0 */
144 segment--;
145 *seg_byte_pos= tape_pos + seg_sz;
146 }
147 }
148 TRACE_EXIT(segment);
149}
150
151/* ftape_calc_tape_pos().
152 *
153 * computes the offset in bytes from the beginning of the
154 * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
155 *
156 * We should do some caching. But how:
157 *
158 * Each time the header segments are read in, this routine is called
159 * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
160 * the time to reset the cache.
161 *
162 * Also, it might be in the future that the bad sector map gets
163 * changed. -> reset the cache
164 */
165static int seg_pos;
166static __s64 tape_pos;
167
168__s64 zft_get_capacity(void)
169{
170 seg_pos = ft_first_data_segment;
171 tape_pos = 0;
172
173 while (seg_pos <= ft_last_data_segment) {
174 tape_pos += zft_get_seg_sz(seg_pos ++);
175 }
176 return tape_pos;
177}
178
179__s64 zft_calc_tape_pos(int segment)
180{
181 int d1, d2, d3;
182 TRACE_FUN(ft_t_any);
183
184 if (segment > ft_last_data_segment) {
185 TRACE_EXIT zft_capacity;
186 }
187 if (segment < ft_first_data_segment) {
188 TRACE_EXIT 0;
189 }
190 d2 = segment - seg_pos;
191 if (-d2 > 10) {
192 d1 = segment - ft_first_data_segment;
193 if (-d2 > d1) {
194 tape_pos = 0;
195 seg_pos = ft_first_data_segment;
196 d2 = d1;
197 }
198 }
199 if (d2 > 10) {
200 d3 = ft_last_data_segment - segment;
201 if (d2 > d3) {
202 tape_pos = zft_capacity;
203 seg_pos = ft_last_data_segment + 1;
204 d2 = -d3;
205 }
206 }
207 if (d2 > 0) {
208 while (seg_pos < segment) {
209 tape_pos += zft_get_seg_sz(seg_pos++);
210 }
211 } else {
212 while (seg_pos > segment) {
213 tape_pos -= zft_get_seg_sz(--seg_pos);
214 }
215 }
216 TRACE(ft_t_noise, "new cached pos: %d", seg_pos);
217
218 TRACE_EXIT tape_pos;
219}
220
221/* copy Z-label string to buffer, keeps track of the correct offset in
222 * `buffer'
223 */
224void zft_update_label(__u8 *buffer)
225{
226 TRACE_FUN(ft_t_flow);
227
228 if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL,
229 sizeof(ZFTAPE_LABEL)-1) != 0) {
230 TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"",
231 &buffer[FT_LABEL], ZFTAPE_LABEL);
232 strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);
233 memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ',
234 FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));
235 PUT4(buffer, FT_LABEL_DATE, 0);
236 zft_label_changed = zft_header_changed = 1; /* changed */
237 }
238 TRACE_EXIT;
239}
240
241int zft_verify_write_segments(unsigned int segment,
242 __u8 *data, size_t size,
243 __u8 *buffer)
244{
245 int result;
246 __u8 *write_buf;
247 __u8 *src_buf;
248 int single;
249 int seg_pos;
250 int seg_sz;
251 int remaining;
252 ft_write_mode_t write_mode;
253 TRACE_FUN(ft_t_flow);
254
255 seg_pos = segment;
256 seg_sz = zft_get_seg_sz(seg_pos);
257 src_buf = data;
258 single = size <= seg_sz;
259 remaining = size;
260 do {
261 TRACE(ft_t_noise, "\n"
262 KERN_INFO "remaining: %d\n"
263 KERN_INFO "seg_sz : %d\n"
264 KERN_INFO "segment : %d",
265 remaining, seg_sz, seg_pos);
266 if (remaining == seg_sz) {
267 write_buf = src_buf;
268 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
269 remaining = 0;
270 } else if (remaining > seg_sz) {
271 write_buf = src_buf;
272 write_mode = FT_WR_ASYNC; /* don't start tape */
273 remaining -= seg_sz;
274 } else { /* remaining < seg_sz */
275 write_buf = buffer;
276 memcpy(write_buf, src_buf, remaining);
277 memset(&write_buf[remaining],'\0',seg_sz-remaining);
278 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
279 remaining = 0;
280 }
281 if ((result = ftape_write_segment(seg_pos,
282 write_buf,
283 write_mode)) != seg_sz) {
284 TRACE(ft_t_err, "Error: "
285 "Couldn't write segment %d", seg_pos);
286 TRACE_EXIT result < 0 ? result : -EIO; /* bail out */
287 }
288 zft_written_segments ++;
289 seg_sz = zft_get_seg_sz(++seg_pos);
290 src_buf += result;
291 } while (remaining > 0);
292 if (ftape_get_status()->fti_state == writing) {
293 TRACE_CATCH(ftape_loop_until_writes_done(),);
294 TRACE_CATCH(ftape_abort_operation(),);
295 zft_prevent_flush();
296 }
297 seg_pos = segment;
298 src_buf = data;
299 remaining = size;
300 do {
301 TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer,
302 single ? FT_RD_SINGLE
303 : FT_RD_AHEAD),);
304 if (memcmp(src_buf, buffer,
305 remaining > result ? result : remaining) != 0) {
306 TRACE_ABORT(-EIO, ft_t_err,
307 "Failed to verify written segment %d",
308 seg_pos);
309 }
310 remaining -= result;
311 TRACE(ft_t_noise, "verify successful:\n"
312 KERN_INFO "segment : %d\n"
313 KERN_INFO "segsize : %d\n"
314 KERN_INFO "remaining: %d",
315 seg_pos, result, remaining);
316 src_buf += seg_sz;
317 seg_pos++;
318 } while (remaining > 0);
319 TRACE_EXIT size;
320}
321
322
323/* zft_erase(). implemented compression-handling
324 *
325 * calculate the first data-segment when using/not using compression.
326 *
327 * update header-segment and compression-map-segment.
328 */
329int zft_erase(void)
330{
331 int result = 0;
332 TRACE_FUN(ft_t_flow);
333
334 if (!zft_header_read) {
335 TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,
336 FT_SEGMENT_SIZE),);
337 /* no need to read the vtbl and compression map */
338 TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
339 if ((zft_old_ftape =
340 zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {
341 zft_ftape_extract_file_marks(zft_hseg_buf);
342 }
343 TRACE(ft_t_noise,
344 "ft_first_data_segment: %d, ft_last_data_segment: %d",
345 ft_first_data_segment, ft_last_data_segment);
346 zft_qic113 = (ft_format_code != fmt_normal &&
347 ft_format_code != fmt_1100ft &&
348 ft_format_code != fmt_425ft);
349 }
350 if (zft_old_ftape) {
351 zft_clear_ftape_file_marks();
352 zft_old_ftape = 0; /* no longer old ftape */
353 }
354 PUT2(zft_hseg_buf, FT_CMAP_START, 0);
355 zft_volume_table_changed = 1;
356 zft_capacity = zft_get_capacity();
357 zft_init_vtbl();
358 /* the rest must be done in ftape_update_header_segments
359 */
360 zft_header_read = 1;
361 zft_header_changed = 1; /* force update of timestamp */
362 result = zft_update_header_segments();
363
364 ftape_abort_operation();
365
366 zft_reset_position(&zft_pos);
367 zft_set_flags (zft_unit);
368 TRACE_EXIT result;
369}
370
371unsigned int zft_get_time(void)
372{
373 unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */
374 return date;
375}
diff --git a/drivers/char/ftape/zftape/zftape-rw.h b/drivers/char/ftape/zftape/zftape-rw.h
deleted file mode 100644
index 1ceec22b60bd..000000000000
--- a/drivers/char/ftape/zftape/zftape-rw.h
+++ /dev/null
@@ -1,101 +0,0 @@
1#ifndef _ZFTAPE_RW_H
2#define _ZFTAPE_RW_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/zftape/zftape-rw.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:09 $
25 *
26 * This file contains the definitions for the read and write
27 * functions for the QIC-117 floppy-tape driver for Linux.
28 *
29 */
30
31#include "../zftape/zftape-buffers.h"
32
33#define SEGMENTS_PER_TAPE (ft_segments_per_track * ft_tracks_per_tape)
34
35/* QIC-113 Rev. G says that `a maximum of 63488 raw bytes may be
36 * compressed into a single frame'.
37 * Maybe we should stick to 32kb to make it more `beautiful'
38 */
39#define ZFT_MAX_BLK_SZ (62*1024) /* bytes */
40#if !defined(CONFIG_ZFT_DFLT_BLK_SZ)
41# define CONFIG_ZFT_DFLT_BLK_SZ (10*1024) /* bytes, default of gnu tar */
42#elif CONFIG_ZFT_DFLT_BLK_SZ == 0
43# undef CONFIG_ZFT_DFLT_BLK_SZ
44# define CONFIG_ZFT_DFLT_BLK_SZ 1
45#elif (CONFIG_ZFT_DFLT_BLK_SZ % 1024) != 0
46# error CONFIG_ZFT_DFLT_BLK_SZ must be 1 or a multiple of 1024
47#endif
48/* The *optional* compression routines need some overhead per tape
49 * block for their purposes. Instead of asking the actual compression
50 * implementation how much it needs, we restrict this overhead to be
51 * maximal of ZFT_CMPT_OVERHEAD size. We need this for EOT
52 * conditions. The tape is assumed to be logical at EOT when the
53 * distance from the physical EOT is less than
54 * one tape block + ZFT_CMPR_OVERHEAD
55 */
56#define ZFT_CMPR_OVERHEAD 16 /* bytes */
57
58typedef enum
59{
60 zft_idle = 0,
61 zft_reading,
62 zft_writing,
63} zft_status_enum;
64
65typedef struct /* all values measured in bytes */
66{
67 int seg_pos; /* segment currently positioned at */
68 int seg_byte_pos; /* offset in current segment */
69 __s64 tape_pos; /* real offset from BOT */
70 __s64 volume_pos; /* pos. in uncompressed data stream in
71 * current volume
72 */
73} zft_position;
74
75extern zft_position zft_pos;
76extern __u8 *zft_deblock_buf;
77extern __u8 *zft_hseg_buf;
78extern int zft_deblock_segment;
79extern zft_status_enum zft_io_state;
80extern int zft_header_changed;
81extern int zft_qic113; /* conform to old specs. and old zftape */
82extern int zft_use_compression;
83extern unsigned int zft_blk_sz;
84extern __s64 zft_capacity;
85extern unsigned int zft_written_segments;
86extern int zft_label_changed;
87
88/* zftape-rw.c exported functions
89 */
90extern unsigned int zft_get_seg_sz(unsigned int segment);
91extern void zft_set_flags(unsigned int minor_unit);
92extern int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos);
93extern __s64 zft_calc_tape_pos(int segment);
94extern __s64 zft_get_capacity(void);
95extern void zft_update_label(__u8 *buffer);
96extern int zft_erase(void);
97extern int zft_verify_write_segments(unsigned int segment,
98 __u8 *data, size_t size, __u8 *buffer);
99extern unsigned int zft_get_time(void);
100#endif /* _ZFTAPE_RW_H */
101
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.c b/drivers/char/ftape/zftape/zftape-vtbl.c
deleted file mode 100644
index ad7f8be6340b..000000000000
--- a/drivers/char/ftape/zftape/zftape-vtbl.c
+++ /dev/null
@@ -1,757 +0,0 @@
1/*
2 * Copyright (c) 1995-1997 Claus-Justus Heine
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2, or (at
7 your option) any later version.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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,
17 USA.
18
19 *
20 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.c,v $
21 * $Revision: 1.7.6.1 $
22 * $Date: 1997/11/24 13:48:31 $
23 *
24 * This file defines a volume table as defined in various QIC
25 * standards.
26 *
27 * This is a minimal implementation, just allowing ordinary DOS
28 * :( prgrams to identify the cartridge as used.
29 */
30
31#include <linux/errno.h>
32#include <linux/mm.h>
33#include <linux/slab.h>
34
35#include <linux/zftape.h>
36#include "../zftape/zftape-init.h"
37#include "../zftape/zftape-eof.h"
38#include "../zftape/zftape-ctl.h"
39#include "../zftape/zftape-write.h"
40#include "../zftape/zftape-read.h"
41#include "../zftape/zftape-rw.h"
42#include "../zftape/zftape-vtbl.h"
43
44#define ZFT_CMAP_HACK /* leave this defined to hide the compression map */
45
46/*
47 * global variables
48 */
49int zft_qic_mode = 1; /* use the vtbl */
50int zft_old_ftape; /* prevents old ftaped tapes to be overwritten */
51int zft_volume_table_changed; /* for write_header_segments() */
52
53/*
54 * private variables (only exported for inline functions)
55 */
56LIST_HEAD(zft_vtbl);
57
58/* We could also allocate these dynamically when extracting the volume table
59 * sizeof(zft_volinfo) is about 32 or something close to that
60 */
61static zft_volinfo tape_vtbl;
62static zft_volinfo eot_vtbl;
63static zft_volinfo *cur_vtbl;
64
65static inline void zft_new_vtbl_entry(void)
66{
67 struct list_head *tmp = &zft_last_vtbl->node;
68 zft_volinfo *new = zft_kmalloc(sizeof(zft_volinfo));
69
70 list_add(&new->node, tmp);
71 new->count = zft_eom_vtbl->count ++;
72}
73
74void zft_free_vtbl(void)
75{
76 for (;;) {
77 struct list_head *tmp = zft_vtbl.prev;
78 zft_volinfo *vtbl;
79
80 if (tmp == &zft_vtbl)
81 break;
82 list_del(tmp);
83 vtbl = list_entry(tmp, zft_volinfo, node);
84 zft_kfree(vtbl, sizeof(zft_volinfo));
85 }
86 INIT_LIST_HEAD(&zft_vtbl);
87 cur_vtbl = NULL;
88}
89
90/* initialize vtbl, called by ftape_new_cartridge()
91 */
92void zft_init_vtbl(void)
93{
94 zft_volinfo *new;
95
96 zft_free_vtbl();
97
98 /* Create the two dummy vtbl entries
99 */
100 new = zft_kmalloc(sizeof(zft_volinfo));
101 list_add(&new->node, &zft_vtbl);
102 new = zft_kmalloc(sizeof(zft_volinfo));
103 list_add(&new->node, &zft_vtbl);
104 zft_head_vtbl->end_seg = ft_first_data_segment;
105 zft_head_vtbl->blk_sz = zft_blk_sz;
106 zft_head_vtbl->count = -1;
107 zft_eom_vtbl->start_seg = ft_first_data_segment + 1;
108 zft_eom_vtbl->end_seg = ft_last_data_segment + 1;
109 zft_eom_vtbl->blk_sz = zft_blk_sz;
110 zft_eom_vtbl->count = 0;
111
112 /* Reset the pointer for zft_find_volume()
113 */
114 cur_vtbl = zft_eom_vtbl;
115
116 /* initialize the dummy vtbl entries for zft_qic_mode == 0
117 */
118 eot_vtbl.start_seg = ft_last_data_segment + 1;
119 eot_vtbl.end_seg = ft_last_data_segment + 1;
120 eot_vtbl.blk_sz = zft_blk_sz;
121 eot_vtbl.count = -1;
122 tape_vtbl.start_seg = ft_first_data_segment;
123 tape_vtbl.end_seg = ft_last_data_segment;
124 tape_vtbl.blk_sz = zft_blk_sz;
125 tape_vtbl.size = zft_capacity;
126 tape_vtbl.count = 0;
127}
128
129/* check for a valid VTBL signature.
130 */
131static int vtbl_signature_valid(__u8 signature[4])
132{
133 const char *vtbl_ids[] = VTBL_IDS; /* valid signatures */
134 int j;
135
136 for (j = 0;
137 (j < NR_ITEMS(vtbl_ids)) && (memcmp(signature, vtbl_ids[j], 4) != 0);
138 j++);
139 return j < NR_ITEMS(vtbl_ids);
140}
141
142/* We used to store the block-size of the volume in the volume-label,
143 * using the keyword "blocksize". The blocksize written to the
144 * volume-label is in bytes.
145 *
146 * We use this now only for compatibility with old zftape version. We
147 * store the blocksize directly as binary number in the vendor
148 * extension part of the volume entry.
149 */
150static int check_volume_label(const char *label, int *blk_sz)
151{
152 int valid_format;
153 char *blocksize;
154 TRACE_FUN(ft_t_flow);
155
156 TRACE(ft_t_noise, "called with \"%s\" / \"%s\"", label, ZFT_VOL_NAME);
157 if (strncmp(label, ZFT_VOL_NAME, strlen(ZFT_VOL_NAME)) != 0) {
158 *blk_sz = 1; /* smallest block size that we allow */
159 valid_format = 0;
160 } else {
161 TRACE(ft_t_noise, "got old style zftape vtbl entry");
162 /* get the default blocksize */
163 /* use the kernel strstr() */
164 blocksize= strstr(label, " blocksize ");
165 if (blocksize) {
166 blocksize += strlen(" blocksize ");
167 for(*blk_sz= 0;
168 *blocksize >= '0' && *blocksize <= '9';
169 blocksize++) {
170 *blk_sz *= 10;
171 *blk_sz += *blocksize - '0';
172 }
173 if (*blk_sz > ZFT_MAX_BLK_SZ) {
174 *blk_sz= 1;
175 valid_format= 0;
176 } else {
177 valid_format = 1;
178 }
179 } else {
180 *blk_sz= 1;
181 valid_format= 0;
182 }
183 }
184 TRACE_EXIT valid_format;
185}
186
187/* check for a zftape volume
188 */
189static int check_volume(__u8 *entry, zft_volinfo *volume)
190{
191 TRACE_FUN(ft_t_flow);
192
193 if(strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
194 strlen(ZFTAPE_SIG)) == 0) {
195 TRACE(ft_t_noise, "got new style zftape vtbl entry");
196 volume->blk_sz = GET2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ);
197 volume->qic113 = entry[VTBL_EXT+EXT_ZFTAPE_QIC113];
198 TRACE_EXIT 1;
199 } else {
200 TRACE_EXIT check_volume_label(&entry[VTBL_DESC], &volume->blk_sz);
201 }
202}
203
204
205/* create zftape specific vtbl entry, the volume bounds are inserted
206 * in the calling function, zft_create_volume_headers()
207 */
208static void create_zft_volume(__u8 *entry, zft_volinfo *vtbl)
209{
210 TRACE_FUN(ft_t_flow);
211
212 memset(entry, 0, VTBL_SIZE);
213 memcpy(&entry[VTBL_SIG], VTBL_ID, 4);
214 sprintf(&entry[VTBL_DESC], ZFT_VOL_NAME" %03d", vtbl->count);
215 entry[VTBL_FLAGS] = (VTBL_FL_NOT_VERIFIED | VTBL_FL_SEG_SPANNING);
216 entry[VTBL_M_NO] = 1; /* multi_cartridge_count */
217 strcpy(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG);
218 PUT2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ, vtbl->blk_sz);
219 if (zft_qic113) {
220 PUT8(entry, VTBL_DATA_SIZE, vtbl->size);
221 entry[VTBL_CMPR] = VTBL_CMPR_UNREG;
222 if (vtbl->use_compression) { /* use compression: */
223 entry[VTBL_CMPR] |= VTBL_CMPR_USED;
224 }
225 entry[VTBL_EXT+EXT_ZFTAPE_QIC113] = 1;
226 } else {
227 PUT4(entry, VTBL_DATA_SIZE, vtbl->size);
228 entry[VTBL_K_CMPR] = VTBL_CMPR_UNREG;
229 if (vtbl->use_compression) { /* use compression: */
230 entry[VTBL_K_CMPR] |= VTBL_CMPR_USED;
231 }
232 }
233 if (ft_format_code == fmt_big) {
234 /* SCSI like vtbl, store the number of used
235 * segments as 4 byte value
236 */
237 PUT4(entry, VTBL_SCSI_SEGS, vtbl->end_seg-vtbl->start_seg + 1);
238 } else {
239 /* normal, QIC-80MC like vtbl
240 */
241 PUT2(entry, VTBL_START, vtbl->start_seg);
242 PUT2(entry, VTBL_END, vtbl->end_seg);
243 }
244 TRACE_EXIT;
245}
246
247/* this one creates the volume headers for each volume. It is assumed
248 * that buffer already contains the old volume-table, so that vtbl
249 * entries without the zft_volume flag set can savely be ignored.
250 */
251static void zft_create_volume_headers(__u8 *buffer)
252{
253 __u8 *entry;
254 struct list_head *tmp;
255 zft_volinfo *vtbl;
256 TRACE_FUN(ft_t_flow);
257
258#ifdef ZFT_CMAP_HACK
259 if((strncmp(&buffer[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
260 strlen(ZFTAPE_SIG)) == 0) &&
261 buffer[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {
262 TRACE(ft_t_noise, "deleting cmap volume");
263 memmove(buffer, buffer + VTBL_SIZE,
264 FT_SEGMENT_SIZE - VTBL_SIZE);
265 }
266#endif
267 entry = buffer;
268 for (tmp = zft_head_vtbl->node.next;
269 tmp != &zft_eom_vtbl->node;
270 tmp = tmp->next) {
271 vtbl = list_entry(tmp, zft_volinfo, node);
272 /* we now fill in the values only for newly created volumes.
273 */
274 if (vtbl->new_volume) {
275 create_zft_volume(entry, vtbl);
276 vtbl->new_volume = 0; /* clear the flag */
277 }
278
279 DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], vtbl);
280 entry += VTBL_SIZE;
281 }
282 memset(entry, 0, FT_SEGMENT_SIZE - zft_eom_vtbl->count * VTBL_SIZE);
283 TRACE_EXIT;
284}
285
286/* write volume table to tape. Calls zft_create_volume_headers()
287 */
288int zft_update_volume_table(unsigned int segment)
289{
290 int result = 0;
291 __u8 *verify_buf = NULL;
292 TRACE_FUN(ft_t_flow);
293
294 TRACE_CATCH(result = ftape_read_segment(ft_first_data_segment,
295 zft_deblock_buf,
296 FT_RD_SINGLE),);
297 zft_create_volume_headers(zft_deblock_buf);
298 TRACE(ft_t_noise, "writing volume table segment %d", segment);
299 if (zft_vmalloc_once(&verify_buf, FT_SEGMENT_SIZE) == 0) {
300 TRACE_CATCH(zft_verify_write_segments(segment,
301 zft_deblock_buf, result,
302 verify_buf),
303 zft_vfree(&verify_buf, FT_SEGMENT_SIZE));
304 zft_vfree(&verify_buf, FT_SEGMENT_SIZE);
305 } else {
306 TRACE_CATCH(ftape_write_segment(segment, zft_deblock_buf,
307 FT_WR_SINGLE),);
308 }
309 TRACE_EXIT 0;
310}
311
312/* non zftape volumes are handled in raw mode. Thus we need to
313 * calculate the raw amount of data contained in those segments.
314 */
315static void extract_alien_volume(__u8 *entry, zft_volinfo *vtbl)
316{
317 TRACE_FUN(ft_t_flow);
318
319 vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) -
320 zft_calc_tape_pos(zft_last_vtbl->start_seg));
321 vtbl->use_compression = 0;
322 vtbl->qic113 = zft_qic113;
323 if (vtbl->qic113) {
324 TRACE(ft_t_noise,
325 "Fake alien volume's size from " LL_X " to " LL_X,
326 LL(GET8(entry, VTBL_DATA_SIZE)), LL(vtbl->size));
327 } else {
328 TRACE(ft_t_noise,
329 "Fake alien volume's size from %d to " LL_X,
330 (int)GET4(entry, VTBL_DATA_SIZE), LL(vtbl->size));
331 }
332 TRACE_EXIT;
333}
334
335
336/* extract an zftape specific volume
337 */
338static void extract_zft_volume(__u8 *entry, zft_volinfo *vtbl)
339{
340 TRACE_FUN(ft_t_flow);
341
342 if (vtbl->qic113) {
343 vtbl->size = GET8(entry, VTBL_DATA_SIZE);
344 vtbl->use_compression =
345 (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0;
346 } else {
347 vtbl->size = GET4(entry, VTBL_DATA_SIZE);
348 if (entry[VTBL_K_CMPR] & VTBL_CMPR_UNREG) {
349 vtbl->use_compression =
350 (entry[VTBL_K_CMPR] & VTBL_CMPR_USED) != 0;
351 } else if (entry[VTBL_CMPR] & VTBL_CMPR_UNREG) {
352 vtbl->use_compression =
353 (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0;
354 } else {
355 TRACE(ft_t_warn, "Geeh! There is something wrong:\n"
356 KERN_INFO "QIC compression (Rev = K): %x\n"
357 KERN_INFO "QIC compression (Rev > K): %x",
358 entry[VTBL_K_CMPR], entry[VTBL_CMPR]);
359 }
360 }
361 TRACE_EXIT;
362}
363
364/* extract the volume table from buffer. "buffer" must already contain
365 * the vtbl-segment
366 */
367int zft_extract_volume_headers(__u8 *buffer)
368{
369 __u8 *entry;
370 TRACE_FUN(ft_t_flow);
371
372 zft_init_vtbl();
373 entry = buffer;
374#ifdef ZFT_CMAP_HACK
375 if ((strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
376 strlen(ZFTAPE_SIG)) == 0) &&
377 entry[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {
378 TRACE(ft_t_noise, "ignoring cmap volume");
379 entry += VTBL_SIZE;
380 }
381#endif
382 /* the end of the vtbl is indicated by an invalid signature
383 */
384 while (vtbl_signature_valid(&entry[VTBL_SIG]) &&
385 (entry - buffer) < FT_SEGMENT_SIZE) {
386 zft_new_vtbl_entry();
387 if (ft_format_code == fmt_big) {
388 /* SCSI like vtbl, stores only the number of
389 * segments used
390 */
391 unsigned int num_segments= GET4(entry, VTBL_SCSI_SEGS);
392 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
393 zft_last_vtbl->end_seg =
394 zft_last_vtbl->start_seg + num_segments - 1;
395 } else {
396 /* `normal', QIC-80 like vtbl
397 */
398 zft_last_vtbl->start_seg = GET2(entry, VTBL_START);
399 zft_last_vtbl->end_seg = GET2(entry, VTBL_END);
400 }
401 zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;
402 /* check if we created this volume and get the
403 * blk_sz
404 */
405 zft_last_vtbl->zft_volume = check_volume(entry, zft_last_vtbl);
406 if (zft_last_vtbl->zft_volume == 0) {
407 extract_alien_volume(entry, zft_last_vtbl);
408 } else {
409 extract_zft_volume(entry, zft_last_vtbl);
410 }
411 DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], zft_last_vtbl);
412 entry +=VTBL_SIZE;
413 }
414#if 0
415/*
416 * undefine to test end of tape handling
417 */
418 zft_new_vtbl_entry();
419 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
420 zft_last_vtbl->end_seg = ft_last_data_segment - 10;
421 zft_last_vtbl->blk_sz = zft_blk_sz;
422 zft_last_vtbl->zft_volume = 1;
423 zft_last_vtbl->qic113 = zft_qic113;
424 zft_last_vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1)
425 - zft_calc_tape_pos(zft_last_vtbl->start_seg));
426#endif
427 TRACE_EXIT 0;
428}
429
430/* this functions translates the failed_sector_log, misused as
431 * EOF-marker list, into a virtual volume table. The table mustn't be
432 * written to tape, because this would occupy the first data segment,
433 * which should be the volume table, but is actually the first segment
434 * that is filled with data (when using standard ftape). We assume,
435 * that we get a non-empty failed_sector_log.
436 */
437int zft_fake_volume_headers (eof_mark_union *eof_map, int num_failed_sectors)
438{
439 unsigned int segment, sector;
440 int have_eom = 0;
441 int vol_no;
442 TRACE_FUN(ft_t_flow);
443
444 if ((num_failed_sectors >= 2) &&
445 (GET2(&eof_map[num_failed_sectors - 1].mark.segment, 0)
446 ==
447 GET2(&eof_map[num_failed_sectors - 2].mark.segment, 0) + 1) &&
448 (GET2(&eof_map[num_failed_sectors - 1].mark.date, 0) == 1)) {
449 /* this should be eom. We keep the remainder of the
450 * tape as another volume.
451 */
452 have_eom = 1;
453 }
454 zft_init_vtbl();
455 zft_eom_vtbl->start_seg = ft_first_data_segment;
456 for(vol_no = 0; vol_no < num_failed_sectors - have_eom; vol_no ++) {
457 zft_new_vtbl_entry();
458
459 segment = GET2(&eof_map[vol_no].mark.segment, 0);
460 sector = GET2(&eof_map[vol_no].mark.date, 0);
461
462 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
463 zft_last_vtbl->end_seg = segment;
464 zft_eom_vtbl->start_seg = segment + 1;
465 zft_last_vtbl->blk_sz = 1;
466 zft_last_vtbl->size =
467 (zft_calc_tape_pos(zft_last_vtbl->end_seg)
468 - zft_calc_tape_pos(zft_last_vtbl->start_seg)
469 + (sector-1) * FT_SECTOR_SIZE);
470 TRACE(ft_t_noise,
471 "failed sector log: segment: %d, sector: %d",
472 segment, sector);
473 DUMP_VOLINFO(ft_t_noise, "Faked volume", zft_last_vtbl);
474 }
475 if (!have_eom) {
476 zft_new_vtbl_entry();
477 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
478 zft_last_vtbl->end_seg = ft_last_data_segment;
479 zft_eom_vtbl->start_seg = ft_last_data_segment + 1;
480 zft_last_vtbl->size = zft_capacity;
481 zft_last_vtbl->size -= zft_calc_tape_pos(zft_last_vtbl->start_seg);
482 zft_last_vtbl->blk_sz = 1;
483 DUMP_VOLINFO(ft_t_noise, "Faked volume",zft_last_vtbl);
484 }
485 TRACE_EXIT 0;
486}
487
488/* update the internal volume table
489 *
490 * if before start of last volume: erase all following volumes if
491 * inside a volume: set end of volume to infinity
492 *
493 * this function is intended to be called every time _ftape_write() is
494 * called
495 *
496 * return: 0 if no new volume was created, 1 if a new volume was
497 * created
498 *
499 * NOTE: we don't need to check for zft_mode as ftape_write() does
500 * that already. This function gets never called without accessing
501 * zftape via the *qft* devices
502 */
503
504int zft_open_volume(zft_position *pos, int blk_sz, int use_compression)
505{
506 TRACE_FUN(ft_t_flow);
507
508 if (!zft_qic_mode) {
509 TRACE_EXIT 0;
510 }
511 if (zft_tape_at_lbot(pos)) {
512 zft_init_vtbl();
513 if(zft_old_ftape) {
514 /* clear old ftape's eof marks */
515 zft_clear_ftape_file_marks();
516 zft_old_ftape = 0; /* no longer old ftape */
517 }
518 zft_reset_position(pos);
519 }
520 if (pos->seg_pos != zft_last_vtbl->end_seg + 1) {
521 TRACE_ABORT(-EIO, ft_t_bug,
522 "BUG: seg_pos: %d, zft_last_vtbl->end_seg: %d",
523 pos->seg_pos, zft_last_vtbl->end_seg);
524 }
525 TRACE(ft_t_noise, "create new volume");
526 if (zft_eom_vtbl->count >= ZFT_MAX_VOLUMES) {
527 TRACE_ABORT(-ENOSPC, ft_t_err,
528 "Error: maxmimal number of volumes exhausted "
529 "(maxmimum is %d)", ZFT_MAX_VOLUMES);
530 }
531 zft_new_vtbl_entry();
532 pos->volume_pos = pos->seg_byte_pos = 0;
533 zft_last_vtbl->start_seg = pos->seg_pos;
534 zft_last_vtbl->end_seg = ft_last_data_segment; /* infinity */
535 zft_last_vtbl->blk_sz = blk_sz;
536 zft_last_vtbl->size = zft_capacity;
537 zft_last_vtbl->zft_volume = 1;
538 zft_last_vtbl->use_compression = use_compression;
539 zft_last_vtbl->qic113 = zft_qic113;
540 zft_last_vtbl->new_volume = 1;
541 zft_last_vtbl->open = 1;
542 zft_volume_table_changed = 1;
543 zft_eom_vtbl->start_seg = ft_last_data_segment + 1;
544 TRACE_EXIT 0;
545}
546
547/* perform mtfsf, mtbsf, not allowed without zft_qic_mode
548 */
549int zft_skip_volumes(int count, zft_position *pos)
550{
551 const zft_volinfo *vtbl;
552 TRACE_FUN(ft_t_flow);
553
554 TRACE(ft_t_noise, "count: %d", count);
555
556 vtbl= zft_find_volume(pos->seg_pos);
557 while (count > 0 && vtbl != zft_eom_vtbl) {
558 vtbl = list_entry(vtbl->node.next, zft_volinfo, node);
559 count --;
560 }
561 while (count < 0 && vtbl != zft_first_vtbl) {
562 vtbl = list_entry(vtbl->node.prev, zft_volinfo, node);
563 count ++;
564 }
565 pos->seg_pos = vtbl->start_seg;
566 pos->seg_byte_pos = 0;
567 pos->volume_pos = 0;
568 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
569 zft_just_before_eof = vtbl->size == 0;
570 if (zft_cmpr_ops) {
571 (*zft_cmpr_ops->reset)();
572 }
573 zft_deblock_segment = -1; /* no need to keep cache */
574 TRACE(ft_t_noise, "repositioning to:\n"
575 KERN_INFO "zft_seg_pos : %d\n"
576 KERN_INFO "zft_seg_byte_pos : %d\n"
577 KERN_INFO "zft_tape_pos : " LL_X "\n"
578 KERN_INFO "zft_volume_pos : " LL_X "\n"
579 KERN_INFO "file number : %d",
580 pos->seg_pos, pos->seg_byte_pos,
581 LL(pos->tape_pos), LL(pos->volume_pos), vtbl->count);
582 zft_resid = count < 0 ? -count : count;
583 TRACE_EXIT zft_resid ? -EINVAL : 0;
584}
585
586/* the following simply returns the raw data position of the EOM
587 * marker, MTIOCSIZE ioctl
588 */
589__s64 zft_get_eom_pos(void)
590{
591 if (zft_qic_mode) {
592 return zft_calc_tape_pos(zft_eom_vtbl->start_seg);
593 } else {
594 /* there is only one volume in raw mode */
595 return zft_capacity;
596 }
597}
598
599/* skip to eom, used for MTEOM
600 */
601void zft_skip_to_eom(zft_position *pos)
602{
603 TRACE_FUN(ft_t_flow);
604 pos->seg_pos = zft_eom_vtbl->start_seg;
605 pos->seg_byte_pos =
606 pos->volume_pos =
607 zft_just_before_eof = 0;
608 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
609 TRACE(ft_t_noise, "ftape positioned to segment %d, data pos " LL_X,
610 pos->seg_pos, LL(pos->tape_pos));
611 TRACE_EXIT;
612}
613
614/* write an EOF-marker by setting zft_last_vtbl->end_seg to seg_pos.
615 * NOTE: this function assumes that zft_last_vtbl points to a valid
616 * vtbl entry
617 *
618 * NOTE: this routine always positions before the EOF marker
619 */
620int zft_close_volume(zft_position *pos)
621{
622 TRACE_FUN(ft_t_any);
623
624 if (zft_vtbl_empty || !zft_last_vtbl->open) { /* should not happen */
625 TRACE(ft_t_noise, "There are no volumes to finish");
626 TRACE_EXIT -EIO;
627 }
628 if (pos->seg_byte_pos == 0 &&
629 pos->seg_pos != zft_last_vtbl->start_seg) {
630 pos->seg_pos --;
631 pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);
632 }
633 zft_last_vtbl->end_seg = pos->seg_pos;
634 zft_last_vtbl->size = pos->volume_pos;
635 zft_volume_table_changed = 1;
636 zft_just_before_eof = 1;
637 zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;
638 zft_last_vtbl->open = 0; /* closed */
639 TRACE_EXIT 0;
640}
641
642/* write count file-marks at current position.
643 *
644 * The tape is positioned after the eof-marker, that is at byte 0 of
645 * the segment following the eof-marker
646 *
647 * this function is only allowed in zft_qic_mode
648 *
649 * Only allowed when tape is at BOT or EOD.
650 */
651int zft_weof(unsigned int count, zft_position *pos)
652{
653
654 TRACE_FUN(ft_t_flow);
655
656 if (!count) { /* write zero EOF marks should be a real no-op */
657 TRACE_EXIT 0;
658 }
659 zft_volume_table_changed = 1;
660 if (zft_tape_at_lbot(pos)) {
661 zft_init_vtbl();
662 if(zft_old_ftape) {
663 /* clear old ftape's eof marks */
664 zft_clear_ftape_file_marks();
665 zft_old_ftape = 0; /* no longer old ftape */
666 }
667 }
668 if (zft_last_vtbl->open) {
669 zft_close_volume(pos);
670 zft_move_past_eof(pos);
671 count --;
672 }
673 /* now it's easy, just append eof-marks, that is empty
674 * volumes, to the end of the already recorded media.
675 */
676 while (count > 0 &&
677 pos->seg_pos <= ft_last_data_segment &&
678 zft_eom_vtbl->count < ZFT_MAX_VOLUMES) {
679 TRACE(ft_t_noise,
680 "Writing zero sized file at segment %d", pos->seg_pos);
681 zft_new_vtbl_entry();
682 zft_last_vtbl->start_seg = pos->seg_pos;
683 zft_last_vtbl->end_seg = pos->seg_pos;
684 zft_last_vtbl->size = 0;
685 zft_last_vtbl->blk_sz = zft_blk_sz;
686 zft_last_vtbl->zft_volume = 1;
687 zft_last_vtbl->use_compression = 0;
688 pos->tape_pos += zft_get_seg_sz(pos->seg_pos);
689 zft_eom_vtbl->start_seg = ++ pos->seg_pos;
690 count --;
691 }
692 if (count > 0) {
693 /* there are two possibilities: end of tape, or the
694 * maximum number of files is exhausted.
695 */
696 zft_resid = count;
697 TRACE(ft_t_noise,"Number of marks NOT written: %d", zft_resid);
698 if (zft_eom_vtbl->count == ZFT_MAX_VOLUMES) {
699 TRACE_ABORT(-EINVAL, ft_t_warn,
700 "maximum allowed number of files "
701 "exhausted: %d", ZFT_MAX_VOLUMES);
702 } else {
703 TRACE_ABORT(-ENOSPC,
704 ft_t_noise, "reached end of tape");
705 }
706 }
707 TRACE_EXIT 0;
708}
709
710const zft_volinfo *zft_find_volume(unsigned int seg_pos)
711{
712 TRACE_FUN(ft_t_flow);
713
714 TRACE(ft_t_any, "called with seg_pos %d",seg_pos);
715 if (!zft_qic_mode) {
716 if (seg_pos > ft_last_data_segment) {
717 TRACE_EXIT &eot_vtbl;
718 }
719 tape_vtbl.blk_sz = zft_blk_sz;
720 TRACE_EXIT &tape_vtbl;
721 }
722 if (seg_pos < zft_first_vtbl->start_seg) {
723 TRACE_EXIT (cur_vtbl = zft_first_vtbl);
724 }
725 while (seg_pos > cur_vtbl->end_seg) {
726 cur_vtbl = list_entry(cur_vtbl->node.next, zft_volinfo, node);
727 TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);
728 }
729 while (seg_pos < cur_vtbl->start_seg) {
730 cur_vtbl = list_entry(cur_vtbl->node.prev, zft_volinfo, node);
731 TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);
732 }
733 if (seg_pos > cur_vtbl->end_seg || seg_pos < cur_vtbl->start_seg) {
734 TRACE(ft_t_bug, "This cannot happen");
735 }
736 DUMP_VOLINFO(ft_t_noise, "", cur_vtbl);
737 TRACE_EXIT cur_vtbl;
738}
739
740/* this function really assumes that we are just before eof
741 */
742void zft_move_past_eof(zft_position *pos)
743{
744 TRACE_FUN(ft_t_flow);
745
746 TRACE(ft_t_noise, "old seg. pos: %d", pos->seg_pos);
747 pos->tape_pos += zft_get_seg_sz(pos->seg_pos++) - pos->seg_byte_pos;
748 pos->seg_byte_pos = 0;
749 pos->volume_pos = 0;
750 if (zft_cmpr_ops) {
751 (*zft_cmpr_ops->reset)();
752 }
753 zft_just_before_eof = 0;
754 zft_deblock_segment = -1; /* no need to cache it anymore */
755 TRACE(ft_t_noise, "new seg. pos: %d", pos->seg_pos);
756 TRACE_EXIT;
757}
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.h b/drivers/char/ftape/zftape/zftape-vtbl.h
deleted file mode 100644
index f31d196d1759..000000000000
--- a/drivers/char/ftape/zftape/zftape-vtbl.h
+++ /dev/null
@@ -1,227 +0,0 @@
1#ifndef _ZFTAPE_VTBL_H
2#define _ZFTAPE_VTBL_H
3
4/*
5 * Copyright (c) 1995-1997 Claus-Justus Heine
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 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,
20 USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.h,v $
24 * $Revision: 1.3 $
25 * $Date: 1997/10/28 14:30:09 $
26 *
27 * This file defines a volume table as defined in the QIC-80
28 * development standards.
29 */
30
31#include <linux/list.h>
32
33#include "../lowlevel/ftape-tracing.h"
34
35#include "../zftape/zftape-eof.h"
36#include "../zftape/zftape-ctl.h"
37#include "../zftape/zftape-rw.h"
38
39#define VTBL_SIZE 128 /* bytes */
40
41/* The following are offsets in the vtbl. */
42#define VTBL_SIG 0
43#define VTBL_START 4
44#define VTBL_END 6
45#define VTBL_DESC 8
46#define VTBL_DATE 52
47#define VTBL_FLAGS 56
48#define VTBL_FL_VENDOR_SPECIFIC (1<<0)
49#define VTBL_FL_MUTLI_CARTRIDGE (1<<1)
50#define VTBL_FL_NOT_VERIFIED (1<<2)
51#define VTBL_FL_REDIR_INHIBIT (1<<3)
52#define VTBL_FL_SEG_SPANNING (1<<4)
53#define VTBL_FL_DIRECTORY_LAST (1<<5)
54#define VTBL_FL_RESERVED_6 (1<<6)
55#define VTBL_FL_RESERVED_7 (1<<7)
56#define VTBL_M_NO 57
57#define VTBL_EXT 58
58#define EXT_ZFTAPE_SIG 0
59#define EXT_ZFTAPE_BLKSZ 10
60#define EXT_ZFTAPE_CMAP 12
61#define EXT_ZFTAPE_QIC113 13
62#define VTBL_PWD 84
63#define VTBL_DIR_SIZE 92
64#define VTBL_DATA_SIZE 96
65#define VTBL_OS_VERSION 104
66#define VTBL_SRC_DRIVE 106
67#define VTBL_DEV 122
68#define VTBL_RESERVED_1 123
69#define VTBL_CMPR 124
70#define VTBL_CMPR_UNREG 0x3f
71#define VTBL_CMPR_USED 0x80
72#define VTBL_FMT 125
73#define VTBL_RESERVED_2 126
74#define VTBL_RESERVED_3 127
75/* compatibility with pre revision K */
76#define VTBL_K_CMPR 120
77
78/* the next is used by QIC-3020 tapes with format code 6 (>2^16
79 * segments) It is specified in QIC-113, Rev. G, Section 5 (SCSI
80 * volume table). The difference is simply, that we only store the
81 * number of segments used, not the starting segment.
82 */
83#define VTBL_SCSI_SEGS 4 /* is a 4 byte value */
84
85/* one vtbl is 128 bytes, that results in a maximum number of
86 * 29*1024/128 = 232 volumes.
87 */
88#define ZFT_MAX_VOLUMES (FT_SEGMENT_SIZE/VTBL_SIZE)
89#define VTBL_ID "VTBL"
90#define VTBL_IDS { VTBL_ID, "XTBL", "UTID", "EXVT" } /* other valid ids */
91#define ZFT_VOL_NAME "zftape volume" /* volume label used by me */
92#define ZFTAPE_SIG "LINUX ZFT"
93
94/* global variables
95 */
96typedef struct zft_internal_vtbl
97{
98 struct list_head node;
99 int count;
100 unsigned int start_seg; /* 32 bits are enough for now */
101 unsigned int end_seg; /* 32 bits are enough for now */
102 __s64 size; /* uncompressed size */
103 unsigned int blk_sz; /* block size for this volume */
104 unsigned int zft_volume :1; /* zftape created this volume */
105 unsigned int use_compression:1; /* compressed volume */
106 unsigned int qic113 :1; /* layout of compressed block
107 * info and vtbl conforms to
108 * QIC-113, Rev. G
109 */
110 unsigned int new_volume :1; /* it was created by us, this
111 * run. this allows the
112 * fields that aren't really
113 * used by zftape to be filled
114 * in by some user level
115 * program.
116 */
117 unsigned int open :1; /* just in progress of being
118 * written
119 */
120} zft_volinfo;
121
122extern struct list_head zft_vtbl;
123#define zft_head_vtbl list_entry(zft_vtbl.next, zft_volinfo, node)
124#define zft_eom_vtbl list_entry(zft_vtbl.prev, zft_volinfo, node)
125#define zft_last_vtbl list_entry(zft_eom_vtbl->node.prev, zft_volinfo, node)
126#define zft_first_vtbl list_entry(zft_head_vtbl->node.next, zft_volinfo, node)
127#define zft_vtbl_empty (zft_eom_vtbl->node.prev == &zft_head_vtbl->node)
128
129#define DUMP_VOLINFO(level, desc, info) \
130{ \
131 char tmp[21]; \
132 strlcpy(tmp, desc, sizeof(tmp)); \
133 TRACE(level, "Volume %d:\n" \
134 KERN_INFO "description : %s\n" \
135 KERN_INFO "first segment: %d\n" \
136 KERN_INFO "last segment: %d\n" \
137 KERN_INFO "size : " LL_X "\n" \
138 KERN_INFO "block size : %d\n" \
139 KERN_INFO "compression : %d\n" \
140 KERN_INFO "zftape volume: %d\n" \
141 KERN_INFO "QIC-113 conf.: %d", \
142 (info)->count, tmp, (info)->start_seg, (info)->end_seg, \
143 LL((info)->size), (info)->blk_sz, \
144 (info)->use_compression != 0, (info)->zft_volume != 0, \
145 (info)->qic113 != 0); \
146}
147
148extern int zft_qic_mode;
149extern int zft_old_ftape;
150extern int zft_volume_table_changed;
151
152/* exported functions */
153extern void zft_init_vtbl (void);
154extern void zft_free_vtbl (void);
155extern int zft_extract_volume_headers(__u8 *buffer);
156extern int zft_update_volume_table (unsigned int segment);
157extern int zft_open_volume (zft_position *pos,
158 int blk_sz, int use_compression);
159extern int zft_close_volume (zft_position *pos);
160extern const zft_volinfo *zft_find_volume(unsigned int seg_pos);
161extern int zft_skip_volumes (int count, zft_position *pos);
162extern __s64 zft_get_eom_pos (void);
163extern void zft_skip_to_eom (zft_position *pos);
164extern int zft_fake_volume_headers (eof_mark_union *eof_map,
165 int num_failed_sectors);
166extern int zft_weof (unsigned int count, zft_position *pos);
167extern void zft_move_past_eof (zft_position *pos);
168
169static inline int zft_tape_at_eod (const zft_position *pos);
170static inline int zft_tape_at_lbot (const zft_position *pos);
171static inline void zft_position_before_eof (zft_position *pos,
172 const zft_volinfo *volume);
173static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
174 const zft_position *pos);
175
176/* this function decrements the zft_seg_pos counter if we are right
177 * at the beginning of a segment. This is to handle fsfm/bsfm -- we
178 * need to position before the eof mark. NOTE: zft_tape_pos is not
179 * changed
180 */
181static inline void zft_position_before_eof(zft_position *pos,
182 const zft_volinfo *volume)
183{
184 TRACE_FUN(ft_t_flow);
185
186 if (pos->seg_pos == volume->end_seg + 1 && pos->seg_byte_pos == 0) {
187 pos->seg_pos --;
188 pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);
189 }
190 TRACE_EXIT;
191}
192
193/* Mmmh. Is the position at the end of the last volume, that is right
194 * before the last EOF mark also logical an EOD condition?
195 */
196static inline int zft_tape_at_eod(const zft_position *pos)
197{
198 TRACE_FUN(ft_t_any);
199
200 if (zft_qic_mode) {
201 TRACE_EXIT (pos->seg_pos >= zft_eom_vtbl->start_seg ||
202 zft_last_vtbl->open);
203 } else {
204 TRACE_EXIT pos->seg_pos > ft_last_data_segment;
205 }
206}
207
208static inline int zft_tape_at_lbot(const zft_position *pos)
209{
210 if (zft_qic_mode) {
211 return (pos->seg_pos <= zft_first_vtbl->start_seg &&
212 pos->volume_pos == 0);
213 } else {
214 return (pos->seg_pos <= ft_first_data_segment &&
215 pos->volume_pos == 0);
216 }
217}
218
219/* This one checks for EOF. return remaing space (may be negative)
220 */
221static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
222 const zft_position *pos)
223{
224 return (__s64)(vtbl->size - pos->volume_pos);
225}
226
227#endif /* _ZFTAPE_VTBL_H */
diff --git a/drivers/char/ftape/zftape/zftape-write.c b/drivers/char/ftape/zftape/zftape-write.c
deleted file mode 100644
index 94327b8c97b9..000000000000
--- a/drivers/char/ftape/zftape/zftape-write.c
+++ /dev/null
@@ -1,483 +0,0 @@
1/*
2 * Copyright (C) 1996, 1997 Claus 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/zftape/zftape-write.c,v $
20 * $Revision: 1.3 $
21 * $Date: 1997/11/06 00:50:29 $
22 *
23 * This file contains the writing code
24 * for the QIC-117 floppy-tape driver for Linux.
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29
30#include <linux/zftape.h>
31
32#include <asm/uaccess.h>
33
34#include "../zftape/zftape-init.h"
35#include "../zftape/zftape-eof.h"
36#include "../zftape/zftape-ctl.h"
37#include "../zftape/zftape-write.h"
38#include "../zftape/zftape-read.h"
39#include "../zftape/zftape-rw.h"
40#include "../zftape/zftape-vtbl.h"
41
42/* Global vars.
43 */
44
45/* Local vars.
46 */
47static int last_write_failed;
48static int need_flush;
49
50void zft_prevent_flush(void)
51{
52 need_flush = 0;
53}
54
55static int zft_write_header_segments(__u8* buffer)
56{
57 int header_1_ok = 0;
58 int header_2_ok = 0;
59 unsigned int time_stamp;
60 TRACE_FUN(ft_t_noise);
61
62 TRACE_CATCH(ftape_abort_operation(),);
63 ftape_seek_to_bot(); /* prevents extra rewind */
64 if (GET4(buffer, 0) != FT_HSEG_MAGIC) {
65 TRACE_ABORT(-EIO, ft_t_err,
66 "wrong header signature found, aborting");
67 }
68 /* Be optimistic: */
69 PUT4(buffer, FT_SEG_CNT,
70 zft_written_segments + GET4(buffer, FT_SEG_CNT) + 2);
71 if ((time_stamp = zft_get_time()) != 0) {
72 PUT4(buffer, FT_WR_DATE, time_stamp);
73 if (zft_label_changed) {
74 PUT4(buffer, FT_LABEL_DATE, time_stamp);
75 }
76 }
77 TRACE(ft_t_noise,
78 "writing first header segment %d", ft_header_segment_1);
79 header_1_ok = zft_verify_write_segments(ft_header_segment_1,
80 buffer, FT_SEGMENT_SIZE,
81 zft_deblock_buf) >= 0;
82 TRACE(ft_t_noise,
83 "writing second header segment %d", ft_header_segment_2);
84 header_2_ok = zft_verify_write_segments(ft_header_segment_2,
85 buffer, FT_SEGMENT_SIZE,
86 zft_deblock_buf) >= 0;
87 if (!header_1_ok) {
88 TRACE(ft_t_warn, "Warning: "
89 "update of first header segment failed");
90 }
91 if (!header_2_ok) {
92 TRACE(ft_t_warn, "Warning: "
93 "update of second header segment failed");
94 }
95 if (!header_1_ok && !header_2_ok) {
96 TRACE_ABORT(-EIO, ft_t_err, "Error: "
97 "update of both header segments failed.");
98 }
99 TRACE_EXIT 0;
100}
101
102int zft_update_header_segments(void)
103{
104 TRACE_FUN(ft_t_noise);
105
106 /* must NOT use zft_write_protected, as it also includes the
107 * file access mode. But we also want to update when soft
108 * write protection is enabled (O_RDONLY)
109 */
110 if (ft_write_protected || zft_old_ftape) {
111 TRACE_ABORT(0, ft_t_noise, "Tape set read-only: no update");
112 }
113 if (!zft_header_read) {
114 TRACE_ABORT(0, ft_t_noise, "Nothing to update");
115 }
116 if (!zft_header_changed) {
117 zft_header_changed = zft_written_segments > 0;
118 }
119 if (!zft_header_changed && !zft_volume_table_changed) {
120 TRACE_ABORT(0, ft_t_noise, "Nothing to update");
121 }
122 TRACE(ft_t_noise, "Updating header segments");
123 if (ftape_get_status()->fti_state == writing) {
124 TRACE_CATCH(ftape_loop_until_writes_done(),);
125 }
126 TRACE_CATCH(ftape_abort_operation(),);
127
128 zft_deblock_segment = -1; /* invalidate the cache */
129 if (zft_header_changed) {
130 TRACE_CATCH(zft_write_header_segments(zft_hseg_buf),);
131 }
132 if (zft_volume_table_changed) {
133 TRACE_CATCH(zft_update_volume_table(ft_first_data_segment),);
134 }
135 zft_header_changed =
136 zft_volume_table_changed =
137 zft_label_changed =
138 zft_written_segments = 0;
139 TRACE_CATCH(ftape_abort_operation(),);
140 ftape_seek_to_bot();
141 TRACE_EXIT 0;
142}
143
144static int read_merge_buffer(int seg_pos, __u8 *buffer, int offset, int seg_sz)
145{
146 int result = 0;
147 const ft_trace_t old_tracing = TRACE_LEVEL;
148 TRACE_FUN(ft_t_flow);
149
150 if (zft_qic_mode) {
151 /* writing in the middle of a volume is NOT allowed
152 *
153 */
154 TRACE(ft_t_noise, "No need to read a segment");
155 memset(buffer + offset, 0, seg_sz - offset);
156 TRACE_EXIT 0;
157 }
158 TRACE(ft_t_any, "waiting");
159 ftape_start_writing(FT_WR_MULTI);
160 TRACE_CATCH(ftape_loop_until_writes_done(),);
161
162 TRACE(ft_t_noise, "trying to read segment %d from offset %d",
163 seg_pos, offset);
164 SET_TRACE_LEVEL(ft_t_bug);
165 result = zft_fetch_segment_fraction(seg_pos, buffer,
166 FT_RD_SINGLE,
167 offset, seg_sz - offset);
168 SET_TRACE_LEVEL(old_tracing);
169 if (result != (seg_sz - offset)) {
170 TRACE(ft_t_noise, "Ignore error: read_segment() result: %d",
171 result);
172 memset(buffer + offset, 0, seg_sz - offset);
173 }
174 TRACE_EXIT 0;
175}
176
177/* flush the write buffer to tape and write an eof-marker at the
178 * current position if not in raw mode. This function always
179 * positions the tape before the eof-marker. _ftape_close() should
180 * then advance to the next segment.
181 *
182 * the parameter "finish_volume" describes whether to position before
183 * or after the possibly created file-mark. We always position after
184 * the file-mark when called from ftape_close() and a flush was needed
185 * (that is ftape_write() was the last tape operation before calling
186 * ftape_flush) But we always position before the file-mark when this
187 * function get's called from outside ftape_close()
188 */
189int zft_flush_buffers(void)
190{
191 int result;
192 int data_remaining;
193 int this_segs_size;
194 TRACE_FUN(ft_t_flow);
195
196 TRACE(ft_t_data_flow,
197 "entered, ftape_state = %d", ftape_get_status()->fti_state);
198 if (ftape_get_status()->fti_state != writing && !need_flush) {
199 TRACE_ABORT(0, ft_t_noise, "no need for flush");
200 }
201 zft_io_state = zft_idle; /* triggers some initializations for the
202 * read and write routines
203 */
204 if (last_write_failed) {
205 ftape_abort_operation();
206 TRACE_EXIT -EIO;
207 }
208 TRACE(ft_t_noise, "flushing write buffers");
209 this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
210 if (this_segs_size == zft_pos.seg_byte_pos) {
211 zft_pos.seg_pos ++;
212 data_remaining = zft_pos.seg_byte_pos = 0;
213 } else {
214 data_remaining = zft_pos.seg_byte_pos;
215 }
216 /* If there is any data not written to tape yet, append zero's
217 * up to the end of the sector (if using compression) or merge
218 * it with the data existing on the tape Then write the
219 * segment(s) to tape.
220 */
221 TRACE(ft_t_noise, "Position:\n"
222 KERN_INFO "seg_pos : %d\n"
223 KERN_INFO "byte pos : %d\n"
224 KERN_INFO "remaining: %d",
225 zft_pos.seg_pos, zft_pos.seg_byte_pos, data_remaining);
226 if (data_remaining > 0) {
227 do {
228 this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
229 if (this_segs_size > data_remaining) {
230 TRACE_CATCH(read_merge_buffer(zft_pos.seg_pos,
231 zft_deblock_buf,
232 data_remaining,
233 this_segs_size),
234 last_write_failed = 1);
235 }
236 result = ftape_write_segment(zft_pos.seg_pos,
237 zft_deblock_buf,
238 FT_WR_MULTI);
239 if (result != this_segs_size) {
240 TRACE(ft_t_err, "flush buffers failed");
241 zft_pos.tape_pos -= zft_pos.seg_byte_pos;
242 zft_pos.seg_byte_pos = 0;
243
244 last_write_failed = 1;
245 TRACE_EXIT result;
246 }
247 zft_written_segments ++;
248 TRACE(ft_t_data_flow,
249 "flush, moved out buffer: %d", result);
250 /* need next segment for more data (empty segments?)
251 */
252 if (result < data_remaining) {
253 if (result > 0) {
254 /* move remainder to buffer beginning
255 */
256 memmove(zft_deblock_buf,
257 zft_deblock_buf + result,
258 FT_SEGMENT_SIZE - result);
259 }
260 }
261 data_remaining -= result;
262 zft_pos.seg_pos ++;
263 } while (data_remaining > 0);
264 TRACE(ft_t_any, "result: %d", result);
265 zft_deblock_segment = --zft_pos.seg_pos;
266 if (data_remaining == 0) { /* first byte next segment */
267 zft_pos.seg_byte_pos = this_segs_size;
268 } else { /* after data previous segment, data_remaining < 0 */
269 zft_pos.seg_byte_pos = data_remaining + result;
270 }
271 } else {
272 TRACE(ft_t_noise, "zft_deblock_buf empty");
273 zft_pos.seg_pos --;
274 zft_pos.seg_byte_pos = zft_get_seg_sz (zft_pos.seg_pos);
275 ftape_start_writing(FT_WR_MULTI);
276 }
277 TRACE(ft_t_any, "waiting");
278 if ((result = ftape_loop_until_writes_done()) < 0) {
279 /* that's really bad. What to to with zft_tape_pos?
280 */
281 TRACE(ft_t_err, "flush buffers failed");
282 }
283 TRACE(ft_t_any, "zft_seg_pos: %d, zft_seg_byte_pos: %d",
284 zft_pos.seg_pos, zft_pos.seg_byte_pos);
285 last_write_failed =
286 need_flush = 0;
287 TRACE_EXIT result;
288}
289
290/* return-value: the number of bytes removed from the user-buffer
291 *
292 * out:
293 * int *write_cnt: how much actually has been moved to the
294 * zft_deblock_buf
295 * int req_len : MUST NOT BE CHANGED, except at EOT, in
296 * which case it may be adjusted
297 * in :
298 * char *buff : the user buffer
299 * int buf_pos_write : copy of buf_len_wr int
300 * this_segs_size : the size in bytes of the actual segment
301 * char
302 * *zft_deblock_buf : zft_deblock_buf
303 */
304static int zft_simple_write(int *cnt,
305 __u8 *dst_buf, const int seg_sz,
306 const __u8 __user *src_buf, const int req_len,
307 const zft_position *pos,const zft_volinfo *volume)
308{
309 int space_left;
310 TRACE_FUN(ft_t_flow);
311
312 /* volume->size holds the tape capacity while volume is open */
313 if (pos->tape_pos + volume->blk_sz > volume->size) {
314 TRACE_EXIT -ENOSPC;
315 }
316 /* remaining space in this segment, NOT zft_deblock_buf
317 */
318 space_left = seg_sz - pos->seg_byte_pos;
319 *cnt = req_len < space_left ? req_len : space_left;
320 if (copy_from_user(dst_buf + pos->seg_byte_pos, src_buf, *cnt) != 0) {
321 TRACE_EXIT -EFAULT;
322 }
323 TRACE_EXIT *cnt;
324}
325
326static int check_write_access(int req_len,
327 const zft_volinfo **volume,
328 zft_position *pos,
329 const unsigned int blk_sz)
330{
331 int result;
332 TRACE_FUN(ft_t_flow);
333
334 if ((req_len % zft_blk_sz) != 0) {
335 TRACE_ABORT(-EINVAL, ft_t_info,
336 "write-count %d must be multiple of block-size %d",
337 req_len, blk_sz);
338 }
339 if (zft_io_state == zft_writing) {
340 /* all other error conditions have been checked earlier
341 */
342 TRACE_EXIT 0;
343 }
344 zft_io_state = zft_idle;
345 TRACE_CATCH(zft_check_write_access(pos),);
346 /* If we haven't read the header segment yet, do it now.
347 * This will verify the configuration, get the bad sector
348 * table and read the volume table segment
349 */
350 if (!zft_header_read) {
351 TRACE_CATCH(zft_read_header_segments(),);
352 }
353 /* fine. Now the tape is either at BOT or at EOD,
354 * Write start of volume now
355 */
356 TRACE_CATCH(zft_open_volume(pos, blk_sz, zft_use_compression),);
357 *volume = zft_find_volume(pos->seg_pos);
358 DUMP_VOLINFO(ft_t_noise, "", *volume);
359 zft_just_before_eof = 0;
360 /* now merge with old data if necessary */
361 if (!zft_qic_mode && pos->seg_byte_pos != 0){
362 result = zft_fetch_segment(pos->seg_pos,
363 zft_deblock_buf,
364 FT_RD_SINGLE);
365 if (result < 0) {
366 if (result == -EINTR || result == -ENOSPC) {
367 TRACE_EXIT result;
368 }
369 TRACE(ft_t_noise,
370 "ftape_read_segment() result: %d. "
371 "This might be normal when using "
372 "a newly\nformatted tape", result);
373 memset(zft_deblock_buf, '\0', pos->seg_byte_pos);
374 }
375 }
376 zft_io_state = zft_writing;
377 TRACE_EXIT 0;
378}
379
380static int fill_deblock_buf(__u8 *dst_buf, const int seg_sz,
381 zft_position *pos, const zft_volinfo *volume,
382 const char __user *usr_buf, const int req_len)
383{
384 int cnt = 0;
385 int result = 0;
386 TRACE_FUN(ft_t_flow);
387
388 if (seg_sz == 0) {
389 TRACE_ABORT(0, ft_t_data_flow, "empty segment");
390 }
391 TRACE(ft_t_data_flow, "\n"
392 KERN_INFO "remaining req_len: %d\n"
393 KERN_INFO " buf_pos: %d",
394 req_len, pos->seg_byte_pos);
395 /* zft_deblock_buf will not contain a valid segment any longer */
396 zft_deblock_segment = -1;
397 if (zft_use_compression) {
398 TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
399 TRACE_CATCH(result= (*zft_cmpr_ops->write)(&cnt,
400 dst_buf, seg_sz,
401 usr_buf, req_len,
402 pos, volume),);
403 } else {
404 TRACE_CATCH(result= zft_simple_write(&cnt,
405 dst_buf, seg_sz,
406 usr_buf, req_len,
407 pos, volume),);
408 }
409 pos->volume_pos += result;
410 pos->seg_byte_pos += cnt;
411 pos->tape_pos += cnt;
412 TRACE(ft_t_data_flow, "\n"
413 KERN_INFO "removed from user-buffer : %d bytes.\n"
414 KERN_INFO "copied to zft_deblock_buf: %d bytes.\n"
415 KERN_INFO "zft_tape_pos : " LL_X " bytes.",
416 result, cnt, LL(pos->tape_pos));
417 TRACE_EXIT result;
418}
419
420
421/* called by the kernel-interface routine "zft_write()"
422 */
423int _zft_write(const char __user *buff, int req_len)
424{
425 int result = 0;
426 int written = 0;
427 int write_cnt;
428 int seg_sz;
429 static const zft_volinfo *volume = NULL;
430 TRACE_FUN(ft_t_flow);
431
432 zft_resid = req_len;
433 last_write_failed = 1; /* reset to 0 when successful */
434 /* check if write is allowed
435 */
436 TRACE_CATCH(check_write_access(req_len, &volume,&zft_pos,zft_blk_sz),);
437 while (req_len > 0) {
438 /* Allow us to escape from this loop with a signal !
439 */
440 FT_SIGNAL_EXIT(_DONT_BLOCK);
441 seg_sz = zft_get_seg_sz(zft_pos.seg_pos);
442 if ((write_cnt = fill_deblock_buf(zft_deblock_buf,
443 seg_sz,
444 &zft_pos,
445 volume,
446 buff,
447 req_len)) < 0) {
448 zft_resid -= written;
449 if (write_cnt == -ENOSPC) {
450 /* leave the remainder to flush_buffers()
451 */
452 TRACE(ft_t_info, "No space left on device");
453 last_write_failed = 0;
454 if (!need_flush) {
455 need_flush = written > 0;
456 }
457 TRACE_EXIT written > 0 ? written : -ENOSPC;
458 } else {
459 TRACE_EXIT result;
460 }
461 }
462 if (zft_pos.seg_byte_pos == seg_sz) {
463 TRACE_CATCH(ftape_write_segment(zft_pos.seg_pos,
464 zft_deblock_buf,
465 FT_WR_ASYNC),
466 zft_resid -= written);
467 zft_written_segments ++;
468 zft_pos.seg_byte_pos = 0;
469 zft_deblock_segment = zft_pos.seg_pos;
470 ++zft_pos.seg_pos;
471 }
472 written += write_cnt;
473 buff += write_cnt;
474 req_len -= write_cnt;
475 } /* while (req_len > 0) */
476 TRACE(ft_t_data_flow, "remaining in blocking buffer: %d",
477 zft_pos.seg_byte_pos);
478 TRACE(ft_t_data_flow, "just written bytes: %d", written);
479 last_write_failed = 0;
480 zft_resid -= written;
481 need_flush = need_flush || written > 0;
482 TRACE_EXIT written; /* bytes written */
483}
diff --git a/drivers/char/ftape/zftape/zftape-write.h b/drivers/char/ftape/zftape/zftape-write.h
deleted file mode 100644
index ea887015b493..000000000000
--- a/drivers/char/ftape/zftape/zftape-write.h
+++ /dev/null
@@ -1,38 +0,0 @@
1#ifndef _ZFTAPE_WRITE_H
2#define _ZFTAPE_WRITE_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/zftape/zftape-write.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:13 $
25 *
26 * This file contains the definitions for the write functions
27 * for the zftape driver for Linux.
28 *
29 */
30
31extern int zft_flush_buffers(void);
32extern int zft_update_header_segments(void);
33extern void zft_prevent_flush(void);
34
35/* hook for the VFS interface
36 */
37extern int _zft_write(const char __user *buff, int req_len);
38#endif /* _ZFTAPE_WRITE_H */
diff --git a/drivers/char/ftape/zftape/zftape_syms.c b/drivers/char/ftape/zftape/zftape_syms.c
deleted file mode 100644
index 2db1401682df..000000000000
--- a/drivers/char/ftape/zftape/zftape_syms.c
+++ /dev/null
@@ -1,43 +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/zftape/zftape_syms.c,v $
20 * $Revision: 1.3 $
21 * $Date: 1997/10/05 19:19:14 $
22 *
23 * This file contains the symbols that the zftape frontend to
24 * the ftape floppy tape driver exports
25 */
26
27#include <linux/module.h>
28
29#include <linux/zftape.h>
30
31#include "../zftape/zftape-init.h"
32#include "../zftape/zftape-read.h"
33#include "../zftape/zftape-buffers.h"
34#include "../zftape/zftape-ctl.h"
35
36/* zftape-init.c */
37EXPORT_SYMBOL(zft_cmpr_register);
38/* zftape-read.c */
39EXPORT_SYMBOL(zft_fetch_segment_fraction);
40/* zftape-buffers.c */
41EXPORT_SYMBOL(zft_vmalloc_once);
42EXPORT_SYMBOL(zft_vmalloc_always);
43EXPORT_SYMBOL(zft_vfree);