aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ftape
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ftape')
-rw-r--r--drivers/char/ftape/Kconfig340
-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.c1352
-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.c129
-rw-r--r--drivers/char/ftape/lowlevel/ftape-buffer.h32
-rw-r--r--drivers/char/ftape/lowlevel/ftape-calibr.c276
-rw-r--r--drivers/char/ftape/lowlevel/ftape-calibr.h37
-rw-r--r--drivers/char/ftape/lowlevel/ftape-ctl.c897
-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.c161
-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.c215
-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.c105
-rw-r--r--drivers/char/ftape/lowlevel/ftape-tracing.c118
-rw-r--r--drivers/char/ftape/lowlevel/ftape-tracing.h180
-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.c88
-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.c1418
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.h59
-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.c403
-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.c376
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.h102
-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, 19417 insertions, 0 deletions
diff --git a/drivers/char/ftape/Kconfig b/drivers/char/ftape/Kconfig
new file mode 100644
index 000000000000..7d3ecb56a1bd
--- /dev/null
+++ b/drivers/char/ftape/Kconfig
@@ -0,0 +1,340 @@
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. The
29 file <file:Documentation/ftape.txt> contains a short description of
30 the most important changes in the file system interface compared to
31 previous versions of ftape. The ftape home page
32 <http://www.instmath.rwth-aachen.de/~heine/ftape/> contains
33 further information.
34
35 IMPORTANT NOTE: zftape can read archives created by previous
36 versions of ftape and provide file mark support (i.e. fast skipping
37 between tape archives) but previous version of ftape will lack file
38 mark support when reading archives produced by zftape.
39
40config ZFT_DFLT_BLK_SZ
41 int "Default block size"
42 depends on ZFTAPE
43 default "10240"
44 ---help---
45 If unsure leave this at its default value, i.e. 10240. Note that
46 you specify only the default block size here. The block size can be
47 changed at run time using the MTSETBLK tape operation with the
48 MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the
49 shell command line).
50
51 The probably most striking difference between zftape and previous
52 versions of ftape is the fact that all data must be written or read
53 in multiples of a fixed block size. The block size defaults to
54 10240 which is what GNU tar uses. The values for the block size
55 should be either 1 or multiples of 1024 up to a maximum value of
56 63488 (i.e. 62 K). If you specify `1' then zftape's builtin
57 compression will be disabled.
58
59 Reasonable values are `10240' (GNU tar's default block size),
60 `5120' (afio's default block size), `32768' (default block size some
61 backup programs assume for SCSI tape drives) or `1' (no restriction
62 on block size, but disables builtin compression).
63
64comment "The compressor will be built as a module only!"
65 depends on FTAPE && ZFTAPE
66
67config ZFT_COMPRESSOR
68 tristate
69 depends on FTAPE!=n && ZFTAPE!=n
70 default m
71
72config FT_NR_BUFFERS
73 int "Number of ftape buffers (EXPERIMENTAL)"
74 depends on FTAPE && EXPERIMENTAL
75 default "3"
76 help
77 Please leave this at `3' unless you REALLY know what you are doing.
78 It is not necessary to change this value. Values below 3 make the
79 proper use of ftape impossible, values greater than 3 are a waste of
80 memory. You can change the amount of DMA memory used by ftape at
81 runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer
82 wastes 32 KB of memory. Please note that this memory cannot be
83 swapped out.
84
85config FT_PROC_FS
86 bool "Enable procfs status report (+2kb)"
87 depends on FTAPE && PROC_FS
88 ---help---
89 Optional. Saying Y will result in creation of a directory
90 `/proc/ftape' under the /proc file system. The files can be viewed
91 with your favorite pager (i.e. use "more /proc/ftape/history" or
92 "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The
93 file will contain some status information about the inserted
94 cartridge, the kernel driver, your tape drive, the floppy disk
95 controller and the error history for the most recent use of the
96 kernel driver. Saying Y will enlarge the size of the ftape driver
97 by approximately 2 KB.
98
99 WARNING: When compiling ftape as a module (i.e. saying M to "Floppy
100 tape drive") it is dangerous to use ftape's /proc file system
101 interface. Accessing `/proc/ftape' while the module is unloaded will
102 result in a kernel Oops. This cannot be fixed from inside ftape.
103
104choice
105 prompt "Debugging output"
106 depends on FTAPE
107 default FT_NORMAL_DEBUG
108
109config FT_NORMAL_DEBUG
110 bool "Normal"
111 ---help---
112 This option controls the amount of debugging output the ftape driver
113 is ABLE to produce; it does not increase or diminish the debugging
114 level itself. If unsure, leave this at its default setting,
115 i.e. choose "Normal".
116
117 Ftape can print lots of debugging messages to the system console
118 resp. kernel log files. Reducing the amount of possible debugging
119 output reduces the size of the kernel module by some KB, so it might
120 be a good idea to use "None" for emergency boot floppies.
121
122 If you want to save memory then the following strategy is
123 recommended: leave this option at its default setting "Normal" until
124 you know that the driver works as expected, afterwards reconfigure
125 the kernel, this time specifying "Reduced" or "None" and recompile
126 and install the kernel as usual. Note that choosing "Excessive"
127 debugging output does not increase the amount of debugging output
128 printed to the console but only makes it possible to produce
129 "Excessive" debugging output.
130
131 Please read <file:Documentation/ftape.txt> for a short description
132 how to control the amount of debugging output.
133
134config FT_FULL_DEBUG
135 bool "Excessive"
136 help
137 Extremely verbose output for driver debugging purposes.
138
139config FT_NO_TRACE
140 bool "Reduced"
141 help
142 Reduced tape driver debugging output.
143
144config FT_NO_TRACE_AT_ALL
145 bool "None"
146 help
147 Suppress all debugging output from the tape drive.
148
149endchoice
150
151comment "Hardware configuration"
152 depends on FTAPE
153
154choice
155 prompt "Floppy tape controllers"
156 depends on FTAPE
157 default FT_STD_FDC
158
159config FT_STD_FDC
160 bool "Standard"
161 ---help---
162 Only change this setting if you have a special controller. If you
163 didn't plug any add-on card into your computer system but just
164 plugged the floppy tape cable into the already existing floppy drive
165 controller then you don't want to change the default setting,
166 i.e. choose "Standard".
167
168 Choose "MACH-2" if you have a Mountain Mach-2 controller.
169 Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20
170 controller.
171 Choose "Alt/82078" if you have another controller that is located at
172 an IO base address different from the standard floppy drive
173 controller's base address of `0x3f0', or uses an IRQ (interrupt)
174 channel different from `6', or a DMA channel different from
175 `2'. This is necessary for any controller card that is based on
176 Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high
177 speed" controllers.
178
179 If you choose something other than "Standard" then please make
180 sure that the settings for the IO base address and the IRQ and DMA
181 channel in the configuration menus below are correct. Use the manual
182 of your tape drive to determine the correct settings!
183
184 If you are already successfully using your tape drive with another
185 operating system then you definitely should use the same settings
186 for the IO base, the IRQ and DMA channel that have proven to work
187 with that other OS.
188
189 Note that this menu lets you specify only the default setting for
190 the hardware setup. The hardware configuration can be changed at
191 boot time (when ftape is compiled into the kernel, i.e. if you
192 have said Y to "Floppy tape drive") or module load time (i.e. if you
193 have said M to "Floppy tape drive").
194
195 Please read also the file <file:Documentation/ftape.txt> which
196 contains a short description of the parameters that can be set at
197 boot or load time. If you want to use your floppy tape drive on a
198 PCI-bus based system, please read the file
199 <file:drivers/char/ftape/README.PCI>.
200
201config FT_MACH2
202 bool "MACH-2"
203
204config FT_PROBE_FC10
205 bool "FC-10/FC-20"
206
207config FT_ALT_FDC
208 bool "Alt/82078"
209
210endchoice
211
212comment "Consult the manuals of your tape drive for the correct settings!"
213 depends on FTAPE && !FT_STD_FDC
214
215config FT_FDC_BASE
216 hex "IO base of the floppy disk controller"
217 depends on FTAPE && !FT_STD_FDC
218 default "0"
219 ---help---
220 You don't need to specify a value if the following default
221 settings for the base IO address are correct:
222 <<< MACH-2 : 0x1E0 >>>
223 <<< FC-10/FC-20: 0x180 >>>
224 <<< Secondary : 0x370 >>>
225 Secondary refers to a secondary FDC controller like the "high speed"
226 controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
227 Please make sure that the setting for the IO base address
228 specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
229 CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
230 successfully using the tape drive with another operating system then
231 you definitely should use the same settings for the IO base that has
232 proven to work with that other OS.
233
234 Note that this menu lets you specify only the default setting for
235 the IO base. The hardware configuration can be changed at boot time
236 (when ftape is compiled into the kernel, i.e. if you specified Y to
237 "Floppy tape drive") or module load time (i.e. if you have said M to
238 "Floppy tape drive").
239
240 Please read also the file <file:Documentation/ftape.txt> which
241 contains a short description of the parameters that can be set at
242 boot or load time.
243
244config FT_FDC_IRQ
245 int "IRQ channel of the floppy disk controller"
246 depends on FTAPE && !FT_STD_FDC
247 default "0"
248 ---help---
249 You don't need to specify a value if the following default
250 settings for the interrupt channel are correct:
251 <<< MACH-2 : 6 >>>
252 <<< FC-10/FC-20: 9 >>>
253 <<< Secondary : 6 >>>
254 Secondary refers to secondary a FDC controller like the "high speed"
255 controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
256 Please make sure that the setting for the IO base address
257 specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
258 CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
259 successfully using the tape drive with another operating system then
260 you definitely should use the same settings for the IO base that has
261 proven to work with that other OS.
262
263 Note that this menu lets you specify only the default setting for
264 the IRQ channel. The hardware configuration can be changed at boot
265 time (when ftape is compiled into the kernel, i.e. if you said Y to
266 "Floppy tape drive") or module load time (i.e. if you said M to
267 "Floppy tape drive").
268
269 Please read also the file <file:Documentation/ftape.txt> which
270 contains a short description of the parameters that can be set at
271 boot or load time.
272
273config FT_FDC_DMA
274 int "DMA channel of the floppy disk controller"
275 depends on FTAPE && !FT_STD_FDC
276 default "0"
277 ---help---
278 You don't need to specify a value if the following default
279 settings for the DMA channel are correct:
280 <<< MACH-2 : 2 >>>
281 <<< FC-10/FC-20: 3 >>>
282 <<< Secondary : 2 >>>
283 Secondary refers to a secondary FDC controller like the "high speed"
284 controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
285 Please make sure that the setting for the IO base address
286 specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
287 CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
288 successfully using the tape drive with another operating system then
289 you definitely should use the same settings for the IO base that has
290 proven to work with that other OS.
291
292 Note that this menu lets you specify only the default setting for
293 the DMA channel. The hardware configuration can be changed at boot
294 time (when ftape is compiled into the kernel, i.e. if you said Y to
295 "Floppy tape drive") or module load time (i.e. if you said M to
296 "Floppy tape drive").
297
298 Please read also the file <file:Documentation/ftape.txt> which
299 contains a short description of the parameters that can be set at
300 boot or load time.
301
302config FT_FDC_THR
303 int "Default FIFO threshold (EXPERIMENTAL)"
304 depends on FTAPE && EXPERIMENTAL
305 default "8"
306 help
307 Set the FIFO threshold of the FDC. If this is higher the DMA
308 controller may serve the FDC after a higher latency time. If this is
309 lower, fewer DMA transfers occur leading to less bus contention.
310 You may try to tune this if ftape annoys you with "reduced data
311 rate because of excessive overrun errors" messages. However, this
312 doesn't seem to have too much effect.
313
314 If unsure, don't touch the initial value, i.e. leave it at "8".
315
316config FT_FDC_MAX_RATE
317 int "Maximal data rate to use (EXPERIMENTAL)"
318 depends on FTAPE && EXPERIMENTAL
319 default "2000"
320 ---help---
321 With some motherboard/FDC combinations ftape will not be able to
322 run your FDC/tape drive combination at the highest available
323 speed. If this is the case you'll encounter "reduced data rate
324 because of excessive overrun errors" messages and lots of retries
325 before ftape finally decides to reduce the data rate.
326
327 In this case it might be desirable to tell ftape beforehand that
328 it need not try to run the tape drive at the highest available
329 speed. If unsure, leave this disabled, i.e. leave it at 2000
330 bits/sec.
331
332config FT_ALPHA_CLOCK
333 int "CPU clock frequency of your DEC Alpha" if ALPHA
334 depends on FTAPE
335 default "0"
336 help
337 On some DEC Alpha machines the CPU clock frequency cannot be
338 determined automatically, so you need to specify it here ONLY if
339 running a DEC Alpha, otherwise this setting has no effect.
340
diff --git a/drivers/char/ftape/Makefile b/drivers/char/ftape/Makefile
new file mode 100644
index 000000000000..0e67d2f8b7ec
--- /dev/null
+++ b/drivers/char/ftape/Makefile
@@ -0,0 +1,28 @@
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
new file mode 100644
index 000000000000..18de159d36e0
--- /dev/null
+++ b/drivers/char/ftape/README.PCI
@@ -0,0 +1,81 @@
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
new file mode 100644
index 000000000000..03799dbc05a4
--- /dev/null
+++ b/drivers/char/ftape/RELEASE-NOTES
@@ -0,0 +1,966 @@
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
new file mode 100644
index 000000000000..1fbd6c4019db
--- /dev/null
+++ b/drivers/char/ftape/compressor/Makefile
@@ -0,0 +1,31 @@
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
new file mode 100644
index 000000000000..a032a0ee2a99
--- /dev/null
+++ b/drivers/char/ftape/compressor/lzrw3.c
@@ -0,0 +1,743 @@
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
new file mode 100644
index 000000000000..533feba47526
--- /dev/null
+++ b/drivers/char/ftape/compressor/lzrw3.h
@@ -0,0 +1,253 @@
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
new file mode 100644
index 000000000000..220a227e6061
--- /dev/null
+++ b/drivers/char/ftape/compressor/zftape-compress.c
@@ -0,0 +1,1203 @@
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("zftape compressor v1.00a 970514\n");
1180 printk("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
new file mode 100644
index 000000000000..f200741e33bf
--- /dev/null
+++ b/drivers/char/ftape/compressor/zftape-compress.h
@@ -0,0 +1,83 @@
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
new file mode 100644
index 000000000000..febab07ba427
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/Makefile
@@ -0,0 +1,43 @@
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
new file mode 100644
index 000000000000..9bc1cddade76
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/fc-10.c
@@ -0,0 +1,175 @@
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
new file mode 100644
index 000000000000..da7b88bca889
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/fc-10.h
@@ -0,0 +1,39 @@
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
new file mode 100644
index 000000000000..1704a2a57048
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -0,0 +1,1352 @@
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/config.h> /* for CONFIG_FT_* */
30#include <linux/errno.h>
31#include <linux/sched.h>
32#include <linux/ioport.h>
33#include <linux/interrupt.h>
34#include <linux/kernel.h>
35#include <asm/system.h>
36#include <asm/io.h>
37#include <asm/dma.h>
38#include <asm/irq.h>
39
40#include <linux/ftape.h>
41#include <linux/qic117.h>
42#include "../lowlevel/ftape-tracing.h"
43#include "../lowlevel/fdc-io.h"
44#include "../lowlevel/fdc-isr.h"
45#include "../lowlevel/ftape-io.h"
46#include "../lowlevel/ftape-rw.h"
47#include "../lowlevel/ftape-ctl.h"
48#include "../lowlevel/ftape-calibr.h"
49#include "../lowlevel/fc-10.h"
50
51/* Global vars.
52 */
53static int ftape_motor;
54volatile int ftape_current_cylinder = -1;
55volatile fdc_mode_enum fdc_mode = fdc_idle;
56fdc_config_info fdc;
57DECLARE_WAIT_QUEUE_HEAD(ftape_wait_intr);
58
59unsigned int ft_fdc_base = CONFIG_FT_FDC_BASE;
60unsigned int ft_fdc_irq = CONFIG_FT_FDC_IRQ;
61unsigned int ft_fdc_dma = CONFIG_FT_FDC_DMA;
62unsigned int ft_fdc_threshold = CONFIG_FT_FDC_THR; /* bytes */
63unsigned int ft_fdc_rate_limit = CONFIG_FT_FDC_MAX_RATE; /* bits/sec */
64int ft_probe_fc10 = CONFIG_FT_PROBE_FC10;
65int ft_mach2 = CONFIG_FT_MACH2;
66
67/* Local vars.
68 */
69static spinlock_t fdc_io_lock;
70static unsigned int fdc_calibr_count;
71static unsigned int fdc_calibr_time;
72static int fdc_status;
73volatile __u8 fdc_head; /* FDC head from sector id */
74volatile __u8 fdc_cyl; /* FDC track from sector id */
75volatile __u8 fdc_sect; /* FDC sector from sector id */
76static int fdc_data_rate = 500; /* data rate (Kbps) */
77static int fdc_rate_code; /* data rate code (0 == 500 Kbps) */
78static int fdc_seek_rate = 2; /* step rate (msec) */
79static void (*do_ftape) (void);
80static int fdc_fifo_state; /* original fifo setting - fifo enabled */
81static int fdc_fifo_thr; /* original fifo setting - threshold */
82static int fdc_lock_state; /* original lock setting - locked */
83static int fdc_fifo_locked; /* has fifo && lock set ? */
84static __u8 fdc_precomp; /* default precomp. value (nsec) */
85static __u8 fdc_prec_code; /* fdc precomp. select code */
86
87static char ftape_id[] = "ftape"; /* used by request irq and free irq */
88
89static int fdc_set_seek_rate(int seek_rate);
90
91void fdc_catch_stray_interrupts(int count)
92{
93 unsigned long flags;
94
95 spin_lock_irqsave(&fdc_io_lock, flags);
96 if (count == 0) {
97 ft_expected_stray_interrupts = 0;
98 } else {
99 ft_expected_stray_interrupts += count;
100 }
101 spin_unlock_irqrestore(&fdc_io_lock, flags);
102}
103
104/* Wait during a timeout period for a given FDC status.
105 * If usecs == 0 then just test status, else wait at least for usecs.
106 * Returns -ETIME on timeout. Function must be calibrated first !
107 */
108static int fdc_wait(unsigned int usecs, __u8 mask, __u8 state)
109{
110 int count_1 = (fdc_calibr_count * usecs +
111 fdc_calibr_count - 1) / fdc_calibr_time;
112
113 do {
114 fdc_status = inb_p(fdc.msr);
115 if ((fdc_status & mask) == state) {
116 return 0;
117 }
118 } while (count_1-- >= 0);
119 return -ETIME;
120}
121
122int fdc_ready_wait(unsigned int usecs)
123{
124 return fdc_wait(usecs, FDC_DATA_READY | FDC_BUSY, FDC_DATA_READY);
125}
126
127/* Why can't we just use udelay()?
128 */
129static void fdc_usec_wait(unsigned int usecs)
130{
131 fdc_wait(usecs, 0, 1); /* will always timeout ! */
132}
133
134static int fdc_ready_out_wait(unsigned int usecs)
135{
136 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
137 return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);
138}
139
140void fdc_wait_calibrate(void)
141{
142 ftape_calibrate("fdc_wait",
143 fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time);
144}
145
146/* Wait for a (short) while for the FDC to become ready
147 * and transfer the next command byte.
148 * Return -ETIME on timeout on getting ready (depends on hardware!).
149 */
150static int fdc_write(const __u8 data)
151{
152 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
153 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) {
154 return -ETIME;
155 } else {
156 outb(data, fdc.fifo);
157 return 0;
158 }
159}
160
161/* Wait for a (short) while for the FDC to become ready
162 * and transfer the next result byte.
163 * Return -ETIME if timeout on getting ready (depends on hardware!).
164 */
165static int fdc_read(__u8 * data)
166{
167 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
168 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) {
169 return -ETIME;
170 } else {
171 *data = inb(fdc.fifo);
172 return 0;
173 }
174}
175
176/* Output a cmd_len long command string to the FDC.
177 * The FDC should be ready to receive a new command or
178 * an error (EBUSY or ETIME) will occur.
179 */
180int fdc_command(const __u8 * cmd_data, int cmd_len)
181{
182 int result = 0;
183 unsigned long flags;
184 int count = cmd_len;
185 int retry = 0;
186#ifdef TESTING
187 static unsigned int last_time;
188 unsigned int time;
189#endif
190 TRACE_FUN(ft_t_any);
191
192 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
193 spin_lock_irqsave(&fdc_io_lock, flags);
194 if (!in_interrupt())
195 /* Yes, I know, too much comments inside this function
196 * ...
197 *
198 * Yet another bug in the original driver. All that
199 * havoc is caused by the fact that the isr() sends
200 * itself a command to the floppy tape driver (pause,
201 * micro step pause). Now, the problem is that
202 * commands are transmitted via the fdc_seek
203 * command. But: the fdc performs seeks in the
204 * background i.e. it doesn't signal busy while
205 * sending the step pulses to the drive. Therefore the
206 * non-interrupt level driver has no chance to tell
207 * whether the isr() just has issued a seek. Therefore
208 * we HAVE TO have a look at the ft_hide_interrupt
209 * flag: it signals the non-interrupt level part of
210 * the driver that it has to wait for the fdc until it
211 * has completet seeking.
212 *
213 * THIS WAS PRESUMABLY THE REASON FOR ALL THAT
214 * "fdc_read timeout" errors, I HOPE :-)
215 */
216 if (ft_hide_interrupt) {
217 restore_flags(flags);
218 TRACE(ft_t_info,
219 "Waiting for the isr() completing fdc_seek()");
220 if (fdc_interrupt_wait(2 * FT_SECOND) < 0) {
221 TRACE(ft_t_warn,
222 "Warning: timeout waiting for isr() seek to complete");
223 }
224 if (ft_hide_interrupt || !ft_seek_completed) {
225 /* There cannot be another
226 * interrupt. The isr() only stops
227 * the tape and the next interrupt
228 * won't come until we have send our
229 * command to the drive.
230 */
231 TRACE_ABORT(-EIO, ft_t_bug,
232 "BUG? isr() is still seeking?\n"
233 KERN_INFO "hide: %d\n"
234 KERN_INFO "seek: %d",
235 ft_hide_interrupt,
236 ft_seek_completed);
237
238 }
239 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
240 spin_lock_irqsave(&fdc_io_lock, flags);
241 }
242 fdc_status = inb(fdc.msr);
243 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {
244 spin_unlock_irqrestore(&fdc_io_lock, flags);
245 TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");
246 }
247 fdc_mode = *cmd_data; /* used by isr */
248#ifdef TESTING
249 if (fdc_mode == FDC_SEEK) {
250 time = ftape_timediff(last_time, ftape_timestamp());
251 if (time < 6000) {
252 TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d",
253 time);
254 }
255 }
256#endif
257 if (!in_interrupt()) {
258 /* shouldn't be cleared if called from isr
259 */
260 ft_interrupt_seen = 0;
261 }
262 while (count) {
263 result = fdc_write(*cmd_data);
264 if (result < 0) {
265 TRACE(ft_t_fdc_dma,
266 "fdc_mode = %02x, status = %02x at index %d",
267 (int) fdc_mode, (int) fdc_status,
268 cmd_len - count);
269 if (++retry <= 3) {
270 TRACE(ft_t_warn, "fdc_write timeout, retry");
271 } else {
272 TRACE(ft_t_err, "fdc_write timeout, fatal");
273 /* recover ??? */
274 break;
275 }
276 } else {
277 --count;
278 ++cmd_data;
279 }
280 }
281#ifdef TESTING
282 if (fdc_mode == FDC_SEEK) {
283 last_time = ftape_timestamp();
284 }
285#endif
286 spin_unlock_irqrestore(&fdc_io_lock, flags);
287 TRACE_EXIT result;
288}
289
290/* Input a res_len long result string from the FDC.
291 * The FDC should be ready to send the result or an error
292 * (EBUSY or ETIME) will occur.
293 */
294int fdc_result(__u8 * res_data, int res_len)
295{
296 int result = 0;
297 unsigned long flags;
298 int count = res_len;
299 int retry = 0;
300 TRACE_FUN(ft_t_any);
301
302 spin_lock_irqsave(&fdc_io_lock, flags);
303 fdc_status = inb(fdc.msr);
304 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {
305 TRACE(ft_t_err, "fdc not ready");
306 result = -EBUSY;
307 } else while (count) {
308 if (!(fdc_status & FDC_BUSY)) {
309 spin_unlock_irqrestore(&fdc_io_lock, flags);
310 TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");
311 }
312 result = fdc_read(res_data);
313 if (result < 0) {
314 TRACE(ft_t_fdc_dma,
315 "fdc_mode = %02x, status = %02x at index %d",
316 (int) fdc_mode,
317 (int) fdc_status,
318 res_len - count);
319 if (++retry <= 3) {
320 TRACE(ft_t_warn, "fdc_read timeout, retry");
321 } else {
322 TRACE(ft_t_err, "fdc_read timeout, fatal");
323 /* recover ??? */
324 break;
325 ++retry;
326 }
327 } else {
328 --count;
329 ++res_data;
330 }
331 }
332 spin_unlock_irqrestore(&fdc_io_lock, flags);
333 fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */
334 TRACE_EXIT result;
335}
336
337/* Handle command and result phases for
338 * commands without data phase.
339 */
340static int fdc_issue_command(const __u8 * out_data, int out_count,
341 __u8 * in_data, int in_count)
342{
343 TRACE_FUN(ft_t_any);
344
345 if (out_count > 0) {
346 TRACE_CATCH(fdc_command(out_data, out_count),);
347 }
348 /* will take 24 - 30 usec for fdc_sense_drive_status and
349 * fdc_sense_interrupt_status commands.
350 * 35 fails sometimes (5/9/93 SJL)
351 * On a loaded system it incidentally takes longer than
352 * this for the fdc to get ready ! ?????? WHY ??????
353 * So until we know what's going on use a very long timeout.
354 */
355 TRACE_CATCH(fdc_ready_out_wait(500 /* usec */),);
356 if (in_count > 0) {
357 TRACE_CATCH(fdc_result(in_data, in_count),
358 TRACE(ft_t_err, "result phase aborted"));
359 }
360 TRACE_EXIT 0;
361}
362
363/* Wait for FDC interrupt with timeout (in milliseconds).
364 * Signals are blocked so the wait will not be aborted.
365 * Note: interrupts must be enabled ! (23/05/93 SJL)
366 */
367int fdc_interrupt_wait(unsigned int time)
368{
369 DECLARE_WAITQUEUE(wait,current);
370 sigset_t old_sigmask;
371 static int resetting;
372 long timeout;
373
374 TRACE_FUN(ft_t_fdc_dma);
375
376 if (waitqueue_active(&ftape_wait_intr)) {
377 TRACE_ABORT(-EIO, ft_t_err, "error: nested call");
378 }
379 /* timeout time will be up to USPT microseconds too long ! */
380 timeout = (1000 * time + FT_USPT - 1) / FT_USPT;
381
382 spin_lock_irq(&current->sighand->siglock);
383 old_sigmask = current->blocked;
384 sigfillset(&current->blocked);
385 recalc_sigpending();
386 spin_unlock_irq(&current->sighand->siglock);
387
388 set_current_state(TASK_INTERRUPTIBLE);
389 add_wait_queue(&ftape_wait_intr, &wait);
390 while (!ft_interrupt_seen && timeout) {
391 set_current_state(TASK_INTERRUPTIBLE);
392 timeout = schedule_timeout(timeout);
393 }
394
395 spin_lock_irq(&current->sighand->siglock);
396 current->blocked = old_sigmask;
397 recalc_sigpending();
398 spin_unlock_irq(&current->sighand->siglock);
399
400 remove_wait_queue(&ftape_wait_intr, &wait);
401 /* the following IS necessary. True: as well
402 * wake_up_interruptible() as the schedule() set TASK_RUNNING
403 * when they wakeup a task, BUT: it may very well be that
404 * ft_interrupt_seen is already set to 1 when we enter here
405 * in which case schedule() gets never called, and
406 * TASK_RUNNING never set. This has the funny effect that we
407 * execute all the code until we leave kernel space, but then
408 * the task is stopped (a task CANNOT be preempted while in
409 * kernel mode. Sending a pair of SIGSTOP/SIGCONT to the
410 * tasks wakes it up again. Funny! :-)
411 */
412 current->state = TASK_RUNNING;
413 if (ft_interrupt_seen) { /* woken up by interrupt */
414 ft_interrupt_seen = 0;
415 TRACE_EXIT 0;
416 }
417 /* Original comment:
418 * In first instance, next statement seems unnecessary since
419 * it will be cleared in fdc_command. However, a small part of
420 * the software seems to rely on this being cleared here
421 * (ftape_close might fail) so stick to it until things get fixed !
422 */
423 /* My deeply sought of knowledge:
424 * Behold NO! It is obvious. fdc_reset() doesn't call fdc_command()
425 * but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to
426 * be reset here.
427 */
428 ft_interrupt_seen = 0; /* clear for next call */
429 if (!resetting) {
430 resetting = 1; /* break infinite recursion if reset fails */
431 TRACE(ft_t_any, "cleanup reset");
432 fdc_reset();
433 resetting = 0;
434 }
435 TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;
436}
437
438/* Start/stop drive motor. Enable DMA mode.
439 */
440void fdc_motor(int motor)
441{
442 int unit = ft_drive_sel;
443 int data = unit | FDC_RESET_NOT | FDC_DMA_MODE;
444 TRACE_FUN(ft_t_any);
445
446 ftape_motor = motor;
447 if (ftape_motor) {
448 data |= FDC_MOTOR_0 << unit;
449 TRACE(ft_t_noise, "turning motor %d on", unit);
450 } else {
451 TRACE(ft_t_noise, "turning motor %d off", unit);
452 }
453 if (ft_mach2) {
454 outb_p(data, fdc.dor2);
455 } else {
456 outb_p(data, fdc.dor);
457 }
458 ftape_sleep(10 * FT_MILLISECOND);
459 TRACE_EXIT;
460}
461
462static void fdc_update_dsr(void)
463{
464 TRACE_FUN(ft_t_any);
465
466 TRACE(ft_t_flow, "rate = %d Kbps, precomp = %d ns",
467 fdc_data_rate, fdc_precomp);
468 if (fdc.type >= i82077) {
469 outb_p((fdc_rate_code & 0x03) | fdc_prec_code, fdc.dsr);
470 } else {
471 outb_p(fdc_rate_code & 0x03, fdc.ccr);
472 }
473 TRACE_EXIT;
474}
475
476void fdc_set_write_precomp(int precomp)
477{
478 TRACE_FUN(ft_t_any);
479
480 TRACE(ft_t_noise, "New precomp: %d nsec", precomp);
481 fdc_precomp = precomp;
482 /* write precompensation can be set in multiples of 41.67 nsec.
483 * round the parameter to the nearest multiple and convert it
484 * into a fdc setting. Note that 0 means default to the fdc,
485 * 7 is used instead of that.
486 */
487 fdc_prec_code = ((fdc_precomp + 21) / 42) << 2;
488 if (fdc_prec_code == 0 || fdc_prec_code > (6 << 2)) {
489 fdc_prec_code = 7 << 2;
490 }
491 fdc_update_dsr();
492 TRACE_EXIT;
493}
494
495/* Reprogram the 82078 registers to use Data Rate Table 1 on all drives.
496 */
497static void fdc_set_drive_specs(void)
498{
499 __u8 cmd[] = { FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};
500 int result;
501 TRACE_FUN(ft_t_any);
502
503 TRACE(ft_t_flow, "Setting of drive specs called");
504 if (fdc.type >= i82078_1) {
505 cmd[1] = (0 << 5) | (2 << 2);
506 cmd[2] = (1 << 5) | (2 << 2);
507 cmd[3] = (2 << 5) | (2 << 2);
508 cmd[4] = (3 << 5) | (2 << 2);
509 result = fdc_command(cmd, NR_ITEMS(cmd));
510 if (result < 0) {
511 TRACE(ft_t_err, "Setting of drive specs failed");
512 }
513 }
514 TRACE_EXIT;
515}
516
517/* Select clock for fdc, must correspond with tape drive setting !
518 * This also influences the fdc timing so we must adjust some values.
519 */
520int fdc_set_data_rate(int rate)
521{
522 int bad_rate = 0;
523 TRACE_FUN(ft_t_any);
524
525 /* Select clock for fdc, must correspond with tape drive setting !
526 * This also influences the fdc timing so we must adjust some values.
527 */
528 TRACE(ft_t_fdc_dma, "new rate = %d", rate);
529 switch (rate) {
530 case 250:
531 fdc_rate_code = fdc_data_rate_250;
532 break;
533 case 500:
534 fdc_rate_code = fdc_data_rate_500;
535 break;
536 case 1000:
537 if (fdc.type < i82077) {
538 bad_rate = 1;
539 } else {
540 fdc_rate_code = fdc_data_rate_1000;
541 }
542 break;
543 case 2000:
544 if (fdc.type < i82078_1) {
545 bad_rate = 1;
546 } else {
547 fdc_rate_code = fdc_data_rate_2000;
548 }
549 break;
550 default:
551 bad_rate = 1;
552 }
553 if (bad_rate) {
554 TRACE_ABORT(-EIO,
555 ft_t_fdc_dma, "%d is not a valid data rate", rate);
556 }
557 fdc_data_rate = rate;
558 fdc_update_dsr();
559 fdc_set_seek_rate(fdc_seek_rate); /* clock changed! */
560 ftape_udelay(1000);
561 TRACE_EXIT 0;
562}
563
564/* keep the unit select if keep_select is != 0,
565 */
566static void fdc_dor_reset(int keep_select)
567{
568 __u8 fdc_ctl = ft_drive_sel;
569
570 if (keep_select != 0) {
571 fdc_ctl |= FDC_DMA_MODE;
572 if (ftape_motor) {
573 fdc_ctl |= FDC_MOTOR_0 << ft_drive_sel;
574 }
575 }
576 ftape_udelay(10); /* ??? but seems to be necessary */
577 if (ft_mach2) {
578 outb_p(fdc_ctl & 0x0f, fdc.dor);
579 outb_p(fdc_ctl, fdc.dor2);
580 } else {
581 outb_p(fdc_ctl, fdc.dor);
582 }
583 fdc_usec_wait(10); /* delay >= 14 fdc clocks */
584 if (keep_select == 0) {
585 fdc_ctl = 0;
586 }
587 fdc_ctl |= FDC_RESET_NOT;
588 if (ft_mach2) {
589 outb_p(fdc_ctl & 0x0f, fdc.dor);
590 outb_p(fdc_ctl, fdc.dor2);
591 } else {
592 outb_p(fdc_ctl, fdc.dor);
593 }
594}
595
596/* Reset the floppy disk controller. Leave the ftape_unit selected.
597 */
598void fdc_reset(void)
599{
600 int st0;
601 int i;
602 int dummy;
603 unsigned long flags;
604 TRACE_FUN(ft_t_any);
605
606 spin_lock_irqsave(&fdc_io_lock, flags);
607
608 fdc_dor_reset(1); /* keep unit selected */
609
610 fdc_mode = fdc_idle;
611
612 /* maybe the cli()/sti() pair is not necessary, BUT:
613 * the following line MUST be here. Otherwise fdc_interrupt_wait()
614 * won't wait. Note that fdc_reset() is called from
615 * ftape_dumb_stop() when the fdc is busy transferring data. In this
616 * case fdc_isr() MOST PROBABLY sets ft_interrupt_seen, and tries
617 * to get the result bytes from the fdc etc. CLASH.
618 */
619 ft_interrupt_seen = 0;
620
621 /* Program data rate
622 */
623 fdc_update_dsr(); /* restore data rate and precomp */
624
625 spin_unlock_irqrestore(&fdc_io_lock, flags);
626
627 /*
628 * Wait for first polling cycle to complete
629 */
630 if (fdc_interrupt_wait(1 * FT_SECOND) < 0) {
631 TRACE(ft_t_err, "no drive polling interrupt!");
632 } else { /* clear all disk-changed statuses */
633 for (i = 0; i < 4; ++i) {
634 if(fdc_sense_interrupt_status(&st0, &dummy) != 0) {
635 TRACE(ft_t_err, "sense failed for %d", i);
636 }
637 if (i == ft_drive_sel) {
638 ftape_current_cylinder = dummy;
639 }
640 }
641 TRACE(ft_t_noise, "drive polling completed");
642 }
643 /*
644 * SPECIFY COMMAND
645 */
646 fdc_set_seek_rate(fdc_seek_rate);
647 /*
648 * DRIVE SPECIFICATION COMMAND (if fdc type known)
649 */
650 if (fdc.type >= i82078_1) {
651 fdc_set_drive_specs();
652 }
653 TRACE_EXIT;
654}
655
656#if !defined(CLK_48MHZ)
657# define CLK_48MHZ 1
658#endif
659
660/* When we're done, put the fdc into reset mode so that the regular
661 * floppy disk driver will figure out that something is wrong and
662 * initialize the controller the way it wants.
663 */
664void fdc_disable(void)
665{
666 __u8 cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00};
667 __u8 cmd2[] = {FDC_LOCK};
668 __u8 cmd3[] = {FDC_UNLOCK};
669 __u8 stat[1];
670 TRACE_FUN(ft_t_flow);
671
672 if (!fdc_fifo_locked) {
673 fdc_reset();
674 TRACE_EXIT;
675 }
676 if (fdc_issue_command(cmd3, 1, stat, 1) < 0 || stat[0] != 0x00) {
677 fdc_dor_reset(0);
678 TRACE_ABORT(/**/, ft_t_bug,
679 "couldn't unlock fifo, configuration remains changed");
680 }
681 fdc_fifo_locked = 0;
682 if (CLK_48MHZ && fdc.type >= i82078) {
683 cmd1[0] |= FDC_CLK48_BIT;
684 }
685 cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1);
686 if (fdc_command(cmd1, NR_ITEMS(cmd1)) < 0) {
687 fdc_dor_reset(0);
688 TRACE_ABORT(/**/, ft_t_bug,
689 "couldn't reconfigure fifo to old state");
690 }
691 if (fdc_lock_state &&
692 fdc_issue_command(cmd2, 1, stat, 1) < 0) {
693 fdc_dor_reset(0);
694 TRACE_ABORT(/**/, ft_t_bug, "couldn't lock old state again");
695 }
696 TRACE(ft_t_noise, "fifo restored: %sabled, thr. %d, %slocked",
697 fdc_fifo_state ? "en" : "dis",
698 fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");
699 fdc_dor_reset(0);
700 TRACE_EXIT;
701}
702
703/* Specify FDC seek-rate (milliseconds)
704 */
705static int fdc_set_seek_rate(int seek_rate)
706{
707 /* set step rate, dma mode, and minimal head load and unload times
708 */
709 __u8 in[3] = { FDC_SPECIFY, 1, (1 << 1)};
710
711 fdc_seek_rate = seek_rate;
712 in[1] |= (16 - (fdc_data_rate * fdc_seek_rate) / 500) << 4;
713
714 return fdc_command(in, 3);
715}
716
717/* Sense drive status: get unit's drive status (ST3)
718 */
719int fdc_sense_drive_status(int *st3)
720{
721 __u8 out[2];
722 __u8 in[1];
723 TRACE_FUN(ft_t_any);
724
725 out[0] = FDC_SENSED;
726 out[1] = ft_drive_sel;
727 TRACE_CATCH(fdc_issue_command(out, 2, in, 1),);
728 *st3 = in[0];
729 TRACE_EXIT 0;
730}
731
732/* Sense Interrupt Status command:
733 * should be issued at the end of each seek.
734 * get ST0 and current cylinder.
735 */
736int fdc_sense_interrupt_status(int *st0, int *current_cylinder)
737{
738 __u8 out[1];
739 __u8 in[2];
740 TRACE_FUN(ft_t_any);
741
742 out[0] = FDC_SENSEI;
743 TRACE_CATCH(fdc_issue_command(out, 1, in, 2),);
744 *st0 = in[0];
745 *current_cylinder = in[1];
746 TRACE_EXIT 0;
747}
748
749/* step to track
750 */
751int fdc_seek(int track)
752{
753 __u8 out[3];
754 int st0, pcn;
755#ifdef TESTING
756 unsigned int time;
757#endif
758 TRACE_FUN(ft_t_any);
759
760 out[0] = FDC_SEEK;
761 out[1] = ft_drive_sel;
762 out[2] = track;
763#ifdef TESTING
764 time = ftape_timestamp();
765#endif
766 /* We really need this command to work !
767 */
768 ft_seek_completed = 0;
769 TRACE_CATCH(fdc_command(out, 3),
770 fdc_reset();
771 TRACE(ft_t_noise, "destination was: %d, resetting FDC...",
772 track));
773 /* Handle interrupts until ft_seek_completed or timeout.
774 */
775 for (;;) {
776 TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),);
777 if (ft_seek_completed) {
778 TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),);
779 if ((st0 & ST0_SEEK_END) == 0) {
780 TRACE_ABORT(-EIO, ft_t_err,
781 "no seek-end after seek completion !??");
782 }
783 break;
784 }
785 }
786#ifdef TESTING
787 time = ftape_timediff(time, ftape_timestamp()) / abs(track - ftape_current_cylinder);
788 if ((time < 900 || time > 3100) && abs(track - ftape_current_cylinder) > 5) {
789 TRACE(ft_t_warn, "Wrong FDC STEP interval: %d usecs (%d)",
790 time, track - ftape_current_cylinder);
791 }
792#endif
793 /* Verify whether we issued the right tape command.
794 */
795 /* Verify that we seek to the proper track. */
796 if (pcn != track) {
797 TRACE_ABORT(-EIO, ft_t_err, "bad seek..");
798 }
799 ftape_current_cylinder = track;
800 TRACE_EXIT 0;
801}
802
803static int perpend_mode; /* set if fdc is in perpendicular mode */
804
805static int perpend_off(void)
806{
807 __u8 perpend[] = {FDC_PERPEND, 0x00};
808 TRACE_FUN(ft_t_any);
809
810 if (perpend_mode) {
811 /* Turn off perpendicular mode */
812 perpend[1] = 0x80;
813 TRACE_CATCH(fdc_command(perpend, 2),
814 TRACE(ft_t_err,"Perpendicular mode exit failed!"));
815 perpend_mode = 0;
816 }
817 TRACE_EXIT 0;
818}
819
820static int handle_perpend(int segment_id)
821{
822 __u8 perpend[] = {FDC_PERPEND, 0x00};
823 TRACE_FUN(ft_t_any);
824
825 /* When writing QIC-3020 tapes, turn on perpendicular mode
826 * if tape is moving in forward direction (even tracks).
827 */
828 if (ft_qic_std == QIC_TAPE_QIC3020 &&
829 ((segment_id / ft_segments_per_track) & 1) == 0) {
830/* FIXME: some i82077 seem to support perpendicular mode as
831 * well.
832 */
833#if 0
834 if (fdc.type < i82077AA) {}
835#else
836 if (fdc.type < i82077 && ft_data_rate < 1000) {
837#endif
838 /* fdc does not support perpendicular mode: complain
839 */
840 TRACE_ABORT(-EIO, ft_t_err,
841 "Your FDC does not support QIC-3020.");
842 }
843 perpend[1] = 0x03 /* 0x83 + (0x4 << ft_drive_sel) */ ;
844 TRACE_CATCH(fdc_command(perpend, 2),
845 TRACE(ft_t_err,"Perpendicular mode entry failed!"));
846 TRACE(ft_t_flow, "Perpendicular mode set");
847 perpend_mode = 1;
848 TRACE_EXIT 0;
849 }
850 TRACE_EXIT perpend_off();
851}
852
853static inline void fdc_setup_dma(char mode,
854 volatile void *addr, unsigned int count)
855{
856 /* Program the DMA controller.
857 */
858 disable_dma(fdc.dma);
859 clear_dma_ff(fdc.dma);
860 set_dma_mode(fdc.dma, mode);
861 set_dma_addr(fdc.dma, virt_to_bus((void*)addr));
862 set_dma_count(fdc.dma, count);
863 enable_dma(fdc.dma);
864}
865
866/* Setup fdc and dma for formatting the next segment
867 */
868int fdc_setup_formatting(buffer_struct * buff)
869{
870 unsigned long flags;
871 __u8 out[6] = {
872 FDC_FORMAT, 0x00, 3, 4 * FT_SECTORS_PER_SEGMENT, 0x00, 0x6b
873 };
874 TRACE_FUN(ft_t_any);
875
876 TRACE_CATCH(handle_perpend(buff->segment_id),);
877 /* Program the DMA controller.
878 */
879 TRACE(ft_t_fdc_dma,
880 "phys. addr. = %lx", virt_to_bus((void*) buff->ptr));
881 spin_lock_irqsave(&fdc_io_lock, flags);
882 fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4);
883 /* Issue FDC command to start reading/writing.
884 */
885 out[1] = ft_drive_sel;
886 out[4] = buff->gap3;
887 TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)),
888 restore_flags(flags); fdc_mode = fdc_idle);
889 spin_unlock_irqrestore(&fdc_io_lock, flags);
890 TRACE_EXIT 0;
891}
892
893
894/* Setup Floppy Disk Controller and DMA to read or write the next cluster
895 * of good sectors from or to the current segment.
896 */
897int fdc_setup_read_write(buffer_struct * buff, __u8 operation)
898{
899 unsigned long flags;
900 __u8 out[9];
901 int dma_mode;
902 TRACE_FUN(ft_t_any);
903
904 switch(operation) {
905 case FDC_VERIFY:
906 if (fdc.type < i82077) {
907 operation = FDC_READ;
908 }
909 case FDC_READ:
910 case FDC_READ_DELETED:
911 dma_mode = DMA_MODE_READ;
912 TRACE(ft_t_fdc_dma, "xfer %d sectors to 0x%p",
913 buff->sector_count, buff->ptr);
914 TRACE_CATCH(perpend_off(),);
915 break;
916 case FDC_WRITE_DELETED:
917 TRACE(ft_t_noise, "deleting segment %d", buff->segment_id);
918 case FDC_WRITE:
919 dma_mode = DMA_MODE_WRITE;
920 /* When writing QIC-3020 tapes, turn on perpendicular mode
921 * if tape is moving in forward direction (even tracks).
922 */
923 TRACE_CATCH(handle_perpend(buff->segment_id),);
924 TRACE(ft_t_fdc_dma, "xfer %d sectors from 0x%p",
925 buff->sector_count, buff->ptr);
926 break;
927 default:
928 TRACE_ABORT(-EIO,
929 ft_t_bug, "bug: invalid operation parameter");
930 }
931 TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr));
932 spin_lock_irqsave(&fdc_io_lock, flags);
933 if (operation != FDC_VERIFY) {
934 fdc_setup_dma(dma_mode, buff->ptr,
935 FT_SECTOR_SIZE * buff->sector_count);
936 }
937 /* Issue FDC command to start reading/writing.
938 */
939 out[0] = operation;
940 out[1] = ft_drive_sel;
941 out[2] = buff->cyl;
942 out[3] = buff->head;
943 out[4] = buff->sect + buff->sector_offset;
944 out[5] = 3; /* Sector size of 1K. */
945 out[6] = out[4] + buff->sector_count - 1; /* last sector */
946 out[7] = 109; /* Gap length. */
947 out[8] = 0xff; /* No limit to transfer size. */
948 TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",
949 out[2], out[3], out[4], out[6] - out[4] + 1);
950 spin_unlock_irqrestore(&fdc_io_lock, flags);
951 TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle);
952 TRACE_EXIT 0;
953}
954
955int fdc_fifo_threshold(__u8 threshold,
956 int *fifo_state, int *lock_state, int *fifo_thr)
957{
958 const __u8 cmd0[] = {FDC_DUMPREGS};
959 __u8 cmd1[] = {FDC_CONFIGURE, 0, (0x0f & (threshold - 1)), 0};
960 const __u8 cmd2[] = {FDC_LOCK};
961 const __u8 cmd3[] = {FDC_UNLOCK};
962 __u8 reg[10];
963 __u8 stat;
964 int i;
965 int result;
966 TRACE_FUN(ft_t_any);
967
968 if (CLK_48MHZ && fdc.type >= i82078) {
969 cmd1[0] |= FDC_CLK48_BIT;
970 }
971 /* Dump fdc internal registers for examination
972 */
973 TRACE_CATCH(fdc_command(cmd0, NR_ITEMS(cmd0)),
974 TRACE(ft_t_warn, "dumpreg cmd failed, fifo unchanged"));
975 /* Now read fdc internal registers from fifo
976 */
977 for (i = 0; i < (int)NR_ITEMS(reg); ++i) {
978 fdc_read(&reg[i]);
979 TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]);
980 }
981 if (fifo_state && lock_state && fifo_thr) {
982 *fifo_state = (reg[8] & 0x20) == 0;
983 *lock_state = reg[7] & 0x80;
984 *fifo_thr = 1 + (reg[8] & 0x0f);
985 }
986 TRACE(ft_t_noise,
987 "original fifo state: %sabled, threshold %d, %slocked",
988 ((reg[8] & 0x20) == 0) ? "en" : "dis",
989 1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not ");
990 /* If fdc is already locked, unlock it first ! */
991 if (reg[7] & 0x80) {
992 fdc_ready_wait(100);
993 TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1),
994 TRACE(ft_t_bug, "FDC unlock command failed, "
995 "configuration unchanged"));
996 }
997 fdc_fifo_locked = 0;
998 /* Enable fifo and set threshold at xx bytes to allow a
999 * reasonably large latency and reduce number of dma bursts.
1000 */
1001 fdc_ready_wait(100);
1002 if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) {
1003 TRACE(ft_t_bug, "configure cmd failed, fifo unchanged");
1004 }
1005 /* Now lock configuration so reset will not change it
1006 */
1007 if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 ||
1008 stat != 0x10) {
1009 TRACE_ABORT(-EIO, ft_t_bug,
1010 "FDC lock command failed, stat = 0x%02x", stat);
1011 }
1012 fdc_fifo_locked = 1;
1013 TRACE_EXIT result;
1014}
1015
1016static int fdc_fifo_enable(void)
1017{
1018 TRACE_FUN(ft_t_any);
1019
1020 if (fdc_fifo_locked) {
1021 TRACE_ABORT(0, ft_t_warn, "Fifo not enabled because locked");
1022 }
1023 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1024 &fdc_fifo_state,
1025 &fdc_lock_state,
1026 &fdc_fifo_thr),);
1027 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1028 NULL, NULL, NULL),);
1029 TRACE_EXIT 0;
1030}
1031
1032/* Determine fd controller type
1033 */
1034static __u8 fdc_save_state[2];
1035
1036static int fdc_probe(void)
1037{
1038 __u8 cmd[1];
1039 __u8 stat[16]; /* must be able to hold dumpregs & save results */
1040 int i;
1041 TRACE_FUN(ft_t_any);
1042
1043 /* Try to find out what kind of fd controller we have to deal with
1044 * Scheme borrowed from floppy driver:
1045 * first try if FDC_DUMPREGS command works
1046 * (this indicates that we have a 82072 or better)
1047 * then try the FDC_VERSION command (82072 doesn't support this)
1048 * then try the FDC_UNLOCK command (some older 82077's don't support this)
1049 * then try the FDC_PARTID command (82078's support this)
1050 */
1051 cmd[0] = FDC_DUMPREGS;
1052 if (fdc_issue_command(cmd, 1, stat, 1) != 0) {
1053 TRACE_ABORT(no_fdc, ft_t_bug, "No FDC found");
1054 }
1055 if (stat[0] == 0x80) {
1056 /* invalid command: must be pre 82072 */
1057 TRACE_ABORT(i8272,
1058 ft_t_warn, "Type 8272A/765A compatible FDC found");
1059 }
1060 fdc_result(&stat[1], 9);
1061 fdc_save_state[0] = stat[7];
1062 fdc_save_state[1] = stat[8];
1063 cmd[0] = FDC_VERSION;
1064 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1065 TRACE_ABORT(i8272, ft_t_warn, "Type 82072 FDC found");
1066 }
1067 if (*stat != 0x90) {
1068 TRACE_ABORT(i8272, ft_t_warn, "Unknown FDC found");
1069 }
1070 cmd[0] = FDC_UNLOCK;
1071 if(fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] != 0x00) {
1072 TRACE_ABORT(i8272, ft_t_warn,
1073 "Type pre-1991 82077 FDC found, "
1074 "treating it like a 82072");
1075 }
1076 if (fdc_save_state[0] & 0x80) { /* was locked */
1077 cmd[0] = FDC_LOCK; /* restore lock */
1078 (void)fdc_issue_command(cmd, 1, stat, 1);
1079 TRACE(ft_t_warn, "FDC is already locked");
1080 }
1081 /* Test for a i82078 FDC */
1082 cmd[0] = FDC_PARTID;
1083 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1084 /* invalid command: not a i82078xx type FDC */
1085 for (i = 0; i < 4; ++i) {
1086 outb_p(i, fdc.tdr);
1087 if ((inb_p(fdc.tdr) & 0x03) != i) {
1088 TRACE_ABORT(i82077,
1089 ft_t_warn, "Type 82077 FDC found");
1090 }
1091 }
1092 TRACE_ABORT(i82077AA, ft_t_warn, "Type 82077AA FDC found");
1093 }
1094 /* FDC_PARTID cmd succeeded */
1095 switch (stat[0] >> 5) {
1096 case 0x0:
1097 /* i82078SL or i82078-1. The SL part cannot run at
1098 * 2Mbps (the SL and -1 dies are identical; they are
1099 * speed graded after production, according to Intel).
1100 * Some SL's can be detected by doing a SAVE cmd and
1101 * look at bit 7 of the first byte (the SEL3V# bit).
1102 * If it is 0, the part runs off 3Volts, and hence it
1103 * is a SL.
1104 */
1105 cmd[0] = FDC_SAVE;
1106 if(fdc_issue_command(cmd, 1, stat, 16) < 0) {
1107 TRACE(ft_t_err, "FDC_SAVE failed. Dunno why");
1108 /* guess we better claim the fdc to be a i82078 */
1109 TRACE_ABORT(i82078,
1110 ft_t_warn,
1111 "Type i82078 FDC (i suppose) found");
1112 }
1113 if ((stat[0] & FDC_SEL3V_BIT)) {
1114 /* fdc running off 5Volts; Pray that it's a i82078-1
1115 */
1116 TRACE_ABORT(i82078_1, ft_t_warn,
1117 "Type i82078-1 or 5Volt i82078SL FDC found");
1118 }
1119 TRACE_ABORT(i82078, ft_t_warn,
1120 "Type 3Volt i82078SL FDC (1Mbps) found");
1121 case 0x1:
1122 case 0x2: /* S82078B */
1123 /* The '78B isn't '78 compatible. Detect it as a '77AA */
1124 TRACE_ABORT(i82077AA, ft_t_warn, "Type i82077AA FDC found");
1125 case 0x3: /* NSC PC8744 core; used in several super-IO chips */
1126 TRACE_ABORT(i82077AA,
1127 ft_t_warn, "Type 82077AA compatible FDC found");
1128 default:
1129 TRACE(ft_t_warn, "A previously undetected FDC found");
1130 TRACE_ABORT(i82077AA, ft_t_warn,
1131 "Treating it as a 82077AA. Please report partid= %d",
1132 stat[0]);
1133 } /* switch(stat[ 0] >> 5) */
1134 TRACE_EXIT no_fdc;
1135}
1136
1137static int fdc_request_regions(void)
1138{
1139 TRACE_FUN(ft_t_flow);
1140
1141 if (ft_mach2 || ft_probe_fc10) {
1142 if (!request_region(fdc.sra, 8, "fdc (ft)")) {
1143#ifndef BROKEN_FLOPPY_DRIVER
1144 TRACE_EXIT -EBUSY;
1145#else
1146 TRACE(ft_t_warn,
1147"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1148#endif
1149 }
1150 } else {
1151 if (!request_region(fdc.sra, 6, "fdc (ft)")) {
1152#ifndef BROKEN_FLOPPY_DRIVER
1153 TRACE_EXIT -EBUSY;
1154#else
1155 TRACE(ft_t_warn,
1156"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1157#endif
1158 }
1159 if (!request_region(fdc.sra + 7, 1, "fdc (ft)")) {
1160#ifndef BROKEN_FLOPPY_DRIVER
1161 release_region(fdc.sra, 6);
1162 TRACE_EXIT -EBUSY;
1163#else
1164 TRACE(ft_t_warn,
1165"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra + 7);
1166#endif
1167 }
1168 }
1169 TRACE_EXIT 0;
1170}
1171
1172void fdc_release_regions(void)
1173{
1174 TRACE_FUN(ft_t_flow);
1175
1176 if (fdc.sra != 0) {
1177 if (fdc.dor2 != 0) {
1178 release_region(fdc.sra, 8);
1179 } else {
1180 release_region(fdc.sra, 6);
1181 release_region(fdc.dir, 1);
1182 }
1183 }
1184 TRACE_EXIT;
1185}
1186
1187static int fdc_config_regs(unsigned int fdc_base,
1188 unsigned int fdc_irq,
1189 unsigned int fdc_dma)
1190{
1191 TRACE_FUN(ft_t_flow);
1192
1193 fdc.irq = fdc_irq;
1194 fdc.dma = fdc_dma;
1195 fdc.sra = fdc_base;
1196 fdc.srb = fdc_base + 1;
1197 fdc.dor = fdc_base + 2;
1198 fdc.tdr = fdc_base + 3;
1199 fdc.msr = fdc.dsr = fdc_base + 4;
1200 fdc.fifo = fdc_base + 5;
1201 fdc.dir = fdc.ccr = fdc_base + 7;
1202 fdc.dor2 = (ft_mach2 || ft_probe_fc10) ? fdc_base + 6 : 0;
1203 TRACE_CATCH(fdc_request_regions(), fdc.sra = 0);
1204 TRACE_EXIT 0;
1205}
1206
1207static int fdc_config(void)
1208{
1209 static int already_done;
1210 TRACE_FUN(ft_t_any);
1211
1212 if (already_done) {
1213 TRACE_CATCH(fdc_request_regions(),);
1214 *(fdc.hook) = fdc_isr; /* hook our handler in */
1215 TRACE_EXIT 0;
1216 }
1217 if (ft_probe_fc10) {
1218 int fc_type;
1219
1220 TRACE_CATCH(fdc_config_regs(ft_fdc_base,
1221 ft_fdc_irq, ft_fdc_dma),);
1222 fc_type = fc10_enable();
1223 if (fc_type != 0) {
1224 TRACE(ft_t_warn, "FC-%c0 controller found", '0' + fc_type);
1225 fdc.type = fc10;
1226 fdc.hook = &do_ftape;
1227 *(fdc.hook) = fdc_isr; /* hook our handler in */
1228 already_done = 1;
1229 TRACE_EXIT 0;
1230 } else {
1231 TRACE(ft_t_warn, "FC-10/20 controller not found");
1232 fdc_release_regions();
1233 fdc.type = no_fdc;
1234 ft_probe_fc10 = 0;
1235 ft_fdc_base = 0x3f0;
1236 ft_fdc_irq = 6;
1237 ft_fdc_dma = 2;
1238 }
1239 }
1240 TRACE(ft_t_warn, "fdc base: 0x%x, irq: %d, dma: %d",
1241 ft_fdc_base, ft_fdc_irq, ft_fdc_dma);
1242 TRACE_CATCH(fdc_config_regs(ft_fdc_base, ft_fdc_irq, ft_fdc_dma),);
1243 fdc.hook = &do_ftape;
1244 *(fdc.hook) = fdc_isr; /* hook our handler in */
1245 already_done = 1;
1246 TRACE_EXIT 0;
1247}
1248
1249static irqreturn_t ftape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1250{
1251 void (*handler) (void) = *fdc.hook;
1252 int handled = 0;
1253 TRACE_FUN(ft_t_any);
1254
1255 *fdc.hook = NULL;
1256 if (handler) {
1257 handled = 1;
1258 handler();
1259 } else {
1260 TRACE(ft_t_bug, "Unexpected ftape interrupt");
1261 }
1262 TRACE_EXIT IRQ_RETVAL(handled);
1263}
1264
1265static int fdc_grab_irq_and_dma(void)
1266{
1267 TRACE_FUN(ft_t_any);
1268
1269 if (fdc.hook == &do_ftape) {
1270 /* Get fast interrupt handler.
1271 */
1272 if (request_irq(fdc.irq, ftape_interrupt,
1273 SA_INTERRUPT, "ft", ftape_id)) {
1274 TRACE_ABORT(-EIO, ft_t_bug,
1275 "Unable to grab IRQ%d for ftape driver",
1276 fdc.irq);
1277 }
1278 if (request_dma(fdc.dma, ftape_id)) {
1279 free_irq(fdc.irq, ftape_id);
1280 TRACE_ABORT(-EIO, ft_t_bug,
1281 "Unable to grab DMA%d for ftape driver",
1282 fdc.dma);
1283 }
1284 }
1285 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1286 /* Using same dma channel or irq as standard fdc, need
1287 * to disable the dma-gate on the std fdc. This
1288 * couldn't be done in the floppy driver as some
1289 * laptops are using the dma-gate to enter a low power
1290 * or even suspended state :-(
1291 */
1292 outb_p(FDC_RESET_NOT, 0x3f2);
1293 TRACE(ft_t_noise, "DMA-gate on standard fdc disabled");
1294 }
1295 TRACE_EXIT 0;
1296}
1297
1298int fdc_release_irq_and_dma(void)
1299{
1300 TRACE_FUN(ft_t_any);
1301
1302 if (fdc.hook == &do_ftape) {
1303 disable_dma(fdc.dma); /* just in case... */
1304 free_dma(fdc.dma);
1305 free_irq(fdc.irq, ftape_id);
1306 }
1307 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1308 /* Using same dma channel as standard fdc, need to
1309 * disable the dma-gate on the std fdc. This couldn't
1310 * be done in the floppy driver as some laptops are
1311 * using the dma-gate to enter a low power or even
1312 * suspended state :-(
1313 */
1314 outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);
1315 TRACE(ft_t_noise, "DMA-gate on standard fdc enabled again");
1316 }
1317 TRACE_EXIT 0;
1318}
1319
1320int fdc_init(void)
1321{
1322 TRACE_FUN(ft_t_any);
1323
1324 /* find a FDC to use */
1325 TRACE_CATCH(fdc_config(),);
1326 TRACE_CATCH(fdc_grab_irq_and_dma(), fdc_release_regions());
1327 ftape_motor = 0;
1328 fdc_catch_stray_interrupts(0); /* clear number of awainted
1329 * stray interrupte
1330 */
1331 fdc_catch_stray_interrupts(1); /* one always comes (?) */
1332 TRACE(ft_t_flow, "resetting fdc");
1333 fdc_set_seek_rate(2); /* use nominal QIC step rate */
1334 fdc_reset(); /* init fdc & clear track counters */
1335 if (fdc.type == no_fdc) { /* no FC-10 or FC-20 found */
1336 fdc.type = fdc_probe();
1337 fdc_reset(); /* update with new knowledge */
1338 }
1339 if (fdc.type == no_fdc) {
1340 fdc_release_irq_and_dma();
1341 fdc_release_regions();
1342 TRACE_EXIT -ENXIO;
1343 }
1344 if (fdc.type >= i82077) {
1345 if (fdc_fifo_enable() < 0) {
1346 TRACE(ft_t_warn, "couldn't enable fdc fifo !");
1347 } else {
1348 TRACE(ft_t_flow, "fdc fifo enabled and locked");
1349 }
1350 }
1351 TRACE_EXIT 0;
1352}
diff --git a/drivers/char/ftape/lowlevel/fdc-io.h b/drivers/char/ftape/lowlevel/fdc-io.h
new file mode 100644
index 000000000000..7ec3c72178bb
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/fdc-io.h
@@ -0,0 +1,252 @@
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
new file mode 100644
index 000000000000..ad2bc733ae1b
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/fdc-isr.c
@@ -0,0 +1,1170 @@
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
new file mode 100644
index 000000000000..065aa978942d
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/fdc-isr.h
@@ -0,0 +1,55 @@
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
new file mode 100644
index 000000000000..d1a301cc344f
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-bsm.c
@@ -0,0 +1,491 @@
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
new file mode 100644
index 000000000000..ed45465af4d4
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-bsm.h
@@ -0,0 +1,66 @@
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
new file mode 100644
index 000000000000..54af20cd9a2c
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-buffer.c
@@ -0,0 +1,129 @@
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
37/* DMA'able memory allocation stuff.
38 */
39
40static inline void *dmaalloc(size_t size)
41{
42 unsigned long addr;
43
44 if (size == 0) {
45 return NULL;
46 }
47 addr = __get_dma_pages(GFP_KERNEL, get_order(size));
48 if (addr) {
49 struct page *page;
50
51 for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)
52 SetPageReserved(page);
53 }
54 return (void *)addr;
55}
56
57static inline void dmafree(void *addr, size_t size)
58{
59 if (size > 0) {
60 struct page *page;
61
62 for (page = virt_to_page((unsigned long)addr);
63 page < virt_to_page((unsigned long)addr+size); page++)
64 ClearPageReserved(page);
65 free_pages((unsigned long) addr, get_order(size));
66 }
67}
68
69static int add_one_buffer(void)
70{
71 TRACE_FUN(ft_t_flow);
72
73 if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) {
74 TRACE_EXIT -ENOMEM;
75 }
76 ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL);
77 if (ft_buffer[ft_nr_buffers] == NULL) {
78 TRACE_EXIT -ENOMEM;
79 }
80 memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct));
81 ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE);
82 if (ft_buffer[ft_nr_buffers]->address == NULL) {
83 kfree(ft_buffer[ft_nr_buffers]);
84 ft_buffer[ft_nr_buffers] = NULL;
85 TRACE_EXIT -ENOMEM;
86 }
87 ft_nr_buffers ++;
88 TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p",
89 ft_nr_buffers,
90 ft_buffer[ft_nr_buffers-1],
91 ft_buffer[ft_nr_buffers-1]->address);
92 TRACE_EXIT 0;
93}
94
95static void del_one_buffer(void)
96{
97 TRACE_FUN(ft_t_flow);
98 if (ft_nr_buffers > 0) {
99 TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p",
100 ft_nr_buffers,
101 ft_buffer[ft_nr_buffers-1],
102 ft_buffer[ft_nr_buffers-1]->address);
103 ft_nr_buffers --;
104 dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE);
105 kfree(ft_buffer[ft_nr_buffers]);
106 ft_buffer[ft_nr_buffers] = NULL;
107 }
108 TRACE_EXIT;
109}
110
111int ftape_set_nr_buffers(int cnt)
112{
113 int delta = cnt - ft_nr_buffers;
114 TRACE_FUN(ft_t_flow);
115
116 if (delta > 0) {
117 while (delta--) {
118 if (add_one_buffer() < 0) {
119 TRACE_EXIT -ENOMEM;
120 }
121 }
122 } else if (delta < 0) {
123 while (delta++) {
124 del_one_buffer();
125 }
126 }
127 ftape_zap_read_buffers();
128 TRACE_EXIT 0;
129}
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.h b/drivers/char/ftape/lowlevel/ftape-buffer.h
new file mode 100644
index 000000000000..eec99cee8f82
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-buffer.h
@@ -0,0 +1,32 @@
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
new file mode 100644
index 000000000000..956b2586e138
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-calibr.c
@@ -0,0 +1,276 @@
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/config.h>
28#include <linux/errno.h>
29#include <linux/jiffies.h>
30#include <asm/system.h>
31#include <asm/io.h>
32#if defined(__alpha__)
33# include <asm/hwrpb.h>
34#elif defined(__x86_64__)
35# include <asm/msr.h>
36# include <asm/timex.h>
37#elif defined(__i386__)
38# include <linux/timex.h>
39#endif
40#include <linux/ftape.h>
41#include "../lowlevel/ftape-tracing.h"
42#include "../lowlevel/ftape-calibr.h"
43#include "../lowlevel/fdc-io.h"
44
45#undef DEBUG
46
47#if !defined(__alpha__) && !defined(__i386__) && !defined(__x86_64__)
48# error Ftape is not implemented for this architecture!
49#endif
50
51#if defined(__alpha__) || defined(__x86_64__)
52static unsigned long ps_per_cycle = 0;
53#endif
54
55static spinlock_t calibr_lock;
56
57/*
58 * Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is
59 * too slow for certain timeouts (and that clock doesn't even tick
60 * when interrupts are disabled). For that reason, the 8254 timer is
61 * used directly to implement fine-grained timeouts. However, on
62 * Alpha PCs, the 8254 is *not* used to implement the clock tick
63 * (which is 1024 Hz, normally) and the 8254 timer runs at some
64 * "random" frequency (it seems to run at 18Hz, but it's not safe to
65 * rely on this value). Instead, we use the Alpha's "rpcc"
66 * instruction to read cycle counts. As this is a 32 bit counter,
67 * it will overflow only once per 30 seconds (on a 200MHz machine),
68 * which is plenty.
69 */
70
71unsigned int ftape_timestamp(void)
72{
73#if defined(__alpha__)
74 unsigned long r;
75
76 asm volatile ("rpcc %0" : "=r" (r));
77 return r;
78#elif defined(__x86_64__)
79 unsigned long r;
80 rdtscl(r);
81 return r;
82#elif defined(__i386__)
83
84/*
85 * Note that there is some time between counter underflowing and jiffies
86 * increasing, so the code below won't always give correct output.
87 * -Vojtech
88 */
89
90 unsigned long flags;
91 __u16 lo;
92 __u16 hi;
93
94 spin_lock_irqsave(&calibr_lock, flags);
95 outb_p(0x00, 0x43); /* latch the count ASAP */
96 lo = inb_p(0x40); /* read the latched count */
97 lo |= inb(0x40) << 8;
98 hi = jiffies;
99 spin_unlock_irqrestore(&calibr_lock, flags);
100 return ((hi + 1) * (unsigned int) LATCH) - lo; /* downcounter ! */
101#endif
102}
103
104static unsigned int short_ftape_timestamp(void)
105{
106#if defined(__alpha__) || defined(__x86_64__)
107 return ftape_timestamp();
108#elif defined(__i386__)
109 unsigned int count;
110 unsigned long flags;
111
112 spin_lock_irqsave(&calibr_lock, flags);
113 outb_p(0x00, 0x43); /* latch the count ASAP */
114 count = inb_p(0x40); /* read the latched count */
115 count |= inb(0x40) << 8;
116 spin_unlock_irqrestore(&calibr_lock, flags);
117 return (LATCH - count); /* normal: downcounter */
118#endif
119}
120
121static unsigned int diff(unsigned int t0, unsigned int t1)
122{
123#if defined(__alpha__) || defined(__x86_64__)
124 return (t1 - t0);
125#elif defined(__i386__)
126 /*
127 * This is tricky: to work for both short and full ftape_timestamps
128 * we'll have to discriminate between these.
129 * If it _looks_ like short stamps with wrapping around we'll
130 * asume it are. This will generate a small error if it really
131 * was a (very large) delta from full ftape_timestamps.
132 */
133 return (t1 <= t0 && t0 <= LATCH) ? t1 + LATCH - t0 : t1 - t0;
134#endif
135}
136
137static unsigned int usecs(unsigned int count)
138{
139#if defined(__alpha__) || defined(__x86_64__)
140 return (ps_per_cycle * count) / 1000000UL;
141#elif defined(__i386__)
142 return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
143#endif
144}
145
146unsigned int ftape_timediff(unsigned int t0, unsigned int t1)
147{
148 /*
149 * Calculate difference in usec for ftape_timestamp results t0 & t1.
150 * Note that on the i386 platform with short time-stamps, the
151 * maximum allowed timespan is 1/HZ or we'll lose ticks!
152 */
153 return usecs(diff(t0, t1));
154}
155
156/* To get an indication of the I/O performance,
157 * measure the duration of the inb() function.
158 */
159static void time_inb(void)
160{
161 int i;
162 int t0, t1;
163 unsigned long flags;
164 int status;
165 TRACE_FUN(ft_t_any);
166
167 spin_lock_irqsave(&calibr_lock, flags);
168 t0 = short_ftape_timestamp();
169 for (i = 0; i < 1000; ++i) {
170 status = inb(fdc.msr);
171 }
172 t1 = short_ftape_timestamp();
173 spin_unlock_irqrestore(&calibr_lock, flags);
174 TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1));
175 TRACE_EXIT;
176}
177
178static void init_clock(void)
179{
180 TRACE_FUN(ft_t_any);
181
182#if defined(__x86_64__)
183 ps_per_cycle = 1000000000UL / cpu_khz;
184#elif defined(__alpha__)
185 extern struct hwrpb_struct *hwrpb;
186 ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
187#endif
188 TRACE_EXIT;
189}
190
191/*
192 * Input: function taking int count as parameter.
193 * pointers to calculated calibration variables.
194 */
195void ftape_calibrate(char *name,
196 void (*fun) (unsigned int),
197 unsigned int *calibr_count,
198 unsigned int *calibr_time)
199{
200 static int first_time = 1;
201 int i;
202 unsigned int tc = 0;
203 unsigned int count;
204 unsigned int time;
205#if defined(__i386__)
206 unsigned int old_tc = 0;
207 unsigned int old_count = 1;
208 unsigned int old_time = 1;
209#endif
210 TRACE_FUN(ft_t_flow);
211
212 if (first_time) { /* get idea of I/O performance */
213 init_clock();
214 time_inb();
215 first_time = 0;
216 }
217 /* value of timeout must be set so that on very slow systems
218 * it will give a time less than one jiffy, and on
219 * very fast systems it'll give reasonable precision.
220 */
221
222 count = 40;
223 for (i = 0; i < 15; ++i) {
224 unsigned int t0;
225 unsigned int t1;
226 unsigned int once;
227 unsigned int multiple;
228 unsigned long flags;
229
230 *calibr_count =
231 *calibr_time = count; /* set TC to 1 */
232 spin_lock_irqsave(&calibr_lock, flags);
233 fun(0); /* dummy, get code into cache */
234 t0 = short_ftape_timestamp();
235 fun(0); /* overhead + one test */
236 t1 = short_ftape_timestamp();
237 once = diff(t0, t1);
238 t0 = short_ftape_timestamp();
239 fun(count); /* overhead + count tests */
240 t1 = short_ftape_timestamp();
241 multiple = diff(t0, t1);
242 spin_unlock_irqrestore(&calibr_lock, flags);
243 time = ftape_timediff(0, multiple - once);
244 tc = (1000 * time) / (count - 1);
245 TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
246 usecs(once), count - 1, usecs(multiple), tc);
247#if defined(__alpha__) || defined(__x86_64__)
248 /*
249 * Increase the calibration count exponentially until the
250 * calibration time exceeds 100 ms.
251 */
252 if (time >= 100*1000) {
253 break;
254 }
255#elif defined(__i386__)
256 /*
257 * increase the count until the resulting time nears 2/HZ,
258 * then the tc will drop sharply because we lose LATCH counts.
259 */
260 if (tc <= old_tc / 2) {
261 time = old_time;
262 count = old_count;
263 break;
264 }
265 old_tc = tc;
266 old_count = count;
267 old_time = time;
268#endif
269 count *= 2;
270 }
271 *calibr_count = count - 1;
272 *calibr_time = time;
273 TRACE(ft_t_info, "TC for `%s()' = %d nsec (at %d counts)",
274 name, (1000 * *calibr_time) / *calibr_count, *calibr_count);
275 TRACE_EXIT;
276}
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.h b/drivers/char/ftape/lowlevel/ftape-calibr.h
new file mode 100644
index 000000000000..0c7e75246c7d
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-calibr.h
@@ -0,0 +1,37 @@
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
new file mode 100644
index 000000000000..32e043911790
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-ctl.c
@@ -0,0 +1,897 @@
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/config.h>
29#include <linux/errno.h>
30#include <linux/mm.h>
31#include <linux/mman.h>
32
33#include <linux/ftape.h>
34#include <linux/qic117.h>
35#include <asm/uaccess.h>
36#include <asm/io.h>
37
38/* ease porting between pre-2.4.x and later kernels */
39#define vma_get_pgoff(v) ((v)->vm_pgoff)
40
41#include "../lowlevel/ftape-tracing.h"
42#include "../lowlevel/ftape-io.h"
43#include "../lowlevel/ftape-ctl.h"
44#include "../lowlevel/ftape-write.h"
45#include "../lowlevel/ftape-read.h"
46#include "../lowlevel/ftape-rw.h"
47#include "../lowlevel/ftape-bsm.h"
48
49/* Global vars.
50 */
51ftape_info ftape_status = {
52/* vendor information */
53 { 0, }, /* drive type */
54/* data rates */
55 500, /* used data rate */
56 500, /* drive max rate */
57 500, /* fdc max rate */
58/* drive selection, either FTAPE_SEL_A/B/C/D */
59 -1, /* drive selection */
60/* flags set after decode the drive and tape status */
61 0, /* formatted */
62 1, /* no tape */
63 1, /* write protected */
64 1, /* new tape */
65/* values of last queried drive/tape status and error */
66 {{0,}}, /* last error code */
67 {{0,}}, /* drive status, configuration, tape status */
68/* cartridge geometry */
69 20, /* tracks_per_tape */
70 102, /* segments_per_track */
71/* location of header segments, etc. */
72 -1, /* used_header_segment */
73 -1, /* header_segment_1 */
74 -1, /* header_segment_2 */
75 -1, /* first_data_segment */
76 -1, /* last_data_segment */
77/* the format code as stored in the header segment */
78 fmt_normal, /* format code */
79/* the default for the qic std: unknown */
80 -1,
81/* is tape running? */
82 idle, /* runner_state */
83/* is tape reading/writing/verifying/formatting/deleting */
84 idle, /* driver state */
85/* flags fatal hardware error */
86 1, /* failure */
87/* history record */
88 { 0, } /* history record */
89};
90
91int ftape_segments_per_head = 1020;
92int ftape_segments_per_cylinder = 4;
93int ftape_init_drive_needed = 1; /* need to be global for ftape_reset_drive()
94 * in ftape-io.c
95 */
96
97/* Local vars.
98 */
99static const vendor_struct vendors[] = QIC117_VENDORS;
100static const wakeup_method methods[] = WAKEUP_METHODS;
101
102const ftape_info *ftape_get_status(void)
103{
104#if defined(STATUS_PARANOYA)
105 static ftape_info get_status;
106
107 get_status = ftape_status;
108 return &get_status;
109#else
110 return &ftape_status; /* maybe return only a copy of it to assure
111 * read only access
112 */
113#endif
114}
115
116static int ftape_not_operational(int status)
117{
118 /* return true if status indicates tape can not be used.
119 */
120 return ((status ^ QIC_STATUS_CARTRIDGE_PRESENT) &
121 (QIC_STATUS_ERROR |
122 QIC_STATUS_CARTRIDGE_PRESENT |
123 QIC_STATUS_NEW_CARTRIDGE));
124}
125
126int ftape_seek_to_eot(void)
127{
128 int status;
129 TRACE_FUN(ft_t_any);
130
131 TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
132 while ((status & QIC_STATUS_AT_EOT) == 0) {
133 if (ftape_not_operational(status)) {
134 TRACE_EXIT -EIO;
135 }
136 TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_FORWARD,
137 ftape_timeout.rewind,&status),);
138 }
139 TRACE_EXIT 0;
140}
141
142int ftape_seek_to_bot(void)
143{
144 int status;
145 TRACE_FUN(ft_t_any);
146
147 TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
148 while ((status & QIC_STATUS_AT_BOT) == 0) {
149 if (ftape_not_operational(status)) {
150 TRACE_EXIT -EIO;
151 }
152 TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_REVERSE,
153 ftape_timeout.rewind,&status),);
154 }
155 TRACE_EXIT 0;
156}
157
158static int ftape_new_cartridge(void)
159{
160 ft_location.track = -1; /* force seek on first access */
161 ftape_zap_read_buffers();
162 ftape_zap_write_buffers();
163 return 0;
164}
165
166int ftape_abort_operation(void)
167{
168 int result = 0;
169 int status;
170 TRACE_FUN(ft_t_flow);
171
172 if (ft_runner_status == running) {
173 TRACE(ft_t_noise, "aborting runner, waiting");
174
175 ft_runner_status = do_abort;
176 /* set timeout so that the tape will run to logical EOT
177 * if we missed the last sector and there are no queue pulses.
178 */
179 result = ftape_dumb_stop();
180 }
181 if (ft_runner_status != idle) {
182 if (ft_runner_status == do_abort) {
183 TRACE(ft_t_noise, "forcing runner abort");
184 }
185 TRACE(ft_t_noise, "stopping tape");
186 result = ftape_stop_tape(&status);
187 ft_location.known = 0;
188 ft_runner_status = idle;
189 }
190 ftape_reset_buffer();
191 ftape_zap_read_buffers();
192 ftape_set_state(idle);
193 TRACE_EXIT result;
194}
195
196static int lookup_vendor_id(unsigned int vendor_id)
197{
198 int i = 0;
199
200 while (vendors[i].vendor_id != vendor_id) {
201 if (++i >= NR_ITEMS(vendors)) {
202 return -1;
203 }
204 }
205 return i;
206}
207
208static void ftape_detach_drive(void)
209{
210 TRACE_FUN(ft_t_any);
211
212 TRACE(ft_t_flow, "disabling tape drive and fdc");
213 ftape_put_drive_to_sleep(ft_drive_type.wake_up);
214 fdc_catch_stray_interrupts(1); /* one always comes */
215 fdc_disable();
216 fdc_release_irq_and_dma();
217 fdc_release_regions();
218 TRACE_EXIT;
219}
220
221static void clear_history(void)
222{
223 ft_history.used = 0;
224 ft_history.id_am_errors =
225 ft_history.id_crc_errors =
226 ft_history.data_am_errors =
227 ft_history.data_crc_errors =
228 ft_history.overrun_errors =
229 ft_history.no_data_errors =
230 ft_history.retries =
231 ft_history.crc_errors =
232 ft_history.crc_failures =
233 ft_history.ecc_failures =
234 ft_history.corrected =
235 ft_history.defects =
236 ft_history.rewinds = 0;
237}
238
239static int ftape_activate_drive(vendor_struct * drive_type)
240{
241 int result = 0;
242 TRACE_FUN(ft_t_flow);
243
244 /* If we already know the drive type, wake it up.
245 * Else try to find out what kind of drive is attached.
246 */
247 if (drive_type->wake_up != unknown_wake_up) {
248 TRACE(ft_t_flow, "enabling tape drive and fdc");
249 result = ftape_wakeup_drive(drive_type->wake_up);
250 if (result < 0) {
251 TRACE(ft_t_err, "known wakeup method failed");
252 }
253 } else {
254 wake_up_types method;
255 const ft_trace_t old_tracing = TRACE_LEVEL;
256 if (TRACE_LEVEL < ft_t_flow) {
257 SET_TRACE_LEVEL(ft_t_bug);
258 }
259
260 /* Try to awaken the drive using all known methods.
261 * Lower tracing for a while.
262 */
263 for (method=no_wake_up; method < NR_ITEMS(methods); ++method) {
264 drive_type->wake_up = method;
265#ifdef CONFIG_FT_TWO_DRIVES
266 /* Test setup for dual drive configuration.
267 * /dev/rft2 uses mountain wakeup
268 * /dev/rft3 uses colorado wakeup
269 * Other systems will use the normal scheme.
270 */
271 if ((ft_drive_sel < 2) ||
272 (ft_drive_sel == 2 && method == FT_WAKE_UP_1) ||
273 (ft_drive_sel == 3 && method == FT_WAKE_UP_2)) {
274 result=ftape_wakeup_drive(drive_type->wake_up);
275 } else {
276 result = -EIO;
277 }
278#else
279 result = ftape_wakeup_drive(drive_type->wake_up);
280#endif
281 if (result >= 0) {
282 TRACE(ft_t_warn, "drive wakeup method: %s",
283 methods[drive_type->wake_up].name);
284 break;
285 }
286 }
287 SET_TRACE_LEVEL(old_tracing);
288
289 if (method >= NR_ITEMS(methods)) {
290 /* no response at all, cannot open this drive */
291 drive_type->wake_up = unknown_wake_up;
292 TRACE(ft_t_err, "no tape drive found !");
293 result = -ENODEV;
294 }
295 }
296 TRACE_EXIT result;
297}
298
299static int ftape_get_drive_status(void)
300{
301 int result;
302 int status;
303 TRACE_FUN(ft_t_flow);
304
305 ft_no_tape = ft_write_protected = 0;
306 /* Tape drive is activated now.
307 * First clear error status if present.
308 */
309 do {
310 result = ftape_ready_wait(ftape_timeout.reset, &status);
311 if (result < 0) {
312 if (result == -ETIME) {
313 TRACE(ft_t_err, "ftape_ready_wait timeout");
314 } else if (result == -EINTR) {
315 TRACE(ft_t_err, "ftape_ready_wait aborted");
316 } else {
317 TRACE(ft_t_err, "ftape_ready_wait failed");
318 }
319 TRACE_EXIT -EIO;
320 }
321 /* Clear error condition (drive is ready !)
322 */
323 if (status & QIC_STATUS_ERROR) {
324 unsigned int error;
325 qic117_cmd_t command;
326
327 TRACE(ft_t_err, "error status set");
328 result = ftape_report_error(&error, &command, 1);
329 if (result < 0) {
330 TRACE(ft_t_err,
331 "report_error_code failed: %d", result);
332 /* hope it's working next time */
333 ftape_reset_drive();
334 TRACE_EXIT -EIO;
335 } else if (error != 0) {
336 TRACE(ft_t_noise, "error code : %d", error);
337 TRACE(ft_t_noise, "error command: %d", command);
338 }
339 }
340 if (status & QIC_STATUS_NEW_CARTRIDGE) {
341 unsigned int error;
342 qic117_cmd_t command;
343 const ft_trace_t old_tracing = TRACE_LEVEL;
344 SET_TRACE_LEVEL(ft_t_bug);
345
346 /* Undocumented feature: Must clear (not present!)
347 * error here or we'll fail later.
348 */
349 ftape_report_error(&error, &command, 1);
350
351 SET_TRACE_LEVEL(old_tracing);
352 TRACE(ft_t_info, "status: new cartridge");
353 ft_new_tape = 1;
354 } else {
355 ft_new_tape = 0;
356 }
357 FT_SIGNAL_EXIT(_DONT_BLOCK);
358 } while (status & QIC_STATUS_ERROR);
359
360 ft_no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT);
361 ft_write_protected = (status & QIC_STATUS_WRITE_PROTECT) != 0;
362 if (ft_no_tape) {
363 TRACE(ft_t_warn, "no cartridge present");
364 } else {
365 if (ft_write_protected) {
366 TRACE(ft_t_noise, "Write protected cartridge");
367 }
368 }
369 TRACE_EXIT 0;
370}
371
372static void ftape_log_vendor_id(void)
373{
374 int vendor_index;
375 TRACE_FUN(ft_t_flow);
376
377 ftape_report_vendor_id(&ft_drive_type.vendor_id);
378 vendor_index = lookup_vendor_id(ft_drive_type.vendor_id);
379 if (ft_drive_type.vendor_id == UNKNOWN_VENDOR &&
380 ft_drive_type.wake_up == wake_up_colorado) {
381 vendor_index = 0;
382 /* hack to get rid of all this mail */
383 ft_drive_type.vendor_id = 0;
384 }
385 if (vendor_index < 0) {
386 /* Unknown vendor id, first time opening device. The
387 * drive_type remains set to type found at wakeup
388 * time, this will probably keep the driver operating
389 * for this new vendor.
390 */
391 TRACE(ft_t_warn, "\n"
392 KERN_INFO "============ unknown vendor id ===========\n"
393 KERN_INFO "A new, yet unsupported tape drive is found\n"
394 KERN_INFO "Please report the following values:\n"
395 KERN_INFO " Vendor id : 0x%04x\n"
396 KERN_INFO " Wakeup method : %s\n"
397 KERN_INFO "And a description of your tape drive\n"
398 KERN_INFO "to "THE_FTAPE_MAINTAINER"\n"
399 KERN_INFO "==========================================",
400 ft_drive_type.vendor_id,
401 methods[ft_drive_type.wake_up].name);
402 ft_drive_type.speed = 0; /* unknown */
403 } else {
404 ft_drive_type.name = vendors[vendor_index].name;
405 ft_drive_type.speed = vendors[vendor_index].speed;
406 TRACE(ft_t_info, "tape drive type: %s", ft_drive_type.name);
407 /* scan all methods for this vendor_id in table */
408 while(ft_drive_type.wake_up != vendors[vendor_index].wake_up) {
409 if (vendor_index < NR_ITEMS(vendors) - 1 &&
410 vendors[vendor_index + 1].vendor_id
411 ==
412 ft_drive_type.vendor_id) {
413 ++vendor_index;
414 } else {
415 break;
416 }
417 }
418 if (ft_drive_type.wake_up != vendors[vendor_index].wake_up) {
419 TRACE(ft_t_warn, "\n"
420 KERN_INFO "==========================================\n"
421 KERN_INFO "wakeup type mismatch:\n"
422 KERN_INFO "found: %s, expected: %s\n"
423 KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n"
424 KERN_INFO "==========================================",
425 methods[ft_drive_type.wake_up].name,
426 methods[vendors[vendor_index].wake_up].name);
427 }
428 }
429 TRACE_EXIT;
430}
431
432void ftape_calc_timeouts(unsigned int qic_std,
433 unsigned int data_rate,
434 unsigned int tape_len)
435{
436 int speed; /* deci-ips ! */
437 int ff_speed;
438 int length;
439 TRACE_FUN(ft_t_any);
440
441 /* tape transport speed
442 * data rate: QIC-40 QIC-80 QIC-3010 QIC-3020
443 *
444 * 250 Kbps 25 ips n/a n/a n/a
445 * 500 Kbps 50 ips 34 ips 22.6 ips n/a
446 * 1 Mbps n/a 68 ips 45.2 ips 22.6 ips
447 * 2 Mbps n/a n/a n/a 45.2 ips
448 *
449 * fast tape transport speed is at least 68 ips.
450 */
451 switch (qic_std) {
452 case QIC_TAPE_QIC40:
453 speed = (data_rate == 250) ? 250 : 500;
454 break;
455 case QIC_TAPE_QIC80:
456 speed = (data_rate == 500) ? 340 : 680;
457 break;
458 case QIC_TAPE_QIC3010:
459 speed = (data_rate == 500) ? 226 : 452;
460 break;
461 case QIC_TAPE_QIC3020:
462 speed = (data_rate == 1000) ? 226 : 452;
463 break;
464 default:
465 TRACE(ft_t_bug, "Unknown qic_std (bug) ?");
466 speed = 500;
467 break;
468 }
469 if (ft_drive_type.speed == 0) {
470 unsigned long t0;
471 static int dt = 0; /* keep gcc from complaining */
472 static int first_time = 1;
473
474 /* Measure the time it takes to wind to EOT and back to BOT.
475 * If the tape length is known, calculate the rewind speed.
476 * Else keep the time value for calculation of the rewind
477 * speed later on, when the length _is_ known.
478 * Ask for a report only when length and speed are both known.
479 */
480 if (first_time) {
481 ftape_seek_to_bot();
482 t0 = jiffies;
483 ftape_seek_to_eot();
484 ftape_seek_to_bot();
485 dt = (int) (((jiffies - t0) * FT_USPT) / 1000);
486 if (dt < 1) {
487 dt = 1; /* prevent div by zero on failures */
488 }
489 first_time = 0;
490 TRACE(ft_t_info,
491 "trying to determine seek timeout, got %d msec",
492 dt);
493 }
494 if (tape_len != 0) {
495 ft_drive_type.speed =
496 (2 * 12 * tape_len * 1000) / dt;
497 TRACE(ft_t_warn, "\n"
498 KERN_INFO "==========================================\n"
499 KERN_INFO "drive type: %s\n"
500 KERN_INFO "delta time = %d ms, length = %d ft\n"
501 KERN_INFO "has a maximum tape speed of %d ips\n"
502 KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n"
503 KERN_INFO "==========================================",
504 ft_drive_type.name, dt, tape_len,
505 ft_drive_type.speed);
506 }
507 }
508 /* Handle unknown length tapes as very long ones. We'll
509 * determine the actual length from a header segment later.
510 * This is normal for all modern (Wide,TR1/2/3) formats.
511 */
512 if (tape_len <= 0) {
513 TRACE(ft_t_noise,
514 "Unknown tape length, using maximal timeouts");
515 length = QIC_TOP_TAPE_LEN; /* use worst case values */
516 } else {
517 length = tape_len; /* use actual values */
518 }
519 if (ft_drive_type.speed == 0) {
520 ff_speed = speed;
521 } else {
522 ff_speed = ft_drive_type.speed;
523 }
524 /* time to go from bot to eot at normal speed (data rate):
525 * time = (1+delta) * length (ft) * 12 (inch/ft) / speed (ips)
526 * delta = 10 % for seek speed, 20 % for rewind speed.
527 */
528 ftape_timeout.seek = (length * 132 * FT_SECOND) / speed;
529 ftape_timeout.rewind = (length * 144 * FT_SECOND) / (10 * ff_speed);
530 ftape_timeout.reset = 20 * FT_SECOND + ftape_timeout.rewind;
531 TRACE(ft_t_noise, "timeouts for speed = %d, length = %d\n"
532 KERN_INFO "seek timeout : %d sec\n"
533 KERN_INFO "rewind timeout: %d sec\n"
534 KERN_INFO "reset timeout : %d sec",
535 speed, length,
536 (ftape_timeout.seek + 500) / 1000,
537 (ftape_timeout.rewind + 500) / 1000,
538 (ftape_timeout.reset + 500) / 1000);
539 TRACE_EXIT;
540}
541
542/* This function calibrates the datarate (i.e. determines the maximal
543 * usable data rate) and sets the global variable ft_qic_std to qic_std
544 *
545 */
546int ftape_calibrate_data_rate(unsigned int qic_std)
547{
548 int rate = ft_fdc_rate_limit;
549 int result;
550 TRACE_FUN(ft_t_flow);
551
552 ft_qic_std = qic_std;
553
554 if (ft_qic_std == -1) {
555 TRACE_ABORT(-EIO, ft_t_err,
556 "Unable to determine data rate if QIC standard is unknown");
557 }
558
559 /* Select highest rate supported by both fdc and drive.
560 * Start with highest rate supported by the fdc.
561 */
562 while (fdc_set_data_rate(rate) < 0 && rate > 250) {
563 rate /= 2;
564 }
565 TRACE(ft_t_info,
566 "Highest FDC supported data rate: %d Kbps", rate);
567 ft_fdc_max_rate = rate;
568 do {
569 result = ftape_set_data_rate(rate, ft_qic_std);
570 } while (result == -EINVAL && (rate /= 2) > 250);
571 if (result < 0) {
572 TRACE_ABORT(-EIO, ft_t_err, "set datarate failed");
573 }
574 ft_data_rate = rate;
575 TRACE_EXIT 0;
576}
577
578static int ftape_init_drive(void)
579{
580 int status;
581 qic_model model;
582 unsigned int qic_std;
583 unsigned int data_rate;
584 TRACE_FUN(ft_t_flow);
585
586 ftape_init_drive_needed = 0; /* don't retry if this fails ? */
587 TRACE_CATCH(ftape_report_raw_drive_status(&status),);
588 if (status & QIC_STATUS_CARTRIDGE_PRESENT) {
589 if (!(status & QIC_STATUS_AT_BOT)) {
590 /* Antique drives will get here after a soft reset,
591 * modern ones only if the driver is loaded when the
592 * tape wasn't rewound properly.
593 */
594 /* Tape should be at bot if new cartridge ! */
595 ftape_seek_to_bot();
596 }
597 if (!(status & QIC_STATUS_REFERENCED)) {
598 TRACE(ft_t_flow, "starting seek_load_point");
599 TRACE_CATCH(ftape_command_wait(QIC_SEEK_LOAD_POINT,
600 ftape_timeout.reset,
601 &status),);
602 }
603 }
604 ft_formatted = (status & QIC_STATUS_REFERENCED) != 0;
605 if (!ft_formatted) {
606 TRACE(ft_t_warn, "Warning: tape is not formatted !");
607 }
608
609 /* report configuration aborts when ftape_tape_len == -1
610 * unknown qic_std is okay if not formatted.
611 */
612 TRACE_CATCH(ftape_report_configuration(&model,
613 &data_rate,
614 &qic_std,
615 &ftape_tape_len),);
616
617 /* Maybe add the following to the /proc entry
618 */
619 TRACE(ft_t_info, "%s drive @ %d Kbps",
620 (model == prehistoric) ? "prehistoric" :
621 ((model == pre_qic117c) ? "pre QIC-117C" :
622 ((model == post_qic117b) ? "post QIC-117B" :
623 "post QIC-117D")), data_rate);
624
625 if (ft_formatted) {
626 /* initialize ft_used_data_rate to maximum value
627 * and set ft_qic_std
628 */
629 TRACE_CATCH(ftape_calibrate_data_rate(qic_std),);
630 if (ftape_tape_len == 0) {
631 TRACE(ft_t_info, "unknown length QIC-%s tape",
632 (ft_qic_std == QIC_TAPE_QIC40) ? "40" :
633 ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
634 ((ft_qic_std == QIC_TAPE_QIC3010)
635 ? "3010" : "3020")));
636 } else {
637 TRACE(ft_t_info, "%d ft. QIC-%s tape", ftape_tape_len,
638 (ft_qic_std == QIC_TAPE_QIC40) ? "40" :
639 ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
640 ((ft_qic_std == QIC_TAPE_QIC3010)
641 ? "3010" : "3020")));
642 }
643 ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
644 /* soft write-protect QIC-40/QIC-80 cartridges used with a
645 * Colorado T3000 drive. Buggy hardware!
646 */
647 if ((ft_drive_type.vendor_id == 0x011c6) &&
648 ((ft_qic_std == QIC_TAPE_QIC40 ||
649 ft_qic_std == QIC_TAPE_QIC80) &&
650 !ft_write_protected)) {
651 TRACE(ft_t_warn, "\n"
652 KERN_INFO "The famous Colorado T3000 bug:\n"
653 KERN_INFO "%s drives can't write QIC40 and QIC80\n"
654 KERN_INFO "cartridges but don't set the write-protect flag!",
655 ft_drive_type.name);
656 ft_write_protected = 1;
657 }
658 } else {
659 /* Doesn't make too much sense to set the data rate
660 * because we don't know what to use for the write
661 * precompensation.
662 * Need to do this again when formatting the cartridge.
663 */
664 ft_data_rate = data_rate;
665 ftape_calc_timeouts(QIC_TAPE_QIC40,
666 data_rate,
667 ftape_tape_len);
668 }
669 ftape_new_cartridge();
670 TRACE_EXIT 0;
671}
672
673static void ftape_munmap(void)
674{
675 int i;
676 TRACE_FUN(ft_t_flow);
677
678 for (i = 0; i < ft_nr_buffers; i++) {
679 ft_buffer[i]->mmapped = 0;
680 }
681 TRACE_EXIT;
682}
683
684/* Map the dma buffers into the virtual address range given by vma.
685 * We only check the caller doesn't map non-existent buffers. We
686 * don't check for multiple mappings.
687 */
688int ftape_mmap(struct vm_area_struct *vma)
689{
690 int num_buffers;
691 int i;
692 TRACE_FUN(ft_t_flow);
693
694 if (ft_failure) {
695 TRACE_EXIT -ENODEV;
696 }
697 if (!(vma->vm_flags & (VM_READ|VM_WRITE))) {
698 TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access");
699 }
700 if (vma_get_pgoff(vma) != 0) {
701 TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0");
702 }
703 if ((vma->vm_end - vma->vm_start) % FT_BUFF_SIZE != 0) {
704 TRACE_ABORT(-EINVAL, ft_t_err,
705 "size = %ld, should be a multiple of %d",
706 vma->vm_end - vma->vm_start,
707 FT_BUFF_SIZE);
708 }
709 num_buffers = (vma->vm_end - vma->vm_start) / FT_BUFF_SIZE;
710 if (num_buffers > ft_nr_buffers) {
711 TRACE_ABORT(-EINVAL,
712 ft_t_err, "size = %ld, should be less than %d",
713 vma->vm_end - vma->vm_start,
714 ft_nr_buffers * FT_BUFF_SIZE);
715 }
716 if (ft_driver_state != idle) {
717 /* this also clears the buffer states
718 */
719 ftape_abort_operation();
720 } else {
721 ftape_reset_buffer();
722 }
723 for (i = 0; i < num_buffers; i++) {
724 unsigned long pfn;
725
726 pfn = virt_to_phys(ft_buffer[i]->address) >> PAGE_SHIFT;
727 TRACE_CATCH(remap_pfn_range(vma, vma->vm_start +
728 i * FT_BUFF_SIZE,
729 pfn,
730 FT_BUFF_SIZE,
731 vma->vm_page_prot),
732 _res = -EAGAIN);
733 TRACE(ft_t_noise, "remapped dma buffer @ %p to location @ %p",
734 ft_buffer[i]->address,
735 (void *)(vma->vm_start + i * FT_BUFF_SIZE));
736 }
737 for (i = 0; i < num_buffers; i++) {
738 memset(ft_buffer[i]->address, 0xAA, FT_BUFF_SIZE);
739 ft_buffer[i]->mmapped++;
740 }
741 TRACE_EXIT 0;
742}
743
744static void ftape_init_driver(void); /* forward declaration */
745
746/* OPEN routine called by kernel-interface code
747 */
748int ftape_enable(int drive_selection)
749{
750 TRACE_FUN(ft_t_any);
751
752 if (ft_drive_sel == -1 || ft_drive_sel != drive_selection) {
753 /* Other selection than last time
754 */
755 ftape_init_driver();
756 }
757 ft_drive_sel = FTAPE_SEL(drive_selection);
758 ft_failure = 0;
759 TRACE_CATCH(fdc_init(),); /* init & detect fdc */
760 TRACE_CATCH(ftape_activate_drive(&ft_drive_type),
761 fdc_disable();
762 fdc_release_irq_and_dma();
763 fdc_release_regions());
764 TRACE_CATCH(ftape_get_drive_status(), ftape_detach_drive());
765 if (ft_drive_type.vendor_id == UNKNOWN_VENDOR) {
766 ftape_log_vendor_id();
767 }
768 if (ft_new_tape) {
769 ftape_init_drive_needed = 1;
770 }
771 if (!ft_no_tape && ftape_init_drive_needed) {
772 TRACE_CATCH(ftape_init_drive(), ftape_detach_drive());
773 }
774 ftape_munmap(); /* clear the mmap flag */
775 clear_history();
776 TRACE_EXIT 0;
777}
778
779/* release routine called by the high level interface modules
780 * zftape or sftape.
781 */
782void ftape_disable(void)
783{
784 int i;
785 TRACE_FUN(ft_t_any);
786
787 for (i = 0; i < ft_nr_buffers; i++) {
788 if (ft_buffer[i]->mmapped) {
789 TRACE(ft_t_noise, "first byte of buffer %d: 0x%02x",
790 i, *ft_buffer[i]->address);
791 }
792 }
793 if (sigtestsetmask(&current->pending.signal, _DONT_BLOCK) &&
794 !(sigtestsetmask(&current->pending.signal, _NEVER_BLOCK)) &&
795 ftape_tape_running) {
796 TRACE(ft_t_warn,
797 "Interrupted by fatal signal and tape still running");
798 ftape_dumb_stop();
799 ftape_abort_operation(); /* it's annoying */
800 } else {
801 ftape_set_state(idle);
802 }
803 ftape_detach_drive();
804 if (ft_history.used) {
805 TRACE(ft_t_info, "== Non-fatal errors this run: ==");
806 TRACE(ft_t_info, "fdc isr statistics:\n"
807 KERN_INFO " id_am_errors : %3d\n"
808 KERN_INFO " id_crc_errors : %3d\n"
809 KERN_INFO " data_am_errors : %3d\n"
810 KERN_INFO " data_crc_errors : %3d\n"
811 KERN_INFO " overrun_errors : %3d\n"
812 KERN_INFO " no_data_errors : %3d\n"
813 KERN_INFO " retries : %3d",
814 ft_history.id_am_errors, ft_history.id_crc_errors,
815 ft_history.data_am_errors, ft_history.data_crc_errors,
816 ft_history.overrun_errors, ft_history.no_data_errors,
817 ft_history.retries);
818 if (ft_history.used & 1) {
819 TRACE(ft_t_info, "ecc statistics:\n"
820 KERN_INFO " crc_errors : %3d\n"
821 KERN_INFO " crc_failures : %3d\n"
822 KERN_INFO " ecc_failures : %3d\n"
823 KERN_INFO " sectors corrected: %3d",
824 ft_history.crc_errors, ft_history.crc_failures,
825 ft_history.ecc_failures, ft_history.corrected);
826 }
827 if (ft_history.defects > 0) {
828 TRACE(ft_t_warn, "Warning: %d media defects!",
829 ft_history.defects);
830 }
831 if (ft_history.rewinds > 0) {
832 TRACE(ft_t_info, "tape motion statistics:\n"
833 KERN_INFO "repositions : %3d",
834 ft_history.rewinds);
835 }
836 }
837 ft_failure = 1;
838 TRACE_EXIT;
839}
840
841static void ftape_init_driver(void)
842{
843 TRACE_FUN(ft_t_flow);
844
845 ft_drive_type.vendor_id = UNKNOWN_VENDOR;
846 ft_drive_type.speed = 0;
847 ft_drive_type.wake_up = unknown_wake_up;
848 ft_drive_type.name = "Unknown";
849
850 ftape_timeout.seek = 650 * FT_SECOND;
851 ftape_timeout.reset = 670 * FT_SECOND;
852 ftape_timeout.rewind = 650 * FT_SECOND;
853 ftape_timeout.head_seek = 15 * FT_SECOND;
854 ftape_timeout.stop = 5 * FT_SECOND;
855 ftape_timeout.pause = 16 * FT_SECOND;
856
857 ft_qic_std = -1;
858 ftape_tape_len = 0; /* unknown */
859 ftape_current_command = 0;
860 ftape_current_cylinder = -1;
861
862 ft_segments_per_track = 102;
863 ftape_segments_per_head = 1020;
864 ftape_segments_per_cylinder = 4;
865 ft_tracks_per_tape = 20;
866
867 ft_failure = 1;
868
869 ft_formatted = 0;
870 ft_no_tape = 1;
871 ft_write_protected = 1;
872 ft_new_tape = 1;
873
874 ft_driver_state = idle;
875
876 ft_data_rate =
877 ft_fdc_max_rate = 500;
878 ft_drive_max_rate = 0; /* triggers set_rate_test() */
879
880 ftape_init_drive_needed = 1;
881
882 ft_header_segment_1 = -1;
883 ft_header_segment_2 = -1;
884 ft_used_header_segment = -1;
885 ft_first_data_segment = -1;
886 ft_last_data_segment = -1;
887
888 ft_location.track = -1;
889 ft_location.known = 0;
890
891 ftape_tape_running = 0;
892 ftape_might_be_off_track = 1;
893
894 ftape_new_cartridge(); /* init some tape related variables */
895 ftape_init_bsm();
896 TRACE_EXIT;
897}
diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.h b/drivers/char/ftape/lowlevel/ftape-ctl.h
new file mode 100644
index 000000000000..5f5e30bc3615
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-ctl.h
@@ -0,0 +1,162 @@
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
new file mode 100644
index 000000000000..e5632f674bc8
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-ecc.c
@@ -0,0 +1,853 @@
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
new file mode 100644
index 000000000000..4829146fe9a0
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-ecc.h
@@ -0,0 +1,84 @@
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
new file mode 100644
index 000000000000..5dd4c59a3f34
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-format.c
@@ -0,0 +1,344 @@
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
new file mode 100644
index 000000000000..f15161566643
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-format.h
@@ -0,0 +1,37 @@
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
new file mode 100644
index 000000000000..b54260d457c2
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-init.c
@@ -0,0 +1,161 @@
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/config.h>
25#include <linux/module.h>
26#include <linux/errno.h>
27#include <linux/fs.h>
28#include <linux/kernel.h>
29#include <linux/signal.h>
30#include <linux/major.h>
31
32#include <linux/ftape.h>
33#include <linux/init.h>
34#include <linux/qic117.h>
35#ifdef CONFIG_ZFTAPE
36#include <linux/zftape.h>
37#endif
38
39#include "../lowlevel/ftape-init.h"
40#include "../lowlevel/ftape-io.h"
41#include "../lowlevel/ftape-read.h"
42#include "../lowlevel/ftape-write.h"
43#include "../lowlevel/ftape-ctl.h"
44#include "../lowlevel/ftape-rw.h"
45#include "../lowlevel/fdc-io.h"
46#include "../lowlevel/ftape-buffer.h"
47#include "../lowlevel/ftape-proc.h"
48#include "../lowlevel/ftape-tracing.h"
49
50
51#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)
52static int ft_tracing = -1;
53#endif
54
55
56/* Called by modules package when installing the driver
57 * or by kernel during the initialization phase
58 */
59static int __init ftape_init(void)
60{
61 TRACE_FUN(ft_t_flow);
62
63#ifdef MODULE
64#ifndef CONFIG_FT_NO_TRACE_AT_ALL
65 if (ft_tracing != -1) {
66 ftape_tracing = ft_tracing;
67 }
68#endif
69 printk(KERN_INFO FTAPE_VERSION "\n");
70 if (TRACE_LEVEL >= ft_t_info) {
71 printk(
72KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n"
73KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n"
74KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
75KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n");
76 }
77#else /* !MODULE */
78 /* print a short no-nonsense boot message */
79 printk(KERN_INFO FTAPE_VERSION "\n");
80#endif /* MODULE */
81 TRACE(ft_t_info, "installing QIC-117 floppy tape hardware drive ... ");
82 TRACE(ft_t_info, "ftape_init @ 0x%p", ftape_init);
83 /* Allocate the DMA buffers. They are deallocated at cleanup() time.
84 */
85#ifdef TESTING
86#ifdef MODULE
87 while (ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS) < 0) {
88 ftape_sleep(FT_SECOND/20);
89 if (signal_pending(current)) {
90 (void)ftape_set_nr_buffers(0);
91 TRACE(ft_t_bug,
92 "Killed by signal while allocating buffers.");
93 TRACE_ABORT(-EINTR,
94 ft_t_bug, "Free up memory and retry");
95 }
96 }
97#else
98 TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),
99 (void)ftape_set_nr_buffers(0));
100#endif
101#else
102 TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),
103 (void)ftape_set_nr_buffers(0));
104#endif
105 ft_drive_sel = -1;
106 ft_failure = 1; /* inhibit any operation but open */
107 ftape_udelay_calibrate(); /* must be before fdc_wait_calibrate ! */
108 fdc_wait_calibrate();
109#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
110 (void)ftape_proc_init();
111#endif
112#ifdef CONFIG_ZFTAPE
113 (void)zft_init();
114#endif
115 TRACE_EXIT 0;
116}
117
118module_param(ft_fdc_base, uint, 0);
119MODULE_PARM_DESC(ft_fdc_base, "Base address of FDC controller.");
120module_param(ft_fdc_irq, uint, 0);
121MODULE_PARM_DESC(ft_fdc_irq, "IRQ (interrupt channel) to use.");
122module_param(ft_fdc_dma, uint, 0);
123MODULE_PARM_DESC(ft_fdc_dma, "DMA channel to use.");
124module_param(ft_fdc_threshold, uint, 0);
125MODULE_PARM_DESC(ft_fdc_threshold, "Threshold of the FDC Fifo.");
126module_param(ft_fdc_rate_limit, uint, 0);
127MODULE_PARM_DESC(ft_fdc_rate_limit, "Maximal data rate for FDC.");
128module_param(ft_probe_fc10, bool, 0);
129MODULE_PARM_DESC(ft_probe_fc10,
130 "If non-zero, probe for a Colorado FC-10/FC-20 controller.");
131module_param(ft_mach2, bool, 0);
132MODULE_PARM_DESC(ft_mach2,
133 "If non-zero, probe for a Mountain MACH-2 controller.");
134#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)
135module_param(ft_tracing, int, 0644);
136MODULE_PARM_DESC(ft_tracing,
137 "Amount of debugging output, 0 <= tracing <= 8, default 3.");
138#endif
139
140MODULE_AUTHOR(
141 "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl), "
142 "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no), "
143 "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)");
144MODULE_DESCRIPTION(
145 "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives.");
146MODULE_LICENSE("GPL");
147
148static void __exit ftape_exit(void)
149{
150 TRACE_FUN(ft_t_flow);
151
152#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
153 ftape_proc_destroy();
154#endif
155 (void)ftape_set_nr_buffers(0);
156 printk(KERN_INFO "ftape: unloaded.\n");
157 TRACE_EXIT;
158}
159
160module_init(ftape_init);
161module_exit(ftape_exit);
diff --git a/drivers/char/ftape/lowlevel/ftape-init.h b/drivers/char/ftape/lowlevel/ftape-init.h
new file mode 100644
index 000000000000..99a7b8ab086f
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-init.h
@@ -0,0 +1,43 @@
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
new file mode 100644
index 000000000000..259015aeff55
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-io.c
@@ -0,0 +1,992 @@
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
new file mode 100644
index 000000000000..26a7baad8717
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-io.h
@@ -0,0 +1,90 @@
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
new file mode 100644
index 000000000000..c66251e997ed
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-proc.c
@@ -0,0 +1,215 @@
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#include <linux/config.h>
30
31#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
32
33#include <linux/proc_fs.h>
34
35#include <linux/ftape.h>
36#include <linux/init.h>
37#include <linux/qic117.h>
38
39#include "../lowlevel/ftape-io.h"
40#include "../lowlevel/ftape-ctl.h"
41#include "../lowlevel/ftape-proc.h"
42#include "../lowlevel/ftape-tracing.h"
43
44static size_t get_driver_info(char *buf)
45{
46 const char *debug_level[] = { "bugs" ,
47 "errors",
48 "warnings",
49 "informational",
50 "noisy",
51 "program flow",
52 "fdc and dma",
53 "data flow",
54 "anything" };
55
56 return sprintf(buf,
57 "version : %s\n"
58 "used data rate: %d kbit/sec\n"
59 "dma memory : %d kb\n"
60 "debug messages: %s\n",
61 FTAPE_VERSION,
62 ft_data_rate,
63 FT_BUFF_SIZE * ft_nr_buffers >> 10,
64 debug_level[TRACE_LEVEL]);
65}
66
67static size_t get_tapedrive_info(char *buf)
68{
69 return sprintf(buf,
70 "vendor id : 0x%04x\n"
71 "drive name: %s\n"
72 "wind speed: %d ips\n"
73 "wakeup : %s\n"
74 "max. rate : %d kbit/sec\n",
75 ft_drive_type.vendor_id,
76 ft_drive_type.name,
77 ft_drive_type.speed,
78 ((ft_drive_type.wake_up == no_wake_up)
79 ? "No wakeup needed" :
80 ((ft_drive_type.wake_up == wake_up_colorado)
81 ? "Colorado" :
82 ((ft_drive_type.wake_up == wake_up_mountain)
83 ? "Mountain" :
84 ((ft_drive_type.wake_up == wake_up_insight)
85 ? "Motor on" :
86 "Unknown")))),
87 ft_drive_max_rate);
88}
89
90static size_t get_cartridge_info(char *buf)
91{
92 if (ftape_init_drive_needed) {
93 return sprintf(buf, "uninitialized\n");
94 }
95 if (ft_no_tape) {
96 return sprintf(buf, "no cartridge inserted\n");
97 }
98 return sprintf(buf,
99 "segments : %5d\n"
100 "tracks : %5d\n"
101 "length : %5dft\n"
102 "formatted : %3s\n"
103 "writable : %3s\n"
104 "QIC spec. : QIC-%s\n"
105 "fmt-code : %1d\n",
106 ft_segments_per_track,
107 ft_tracks_per_tape,
108 ftape_tape_len,
109 (ft_formatted == 1) ? "yes" : "no",
110 (ft_write_protected == 1) ? "no" : "yes",
111 ((ft_qic_std == QIC_TAPE_QIC40) ? "40" :
112 ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :
113 ((ft_qic_std == QIC_TAPE_QIC3010) ? "3010" :
114 ((ft_qic_std == QIC_TAPE_QIC3020) ? "3020" :
115 "???")))),
116 ft_format_code);
117}
118
119static size_t get_controller_info(char *buf)
120{
121 const char *fdc_name[] = { "no fdc",
122 "i8272",
123 "i82077",
124 "i82077AA",
125 "Colorado FC-10 or FC-20",
126 "i82078",
127 "i82078_1" };
128
129 return sprintf(buf,
130 "FDC type : %s\n"
131 "FDC base : 0x%03x\n"
132 "FDC irq : %d\n"
133 "FDC dma : %d\n"
134 "FDC thr. : %d\n"
135 "max. rate : %d kbit/sec\n",
136 ft_mach2 ? "Mountain MACH-2" : fdc_name[fdc.type],
137 fdc.sra, fdc.irq, fdc.dma,
138 ft_fdc_threshold, ft_fdc_max_rate);
139}
140
141static size_t get_history_info(char *buf)
142{
143 size_t len;
144
145 len = sprintf(buf,
146 "\nFDC isr statistics\n"
147 " id_am_errors : %3d\n"
148 " id_crc_errors : %3d\n"
149 " data_am_errors : %3d\n"
150 " data_crc_errors : %3d\n"
151 " overrun_errors : %3d\n"
152 " no_data_errors : %3d\n"
153 " retries : %3d\n",
154 ft_history.id_am_errors, ft_history.id_crc_errors,
155 ft_history.data_am_errors, ft_history.data_crc_errors,
156 ft_history.overrun_errors, ft_history.no_data_errors,
157 ft_history.retries);
158 len += sprintf(buf + len,
159 "\nECC statistics\n"
160 " crc_errors : %3d\n"
161 " crc_failures : %3d\n"
162 " ecc_failures : %3d\n"
163 " sectors corrected: %3d\n",
164 ft_history.crc_errors, ft_history.crc_failures,
165 ft_history.ecc_failures, ft_history.corrected);
166 len += sprintf(buf + len,
167 "\ntape quality statistics\n"
168 " media defects : %3d\n",
169 ft_history.defects);
170 len += sprintf(buf + len,
171 "\ntape motion statistics\n"
172 " repositions : %3d\n",
173 ft_history.rewinds);
174 return len;
175}
176
177static int ftape_read_proc(char *page, char **start, off_t off,
178 int count, int *eof, void *data)
179{
180 char *ptr = page;
181 size_t len;
182
183 ptr += sprintf(ptr, "Kernel Driver\n\n");
184 ptr += get_driver_info(ptr);
185 ptr += sprintf(ptr, "\nTape Drive\n\n");
186 ptr += get_tapedrive_info(ptr);
187 ptr += sprintf(ptr, "\nFDC Controller\n\n");
188 ptr += get_controller_info(ptr);
189 ptr += sprintf(ptr, "\nTape Cartridge\n\n");
190 ptr += get_cartridge_info(ptr);
191 ptr += sprintf(ptr, "\nHistory Record\n\n");
192 ptr += get_history_info(ptr);
193
194 len = strlen(page);
195 *start = NULL;
196 if (off+count >= len) {
197 *eof = 1;
198 } else {
199 *eof = 0;
200 }
201 return len;
202}
203
204int __init ftape_proc_init(void)
205{
206 return create_proc_read_entry("ftape", 0, &proc_root,
207 ftape_read_proc, NULL) != NULL;
208}
209
210void ftape_proc_destroy(void)
211{
212 remove_proc_entry("ftape", &proc_root);
213}
214
215#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
new file mode 100644
index 000000000000..264dfcc1d22d
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-proc.h
@@ -0,0 +1,35 @@
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
new file mode 100644
index 000000000000..d967d8cd86dc
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-read.c
@@ -0,0 +1,621 @@
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
new file mode 100644
index 000000000000..069f99f2a984
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-read.h
@@ -0,0 +1,51 @@
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
new file mode 100644
index 000000000000..c0d6dc2cbfd3
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-rw.c
@@ -0,0 +1,1092 @@
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
new file mode 100644
index 000000000000..32f4feeb887c
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-rw.h
@@ -0,0 +1,111 @@
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
new file mode 100644
index 000000000000..280a1a55d87e
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-setup.c
@@ -0,0 +1,105 @@
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/config.h>
29#include <linux/string.h>
30#include <linux/errno.h>
31#include <linux/mm.h>
32
33#include <linux/ftape.h>
34#include <linux/init.h>
35#include "../lowlevel/ftape-tracing.h"
36#include "../lowlevel/fdc-io.h"
37
38static struct param_table {
39 const char *name;
40 int *var;
41 int def_param;
42 int min;
43 int max;
44} config_params[] __initdata = {
45#ifndef CONFIG_FT_NO_TRACE_AT_ALL
46 { "tracing", &ftape_tracing, 3, ft_t_bug, ft_t_any},
47#endif
48 { "ioport", &ft_fdc_base, CONFIG_FT_FDC_BASE, 0x0, 0xfff},
49 { "irq", &ft_fdc_irq, CONFIG_FT_FDC_IRQ, 2, 15},
50 { "dma", &ft_fdc_dma, CONFIG_FT_FDC_DMA, 0, 3},
51 { "threshold", &ft_fdc_threshold, CONFIG_FT_FDC_THR, 1, 16},
52 { "datarate", &ft_fdc_rate_limit, CONFIG_FT_FDC_MAX_RATE, 500, 2000},
53 { "fc10", &ft_probe_fc10, CONFIG_FT_PROBE_FC10, 0, 1},
54 { "mach2", &ft_mach2, CONFIG_FT_MACH2, 0, 1}
55};
56
57static int __init ftape_setup(char *str)
58{
59 int i;
60 int param;
61 int ints[2];
62
63 TRACE_FUN(ft_t_flow);
64
65 str = get_options(str, ARRAY_SIZE(ints), ints);
66 if (str) {
67 for (i=0; i < NR_ITEMS(config_params); i++) {
68 if (strcmp(str,config_params[i].name) == 0){
69 if (ints[0]) {
70 param = ints[1];
71 } else {
72 param = config_params[i].def_param;
73 }
74 if (param < config_params[i].min ||
75 param > config_params[i].max) {
76 TRACE(ft_t_err,
77 "parameter %s out of range %d ... %d",
78 config_params[i].name,
79 config_params[i].min,
80 config_params[i].max);
81 goto out;
82 }
83 if(config_params[i].var) {
84 TRACE(ft_t_info, "%s=%d", str, param);
85 *config_params[i].var = param;
86 }
87 goto out;
88 }
89 }
90 }
91 if (str) {
92 TRACE(ft_t_err, "unknown ftape option [%s]", str);
93
94 TRACE(ft_t_err, "allowed options are:");
95 for (i=0; i < NR_ITEMS(config_params); i++) {
96 TRACE(ft_t_err, " %s",config_params[i].name);
97 }
98 } else {
99 TRACE(ft_t_err, "botched ftape option");
100 }
101 out:
102 TRACE_EXIT 1;
103}
104
105__setup("ftape=", ftape_setup);
diff --git a/drivers/char/ftape/lowlevel/ftape-tracing.c b/drivers/char/ftape/lowlevel/ftape-tracing.c
new file mode 100644
index 000000000000..7fdc6567440b
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-tracing.c
@@ -0,0 +1,118 @@
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
new file mode 100644
index 000000000000..fa7cd20ee66c
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-tracing.h
@@ -0,0 +1,180 @@
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/config.h>
32#include <linux/kernel.h>
33
34/*
35 * Be very careful with TRACE_EXIT and TRACE_ABORT.
36 *
37 * if (something) TRACE_EXIT error;
38 *
39 * will NOT work. Use
40 *
41 * if (something) {
42 * TRACE_EXIT error;
43 * }
44 *
45 * instead. Maybe a bit dangerous, but save lots of lines of code.
46 */
47
48#define LL_X "%d/%d KB"
49#define LL(x) (unsigned int)((__u64)(x)>>10), (unsigned int)((x)&1023)
50
51typedef enum {
52 ft_t_nil = -1,
53 ft_t_bug,
54 ft_t_err,
55 ft_t_warn,
56 ft_t_info,
57 ft_t_noise,
58 ft_t_flow,
59 ft_t_fdc_dma,
60 ft_t_data_flow,
61 ft_t_any
62} ft_trace_t;
63
64#ifdef CONFIG_FT_NO_TRACE_AT_ALL
65/* the compiler will optimize away most TRACE() macros
66 */
67#define FT_TRACE_TOP_LEVEL ft_t_bug
68#define TRACE_FUN(level) do {} while(0)
69#define TRACE_EXIT return
70#define TRACE(l, m, i...) \
71{ \
72 if ((ft_trace_t)(l) == FT_TRACE_TOP_LEVEL) { \
73 printk(KERN_INFO"ftape%s(%s):\n" \
74 KERN_INFO m".\n" ,__FILE__, __FUNCTION__ , ##i); \
75 } \
76}
77#define SET_TRACE_LEVEL(l) if ((l) == (l)) do {} while(0)
78#define TRACE_LEVEL FT_TRACE_TOP_LEVEL
79
80#else
81
82#ifdef CONFIG_FT_NO_TRACE
83/* the compiler will optimize away many TRACE() macros
84 * the ftape_simple_trace_call() function simply increments
85 * the function nest level.
86 */
87#define FT_TRACE_TOP_LEVEL ft_t_warn
88#define TRACE_FUN(level) ftape_function_nest_level++
89#define TRACE_EXIT ftape_function_nest_level--; return
90
91#else
92#ifdef CONFIG_FT_FULL_DEBUG
93#define FT_TRACE_TOP_LEVEL ft_t_any
94#else
95#define FT_TRACE_TOP_LEVEL ft_t_flow
96#endif
97#define TRACE_FUN(level) \
98 const ft_trace_t _tracing = level; \
99 if (ftape_tracing >= (ft_trace_t)(level) && \
100 (ft_trace_t)(level) <= FT_TRACE_TOP_LEVEL) \
101 ftape_trace_call(__FILE__, __FUNCTION__); \
102 ftape_function_nest_level ++;
103
104#define TRACE_EXIT \
105 --ftape_function_nest_level; \
106 if (ftape_tracing >= (ft_trace_t)(_tracing) && \
107 (ft_trace_t)(_tracing) <= FT_TRACE_TOP_LEVEL) \
108 ftape_trace_exit(__FILE__, __FUNCTION__); \
109 return
110
111#endif
112
113#define TRACE(l, m, i...) \
114{ \
115 if (ftape_tracing >= (ft_trace_t)(l) && \
116 (ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \
117 ftape_trace_log(__FILE__, __FUNCTION__); \
118 printk(m".\n" ,##i); \
119 } \
120}
121
122#define SET_TRACE_LEVEL(l) \
123{ \
124 if ((ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \
125 ftape_tracing = (ft_trace_t)(l); \
126 } else { \
127 ftape_tracing = FT_TRACE_TOP_LEVEL; \
128 } \
129}
130#define TRACE_LEVEL \
131((ftape_tracing <= FT_TRACE_TOP_LEVEL) ? ftape_tracing : FT_TRACE_TOP_LEVEL)
132
133
134/* Global variables declared in tracing.c
135 */
136extern ft_trace_t ftape_tracing; /* sets default level */
137extern int ftape_function_nest_level;
138
139/* Global functions declared in tracing.c
140 */
141extern void ftape_trace_call(const char *file, const char *name);
142extern void ftape_trace_exit(const char *file, const char *name);
143extern void ftape_trace_log (const char *file, const char *name);
144
145#endif /* !defined(CONFIG_FT_NO_TRACE_AT_ALL) */
146
147/*
148 * Abort with a message.
149 */
150#define TRACE_ABORT(res, i...) \
151{ \
152 TRACE(i); \
153 TRACE_EXIT res; \
154}
155
156/* The following transforms the common "if(result < 0) ... " into a
157 * one-liner.
158 */
159#define _TRACE_CATCH(level, fun, action) \
160{ \
161 int _res = (fun); \
162 if (_res < 0) { \
163 do { action /* */ ; } while(0); \
164 TRACE_ABORT(_res, level, "%s failed: %d", #fun, _res); \
165 } \
166}
167
168#define TRACE_CATCH(fun, fail) _TRACE_CATCH(ft_t_err, fun, fail)
169
170/* Abort the current function when signalled. This doesn't belong here,
171 * but rather into ftape-rw.h (maybe)
172 */
173#define FT_SIGNAL_EXIT(sig_mask) \
174 if (sigtestsetmask(&current->pending.signal, sig_mask)) { \
175 TRACE_ABORT(-EINTR, \
176 ft_t_warn, \
177 "interrupted by non-blockable signal"); \
178 }
179
180#endif /* _FTAPE_TRACING_H */
diff --git a/drivers/char/ftape/lowlevel/ftape-write.c b/drivers/char/ftape/lowlevel/ftape-write.c
new file mode 100644
index 000000000000..45601ec801ee
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-write.c
@@ -0,0 +1,336 @@
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
new file mode 100644
index 000000000000..0e7f898b7af9
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape-write.h
@@ -0,0 +1,53 @@
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
new file mode 100644
index 000000000000..5dc3a380c9bf
--- /dev/null
+++ b/drivers/char/ftape/lowlevel/ftape_syms.c
@@ -0,0 +1,88 @@
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/config.h>
29#include <linux/module.h>
30
31#include <linux/ftape.h>
32#include "../lowlevel/ftape-tracing.h"
33#include "../lowlevel/ftape-init.h"
34#include "../lowlevel/fdc-io.h"
35#include "../lowlevel/ftape-read.h"
36#include "../lowlevel/ftape-write.h"
37#include "../lowlevel/ftape-io.h"
38#include "../lowlevel/ftape-ctl.h"
39#include "../lowlevel/ftape-rw.h"
40#include "../lowlevel/ftape-bsm.h"
41#include "../lowlevel/ftape-buffer.h"
42#include "../lowlevel/ftape-format.h"
43
44/* bad sector handling from ftape-bsm.c */
45EXPORT_SYMBOL(ftape_get_bad_sector_entry);
46EXPORT_SYMBOL(ftape_find_end_of_bsm_list);
47/* from ftape-rw.c */
48EXPORT_SYMBOL(ftape_set_state);
49/* from ftape-ctl.c */
50EXPORT_SYMBOL(ftape_seek_to_bot);
51EXPORT_SYMBOL(ftape_seek_to_eot);
52EXPORT_SYMBOL(ftape_abort_operation);
53EXPORT_SYMBOL(ftape_get_status);
54EXPORT_SYMBOL(ftape_enable);
55EXPORT_SYMBOL(ftape_disable);
56EXPORT_SYMBOL(ftape_mmap);
57EXPORT_SYMBOL(ftape_calibrate_data_rate);
58/* from ftape-io.c */
59EXPORT_SYMBOL(ftape_reset_drive);
60EXPORT_SYMBOL(ftape_command);
61EXPORT_SYMBOL(ftape_parameter);
62EXPORT_SYMBOL(ftape_ready_wait);
63EXPORT_SYMBOL(ftape_report_operation);
64EXPORT_SYMBOL(ftape_report_error);
65/* from ftape-read.c */
66EXPORT_SYMBOL(ftape_read_segment_fraction);
67EXPORT_SYMBOL(ftape_zap_read_buffers);
68EXPORT_SYMBOL(ftape_read_header_segment);
69EXPORT_SYMBOL(ftape_decode_header_segment);
70/* from ftape-write.c */
71EXPORT_SYMBOL(ftape_write_segment);
72EXPORT_SYMBOL(ftape_start_writing);
73EXPORT_SYMBOL(ftape_loop_until_writes_done);
74/* from ftape-buffer.h */
75EXPORT_SYMBOL(ftape_set_nr_buffers);
76/* from ftape-format.h */
77EXPORT_SYMBOL(ftape_format_track);
78EXPORT_SYMBOL(ftape_format_status);
79EXPORT_SYMBOL(ftape_verify_segment);
80/* from tracing.c */
81#ifndef CONFIG_FT_NO_TRACE_AT_ALL
82EXPORT_SYMBOL(ftape_tracing);
83EXPORT_SYMBOL(ftape_function_nest_level);
84EXPORT_SYMBOL(ftape_trace_call);
85EXPORT_SYMBOL(ftape_trace_exit);
86EXPORT_SYMBOL(ftape_trace_log);
87#endif
88
diff --git a/drivers/char/ftape/zftape/Makefile b/drivers/char/ftape/zftape/Makefile
new file mode 100644
index 000000000000..6d91c1f77c05
--- /dev/null
+++ b/drivers/char/ftape/zftape/Makefile
@@ -0,0 +1,36 @@
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
new file mode 100644
index 000000000000..da06f138334e
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-buffers.c
@@ -0,0 +1,149 @@
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, %d 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, %d 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
new file mode 100644
index 000000000000..798e3128c682
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-buffers.h
@@ -0,0 +1,55 @@
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
new file mode 100644
index 000000000000..6c7874e5c199
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-ctl.c
@@ -0,0 +1,1418 @@
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/config.h>
28#include <linux/errno.h>
29#include <linux/mm.h>
30#include <linux/module.h>
31#include <linux/fcntl.h>
32
33#include <linux/zftape.h>
34
35#include <asm/uaccess.h>
36
37#include "../zftape/zftape-init.h"
38#include "../zftape/zftape-eof.h"
39#include "../zftape/zftape-ctl.h"
40#include "../zftape/zftape-write.h"
41#include "../zftape/zftape-read.h"
42#include "../zftape/zftape-rw.h"
43#include "../zftape/zftape-vtbl.h"
44
45/* Global vars.
46 */
47int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */
48int zft_header_read;
49int zft_offline;
50unsigned int zft_unit;
51int zft_resid;
52int zft_mt_compression;
53
54/* Local vars.
55 */
56static int going_offline;
57
58typedef int (mt_fun)(int *argptr);
59typedef int (*mt_funp)(int *argptr);
60typedef struct
61{
62 mt_funp function;
63 unsigned offline : 1; /* op permitted if offline or no_tape */
64 unsigned write_protected : 1; /* op permitted if write-protected */
65 unsigned not_formatted : 1; /* op permitted if tape not formatted */
66 unsigned raw_mode : 1; /* op permitted if zft_mode == 0 */
67 unsigned need_idle_state : 1; /* need to call def_idle_state */
68 char *name;
69} fun_entry;
70
71static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop,
72 mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity,
73 mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf,
74 mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression;
75
76static fun_entry mt_funs[]=
77{
78 {mt_reset , 1, 1, 1, 1, 0, "MT_RESET" }, /* 0 */
79 {mt_fsf , 0, 1, 0, 0, 1, "MT_FSF" },
80 {mt_bsf , 0, 1, 0, 0, 1, "MT_BSF" },
81 {mt_fsr , 0, 1, 0, 1, 1, "MT_FSR" },
82 {mt_bsr , 0, 1, 0, 1, 1, "MT_BSR" },
83 {mt_weof , 0, 0, 0, 0, 0, "MT_WEOF" }, /* 5 */
84 {mt_rew , 0, 1, 1, 1, 0, "MT_REW" },
85 {mt_offl , 0, 1, 1, 1, 0, "MT_OFFL" },
86 {mt_nop , 1, 1, 1, 1, 0, "MT_NOP" },
87 {mt_reten , 0, 1, 1, 1, 0, "MT_RETEN" },
88 {mt_bsfm , 0, 1, 0, 0, 1, "MT_BSFM" }, /* 10 */
89 {mt_fsfm , 0, 1, 0, 0, 1, "MT_FSFM" },
90 {mt_eom , 0, 1, 0, 0, 1, "MT_EOM" },
91 {mt_erase , 0, 0, 0, 1, 0, "MT_ERASE" },
92 {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS1" },
93 {mt_ras2 , 0, 0, 0, 1, 0, "MT_RAS2" },
94 {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS3" },
95 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
96 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
97 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
98 {mt_setblk , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */
99 {mt_setdensity , 1, 1, 1, 1, 0, "MT_SETDENSITY"},
100 {mt_seek , 0, 1, 0, 1, 1, "MT_SEEK" },
101 {mt_dummy , 0, 1, 0, 1, 1, "MT_TELL" }, /* wr-only ?! */
102 {mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" },
103 {mt_dummy , 1, 1, 1, 1, 0, "MT_FSS" }, /* 25 */
104 {mt_dummy , 1, 1, 1, 1, 0, "MT_BSS" },
105 {mt_dummy , 1, 1, 1, 1, 0, "MT_WSM" },
106 {mt_dummy , 1, 1, 1, 1, 0, "MT_LOCK" },
107 {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOCK"},
108 {mt_dummy , 1, 1, 1, 1, 0, "MT_LOAD" }, /* 30 */
109 {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOAD"},
110 {mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"},
111 {mt_dummy , 1, 1, 1, 1, 0, "MT_SETPART"},
112 {mt_dummy , 1, 1, 1, 1, 0, "MT_MKPART"}
113};
114
115#define NR_MT_CMDS NR_ITEMS(mt_funs)
116
117void zft_reset_position(zft_position *pos)
118{
119 TRACE_FUN(ft_t_flow);
120
121 pos->seg_byte_pos =
122 pos->volume_pos = 0;
123 if (zft_header_read) {
124 /* need to keep track of the volume table and
125 * compression map. We therefor simply
126 * position at the beginning of the first
127 * volume. This covers old ftape archives as
128 * well has various flavours of the
129 * compression map segments. The worst case is
130 * that the compression map shows up as a
131 * additional volume in front of all others.
132 */
133 pos->seg_pos = zft_find_volume(0)->start_seg;
134 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
135 } else {
136 pos->tape_pos = 0;
137 pos->seg_pos = -1;
138 }
139 zft_just_before_eof = 0;
140 zft_deblock_segment = -1;
141 zft_io_state = zft_idle;
142 zft_zap_read_buffers();
143 zft_prevent_flush();
144 /* unlock the compresison module if it is loaded.
145 * The zero arg means not to try to load the module.
146 */
147 if (zft_cmpr_lock(0) == 0) {
148 (*zft_cmpr_ops->reset)(); /* unlock */
149 }
150 TRACE_EXIT;
151}
152
153static void zft_init_driver(void)
154{
155 TRACE_FUN(ft_t_flow);
156
157 zft_resid =
158 zft_header_read =
159 zft_old_ftape =
160 zft_offline =
161 zft_write_protected =
162 going_offline =
163 zft_mt_compression =
164 zft_header_changed =
165 zft_volume_table_changed =
166 zft_written_segments = 0;
167 zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
168 zft_reset_position(&zft_pos); /* does most of the stuff */
169 ftape_zap_read_buffers();
170 ftape_set_state(idle);
171 TRACE_EXIT;
172}
173
174int zft_def_idle_state(void)
175{
176 int result = 0;
177 TRACE_FUN(ft_t_flow);
178
179 if (!zft_header_read) {
180 result = zft_read_header_segments();
181 } else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) {
182 /* don't move past eof
183 */
184 (void)zft_close_volume(&zft_pos);
185 }
186 if (ftape_abort_operation() < 0) {
187 TRACE(ft_t_warn, "ftape_abort_operation() failed");
188 result = -EIO;
189 }
190 /* clear remaining read buffers */
191 zft_zap_read_buffers();
192 zft_io_state = zft_idle;
193 TRACE_EXIT result;
194}
195
196/*****************************************************************************
197 * *
198 * functions for the MTIOCTOP commands *
199 * *
200 *****************************************************************************/
201
202static int mt_dummy(int *dummy)
203{
204 TRACE_FUN(ft_t_flow);
205
206 TRACE_EXIT -ENOSYS;
207}
208
209static int mt_reset(int *dummy)
210{
211 TRACE_FUN(ft_t_flow);
212
213 (void)ftape_seek_to_bot();
214 TRACE_CATCH(ftape_reset_drive(),
215 zft_init_driver(); zft_uninit_mem(); zft_offline = 1);
216 /* fake a re-open of the device. This will set all flage and
217 * allocate buffers as appropriate. The new tape condition will
218 * force the open routine to do anything we need.
219 */
220 TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),);
221 TRACE_EXIT 0;
222}
223
224static int mt_fsf(int *arg)
225{
226 int result;
227 TRACE_FUN(ft_t_flow);
228
229 result = zft_skip_volumes(*arg, &zft_pos);
230 zft_just_before_eof = 0;
231 TRACE_EXIT result;
232}
233
234static int mt_bsf(int *arg)
235{
236 int result = 0;
237 TRACE_FUN(ft_t_flow);
238
239 if (*arg != 0) {
240 result = zft_skip_volumes(-*arg + 1, &zft_pos);
241 }
242 TRACE_EXIT result;
243}
244
245static int seek_block(__s64 data_offset,
246 __s64 block_increment,
247 zft_position *pos)
248{
249 int result = 0;
250 __s64 new_block_pos;
251 __s64 vol_block_count;
252 const zft_volinfo *volume;
253 int exceed;
254 TRACE_FUN(ft_t_flow);
255
256 volume = zft_find_volume(pos->seg_pos);
257 if (volume->start_seg == 0 || volume->end_seg == 0) {
258 TRACE_EXIT -EIO;
259 }
260 new_block_pos = (zft_div_blksz(data_offset, volume->blk_sz)
261 + block_increment);
262 vol_block_count = zft_div_blksz(volume->size, volume->blk_sz);
263 if (new_block_pos < 0) {
264 TRACE(ft_t_noise,
265 "new_block_pos " LL_X " < 0", LL(new_block_pos));
266 zft_resid = (int)new_block_pos;
267 new_block_pos = 0;
268 exceed = 1;
269 } else if (new_block_pos > vol_block_count) {
270 TRACE(ft_t_noise,
271 "new_block_pos " LL_X " exceeds size of volume " LL_X,
272 LL(new_block_pos), LL(vol_block_count));
273 zft_resid = (int)(vol_block_count - new_block_pos);
274 new_block_pos = vol_block_count;
275 exceed = 1;
276 } else {
277 exceed = 0;
278 }
279 if (zft_use_compression && volume->use_compression) {
280 TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
281 result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume,
282 zft_deblock_buf);
283 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
284 pos->tape_pos += pos->seg_byte_pos;
285 } else {
286 pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz);
287 pos->tape_pos = zft_calc_tape_pos(volume->start_seg);
288 pos->tape_pos += pos->volume_pos;
289 pos->seg_pos = zft_calc_seg_byte_coord(&pos->seg_byte_pos,
290 pos->tape_pos);
291 }
292 zft_just_before_eof = volume->size == pos->volume_pos;
293 if (zft_just_before_eof) {
294 /* why this? because zft_file_no checks agains start
295 * and end segment of a volume. We do not want to
296 * advance to the next volume with this function.
297 */
298 TRACE(ft_t_noise, "set zft_just_before_eof");
299 zft_position_before_eof(pos, volume);
300 }
301 TRACE(ft_t_noise, "\n"
302 KERN_INFO "new_seg_pos : %d\n"
303 KERN_INFO "new_tape_pos: " LL_X "\n"
304 KERN_INFO "vol_size : " LL_X "\n"
305 KERN_INFO "seg_byte_pos: %d\n"
306 KERN_INFO "blk_sz : %d",
307 pos->seg_pos, LL(pos->tape_pos),
308 LL(volume->size), pos->seg_byte_pos,
309 volume->blk_sz);
310 if (!exceed) {
311 zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos,
312 volume->blk_sz);
313 }
314 if (zft_resid < 0) {
315 zft_resid = -zft_resid;
316 }
317 TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result;
318}
319
320static int mt_fsr(int *arg)
321{
322 int result;
323 TRACE_FUN(ft_t_flow);
324
325 result = seek_block(zft_pos.volume_pos, *arg, &zft_pos);
326 TRACE_EXIT result;
327}
328
329static int mt_bsr(int *arg)
330{
331 int result;
332 TRACE_FUN(ft_t_flow);
333
334 result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos);
335 TRACE_EXIT result;
336}
337
338static int mt_weof(int *arg)
339{
340 int result;
341 TRACE_FUN(ft_t_flow);
342
343 TRACE_CATCH(zft_flush_buffers(),);
344 result = zft_weof(*arg, &zft_pos);
345 TRACE_EXIT result;
346}
347
348static int mt_rew(int *dummy)
349{
350 int result;
351 TRACE_FUN(ft_t_flow);
352
353 if(zft_header_read) {
354 (void)zft_def_idle_state();
355 }
356 result = ftape_seek_to_bot();
357 zft_reset_position(&zft_pos);
358 TRACE_EXIT result;
359}
360
361static int mt_offl(int *dummy)
362{
363 int result;
364 TRACE_FUN(ft_t_flow);
365
366 going_offline= 1;
367 result = mt_rew(NULL);
368 TRACE_EXIT result;
369}
370
371static int mt_nop(int *dummy)
372{
373 TRACE_FUN(ft_t_flow);
374 /* should we set tape status?
375 */
376 if (!zft_offline) { /* offline includes no_tape */
377 (void)zft_def_idle_state();
378 }
379 TRACE_EXIT 0;
380}
381
382static int mt_reten(int *dummy)
383{
384 int result;
385 TRACE_FUN(ft_t_flow);
386
387 if(zft_header_read) {
388 (void)zft_def_idle_state();
389 }
390 result = ftape_seek_to_eot();
391 if (result >= 0) {
392 result = ftape_seek_to_bot();
393 }
394 TRACE_EXIT(result);
395}
396
397static int fsfbsfm(int arg, zft_position *pos)
398{
399 const zft_volinfo *vtbl;
400 __s64 block_pos;
401 TRACE_FUN(ft_t_flow);
402
403 /* What to do? This should seek to the next file-mark and
404 * position BEFORE. That is, a next write would just extend
405 * the current file. Well. Let's just seek to the end of the
406 * current file, if count == 1. If count > 1, then do a
407 * "mt_fsf(count - 1)", and then seek to the end of that file.
408 * If count == 0, do nothing
409 */
410 if (arg == 0) {
411 TRACE_EXIT 0;
412 }
413 zft_just_before_eof = 0;
414 TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos),
415 if (arg > 0) {
416 zft_resid ++;
417 });
418 vtbl = zft_find_volume(pos->seg_pos);
419 block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz);
420 (void)seek_block(0, block_pos, pos);
421 if (pos->volume_pos != vtbl->size) {
422 zft_just_before_eof = 0;
423 zft_resid = 1;
424 /* we didn't managed to go there */
425 TRACE_ABORT(-EIO, ft_t_err,
426 "wanted file position " LL_X ", arrived at " LL_X,
427 LL(vtbl->size), LL(pos->volume_pos));
428 }
429 zft_just_before_eof = 1;
430 TRACE_EXIT 0;
431}
432
433static int mt_bsfm(int *arg)
434{
435 int result;
436 TRACE_FUN(ft_t_flow);
437
438 result = fsfbsfm(-*arg, &zft_pos);
439 TRACE_EXIT result;
440}
441
442static int mt_fsfm(int *arg)
443{
444 int result;
445 TRACE_FUN(ft_t_flow);
446
447 result = fsfbsfm(*arg, &zft_pos);
448 TRACE_EXIT result;
449}
450
451static int mt_eom(int *dummy)
452{
453 TRACE_FUN(ft_t_flow);
454
455 zft_skip_to_eom(&zft_pos);
456 TRACE_EXIT 0;
457}
458
459static int mt_erase(int *dummy)
460{
461 int result;
462 TRACE_FUN(ft_t_flow);
463
464 result = zft_erase();
465 TRACE_EXIT result;
466}
467
468static int mt_ras2(int *dummy)
469{
470 int result;
471 TRACE_FUN(ft_t_flow);
472
473 result = -ENOSYS;
474 TRACE_EXIT result;
475}
476
477/* Sets the new blocksize in BYTES
478 *
479 */
480static int mt_setblk(int *new_size)
481{
482 TRACE_FUN(ft_t_flow);
483
484 if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) {
485 TRACE_ABORT(-EINVAL, ft_t_info,
486 "desired blk_sz (%d) should be <= %d bytes",
487 *new_size, ZFT_MAX_BLK_SZ);
488 }
489 if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) {
490 TRACE_ABORT(-EINVAL, ft_t_info,
491 "desired blk_sz (%d) must be a multiple of %d bytes",
492 *new_size, FT_SECTOR_SIZE);
493 }
494 if (*new_size == 0) {
495 if (zft_use_compression) {
496 TRACE_ABORT(-EINVAL, ft_t_info,
497 "Variable block size not yet "
498 "supported with compression");
499 }
500 *new_size = 1;
501 }
502 zft_blk_sz = *new_size;
503 TRACE_EXIT 0;
504}
505
506static int mt_setdensity(int *arg)
507{
508 TRACE_FUN(ft_t_flow);
509
510 SET_TRACE_LEVEL(*arg);
511 TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL);
512 if ((int)TRACE_LEVEL != *arg) {
513 TRACE_EXIT -EINVAL;
514 }
515 TRACE_EXIT 0;
516}
517
518static int mt_seek(int *new_block_pos)
519{
520 int result= 0;
521 TRACE_FUN(ft_t_any);
522
523 result = seek_block(0, (__s64)*new_block_pos, &zft_pos);
524 TRACE_EXIT result;
525}
526
527/* OK, this is totally different from SCSI, but the worst thing that can
528 * happen is that there is not enough defragmentated memory that can be
529 * allocated. Also, there is a hardwired limit of 16 dma buffers in the
530 * stock ftape module. This shouldn't bring the system down.
531 *
532 * NOTE: the argument specifies the total number of dma buffers to use.
533 * The driver needs at least 3 buffers to function at all.
534 *
535 */
536static int mt_setdrvbuffer(int *cnt)
537{
538 TRACE_FUN(ft_t_flow);
539
540 if (*cnt < 3) {
541 TRACE_EXIT -EINVAL;
542 }
543 TRACE_CATCH(ftape_set_nr_buffers(*cnt),);
544 TRACE_EXIT 0;
545}
546/* return the block position from start of volume
547 */
548static int mt_tell(int *arg)
549{
550 TRACE_FUN(ft_t_flow);
551
552 *arg = zft_div_blksz(zft_pos.volume_pos,
553 zft_find_volume(zft_pos.seg_pos)->blk_sz);
554 TRACE_EXIT 0;
555}
556
557static int mt_compression(int *arg)
558{
559 TRACE_FUN(ft_t_flow);
560
561 /* Ok. We could also check whether compression is available at
562 * all by trying to load the compression module. We could
563 * also check for a block size of 1 byte which is illegal
564 * with compression. Instead of doing it here we rely on
565 * zftape_write() to do the proper checks.
566 */
567 if ((unsigned int)*arg > 1) {
568 TRACE_EXIT -EINVAL;
569 }
570 if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */
571 TRACE_ABORT(-EINVAL, ft_t_info,
572 "Compression not yet supported "
573 "with variable block size");
574 }
575 zft_mt_compression = *arg;
576 if ((zft_unit & ZFT_ZIP_MODE) == 0) {
577 zft_use_compression = zft_mt_compression;
578 }
579 TRACE_EXIT 0;
580}
581
582/* check whether write access is allowed. Write access is denied when
583 * + zft_write_protected == 1 -- this accounts for either hard write
584 * protection of the cartridge or for
585 * O_RDONLY access mode of the tape device
586 * + zft_offline == 1 -- this meany that there is either no tape
587 * or that the MTOFFLINE ioctl has been
588 * previously issued (`soft eject')
589 * + ft_formatted == 0 -- this means that the cartridge is not
590 * formatted
591 * Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try
592 * to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we
593 * deny writes when
594 * + zft_qic_mode ==1 &&
595 * (!zft_tape_at_lbot() && -- tape no at logical BOT
596 * !(zft_tape_at_eom() || -- tape not at logical EOM (or EOD)
597 * (zft_tape_at_eom() &&
598 * zft_old_ftape()))) -- we can't add new volume to tapes
599 * written by old ftape because ftape
600 * don't use the volume table
601 *
602 * when the drive is in true raw mode (aka /dev/rawft0) then we don't
603 * care about LBOT and EOM conditions. This device is intended for a
604 * user level program that wants to truly implement the QIC-80 compliance
605 * at the logical data layout level of the cartridge, i.e. implement all
606 * that volume table and volume directory stuff etc.<
607 */
608int zft_check_write_access(zft_position *pos)
609{
610 TRACE_FUN(ft_t_flow);
611
612 if (zft_offline) { /* offline includes no_tape */
613 TRACE_ABORT(-ENXIO,
614 ft_t_info, "tape is offline or no cartridge");
615 }
616 if (!ft_formatted) {
617 TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
618 }
619 if (zft_write_protected) {
620 TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected");
621 }
622 if (zft_qic_mode) {
623 /* check BOT condition */
624 if (!zft_tape_at_lbot(pos)) {
625 /* protect cartridges written by old ftape if
626 * not at BOT because they use the vtbl
627 * segment for storing data
628 */
629 if (zft_old_ftape) {
630 TRACE_ABORT(-EACCES, ft_t_warn,
631 "Cannot write to cartridges written by old ftape when not at BOT");
632 }
633 /* not at BOT, but allow writes at EOD, of course
634 */
635 if (!zft_tape_at_eod(pos)) {
636 TRACE_ABORT(-EACCES, ft_t_info,
637 "tape not at BOT and not at EOD");
638 }
639 }
640 /* fine. Now the tape is either at BOT or at EOD. */
641 }
642 /* or in raw mode in which case we don't care about BOT and EOD */
643 TRACE_EXIT 0;
644}
645
646/* OPEN routine called by kernel-interface code
647 *
648 * NOTE: this is also called by mt_reset() with dev_minor == -1
649 * to fake a reopen after a reset.
650 */
651int _zft_open(unsigned int dev_minor, unsigned int access_mode)
652{
653 static unsigned int tape_unit;
654 static unsigned int file_access_mode;
655 int result;
656 TRACE_FUN(ft_t_flow);
657
658 if ((int)dev_minor == -1) {
659 /* fake reopen */
660 zft_unit = tape_unit;
661 access_mode = file_access_mode;
662 zft_init_driver(); /* reset all static data to defaults */
663 } else {
664 tape_unit = dev_minor;
665 file_access_mode = access_mode;
666 if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) {
667 TRACE_ABORT(-ENXIO, ft_t_err,
668 "ftape_enable failed: %d", result);
669 }
670 if (ft_new_tape || ft_no_tape || !ft_formatted ||
671 (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) ||
672 (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) {
673 /* reset all static data to defaults,
674 */
675 zft_init_driver();
676 }
677 zft_unit = dev_minor;
678 }
679 zft_set_flags(zft_unit); /* decode the minor bits */
680 if (zft_blk_sz == 1 && zft_use_compression) {
681 ftape_disable(); /* resets ft_no_tape */
682 TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet "
683 "supported with compression");
684 }
685 /* no need for most of the buffers when no tape or not
686 * formatted. for the read/write operations, it is the
687 * regardless whether there is no tape, a not-formatted tape
688 * or the whether the driver is soft offline.
689 * Nevertheless we allow some ioctls with non-formatted tapes,
690 * like rewind and reset.
691 */
692 if (ft_no_tape || !ft_formatted) {
693 zft_uninit_mem();
694 }
695 if (ft_no_tape) {
696 zft_offline = 1; /* so we need not test two variables */
697 }
698 if ((access_mode == O_WRONLY || access_mode == O_RDWR) &&
699 (ft_write_protected || ft_no_tape)) {
700 ftape_disable(); /* resets ft_no_tape */
701 TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS,
702 ft_t_warn, "wrong access mode %s cartridge",
703 ft_no_tape ? "without a" : "with write protected");
704 }
705 zft_write_protected = (access_mode == O_RDONLY ||
706 ft_write_protected != 0);
707 if (zft_write_protected) {
708 TRACE(ft_t_noise,
709 "read only access mode: %d, "
710 "drive write protected: %d",
711 access_mode == O_RDONLY,
712 ft_write_protected != 0);
713 }
714 if (!zft_offline) {
715 TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE),
716 ftape_disable());
717 }
718 /* zft_seg_pos should be greater than the vtbl segpos but not
719 * if in compatibility mode and only after we read in the
720 * header segments
721 *
722 * might also be a problem if the user makes a backup with a
723 * *qft* device and rewinds it with a raw device.
724 */
725 if (zft_qic_mode &&
726 !zft_old_ftape &&
727 zft_pos.seg_pos >= 0 &&
728 zft_header_read &&
729 zft_pos.seg_pos <= ft_first_data_segment) {
730 TRACE(ft_t_noise, "you probably mixed up the zftape devices!");
731 zft_reset_position(&zft_pos);
732 }
733 TRACE_EXIT 0;
734}
735
736/* RELEASE routine called by kernel-interface code
737 */
738int _zft_close(void)
739{
740 int result = 0;
741 TRACE_FUN(ft_t_flow);
742
743 if (zft_offline) {
744 /* call the hardware release routine. Puts the drive offline */
745 ftape_disable();
746 TRACE_EXIT 0;
747 }
748 if (!(ft_write_protected || zft_old_ftape)) {
749 result = zft_flush_buffers();
750 TRACE(ft_t_noise, "writing file mark at current position");
751 if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) {
752 zft_move_past_eof(&zft_pos);
753 }
754 if ((zft_tape_at_lbot(&zft_pos) ||
755 !(zft_unit & FTAPE_NO_REWIND))) {
756 if (result >= 0) {
757 result = zft_update_header_segments();
758 } else {
759 TRACE(ft_t_err,
760 "Error: unable to update header segments");
761 }
762 }
763 }
764 ftape_abort_operation();
765 if (!(zft_unit & FTAPE_NO_REWIND)) {
766 TRACE(ft_t_noise, "rewinding tape");
767 if (ftape_seek_to_bot() < 0 && result >= 0) {
768 result = -EIO; /* keep old value */
769 }
770 zft_reset_position(&zft_pos);
771 }
772 zft_zap_read_buffers();
773 /* now free up memory as much as possible. We don't destroy
774 * the deblock buffer if it containes a valid segment.
775 */
776 if (zft_deblock_segment == -1) {
777 zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE);
778 }
779 /* high level driver status, forces creation of a new volume
780 * when calling ftape_write again and not zft_just_before_eof
781 */
782 zft_io_state = zft_idle;
783 if (going_offline) {
784 zft_init_driver();
785 zft_uninit_mem();
786 going_offline = 0;
787 zft_offline = 1;
788 } else if (zft_cmpr_lock(0 /* don't load */) == 0) {
789 (*zft_cmpr_ops->reset)(); /* unlock it again */
790 }
791 zft_memory_stats();
792 /* call the hardware release routine. Puts the drive offline */
793 ftape_disable();
794 TRACE_EXIT result;
795}
796
797/*
798 * the wrapper function around the wrapper MTIOCTOP ioctl
799 */
800static int mtioctop(struct mtop *mtop, int arg_size)
801{
802 int result = 0;
803 fun_entry *mt_fun_entry;
804 TRACE_FUN(ft_t_flow);
805
806 if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) {
807 TRACE_EXIT -EINVAL;
808 }
809 TRACE(ft_t_noise, "calling MTIOCTOP command: %s",
810 mt_funs[mtop->mt_op].name);
811 mt_fun_entry= &mt_funs[mtop->mt_op];
812 zft_resid = mtop->mt_count;
813 if (!mt_fun_entry->offline && zft_offline) {
814 if (ft_no_tape) {
815 TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
816 } else {
817 TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
818 }
819 }
820 if (!mt_fun_entry->not_formatted && !ft_formatted) {
821 TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
822 }
823 if (!mt_fun_entry->write_protected) {
824 TRACE_CATCH(zft_check_write_access(&zft_pos),);
825 }
826 if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) {
827 TRACE_CATCH(zft_def_idle_state(),);
828 }
829 if (!zft_qic_mode && !mt_fun_entry->raw_mode) {
830 TRACE_ABORT(-EACCES, ft_t_info,
831"Drive needs to be in QIC-80 compatibility mode for this command");
832 }
833 result = (mt_fun_entry->function)(&mtop->mt_count);
834 if (zft_tape_at_lbot(&zft_pos)) {
835 TRACE_CATCH(zft_update_header_segments(),);
836 }
837 if (result >= 0) {
838 zft_resid = 0;
839 }
840 TRACE_EXIT result;
841}
842
843/*
844 * standard MTIOCGET ioctl
845 */
846static int mtiocget(struct mtget *mtget, int arg_size)
847{
848 const zft_volinfo *volume;
849 __s64 max_tape_pos;
850 TRACE_FUN(ft_t_flow);
851
852 if (arg_size != sizeof(struct mtget)) {
853 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
854 arg_size);
855 }
856 mtget->mt_type = ft_drive_type.vendor_id + 0x800000;
857 mtget->mt_dsreg = ft_last_status.space;
858 mtget->mt_erreg = ft_last_error.space; /* error register */
859 mtget->mt_resid = zft_resid; /* residuum of writes, reads and
860 * MTIOCTOP commands
861 */
862 if (!zft_offline) { /* neither no_tape nor soft offline */
863 mtget->mt_gstat = GMT_ONLINE(~0UL);
864 /* should rather return the status of the cartridge
865 * than the access mode of the file, therefor use
866 * ft_write_protected, not zft_write_protected
867 */
868 if (ft_write_protected) {
869 mtget->mt_gstat |= GMT_WR_PROT(~0UL);
870 }
871 if(zft_header_read) { /* this catches non-formatted */
872 volume = zft_find_volume(zft_pos.seg_pos);
873 mtget->mt_fileno = volume->count;
874 max_tape_pos = zft_capacity - zft_blk_sz;
875 if (zft_use_compression) {
876 max_tape_pos -= ZFT_CMPR_OVERHEAD;
877 }
878 if (zft_tape_at_eod(&zft_pos)) {
879 mtget->mt_gstat |= GMT_EOD(~0UL);
880 }
881 if (zft_pos.tape_pos > max_tape_pos) {
882 mtget->mt_gstat |= GMT_EOT(~0UL);
883 }
884 mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos,
885 volume->blk_sz);
886 if (zft_just_before_eof) {
887 mtget->mt_gstat |= GMT_EOF(~0UL);
888 }
889 if (zft_tape_at_lbot(&zft_pos)) {
890 mtget->mt_gstat |= GMT_BOT(~0UL);
891 }
892 } else {
893 mtget->mt_fileno = mtget->mt_blkno = -1;
894 if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) {
895 mtget->mt_gstat |= GMT_BOT(~0UL);
896 }
897 }
898 } else {
899 if (ft_no_tape) {
900 mtget->mt_gstat = GMT_DR_OPEN(~0UL);
901 } else {
902 mtget->mt_gstat = 0UL;
903 }
904 mtget->mt_fileno = mtget->mt_blkno = -1;
905 }
906 TRACE_EXIT 0;
907}
908
909#ifdef MTIOCRDFTSEG
910/*
911 * Read a floppy tape segment. This is useful for manipulating the
912 * volume table, and read the old header segment before re-formatting
913 * the cartridge.
914 */
915static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size)
916{
917 TRACE_FUN(ft_t_flow);
918
919 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG");
920 if (zft_qic_mode) {
921 TRACE_ABORT(-EACCES, ft_t_info,
922 "driver needs to be in raw mode for this ioctl");
923 }
924 if (arg_size != sizeof(struct mtftseg)) {
925 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
926 arg_size);
927 }
928 if (zft_offline) {
929 TRACE_EXIT -ENXIO;
930 }
931 if (mtftseg->mt_mode != FT_RD_SINGLE &&
932 mtftseg->mt_mode != FT_RD_AHEAD) {
933 TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode");
934 }
935 if (!ft_formatted) {
936 TRACE_EXIT -EACCES; /* -ENXIO ? */
937
938 }
939 if (!zft_header_read) {
940 TRACE_CATCH(zft_def_idle_state(),);
941 }
942 if (mtftseg->mt_segno > ft_last_data_segment) {
943 TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large");
944 }
945 mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno,
946 zft_deblock_buf,
947 mtftseg->mt_mode);
948 if (mtftseg->mt_result < 0) {
949 /* a negativ result is not an ioctl error. if
950 * the user wants to read damaged tapes,
951 * it's up to her/him
952 */
953 TRACE_EXIT 0;
954 }
955 if (copy_to_user(mtftseg->mt_data,
956 zft_deblock_buf,
957 mtftseg->mt_result) != 0) {
958 TRACE_EXIT -EFAULT;
959 }
960 TRACE_EXIT 0;
961}
962#endif
963
964#ifdef MTIOCWRFTSEG
965/*
966 * write a floppy tape segment. This version features writing of
967 * deleted address marks, and gracefully ignores the (software)
968 * ft_formatted flag to support writing of header segments after
969 * formatting.
970 */
971static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size)
972{
973 int result;
974 TRACE_FUN(ft_t_flow);
975
976 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG");
977 if (zft_write_protected || zft_qic_mode) {
978 TRACE_EXIT -EACCES;
979 }
980 if (arg_size != sizeof(struct mtftseg)) {
981 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
982 arg_size);
983 }
984 if (zft_offline) {
985 TRACE_EXIT -ENXIO;
986 }
987 if (mtftseg->mt_mode != FT_WR_ASYNC &&
988 mtftseg->mt_mode != FT_WR_MULTI &&
989 mtftseg->mt_mode != FT_WR_SINGLE &&
990 mtftseg->mt_mode != FT_WR_DELETE) {
991 TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode");
992 }
993 /*
994 * We don't check for ft_formatted, because this gives
995 * only the software status of the driver.
996 *
997 * We assume that the user knows what it is
998 * doing. And rely on the low level stuff to fail
999 * when the tape isn't formatted. We only make sure
1000 * that The header segment buffer is allocated,
1001 * because it holds the bad sector map.
1002 */
1003 if (zft_hseg_buf == NULL) {
1004 TRACE_EXIT -ENXIO;
1005 }
1006 if (mtftseg->mt_mode != FT_WR_DELETE) {
1007 if (copy_from_user(zft_deblock_buf,
1008 mtftseg->mt_data,
1009 FT_SEGMENT_SIZE) != 0) {
1010 TRACE_EXIT -EFAULT;
1011 }
1012 }
1013 mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno,
1014 zft_deblock_buf,
1015 mtftseg->mt_mode);
1016 if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) {
1017 /*
1018 * a negativ result is not an ioctl error. if
1019 * the user wants to write damaged tapes,
1020 * it's up to her/him
1021 */
1022 if ((result = ftape_loop_until_writes_done()) < 0) {
1023 mtftseg->mt_result = result;
1024 }
1025 }
1026 TRACE_EXIT 0;
1027}
1028#endif
1029
1030#ifdef MTIOCVOLINFO
1031/*
1032 * get information about volume positioned at.
1033 */
1034static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size)
1035{
1036 const zft_volinfo *volume;
1037 TRACE_FUN(ft_t_flow);
1038
1039 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO");
1040 if (arg_size != sizeof(struct mtvolinfo)) {
1041 TRACE_ABORT(-EINVAL,
1042 ft_t_info, "bad argument size: %d", arg_size);
1043 }
1044 if (zft_offline) {
1045 TRACE_EXIT -ENXIO;
1046 }
1047 if (!ft_formatted) {
1048 TRACE_EXIT -EACCES;
1049 }
1050 TRACE_CATCH(zft_def_idle_state(),);
1051 volume = zft_find_volume(zft_pos.seg_pos);
1052 volinfo->mt_volno = volume->count;
1053 volinfo->mt_blksz = volume->blk_sz == 1 ? 0 : volume->blk_sz;
1054 volinfo->mt_size = volume->size >> 10;
1055 volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) -
1056 (zft_calc_tape_pos(volume->start_seg) >> 10));
1057 volinfo->mt_cmpr = volume->use_compression;
1058 TRACE_EXIT 0;
1059}
1060#endif
1061
1062#ifdef ZFT_OBSOLETE
1063static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size)
1064{
1065 TRACE_FUN(ft_t_flow);
1066
1067 TRACE(ft_t_noise, "\n"
1068 KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n"
1069 KERN_INFO "This ioctl is here merely for compatibility.\n"
1070 KERN_INFO "Please use MTIOCVOLINFO instead");
1071 if (arg_size != sizeof(struct mtblksz)) {
1072 TRACE_ABORT(-EINVAL,
1073 ft_t_info, "bad argument size: %d", arg_size);
1074 }
1075 if (zft_offline) {
1076 TRACE_EXIT -ENXIO;
1077 }
1078 if (!ft_formatted) {
1079 TRACE_EXIT -EACCES;
1080 }
1081 TRACE_CATCH(zft_def_idle_state(),);
1082 blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz;
1083 TRACE_EXIT 0;
1084}
1085#endif
1086
1087#ifdef MTIOCGETSIZE
1088/*
1089 * get the capacity of the tape cartridge.
1090 */
1091static int mtiocgetsize(struct mttapesize *size, int arg_size)
1092{
1093 TRACE_FUN(ft_t_flow);
1094
1095 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE");
1096 if (arg_size != sizeof(struct mttapesize)) {
1097 TRACE_ABORT(-EINVAL,
1098 ft_t_info, "bad argument size: %d", arg_size);
1099 }
1100 if (zft_offline) {
1101 TRACE_EXIT -ENXIO;
1102 }
1103 if (!ft_formatted) {
1104 TRACE_EXIT -EACCES;
1105 }
1106 TRACE_CATCH(zft_def_idle_state(),);
1107 size->mt_capacity = (unsigned int)(zft_capacity>>10);
1108 size->mt_used = (unsigned int)(zft_get_eom_pos()>>10);
1109 TRACE_EXIT 0;
1110}
1111#endif
1112
1113static int mtiocpos(struct mtpos *mtpos, int arg_size)
1114{
1115 int result;
1116 TRACE_FUN(ft_t_flow);
1117
1118 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS");
1119 if (arg_size != sizeof(struct mtpos)) {
1120 TRACE_ABORT(-EINVAL,
1121 ft_t_info, "bad argument size: %d", arg_size);
1122 }
1123 result = mt_tell((int *)&mtpos->mt_blkno);
1124 TRACE_EXIT result;
1125}
1126
1127#ifdef MTIOCFTFORMAT
1128/*
1129 * formatting of floppy tape cartridges. This is intended to be used
1130 * together with the MTIOCFTCMD ioctl and the new mmap feature
1131 */
1132
1133/*
1134 * This function uses ftape_decode_header_segment() to inform the low
1135 * level ftape module about the new parameters.
1136 *
1137 * It erases the hseg_buf. The calling process must specify all
1138 * parameters to assure proper operation.
1139 *
1140 * return values: -EINVAL - wrong argument size
1141 * -EINVAL - if ftape_decode_header_segment() failed.
1142 */
1143static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf)
1144{
1145 ft_trace_t old_level = TRACE_LEVEL;
1146 TRACE_FUN(ft_t_flow);
1147
1148 TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS");
1149 memset(hseg_buf, 0, FT_SEGMENT_SIZE);
1150 PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC);
1151
1152 /* fill in user specified parameters
1153 */
1154 hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode;
1155 PUT2(hseg_buf, FT_SPT, p->ft_spt);
1156 hseg_buf[FT_TPC] = (__u8)p->ft_tpc;
1157 hseg_buf[FT_FHM] = (__u8)p->ft_fhm;
1158 hseg_buf[FT_FTM] = (__u8)p->ft_ftm;
1159
1160 /* fill in sane defaults to make ftape happy.
1161 */
1162 hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */
1163 if (p->ft_fmtcode == fmt_big) {
1164 PUT4(hseg_buf, FT_6_HSEG_1, 0);
1165 PUT4(hseg_buf, FT_6_HSEG_2, 1);
1166 PUT4(hseg_buf, FT_6_FRST_SEG, 2);
1167 PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1168 } else {
1169 PUT2(hseg_buf, FT_HSEG_1, 0);
1170 PUT2(hseg_buf, FT_HSEG_2, 1);
1171 PUT2(hseg_buf, FT_FRST_SEG, 2);
1172 PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1173 }
1174
1175 /* Synchronize with the low level module. This is particularly
1176 * needed for unformatted cartridges as the QIC std was previously
1177 * unknown BUT is needed to set data rate and to calculate timeouts.
1178 */
1179 TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK),
1180 _res = -EINVAL);
1181
1182 /* The following will also recalcualte the timeouts for the tape
1183 * length and QIC std we want to format to.
1184 * abort with -EINVAL rather than -EIO
1185 */
1186 SET_TRACE_LEVEL(ft_t_warn);
1187 TRACE_CATCH(ftape_decode_header_segment(hseg_buf),
1188 SET_TRACE_LEVEL(old_level); _res = -EINVAL);
1189 SET_TRACE_LEVEL(old_level);
1190 TRACE_EXIT 0;
1191}
1192
1193/*
1194 * Return the internal SOFTWARE status of the kernel driver. This does
1195 * NOT query the tape drive about its status.
1196 */
1197static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer)
1198{
1199 TRACE_FUN(ft_t_flow);
1200
1201 TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS");
1202 p->ft_qicstd = ft_qic_std;
1203 p->ft_fmtcode = ft_format_code;
1204 p->ft_fhm = hseg_buffer[FT_FHM];
1205 p->ft_ftm = hseg_buffer[FT_FTM];
1206 p->ft_spt = ft_segments_per_track;
1207 p->ft_tpc = ft_tracks_per_tape;
1208 TRACE_EXIT 0;
1209}
1210
1211static int mtiocftformat(struct mtftformat *mtftformat, int arg_size)
1212{
1213 int result;
1214 union fmt_arg *arg = &mtftformat->fmt_arg;
1215 TRACE_FUN(ft_t_flow);
1216
1217 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT");
1218 if (zft_offline) {
1219 if (ft_no_tape) {
1220 TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
1221 } else {
1222 TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
1223 }
1224 }
1225 if (zft_qic_mode) {
1226 TRACE_ABORT(-EACCES, ft_t_info,
1227 "driver needs to be in raw mode for this ioctl");
1228 }
1229 if (zft_hseg_buf == NULL) {
1230 TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
1231 }
1232 zft_header_read = 0;
1233 switch(mtftformat->fmt_op) {
1234 case FTFMT_SET_PARMS:
1235 TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1236 TRACE_EXIT 0;
1237 case FTFMT_GET_PARMS:
1238 TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1239 TRACE_EXIT 0;
1240 case FTFMT_FORMAT_TRACK:
1241 if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) ||
1242 (!ft_formatted && zft_write_protected)) {
1243 TRACE_ABORT(-EACCES, ft_t_info, "Write access denied");
1244 }
1245 TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track,
1246 arg->fmt_track.ft_gap3),);
1247 TRACE_EXIT 0;
1248 case FTFMT_STATUS:
1249 TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),);
1250 TRACE_EXIT 0;
1251 case FTFMT_VERIFY:
1252 TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment,
1253 (SectorMap *)&arg->fmt_verify.ft_bsm),);
1254 TRACE_EXIT 0;
1255 default:
1256 TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation");
1257 }
1258 TRACE_EXIT result;
1259}
1260#endif
1261
1262#ifdef MTIOCFTCMD
1263/*
1264 * send a QIC-117 command to the drive, with optional timeouts,
1265 * parameter and result bits. This is intended to be used together
1266 * with the formatting ioctl.
1267 */
1268static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)
1269{
1270 int i;
1271 TRACE_FUN(ft_t_flow);
1272
1273 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");
1274 if (!capable(CAP_SYS_ADMIN)) {
1275 TRACE_ABORT(-EPERM, ft_t_info,
1276 "need CAP_SYS_ADMIN capability to send raw qic-117 commands");
1277 }
1278 if (zft_qic_mode) {
1279 TRACE_ABORT(-EACCES, ft_t_info,
1280 "driver needs to be in raw mode for this ioctl");
1281 }
1282 if (arg_size != sizeof(struct mtftcmd)) {
1283 TRACE_ABORT(-EINVAL,
1284 ft_t_info, "bad argument size: %d", arg_size);
1285 }
1286 if (ftcmd->ft_wait_before) {
1287 TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before,
1288 &ftcmd->ft_status),);
1289 }
1290 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1291 goto ftmtcmd_error;
1292 if (ftcmd->ft_result_bits != 0) {
1293 TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result,
1294 ftcmd->ft_cmd,
1295 ftcmd->ft_result_bits),);
1296 } else {
1297 TRACE_CATCH(ftape_command(ftcmd->ft_cmd),);
1298 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1299 goto ftmtcmd_error;
1300 for (i = 0; i < ftcmd->ft_parm_cnt; i++) {
1301 TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),);
1302 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1303 goto ftmtcmd_error;
1304 }
1305 }
1306 if (ftcmd->ft_wait_after != 0) {
1307 TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after,
1308 &ftcmd->ft_status),);
1309 }
1310ftmtcmd_error:
1311 if (ftcmd->ft_status & QIC_STATUS_ERROR) {
1312 TRACE(ft_t_noise, "error status set");
1313 TRACE_CATCH(ftape_report_error(&ftcmd->ft_error,
1314 &ftcmd->ft_cmd, 1),);
1315 }
1316 TRACE_EXIT 0; /* this is not an i/o error */
1317}
1318#endif
1319
1320/* IOCTL routine called by kernel-interface code
1321 */
1322int _zft_ioctl(unsigned int command, void __user * arg)
1323{
1324 int result;
1325 union { struct mtop mtop;
1326 struct mtget mtget;
1327 struct mtpos mtpos;
1328#ifdef MTIOCRDFTSEG
1329 struct mtftseg mtftseg;
1330#endif
1331#ifdef MTIOCVOLINFO
1332 struct mtvolinfo mtvolinfo;
1333#endif
1334#ifdef MTIOCGETSIZE
1335 struct mttapesize mttapesize;
1336#endif
1337#ifdef MTIOCFTFORMAT
1338 struct mtftformat mtftformat;
1339#endif
1340#ifdef ZFT_OBSOLETE
1341 struct mtblksz mtblksz;
1342#endif
1343#ifdef MTIOCFTCMD
1344 struct mtftcmd mtftcmd;
1345#endif
1346 } krnl_arg;
1347 int arg_size = _IOC_SIZE(command);
1348 int dir = _IOC_DIR(command);
1349 TRACE_FUN(ft_t_flow);
1350
1351 /* This check will only catch arguments that are too large !
1352 */
1353 if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) {
1354 TRACE_ABORT(-EINVAL,
1355 ft_t_info, "bad argument size: %d", arg_size);
1356 }
1357 if (dir & _IOC_WRITE) {
1358 if (copy_from_user(&krnl_arg, arg, arg_size) != 0) {
1359 TRACE_EXIT -EFAULT;
1360 }
1361 }
1362 TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command);
1363 switch (command) {
1364 case MTIOCTOP:
1365 result = mtioctop(&krnl_arg.mtop, arg_size);
1366 break;
1367 case MTIOCGET:
1368 result = mtiocget(&krnl_arg.mtget, arg_size);
1369 break;
1370 case MTIOCPOS:
1371 result = mtiocpos(&krnl_arg.mtpos, arg_size);
1372 break;
1373#ifdef MTIOCVOLINFO
1374 case MTIOCVOLINFO:
1375 result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size);
1376 break;
1377#endif
1378#ifdef ZFT_OBSOLETE
1379 case MTIOC_ZFTAPE_GETBLKSZ:
1380 result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size);
1381 break;
1382#endif
1383#ifdef MTIOCRDFTSEG
1384 case MTIOCRDFTSEG: /* read a segment via ioctl */
1385 result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size);
1386 break;
1387#endif
1388#ifdef MTIOCWRFTSEG
1389 case MTIOCWRFTSEG: /* write a segment via ioctl */
1390 result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size);
1391 break;
1392#endif
1393#ifdef MTIOCGETSIZE
1394 case MTIOCGETSIZE:
1395 result = mtiocgetsize(&krnl_arg.mttapesize, arg_size);
1396 break;
1397#endif
1398#ifdef MTIOCFTFORMAT
1399 case MTIOCFTFORMAT:
1400 result = mtiocftformat(&krnl_arg.mtftformat, arg_size);
1401 break;
1402#endif
1403#ifdef MTIOCFTCMD
1404 case MTIOCFTCMD:
1405 result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size);
1406 break;
1407#endif
1408 default:
1409 result = -EINVAL;
1410 break;
1411 }
1412 if ((result >= 0) && (dir & _IOC_READ)) {
1413 if (copy_to_user(arg, &krnl_arg, arg_size) != 0) {
1414 TRACE_EXIT -EFAULT;
1415 }
1416 }
1417 TRACE_EXIT result;
1418}
diff --git a/drivers/char/ftape/zftape/zftape-ctl.h b/drivers/char/ftape/zftape/zftape-ctl.h
new file mode 100644
index 000000000000..414159891990
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-ctl.h
@@ -0,0 +1,59 @@
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/config.h>
31#include <linux/ioctl.h>
32#include <linux/mtio.h>
33
34#include "../zftape/zftape-rw.h"
35
36#ifdef CONFIG_ZFTAPE_MODULE
37#define ftape_status (*zft_status)
38#endif
39
40extern int zft_offline;
41extern int zft_mt_compression;
42extern int zft_write_protected;
43extern int zft_header_read;
44extern unsigned int zft_unit;
45extern int zft_resid;
46
47extern void zft_reset_position(zft_position *pos);
48extern int zft_check_write_access(zft_position *pos);
49extern int zft_def_idle_state(void);
50
51/* hooks for the VFS interface
52 */
53extern int _zft_open(unsigned int dev_minor, unsigned int access_mode);
54extern int _zft_close(void);
55extern int _zft_ioctl(unsigned int command, void __user *arg);
56#endif
57
58
59
diff --git a/drivers/char/ftape/zftape/zftape-eof.c b/drivers/char/ftape/zftape/zftape-eof.c
new file mode 100644
index 000000000000..dcadcaee9ac1
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-eof.c
@@ -0,0 +1,199 @@
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
new file mode 100644
index 000000000000..26568c26c518
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-eof.h
@@ -0,0 +1,52 @@
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
new file mode 100644
index 000000000000..dbac7e54e8e0
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -0,0 +1,403 @@
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/config.h>
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#include <linux/slab.h>
31#ifdef CONFIG_KMOD
32#include <linux/kmod.h>
33#endif
34#include <linux/fcntl.h>
35#include <linux/smp_lock.h>
36#include <linux/devfs_fs_kernel.h>
37
38#include <linux/zftape.h>
39#include <linux/init.h>
40#include <linux/device.h>
41
42#include "../zftape/zftape-init.h"
43#include "../zftape/zftape-read.h"
44#include "../zftape/zftape-write.h"
45#include "../zftape/zftape-ctl.h"
46#include "../zftape/zftape-buffers.h"
47
48MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine "
49 "(claus@momo.math.rwth-aachen.de)");
50MODULE_DESCRIPTION(ZFTAPE_VERSION " - "
51 "VFS interface for the Linux floppy tape driver. "
52 "Support for QIC-113 compatible volume table "
53 "and builtin compression (lzrw3 algorithm)");
54MODULE_SUPPORTED_DEVICE("char-major-27");
55MODULE_LICENSE("GPL");
56
57/* Global vars.
58 */
59struct zft_cmpr_ops *zft_cmpr_ops = NULL;
60const ftape_info *zft_status;
61
62/* Local vars.
63 */
64static unsigned long busy_flag;
65
66static sigset_t orig_sigmask;
67
68/* the interface to the kernel vfs layer
69 */
70
71/* Note about llseek():
72 *
73 * st.c and tpqic.c update fp->f_pos but don't implment llseek() and
74 * initialize the llseek component of the file_ops struct with NULL.
75 * This means that the user will get the default seek, but the tape
76 * device will not respect the new position, but happily read from the
77 * old position. Think a zftape specific llseek() function would be
78 * better, returning -ESPIPE. TODO.
79 */
80
81static int zft_open (struct inode *ino, struct file *filep);
82static int zft_close(struct inode *ino, struct file *filep);
83static int zft_ioctl(struct inode *ino, struct file *filep,
84 unsigned int command, unsigned long arg);
85static int zft_mmap(struct file *filep, struct vm_area_struct *vma);
86static ssize_t zft_read (struct file *fp, char __user *buff,
87 size_t req_len, loff_t *ppos);
88static ssize_t zft_write(struct file *fp, const char __user *buff,
89 size_t req_len, loff_t *ppos);
90
91static struct file_operations zft_cdev =
92{
93 .owner = THIS_MODULE,
94 .read = zft_read,
95 .write = zft_write,
96 .ioctl = zft_ioctl,
97 .mmap = zft_mmap,
98 .open = zft_open,
99 .release = zft_close,
100};
101
102static struct class_simple *zft_class;
103
104/* Open floppy tape device
105 */
106static int zft_open(struct inode *ino, struct file *filep)
107{
108 int result;
109 TRACE_FUN(ft_t_flow);
110
111 nonseekable_open(ino, filep);
112 TRACE(ft_t_flow, "called for minor %d", iminor(ino));
113 if ( test_and_set_bit(0,&busy_flag) ) {
114 TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
115 }
116 if ((iminor(ino) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
117 >
118 FTAPE_SEL_D) {
119 clear_bit(0,&busy_flag);
120 TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr");
121 }
122 orig_sigmask = current->blocked;
123 sigfillset(&current->blocked);
124 result = _zft_open(iminor(ino), filep->f_flags & O_ACCMODE);
125 if (result < 0) {
126 current->blocked = orig_sigmask; /* restore mask */
127 clear_bit(0,&busy_flag);
128 TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
129 } else {
130 /* Mask signals that will disturb proper operation of the
131 * program that is calling.
132 */
133 current->blocked = orig_sigmask;
134 sigaddsetmask (&current->blocked, _DO_BLOCK);
135 TRACE_EXIT 0;
136 }
137}
138
139/* Close floppy tape device
140 */
141static int zft_close(struct inode *ino, struct file *filep)
142{
143 int result;
144 TRACE_FUN(ft_t_flow);
145
146 if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit) {
147 TRACE(ft_t_err, "failed: not busy or wrong unit");
148 TRACE_EXIT 0;
149 }
150 sigfillset(&current->blocked);
151 result = _zft_close();
152 if (result < 0) {
153 TRACE(ft_t_err, "_zft_close failed");
154 }
155 current->blocked = orig_sigmask; /* restore before open state */
156 clear_bit(0,&busy_flag);
157 TRACE_EXIT 0;
158}
159
160/* Ioctl for floppy tape device
161 */
162static int zft_ioctl(struct inode *ino, struct file *filep,
163 unsigned int command, unsigned long arg)
164{
165 int result = -EIO;
166 sigset_t old_sigmask;
167 TRACE_FUN(ft_t_flow);
168
169 if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
170 TRACE_ABORT(-EIO, ft_t_err,
171 "failed: not busy, failure or wrong unit");
172 }
173 old_sigmask = current->blocked; /* save mask */
174 sigfillset(&current->blocked);
175 /* This will work as long as sizeof(void *) == sizeof(long) */
176 result = _zft_ioctl(command, (void __user *) arg);
177 current->blocked = old_sigmask; /* restore mask */
178 TRACE_EXIT result;
179}
180
181/* Ioctl for floppy tape device
182 */
183static int zft_mmap(struct file *filep, struct vm_area_struct *vma)
184{
185 int result = -EIO;
186 sigset_t old_sigmask;
187 TRACE_FUN(ft_t_flow);
188
189 if ( !test_bit(0,&busy_flag) ||
190 iminor(filep->f_dentry->d_inode) != zft_unit ||
191 ft_failure)
192 {
193 TRACE_ABORT(-EIO, ft_t_err,
194 "failed: not busy, failure or wrong unit");
195 }
196 old_sigmask = current->blocked; /* save mask */
197 sigfillset(&current->blocked);
198 if ((result = ftape_mmap(vma)) >= 0) {
199#ifndef MSYNC_BUG_WAS_FIXED
200 static struct vm_operations_struct dummy = { NULL, };
201 vma->vm_ops = &dummy;
202#endif
203 }
204 current->blocked = old_sigmask; /* restore mask */
205 TRACE_EXIT result;
206}
207
208/* Read from floppy tape device
209 */
210static ssize_t zft_read(struct file *fp, char __user *buff,
211 size_t req_len, loff_t *ppos)
212{
213 int result = -EIO;
214 sigset_t old_sigmask;
215 struct inode *ino = fp->f_dentry->d_inode;
216 TRACE_FUN(ft_t_flow);
217
218 TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
219 if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
220 TRACE_ABORT(-EIO, ft_t_err,
221 "failed: not busy, failure or wrong unit");
222 }
223 old_sigmask = current->blocked; /* save mask */
224 sigfillset(&current->blocked);
225 result = _zft_read(buff, req_len);
226 current->blocked = old_sigmask; /* restore mask */
227 TRACE(ft_t_data_flow, "return with count: %d", result);
228 TRACE_EXIT result;
229}
230
231/* Write to tape device
232 */
233static ssize_t zft_write(struct file *fp, const char __user *buff,
234 size_t req_len, loff_t *ppos)
235{
236 int result = -EIO;
237 sigset_t old_sigmask;
238 struct inode *ino = fp->f_dentry->d_inode;
239 TRACE_FUN(ft_t_flow);
240
241 TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
242 if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
243 TRACE_ABORT(-EIO, ft_t_err,
244 "failed: not busy, failure or wrong unit");
245 }
246 old_sigmask = current->blocked; /* save mask */
247 sigfillset(&current->blocked);
248 result = _zft_write(buff, req_len);
249 current->blocked = old_sigmask; /* restore mask */
250 TRACE(ft_t_data_flow, "return with count: %d", result);
251 TRACE_EXIT result;
252}
253
254/* END OF VFS INTERFACE
255 *
256 *****************************************************************************/
257
258/* driver/module initialization
259 */
260
261/* the compression module has to call this function to hook into the zftape
262 * code
263 */
264int zft_cmpr_register(struct zft_cmpr_ops *new_ops)
265{
266 TRACE_FUN(ft_t_flow);
267
268 if (zft_cmpr_ops != NULL) {
269 TRACE_EXIT -EBUSY;
270 } else {
271 zft_cmpr_ops = new_ops;
272 TRACE_EXIT 0;
273 }
274}
275
276/* lock the zft-compressor() module.
277 */
278int zft_cmpr_lock(int try_to_load)
279{
280 if (zft_cmpr_ops == NULL) {
281#ifdef CONFIG_KMOD
282 if (try_to_load) {
283 request_module("zft-compressor");
284 if (zft_cmpr_ops == NULL) {
285 return -ENOSYS;
286 }
287 } else {
288 return -ENOSYS;
289 }
290#else
291 return -ENOSYS;
292#endif
293 }
294 (*zft_cmpr_ops->lock)();
295 return 0;
296}
297
298#ifdef CONFIG_ZFT_COMPRESSOR
299extern int zft_compressor_init(void);
300#endif
301
302/* Called by modules package when installing the driver or by kernel
303 * during the initialization phase
304 */
305int __init zft_init(void)
306{
307 int i;
308 TRACE_FUN(ft_t_flow);
309
310#ifdef MODULE
311 printk(KERN_INFO ZFTAPE_VERSION "\n");
312 if (TRACE_LEVEL >= ft_t_info) {
313 printk(
314KERN_INFO
315"(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
316KERN_INFO
317"vfs interface for ftape floppy tape driver.\n"
318KERN_INFO
319"Support for QIC-113 compatible volume table, dynamic memory allocation\n"
320KERN_INFO
321"and builtin compression (lzrw3 algorithm).\n");
322 }
323#else /* !MODULE */
324 /* print a short no-nonsense boot message */
325 printk(KERN_INFO ZFTAPE_VERSION "\n");
326#endif /* MODULE */
327 TRACE(ft_t_info, "zft_init @ 0x%p", zft_init);
328 TRACE(ft_t_info,
329 "installing zftape VFS interface for ftape driver ...");
330 TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
331
332 zft_class = class_simple_create(THIS_MODULE, "zft");
333 for (i = 0; i < 4; i++) {
334 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
335 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
336 S_IFCHR | S_IRUSR | S_IWUSR,
337 "qft%i", i);
338 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
339 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
340 S_IFCHR | S_IRUSR | S_IWUSR,
341 "nqft%i", i);
342 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
343 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
344 S_IFCHR | S_IRUSR | S_IWUSR,
345 "zqft%i", i);
346 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
347 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
348 S_IFCHR | S_IRUSR | S_IWUSR,
349 "nzqft%i", i);
350 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
351 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
352 S_IFCHR | S_IRUSR | S_IWUSR,
353 "rawqft%i", i);
354 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
355 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
356 S_IFCHR | S_IRUSR | S_IWUSR,
357 "nrawqft%i", i);
358 }
359
360#ifdef CONFIG_ZFT_COMPRESSOR
361 (void)zft_compressor_init();
362#endif
363 zft_status = ftape_get_status(); /* fetch global data of ftape
364 * hardware driver
365 */
366 TRACE_EXIT 0;
367}
368
369
370/* Called by modules package when removing the driver
371 */
372static void zft_exit(void)
373{
374 int i;
375 TRACE_FUN(ft_t_flow);
376
377 if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
378 TRACE(ft_t_warn, "failed");
379 } else {
380 TRACE(ft_t_info, "successful");
381 }
382 for (i = 0; i < 4; i++) {
383 devfs_remove("qft%i", i);
384 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i));
385 devfs_remove("nqft%i", i);
386 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 4));
387 devfs_remove("zqft%i", i);
388 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 16));
389 devfs_remove("nzqft%i", i);
390 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 20));
391 devfs_remove("rawqft%i", i);
392 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 32));
393 devfs_remove("nrawqft%i", i);
394 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 36));
395 }
396 class_simple_destroy(zft_class);
397 zft_uninit_mem(); /* release remaining memory, if any */
398 printk(KERN_INFO "zftape successfully unloaded.\n");
399 TRACE_EXIT;
400}
401
402module_init(zft_init);
403module_exit(zft_exit);
diff --git a/drivers/char/ftape/zftape/zftape-init.h b/drivers/char/ftape/zftape/zftape-init.h
new file mode 100644
index 000000000000..937e5d48c20e
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-init.h
@@ -0,0 +1,77 @@
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
new file mode 100644
index 000000000000..214bf03dce68
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-read.c
@@ -0,0 +1,377 @@
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
new file mode 100644
index 000000000000..42941de0c23a
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-read.h
@@ -0,0 +1,53 @@
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
new file mode 100644
index 000000000000..a61ef50f3dfc
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-rw.c
@@ -0,0 +1,376 @@
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/config.h> /* for CONFIG_ZFT_DFLT_BLK_SZ */
28#include <linux/errno.h>
29#include <linux/mm.h>
30
31#include <linux/zftape.h>
32#include "../zftape/zftape-init.h"
33#include "../zftape/zftape-eof.h"
34#include "../zftape/zftape-ctl.h"
35#include "../zftape/zftape-write.h"
36#include "../zftape/zftape-read.h"
37#include "../zftape/zftape-rw.h"
38#include "../zftape/zftape-vtbl.h"
39
40/* Global vars.
41 */
42
43__u8 *zft_deblock_buf;
44__u8 *zft_hseg_buf;
45int zft_deblock_segment = -1;
46zft_status_enum zft_io_state = zft_idle;
47int zft_header_changed;
48int zft_qic113; /* conform to old specs. and old zftape */
49int zft_use_compression;
50zft_position zft_pos = {
51 -1, /* seg_pos */
52 0, /* seg_byte_pos */
53 0, /* tape_pos */
54 0 /* volume_pos */
55};
56unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
57__s64 zft_capacity;
58
59unsigned int zft_written_segments;
60int zft_label_changed;
61
62/* Local vars.
63 */
64
65unsigned int zft_get_seg_sz(unsigned int segment)
66{
67 int size;
68 TRACE_FUN(ft_t_any);
69
70 size = FT_SEGMENT_SIZE -
71 count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;
72 if (size > 0) {
73 TRACE_EXIT (unsigned)size;
74 } else {
75 TRACE_EXIT 0;
76 }
77}
78
79/* ftape_set_flags(). Claus-Justus Heine, 1994/1995
80 */
81void zft_set_flags(unsigned minor_unit)
82{
83 TRACE_FUN(ft_t_flow);
84
85 zft_use_compression = zft_qic_mode = 0;
86 switch (minor_unit & ZFT_MINOR_OP_MASK) {
87 case (ZFT_Q80_MODE | ZFT_ZIP_MODE):
88 case ZFT_ZIP_MODE:
89 zft_use_compression = 1;
90 case 0:
91 case ZFT_Q80_MODE:
92 zft_qic_mode = 1;
93 if (zft_mt_compression) { /* override the default */
94 zft_use_compression = 1;
95 }
96 break;
97 case ZFT_RAW_MODE:
98 TRACE(ft_t_noise, "switching to raw mode");
99 break;
100 default:
101 TRACE(ft_t_warn, "Warning:\n"
102 KERN_INFO "Wrong combination of minor device bits.\n"
103 KERN_INFO "Switching to raw read-only mode.");
104 zft_write_protected = 1;
105 break;
106 }
107 TRACE_EXIT;
108}
109
110/* computes the segment and byte offset inside the segment
111 * corresponding to tape_pos.
112 *
113 * tape_pos gives the offset in bytes from the beginning of the
114 * ft_first_data_segment *seg_byte_pos is the offset in the current
115 * segment in bytes
116 *
117 * Of, if this routine was called often one should cache the last data
118 * pos it was called with, but actually this is only needed in
119 * ftape_seek_block(), that is, almost never.
120 */
121int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)
122{
123 int segment;
124 int seg_sz;
125 TRACE_FUN(ft_t_flow);
126
127 if (tape_pos == 0) {
128 *seg_byte_pos = 0;
129 segment = ft_first_data_segment;
130 } else {
131 seg_sz = 0;
132
133 for (segment = ft_first_data_segment;
134 ((tape_pos > 0) && (segment <= ft_last_data_segment));
135 segment++) {
136 seg_sz = zft_get_seg_sz(segment);
137 tape_pos -= seg_sz;
138 }
139 if(tape_pos >= 0) {
140 /* the case tape_pos > != 0 means that the
141 * argument tape_pos lies beyond the EOT.
142 */
143 *seg_byte_pos= 0;
144 } else { /* tape_pos < 0 */
145 segment--;
146 *seg_byte_pos= tape_pos + seg_sz;
147 }
148 }
149 TRACE_EXIT(segment);
150}
151
152/* ftape_calc_tape_pos().
153 *
154 * computes the offset in bytes from the beginning of the
155 * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
156 *
157 * We should do some caching. But how:
158 *
159 * Each time the header segments are read in, this routine is called
160 * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
161 * the time to reset the cache.
162 *
163 * Also, it might be in the future that the bad sector map gets
164 * changed. -> reset the cache
165 */
166static int seg_pos;
167static __s64 tape_pos;
168
169__s64 zft_get_capacity(void)
170{
171 seg_pos = ft_first_data_segment;
172 tape_pos = 0;
173
174 while (seg_pos <= ft_last_data_segment) {
175 tape_pos += zft_get_seg_sz(seg_pos ++);
176 }
177 return tape_pos;
178}
179
180__s64 zft_calc_tape_pos(int segment)
181{
182 int d1, d2, d3;
183 TRACE_FUN(ft_t_any);
184
185 if (segment > ft_last_data_segment) {
186 TRACE_EXIT zft_capacity;
187 }
188 if (segment < ft_first_data_segment) {
189 TRACE_EXIT 0;
190 }
191 d2 = segment - seg_pos;
192 if (-d2 > 10) {
193 d1 = segment - ft_first_data_segment;
194 if (-d2 > d1) {
195 tape_pos = 0;
196 seg_pos = ft_first_data_segment;
197 d2 = d1;
198 }
199 }
200 if (d2 > 10) {
201 d3 = ft_last_data_segment - segment;
202 if (d2 > d3) {
203 tape_pos = zft_capacity;
204 seg_pos = ft_last_data_segment + 1;
205 d2 = -d3;
206 }
207 }
208 if (d2 > 0) {
209 while (seg_pos < segment) {
210 tape_pos += zft_get_seg_sz(seg_pos++);
211 }
212 } else {
213 while (seg_pos > segment) {
214 tape_pos -= zft_get_seg_sz(--seg_pos);
215 }
216 }
217 TRACE(ft_t_noise, "new cached pos: %d", seg_pos);
218
219 TRACE_EXIT tape_pos;
220}
221
222/* copy Z-label string to buffer, keeps track of the correct offset in
223 * `buffer'
224 */
225void zft_update_label(__u8 *buffer)
226{
227 TRACE_FUN(ft_t_flow);
228
229 if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL,
230 sizeof(ZFTAPE_LABEL)-1) != 0) {
231 TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"",
232 &buffer[FT_LABEL], ZFTAPE_LABEL);
233 strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);
234 memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ',
235 FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));
236 PUT4(buffer, FT_LABEL_DATE, 0);
237 zft_label_changed = zft_header_changed = 1; /* changed */
238 }
239 TRACE_EXIT;
240}
241
242int zft_verify_write_segments(unsigned int segment,
243 __u8 *data, size_t size,
244 __u8 *buffer)
245{
246 int result;
247 __u8 *write_buf;
248 __u8 *src_buf;
249 int single;
250 int seg_pos;
251 int seg_sz;
252 int remaining;
253 ft_write_mode_t write_mode;
254 TRACE_FUN(ft_t_flow);
255
256 seg_pos = segment;
257 seg_sz = zft_get_seg_sz(seg_pos);
258 src_buf = data;
259 single = size <= seg_sz;
260 remaining = size;
261 do {
262 TRACE(ft_t_noise, "\n"
263 KERN_INFO "remaining: %d\n"
264 KERN_INFO "seg_sz : %d\n"
265 KERN_INFO "segment : %d",
266 remaining, seg_sz, seg_pos);
267 if (remaining == seg_sz) {
268 write_buf = src_buf;
269 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
270 remaining = 0;
271 } else if (remaining > seg_sz) {
272 write_buf = src_buf;
273 write_mode = FT_WR_ASYNC; /* don't start tape */
274 remaining -= seg_sz;
275 } else { /* remaining < seg_sz */
276 write_buf = buffer;
277 memcpy(write_buf, src_buf, remaining);
278 memset(&write_buf[remaining],'\0',seg_sz-remaining);
279 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
280 remaining = 0;
281 }
282 if ((result = ftape_write_segment(seg_pos,
283 write_buf,
284 write_mode)) != seg_sz) {
285 TRACE(ft_t_err, "Error: "
286 "Couldn't write segment %d", seg_pos);
287 TRACE_EXIT result < 0 ? result : -EIO; /* bail out */
288 }
289 zft_written_segments ++;
290 seg_sz = zft_get_seg_sz(++seg_pos);
291 src_buf += result;
292 } while (remaining > 0);
293 if (ftape_get_status()->fti_state == writing) {
294 TRACE_CATCH(ftape_loop_until_writes_done(),);
295 TRACE_CATCH(ftape_abort_operation(),);
296 zft_prevent_flush();
297 }
298 seg_pos = segment;
299 src_buf = data;
300 remaining = size;
301 do {
302 TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer,
303 single ? FT_RD_SINGLE
304 : FT_RD_AHEAD),);
305 if (memcmp(src_buf, buffer,
306 remaining > result ? result : remaining) != 0) {
307 TRACE_ABORT(-EIO, ft_t_err,
308 "Failed to verify written segment %d",
309 seg_pos);
310 }
311 remaining -= result;
312 TRACE(ft_t_noise, "verify successful:\n"
313 KERN_INFO "segment : %d\n"
314 KERN_INFO "segsize : %d\n"
315 KERN_INFO "remaining: %d",
316 seg_pos, result, remaining);
317 src_buf += seg_sz;
318 seg_pos++;
319 } while (remaining > 0);
320 TRACE_EXIT size;
321}
322
323
324/* zft_erase(). implemented compression-handling
325 *
326 * calculate the first data-segment when using/not using compression.
327 *
328 * update header-segment and compression-map-segment.
329 */
330int zft_erase(void)
331{
332 int result = 0;
333 TRACE_FUN(ft_t_flow);
334
335 if (!zft_header_read) {
336 TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,
337 FT_SEGMENT_SIZE),);
338 /* no need to read the vtbl and compression map */
339 TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
340 if ((zft_old_ftape =
341 zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {
342 zft_ftape_extract_file_marks(zft_hseg_buf);
343 }
344 TRACE(ft_t_noise,
345 "ft_first_data_segment: %d, ft_last_data_segment: %d",
346 ft_first_data_segment, ft_last_data_segment);
347 zft_qic113 = (ft_format_code != fmt_normal &&
348 ft_format_code != fmt_1100ft &&
349 ft_format_code != fmt_425ft);
350 }
351 if (zft_old_ftape) {
352 zft_clear_ftape_file_marks();
353 zft_old_ftape = 0; /* no longer old ftape */
354 }
355 PUT2(zft_hseg_buf, FT_CMAP_START, 0);
356 zft_volume_table_changed = 1;
357 zft_capacity = zft_get_capacity();
358 zft_init_vtbl();
359 /* the rest must be done in ftape_update_header_segments
360 */
361 zft_header_read = 1;
362 zft_header_changed = 1; /* force update of timestamp */
363 result = zft_update_header_segments();
364
365 ftape_abort_operation();
366
367 zft_reset_position(&zft_pos);
368 zft_set_flags (zft_unit);
369 TRACE_EXIT result;
370}
371
372unsigned int zft_get_time(void)
373{
374 unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */
375 return date;
376}
diff --git a/drivers/char/ftape/zftape/zftape-rw.h b/drivers/char/ftape/zftape/zftape-rw.h
new file mode 100644
index 000000000000..14c07f086575
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-rw.h
@@ -0,0 +1,102 @@
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 <linux/config.h> /* for CONFIG_ZFT_DFLT_BLK_SZ */
32#include "../zftape/zftape-buffers.h"
33
34#define SEGMENTS_PER_TAPE (ft_segments_per_track * ft_tracks_per_tape)
35
36/* QIC-113 Rev. G says that `a maximum of 63488 raw bytes may be
37 * compressed into a single frame'.
38 * Maybe we should stick to 32kb to make it more `beautiful'
39 */
40#define ZFT_MAX_BLK_SZ (62*1024) /* bytes */
41#if !defined(CONFIG_ZFT_DFLT_BLK_SZ)
42# define CONFIG_ZFT_DFLT_BLK_SZ (10*1024) /* bytes, default of gnu tar */
43#elif CONFIG_ZFT_DFLT_BLK_SZ == 0
44# undef CONFIG_ZFT_DFLT_BLK_SZ
45# define CONFIG_ZFT_DFLT_BLK_SZ 1
46#elif (CONFIG_ZFT_DFLT_BLK_SZ % 1024) != 0
47# error CONFIG_ZFT_DFLT_BLK_SZ must be 1 or a multiple of 1024
48#endif
49/* The *optional* compression routines need some overhead per tape
50 * block for their purposes. Instead of asking the actual compression
51 * implementation how much it needs, we restrict this overhead to be
52 * maximal of ZFT_CMPT_OVERHEAD size. We need this for EOT
53 * conditions. The tape is assumed to be logical at EOT when the
54 * distance from the physical EOT is less than
55 * one tape block + ZFT_CMPR_OVERHEAD
56 */
57#define ZFT_CMPR_OVERHEAD 16 /* bytes */
58
59typedef enum
60{
61 zft_idle = 0,
62 zft_reading,
63 zft_writing,
64} zft_status_enum;
65
66typedef struct /* all values measured in bytes */
67{
68 int seg_pos; /* segment currently positioned at */
69 int seg_byte_pos; /* offset in current segment */
70 __s64 tape_pos; /* real offset from BOT */
71 __s64 volume_pos; /* pos. in uncompressed data stream in
72 * current volume
73 */
74} zft_position;
75
76extern zft_position zft_pos;
77extern __u8 *zft_deblock_buf;
78extern __u8 *zft_hseg_buf;
79extern int zft_deblock_segment;
80extern zft_status_enum zft_io_state;
81extern int zft_header_changed;
82extern int zft_qic113; /* conform to old specs. and old zftape */
83extern int zft_use_compression;
84extern unsigned int zft_blk_sz;
85extern __s64 zft_capacity;
86extern unsigned int zft_written_segments;
87extern int zft_label_changed;
88
89/* zftape-rw.c exported functions
90 */
91extern unsigned int zft_get_seg_sz(unsigned int segment);
92extern void zft_set_flags(unsigned int minor_unit);
93extern int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos);
94extern __s64 zft_calc_tape_pos(int segment);
95extern __s64 zft_get_capacity(void);
96extern void zft_update_label(__u8 *buffer);
97extern int zft_erase(void);
98extern int zft_verify_write_segments(unsigned int segment,
99 __u8 *data, size_t size, __u8 *buffer);
100extern unsigned int zft_get_time(void);
101#endif /* _ZFTAPE_RW_H */
102
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.c b/drivers/char/ftape/zftape/zftape-vtbl.c
new file mode 100644
index 000000000000..ad7f8be6340b
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-vtbl.c
@@ -0,0 +1,757 @@
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
new file mode 100644
index 000000000000..f31d196d1759
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-vtbl.h
@@ -0,0 +1,227 @@
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
new file mode 100644
index 000000000000..94327b8c97b9
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-write.c
@@ -0,0 +1,483 @@
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
new file mode 100644
index 000000000000..ea887015b493
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape-write.h
@@ -0,0 +1,38 @@
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
new file mode 100644
index 000000000000..2db1401682df
--- /dev/null
+++ b/drivers/char/ftape/zftape/zftape_syms.c
@@ -0,0 +1,43 @@
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);