It's bitrotten, long unmaintained, long hidden under BROKEN_ON_SMP, etc. As scheduled in feature-removal-schedule.txt, and ack'd several times on lkml.
···104104 - request_firmware() hotplug interface info.105105floppy.txt106106 - notes and driver options for the floppy disk driver.107107-ftape.txt108108- - notes about the floppy tape device driver.109107hayes-esp.txt110108 - info on using the Hayes ESP serial driver.111109highuid.txt
-8
Documentation/feature-removal-schedule.txt
···234234235235---------------------------236236237237-What: ftape238238-When: 2.6.20239239-Why: Orphaned for ages. SMP bugs long unfixed. Few users left240240- in the world.241241-Who: Jeff Garzik <jeff@garzik.org>242242-243243----------------------------244244-245237What: IPv4 only connection tracking/NAT/helpers246238When: 2.6.22247239Why: The new layer 3 independant connection tracking replaces the old
-307
Documentation/ftape.txt
···11-Intro22-=====33-44-This file describes some issues involved when using the "ftape"55-floppy tape device driver that comes with the Linux kernel.66-77-ftape has a home page at88-99-http://ftape.dot-heine.de/1010-1111-which contains further information about ftape. Please cross check1212-this WWW address against the address given (if any) in the MAINTAINERS1313-file located in the top level directory of the Linux kernel source1414-tree.1515-1616-NOTE: This is an unmaintained set of drivers, and it is not guaranteed to work.1717-If you are interested in taking over maintenance, contact Claus-Justus Heine1818-<ch@dot-heine.de>, the former maintainer.1919-2020-Contents2121-========2222-2323-A minus 1: Ftape documentation2424-2525-A. Changes2626- 1. Goal2727- 2. I/O Block Size2828- 3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape)2929- 4. Formatting3030- 5. Interchanging cartridges with other operating systems3131-3232-B. Debugging Output3333- 1. Introduction3434- 2. Tuning the debugging output3535-3636-C. Boot and load time configuration3737- 1. Setting boot time parameters3838- 2. Module load time parameters3939- 3. Ftape boot- and load time options4040- 4. Example kernel parameter setting4141- 5. Example module parameter setting4242-4343-D. Support and contacts4444-4545-*******************************************************************************4646-4747-A minus 1. Ftape documentation4848-==============================4949-5050-Unluckily, the ftape-HOWTO is out of date. This really needs to be5151-changed. Up to date documentation as well as recent development5252-versions of ftape and useful links to related topics can be found at5353-the ftape home page at5454-5555-http://ftape.dot-heine.de/5656-5757-*******************************************************************************5858-5959-A. Changes6060-==========6161-6262-1. Goal6363- ~~~~6464- The goal of all that incompatibilities was to give ftape an interface6565- that resembles the interface provided by SCSI tape drives as close6666- as possible. Thus any Unix backup program that is known to work6767- with SCSI tape drives should also work.6868-6969- The concept of a fixed block size for read/write transfers is7070- rather unrelated to this SCSI tape compatibility at the file system7171- interface level. It developed out of a feature of zftape, a7272- block wise user transparent on-the-fly compression. That compression7373- support will not be dropped in future releases for compatibility7474- reasons with previous releases of zftape.7575-7676-2. I/O Block Size7777- ~~~~~~~~~~~~~~7878- The block size defaults to 10k which is the default block size of7979- GNU tar.8080-8181- The block size can be tuned either during kernel configuration or8282- at runtime with the MTIOCTOP ioctl using the MTSETBLK operation8383- (i.e. do "mt -f /dev/qft0" setblk #BLKSZ). A block size of 08484- switches to variable block size mode i.e. "mt setblk 0" switches8585- off the block size restriction. However, this disables zftape's8686- built in on-the-fly compression which doesn't work with variable8787- block size mode.8888-8989- The BLKSZ parameter must be given as a byte count and must be a9090- multiple of 32k or 0, i.e. use "mt setblk 32768" to switch to a9191- block size of 32k.9292-9393- The typical symptom of a block size mismatch is an "invalid9494- argument" error message.9595-9696-3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape)9797- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~9898- zftape (the file system interface of ftape-3.x) denies write access9999- to the tape cartridge when it isn't positioned either at BOT or100100- EOD.101101-102102-4. Formatting103103- ~~~~~~~~~~104104- ftape DOES support formatting of floppy tape cartridges. You need the105105- `ftformat' program that is shipped with the modules version of ftape.106106- Please get the latest version of ftape from107107-108108- ftp://sunsite.unc.edu/pub/Linux/kernel/tapes109109-110110- or from the ftape home page at111111-112112- http://ftape.dot-heine.de/113113-114114- `ftformat' is contained in the `./contrib/' subdirectory of that115115- separate ftape package.116116-117117-5. Interchanging cartridges with other operating systems118118- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~119119-120120- The internal emulation of Unix tape device file marks has changed121121- completely. ftape now uses the volume table segment as specified122122- by the QIC-40/80/3010/3020/113 standards to emulate file marks. As123123- a consequence there is limited support to interchange cartridges124124- with other operating systems.125125-126126- To be more precise: ftape will detect volumes written by other OS's127127- programs and other OS's programs will detect volumes written by128128- ftape.129129-130130- However, it isn't possible to extract the data dumped to the tape131131- by some MSDOS program with ftape. This exceeds the scope of a132132- kernel device driver. If you need such functionality, then go ahead133133- and write a user space utility that is able to do that. ftape already134134- provides all kernel level support necessary to do that.135135-136136-*******************************************************************************137137-138138-B. Debugging Output139139- ================140140-141141-1. Introduction142142- ~~~~~~~~~~~~143143- The ftape driver can be very noisy in that is can print lots of144144- debugging messages to the kernel log files and the system console.145145- While this is useful for debugging it might be annoying during146146- normal use and enlarges the size of the driver by several kilobytes.147147-148148- To reduce the size of the driver you can trim the maximal amount of149149- debugging information available during kernel configuration. Please150150- refer to the kernel configuration script and its on-line help151151- functionality.152152-153153- The amount of debugging output maps to the "tracing" boot time154154- option and the "ft_tracing" modules option as follows:155155-156156- 0 bugs157157- 1 + errors (with call-stack dump)158158- 2 + warnings159159- 3 + information160160- 4 + more information161161- 5 + program flow162162- 6 + fdc/dma info163163- 7 + data flow164164- 8 + everything else165165-166166-2. Tuning the debugging output167167- ~~~~~~~~~~~~~~~~~~~~~~~~~~~168168- To reduce the amount of debugging output printed to the system169169- console you can170170-171171- i) trim the debugging output at run-time with172172-173173- mt -f /dev/nqft0 setdensity #DBGLVL174174-175175- where "#DBGLVL" is a number between 0 and 9176176-177177- ii) trim the debugging output at module load time with178178-179179- modprobe ftape ft_tracing=#DBGLVL180180-181181- Of course, this applies only if you have configured ftape to be182182- compiled as a module.183183-184184- iii) trim the debugging output during system boot time. Add the185185- following to the kernel command line:186186-187187- ftape=#DBGLVL,tracing188188-189189- Please refer also to the next section if you don't know how to190190- set boot time parameters.191191-192192-*******************************************************************************193193-194194-C. Boot and load time configuration195195- ================================196196-197197-1. Setting boot time parameters198198- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 199199- Assuming that you use lilo, the LI)nux LO)ader, boot time kernel200200- parameters can be set by adding a line201201-202202- append some_kernel_boot_time_parameter203203-204204- to `/etc/lilo.conf' or at real boot time by typing in the options205205- at the prompt provided by LILO. I can't give you advice on how to206206- specify those parameters with other loaders as I don't use them.207207-208208- For ftape, each "some_kernel_boot_time_parameter" looks like209209- "ftape=value,option". As an example, the debugging output can be210210- increased with211211-212212- ftape=4,tracing213213-214214- NOTE: the value precedes the option name.215215-216216-2. Module load time parameters217217- ~~~~~~~~~~~~~~~~~~~~~~~~~~~218218- Module parameters can be specified either directly when invoking219219- the program 'modprobe' at the shell prompt:220220-221221- modprobe ftape ft_tracing=4222222-223223- or by editing the file `/etc/modprobe.conf' in which case they take224224- effect each time when the module is loaded with `modprobe' (please225225- refer to the respective manual pages). Thus, you should add a line226226-227227- options ftape ft_tracing=4228228-229229- to `/etc/modprobe.conf` if you intend to increase the debugging230230- output of the driver.231231-232232-233233-3. Ftape boot- and load time options234234- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~235235-236236- i. Controlling the amount of debugging output237237- DBGLVL has to be replaced by a number between 0 and 8.238238-239239- module | kernel command line240240- -----------------------|----------------------241241- ft_tracing=DBGLVL | ftape=DBGLVL,tracing242242-243243- ii. Hardware setup244244- BASE is the base address of your floppy disk controller,245245- IRQ and DMA give its interrupt and DMA channel, respectively.246246- BOOL is an integer, "0" means "no"; any other value means247247- "yes". You don't need to specify anything if connecting your tape248248- drive to the standard floppy disk controller. All of these249249- values have reasonable defaults. The defaults can be modified250250- during kernel configuration, i.e. while running "make config",251251- "make menuconfig" or "make xconfig" in the top level directory252252- of the Linux kernel source tree. Please refer also to the on253253- line documentation provided during that kernel configuration254254- process.255255-256256- ft_probe_fc10 is set to a non-zero value if you wish for ftape to257257- probe for a Colorado FC-10 or FC-20 controller.258258-259259- ft_mach2 is set to a non-zero value if you wish for ftape to probe260260- for a Mountain MACH-2 controller.261261-262262- module | kernel command line263263- -----------------------|----------------------264264- ft_fdc_base=BASE | ftape=BASE,ioport265265- ft_fdc_irq=IRQ | ftape=IRQ,irq266266- ft_fdc_dma=DMA | ftape=DMA,dma267267- ft_probe_fc10=BOOL | ftape=BOOL,fc10268268- ft_mach2=BOOL | ftape=BOOL,mach2269269- ft_fdc_threshold=THR | ftape=THR,threshold270270- ft_fdc_rate_limit=RATE | ftape=RATE,datarate271271-272272-4. Example kernel parameter setting273273- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 274274- To configure ftape to probe for a Colorado FC-10/FC-20 controller275275- and to increase the amount of debugging output a little bit, add276276- the following line to `/etc/lilo.conf':277277-278278- append ftape=1,fc10 ftape=4,tracing279279-280280-5. Example module parameter setting281281- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~282282- To do the same, but with ftape compiled as a loadable kernel283283- module, add the following line to `/etc/modprobe.conf':284284-285285- options ftape ft_probe_fc10=1 ft_tracing=4286286-287287-*******************************************************************************288288-289289-D. Support and contacts290290- ====================291291-292292- Ftape is distributed under the GNU General Public License. There is293293- absolutely no warranty for this software. However, you can reach294294- the current maintainer of the ftape package under the email address295295- given in the MAINTAINERS file which is located in the top level296296- directory of the Linux kernel source tree. There you'll find also297297- the relevant mailing list to use as a discussion forum and the web298298- page to query for the most recent documentation, related work and299299- development versions of ftape.300300-301301- Changelog:302302- ==========303303-304304-~1996: Original Document305305-306306-10-24-2004: General cleanup and updating, noting additional module options.307307- James Nelson <james4765@gmail.com>
-3
Documentation/kernel-parameters.txt
···557557 floppy= [HW]558558 See Documentation/floppy.txt.559559560560- ftape= [HW] Floppy Tape subsystem debugging options.561561- See Documentation/ftape.txt.562562-563560 gamecon.map[2|3]=564561 [HW,JOY] Multisystem joystick and NES/SNES/PSX pad565562 support via parallel port (up to 5 devices per port)
···855855 depends TANBAC_TB022X856856 select GPIO_VR41XX857857858858-menu "Ftape, the floppy tape device driver"859859-860860-config FTAPE861861- tristate "Ftape (QIC-80/Travan) support"862862- depends on BROKEN_ON_SMP && (ALPHA || X86)863863- ---help---864864- If you have a tape drive that is connected to your floppy865865- controller, say Y here.866866-867867- Some tape drives (like the Seagate "Tape Store 3200" or the Iomega868868- "Ditto 3200" or the Exabyte "Eagle TR-3") come with a "high speed"869869- controller of their own. These drives (and their companion870870- controllers) are also supported if you say Y here.871871-872872- If you have a special controller (such as the CMS FC-10, FC-20,873873- Mountain Mach-II, or any controller that is based on the Intel 82078874874- FDC like the high speed controllers by Seagate and Exabyte and875875- Iomega's "Ditto Dash") you must configure it by selecting the876876- appropriate entries from the "Floppy tape controllers" sub-menu877877- below and possibly modify the default values for the IRQ and DMA878878- channel and the IO base in ftape's configuration menu.879879-880880- If you want to use your floppy tape drive on a PCI-bus based system,881881- please read the file <file:drivers/char/ftape/README.PCI>.882882-883883- The ftape kernel driver is also available as a runtime loadable884884- module. To compile this driver as a module, choose M here: the885885- module will be called ftape.886886-887887-source "drivers/char/ftape/Kconfig"888888-889889-endmenu890890-891858source "drivers/char/agp/Kconfig"892859893860source "drivers/char/drm/Kconfig"
···11-#22-# Ftape configuration33-#44-config ZFTAPE55- tristate "Zftape, the VFS interface"66- depends on FTAPE77- ---help---88- Normally, you want to say Y or M. DON'T say N here or you99- WON'T BE ABLE TO USE YOUR FLOPPY TAPE DRIVE.1010-1111- The ftape module itself no longer contains the routines necessary1212- to interface with the kernel VFS layer (i.e. to actually write data1313- to and read data from the tape drive). Instead the file system1414- interface (i.e. the hardware independent part of the driver) has1515- been moved to a separate module.1616-1717- To compile this driver as a module, choose M here: the1818- module will be called zftape.1919-2020- Regardless of whether you say Y or M here, an additional runtime2121- loadable module called `zft-compressor' which contains code to2222- support user transparent on-the-fly compression based on Ross2323- William's lzrw3 algorithm will be produced. If you have enabled the2424- kernel module loader (i.e. have said Y to "Kernel module loader2525- support", above) then `zft-compressor' will be loaded2626- automatically by zftape when needed.2727-2828- Despite its name, zftape does NOT use compression by default.2929-3030-config ZFT_DFLT_BLK_SZ3131- int "Default block size"3232- depends on ZFTAPE3333- default "10240"3434- ---help---3535- If unsure leave this at its default value, i.e. 10240. Note that3636- you specify only the default block size here. The block size can be3737- changed at run time using the MTSETBLK tape operation with the3838- MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the3939- shell command line).4040-4141- The probably most striking difference between zftape and previous4242- versions of ftape is the fact that all data must be written or read4343- in multiples of a fixed block size. The block size defaults to4444- 10240 which is what GNU tar uses. The values for the block size4545- should be either 1 or multiples of 1024 up to a maximum value of4646- 63488 (i.e. 62 K). If you specify `1' then zftape's builtin4747- compression will be disabled.4848-4949- Reasonable values are `10240' (GNU tar's default block size),5050- `5120' (afio's default block size), `32768' (default block size some5151- backup programs assume for SCSI tape drives) or `1' (no restriction5252- on block size, but disables builtin compression).5353-5454-comment "The compressor will be built as a module only!"5555- depends on FTAPE && ZFTAPE5656-5757-config ZFT_COMPRESSOR5858- tristate5959- depends on FTAPE!=n && ZFTAPE!=n6060- default m6161-6262-config FT_NR_BUFFERS6363- int "Number of ftape buffers (EXPERIMENTAL)"6464- depends on FTAPE && EXPERIMENTAL6565- default "3"6666- help6767- Please leave this at `3' unless you REALLY know what you are doing.6868- It is not necessary to change this value. Values below 3 make the6969- proper use of ftape impossible, values greater than 3 are a waste of7070- memory. You can change the amount of DMA memory used by ftape at7171- runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer7272- wastes 32 KB of memory. Please note that this memory cannot be7373- swapped out.7474-7575-config FT_PROC_FS7676- bool "Enable procfs status report (+2kb)"7777- depends on FTAPE && PROC_FS7878- ---help---7979- Optional. Saying Y will result in creation of a directory8080- `/proc/ftape' under the /proc file system. The files can be viewed8181- with your favorite pager (i.e. use "more /proc/ftape/history" or8282- "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The8383- file will contain some status information about the inserted8484- cartridge, the kernel driver, your tape drive, the floppy disk8585- controller and the error history for the most recent use of the8686- kernel driver. Saying Y will enlarge the size of the ftape driver8787- by approximately 2 KB.8888-8989- WARNING: When compiling ftape as a module (i.e. saying M to "Floppy9090- tape drive") it is dangerous to use ftape's /proc file system9191- interface. Accessing `/proc/ftape' while the module is unloaded will9292- result in a kernel Oops. This cannot be fixed from inside ftape.9393-9494-choice9595- prompt "Debugging output"9696- depends on FTAPE9797- default FT_NORMAL_DEBUG9898-9999-config FT_NORMAL_DEBUG100100- bool "Normal"101101- ---help---102102- This option controls the amount of debugging output the ftape driver103103- is ABLE to produce; it does not increase or diminish the debugging104104- level itself. If unsure, leave this at its default setting,105105- i.e. choose "Normal".106106-107107- Ftape can print lots of debugging messages to the system console108108- resp. kernel log files. Reducing the amount of possible debugging109109- output reduces the size of the kernel module by some KB, so it might110110- be a good idea to use "None" for emergency boot floppies.111111-112112- If you want to save memory then the following strategy is113113- recommended: leave this option at its default setting "Normal" until114114- you know that the driver works as expected, afterwards reconfigure115115- the kernel, this time specifying "Reduced" or "None" and recompile116116- and install the kernel as usual. Note that choosing "Excessive"117117- debugging output does not increase the amount of debugging output118118- printed to the console but only makes it possible to produce119119- "Excessive" debugging output.120120-121121- Please read <file:Documentation/ftape.txt> for a short description122122- how to control the amount of debugging output.123123-124124-config FT_FULL_DEBUG125125- bool "Excessive"126126- help127127- Extremely verbose output for driver debugging purposes.128128-129129-config FT_NO_TRACE130130- bool "Reduced"131131- help132132- Reduced tape driver debugging output.133133-134134-config FT_NO_TRACE_AT_ALL135135- bool "None"136136- help137137- Suppress all debugging output from the tape drive.138138-139139-endchoice140140-141141-comment "Hardware configuration"142142- depends on FTAPE143143-144144-choice145145- prompt "Floppy tape controllers"146146- depends on FTAPE147147- default FT_STD_FDC148148-149149-config FT_STD_FDC150150- bool "Standard"151151- ---help---152152- Only change this setting if you have a special controller. If you153153- didn't plug any add-on card into your computer system but just154154- plugged the floppy tape cable into the already existing floppy drive155155- controller then you don't want to change the default setting,156156- i.e. choose "Standard".157157-158158- Choose "MACH-2" if you have a Mountain Mach-2 controller.159159- Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20160160- controller.161161- Choose "Alt/82078" if you have another controller that is located at162162- an IO base address different from the standard floppy drive163163- controller's base address of `0x3f0', or uses an IRQ (interrupt)164164- channel different from `6', or a DMA channel different from165165- `2'. This is necessary for any controller card that is based on166166- Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high167167- speed" controllers.168168-169169- If you choose something other than "Standard" then please make170170- sure that the settings for the IO base address and the IRQ and DMA171171- channel in the configuration menus below are correct. Use the manual172172- of your tape drive to determine the correct settings!173173-174174- If you are already successfully using your tape drive with another175175- operating system then you definitely should use the same settings176176- for the IO base, the IRQ and DMA channel that have proven to work177177- with that other OS.178178-179179- Note that this menu lets you specify only the default setting for180180- the hardware setup. The hardware configuration can be changed at181181- boot time (when ftape is compiled into the kernel, i.e. if you182182- have said Y to "Floppy tape drive") or module load time (i.e. if you183183- have said M to "Floppy tape drive").184184-185185- Please read also the file <file:Documentation/ftape.txt> which186186- contains a short description of the parameters that can be set at187187- boot or load time. If you want to use your floppy tape drive on a188188- PCI-bus based system, please read the file189189- <file:drivers/char/ftape/README.PCI>.190190-191191-config FT_MACH2192192- bool "MACH-2"193193-194194-config FT_PROBE_FC10195195- bool "FC-10/FC-20"196196-197197-config FT_ALT_FDC198198- bool "Alt/82078"199199-200200-endchoice201201-202202-comment "Consult the manuals of your tape drive for the correct settings!"203203- depends on FTAPE && !FT_STD_FDC204204-205205-config FT_FDC_BASE206206- hex "IO base of the floppy disk controller"207207- depends on FTAPE && !FT_STD_FDC208208- default "0"209209- ---help---210210- You don't need to specify a value if the following default211211- settings for the base IO address are correct:212212- <<< MACH-2 : 0x1E0 >>>213213- <<< FC-10/FC-20: 0x180 >>>214214- <<< Secondary : 0x370 >>>215215- Secondary refers to a secondary FDC controller like the "high speed"216216- controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.217217- Please make sure that the setting for the IO base address218218- specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR219219- CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already220220- successfully using the tape drive with another operating system then221221- you definitely should use the same settings for the IO base that has222222- proven to work with that other OS.223223-224224- Note that this menu lets you specify only the default setting for225225- the IO base. The hardware configuration can be changed at boot time226226- (when ftape is compiled into the kernel, i.e. if you specified Y to227227- "Floppy tape drive") or module load time (i.e. if you have said M to228228- "Floppy tape drive").229229-230230- Please read also the file <file:Documentation/ftape.txt> which231231- contains a short description of the parameters that can be set at232232- boot or load time.233233-234234-config FT_FDC_IRQ235235- int "IRQ channel of the floppy disk controller"236236- depends on FTAPE && !FT_STD_FDC237237- default "0"238238- ---help---239239- You don't need to specify a value if the following default240240- settings for the interrupt channel are correct:241241- <<< MACH-2 : 6 >>>242242- <<< FC-10/FC-20: 9 >>>243243- <<< Secondary : 6 >>>244244- Secondary refers to secondary a FDC controller like the "high speed"245245- controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.246246- Please make sure that the setting for the IO base address247247- specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR248248- CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already249249- successfully using the tape drive with another operating system then250250- you definitely should use the same settings for the IO base that has251251- proven to work with that other OS.252252-253253- Note that this menu lets you specify only the default setting for254254- the IRQ channel. The hardware configuration can be changed at boot255255- time (when ftape is compiled into the kernel, i.e. if you said Y to256256- "Floppy tape drive") or module load time (i.e. if you said M to257257- "Floppy tape drive").258258-259259- Please read also the file <file:Documentation/ftape.txt> which260260- contains a short description of the parameters that can be set at261261- boot or load time.262262-263263-config FT_FDC_DMA264264- int "DMA channel of the floppy disk controller"265265- depends on FTAPE && !FT_STD_FDC266266- default "0"267267- ---help---268268- You don't need to specify a value if the following default269269- settings for the DMA channel are correct:270270- <<< MACH-2 : 2 >>>271271- <<< FC-10/FC-20: 3 >>>272272- <<< Secondary : 2 >>>273273- Secondary refers to a secondary FDC controller like the "high speed"274274- controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.275275- Please make sure that the setting for the IO base address276276- specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR277277- CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already278278- successfully using the tape drive with another operating system then279279- you definitely should use the same settings for the IO base that has280280- proven to work with that other OS.281281-282282- Note that this menu lets you specify only the default setting for283283- the DMA channel. The hardware configuration can be changed at boot284284- time (when ftape is compiled into the kernel, i.e. if you said Y to285285- "Floppy tape drive") or module load time (i.e. if you said M to286286- "Floppy tape drive").287287-288288- Please read also the file <file:Documentation/ftape.txt> which289289- contains a short description of the parameters that can be set at290290- boot or load time.291291-292292-config FT_FDC_THR293293- int "Default FIFO threshold (EXPERIMENTAL)"294294- depends on FTAPE && EXPERIMENTAL295295- default "8"296296- help297297- Set the FIFO threshold of the FDC. If this is higher the DMA298298- controller may serve the FDC after a higher latency time. If this is299299- lower, fewer DMA transfers occur leading to less bus contention.300300- You may try to tune this if ftape annoys you with "reduced data301301- rate because of excessive overrun errors" messages. However, this302302- doesn't seem to have too much effect.303303-304304- If unsure, don't touch the initial value, i.e. leave it at "8".305305-306306-config FT_FDC_MAX_RATE307307- int "Maximal data rate to use (EXPERIMENTAL)"308308- depends on FTAPE && EXPERIMENTAL309309- default "2000"310310- ---help---311311- With some motherboard/FDC combinations ftape will not be able to312312- run your FDC/tape drive combination at the highest available313313- speed. If this is the case you'll encounter "reduced data rate314314- because of excessive overrun errors" messages and lots of retries315315- before ftape finally decides to reduce the data rate.316316-317317- In this case it might be desirable to tell ftape beforehand that318318- it need not try to run the tape drive at the highest available319319- speed. If unsure, leave this disabled, i.e. leave it at 2000320320- bits/sec.321321-322322-config FT_ALPHA_CLOCK323323- int "CPU clock frequency of your DEC Alpha" if ALPHA324324- depends on FTAPE325325- default "0"326326- help327327- On some DEC Alpha machines the CPU clock frequency cannot be328328- determined automatically, so you need to specify it here ONLY if329329- running a DEC Alpha, otherwise this setting has no effect.330330-
-28
drivers/char/ftape/Makefile
···11-#22-# Copyright (C) 1997 Claus Heine.33-#44-# This program is free software; you can redistribute it and/or modify55-# it under the terms of the GNU General Public License as published by66-# the Free Software Foundation; either version 2, or (at your option)77-# any later version.88-# 99-# This program is distributed in the hope that it will be useful,1010-# but WITHOUT ANY WARRANTY; without even the implied warranty of1111-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212-# GNU General Public License for more details.1313-# 1414-# You should have received a copy of the GNU General Public License1515-# along with this program; see the file COPYING. If not, write to1616-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-#1818-# $Source: /homes/cvs/ftape-stacked/ftape/Makefile,v $1919-# $Revision: 1.4 $2020-# $Date: 1997/10/05 19:17:56 $2121-#2222-# Makefile for the QIC-40/80/3010/3020 floppy-tape driver for2323-# Linux.2424-#2525-2626-obj-$(CONFIG_FTAPE) += lowlevel/2727-obj-$(CONFIG_ZFTAPE) += zftape/2828-obj-$(CONFIG_ZFT_COMPRESSOR) += compressor/
-81
drivers/char/ftape/README.PCI
···11-Some notes for ftape users with PCI motherboards:22-=================================================33-44-The problem:55-------------66-77-There have been some problem reports from people using PCI-bus based88-systems getting overrun errors.99-I wasn't able to reproduce these until I ran ftape on a Intel Plato1010-(Premiere PCI II) motherboard with bios version 1.00.08AX1.1111-It turned out that if GAT (Guaranteed Access Timing) is enabled (?)1212-ftape gets a lot of overrun errors.1313-The problem disappears when disabling GAT in the bios.1414-Note that Intel removed this setting (permanently disabled) from the1515-1.00.10AX1 bios !1616-1717-It looks like that if GAT is enabled there are often large periods1818-(greater than 120 us !??) on the ISA bus that the DMA controller cannot1919-service the floppy disk controller.2020-I cannot imagine this being acceptable in a decent PCI implementation.2121-Maybe this is a `feature' of the chipset. I can only speculate why2222-Intel choose to remove the option from the latest Bios...2323-2424-The lesson of this all is that there may be other motherboard2525-implementations having the same of similar problems.2626-If you experience a lot of overrun errors during a backup to tape,2727-see if there is some setting in the Bios that may influence the2828-bus timing.2929-3030-I judge this a hardware problem and not a limitation of ftape ;-)3131-My DOS backup software seems to be suffering from the same problems3232-and even refuses to run at 1 Mbps !3333-Ftape will reduce the data-rate from 1 Mbps to 500 Kbps if the number3434-of overrun errors on a track exceeds a threshold.3535-3636-3737-Possible solutions:3838--------------------3939-4040-Some of the problems were solved by upgrading the (flash) bios.4141-Other suggest that it has to do with the FDC being on the PCI4242-bus, but that is not the case with the Intel Premiere II boards.4343-[If upgrading the bios doesn't solve the problem you could try4444-a floppy disk controller on the isa-bus].4545-4646-Here is a list of systems and recommended BIOS settings:4747-4848-4949- Intel Premiere PCI (Revenge):5050-5151-Bios version 1.00.09.AF2 is reported to work.5252-5353-5454-5555- Intel Premiere PCI II (Plato):5656-5757-Bios version 1.00.10.AX1 and version 11 beta are ok.5858-If using version 1.00.08.AX1, GAT must be disabled !5959-6060-6161-6262- ASUS PCI/I-SP3G:6363-6464-Preferred settings: ISA-GAT-mode : disabled6565- DMA-linebuffer-mode : standard6666- ISA-masterbuffer-mode : standard6767-6868-6969- DELL Dimension XPS P907070-7171-Bios version A2 is reported to be broken, while bios version A5 works.7272-You can get a flash bios upgrade from http://www.dell.com7373-7474-7575-To see if you're having the GAT problem, try making a backup7676-under DOS. If it's very slow and often repositions you're7777-probably having this problem.7878-7979- --//--8080- LocalWords: ftape PCI bios GAT ISA DMA chipset Mbps Kbps FDC isa AF ok ASUS8181- LocalWords: SP linebuffer masterbuffer XPS http www com
-966
drivers/char/ftape/RELEASE-NOTES
···11-Hey, Emacs, we're -*-Text-*- mode!22-33-===== Release notes for ftape-3.04d 25/11/97 =====44-- The correct pre-processor statement for "else if" is "#elif" not55- "elsif".66-- Need to call zft_reset_position() when overwriting cartridges77- previously written with ftape-2.x, sftape, or ancient88- (pre-ftape-3.x) versions of zftape.99-1010-===== Release notes for ftape-3.04c 16/11/97 =====1111-- fdc_probe() was calling DUMPREGS with a result length of "1" which1212- was just fine. Undo previous change.1313-1414-===== Release notes for ftape-3.04b 14/11/97 =====1515-1616-- patches/2.x.x/floppy.c.diff was somewhat broken, releasing i/o1717- regions it never had allocated.1818-- fdc_probe() was calling DUMPREGS with a result length of "1" instead1919- of "10"2020-- Writing deleted data marks if the first segents on track zero are2121- should work now.2222-- ftformat should now be able to handle those cases where the tape2323- drive sets the read only status bit (QIC-40/80 cartridges with2424- QIC-3010/3020 tape drives) because the header segment is damaged.2525-- the MTIOCFTCMD ioctl may now be issued by the superuser ONLY.2626-2727-===== Release notes for ftape-3.04a 12/11/97 =====2828-- Fix an "infinite loop can't be killed by signal" bug in2929- ftape_get_drive_status(). Only relevant when trying to access3030- buggy/misconfigured hardware3131-- Try to compensate a bug in the HP Colorado T3000's firmware: it3232- doesn't set the write protect bit for QIC80/QIC40 cartridges.3333-3434-===== Release notes for ftape-3.04 06/11/97 =====3535-- If positioning with fast seeking fails fall back to a slow seek3636- before giving up.3737-- (nearly) no retries on "no data errors" when verifying after3838- formatting. Improved tuning of the bad sector map after formatting.3939-- the directory layout has changed again to allow for easier kernel4040- integration4141-- Module parameter "ftape_tracing" now is called "ft_tracing" because4242- the "ftape_tracing" variable has the version checksum attached to it.4343-- `/proc/ftape' interface for 2.0.* kernels. `/proc/ftape' no longer4444- is a directory but a file that contains all the information formerly4545- provided in separate files under the `/proc/ftape/' directory.4646-- Most of the configuration options have been prefixed by "CONFIG_FT_"4747- in preparation of the kernel inclusion. The Makefiles under4848- "./ftape/" should be directly usable by the kernel.4949-- The MODVERSIONS stuff is now auto-detected.5050-- Broke backslashed multi line options in MCONFIG into separate lines5151- using GNU-make's "+=" feature.5252-- The html and dvi version of the manual is now installed under5353- '/usr/doc/ftape` with 'make install`5454-- New SMP define in MCONFIG. ftape works with SMP if this is defined.5555-- attempt to cope with "excessive overrun errors" by gradually5656- increasing FDC FIFO threshold. But this doesn't seem to have too5757- much an effect.5858-- New load time configuration parameter "ft_fdc_rate_limit". If you5959- encounter too many overrun errors with a 2Mb controller then you6060- might want to set this to 1000.6161-- overrun errors on the last sector in a segment sometimes result in6262- a zero DMA residue. Dunno why, but compensate for it.6363-- there were still fdc_read() timeout errors. I think I have fixed it6464- now, please FIXME.6565-- Sometimes ftape_write() failed to re-start the tape drive when a6666- segment without a good sector was reached ("wait for empty segment6767- failed"). This is fixed. Especially important for > QIC-3010.6868-- sftape (aka ftape-2.x) has vanished. I didn't work on it for6969- ages. It is probably still possible to use the old code with7070- ftape-3.04, if one really needs it (BUT RECOMPILE IT)7171-- zftape no longer alters the contents of already existing volume7272- table entries, which makes it possible to fill in missing fields,7373- like time stamps using some user space program.7474-- ./contrib/vtblc/ contains such a program.7575-- new perl script ./contrib/scripts/listtape that list the contents of a7676- floppy tape cartridge parsing the output of "mt volinfo" + "mt fsf"7777-- the MTWEOF implementation has changed a little bit (after I had a7878- look at amanda). Calling MTWEOF while the tape is still held open7979- after writing something to the tape now will terminate the current8080- volume, and start a new one at the current position.8181-- the volume table maintained by zftape now is a doubly linked list8282- that grows dynamically as needed.8383-8484- formatting floppy tape cartridges8585- ---------------------------------8686- * there is a new user space formatting program that does most of the8787- dirty work in user space (auto-detect, computing the sector8888- coordinates, adjusting time stamps and statistics). It has a8989- simple command line interface.9090- * ftape-format.o has vanished, it has been folded into the low level9191- ftape.o module, and the ioctl interface into zftape.o. Most of the9292- complicated stuff has been moved to user space, so there was no9393- need for a separate module anymore.9494- * there is a new ioctl MTIOCFTCMD that sends a bare QIC-117 command9595- to the tape drive.9696- * there is a new mmap() feature to map the dma buffers into user9797- space to be used by the user level formatting program.9898- * Formatting of yet unformatted or totally degaussed cartridges9999- should be possible now. FIXME.100100-101101-===== Release notes for ftape-3.03b, <forgot the exact date> ====102102-103103-ftape-3.03b was released as a beta release only. Its main new feature104104-was support of the DITTO-2GB drive. This was made possible by reverse105105-engineering done by <fill in his name> after Iomega failed to support106106-ftape. Although they had promised to do so (this makes me feel a bit107107-sad and uncomfortable about Iomega).108108-109109-===== Release notes for ftape-3.03a, 22/05/97 ====110110-111111-- Finally fixed auto-un-loading of modules for kernels > 2.1.18112112-- Add an "uninstall" target to the Makefile113113-- removed the kdtime hack114114-- texi2www didn't properly set the back-reference from a footnote back115115- to the regular text.116116-117117- zftape specific118118- ---------------119119- * hide the old compression map volume. Taper doesn't accept the120120- presence of non-Taper volumes and Taper-written volume on the same121121- tape.122122- * EOD (End Of Data) handling was still broken: the expected behavior123123- is to return a zero byte count at the first attempt to read past124124- EOD, return a zero byte count at the second attempt to read past125125- EOD and THEN return -EIO.126126-127127- ftape-format specific128128- ---------------------129129- * Detection of QIC-40 cartridges in select_tape_format() was broken130130- and made it impossible to format QIC-3010/3020 cartridges.131131- * There are strange "TR-1 Extra" cartridges out there which weren't132132- detected properly because the don't strictly conform to the133133- QIC-80, Rev. N, spec.134134-135135-===== Release notes for ftape-3.03, 30/04/97 =====136136-137137-- Removed kernel integration code from the package. I plan to provide138138- a package that can be integrated into the stock kernel separately139139- (hopefully soon).140140- As a result, a simple `make' command now will build everything.141141-- ALL compile time configuration options have been moved to the file142142- `MCONFIG'.143143-- Quite a few `low level' changes to allow formatting of cartridges.144144-- formatting is implemented as a separate module `ftape-format.o'. The145145- modified `mt' program contains sample code that shows how to use it.146146-- The VFS interface has been moved from the `ftape.o' module to the147147- high level modules `zftape.o' resp. `sftape.o'. `ftape.o' contains148148- the hardware support only.149149-- A bit of /proc support for kernels > 2.1.28150150-- Moved documentation to Doc subdir. INSTALL now contains some real151151- installation notes.152152-- `install' target in Makefile.153153-154154-zftape specific:155155-----------------156156-157157-- zftape works for large cartridges now ( > 2^31 bytes)158158-- MTIOCVOLINFO and MTIOCGETSIZE now return the size in KILOBYTES,159159- NO LONGER in bytes.160160-161161-- permissions for write access to a cartridge have changed:162162- * zftape now also takes the file access mode into account163163- * zftape no longer allows writing in the middle of the recorded164164- media. The tape has to be positioned at BOT or EOD for write165165- access.166166-167167-- MTBSF has changed. It used to position at the beginning of the168168- previous file when called with count 1. This was different from the169169- expected behavior for other Un*x tape drivers (i.e. SCSI). MTBSF170170- with count 1 should merely position at the beginning of the current171171- volume. Fixed. As a result, `tar --verify' now produces the desired172172- result: it verifies the last written volume, not the pre-last173173- written volume.174174-175175-- The compression map has vanished --> no need for `mt erase' any176176- more. Fast seeking in a compressed volume is still be possible, but177177- takes slightly longer. As a side effect, you may experience an178178- additional volume showing up in front of all others for old179179- cartridges. This is the tape volume that holds the compression map.180180-181181-- The compression support for zftape has been moved to a separate182182- module `zft-compressor'. DON'T forget to load it before trying to183183- read back compressed volumes. The stock `zftape.o' module probes for184184- the module `zft-compressor' using the kerneld message channel; you185185- have to install `zft-compressor.o' in a place where modprobe can186186- find it if you want to use this.187187-188188-- New experimental feature that tries to get the broken down GMT time189189- from user space via a kernel daemon message channel. You need to190190- compile and start the `kdtime' daemon contained in the contrib191191- directory to use it. Needed (?) for time stamps in the header192192- segments and the volume table.193193-194194-- variable block size mode via MTSETBLK 0195195-196196-- keep modules locked in memory after the block size has been changed197197-198198-sftape specific:199199-----------------200200-201201-- end of tape handling should be fixed, i.e. multi volume archives202202- written with `afio' can be read back now.203203-204204-205205-===== Release notes for ftape-3.02a, 09/01/97 =====206206-207207-No big news:208208-- call zft_init() resp. sft_init() when compiling the entire stuff209209- into the kernel image.210210-- fix bug in ftape-setup.c when NO_TRACE_AT_ALL was defined.211211-- fix bug in sftape-eof.c/zftape-eof.c for old kernels (1.2.*)212212-- add support for new module interface for recent kernels213213-214214-===== Release notes for ftape-3.02, 16/12/96 =====215215-- Fixed the `FDC unlock command failed' bug in fdc-io.c. When the FIFO216216- was already locked when ftape was loaded, ftape failed to unlock it.217217-- Fixed compilation of `contrib/gnumt'. It now finds `mtio.h' even if218218- ftape is NOT included into the kernel source tree.219219-- fc-10.c: include <asm/io.h> for inb() and outb().220220-- ftape/sftape/zftape: all global variable now have either a `ftape_',221221- a `ft_', `sft_', `zft_' or `qic_' prefix to prevent name clashes222222- with other parts of the kernel when including ftape into the kernel223223- source tree.224224-- Kerneld support has changed. `ftape' now searches for a module225225- `ftape-frontend' when none of the frontend (`sftape' or `zftape') is226226- loaded. Please refer to the `Installation/Loading ftape' section of227227- the TeXinfo manual.228228-- Add load resp. boot-time configuration of ftape. There are now229229- variables ft_fdc_base, ft_fdc_dma and ft_fdc_irq corresponding to230230- the former FDC_BASE etc. compile time definitions. One can also use231231- the kernel command line parameters to configure the driver if it is232232- compiled into the kernel. Also, the FC-10/FC-20 support is load-time233233- configurable now as well as the MACH-II hack (ft_probe_fc10,234234- resp. ft_mach2). Please refer to the section `Installation/Configure235235- ftape' of the TeXinfo manual.236236-- I removed the MODVERSIONS option from `Makefile.module'. Let me alone237237- with ftape and MODVERSIONS unless you include the ftape sources into238238- the kernel source tree.239239-- new vendors in `vendors.h':240240- * HP Colorado T3000 241241- * ComByte DoublePlay (including a bug fix for their broken242242- formatting software, thanks to whraven@njackn.com)243243- * Iomega DITTO 2GIG. NOTE: this drive cannot work with ftape because244244- the logical data layout of the cartridges used by this drive does245245- NOT conform to the QIC standards, it is a special Iomega specific246246- format. I've sent mail to Iomega but didn't receive an answer247247- yet. If you want this drive to be supported by ftape, ask Iomega248248- to give me information about it.249249-- zftape:250250- * re-introduced the MTIOC_ZFTAPE_GETBLKSZ ioctl for compatibility251251- with zftape 1.06a and earlier. Please don't use it when writing252252- new software, use the MTIOCVOLINFO ioctl instead.253253- * Major overhaul of the code that updates the header segments. Never254254- change the tape label unless erasing the tape. Thus we almost255255- never need to write the header segments, unless we would modify256256- the bad sector map which isn't done yet. Updating of volume table257257- and compression map more secure now although it takes a bit258258- longer.259259- * Fixed bug when aborting a write operation with a signal: zftape260260- now finishes the current volume (i.e. writes an eof marker) at the261261- current position. It didn't before which led to somehow *strange*262262- behavior in this cases.263263- * Keep module locked in memory when using it with the non-rewinding264264- devices and the tape is not logical at BOT. Needed for kerneld265265- support.266266-- sftape:267267- * Keep module locked in memory when using it with the non-rewinding268268- devices and the tape is not logical at BOT. Needed for kerneld269269- support.270270-271271-===== Release notes for ftape-3.01, 14/11/96 =====272272-273273-- Fixed silly bugs in ftape-3.00:274274- * MAKEDEV.ftape: major device number must be 27, not 23 275275- * sftape/sftape-read.c: sftape_read_header_segments() called 276276- itself recursively instead of calling ftape_read_header_segment()277277- * zftape/qic-vtbl.h: conversion of ftape's file marks to zftape's278278- internal volume table was broken.279279- * patches/2.x.x/linux-2.0.21.dif: my RCS (resp. CVS) system replaced280280- the `$Revison:' etc. macros in the `ftape.h' concerning part of the281281- patch :-( Fixed.282282- * info/ftape.info: Fixed misspellings (`cp' <-> `cp -r' etc.)283283- * when ftape/sftape or ftape/zftape was compiled into the kernel the284284- variable ftape_status was declared twice. Fixed.285285- * removed reference to undeclared variable kernel_version when not286286- compiling as module287287- * fixed a bug introduced by the use of bit-fields for some flags288288- (i.e. write_protected, no_cartridge, formatted)289289- * flag `header_read' is now reset correctly to zero when tape is290290- removed.291291-- fixed a bug in sftape/sftape-eof.c that was already in the original292292- ftape code. MTFSF/BSF was not handled correctly when positioned293293- right before the file mark (think of tar)294294-- Changed TRACE macros (following a suggestion of Marcin Dalecki) to use295295- the predefined __FUNCTION__ macro of GCC. Spares about 4k of code.296296-- added new vendor id for Iomega DITTO 2GIG297297-- fixed a bug already present in zftape-1.06 when aborting a write298298- with a signal: we now finish the current volume at that299299- position. Header segments remain NOT up to date until an explicit call300300- to MTREW or MTOFFL is done. 301301-302302-===== Release notes for ftape-3.00, 14/10/96 =====303303-304304-- Merged ftape with zftape. There are three modules now:305305- ftape for the hardware support, sftape for the implementation of the306306- original ftape eof mark stuff and zftape that implements zftape's way307307- of handling things (compression, volume table, tape blocks of308308- constant length)309309-- Documentation in TeXinfo format in the `info' subdirectory.310310-- New ioctls for zftape. See zftape/zftape.h311311-- Dummy formatting ioctl for ftape. See ftape.h312312-- Kernel patch files for the 2.*.* series to include ftape-3.00 in the313313- kernel source tree. These includes a kernel compatible Config.in314314- script and fairly large online information for the kernel configure315315- script.316316-- Support for compiling with Linux-1.2.13. 317317-- Modified GNU mt from their cpio package that can handle the new318318- ioctls.319319-- ftape/sftape/zftape is kerneld save now!320320-321321-Notes on sftape:322322-- sftape implements the eof handling code of the original ftape. If323323- you like to stick with the original ftape stuff, you have to use324324- this module, not zftape.325325-- sftape is kerneld save, unlike the original ftape.326326-- we keep the entire header segment now in memory, so no need to read327327- it before updating the header segments. Additional memory328328- consumption: 256 bytes. 329329-330330-Notes for zftape:331331-- zftape has support for tapes with format code 6 now, which use a332332- slightly different volume table format compared with other floppy333333- tapes.334334-- new ioctls for zftape. Have a look at zftape/zftape.h335335-- The internal volume table representation has changed for zftape. Old336336- cartridges are converted automatically.337337-- zftape no longer uses compression map segments, which have vanished338338- from the QIC specs, but creates volume table entry that reserves339339- enough space for the compression map. 340340-- zftape is kerneld save now.341341-- we keep the entire header segment now in memory, so no need to read342342- it before updating the header segments. Additional memory343343- consumption: 256 bytes. 344344-345345-Notes for contrib/gnumt:346346-- modified mt from the GNU cpio package that supports all the new347347- ioctls of zftape.348348-Notes for contrib/swapout:349349-- This contains the swapout.c program that was written by Kai350350- Harrekilde-Pederson. I simply added a Makefile.351351-352352-===== Release notes for ftape-2.10, 14/10/96 =====353353-354354-The ftape maintainer has changed. 355355-Kai Harrekilde-Petersen <khp@dolphinics.no>356356-has resigned from maintaining ftape, and I,357357-Claus-Justus Heine <claus@momo.math.rwth-aachen.de>,358358-have taken over.359359-360360-- Added support for tapes with `format code 6', i.e. QIC-3020 tapes361361- with more than 2^16 segments.362362-- merged changes made by Bas Laarhoven with ftape-2.09. Refer363363- to his release notes below. I've included them into this364364- file unchanged for your reference.365365-- disabled call stack back trace for now. This new feature366366- introduced by the interim release 2.0.x still seems to367367- be buggy.368368-- Tried to minimize differences between the ftape version369369- to be included into the kernel source tree and the standalone370370- module version.371371-- Reintroduced support for Linux-1.2.13. Please refer to the372372- Install-guide. 373373-374374-===== Release notes for ftape-2.09, 16/06/96 =====375375-376376-There aren't any really big news in this release, mostly just that I377377-(the maintainer) have changed my email address (due to a new job). My378378-new address is <khp@dolphinics.no>379379-380380-- The CLK_48MHZ and FDC_82078SL options has gone (all 2Mbps cards seem381381- to use a 48MHz oscillator anyway and I haven't heard of an 'SL382382- chip out there).383383-- The S82078B has been `downgraded' to i82077AA compability.384384-- TESTING option revived. Right now, it'll enable the (seriously broken)385385- 2Mbps code. If you enable it, you'll experience a tape drive that's386386- *really* out to lunch!387387-- Some (bold) changes in the init code. Please notify me if they388388- break things for you.389389-390390-===== Release notes for ftape-2.08, 14/03/96 =====391391-392392-If you correct a problem with ftape, please send your patch to393393-khp@dolphinics.no too.394394-395395-- Updated to reflect that NR_MEM_LISTS is gone in 1.3.74396396-- Teac 700 added to list of known drives.397397-- The registered device name is now "ft" rather than "ftape".398398-399399-===== Release notes for ftape-2.07a, 14/03/96 =====400400-401401-Bugfixes by Marcin Dalecki <dalecki@namu03.gwdg.de>:402402-- In the last release it just compiled against 1.3.70;403403- now the params to request_irq() and free_irq are() are fixed, so it also 404404- works in 1.3.73 :-)405405-- Support for modules is now correct for newer kernels.406406-407407-===== Release notes for ftape-2.07, 04/03/96 =====408408-409409-410410-- ftape updated to compile against 1.3.70.411411-- Iomega 700 and Wangtek 3200 recognised.412412-413413-414414-===== Release notes for ftape-2.06b, 13/02/96 =====415415-416416-Another simple bugfix version.417417-418418-- Jumbo 700 recognised.419419-- Typo in vendors.h fixed.420420-421421-422422-===== Release notes for ftape-2.06a, 10/02/96 =====423423-424424-This release is a simple bugfix version.425425-426426-- Linux/SMP: ftape *should* work.427427-- FC-10/20: Only accepts IRQs 3-7, or 9. If IRQ 9, properly tell the card428428- to use IRQ 2. Thanks to Greg Crider (gcrider@iclnet.org) for finding and429429- locating this bug and testing the patch.430430-- Insight drive recognised correctly again.431431-- Motor-on wakeup version of the Iomega 250 drive added432432-433433-434434-===== Release notes for ftape-2.06, 28/01/96 =====435435-436436-Special thanks go to Neal Friedman and Steven Sorbom for their437437-help in producing and testing this release.438438-439439-I have continued to clean up the code, with an eye towards inclusion440440-of ftape in Linus' official kernel (In fact, as I type this, I am441441-running on a kernel with ftape support statically linked). I have442442-test-compiled ftape against my 1.2.13 tree without problems.443443-Hopefully, everything should be OK for the v1.2.x people.444444-445445-WARNING! Alan Cox has mailed me that ftape does *NOT* work with446446-Linux/SMP. If you try to run ftape under Linux/SMP, it will cause a447447-kernel deadlock (which is worse than a panic).448448-449449-- QIC-3020/TR-3: 1Mbps support works. Neal is capable of reading and450450- writing data to a tape. ftape will automatically detect the type of451451- tape (e.g. TR-3 vs QIC-80) and move the fdc in and out of452452- "perpendicular mode" as necessary.453453-- 2Mbps support is disabled by default, since it is not fully454454- debugged. If you are adventurous, remove -DFDC_82078SL in the455455- Makefile and see what happens :-)456456-- fdc detection: silly bugs removed (Only 2Mbps fdcs were affected)457457- and added detection of the National Semiconductors PC8744 fdc chip458458- (used in the PC873xx "super-IO" chips).459459-- Removed warning about incompatible types when compiling with Linux460460- 1.2.x.461461-- README.PCI updated with info about the DELL Dimension XPS P90.462462-- Connor TST3200R added to detected drives.463463-- `swapout' utility added to distribution. It will dirty 5Meg of464464- memory, trying to swap out other programs. Just say `make swapout'465465- to build it. ftape will do this automatically Real Soon Now (ie:466466- when I have found out which kernel memory alloc function to call).467467-468468-469469-===== Release notes for ftape-2.05, 08/01/96 =====470470-471471-- For v1.2.x Kernels, you must apply the patch linux-1.2/ksyms.patch to472472- the kernel and rebuild it (it adds the __get_dma_pages symbol to473473- ksyms.c).474474-- Included new asm-i386/io.h file from v1.3.x kernel series, to enable475475- gcc v.2.7.[12] to compile v1.2.x kernels (linux-1.2/io.h).476476-- Module versions: If you wish to compile ftape as a versioned module,477477- you must first compile your kernel with CONFIG_MODVERSIONS=y.478478- Otherwise, you will get complaints that <linux/modversions.h> does not479479- exist (if that happens, a `touch modversions.h' will help you out).480480-- CLK_48MHZ: new define in the Makefile (default: non-zero). If you have481481- a tape controller card that uses the i82078(-1) chip, but cannot get482482- it to work with ftape, try set it to 0 (and please report this).483483-- QIC-3010/3020: Complete support is still missing, but will hopefully484484- come soon. Steven Sorbom has kindly provided me with hints about485485- this. Writing of QIC-3020 tapes definitely does NOT work (do not try486486- it! - the drive will not be in "perpendicular mode" and this will ruin487487- the formatting info on the tape).488488-- ftape_num_buffers is out of fashion: use NR_BUFFERS instead (and489489- recompile if you want to change it :-).490490-491491-492492-===== Release notes for ftape-2.04, 01/01/96 =====493493-494494-This version by Kai Harrekilde-Petersen <khp@dolphinics.no>495495-496496-- ALERT! Support for Kernels earlier then v1.1.85 is about to go away.497497- I intend to clean up some of the code (getting rid of an annoyingly498498- large numbers of #ifdef mostly), which means that support for499499- pre-1.1.85 kernels must go as well.500500-- NR_FTAPE_BUFFERS is gone; You can instead select the number of dma501501- buffers by saying `insmod ftape.o ftape_num_buffer=<n>' instead.502502-- Configure script gone. ftape will now automagically determine your503503- kernel version by /usr/include/linux/version.h instead.504504-- CONFIG_MODVERSIONS now work. All combinations of versioned /505505- unversioned kernel and ftape module works (at least with my 1.3.52506506- kernel).507507-- If you have problems with inserting ftape into an old (1.2.x)508508- kernel (e.g. insmod says "1.2.8 does not match 1.2.8), recompile509509- your modules utilities with your new compiler.510510-- Reveal TB1400 drive added to vendors.h511511-- Support for the i82078-1 (2Mbps) chip is coming along. The512512- biggest problem is that I don't have such a card, which makes513513- testing / debugging somewhat problematic. The second biggest514514- problem is that I do not have the QIC-3010/3020 standards either.515515- Status right now is that the chip is detected, and it should be516516- possible to put it into 2Mbps mode. However, I do not know what517517- "extras" are needed to complete the support. Although putting the518518- i82078 into 1Mbps mode ought to work out of the box, it doesn't519519- (right now, ftape complains about id am errors).520520-521521-522522-===== Release notes for ftape-2.04beta5, 29/12/95 =====523523-524524-Bas offline linux-tape525525-----------------------526526-For reasons only known to the majordomo mail list processor, Bas was527527-kicked off the linux-tape list sometime during the summer. Being528528-overworked at his for-pay job, he didn't notice it much. Instead I529529-(Kai, khp@dolphinics.no) has worked on ftape to produce the 2.04(beta)530530-version.531531-532532-zftape533533-------534534-Note that there exists a much improved version of ftape, written by535535-Claus-Justus Heine <claus@willi.math.rwth-aachen.de> which is named536536-zftape, which conforms to the QIC-80 specs on how to mark backups, and537537-is capable of doing automatic compression. However, zftape makes538538-substantial changes to ftape, and I (Kai) have therefore declined to539539-integrate zftape into ftape. Hopefully, this will happen soon.540540-541541-CONFIG_QIC117 removed from the kernel542542--------------------------------------543543-The biggest change of all is that ftape now will allocate its dma544544-buffers when it is inserted. The means that the CONFIG_QIC117 option545545-has disappeared from the Linux kernel as of v1.3.34. If you have an546546-earlier kernel, simply answer 'no' to the question will do the trick547547-(if you get complains about __get_free_pages() missing, contact the548548-linux-tape mailing list).549549-550550-Note that ftape-2.04beta will work equally well on kernels with and551551-without `ftape support'. The only catch is, that you will waste552552-around 96-128Kb of precious DMA'able memory on a box that has ftape553553-support compiled in.554554-555555-Now for the real changes:556556-557557-- FC-20 can now use DMA channels 1, 2, and 3. Thanks to Daniel558558- Cohen, catman@wpi.edu.559559-- ftape no longer requires a (gigantic) 96Kb buffer to be statically560560- allocated by the kernel.561561-- Added new Iomega drive (8882) to vendors.h562562-- -fno-strength-reduce added to Makefile, since GCC is broken.563563-- i82078-1 (2Mbps) FDC support started.564564-565565-566566-===== Release notes for ftape-2.03b, 27/05/95 =====567567-568568-- Prevented verify_area to return error if called with zero length.569569-- Fixed a bug in flush_buffers that caused too much padding to be570570- written when a final segment had bad sectors.571571-- Increased maximum fast-seek overshoot value from 5 to 10 segments.572572-- Breaking loop after 5 retries when positioning fails.573573-- Fixed wrong calculation of tape length for QIC-3010 and QIC-3020574574- tapes (densities were swapped).575575-- Fixed wrong calculation of overshoot on seek_forward: Wrong sign576576- of error.577577-- Suppress (false) error message due to new tape loaded.578578-- Added two new CMS drives (11c3 and 11c5) to vendors.h.579579-580580-581581-===== Release notes for ftape-2.03a, 09/05/95 =====582582-583583-- Fixed display of old error (even if already cleared) in ftape_open.584584-- Improved tape length detection, ioctls would fail for 425 ft tapes.585585- Until the tape length is calculated with data from the header586586- segment, we'll use worst-case values.587587-- Clear eof_mark after rewinding ioctls.588588-- Fixed wrong version message (2.03 had 2.02g id).589589-- Fixed bug that caused the fdc to be reset very frequently.590590- This shouldn't affect normal operation but the timing of the591591- report routines has changed again and that may cause problems.592592- We'll just have to find out....593593-- Implemented correct write precompensation setting for QIC-3010/3020.594594-- Cleaned up fdc_interrupt_wait routine. Hope it still works :-)595595-- Finally removed (already disabled) special eof mark handling for596596- gnu tar.597597-- Changed order of get_dma_residue and disable_dma in fdc-isr.c598598- because the current order would fail on at least one system.599599- We're back to the original order again, hope (and expect) this600600- doesn't break any other system.601601-602602-603603-===== Release notes for ftape-2.03, 07/05/95 =====604604-605605-(Changes refer to the first ftape-2.02 release)606606-607607-Support for wide and extended length tapes608608-------------------------------------------609609-The Conner TSM 420 and 850 drives are reported to be working.610610-I haven't received any reports about other brands; the TSM 420611611-and 850 seem to be the most widely used wide drives.612612-Extended length tapes (425 ft) with normal QIC-80 drives613613-are operating too (At least I've had no reports stating otherwise).614614-_Not_ yet completely supported (although they may work) are615615-QIC-3020 drives and 2 Mbps floppy disk controllers won't work at616616-the highest speed.617617-If someone is kind enough to send me one of these, I'll include618618-support for it too ;-)619619-620620-Easier configuration621621---------------------622622-Problems due to wrong settings in the Makefile are prevented623623-by using a configuration script that sets the necessary (kernel624624-version dependent) compile time options.625625-This kernel version is now determined from the sources found626626-at /usr/src/linux, or if not found, the old way using627627-/proc/version.628628-Versioned modules will be used automatically when supported629629-by- and configured in- the kernel.630630-Note that the current modules code (1.1.87) is still broken631631-and _needs_ the fix included in the insmod directory.632632-Please don't send me any more Oops reports caused by insmod :-(633633-634634-Reduced module size635635--------------------636636-The standard module size is much reduced and some compile time637637-options can even reduce it further. (I don't recommend this638638-for normal use but it can be handy for rescue diskettes)639639-640640-Option: Approx. module size:641641-642642-<standard> 150 Kb643643-NO_TRACE 125 Kb644644-NO_TRACE_AT_ALL 67 Kb645645-646646-647647-Much improved driver interruption648648----------------------------------649649-Most possible loops have been broken and signal detection650650-has been improved.651651-In most cases the driver can be aborted by ^C (SIGINT) and652652-SIGKILL (kill -9) will generate be a sure kill.653653-(Note that aborting a tape operation may damage the last654654-data written to tape)655655-656656-Improved error recovery657657------------------------658658-Ftape now returns an error (ENODATA) to the application if659659-a segment proves to be unrecoverable and then skips the660660-bad segment.661661-This causes most applications to continue to work (tar662662-and afio) loosing only a small amount (up to 29 Kb) of data.663663-Retried read operations will now be done slightly off-track664664-to improve the chance of success. Serious head off-track665665-errors will be detected.666666-667667-FC-10 and FC-20 controllers668668----------------------------669669-Ftape now supports both the old CMS FC-10 and the newer FC-20670670-controllers.671671-Because the operation of these cards is still undocumented,672672-thus far they will only work with the default settings (See673673-Makefile). Any feed-back on how to use them with other settings674674-will be welcome !675675-Compilation will fail if one changes the settings to illegal676676-values.677677-678678-Kernels and compilers679679----------------------680680-Ftape is currently being developed using the 2.5.8 compiler.681681-The older 2.4.5 probably works too (Set option in Makefile!).682682-I have no experience with any later compilers nor Elf support.683683-Any information on this is welcome.684684-The latest kernel I have tested ftape with is 1.2.6.685685-686686-Compression687687------------688688-An impressive collection of changes for ftape including689689-on-the-fly compression is still lying on my desk.690690-If 2.03 proves to be reliable I might start integrating these691691-but as usual, I'm short in time :-(692692-693693-Formatting694694-----------695695-There is still no way to format tapes under Linux. As far as696696-I know all attempts to write such a program have died now.697697-Since formatted tapes are rather common now, I think all we698698-need is a utility that writes a worst case pattern and verifies699699-that with the drive put in verify mode, reducing margins.700700-Any takers ?701701-702702-Furthermore703703------------704704-Cleaned up messages.705705-Prepared to support multiple tape drives on one fdc.706706-Thanks to all the people who sent bug reports and helped me707707-improve the driver. Without trying to be complete I'll mention708708-Gary Anderson (without his accurate reports and unreliable709709-hardware there wouldn't be a 2.03), Stefan Kneifel (FC-20),710710-Robert Broughton (FC-20, you were almost there ;-), Bjorn711711-Ekwall (for the versioned modules and buggy insmod ;-), Peter712712-Fox, Christopher Oliver, Ralph Whittaker and not the least713713-Linus Torvalds (for Linux and keeping me busy because of714714-changes to the kernel ;-)715715-Thanks to anyone I forgot, for the bug reports, the ftape716716-bashing and the mental support...717717-718718-719719-That's it for now. Have Fun,720720-721721-Bas.722722-723723-724724-===== Release notes for ftape-2.02g, 06/05/95 =====725725-726726-- Added extra test to break read-id loop with signal.727727-- Changed rewind code to handle negative overshoot for drives728728- that take very long to start or stop.729729-- Let use of get/set i/o-regions depend on kernel version.730730-- Changed code to use a more general test for conditional731731- compilations depending on kernel version.732732-- Improved micro-step functionality to go off-track only733733- while reading (id & data).734734-- Added failure on tape-not-referenced bit in ftape_command.735735-- Added FOREVER option to read-wait routine.736736-- Changed read-id to use shorter timeout causing smaller737737- rewinds on timeout.738738-- Made kernel-interface functions static.739739-740740-741741-===== Release notes for ftape-2.02f, 03/05/95 =====742742-743743-- Added support for dual tape drives on my system, extended Configure744744- script to detect host 'dodo'.745745-- Log media defect in history if ecc failed and no data was returned.746746-- Fixed Configure script that was failing for kernel versions with747747- double digit version or revision numbers.748748-749749-750750-===== Release notes for ftape-2.02e, 01/05/95 =====751751-752752-- Fixed reposition loop at logical eot (failing read_id).753753-- Fixed 34 segment offset when rewinding.754754-- Added fast seek capability for more than 255 segments.755755-- Fixed wrong busy result from ftape_command causing reverse756756- seek to fail.757757-- Added breakout from infinite rewind loop (if something fails).758758-759759-760760-===== Release notes for ftape-2.02d, 30/04/95 =====761761-762762-- Improved abortion on signals: Interrupt will make a graceful763763- exit, Kill will be less nice and should be used if everything764764- else fails.765765-- Included check for tape-head off track.766766-- Implemented exit from tape-start loop.767767-- Added kernel io-port registration.768768-- Implemented skip of failing segment (ENODATA) on ecc failure.769769- This allows afio and tar to continue when the tape is damaged.770770-- Made distinction between drive names with different codes.771771-772772-773773-===== Release notes for ftape-2.02c, 22/04/95 =====774774-775775-- Fixed too tight command queueing after tape stop/pause command776776- issued from within interrupt service routine (Showed as timeout777777- on Acknowledge errors during retries on some systems)778778-- Tried to fix timeouts when using 425 ft tape because the extended779779- length doesn't seem to be detected by the hardware.780780- We now use the format code from the header segment so adjust the781781- timing after reading the header segment.782782-- Fixed some messages stating 'unexpected something...' being not783783- unexpected anymore.784784-- Started preparations for merge of dynamic buffer allocation and785785- compression code.786786-- Changed some debug messages to include relevant segment information787787- at level 4.788788-- Included early bail-out when drive offline, preventing a lot of789789- false messages.790790-- Moved ftape_parameter_xxx() offsets into function instead of in calls.791791-- Removed 'weird, drive busy but no data' error when caused by792792- an error during a read-id.793793-- Improved 'timeout on acknowledge' diagnostics.794794-- Moved MODULE option into Configure.795795-- Reduced code size when no tracing at all was set (Claus Heine).796796-- No longer log error code 0 (no error) as an error.797797-798798-799799-===== Release notes for ftape-2.02b, 09/04/95 =====800800-801801-- Relaxed timing for status operation and displaying802802- abnormal results. Hopefully this shows what's going803803- wrong with the Conner TSM850R drives.804804-- Created script for configuration, using version number805805- of kernel source if available, otherwise /proc/version.806806-- Fixed conditionals in kernel-interface.c.807807-- Removed unavoidable TRACE output.808808-809809-810810-===== Release notes for ftape-2.02a, 01/04/95 =====811811-812812-- Implemented `new-style' (versioned) modules support for new813813- kernels.814814-- Reduced size of module by moving static data to bss.815815-- Now using version number of kernel source instead of running816816- kernel for kernel versions >= 1.1.82817817-- Added feedback on drive speeds to vendor information.818818-- Included fixed insmod sources to distribution (Let's hope819819- the modules distribution get fixed soon :-/).820820-821821-Note that I haven't yet implemented any of the code extension I822822-received. I hope to find some time to do this soon.823823-824824-825825-===== Release notes for ftape-2.02, 15/01/95 =====826826-827827-828828-- Fixed failing repositioning when overshoot was incremented.829829-- Fixed rate selection: Because of a deficiency in the QIC-117830830- specification one cannot distinguish between a not implemented831831- and a failing command. Therefor we now try to find out if the832832- drive does support this command before usage.833833-- Fixed error retry using wrong offset in fdc-isr.834834-- Improved retry code to retry only once on a single no-data835835- error in a segment.836836-- Validate sector number extracted from eof mark because an837837- invalid file mark (due to ???) could cause kernel panic.838838-- Split ftape-io.c into ftape-io.c and ftape-ctl.c files.839839-- Corrected too high media error count after writing to840840- a bad tape.841841-- Added #include <asm/segment.h> again because old kernel versions842842- need it.843843-- Fixed fdc not being disabled when open failed because no tape844844- drive was found.845845-- Fixed problem with soft error in sector 32 (shift operator with846846- shiftcount 32 is not defined).847847-848848-849849-===== Release notes for ftape-2.01, 08/01/95 =====850850-851851-852852-- Removed TESTING setting from distributed Makefile.853853-- Fixed `mt asf' failure: Rewind was deferred to close which854854- overruled the fsf ioctl.855855-- Prevented non-interruptible commands being interrupted.856856-- Added missing timeout.pause setting.857857-- Maximum tape speed read from drive type information table.858858- If the information is not in the table (0) the drive will859859- determine the speed itself and put a message in the logfile.860860- This information should then be added to the table in the861861- vendors.h file (and reported to me).862862-- Added call to ftape_init_drive after soft reset for those863863- (antique) drives that don't do an implicit seek_load_point864864- after a reset or power up.865865-- Don't try to set data rate if reset failed.866866-- Prevent update of seek variables when starting from the867867- beginning or the end of the tape.868868-- Fixed wrong adjustment of overshoot in seek_forward().869869-- Added sync to Makefile (again).870870-- Added code to diagnose timer problems (calibr.c).871871-- Replaced time differences by timediff calls.872872-- Removed reference to do_floppy from object for recent kernels.873873-- Fixed wrong display of 'failing dma controller' message.874874-- Removed various no longer used #include statements.875875-- Added max. tape speed value to vendor-struct.876876-- Changed ftape-command to check pre-conditions and wait877877- if needed.878878-- Further updated qic117.h to rev G.879879-- Combined command name table and restrictions table to one.880880- Extended this table with some new fields.881881-- Increased timeout on Ack timer value and included code to882882- report out of spec behaviour.883883-- Increased rewind timeout margin to calculated + 20%.884884-- Improved data rate selection so it won't fail on some885885- older (pre standard) drives.886886-- Changed initialisation code so drive will be rewound if the887887- driver is reloaded and the tape is not at bot.888888-- Moved some of the flush operations from close to the ioctls.889889-- Added exit code value to failing verify area message.890890-- Loop until tape halted in smart-stop.891891-- Fast seek handled specially if located at bot or eot.892892-- Being more conservative on overshoot value.893893-894894-895895-===== Release notes for ftape-2.00, 31/12/94 =====896896-897897- The Install-guide is completely rewritten and now also includes898898-some information on how to use the driver. If you're either new899899-to ftape or new to Unix tape devices make sure to read it !900900-901901- If you own a pci system and experience problems with the902902-ftape driver make sure to read the README.PCI file. It contains903903-some hints on how to fix your hardware.904904-905905- For anybody who hasn't noticed: The version number of the906906-driver has been incremented (The latest released version has907907-been version 1.14d).908908- This has been done for two major reasons:909909-910910- o A new (better) error recovery scheme is implemented.911911- o Support for new drive types has been added.912912-913913- All these improvements/changes will probably include a couple914914-of new (and old?) bugs. If you encounter any problems that you think915915-I'm not yet aware of, feel free to send a report to <bas@vimec.nl>.916916- I recommend keeping a version of ftape-1.14d available, just917917-in case ;-)918918-919919- This version should work with all kernel versions from 1.0.9 up920920-to 1.1.72 (and probably earlier and later versions too).921921-922922-923923-Major new features:924924-925925-- Better handling of tapes with defects: When a sector repeatedly926926- (SOFT_RETRIES in ftape.h) cannot be written to or read from it is927927- marked as an hard error and gets skipped.928928- The error correction code can handle up to three of these hard929929- errors provided there are no other errors in that segment (32 Kb).930930-931931-- Allows writing to tapes with defects (although the risk of loosing932932- data increases !)933933- Look for the media-defects entry printed with the statistics when934934- the tape is closed. A non-zero value here shows a bad tape.935935- [the actual count is wrong (too high), this is a known bug].936936-937937-- Use of backup header segment if first one is failing.938938-939939-- Support for extended length tapes with QIC-80: both 425 and 1100 ft.940940- 0.25 inch tapes are now recognized and handled.941941-942942-- Support for new QIC-80 drives with 8 mm `wide' tapes (e.g. Conner943943- TSM 420).944944-945945-- Support for new QIC-3010 and QIC-3020 drives (experimental) with946946- both 0.25 inch and 8 mm tapes.947947-948948-Some minor features were added, a couple of small bugs were fixed and949949-probably some new ones introduced ;-).950950-951951-[lseek() didn't make it into this version]952952-953953-Have fun,954954-955955-Bas.956956-----957957- LocalWords: ftape MCONFIG mt VFS zftape resp sftape proc subdir MTIOCVOLINFO958958- LocalWords: MTIOCGETSIZE BOT EOD MTBSF zft kerneld modprobe kdtime contrib TR959959- LocalWords: MTSETBLK afio uninstall texi www EIO QIC init sft eof aka dma GB960960- LocalWords: SIGKILL MTIOCFTCMD mmap Iomega FDC fdc io gnumt mtio fc asm inb961961- LocalWords: outb ft qic frontend TeXinfo irq mach MODVERSIONS CONFIG html dvi962962- LocalWords: usr doc SMP Mb Dunno FIXME vtblc perl listtape volinfo fsf MTWEOF963963- LocalWords: amanda degaussed ComByte DoublePlay whraven njackn com MTIOC vtbl964964- LocalWords: GETBLKSZ MAKEDEV zftape's linux dif CVS Revison cp MTREW MTOFFL965965- LocalWords: MTFSF BSF Marcin Dalecki GCC Config cpio swapout Kai Harrekilde966966- LocalWords: Pederson khp dolphinics Justus claus momo rwth aachen Laarhoven
-31
drivers/char/ftape/compressor/Makefile
···11-#22-# Copyright (C) 1997 Claus-Justus Heine.33-#44-# This program is free software; you can redistribute it and/or modify55-# it under the terms of the GNU General Public License as published by66-# the Free Software Foundation; either version 2, or (at your option)77-# any later version.88-# 99-# This program is distributed in the hope that it will be useful,1010-# but WITHOUT ANY WARRANTY; without even the implied warranty of1111-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212-# GNU General Public License for more details.1313-# 1414-# You should have received a copy of the GNU General Public License1515-# along with this program; see the file COPYING. If not, write to1616-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-#1818-# $Source: /homes/cvs/ftape-stacked/ftape/compressor/Makefile,v $1919-# $Revision: 1.1 $2020-# $Date: 1997/10/05 19:12:28 $2121-#2222-# Makefile for the optional compressor for th zftape VFS2323-# interface to the QIC-40/80/3010/3020 floppy-tape driver for2424-# Linux.2525-#2626-2727-obj-$(CONFIG_ZFT_COMPRESSOR) += zft-compressor.o2828-2929-zft-compressor-objs := zftape-compress.o lzrw3.o3030-3131-CFLAGS_lzrw3.o := -O6 -funroll-all-loops
-743
drivers/char/ftape/compressor/lzrw3.c
···11-/*22- * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.c,v $33- * $Revision: 1.1 $44- * $Date: 1997/10/05 19:12:29 $55- *66- * Implementation of Ross Williams lzrw3 algorithm. Adaption for zftape.77- *88- */99-1010-#include "../compressor/lzrw3.h" /* Defines single exported function "compress". */1111-1212-/******************************************************************************/1313-/* */1414-/* LZRW3.C */1515-/* */1616-/******************************************************************************/1717-/* */1818-/* Author : Ross Williams. */1919-/* Date : 30-Jun-1991. */2020-/* Release : 1. */2121-/* */2222-/******************************************************************************/2323-/* */2424-/* This file contains an implementation of the LZRW3 data compression */2525-/* algorithm in C. */2626-/* */2727-/* The algorithm is a general purpose compression algorithm that runs fast */2828-/* and gives reasonable compression. The algorithm is a member of the Lempel */2929-/* Ziv family of algorithms and bases its compression on the presence in the */3030-/* data of repeated substrings. */3131-/* */3232-/* This algorithm is unpatented and the code is public domain. As the */3333-/* algorithm is based on the LZ77 class of algorithms, it is unlikely to be */3434-/* the subject of a patent challenge. */3535-/* */3636-/* Unlike the LZRW1 and LZRW1-A algorithms, the LZRW3 algorithm is */3737-/* deterministic and is guaranteed to yield the same compressed */3838-/* representation for a given file each time it is run. */3939-/* */4040-/* The LZRW3 algorithm was originally designed and implemented */4141-/* by Ross Williams on 31-Dec-1990. */4242-/* */4343-/* Here are the results of applying this code, compiled under THINK C 4.0 */4444-/* and running on a Mac-SE (8MHz 68000), to the standard calgary corpus. */4545-/* */4646-/* +----------------------------------------------------------------+ */4747-/* | DATA COMPRESSION TEST | */4848-/* | ===================== | */4949-/* | Time of run : Sun 30-Jun-1991 09:31PM | */5050-/* | Timing accuracy : One part in 100 | */5151-/* | Context length : 262144 bytes (= 256.0000K) | */5252-/* | Test suite : Calgary Corpus Suite | */5353-/* | Files in suite : 14 | */5454-/* | Algorithm : LZRW3 | */5555-/* | Note: All averages are calculated from the un-rounded values. | */5656-/* +----------------------------------------------------------------+ */5757-/* | File Name Length CxB ComLen %Remn Bits Com K/s Dec K/s | */5858-/* | ---------- ------ --- ------ ----- ---- ------- ------- | */5959-/* | rpus:Bib.D 111261 1 55033 49.5 3.96 19.46 32.27 | */6060-/* | us:Book1.D 768771 3 467962 60.9 4.87 17.03 31.07 | */6161-/* | us:Book2.D 610856 3 317102 51.9 4.15 19.39 34.15 | */6262-/* | rpus:Geo.D 102400 1 82424 80.5 6.44 11.65 18.18 | */6363-/* | pus:News.D 377109 2 205670 54.5 4.36 17.14 27.47 | */6464-/* | pus:Obj1.D 21504 1 13027 60.6 4.85 13.40 18.95 | */6565-/* | pus:Obj2.D 246814 1 116286 47.1 3.77 19.31 30.10 | */6666-/* | s:Paper1.D 53161 1 27522 51.8 4.14 18.60 31.15 | */6767-/* | s:Paper2.D 82199 1 45160 54.9 4.40 18.45 32.84 | */6868-/* | rpus:Pic.D 513216 2 122388 23.8 1.91 35.29 51.05 | */6969-/* | us:Progc.D 39611 1 19669 49.7 3.97 18.87 30.64 | */7070-/* | us:Progl.D 71646 1 28247 39.4 3.15 24.34 40.66 | */7171-/* | us:Progp.D 49379 1 19377 39.2 3.14 23.91 39.23 | */7272-/* | us:Trans.D 93695 1 33481 35.7 2.86 25.48 40.37 | */7373-/* +----------------------------------------------------------------+ */7474-/* | Average 224401 1 110953 50.0 4.00 20.17 32.72 | */7575-/* +----------------------------------------------------------------+ */7676-/* */7777-/******************************************************************************/7878-7979-/******************************************************************************/8080-8181-/* The following structure is returned by the "compress" function below when */8282-/* the user asks the function to return identifying information. */8383-/* The most important field in the record is the working memory field which */8484-/* tells the calling program how much working memory should be passed to */8585-/* "compress" when it is called to perform a compression or decompression. */8686-/* LZRW3 uses the same amount of memory during compression and decompression. */8787-/* For more information on this structure see "compress.h". */8888-8989-#define U(X) ((ULONG) X)9090-#define SIZE_P_BYTE (U(sizeof(UBYTE *)))9191-#define SIZE_WORD (U(sizeof(UWORD )))9292-#define ALIGNMENT_FUDGE (U(16))9393-#define MEM_REQ ( U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE )9494-9595-static struct compress_identity identity =9696-{9797- U(0x032DDEA8), /* Algorithm identification number. */9898- MEM_REQ, /* Working memory (bytes) required. */9999- "LZRW3", /* Name of algorithm. */100100- "1.0", /* Version number of algorithm. */101101- "31-Dec-1990", /* Date of algorithm. */102102- "Public Domain", /* Copyright notice. */103103- "Ross N. Williams", /* Author of algorithm. */104104- "Renaissance Software", /* Affiliation of author. */105105- "Public Domain" /* Vendor of algorithm. */106106-};107107-108108-LOCAL void compress_compress (UBYTE *,UBYTE *,ULONG,UBYTE *, LONG *);109109-LOCAL void compress_decompress(UBYTE *,UBYTE *,LONG, UBYTE *, ULONG *);110110-111111-/******************************************************************************/112112-113113-/* This function is the only function exported by this module. */114114-/* Depending on its first parameter, the function can be requested to */115115-/* compress a block of memory, decompress a block of memory, or to identify */116116-/* itself. For more information, see the specification file "compress.h". */117117-118118-EXPORT void lzrw3_compress(119119- UWORD action, /* Action to be performed. */120120- UBYTE *wrk_mem, /* Address of working memory we can use.*/121121- UBYTE *src_adr, /* Address of input data. */122122- LONG src_len, /* Length of input data. */123123- UBYTE *dst_adr, /* Address to put output data. */124124- void *p_dst_len /* Address of longword for length of output data.*/125125-)126126-{127127- switch (action)128128- {129129- case COMPRESS_ACTION_IDENTITY:130130- *((struct compress_identity **)p_dst_len)= &identity;131131- break;132132- case COMPRESS_ACTION_COMPRESS:133133- compress_compress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len);134134- break;135135- case COMPRESS_ACTION_DECOMPRESS:136136- compress_decompress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len);137137- break;138138- }139139-}140140-141141-/******************************************************************************/142142-/* */143143-/* BRIEF DESCRIPTION OF THE LZRW3 ALGORITHM */144144-/* ======================================== */145145-/* The LZRW3 algorithm is identical to the LZRW1-A algorithm except that */146146-/* instead of transmitting history offsets, it transmits hash table indexes. */147147-/* In order to decode the indexes, the decompressor must maintain an */148148-/* identical hash table. Copy items are straightforward:when the decompressor */149149-/* receives a copy item, it simply looks up the hash table to translate the */150150-/* index into a pointer into the data already decompressed. To update the */151151-/* hash table, it replaces the same table entry with a pointer to the start */152152-/* of the newly decoded phrase. The tricky part is with literal items, for at */153153-/* the time that the decompressor receives a literal item the decompressor */154154-/* does not have the three bytes in the Ziv (that the compressor has) to */155155-/* perform the three-byte hash. To solve this problem, in LZRW3, both the */156156-/* compressor and decompressor are wired up so that they "buffer" these */157157-/* literals and update their hash tables only when three bytes are available. */158158-/* This makes the maximum buffering 2 bytes. */159159-/* */160160-/* Replacement of offsets by hash table indexes yields a few percent extra */161161-/* compression at the cost of some speed. LZRW3 is slower than LZRW1, LZRW1-A */162162-/* and LZRW2, but yields better compression. */163163-/* */164164-/* Extra compression could be obtained by using a hash table of depth two. */165165-/* However, increasing the depth above one incurs a significant decrease in */166166-/* compression speed which was not considered worthwhile. Another reason for */167167-/* keeping the depth down to one was to allow easy comparison with the */168168-/* LZRW1-A and LZRW2 algorithms so as to demonstrate the exact effect of the */169169-/* use of direct hash indexes. */170170-/* */171171-/* +---+ */172172-/* |___|4095 */173173-/* |___| */174174-/* +---------------------*_|<---+ /----+---\ */175175-/* | |___| +---|Hash | */176176-/* | |___| |Function| */177177-/* | |___| \--------/ */178178-/* | |___|0 ^ */179179-/* | +---+ | */180180-/* | Hash +-----+ */181181-/* | Table | */182182-/* | --- */183183-/* v ^^^ */184184-/* +-------------------------------------|----------------+ */185185-/* |||||||||||||||||||||||||||||||||||||||||||||||||||||||| */186186-/* +-------------------------------------|----------------+ */187187-/* | |1......18| | */188188-/* |<------- Lempel=History ------------>|<--Ziv-->| | */189189-/* | (=bytes already processed) |<-Still to go-->| */190190-/* |<-------------------- INPUT BLOCK ------------------->| */191191-/* */192192-/* The diagram above for LZRW3 looks almost identical to the diagram for */193193-/* LZRW1. The difference is that in LZRW3, the compressor transmits hash */194194-/* table indices instead of Lempel offsets. For this to work, the */195195-/* decompressor must maintain a hash table as well as the compressor and both */196196-/* compressor and decompressor must "buffer" literals, as the decompressor */197197-/* cannot hash phrases commencing with a literal until another two bytes have */198198-/* arrived. */199199-/* */200200-/* LZRW3 Algorithm Execution Summary */201201-/* --------------------------------- */202202-/* 1. Hash the first three bytes of the Ziv to yield a hash table index h. */203203-/* 2. Look up the hash table yielding history pointer p. */204204-/* 3. Match where p points with the Ziv. If there is a match of three or */205205-/* more bytes, code those bytes (in the Ziv) as a copy item, otherwise */206206-/* code the next byte in the Ziv as a literal item. */207207-/* 4. Update the hash table as possible subject to the constraint that only */208208-/* phrases commencing three bytes back from the Ziv can be hashed and */209209-/* entered into the hash table. (This enables the decompressor to keep */210210-/* pace). See the description and code for more details. */211211-/* */212212-/******************************************************************************/213213-/* */214214-/* DEFINITION OF COMPRESSED FILE FORMAT */215215-/* ==================================== */216216-/* * A compressed file consists of a COPY FLAG followed by a REMAINDER. */217217-/* * The copy flag CF uses up four bytes with the first byte being the */218218-/* least significant. */219219-/* * If CF=1, then the compressed file represents the remainder of the file */220220-/* exactly. Otherwise CF=0 and the remainder of the file consists of zero */221221-/* or more GROUPS, each of which represents one or more bytes. */222222-/* * Each group consists of two bytes of CONTROL information followed by */223223-/* sixteen ITEMs except for the last group which can contain from one */224224-/* to sixteen items. */225225-/* * An item can be either a LITERAL item or a COPY item. */226226-/* * Each item corresponds to a bit in the control bytes. */227227-/* * The first control byte corresponds to the first 8 items in the group */228228-/* with bit 0 corresponding to the first item in the group and bit 7 to */229229-/* the eighth item in the group. */230230-/* * The second control byte corresponds to the second 8 items in the group */231231-/* with bit 0 corresponding to the ninth item in the group and bit 7 to */232232-/* the sixteenth item in the group. */233233-/* * A zero bit in a control word means that the corresponding item is a */234234-/* literal item. A one bit corresponds to a copy item. */235235-/* * A literal item consists of a single byte which represents itself. */236236-/* * A copy item consists of two bytes that represent from 3 to 18 bytes. */237237-/* * The first byte in a copy item will be denoted C1. */238238-/* * The second byte in a copy item will be denoted C2. */239239-/* * Bits will be selected using square brackets. */240240-/* For example: C1[0..3] is the low nibble of the first control byte. */241241-/* of copy item C1. */242242-/* * The LENGTH of a copy item is defined to be C1[0..3]+3 which is a number */243243-/* in the range [3,18]. */244244-/* * The INDEX of a copy item is defined to be C1[4..7]*256+C2[0..8] which */245245-/* is a number in the range [0,4095]. */246246-/* * A copy item represents the sequence of bytes */247247-/* text[POS-OFFSET..POS-OFFSET+LENGTH-1] where */248248-/* text is the entire text of the uncompressed string. */249249-/* POS is the index in the text of the character following the */250250-/* string represented by all the items preceeding the item */251251-/* being defined. */252252-/* OFFSET is obtained from INDEX by looking up the hash table. */253253-/* */254254-/******************************************************************************/255255-256256-/* The following #define defines the length of the copy flag that appears at */257257-/* the start of the compressed file. The value of four bytes was chosen */258258-/* because the fast_copy routine on my Macintosh runs faster if the source */259259-/* and destination blocks are relatively longword aligned. */260260-/* The actual flag data appears in the first byte. The rest are zeroed so as */261261-/* to normalize the compressed representation (i.e. not non-deterministic). */262262-#define FLAG_BYTES 4263263-264264-/* The following #defines define the meaning of the values of the copy */265265-/* flag at the start of the compressed file. */266266-#define FLAG_COMPRESS 0 /* Signals that output was result of compression. */267267-#define FLAG_COPY 1 /* Signals that output was simply copied over. */268268-269269-/* The 68000 microprocessor (on which this algorithm was originally developed */270270-/* is fussy about non-aligned arrays of words. To avoid these problems the */271271-/* following macro can be used to "waste" from 0 to 3 bytes so as to align */272272-/* the argument pointer. */273273-#define ULONG_ALIGN_UP(X) ((((ULONG)X)+sizeof(ULONG)-1)&~(sizeof(ULONG)-1))274274-275275-276276-/* The following constant defines the maximum length of an uncompressed item. */277277-/* This definition must not be changed; its value is hardwired into the code. */278278-/* The longest number of bytes that can be spanned by a single item is 18 */279279-/* for the longest copy item. */280280-#define MAX_RAW_ITEM (18)281281-282282-/* The following constant defines the maximum length of an uncompressed group.*/283283-/* This definition must not be changed; its value is hardwired into the code. */284284-/* A group contains at most 16 items which explains this definition. */285285-#define MAX_RAW_GROUP (16*MAX_RAW_ITEM)286286-287287-/* The following constant defines the maximum length of a compressed group. */288288-/* This definition must not be changed; its value is hardwired into the code. */289289-/* A compressed group consists of two control bytes followed by up to 16 */290290-/* compressed items each of which can have a maximum length of two bytes. */291291-#define MAX_CMP_GROUP (2+16*2)292292-293293-/* The following constant defines the number of entries in the hash table. */294294-/* This definition must not be changed; its value is hardwired into the code. */295295-#define HASH_TABLE_LENGTH (4096)296296-297297-/* LZRW3, unlike LZRW1(-A), must initialize its hash table so as to enable */298298-/* the compressor and decompressor to stay in step maintaining identical hash */299299-/* tables. In an early version of the algorithm, the tables were simply */300300-/* initialized to zero and a check for zero was included just before the */301301-/* matching code. However, this test costs time. A better solution is to */302302-/* initialize all the entries in the hash table to point to a constant */303303-/* string. The decompressor does the same. This solution requires no extra */304304-/* test. The contents of the string do not matter so long as the string is */305305-/* the same for the compressor and decompressor and contains at least */306306-/* MAX_RAW_ITEM bytes. I chose consecutive decimal digits because they do not */307307-/* have white space problems (e.g. there is no chance that the compiler will */308308-/* replace more than one space by a TAB) and because they make the length of */309309-/* the string obvious by inspection. */310310-#define START_STRING_18 ((UBYTE *) "123456789012345678")311311-312312-/* In this algorithm, hash values have to be calculated at more than one */313313-/* point. The following macro neatens the code up for this. */314314-#define HASH(PTR) \315315- (((40543*(((*(PTR))<<8)^((*((PTR)+1))<<4)^(*((PTR)+2))))>>4) & 0xFFF)316316-317317-/******************************************************************************/318318-319319-/* Input : Hand over the required amount of working memory in p_wrk_mem. */320320-/* Input : Specify input block using p_src_first and src_len. */321321-/* Input : Point p_dst_first to the start of the output zone (OZ). */322322-/* Input : Point p_dst_len to a ULONG to receive the output length. */323323-/* Input : Input block and output zone must not overlap. */324324-/* Output : Length of output block written to *p_dst_len. */325325-/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. May */326326-/* Output : write in OZ=Mem[p_dst_first..p_dst_first+src_len+MAX_CMP_GROUP-1].*/327327-/* Output : Upon completion guaranteed *p_dst_len<=src_len+FLAG_BYTES. */328328-LOCAL void compress_compress(UBYTE *p_wrk_mem,329329- UBYTE *p_src_first, ULONG src_len,330330- UBYTE *p_dst_first, LONG *p_dst_len)331331-{332332- /* p_src and p_dst step through the source and destination blocks. */333333- register UBYTE *p_src = p_src_first;334334- register UBYTE *p_dst = p_dst_first;335335-336336- /* The following variables are never modified and are used in the */337337- /* calculations that determine when the main loop terminates. */338338- UBYTE *p_src_post = p_src_first+src_len;339339- UBYTE *p_dst_post = p_dst_first+src_len;340340- UBYTE *p_src_max1 = p_src_first+src_len-MAX_RAW_ITEM;341341- UBYTE *p_src_max16 = p_src_first+src_len-MAX_RAW_ITEM*16;342342-343343- /* The variables 'p_control' and 'control' are used to buffer control bits. */344344- /* Before each group is processed, the next two bytes of the output block */345345- /* are set aside for the control word for the group about to be processed. */346346- /* 'p_control' is set to point to the first byte of that word. Meanwhile, */347347- /* 'control' buffers the control bits being generated during the processing */348348- /* of the group. Instead of having a counter to keep track of how many items */349349- /* have been processed (=the number of bits in the control word), at the */350350- /* start of each group, the top word of 'control' is filled with 1 bits. */351351- /* As 'control' is shifted for each item, the 1 bits in the top word are */352352- /* absorbed or destroyed. When they all run out (i.e. when the top word is */353353- /* all zero bits, we know that we are at the end of a group. */354354-# define TOPWORD 0xFFFF0000355355- UBYTE *p_control;356356- register ULONG control=TOPWORD;357357-358358- /* THe variable 'hash' always points to the first element of the hash table. */359359- UBYTE **hash= (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem);360360-361361- /* The following two variables represent the literal buffer. p_h1 points to */362362- /* the hash table entry corresponding to the youngest literal. p_h2 points */363363- /* to the hash table entry corresponding to the second youngest literal. */364364- /* Note: p_h1=0=>p_h2=0 because zero values denote absence of a pending */365365- /* literal. The variables are initialized to zero meaning an empty "buffer". */366366- UBYTE **p_h1=NULL;367367- UBYTE **p_h2=NULL;368368-369369- /* To start, we write the flag bytes. Being optimistic, we set the flag to */370370- /* FLAG_COMPRESS. The remaining flag bytes are zeroed so as to keep the */371371- /* algorithm deterministic. */372372- *p_dst++=FLAG_COMPRESS;373373- {UWORD i; for (i=2;i<=FLAG_BYTES;i++) *p_dst++=0;}374374-375375- /* Reserve the first word of output as the control word for the first group. */376376- /* Note: This is undone at the end if the input block is empty. */377377- p_control=p_dst; p_dst+=2;378378-379379- /* Initialize all elements of the hash table to point to a constant string. */380380- /* Use of an unrolled loop speeds this up considerably. */381381- {UWORD i; UBYTE **p_h=hash;382382-# define ZH *p_h++=START_STRING_18383383- for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */384384- {ZH;ZH;ZH;ZH;385385- ZH;ZH;ZH;ZH;386386- ZH;ZH;ZH;ZH;387387- ZH;ZH;ZH;ZH;}388388- }389389-390390- /* The main loop processes either 1 or 16 items per iteration. As its */391391- /* termination logic is complicated, I have opted for an infinite loop */392392- /* structure containing 'break' and 'goto' statements. */393393- while (TRUE)394394- {/* Begin main processing loop. */395395-396396- /* Note: All the variables here except unroll should be defined within */397397- /* the inner loop. Unfortunately the loop hasn't got a block. */398398- register UBYTE *p; /* Scans through targ phrase during matching. */399399- register UBYTE *p_ziv= NULL ; /* Points to first byte of current Ziv. */400400- register UWORD unroll; /* Loop counter for unrolled inner loop. */401401- register UWORD index; /* Index of current hash table entry. */402402- register UBYTE **p_h0 = NULL ; /* Pointer to current hash table entry. */403403-404404- /* Test for overrun and jump to overrun code if necessary. */405405- if (p_dst>p_dst_post)406406- goto overrun;407407-408408- /* The following cascade of if statements efficiently catches and deals */409409- /* with varying degrees of closeness to the end of the input block. */410410- /* When we get very close to the end, we stop updating the table and */411411- /* code the remaining bytes as literals. This makes the code simpler. */412412- unroll=16;413413- if (p_src>p_src_max16)414414- {415415- unroll=1;416416- if (p_src>p_src_max1)417417- {418418- if (p_src==p_src_post)419419- break;420420- else421421- goto literal;422422- }423423- }424424-425425- /* This inner unrolled loop processes 'unroll' (whose value is either 1 */426426- /* or 16) items. I have chosen to implement this loop with labels and */427427- /* gotos to heighten the ease with which the loop may be implemented with */428428- /* a single decrement and branch instruction in assembly language and */429429- /* also because the labels act as highly readable place markers. */430430- /* (Also because we jump into the loop for endgame literals (see above)). */431431-432432- begin_unrolled_loop:433433-434434- /* To process the next phrase, we hash the next three bytes and use */435435- /* the resultant hash table index to look up the hash table. A pointer */436436- /* to the entry is stored in p_h0 so as to avoid an array lookup. The */437437- /* hash table entry *p_h0 is looked up yielding a pointer p to a */438438- /* potential match of the Ziv in the history. */439439- index=HASH(p_src);440440- p_h0=&hash[index];441441- p=*p_h0;442442-443443- /* Having looked up the candidate position, we are in a position to */444444- /* attempt a match. The match loop has been unrolled using the PS */445445- /* macro so that failure within the first three bytes automatically */446446- /* results in the literal branch being taken. The coding is simple. */447447- /* p_ziv saves p_src so we can let p_src wander. */448448-# define PS *p++!=*p_src++449449- p_ziv=p_src;450450- if (PS || PS || PS)451451- {452452- /* Literal. */453453-454454- /* Code the literal byte as itself and a zero control bit. */455455- p_src=p_ziv; literal: *p_dst++=*p_src++; control&=0xFFFEFFFF;456456-457457- /* We have just coded a literal. If we had two pending ones, that */458458- /* makes three and we can update the hash table. */459459- if (p_h2!=0)460460- {*p_h2=p_ziv-2;}461461-462462- /* In any case, rotate the hash table pointers for next time. */463463- p_h2=p_h1; p_h1=p_h0;464464-465465- }466466- else467467- {468468- /* Copy */469469-470470- /* Match up to 15 remaining bytes using an unrolled loop and code. */471471-#if 0472472- PS || PS || PS || PS || PS || PS || PS || PS ||473473- PS || PS || PS || PS || PS || PS || PS || p_src++;474474-#else 475475- if (476476- !( PS || PS || PS || PS || PS || PS || PS || PS ||477477- PS || PS || PS || PS || PS || PS || PS ) 478478- ) p_src++;479479-#endif480480- *p_dst++=((index&0xF00)>>4)|(--p_src-p_ziv-3);481481- *p_dst++=index&0xFF;482482-483483- /* As we have just coded three bytes, we are now in a position to */484484- /* update the hash table with the literal bytes that were pending */485485- /* upon the arrival of extra context bytes. */486486- if (p_h1!=0)487487- {488488- if (p_h2)489489- {*p_h2=p_ziv-2; p_h2=NULL;}490490- *p_h1=p_ziv-1; p_h1=NULL;491491- }492492-493493- /* In any case, we can update the hash table based on the current */494494- /* position as we just coded at least three bytes in a copy items. */495495- *p_h0=p_ziv;496496-497497- }498498- control>>=1;499499-500500- /* This loop is all set up for a decrement and jump instruction! */501501-#ifndef linux502502-` end_unrolled_loop: if (--unroll) goto begin_unrolled_loop;503503-#else504504- /* end_unrolled_loop: */ if (--unroll) goto begin_unrolled_loop;505505-#endif506506-507507- /* At this point it will nearly always be the end of a group in which */508508- /* case, we have to do some control-word processing. However, near the */509509- /* end of the input block, the inner unrolled loop is only executed once. */510510- /* This necessitates the 'if' test. */511511- if ((control&TOPWORD)==0)512512- {513513- /* Write the control word to the place we saved for it in the output. */514514- *p_control++= control &0xFF;515515- *p_control = (control>>8) &0xFF;516516-517517- /* Reserve the next word in the output block for the control word */518518- /* for the group about to be processed. */519519- p_control=p_dst; p_dst+=2;520520-521521- /* Reset the control bits buffer. */522522- control=TOPWORD;523523- }524524-525525- } /* End main processing loop. */526526-527527- /* After the main processing loop has executed, all the input bytes have */528528- /* been processed. However, the control word has still to be written to the */529529- /* word reserved for it in the output at the start of the most recent group. */530530- /* Before writing, the control word has to be shifted so that all the bits */531531- /* are in the right place. The "empty" bit positions are filled with 1s */532532- /* which partially fill the top word. */533533- while(control&TOPWORD) control>>=1;534534- *p_control++= control &0xFF;535535- *p_control++=(control>>8) &0xFF;536536-537537- /* If the last group contained no items, delete the control word too. */538538- if (p_control==p_dst) p_dst-=2;539539-540540- /* Write the length of the output block to the dst_len parameter and return. */541541- *p_dst_len=p_dst-p_dst_first; 542542- return;543543-544544- /* Jump here as soon as an overrun is detected. An overrun is defined to */545545- /* have occurred if p_dst>p_dst_first+src_len. That is, the moment the */546546- /* length of the output written so far exceeds the length of the input block.*/547547- /* The algorithm checks for overruns at least at the end of each group */548548- /* which means that the maximum overrun is MAX_CMP_GROUP bytes. */549549- /* Once an overrun occurs, the only thing to do is to set the copy flag and */550550- /* copy the input over. */551551- overrun:552552-#if 0553553- *p_dst_first=FLAG_COPY;554554- fast_copy(p_src_first,p_dst_first+FLAG_BYTES,src_len);555555- *p_dst_len=src_len+FLAG_BYTES;556556-#else557557- fast_copy(p_src_first,p_dst_first,src_len);558558- *p_dst_len= -src_len; /* return a negative number to indicate uncompressed data */559559-#endif560560-}561561-562562-/******************************************************************************/563563-564564-/* Input : Hand over the required amount of working memory in p_wrk_mem. */565565-/* Input : Specify input block using p_src_first and src_len. */566566-/* Input : Point p_dst_first to the start of the output zone. */567567-/* Input : Point p_dst_len to a ULONG to receive the output length. */568568-/* Input : Input block and output zone must not overlap. User knows */569569-/* Input : upperbound on output block length from earlier compression. */570570-/* Input : In any case, maximum expansion possible is nine times. */571571-/* Output : Length of output block written to *p_dst_len. */572572-/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */573573-/* Output : Writes only in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */574574-LOCAL void compress_decompress( UBYTE *p_wrk_mem,575575- UBYTE *p_src_first, LONG src_len,576576- UBYTE *p_dst_first, ULONG *p_dst_len)577577-{578578- /* Byte pointers p_src and p_dst scan through the input and output blocks. */579579- register UBYTE *p_src = p_src_first+FLAG_BYTES;580580- register UBYTE *p_dst = p_dst_first;581581- /* we need to avoid a SEGV when trying to uncompress corrupt data */582582- register UBYTE *p_dst_post = p_dst_first + *p_dst_len;583583-584584- /* The following two variables are never modified and are used to control */585585- /* the main loop. */586586- UBYTE *p_src_post = p_src_first+src_len;587587- UBYTE *p_src_max16 = p_src_first+src_len-(MAX_CMP_GROUP-2);588588-589589- /* The hash table is the only resident of the working memory. The hash table */590590- /* contains HASH_TABLE_LENGTH=4096 pointers to positions in the history. To */591591- /* keep Macintoshes happy, it is longword aligned. */592592- UBYTE **hash = (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem);593593-594594- /* The variable 'control' is used to buffer the control bits which appear in */595595- /* groups of 16 bits (control words) at the start of each compressed group. */596596- /* When each group is read, bit 16 of the register is set to one. Whenever */597597- /* a new bit is needed, the register is shifted right. When the value of the */598598- /* register becomes 1, we know that we have reached the end of a group. */599599- /* Initializing the register to 1 thus instructs the code to follow that it */600600- /* should read a new control word immediately. */601601- register ULONG control=1;602602-603603- /* The value of 'literals' is always in the range 0..3. It is the number of */604604- /* consecutive literal items just seen. We have to record this number so as */605605- /* to know when to update the hash table. When literals gets to 3, there */606606- /* have been three consecutive literals and we can update at the position of */607607- /* the oldest of the three. */608608- register UWORD literals=0;609609-610610- /* Check the leading copy flag to see if the compressor chose to use a copy */611611- /* operation instead of a compression operation. If a copy operation was */612612- /* used, then all we need to do is copy the data over, set the output length */613613- /* and return. */614614-#if 0615615- if (*p_src_first==FLAG_COPY)616616- {617617- fast_copy(p_src_first+FLAG_BYTES,p_dst_first,src_len-FLAG_BYTES);618618- *p_dst_len=src_len-FLAG_BYTES;619619- return;620620- }621621-#else622622- if ( src_len < 0 )623623- { 624624- fast_copy(p_src_first,p_dst_first,-src_len );625625- *p_dst_len = (ULONG)-src_len;626626- return;627627- }628628-#endif629629-630630- /* Initialize all elements of the hash table to point to a constant string. */631631- /* Use of an unrolled loop speeds this up considerably. */632632- {UWORD i; UBYTE **p_h=hash;633633-# define ZJ *p_h++=START_STRING_18634634- for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */635635- {ZJ;ZJ;ZJ;ZJ;636636- ZJ;ZJ;ZJ;ZJ;637637- ZJ;ZJ;ZJ;ZJ;638638- ZJ;ZJ;ZJ;ZJ;}639639- }640640-641641- /* The outer loop processes either 1 or 16 items per iteration depending on */642642- /* how close p_src is to the end of the input block. */643643- while (p_src!=p_src_post)644644- {/* Start of outer loop */645645-646646- register UWORD unroll; /* Counts unrolled loop executions. */647647-648648- /* When 'control' has the value 1, it means that the 16 buffered control */649649- /* bits that were read in at the start of the current group have all been */650650- /* shifted out and that all that is left is the 1 bit that was injected */651651- /* into bit 16 at the start of the current group. When we reach the end */652652- /* of a group, we have to load a new control word and inject a new 1 bit. */653653- if (control==1)654654- {655655- control=0x10000|*p_src++;656656- control|=(*p_src++)<<8;657657- }658658-659659- /* If it is possible that we are within 16 groups from the end of the */660660- /* input, execute the unrolled loop only once, else process a whole group */661661- /* of 16 items by looping 16 times. */662662- unroll= p_src<=p_src_max16 ? 16 : 1;663663-664664- /* This inner loop processes one phrase (item) per iteration. */665665- while (unroll--)666666- { /* Begin unrolled inner loop. */667667-668668- /* Process a literal or copy item depending on the next control bit. */669669- if (control&1)670670- {671671- /* Copy item. */672672-673673- register UBYTE *p; /* Points to place from which to copy. */674674- register UWORD lenmt; /* Length of copy item minus three. */675675- register UBYTE **p_hte; /* Pointer to current hash table entry.*/676676- register UBYTE *p_ziv=p_dst; /* Pointer to start of current Ziv. */677677-678678- /* Read and dismantle the copy word. Work out from where to copy. */679679- lenmt=*p_src++;680680- p_hte=&hash[((lenmt&0xF0)<<4)|*p_src++];681681- p=*p_hte;682682- lenmt&=0xF;683683-684684- /* Now perform the copy using a half unrolled loop. */685685- *p_dst++=*p++;686686- *p_dst++=*p++;687687- *p_dst++=*p++;688688- while (lenmt--)689689- *p_dst++=*p++;690690-691691- /* Because we have just received 3 or more bytes in a copy item */692692- /* (whose bytes we have just installed in the output), we are now */693693- /* in a position to flush all the pending literal hashings that had */694694- /* been postponed for lack of bytes. */695695- if (literals>0)696696- {697697- register UBYTE *r=p_ziv-literals;698698- hash[HASH(r)]=r;699699- if (literals==2)700700- {r++; hash[HASH(r)]=r;}701701- literals=0;702702- }703703-704704- /* In any case, we can immediately update the hash table with the */705705- /* current position. We don't need to do a HASH(...) to work out */706706- /* where to put the pointer, as the compressor just told us!!! */707707- *p_hte=p_ziv;708708-709709- }710710- else711711- {712712- /* Literal item. */713713-714714- /* Copy over the literal byte. */715715- *p_dst++=*p_src++;716716-717717- /* If we now have three literals waiting to be hashed into the hash */718718- /* table, we can do one of them now (because there are three). */719719- if (++literals == 3)720720- {register UBYTE *p=p_dst-3; hash[HASH(p)]=p; literals=2;}721721- }722722-723723- /* Shift the control buffer so the next control bit is in bit 0. */724724- control>>=1;725725-#if 1726726- if (p_dst > p_dst_post) 727727- {728728- /* Shit: we tried to decompress corrupt data */729729- *p_dst_len = 0;730730- return;731731- }732732-#endif733733- } /* End unrolled inner loop. */734734-735735- } /* End of outer loop */736736-737737- /* Write the length of the decompressed data before returning. */738738- *p_dst_len=p_dst-p_dst_first;739739-}740740-741741-/******************************************************************************/742742-/* End of LZRW3.C */743743-/******************************************************************************/
-253
drivers/char/ftape/compressor/lzrw3.h
···11-#ifndef _LZRW3_H22-#define _LZRW3_H33-/*44- * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.h,v $55- * $Revision: 1.1 $66- * $Date: 1997/10/05 19:12:30 $77- *88- * include files for lzrw3. Only slighty modified from the original99- * version. Assembles the three include files compress.h, port.h and1010- * fastcopy.h from the original lzrw3 package.1111- *1212- */1313-1414-#include <linux/types.h>1515-#include <linux/string.h>1616-1717-/******************************************************************************/1818-/* */1919-/* COMPRESS.H */2020-/* */2121-/******************************************************************************/2222-/* */2323-/* Author : Ross Williams. */2424-/* Date : December 1989. */2525-/* */2626-/* This header file defines the interface to a set of functions called */2727-/* 'compress', each member of which implements a particular data compression */2828-/* algorithm. */2929-/* */3030-/* Normally in C programming, for each .H file, there is a corresponding .C */3131-/* file that implements the functions promised in the .H file. */3232-/* Here, there are many .C files corresponding to this header file. */3333-/* Each comforming implementation file contains a single function */3434-/* called 'compress' that implements a single data compression */3535-/* algorithm that conforms with the interface specified in this header file. */3636-/* Only one algorithm can be linked in at a time in this organization. */3737-/* */3838-/******************************************************************************/3939-/* */4040-/* DEFINITION OF FUNCTION COMPRESS */4141-/* =============================== */4242-/* */4343-/* Summary of Function Compress */4444-/* ---------------------------- */4545-/* The action that 'compress' takes depends on its first argument called */4646-/* 'action'. The function provides three actions: */4747-/* */4848-/* - Return information about the algorithm. */4949-/* - Compress a block of memory. */5050-/* - Decompress a block of memory. */5151-/* */5252-/* Parameters */5353-/* ---------- */5454-/* See the formal C definition later for a description of the parameters. */5555-/* */5656-/* Constants */5757-/* --------- */5858-/* COMPRESS_OVERRUN: The constant COMPRESS_OVERRUN defines by how many bytes */5959-/* an algorithm is allowed to expand a block during a compression operation. */6060-/* */6161-/* Although compression algorithms usually compress data, there will always */6262-/* be data that a given compressor will expand (this can be proven). */6363-/* Fortunately, the degree of expansion can be limited to a single bit, by */6464-/* copying over the input data if the data gets bigger during compression. */6565-/* To allow for this possibility, the first bit of a compressed */6666-/* representation can be used as a flag indicating whether the */6767-/* input data was copied over, or truly compressed. In practice, the first */6868-/* byte would be used to store this bit so as to maintain byte alignment. */6969-/* */7070-/* Unfortunately, in general, the only way to tell if an algorithm will */7171-/* expand a particular block of data is to run the algorithm on the data. */7272-/* If the algorithm does not continuously monitor how many output bytes it */7373-/* has written, it might write an output block far larger than the input */7474-/* block before realizing that it has done so. */7575-/* On the other hand, continuous checks on output length are inefficient. */7676-/* */7777-/* To cater for all these problems, this interface definition: */7878-/* > Allows a compression algorithm to return an output block that is up to */7979-/* COMPRESS_OVERRUN bytes longer than the input block. */8080-/* > Allows a compression algorithm to write up to COMPRESS_OVERRUN bytes */8181-/* more than the length of the input block to the memory of the output */8282-/* block regardless of the length of the output block eventually returned. */8383-/* This allows an algorithm to overrun the length of the input block in the */8484-/* output block by up to COMPRESS_OVERRUN bytes between expansion checks. */8585-/* */8686-/* The problem does not arise for decompression. */8787-/* */8888-/* Identity Action */8989-/* --------------- */9090-/* > action must be COMPRESS_ACTION_IDENTITY. */9191-/* > p_dst_len must point to a longword to receive a longword address. */9292-/* > The value of the other parameters does not matter. */9393-/* > After execution, the longword that p_dst_len points to will be a pointer */9494-/* to a structure of type compress_identity. */9595-/* Thus, for example, after the call, (*p_dst_len)->memory will return the */9696-/* number of bytes of working memory that the algorithm requires to run. */9797-/* > The values of the identity structure returned are fixed constant */9898-/* attributes of the algorithm and must not vary from call to call. */9999-/* */100100-/* Common Requirements for Compression and Decompression Actions */101101-/* ------------------------------------------------------------- */102102-/* > wrk_mem must point to an unused block of memory of a length specified in */103103-/* the algorithm's identity block. The identity block can be obtained by */104104-/* making a separate call to compress, specifying the identity action. */105105-/* > The INPUT BLOCK is defined to be Memory[src_addr,src_addr+src_len-1]. */106106-/* > dst_len will be used to denote *p_dst_len. */107107-/* > dst_len is not read by compress, only written. */108108-/* > The value of dst_len is defined only upon termination. */109109-/* > The OUTPUT BLOCK is defined to be Memory[dst_addr,dst_addr+dst_len-1]. */110110-/* */111111-/* Compression Action */112112-/* ------------------ */113113-/* > action must be COMPRESS_ACTION_COMPRESS. */114114-/* > src_len must be in the range [0,COMPRESS_MAX_ORG]. */115115-/* > The OUTPUT ZONE is defined to be */116116-/* Memory[dst_addr,dst_addr+src_len-1+COMPRESS_OVERRUN]. */117117-/* > The function can modify any part of the output zone regardless of the */118118-/* final length of the output block. */119119-/* > The input block and the output zone must not overlap. */120120-/* > dst_len will be in the range [0,src_len+COMPRESS_OVERRUN]. */121121-/* > dst_len will be in the range [0,COMPRESS_MAX_COM] (from prev fact). */122122-/* > The output block will consist of a representation of the input block. */123123-/* */124124-/* Decompression Action */125125-/* -------------------- */126126-/* > action must be COMPRESS_ACTION_DECOMPRESS. */127127-/* > The input block must be the result of an earlier compression operation. */128128-/* > If the previous fact is true, the following facts must also be true: */129129-/* > src_len will be in the range [0,COMPRESS_MAX_COM]. */130130-/* > dst_len will be in the range [0,COMPRESS_MAX_ORG]. */131131-/* > The input and output blocks must not overlap. */132132-/* > Only the output block is modified. */133133-/* > Upon termination, the output block will consist of the bytes contained */134134-/* in the input block passed to the earlier compression operation. */135135-/* */136136-/******************************************************************************/137137-138138-/******************************************************************************/139139-/* */140140-/* PORT.H */141141-/* */142142-/******************************************************************************/143143-/* */144144-/* This module contains macro definitions and types that are likely to */145145-/* change between computers. */146146-/* */147147-/******************************************************************************/148148-149149-#ifndef DONE_PORT /* Only do this if not previously done. */150150-151151- #ifdef THINK_C152152- #define UBYTE unsigned char /* Unsigned byte */153153- #define UWORD unsigned int /* Unsigned word (2 bytes) */154154- #define ULONG unsigned long /* Unsigned word (4 bytes) */155155- #define BOOL unsigned char /* Boolean */156156- #define FOPEN_BINARY_READ "rb" /* Mode string for binary reading. */157157- #define FOPEN_BINARY_WRITE "wb" /* Mode string for binary writing. */158158- #define FOPEN_TEXT_APPEND "a" /* Mode string for text appending. */159159- #define REAL double /* USed for floating point stuff. */160160- #endif161161- #if defined(LINUX) || defined(linux)162162- #define UBYTE __u8 /* Unsigned byte */163163- #define UWORD __u16 /* Unsigned word (2 bytes) */164164- #define ULONG __u32 /* Unsigned word (4 bytes) */165165- #define LONG __s32 /* Signed word (4 bytes) */166166- #define BOOL is not used here /* Boolean */167167- #define FOPEN_BINARY_READ not used /* Mode string for binary reading. */168168- #define FOPEN_BINARY_WRITE not used /* Mode string for binary writing. */169169- #define FOPEN_TEXT_APPEND not used /* Mode string for text appending. */170170- #define REAL not used /* USed for floating point stuff. */171171- #ifndef TRUE172172- #define TRUE 1173173- #endif174174- #endif175175-176176- #define DONE_PORT /* Don't do all this again. */177177- #define MALLOC_FAIL NULL /* Failure status from malloc() */178178- #define LOCAL static /* For non-exported routines. */179179- #define EXPORT /* Signals exported function. */180180- #define then /* Useful for aligning ifs. */181181-182182-#endif183183-184184-/******************************************************************************/185185-/* End of PORT.H */186186-/******************************************************************************/187187-188188-#define COMPRESS_ACTION_IDENTITY 0189189-#define COMPRESS_ACTION_COMPRESS 1190190-#define COMPRESS_ACTION_DECOMPRESS 2191191-192192-#define COMPRESS_OVERRUN 1024193193-#define COMPRESS_MAX_COM 0x70000000194194-#define COMPRESS_MAX_ORG (COMPRESS_MAX_COM-COMPRESS_OVERRUN)195195-196196-#define COMPRESS_MAX_STRLEN 255197197-198198-/* The following structure provides information about the algorithm. */199199-/* > The top bit of id must be zero. The remaining bits must be chosen by */200200-/* the author of the algorithm by tossing a coin 31 times. */201201-/* > The amount of memory requested by the algorithm is specified in bytes */202202-/* and must be in the range [0,0x70000000]. */203203-/* > All strings s must be such that strlen(s)<=COMPRESS_MAX_STRLEN. */204204-struct compress_identity205205- {206206- ULONG id; /* Identifying number of algorithm. */207207- ULONG memory; /* Number of bytes of working memory required. */208208-209209- char *name; /* Name of algorithm. */210210- char *version; /* Version number. */211211- char *date; /* Date of release of this version. */212212- char *copyright; /* Copyright message. */213213-214214- char *author; /* Author of algorithm. */215215- char *affiliation; /* Affiliation of author. */216216- char *vendor; /* Where the algorithm can be obtained. */217217- };218218-219219-void lzrw3_compress( /* Single function interface to compression algorithm. */220220-UWORD action, /* Action to be performed. */221221-UBYTE *wrk_mem, /* Working memory temporarily given to routine to use. */222222-UBYTE *src_adr, /* Address of input data. */223223-LONG src_len, /* Length of input data. */224224-UBYTE *dst_adr, /* Address of output data. */225225-void *p_dst_len /* Pointer to a longword where routine will write: */226226- /* If action=..IDENTITY => Adr of id structure. */227227- /* If action=..COMPRESS => Length of output data. */228228- /* If action=..DECOMPRESS => Length of output data. */229229-);230230-231231-/******************************************************************************/232232-/* End of COMPRESS.H */233233-/******************************************************************************/234234-235235-236236-/******************************************************************************/237237-/* fast_copy.h */238238-/******************************************************************************/239239-240240-/* This function copies a block of memory very quickly. */241241-/* The exact speed depends on the relative alignment of the blocks of memory. */242242-/* PRE : 0<=src_len<=(2^32)-1 . */243243-/* PRE : Source and destination blocks must not overlap. */244244-/* POST : MEM[dst_adr,dst_adr+src_len-1]=MEM[src_adr,src_adr+src_len-1]. */245245-/* POST : MEM[dst_adr,dst_adr+src_len-1] is the only memory changed. */246246-247247-#define fast_copy(src,dst,len) memcpy(dst,src,len)248248-249249-/******************************************************************************/250250-/* End of fast_copy.h */251251-/******************************************************************************/252252-253253-#endif
-1203
drivers/char/ftape/compressor/zftape-compress.c
···11-/*22- * Copyright (C) 1994-1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or55- modify it under the terms of the GNU General Public License as66- published by the Free Software Foundation; either version 2, or (at77- your option) any later version.88-99- This program is distributed in the hope that it will be useful, but1010- WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1212- General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,1717- USA.1818-1919- *2020- * This file implements a "generic" interface between the *2121- * zftape-driver and a compression-algorithm. The *2222- * compression-algorithm currently used is a LZ77. I use the *2323- * implementation lzrw3 by Ross N. Williams (Renaissance *2424- * Software). The compression program itself is in the file2525- * lzrw3.c * and lzrw3.h. To adopt another compression algorithm2626- * the functions * zft_compress() and zft_uncompress() must be2727- * changed * appropriately. See below.2828- */2929-3030-#include <linux/errno.h>3131-#include <linux/mm.h>3232-#include <linux/module.h>3333-3434-#include <linux/zftape.h>3535-3636-#include <asm/uaccess.h>3737-3838-#include "../zftape/zftape-init.h"3939-#include "../zftape/zftape-eof.h"4040-#include "../zftape/zftape-ctl.h"4141-#include "../zftape/zftape-write.h"4242-#include "../zftape/zftape-read.h"4343-#include "../zftape/zftape-rw.h"4444-#include "../compressor/zftape-compress.h"4545-#include "../zftape/zftape-vtbl.h"4646-#include "../compressor/lzrw3.h"4747-4848-/*4949- * global variables5050- */5151-5252-/* I handle the allocation of this buffer as a special case, because5353- * it's size varies depending on the tape length inserted.5454- */5555-5656-/* local variables 5757- */5858-static void *zftc_wrk_mem = NULL;5959-static __u8 *zftc_buf = NULL;6060-static void *zftc_scratch_buf = NULL;6161-6262-/* compression statistics 6363- */6464-static unsigned int zftc_wr_uncompressed = 0;6565-static unsigned int zftc_wr_compressed = 0;6666-static unsigned int zftc_rd_uncompressed = 0;6767-static unsigned int zftc_rd_compressed = 0;6868-6969-/* forward */7070-static int zftc_write(int *write_cnt,7171- __u8 *dst_buf, const int seg_sz,7272- const __u8 __user *src_buf, const int req_len,7373- const zft_position *pos, const zft_volinfo *volume);7474-static int zftc_read(int *read_cnt,7575- __u8 __user *dst_buf, const int to_do,7676- const __u8 *src_buf, const int seg_sz,7777- const zft_position *pos, const zft_volinfo *volume);7878-static int zftc_seek(unsigned int new_block_pos, 7979- zft_position *pos, const zft_volinfo *volume,8080- __u8 *buffer);8181-static void zftc_lock (void);8282-static void zftc_reset (void);8383-static void zftc_cleanup(void);8484-static void zftc_stats (void);8585-8686-/* compressed segment. This conforms to QIC-80-MC, Revision K.8787- * 8888- * Rev. K applies to tapes with `fixed length format' which is8989- * indicated by format code 2,3 and 5. See below for format code 4 and 69090- *9191- * 2 bytes: offset of compression segment structure9292- * 29k > offset >= 29k-18: data from previous segment ens in this9393- * segment and no compressed block starts9494- * in this segment9595- * offset == 0: data from previous segment occupies entire9696- * segment and continues in next segment9797- * n bytes: remainder from previous segment9898- * 9999- * Rev. K: 100100- * 4 bytes: 4 bytes: files set byte offset101101- * Post Rev. K and QIC-3020/3020:102102- * 8 bytes: 8 bytes: files set byte offset103103- * 2 bytes: byte count N (amount of data following)104104- * bit 15 is set if data is compressed, bit 15 is not105105- * set if data is uncompressed106106- * N bytes: data (as much as specified in the byte count)107107- * 2 bytes: byte count N_1 of next cluster108108- * N_1 bytes: data of next cluset109109- * 2 bytes: byte count N_2 of next cluster110110- * N_2 bytes: ... 111111- *112112- * Note that the `N' byte count accounts only for the bytes that in the113113- * current segment if the cluster spans to the next segment.114114- */115115-116116-typedef struct117117-{118118- int cmpr_pos; /* actual position in compression buffer */119119- int cmpr_sz; /* what is left in the compression buffer120120- * when copying the compressed data to the121121- * deblock buffer122122- */123123- unsigned int first_block; /* location of header information in124124- * this segment125125- */126126- unsigned int count; /* amount of data of current block127127- * contained in current segment 128128- */129129- unsigned int offset; /* offset in current segment */130130- unsigned int spans:1; /* might continue in next segment */131131- unsigned int uncmpr; /* 0x8000 if this block contains132132- * uncompressed data 133133- */134134- __s64 foffs; /* file set byte offset, same as in 135135- * compression map segment136136- */137137-} cmpr_info;138138-139139-static cmpr_info cseg; /* static data. Must be kept uptodate and shared by 140140- * read, write and seek functions141141- */142142-143143-#define DUMP_CMPR_INFO(level, msg, info) \144144- TRACE(level, msg "\n" \145145- KERN_INFO "cmpr_pos : %d\n" \146146- KERN_INFO "cmpr_sz : %d\n" \147147- KERN_INFO "first_block: %d\n" \148148- KERN_INFO "count : %d\n" \149149- KERN_INFO "offset : %d\n" \150150- KERN_INFO "spans : %d\n" \151151- KERN_INFO "uncmpr : 0x%04x\n" \152152- KERN_INFO "foffs : " LL_X, \153153- (info)->cmpr_pos, (info)->cmpr_sz, (info)->first_block, \154154- (info)->count, (info)->offset, (info)->spans == 1, \155155- (info)->uncmpr, LL((info)->foffs))156156-157157-/* dispatch compression segment info, return error code158158- * 159159- * afterwards, cseg->offset points to start of data of the NEXT160160- * compressed block, and cseg->count contains the amount of data161161- * left in the actual compressed block. cseg->spans is set to 1 if162162- * the block is continued in the following segment. Otherwise it is163163- * set to 0. 164164- */165165-static int get_cseg (cmpr_info *cinfo, const __u8 *buff, 166166- const unsigned int seg_sz,167167- const zft_volinfo *volume)168168-{169169- TRACE_FUN(ft_t_flow);170170-171171- cinfo->first_block = GET2(buff, 0);172172- if (cinfo->first_block == 0) { /* data spans to next segment */173173- cinfo->count = seg_sz - sizeof(__u16);174174- cinfo->offset = seg_sz;175175- cinfo->spans = 1;176176- } else { /* cluster definetely ends in this segment */177177- if (cinfo->first_block > seg_sz) {178178- /* data corrupted */179179- TRACE_ABORT(-EIO, ft_t_err, "corrupted data:\n"180180- KERN_INFO "segment size: %d\n"181181- KERN_INFO "first block : %d",182182- seg_sz, cinfo->first_block);183183- }184184- cinfo->count = cinfo->first_block - sizeof(__u16);185185- cinfo->offset = cinfo->first_block;186186- cinfo->spans = 0;187187- }188188- /* now get the offset the first block should have in the189189- * uncompressed data stream.190190- *191191- * For this magic `18' refer to CRF-3 standard or QIC-80MC,192192- * Rev. K. 193193- */194194- if ((seg_sz - cinfo->offset) > 18) {195195- if (volume->qic113) { /* > revision K */196196- TRACE(ft_t_data_flow, "New QIC-113 compliance");197197- cinfo->foffs = GET8(buff, cinfo->offset);198198- cinfo->offset += sizeof(__s64); 199199- } else {200200- TRACE(/* ft_t_data_flow */ ft_t_noise, "pre QIC-113 version");201201- cinfo->foffs = (__s64)GET4(buff, cinfo->offset);202202- cinfo->offset += sizeof(__u32); 203203- }204204- }205205- if (cinfo->foffs > volume->size) {206206- TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n"207207- KERN_INFO "offset in current volume: %d\n"208208- KERN_INFO "size of current volume : %d",209209- (int)(cinfo->foffs>>10), (int)(volume->size>>10));210210- }211211- if (cinfo->cmpr_pos + cinfo->count > volume->blk_sz) {212212- TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n"213213- KERN_INFO "block size : %d\n"214214- KERN_INFO "data record: %d",215215- volume->blk_sz, cinfo->cmpr_pos + cinfo->count);216216- }217217- DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", cinfo);218218- TRACE_EXIT 0;219219-}220220-221221-/* This one is called, when a new cluster starts in same segment.222222- * 223223- * Note: if this is the first cluster in the current segment, we must224224- * not check whether there are more than 18 bytes available because225225- * this have already been done in get_cseg() and there may be less226226- * than 18 bytes available due to header information.227227- * 228228- */229229-static void get_next_cluster(cmpr_info *cluster, const __u8 *buff, 230230- const int seg_sz, const int finish)231231-{232232- TRACE_FUN(ft_t_flow);233233-234234- if (seg_sz - cluster->offset > 18 || cluster->foffs != 0) {235235- cluster->count = GET2(buff, cluster->offset);236236- cluster->uncmpr = cluster->count & 0x8000;237237- cluster->count -= cluster->uncmpr;238238- cluster->offset += sizeof(__u16);239239- cluster->foffs = 0;240240- if ((cluster->offset + cluster->count) < seg_sz) {241241- cluster->spans = 0;242242- } else if (cluster->offset + cluster->count == seg_sz) {243243- cluster->spans = !finish;244244- } else {245245- /* either an error or a volume written by an 246246- * old version. If this is a data error, then we'll247247- * catch it later.248248- */249249- TRACE(ft_t_data_flow, "Either error or old volume");250250- cluster->spans = 1;251251- cluster->count = seg_sz - cluster->offset;252252- }253253- } else {254254- cluster->count = 0;255255- cluster->spans = 0;256256- cluster->foffs = 0;257257- }258258- DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */ , "", cluster);259259- TRACE_EXIT;260260-}261261-262262-static void zftc_lock(void)263263-{264264-}265265-266266-/* this function is needed for zftape_reset_position in zftape-io.c 267267- */268268-static void zftc_reset(void)269269-{270270- TRACE_FUN(ft_t_flow);271271-272272- memset((void *)&cseg, '\0', sizeof(cseg));273273- zftc_stats();274274- TRACE_EXIT;275275-}276276-277277-static int cmpr_mem_initialized = 0;278278-static unsigned int alloc_blksz = 0;279279-280280-static int zft_allocate_cmpr_mem(unsigned int blksz)281281-{282282- TRACE_FUN(ft_t_flow);283283-284284- if (cmpr_mem_initialized && blksz == alloc_blksz) {285285- TRACE_EXIT 0;286286- }287287- TRACE_CATCH(zft_vmalloc_once(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE),288288- zftc_cleanup());289289- TRACE_CATCH(zft_vmalloc_always(&zftc_buf, blksz + CMPR_OVERRUN),290290- zftc_cleanup());291291- alloc_blksz = blksz;292292- TRACE_CATCH(zft_vmalloc_always(&zftc_scratch_buf, blksz+CMPR_OVERRUN),293293- zftc_cleanup());294294- cmpr_mem_initialized = 1;295295- TRACE_EXIT 0;296296-}297297-298298-static void zftc_cleanup(void)299299-{300300- TRACE_FUN(ft_t_flow);301301-302302- zft_vfree(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE);303303- zft_vfree(&zftc_buf, alloc_blksz + CMPR_OVERRUN);304304- zft_vfree(&zftc_scratch_buf, alloc_blksz + CMPR_OVERRUN);305305- cmpr_mem_initialized = alloc_blksz = 0;306306- TRACE_EXIT;307307-}308308-309309-/*****************************************************************************310310- * *311311- * The following two functions "ftape_compress()" and *312312- * "ftape_uncompress()" are the interface to the actual compression *313313- * algorithm (i.e. they are calling the "compress()" function from *314314- * the lzrw3 package for now). These routines could quite easily be *315315- * changed to adopt another compression algorithm instead of lzrw3, *316316- * which currently is used. *317317- * *318318- *****************************************************************************/319319-320320-/* called by zft_compress_write() to perform the compression. Must321321- * return the size of the compressed data.322322- *323323- * NOTE: The size of the compressed data should not exceed the size of324324- * the uncompressed data. Most compression algorithms have means325325- * to store data unchanged if the "compressed" data amount would326326- * exceed the original one. Mostly this is done by storing some327327- * flag-bytes in front of the compressed data to indicate if it328328- * is compressed or not. Thus the worst compression result329329- * length is the original length plus those flag-bytes.330330- *331331- * We don't want that, as the QIC-80 standard provides a means332332- * of marking uncompressed blocks by simply setting bit 15 of333333- * the compressed block's length. Thus a compessed block can334334- * have at most a length of 2^15-1 bytes. The QIC-80 standard335335- * restricts the block-length even further, allowing only 29k -336336- * 6 bytes.337337- *338338- * Currently, the maximum blocksize used by zftape is 28k.339339- *340340- * In short: don't exceed the length of the input-package, set341341- * bit 15 of the compressed size to 1 if you have copied data342342- * instead of compressing it.343343- */344344-static int zft_compress(__u8 *in_buffer, unsigned int in_sz, __u8 *out_buffer)345345-{ 346346- __s32 compressed_sz;347347- TRACE_FUN(ft_t_flow);348348-349349-350350- lzrw3_compress(COMPRESS_ACTION_COMPRESS, zftc_wrk_mem,351351- in_buffer, in_sz, out_buffer, &compressed_sz);352352- if (TRACE_LEVEL >= ft_t_info) {353353- /* the compiler will optimize this away when354354- * compiled with NO_TRACE_AT_ALL option355355- */356356- TRACE(ft_t_data_flow, "\n"357357- KERN_INFO "before compression: %d bytes\n"358358- KERN_INFO "after compresison : %d bytes", 359359- in_sz, 360360- (int)(compressed_sz < 0 361361- ? -compressed_sz : compressed_sz));362362- /* for statistical purposes363363- */364364- zftc_wr_compressed += (compressed_sz < 0 365365- ? -compressed_sz : compressed_sz);366366- zftc_wr_uncompressed += in_sz;367367- }368368- TRACE_EXIT (int)compressed_sz;369369-}370370-371371-/* called by zft_compress_read() to decompress the data. Must372372- * return the size of the decompressed data for sanity checks373373- * (compared with zft_blk_sz)374374- *375375- * NOTE: Read the note for zft_compress() above! If bit 15 of the376376- * parameter in_sz is set, then the data in in_buffer isn't377377- * compressed, which must be handled by the un-compression378378- * algorithm. (I changed lzrw3 to handle this.)379379- *380380- * The parameter max_out_sz is needed to prevent buffer overruns when 381381- * uncompressing corrupt data.382382- */383383-static unsigned int zft_uncompress(__u8 *in_buffer, 384384- int in_sz, 385385- __u8 *out_buffer,386386- unsigned int max_out_sz)387387-{ 388388- TRACE_FUN(ft_t_flow);389389-390390- lzrw3_compress(COMPRESS_ACTION_DECOMPRESS, zftc_wrk_mem,391391- in_buffer, (__s32)in_sz,392392- out_buffer, (__u32 *)&max_out_sz);393393-394394- if (TRACE_LEVEL >= ft_t_info) {395395- TRACE(ft_t_data_flow, "\n"396396- KERN_INFO "before decompression: %d bytes\n"397397- KERN_INFO "after decompression : %d bytes", 398398- in_sz < 0 ? -in_sz : in_sz,(int)max_out_sz);399399- /* for statistical purposes400400- */401401- zftc_rd_compressed += in_sz < 0 ? -in_sz : in_sz;402402- zftc_rd_uncompressed += max_out_sz;403403- }404404- TRACE_EXIT (unsigned int)max_out_sz;405405-}406406-407407-/* print some statistics about the efficiency of the compression to408408- * the kernel log 409409- */410410-static void zftc_stats(void)411411-{412412- TRACE_FUN(ft_t_flow);413413-414414- if (TRACE_LEVEL < ft_t_info) {415415- TRACE_EXIT;416416- }417417- if (zftc_wr_uncompressed != 0) {418418- if (zftc_wr_compressed > (1<<14)) {419419- TRACE(ft_t_info, "compression statistics (writing):\n"420420- KERN_INFO " compr./uncmpr. : %3d %%",421421- (((zftc_wr_compressed>>10) * 100)422422- / (zftc_wr_uncompressed>>10)));423423- } else {424424- TRACE(ft_t_info, "compression statistics (writing):\n"425425- KERN_INFO " compr./uncmpr. : %3d %%",426426- ((zftc_wr_compressed * 100)427427- / zftc_wr_uncompressed));428428- }429429- }430430- if (zftc_rd_uncompressed != 0) {431431- if (zftc_rd_compressed > (1<<14)) {432432- TRACE(ft_t_info, "compression statistics (reading):\n"433433- KERN_INFO " compr./uncmpr. : %3d %%",434434- (((zftc_rd_compressed>>10) * 100)435435- / (zftc_rd_uncompressed>>10)));436436- } else {437437- TRACE(ft_t_info, "compression statistics (reading):\n"438438- KERN_INFO " compr./uncmpr. : %3d %%",439439- ((zftc_rd_compressed * 100)440440- / zftc_rd_uncompressed));441441- }442442- }443443- /* only print it once: */444444- zftc_wr_uncompressed = 445445- zftc_wr_compressed =446446- zftc_rd_uncompressed =447447- zftc_rd_compressed = 0;448448- TRACE_EXIT;449449-}450450-451451-/* start new compressed block 452452- */453453-static int start_new_cseg(cmpr_info *cluster, 454454- char *dst_buf, 455455- const zft_position *pos,456456- const unsigned int blk_sz,457457- const char *src_buf,458458- const int this_segs_sz,459459- const int qic113)460460-{461461- int size_left;462462- int cp_cnt;463463- int buf_pos;464464- TRACE_FUN(ft_t_flow);465465-466466- size_left = this_segs_sz - sizeof(__u16) - cluster->cmpr_sz;467467- TRACE(ft_t_data_flow,"\n" 468468- KERN_INFO "segment size : %d\n"469469- KERN_INFO "compressed_sz: %d\n"470470- KERN_INFO "size_left : %d",471471- this_segs_sz, cluster->cmpr_sz, size_left);472472- if (size_left > 18) { /* start a new cluseter */473473- cp_cnt = cluster->cmpr_sz;474474- cluster->cmpr_sz = 0;475475- buf_pos = cp_cnt + sizeof(__u16);476476- PUT2(dst_buf, 0, buf_pos);477477-478478- if (qic113) {479479- __s64 foffs = pos->volume_pos;480480- if (cp_cnt) foffs += (__s64)blk_sz;481481-482482- TRACE(ft_t_data_flow, "new style QIC-113 header");483483- PUT8(dst_buf, buf_pos, foffs);484484- buf_pos += sizeof(__s64);485485- } else {486486- __u32 foffs = (__u32)pos->volume_pos;487487- if (cp_cnt) foffs += (__u32)blk_sz;488488-489489- TRACE(ft_t_data_flow, "old style QIC-80MC header");490490- PUT4(dst_buf, buf_pos, foffs);491491- buf_pos += sizeof(__u32);492492- }493493- } else if (size_left >= 0) {494494- cp_cnt = cluster->cmpr_sz;495495- cluster->cmpr_sz = 0;496496- buf_pos = cp_cnt + sizeof(__u16);497497- PUT2(dst_buf, 0, buf_pos); 498498- /* zero unused part of segment. */499499- memset(dst_buf + buf_pos, '\0', size_left);500500- buf_pos = this_segs_sz;501501- } else { /* need entire segment and more space */502502- PUT2(dst_buf, 0, 0); 503503- cp_cnt = this_segs_sz - sizeof(__u16);504504- cluster->cmpr_sz -= cp_cnt;505505- buf_pos = this_segs_sz;506506- }507507- memcpy(dst_buf + sizeof(__u16), src_buf + cluster->cmpr_pos, cp_cnt);508508- cluster->cmpr_pos += cp_cnt;509509- TRACE_EXIT buf_pos;510510-}511511-512512-/* return-value: the number of bytes removed from the user-buffer513513- * `src_buf' or error code514514- *515515- * int *write_cnt : how much actually has been moved to the516516- * dst_buf. Need not be initialized when517517- * function returns with an error code518518- * (negativ return value) 519519- * __u8 *dst_buf : kernel space buffer where the has to be520520- * copied to. The contents of this buffers521521- * goes to a specific segment.522522- * const int seg_sz : the size of the segment dst_buf will be523523- * copied to.524524- * const zft_position *pos : struct containing the coordinates in525525- * the current volume (byte position,526526- * segment id of current segment etc)527527- * const zft_volinfo *volume: information about the current volume,528528- * size etc.529529- * const __u8 *src_buf : user space buffer that contains the530530- * data the user wants to be written to531531- * tape.532532- * const int req_len : the amount of data the user wants to be533533- * written to tape.534534- */535535-static int zftc_write(int *write_cnt,536536- __u8 *dst_buf, const int seg_sz,537537- const __u8 __user *src_buf, const int req_len,538538- const zft_position *pos, const zft_volinfo *volume)539539-{540540- int req_len_left = req_len;541541- int result;542542- int len_left;543543- int buf_pos_write = pos->seg_byte_pos;544544- TRACE_FUN(ft_t_flow);545545-546546- /* Note: we do not unlock the module because547547- * there are some values cached in that `cseg' variable. We548548- * don't don't want to use this information when being549549- * unloaded by kerneld even when the tape is full or when we550550- * cannot allocate enough memory.551551- */552552- if (pos->tape_pos > (volume->size-volume->blk_sz-ZFT_CMPR_OVERHEAD)) {553553- TRACE_EXIT -ENOSPC;554554- } 555555- if (zft_allocate_cmpr_mem(volume->blk_sz) < 0) {556556- /* should we unlock the module? But it shouldn't 557557- * be locked anyway ...558558- */559559- TRACE_EXIT -ENOMEM;560560- }561561- if (buf_pos_write == 0) { /* fill a new segment */562562- *write_cnt = buf_pos_write = start_new_cseg(&cseg,563563- dst_buf,564564- pos,565565- volume->blk_sz,566566- zftc_buf, 567567- seg_sz,568568- volume->qic113);569569- if (cseg.cmpr_sz == 0 && cseg.cmpr_pos != 0) {570570- req_len_left -= result = volume->blk_sz;571571- cseg.cmpr_pos = 0;572572- } else {573573- result = 0;574574- }575575- } else {576576- *write_cnt = result = 0;577577- }578578-579579- len_left = seg_sz - buf_pos_write;580580- while ((req_len_left > 0) && (len_left > 18)) {581581- /* now we have some size left for a new compressed582582- * block. We know, that the compression buffer is583583- * empty (else there wouldn't be any space left). 584584- */585585- if (copy_from_user(zftc_scratch_buf, src_buf + result, 586586- volume->blk_sz) != 0) {587587- TRACE_EXIT -EFAULT;588588- }589589- req_len_left -= volume->blk_sz;590590- cseg.cmpr_sz = zft_compress(zftc_scratch_buf, volume->blk_sz, 591591- zftc_buf);592592- if (cseg.cmpr_sz < 0) {593593- cseg.uncmpr = 0x8000;594594- cseg.cmpr_sz = -cseg.cmpr_sz;595595- } else {596596- cseg.uncmpr = 0;597597- }598598- /* increment "result" iff we copied the entire599599- * compressed block to the zft_deblock_buf 600600- */601601- len_left -= sizeof(__u16);602602- if (len_left >= cseg.cmpr_sz) {603603- len_left -= cseg.count = cseg.cmpr_sz;604604- cseg.cmpr_pos = cseg.cmpr_sz = 0;605605- result += volume->blk_sz;606606- } else {607607- cseg.cmpr_sz -= 608608- cseg.cmpr_pos =609609- cseg.count = len_left;610610- len_left = 0;611611- }612612- PUT2(dst_buf, buf_pos_write, cseg.uncmpr | cseg.count);613613- buf_pos_write += sizeof(__u16);614614- memcpy(dst_buf + buf_pos_write, zftc_buf, cseg.count);615615- buf_pos_write += cseg.count;616616- *write_cnt += cseg.count + sizeof(__u16);617617- FT_SIGNAL_EXIT(_DONT_BLOCK);618618- }619619- /* erase the remainder of the segment if less than 18 bytes620620- * left (18 bytes is due to the QIC-80 standard) 621621- */622622- if (len_left <= 18) {623623- memset(dst_buf + buf_pos_write, '\0', len_left);624624- (*write_cnt) += len_left;625625- }626626- TRACE(ft_t_data_flow, "returning %d", result);627627- TRACE_EXIT result;628628-} 629629-630630-/* out:631631- *632632- * int *read_cnt: the number of bytes we removed from the zft_deblock_buf633633- * (result)634634- * int *to_do : the remaining size of the read-request.635635- *636636- * in:637637- *638638- * char *buff : buff is the address of the upper part of the user639639- * buffer, that hasn't been filled with data yet.640640-641641- * int buf_pos_read : copy of from _ftape_read()642642- * int buf_len_read : copy of buf_len_rd from _ftape_read()643643- * char *zft_deblock_buf: zft_deblock_buf644644- * unsigned short blk_sz: the block size valid for this volume, may differ645645- * from zft_blk_sz.646646- * int finish: if != 0 means that this is the last segment belonging647647- * to this volume648648- * returns the amount of data actually copied to the user-buffer649649- *650650- * to_do MUST NOT SHRINK except to indicate an EOF. In this case *to_do has to651651- * be set to 0 652652- */653653-static int zftc_read (int *read_cnt, 654654- __u8 __user *dst_buf, const int to_do, 655655- const __u8 *src_buf, const int seg_sz, 656656- const zft_position *pos, const zft_volinfo *volume)657657-{ 658658- int uncompressed_sz; 659659- int result = 0;660660- int remaining = to_do;661661- TRACE_FUN(ft_t_flow);662662-663663- TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),);664664- if (pos->seg_byte_pos == 0) {665665- /* new segment just read666666- */667667- TRACE_CATCH(get_cseg(&cseg, src_buf, seg_sz, volume),668668- *read_cnt = 0);669669- memcpy(zftc_buf + cseg.cmpr_pos, src_buf + sizeof(__u16), 670670- cseg.count);671671- cseg.cmpr_pos += cseg.count;672672- *read_cnt = cseg.offset;673673- DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", &cseg);674674- } else {675675- *read_cnt = 0;676676- }677677- /* loop and uncompress until user buffer full or678678- * deblock-buffer empty 679679- */680680- TRACE(ft_t_data_flow, "compressed_sz: %d, compos : %d, *read_cnt: %d",681681- cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);682682- while ((cseg.spans == 0) && (remaining > 0)) {683683- if (cseg.cmpr_pos != 0) { /* cmpr buf is not empty */684684- uncompressed_sz = 685685- zft_uncompress(zftc_buf,686686- cseg.uncmpr == 0x8000 ?687687- -cseg.cmpr_pos : cseg.cmpr_pos,688688- zftc_scratch_buf,689689- volume->blk_sz);690690- if (uncompressed_sz != volume->blk_sz) {691691- *read_cnt = 0;692692- TRACE_ABORT(-EIO, ft_t_warn,693693- "Uncompressed blk (%d) != blk size (%d)",694694- uncompressed_sz, volume->blk_sz);695695- } 696696- if (copy_to_user(dst_buf + result, 697697- zftc_scratch_buf, 698698- uncompressed_sz) != 0 ) {699699- TRACE_EXIT -EFAULT;700700- }701701- remaining -= uncompressed_sz;702702- result += uncompressed_sz;703703- cseg.cmpr_pos = 0;704704- } 705705- if (remaining > 0) {706706- get_next_cluster(&cseg, src_buf, seg_sz, 707707- volume->end_seg == pos->seg_pos);708708- if (cseg.count != 0) {709709- memcpy(zftc_buf, src_buf + cseg.offset,710710- cseg.count);711711- cseg.cmpr_pos = cseg.count;712712- cseg.offset += cseg.count;713713- *read_cnt += cseg.count + sizeof(__u16);714714- } else {715715- remaining = 0;716716- }717717- }718718- TRACE(ft_t_data_flow, "\n" 719719- KERN_INFO "compressed_sz: %d\n"720720- KERN_INFO "compos : %d\n"721721- KERN_INFO "*read_cnt : %d",722722- cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt);723723- }724724- if (seg_sz - cseg.offset <= 18) {725725- *read_cnt += seg_sz - cseg.offset;726726- TRACE(ft_t_data_flow, "expanding read cnt to: %d", *read_cnt);727727- }728728- TRACE(ft_t_data_flow, "\n"729729- KERN_INFO "segment size : %d\n"730730- KERN_INFO "read count : %d\n"731731- KERN_INFO "buf_pos_read : %d\n"732732- KERN_INFO "remaining : %d",733733- seg_sz, *read_cnt, pos->seg_byte_pos, 734734- seg_sz - *read_cnt - pos->seg_byte_pos);735735- TRACE(ft_t_data_flow, "returning: %d", result);736736- TRACE_EXIT result;737737-} 738738-739739-/* seeks to the new data-position. Reads sometimes a segment.740740- * 741741- * start_seg and end_seg give the boundaries of the current volume742742- * blk_sz is the blk_sz of the current volume as stored in the743743- * volume label744744- *745745- * We don't allow blocksizes less than 1024 bytes, therefore we don't need746746- * a 64 bit argument for new_block_pos.747747- */748748-749749-static int seek_in_segment(const unsigned int to_do, cmpr_info *c_info,750750- const char *src_buf, const int seg_sz, 751751- const int seg_pos, const zft_volinfo *volume);752752-static int slow_seek_forward_until_error(const unsigned int distance,753753- cmpr_info *c_info, zft_position *pos, 754754- const zft_volinfo *volume, __u8 *buf);755755-static int search_valid_segment(unsigned int segment,756756- const unsigned int end_seg,757757- const unsigned int max_foffs,758758- zft_position *pos, cmpr_info *c_info,759759- const zft_volinfo *volume, __u8 *buf);760760-static int slow_seek_forward(unsigned int dest, cmpr_info *c_info,761761- zft_position *pos, const zft_volinfo *volume,762762- __u8 *buf);763763-static int compute_seg_pos(unsigned int dest, zft_position *pos,764764- const zft_volinfo *volume);765765-766766-#define ZFT_SLOW_SEEK_THRESHOLD 10 /* segments */767767-#define ZFT_FAST_SEEK_MAX_TRIALS 10 /* times */768768-#define ZFT_FAST_SEEK_BACKUP 10 /* segments */769769-770770-static int zftc_seek(unsigned int new_block_pos,771771- zft_position *pos, const zft_volinfo *volume, __u8 *buf)772772-{773773- unsigned int dest;774774- int limit;775775- int distance;776776- int result = 0;777777- int seg_dist;778778- int new_seg;779779- int old_seg = 0;780780- int fast_seek_trials = 0;781781- TRACE_FUN(ft_t_flow);782782-783783- if (new_block_pos == 0) {784784- pos->seg_pos = volume->start_seg;785785- pos->seg_byte_pos = 0;786786- pos->volume_pos = 0;787787- zftc_reset();788788- TRACE_EXIT 0;789789- }790790- dest = new_block_pos * (volume->blk_sz >> 10);791791- distance = dest - (pos->volume_pos >> 10);792792- while (distance != 0) {793793- seg_dist = compute_seg_pos(dest, pos, volume);794794- TRACE(ft_t_noise, "\n"795795- KERN_INFO "seg_dist: %d\n"796796- KERN_INFO "distance: %d\n"797797- KERN_INFO "dest : %d\n"798798- KERN_INFO "vpos : %d\n"799799- KERN_INFO "seg_pos : %d\n"800800- KERN_INFO "trials : %d",801801- seg_dist, distance, dest,802802- (unsigned int)(pos->volume_pos>>10), pos->seg_pos,803803- fast_seek_trials);804804- if (distance > 0) {805805- if (seg_dist < 0) {806806- TRACE(ft_t_bug, "BUG: distance %d > 0, "807807- "segment difference %d < 0",808808- distance, seg_dist);809809- result = -EIO;810810- break;811811- }812812- new_seg = pos->seg_pos + seg_dist;813813- if (new_seg > volume->end_seg) {814814- new_seg = volume->end_seg;815815- }816816- if (old_seg == new_seg || /* loop */817817- seg_dist <= ZFT_SLOW_SEEK_THRESHOLD ||818818- fast_seek_trials >= ZFT_FAST_SEEK_MAX_TRIALS) {819819- TRACE(ft_t_noise, "starting slow seek:\n"820820- KERN_INFO "fast seek failed too often: %s\n"821821- KERN_INFO "near target position : %s\n"822822- KERN_INFO "looping between two segs : %s",823823- (fast_seek_trials >= 824824- ZFT_FAST_SEEK_MAX_TRIALS)825825- ? "yes" : "no",826826- (seg_dist <= ZFT_SLOW_SEEK_THRESHOLD) 827827- ? "yes" : "no",828828- (old_seg == new_seg)829829- ? "yes" : "no");830830- result = slow_seek_forward(dest, &cseg, 831831- pos, volume, buf);832832- break;833833- }834834- old_seg = new_seg;835835- limit = volume->end_seg;836836- fast_seek_trials ++;837837- for (;;) {838838- result = search_valid_segment(new_seg, limit,839839- volume->size,840840- pos, &cseg,841841- volume, buf);842842- if (result == 0 || result == -EINTR) {843843- break;844844- }845845- if (new_seg == volume->start_seg) {846846- result = -EIO; /* set errror 847847- * condition848848- */849849- break;850850- }851851- limit = new_seg;852852- new_seg -= ZFT_FAST_SEEK_BACKUP;853853- if (new_seg < volume->start_seg) {854854- new_seg = volume->start_seg;855855- }856856- }857857- if (result < 0) {858858- TRACE(ft_t_warn,859859- "Couldn't find a readable segment");860860- break;861861- }862862- } else /* if (distance < 0) */ {863863- if (seg_dist > 0) {864864- TRACE(ft_t_bug, "BUG: distance %d < 0, "865865- "segment difference %d >0",866866- distance, seg_dist);867867- result = -EIO;868868- break;869869- }870870- new_seg = pos->seg_pos + seg_dist;871871- if (fast_seek_trials > 0 && seg_dist == 0) {872872- /* this avoids sticking to the same873873- * segment all the time. On the other hand:874874- * if we got here for the first time, and the875875- * deblock_buffer still contains a valid876876- * segment, then there is no need to skip to 877877- * the previous segment if the desired position878878- * is inside this segment.879879- */880880- new_seg --;881881- }882882- if (new_seg < volume->start_seg) {883883- new_seg = volume->start_seg;884884- }885885- limit = pos->seg_pos;886886- fast_seek_trials ++;887887- for (;;) {888888- result = search_valid_segment(new_seg, limit,889889- pos->volume_pos,890890- pos, &cseg,891891- volume, buf);892892- if (result == 0 || result == -EINTR) {893893- break;894894- }895895- if (new_seg == volume->start_seg) {896896- result = -EIO; /* set errror 897897- * condition898898- */899899- break;900900- }901901- limit = new_seg;902902- new_seg -= ZFT_FAST_SEEK_BACKUP;903903- if (new_seg < volume->start_seg) {904904- new_seg = volume->start_seg;905905- }906906- }907907- if (result < 0) {908908- TRACE(ft_t_warn,909909- "Couldn't find a readable segment");910910- break;911911- }912912- }913913- distance = dest - (pos->volume_pos >> 10);914914- }915915- TRACE_EXIT result;916916-}917917-918918-919919-/* advance inside the given segment at most to_do bytes.920920- * of kilobytes moved921921- */922922-923923-static int seek_in_segment(const unsigned int to_do,924924- cmpr_info *c_info,925925- const char *src_buf, 926926- const int seg_sz, 927927- const int seg_pos,928928- const zft_volinfo *volume)929929-{930930- int result = 0;931931- int blk_sz = volume->blk_sz >> 10;932932- int remaining = to_do;933933- TRACE_FUN(ft_t_flow);934934-935935- if (c_info->offset == 0) {936936- /* new segment just read937937- */938938- TRACE_CATCH(get_cseg(c_info, src_buf, seg_sz, volume),);939939- c_info->cmpr_pos += c_info->count;940940- DUMP_CMPR_INFO(ft_t_noise, "", c_info);941941- }942942- /* loop and uncompress until user buffer full or943943- * deblock-buffer empty 944944- */945945- TRACE(ft_t_noise, "compressed_sz: %d, compos : %d",946946- c_info->cmpr_sz, c_info->cmpr_pos);947947- while (c_info->spans == 0 && remaining > 0) {948948- if (c_info->cmpr_pos != 0) { /* cmpr buf is not empty */949949- result += blk_sz;950950- remaining -= blk_sz;951951- c_info->cmpr_pos = 0;952952- }953953- if (remaining > 0) {954954- get_next_cluster(c_info, src_buf, seg_sz, 955955- volume->end_seg == seg_pos);956956- if (c_info->count != 0) {957957- c_info->cmpr_pos = c_info->count;958958- c_info->offset += c_info->count;959959- } else {960960- break;961961- }962962- }963963- /* Allow escape from this loop on signal!964964- */965965- FT_SIGNAL_EXIT(_DONT_BLOCK);966966- DUMP_CMPR_INFO(ft_t_noise, "", c_info);967967- TRACE(ft_t_noise, "to_do: %d", remaining);968968- }969969- if (seg_sz - c_info->offset <= 18) {970970- c_info->offset = seg_sz;971971- }972972- TRACE(ft_t_noise, "\n"973973- KERN_INFO "segment size : %d\n"974974- KERN_INFO "buf_pos_read : %d\n"975975- KERN_INFO "remaining : %d",976976- seg_sz, c_info->offset,977977- seg_sz - c_info->offset);978978- TRACE_EXIT result;979979-} 980980-981981-static int slow_seek_forward_until_error(const unsigned int distance,982982- cmpr_info *c_info,983983- zft_position *pos, 984984- const zft_volinfo *volume,985985- __u8 *buf)986986-{987987- unsigned int remaining = distance;988988- int seg_sz;989989- int seg_pos;990990- int result;991991- TRACE_FUN(ft_t_flow);992992-993993- seg_pos = pos->seg_pos;994994- do {995995- TRACE_CATCH(seg_sz = zft_fetch_segment(seg_pos, buf, 996996- FT_RD_AHEAD),);997997- /* now we have the contents of the actual segment in998998- * the deblock buffer999999- */10001000- TRACE_CATCH(result = seek_in_segment(remaining, c_info, buf,10011001- seg_sz, seg_pos,volume),);10021002- remaining -= result;10031003- pos->volume_pos += result<<10;10041004- pos->seg_pos = seg_pos;10051005- pos->seg_byte_pos = c_info->offset;10061006- seg_pos ++;10071007- if (seg_pos <= volume->end_seg && c_info->offset == seg_sz) {10081008- pos->seg_pos ++;10091009- pos->seg_byte_pos = 0;10101010- c_info->offset = 0;10111011- }10121012- /* Allow escape from this loop on signal!10131013- */10141014- FT_SIGNAL_EXIT(_DONT_BLOCK);10151015- TRACE(ft_t_noise, "\n"10161016- KERN_INFO "remaining: %d\n"10171017- KERN_INFO "seg_pos: %d\n"10181018- KERN_INFO "end_seg: %d\n"10191019- KERN_INFO "result: %d",10201020- remaining, seg_pos, volume->end_seg, result); 10211021- } while (remaining > 0 && seg_pos <= volume->end_seg);10221022- TRACE_EXIT 0;10231023-}10241024-10251025-/* return segment id of next segment containing valid data, -EIO otherwise10261026- */10271027-static int search_valid_segment(unsigned int segment,10281028- const unsigned int end_seg,10291029- const unsigned int max_foffs,10301030- zft_position *pos,10311031- cmpr_info *c_info,10321032- const zft_volinfo *volume,10331033- __u8 *buf)10341034-{10351035- cmpr_info tmp_info;10361036- int seg_sz;10371037- TRACE_FUN(ft_t_flow);10381038-10391039- memset(&tmp_info, 0, sizeof(cmpr_info));10401040- while (segment <= end_seg) {10411041- FT_SIGNAL_EXIT(_DONT_BLOCK);10421042- TRACE(ft_t_noise,10431043- "Searching readable segment between %d and %d",10441044- segment, end_seg);10451045- seg_sz = zft_fetch_segment(segment, buf, FT_RD_AHEAD);10461046- if ((seg_sz > 0) &&10471047- (get_cseg (&tmp_info, buf, seg_sz, volume) >= 0) &&10481048- (tmp_info.foffs != 0 || segment == volume->start_seg)) {10491049- if ((tmp_info.foffs>>10) > max_foffs) {10501050- TRACE_ABORT(-EIO, ft_t_noise, "\n"10511051- KERN_INFO "cseg.foff: %d\n"10521052- KERN_INFO "dest : %d",10531053- (int)(tmp_info.foffs >> 10),10541054- max_foffs);10551055- }10561056- DUMP_CMPR_INFO(ft_t_noise, "", &tmp_info);10571057- *c_info = tmp_info;10581058- pos->seg_pos = segment;10591059- pos->volume_pos = c_info->foffs;10601060- pos->seg_byte_pos = c_info->offset;10611061- TRACE(ft_t_noise, "found segment at %d", segment);10621062- TRACE_EXIT 0;10631063- }10641064- segment++;10651065- }10661066- TRACE_EXIT -EIO;10671067-}10681068-10691069-static int slow_seek_forward(unsigned int dest,10701070- cmpr_info *c_info,10711071- zft_position *pos,10721072- const zft_volinfo *volume,10731073- __u8 *buf)10741074-{10751075- unsigned int distance;10761076- int result = 0;10771077- TRACE_FUN(ft_t_flow);10781078-10791079- distance = dest - (pos->volume_pos >> 10);10801080- while ((distance > 0) &&10811081- (result = slow_seek_forward_until_error(distance,10821082- c_info,10831083- pos,10841084- volume,10851085- buf)) < 0) {10861086- if (result == -EINTR) {10871087- break;10881088- }10891089- TRACE(ft_t_noise, "seg_pos: %d", pos->seg_pos);10901090- /* the failing segment is either pos->seg_pos or10911091- * pos->seg_pos + 1. There is no need to further try10921092- * that segment, because ftape_read_segment() already10931093- * has tried very much to read it. So we start with10941094- * following segment, which is pos->seg_pos + 110951095- */10961096- if(search_valid_segment(pos->seg_pos+1, volume->end_seg, dest,10971097- pos, c_info,10981098- volume, buf) < 0) {10991099- TRACE(ft_t_noise, "search_valid_segment() failed");11001100- result = -EIO;11011101- break;11021102- }11031103- distance = dest - (pos->volume_pos >> 10);11041104- result = 0;11051105- TRACE(ft_t_noise, "segment: %d", pos->seg_pos);11061106- /* found valid segment, retry the seek */11071107- }11081108- TRACE_EXIT result;11091109-}11101110-11111111-static int compute_seg_pos(const unsigned int dest,11121112- zft_position *pos,11131113- const zft_volinfo *volume)11141114-{11151115- int segment;11161116- int distance = dest - (pos->volume_pos >> 10);11171117- unsigned int raw_size;11181118- unsigned int virt_size;11191119- unsigned int factor;11201120- TRACE_FUN(ft_t_flow);11211121-11221122- if (distance >= 0) {11231123- raw_size = volume->end_seg - pos->seg_pos + 1;11241124- virt_size = ((unsigned int)(volume->size>>10) 11251125- - (unsigned int)(pos->volume_pos>>10)11261126- + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);11271127- virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;11281128- if (virt_size == 0 || raw_size == 0) {11291129- TRACE_EXIT 0;11301130- }11311131- if (raw_size >= (1<<25)) {11321132- factor = raw_size/(virt_size>>7);11331133- } else {11341134- factor = (raw_size<<7)/virt_size;11351135- }11361136- segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);11371137- segment = (segment * factor)>>7;11381138- } else {11391139- raw_size = pos->seg_pos - volume->start_seg + 1;11401140- virt_size = ((unsigned int)(pos->volume_pos>>10)11411141- + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1);11421142- virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS;11431143- if (virt_size == 0 || raw_size == 0) {11441144- TRACE_EXIT 0;11451145- }11461146- if (raw_size >= (1<<25)) {11471147- factor = raw_size/(virt_size>>7);11481148- } else {11491149- factor = (raw_size<<7)/virt_size;11501150- }11511151- segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS);11521152- }11531153- TRACE(ft_t_noise, "factor: %d/%d", factor, 1<<7);11541154- TRACE_EXIT segment;11551155-}11561156-11571157-static struct zft_cmpr_ops cmpr_ops = {11581158- zftc_write,11591159- zftc_read,11601160- zftc_seek,11611161- zftc_lock,11621162- zftc_reset,11631163- zftc_cleanup11641164-};11651165-11661166-int zft_compressor_init(void)11671167-{11681168- TRACE_FUN(ft_t_flow);11691169-11701170-#ifdef MODULE11711171- printk(KERN_INFO "zftape compressor v1.00a 970514 for " FTAPE_VERSION "\n");11721172- if (TRACE_LEVEL >= ft_t_info) {11731173- printk(11741174-KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"11751175-KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n");11761176- }11771177-#else /* !MODULE */11781178- /* print a short no-nonsense boot message */11791179- printk(KERN_INFO "zftape compressor v1.00a 970514\n");11801180- printk(KERN_INFO "For use with " FTAPE_VERSION "\n");11811181-#endif /* MODULE */11821182- TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);11831183- TRACE(ft_t_info, "installing compressor for zftape ...");11841184- TRACE_CATCH(zft_cmpr_register(&cmpr_ops),);11851185- TRACE_EXIT 0;11861186-}11871187-11881188-#ifdef MODULE11891189-11901190-MODULE_AUTHOR(11911191- "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de");11921192-MODULE_DESCRIPTION(11931193-"Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams");11941194-MODULE_LICENSE("GPL");11951195-11961196-/* Called by modules package when installing the driver11971197- */11981198-int init_module(void)11991199-{12001200- return zft_compressor_init();12011201-}12021202-12031203-#endif /* MODULE */
-83
drivers/char/ftape/compressor/zftape-compress.h
···11-#ifndef _ZFTAPE_COMPRESS_H22-#define _ZFTAPE_COMPRESS_H33-/*44- * Copyright (c) 1994-1997 Claus-Justus Heine55-66- This program is free software; you can redistribute it and/or77- modify it under the terms of the GNU General Public License as88- published by the Free Software Foundation; either version 2, or (at99- your option) any later version.1010-1111- This program is distributed in the hope that it will be useful, but1212- WITHOUT ANY WARRANTY; without even the implied warranty of1313- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1414- General Public License for more details.1515-1616- You should have received a copy of the GNU General Public License1717- along with this program; see the file COPYING. If not, write to1818- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,1919- USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/compressor/zftape-compress.h,v $2323- * $Revision: 1.1 $2424- * $Date: 1997/10/05 19:12:32 $2525- *2626- * This file contains macros and definitions for zftape's2727- * builtin compression code.2828- *2929- */3030-3131-#include "../zftape/zftape-buffers.h"3232-#include "../zftape/zftape-vtbl.h"3333-#include "../compressor/lzrw3.h"3434-3535-/* CMPR_WRK_MEM_SIZE gives the size of the compression wrk_mem */3636-/* I got these out of lzrw3.c */3737-#define U(X) ((__u32) X)3838-#define SIZE_P_BYTE (U(sizeof(__u8 *)))3939-#define ALIGNMENT_FUDGE (U(16))4040-4141-#define CMPR_WRK_MEM_SIZE (U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE)4242-4343-/* the maximum number of bytes the size of the "compressed" data can4444- * exceed the uncompressed data. As it is quite useless to compress4545- * data twice it is sometimes the case that it is more efficient to4646- * copy a block of data but to feed it to the "compression"4747- * algorithm. In this case there are some flag bytes or the like4848- * proceding the "compressed" data. THAT MUST NOT BE THE CASE for the4949- * algorithm we use for this driver. Instead, the high bit 15 of5050- * compressed_size:5151- *5252- * compressed_size = ftape_compress()5353- *5454- * must be set in such a case.5555- *5656- * Nevertheless, it might also be as for lzrw3 that there is an5757- * "intermediate" overrun that exceeds the amount of the compressed5858- * data that is actually produced. During the algorithm we need in the5959- * worst case MAX_CMP_GROUP bytes more than the input-size.6060- */6161-#define MAX_CMP_GROUP (2+16*2) /* from lzrw3.c */6262-6363-#define CMPR_OVERRUN MAX_CMP_GROUP /* during compression */6464-6565-/****************************************************/6666-6767-#define CMPR_BUFFER_SIZE (MAX_BLOCK_SIZE + CMPR_OVERRUN)6868-6969-/* the compression map stores the byte offset compressed blocks within7070- * the current volume for catridges with format code 2,3 and 57171- * (and old versions of zftape) and the offset measured in kilobytes for7272- * format code 4 and 6. This gives us a possible max. size of a 7373- * compressed volume of 1024*4GIG which should be enough.7474- */7575-typedef __u32 CmprMap;7676-7777-/* globals 7878- */7979-8080-/* exported functions8181- */8282-8383-#endif /* _ZFTAPE_COMPRESS_H */
-43
drivers/char/ftape/lowlevel/Makefile
···11-#22-# Copyright (C) 1996, 1997 Clau-Justus Heine.33-#44-# This program is free software; you can redistribute it and/or modify55-# it under the terms of the GNU General Public License as published by66-# the Free Software Foundation; either version 2, or (at your option)77-# any later version.88-# 99-# This program is distributed in the hope that it will be useful,1010-# but WITHOUT ANY WARRANTY; without even the implied warranty of1111-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212-# GNU General Public License for more details.1313-# 1414-# You should have received a copy of the GNU General Public License1515-# along with this program; see the file COPYING. If not, write to1616-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-#1818-# $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/Makefile,v $1919-# $Revision: 1.4 $2020-# $Date: 1997/10/07 09:26:02 $2121-#2222-# Makefile for the lowlevel part QIC-40/80/3010/3020 floppy-tape2323-# driver for Linux.2424-#2525-2626-obj-$(CONFIG_FTAPE) += ftape.o2727-2828-ftape-objs := ftape-init.o fdc-io.o fdc-isr.o \2929- ftape-bsm.o ftape-ctl.o ftape-read.o ftape-rw.o \3030- ftape-write.o ftape-io.o ftape-calibr.o ftape-ecc.o fc-10.o \3131- ftape-buffer.o ftape-format.o ftape_syms.o3232-3333-ifeq ($(CONFIG_FTAPE),y)3434-ftape-objs += ftape-setup.o3535-endif3636-3737-ifndef CONFIG_FT_NO_TRACE_AT_ALL3838-ftape-objs += ftape-tracing.o3939-endif4040-4141-ifeq ($(CONFIG_FT_PROC_FS),y)4242-ftape-objs += ftape-proc.o4343-endif
-175
drivers/char/ftape/lowlevel/fc-10.c
···11-/*22- *33-44- Copyright (C) 1993,1994 Jon Tombs.55-66- This program is distributed in the hope that it will be useful,77- but WITHOUT ANY WARRANTY; without even the implied warranty of88- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the99- GNU General Public License for more details.1010-1111- The entire guts of this program was written by dosemu, modified to1212- record reads and writes to the ports in the 0x180-0x188 address space,1313- while running the CMS program TAPE.EXE V2.0.5 supplied with the drive.1414-1515- Modified to use an array of addresses and generally cleaned up (made1616- much shorter) 4 June 94, dosemu isn't that good at writing short code it1717- would seem :-). Made independent of 0x180, but I doubt it will work1818- at any other address.1919-2020- Modified for distribution with ftape source. 21 June 94, SJL.2121-2222- Modifications on 20 October 95, by Daniel Cohen (catman@wpi.edu):2323- Modified to support different DMA, IRQ, and IO Ports. Borland's2424- Turbo Debugger in virtual 8086 mode (TD386.EXE with hardware breakpoints2525- provided by the TDH386.SYS Device Driver) was used on the CMS program2626- TAPE V4.0.5. I set breakpoints on I/O to ports 0x180-0x187. Note that2727- CMS's program will not successfully configure the tape drive if you set2828- breakpoints on IO Reads, but you can set them on IO Writes without problems.2929- Known problems:3030- - You can not use DMA Channels 5 or 7.3131-3232- Modification on 29 January 96, by Daniel Cohen (catman@wpi.edu):3333- Modified to only accept IRQs 3 - 7, or 9. Since we can only send a 3 bit3434- number representing the IRQ to the card, special handling is required when3535- IRQ 9 is selected. IRQ 2 and 9 are the same, and we should request IRQ 93636- from the kernel while telling the card to use IRQ 2. Thanks to Greg3737- Crider (gcrider@iclnet.org) for finding and locating this bug, as well as3838- testing the patch.3939-4040- Modification on 11 December 96, by Claus Heine (claus@momo.math.rwth-aachen.de):4141- Modified a little to use variahle ft_fdc_base, ft_fdc_irq, ft_fdc_dma 4242- instead of preprocessor symbols. Thus we can compile this into the module4343- or kernel and let the user specify the options as command line arguments.4444-4545- *4646- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.c,v $4747- * $Revision: 1.2 $4848- * $Date: 1997/10/05 19:18:04 $4949- *5050- * This file contains code for the CMS FC-10/FC-20 card.5151- */5252-5353-#include <asm/io.h>5454-#include <linux/ftape.h>5555-#include "../lowlevel/ftape-tracing.h"5656-#include "../lowlevel/fdc-io.h"5757-#include "../lowlevel/fc-10.h"5858-5959-static __u16 inbs_magic[] = {6060- 0x3, 0x3, 0x0, 0x4, 0x7, 0x2, 0x5, 0x3, 0x1, 0x4,6161- 0x3, 0x5, 0x2, 0x0, 0x3, 0x7, 0x4, 0x2,6262- 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x76363-};6464-6565-static __u16 fc10_ports[] = {6666- 0x180, 0x210, 0x2A0, 0x300, 0x330, 0x340, 0x3706767-};6868-6969-int fc10_enable(void)7070-{7171- int i;7272- __u8 cardConfig = 0x00;7373- __u8 x;7474- TRACE_FUN(ft_t_flow);7575-7676-/* This code will only work if the FC-10 (or FC-20) is set to7777- * use DMA channels 1, 2, or 3. DMA channels 5 and 7 seem to be 7878- * initialized by the same command as channels 1 and 3, respectively.7979- */8080- if (ft_fdc_dma > 3) {8181- TRACE_ABORT(0, ft_t_err,8282-"Error: The FC-10/20 must be set to use DMA channels 1, 2, or 3!");8383- }8484-/* Only allow the FC-10/20 to use IRQ 3-7, or 9. Note that CMS's program8585- * only accepts IRQ's 2-7, but in linux, IRQ 2 is the same as IRQ 9.8686- */8787- if (ft_fdc_irq < 3 || ft_fdc_irq == 8 || ft_fdc_irq > 9) {8888- TRACE_ABORT(0, ft_t_err, 8989-"Error: The FC-10/20 must be set to use IRQ levels 3 - 7, or 9!\n"9090-KERN_INFO "Note: IRQ 9 is the same as IRQ 2");9191- }9292- /* Clear state machine ???9393- */9494- for (i = 0; i < NR_ITEMS(inbs_magic); i++) {9595- inb(ft_fdc_base + inbs_magic[i]);9696- }9797- outb(0x0, ft_fdc_base);9898-9999- x = inb(ft_fdc_base);100100- if (x == 0x13 || x == 0x93) {101101- for (i = 1; i < 8; i++) {102102- if (inb(ft_fdc_base + i) != x) {103103- TRACE_EXIT 0;104104- }105105- }106106- } else {107107- TRACE_EXIT 0;108108- }109109-110110- outb(0x8, ft_fdc_base);111111-112112- for (i = 0; i < 8; i++) {113113- if (inb(ft_fdc_base + i) != 0x0) {114114- TRACE_EXIT 0;115115- }116116- }117117- outb(0x10, ft_fdc_base);118118-119119- for (i = 0; i < 8; i++) {120120- if (inb(ft_fdc_base + i) != 0xff) {121121- TRACE_EXIT 0;122122- }123123- }124124-125125- /* Okay, we found a FC-10 card ! ???126126- */127127- outb(0x0, fdc.ccr);128128-129129- /* Clear state machine again ???130130- */131131- for (i = 0; i < NR_ITEMS(inbs_magic); i++) {132132- inb(ft_fdc_base + inbs_magic[i]);133133- }134134- /* Send io port */135135- for (i = 0; i < NR_ITEMS(fc10_ports); i++)136136- if (ft_fdc_base == fc10_ports[i])137137- cardConfig = i + 1;138138- if (cardConfig == 0) {139139- TRACE_EXIT 0; /* Invalid I/O Port */140140- }141141- /* and IRQ - If using IRQ 9, tell the FC card it is actually IRQ 2 */142142- if (ft_fdc_irq != 9)143143- cardConfig |= ft_fdc_irq << 3;144144- else145145- cardConfig |= 2 << 3;146146-147147- /* and finally DMA Channel */148148- cardConfig |= ft_fdc_dma << 6;149149- outb(cardConfig, ft_fdc_base); /* DMA [2 bits]/IRQ [3 bits]/BASE [3 bits] */150150-151151- /* Enable FC-10 ???152152- */153153- outb(0, fdc.ccr);154154- outb(0, fdc.dor2);155155- outb(FDC_DMA_MODE /* 8 */, fdc.dor);156156- outb(FDC_DMA_MODE /* 8 */, fdc.dor);157157- outb(1, fdc.dor2);158158-159159- /*************************************160160- *161161- * cH: why the hell should this be necessary? This is done 162162- * by fdc_reset()!!!163163- *164164- *************************************/165165- /* Initialize fdc, select drive B:166166- */167167- outb(FDC_DMA_MODE, fdc.dor); /* assert reset, dma & irq enabled */168168- /* 0x08 */169169- outb(FDC_DMA_MODE|FDC_RESET_NOT, fdc.dor); /* release reset */170170- /* 0x08 | 0x04 = 0x0c */171171- outb(FDC_DMA_MODE|FDC_RESET_NOT|FDC_MOTOR_1|FTAPE_SEL_B, fdc.dor);172172- /* 0x08 | 0x04 | 0x20 | 0x01 = 0x2d */ 173173- /* select drive 1 */ /* why not drive 0 ???? */174174- TRACE_EXIT (x == 0x93) ? 2 : 1;175175-}
-39
drivers/char/ftape/lowlevel/fc-10.h
···11-#ifndef _FC_10_H22-#define _FC_10_H33-44-/*55- * Copyright (C) 1994-1996 Bas Laarhoven.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.h,v $2323- * $Revision: 1.1 $2424- * $Date: 1997/09/19 09:05:22 $2525- *2626- * This file contains definitions for the FC-10 code2727- * of the QIC-40/80 floppy-tape driver for Linux.2828- */2929-3030-/*3131- * fc-10.c defined global vars.3232- */3333-3434-/*3535- * fc-10.c defined global functions.3636- */3737-extern int fc10_enable(void);3838-3939-#endif
-1349
drivers/char/ftape/lowlevel/fdc-io.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven,33- * (C) 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-io.c,v $2121- * $Revision: 1.7.4.2 $2222- * $Date: 1997/11/16 14:48:17 $2323- *2424- * This file contains the low-level floppy disk interface code2525- * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for2626- * Linux.2727- */2828-2929-#include <linux/errno.h>3030-#include <linux/sched.h>3131-#include <linux/ioport.h>3232-#include <linux/interrupt.h>3333-#include <linux/kernel.h>3434-#include <asm/system.h>3535-#include <asm/io.h>3636-#include <asm/dma.h>3737-#include <asm/irq.h>3838-3939-#include <linux/ftape.h>4040-#include <linux/qic117.h>4141-#include "../lowlevel/ftape-tracing.h"4242-#include "../lowlevel/fdc-io.h"4343-#include "../lowlevel/fdc-isr.h"4444-#include "../lowlevel/ftape-io.h"4545-#include "../lowlevel/ftape-rw.h"4646-#include "../lowlevel/ftape-ctl.h"4747-#include "../lowlevel/ftape-calibr.h"4848-#include "../lowlevel/fc-10.h"4949-5050-/* Global vars.5151- */5252-static int ftape_motor;5353-volatile int ftape_current_cylinder = -1;5454-volatile fdc_mode_enum fdc_mode = fdc_idle;5555-fdc_config_info fdc;5656-DECLARE_WAIT_QUEUE_HEAD(ftape_wait_intr);5757-5858-unsigned int ft_fdc_base = CONFIG_FT_FDC_BASE;5959-unsigned int ft_fdc_irq = CONFIG_FT_FDC_IRQ;6060-unsigned int ft_fdc_dma = CONFIG_FT_FDC_DMA;6161-unsigned int ft_fdc_threshold = CONFIG_FT_FDC_THR; /* bytes */6262-unsigned int ft_fdc_rate_limit = CONFIG_FT_FDC_MAX_RATE; /* bits/sec */6363-int ft_probe_fc10 = CONFIG_FT_PROBE_FC10;6464-int ft_mach2 = CONFIG_FT_MACH2;6565-6666-/* Local vars.6767- */6868-static spinlock_t fdc_io_lock; 6969-static unsigned int fdc_calibr_count;7070-static unsigned int fdc_calibr_time;7171-static int fdc_status;7272-volatile __u8 fdc_head; /* FDC head from sector id */7373-volatile __u8 fdc_cyl; /* FDC track from sector id */7474-volatile __u8 fdc_sect; /* FDC sector from sector id */7575-static int fdc_data_rate = 500; /* data rate (Kbps) */7676-static int fdc_rate_code; /* data rate code (0 == 500 Kbps) */7777-static int fdc_seek_rate = 2; /* step rate (msec) */7878-static void (*do_ftape) (void);7979-static int fdc_fifo_state; /* original fifo setting - fifo enabled */8080-static int fdc_fifo_thr; /* original fifo setting - threshold */8181-static int fdc_lock_state; /* original lock setting - locked */8282-static int fdc_fifo_locked; /* has fifo && lock set ? */8383-static __u8 fdc_precomp; /* default precomp. value (nsec) */8484-static __u8 fdc_prec_code; /* fdc precomp. select code */8585-8686-static char ftape_id[] = "ftape"; /* used by request irq and free irq */8787-8888-static int fdc_set_seek_rate(int seek_rate);8989-9090-void fdc_catch_stray_interrupts(int count)9191-{9292- unsigned long flags;9393-9494- spin_lock_irqsave(&fdc_io_lock, flags);9595- if (count == 0) {9696- ft_expected_stray_interrupts = 0;9797- } else {9898- ft_expected_stray_interrupts += count;9999- }100100- spin_unlock_irqrestore(&fdc_io_lock, flags);101101-}102102-103103-/* Wait during a timeout period for a given FDC status.104104- * If usecs == 0 then just test status, else wait at least for usecs.105105- * Returns -ETIME on timeout. Function must be calibrated first !106106- */107107-static int fdc_wait(unsigned int usecs, __u8 mask, __u8 state)108108-{109109- int count_1 = (fdc_calibr_count * usecs +110110- fdc_calibr_count - 1) / fdc_calibr_time;111111-112112- do {113113- fdc_status = inb_p(fdc.msr);114114- if ((fdc_status & mask) == state) {115115- return 0;116116- }117117- } while (count_1-- >= 0);118118- return -ETIME;119119-}120120-121121-int fdc_ready_wait(unsigned int usecs)122122-{123123- return fdc_wait(usecs, FDC_DATA_READY | FDC_BUSY, FDC_DATA_READY);124124-}125125-126126-/* Why can't we just use udelay()?127127- */128128-static void fdc_usec_wait(unsigned int usecs)129129-{130130- fdc_wait(usecs, 0, 1); /* will always timeout ! */131131-}132132-133133-static int fdc_ready_out_wait(unsigned int usecs)134134-{135135- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */136136- return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);137137-}138138-139139-void fdc_wait_calibrate(void)140140-{141141- ftape_calibrate("fdc_wait",142142- fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time); 143143-}144144-145145-/* Wait for a (short) while for the FDC to become ready146146- * and transfer the next command byte.147147- * Return -ETIME on timeout on getting ready (depends on hardware!).148148- */149149-static int fdc_write(const __u8 data)150150-{151151- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */152152- if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) {153153- return -ETIME;154154- } else {155155- outb(data, fdc.fifo);156156- return 0;157157- }158158-}159159-160160-/* Wait for a (short) while for the FDC to become ready161161- * and transfer the next result byte.162162- * Return -ETIME if timeout on getting ready (depends on hardware!).163163- */164164-static int fdc_read(__u8 * data)165165-{166166- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */167167- if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) {168168- return -ETIME;169169- } else {170170- *data = inb(fdc.fifo);171171- return 0;172172- }173173-}174174-175175-/* Output a cmd_len long command string to the FDC.176176- * The FDC should be ready to receive a new command or177177- * an error (EBUSY or ETIME) will occur.178178- */179179-int fdc_command(const __u8 * cmd_data, int cmd_len)180180-{181181- int result = 0;182182- unsigned long flags;183183- int count = cmd_len;184184- int retry = 0;185185-#ifdef TESTING186186- static unsigned int last_time;187187- unsigned int time;188188-#endif189189- TRACE_FUN(ft_t_any);190190-191191- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */192192- spin_lock_irqsave(&fdc_io_lock, flags);193193- if (!in_interrupt())194194- /* Yes, I know, too much comments inside this function195195- * ...196196- * 197197- * Yet another bug in the original driver. All that198198- * havoc is caused by the fact that the isr() sends199199- * itself a command to the floppy tape driver (pause,200200- * micro step pause). Now, the problem is that201201- * commands are transmitted via the fdc_seek202202- * command. But: the fdc performs seeks in the203203- * background i.e. it doesn't signal busy while204204- * sending the step pulses to the drive. Therefore the205205- * non-interrupt level driver has no chance to tell206206- * whether the isr() just has issued a seek. Therefore207207- * we HAVE TO have a look at the ft_hide_interrupt208208- * flag: it signals the non-interrupt level part of209209- * the driver that it has to wait for the fdc until it210210- * has completet seeking.211211- *212212- * THIS WAS PRESUMABLY THE REASON FOR ALL THAT213213- * "fdc_read timeout" errors, I HOPE :-)214214- */215215- if (ft_hide_interrupt) {216216- restore_flags(flags);217217- TRACE(ft_t_info,218218- "Waiting for the isr() completing fdc_seek()");219219- if (fdc_interrupt_wait(2 * FT_SECOND) < 0) {220220- TRACE(ft_t_warn,221221- "Warning: timeout waiting for isr() seek to complete");222222- }223223- if (ft_hide_interrupt || !ft_seek_completed) {224224- /* There cannot be another225225- * interrupt. The isr() only stops226226- * the tape and the next interrupt227227- * won't come until we have send our228228- * command to the drive.229229- */230230- TRACE_ABORT(-EIO, ft_t_bug,231231- "BUG? isr() is still seeking?\n"232232- KERN_INFO "hide: %d\n"233233- KERN_INFO "seek: %d",234234- ft_hide_interrupt,235235- ft_seek_completed);236236-237237- }238238- fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */239239- spin_lock_irqsave(&fdc_io_lock, flags);240240- }241241- fdc_status = inb(fdc.msr);242242- if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {243243- spin_unlock_irqrestore(&fdc_io_lock, flags);244244- TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");245245- } 246246- fdc_mode = *cmd_data; /* used by isr */247247-#ifdef TESTING248248- if (fdc_mode == FDC_SEEK) {249249- time = ftape_timediff(last_time, ftape_timestamp());250250- if (time < 6000) {251251- TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d",252252- time);253253- }254254- }255255-#endif256256- if (!in_interrupt()) {257257- /* shouldn't be cleared if called from isr258258- */259259- ft_interrupt_seen = 0;260260- }261261- while (count) {262262- result = fdc_write(*cmd_data);263263- if (result < 0) {264264- TRACE(ft_t_fdc_dma,265265- "fdc_mode = %02x, status = %02x at index %d",266266- (int) fdc_mode, (int) fdc_status,267267- cmd_len - count);268268- if (++retry <= 3) {269269- TRACE(ft_t_warn, "fdc_write timeout, retry");270270- } else {271271- TRACE(ft_t_err, "fdc_write timeout, fatal");272272- /* recover ??? */273273- break;274274- }275275- } else {276276- --count;277277- ++cmd_data;278278- }279279- }280280-#ifdef TESTING281281- if (fdc_mode == FDC_SEEK) {282282- last_time = ftape_timestamp();283283- }284284-#endif285285- spin_unlock_irqrestore(&fdc_io_lock, flags);286286- TRACE_EXIT result;287287-}288288-289289-/* Input a res_len long result string from the FDC.290290- * The FDC should be ready to send the result or an error291291- * (EBUSY or ETIME) will occur.292292- */293293-int fdc_result(__u8 * res_data, int res_len)294294-{295295- int result = 0;296296- unsigned long flags;297297- int count = res_len;298298- int retry = 0;299299- TRACE_FUN(ft_t_any);300300-301301- spin_lock_irqsave(&fdc_io_lock, flags);302302- fdc_status = inb(fdc.msr);303303- if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {304304- TRACE(ft_t_err, "fdc not ready");305305- result = -EBUSY;306306- } else while (count) {307307- if (!(fdc_status & FDC_BUSY)) {308308- spin_unlock_irqrestore(&fdc_io_lock, flags);309309- TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");310310- }311311- result = fdc_read(res_data);312312- if (result < 0) {313313- TRACE(ft_t_fdc_dma,314314- "fdc_mode = %02x, status = %02x at index %d",315315- (int) fdc_mode,316316- (int) fdc_status,317317- res_len - count);318318- if (++retry <= 3) {319319- TRACE(ft_t_warn, "fdc_read timeout, retry");320320- } else {321321- TRACE(ft_t_err, "fdc_read timeout, fatal");322322- /* recover ??? */323323- break;324324- ++retry;325325- }326326- } else {327327- --count;328328- ++res_data;329329- }330330- }331331- spin_unlock_irqrestore(&fdc_io_lock, flags);332332- fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */333333- TRACE_EXIT result;334334-}335335-336336-/* Handle command and result phases for337337- * commands without data phase.338338- */339339-static int fdc_issue_command(const __u8 * out_data, int out_count,340340- __u8 * in_data, int in_count)341341-{342342- TRACE_FUN(ft_t_any);343343-344344- if (out_count > 0) {345345- TRACE_CATCH(fdc_command(out_data, out_count),);346346- }347347- /* will take 24 - 30 usec for fdc_sense_drive_status and348348- * fdc_sense_interrupt_status commands.349349- * 35 fails sometimes (5/9/93 SJL)350350- * On a loaded system it incidentally takes longer than351351- * this for the fdc to get ready ! ?????? WHY ??????352352- * So until we know what's going on use a very long timeout.353353- */354354- TRACE_CATCH(fdc_ready_out_wait(500 /* usec */),);355355- if (in_count > 0) {356356- TRACE_CATCH(fdc_result(in_data, in_count),357357- TRACE(ft_t_err, "result phase aborted"));358358- }359359- TRACE_EXIT 0;360360-}361361-362362-/* Wait for FDC interrupt with timeout (in milliseconds).363363- * Signals are blocked so the wait will not be aborted.364364- * Note: interrupts must be enabled ! (23/05/93 SJL)365365- */366366-int fdc_interrupt_wait(unsigned int time)367367-{368368- DECLARE_WAITQUEUE(wait,current);369369- sigset_t old_sigmask; 370370- static int resetting;371371- long timeout;372372-373373- TRACE_FUN(ft_t_fdc_dma);374374-375375- if (waitqueue_active(&ftape_wait_intr)) {376376- TRACE_ABORT(-EIO, ft_t_err, "error: nested call");377377- }378378- /* timeout time will be up to USPT microseconds too long ! */379379- timeout = (1000 * time + FT_USPT - 1) / FT_USPT;380380-381381- spin_lock_irq(¤t->sighand->siglock);382382- old_sigmask = current->blocked;383383- sigfillset(¤t->blocked);384384- recalc_sigpending();385385- spin_unlock_irq(¤t->sighand->siglock);386386-387387- set_current_state(TASK_INTERRUPTIBLE);388388- add_wait_queue(&ftape_wait_intr, &wait);389389- while (!ft_interrupt_seen && timeout)390390- timeout = schedule_timeout_interruptible(timeout);391391-392392- spin_lock_irq(¤t->sighand->siglock);393393- current->blocked = old_sigmask;394394- recalc_sigpending();395395- spin_unlock_irq(¤t->sighand->siglock);396396-397397- remove_wait_queue(&ftape_wait_intr, &wait);398398- /* the following IS necessary. True: as well399399- * wake_up_interruptible() as the schedule() set TASK_RUNNING400400- * when they wakeup a task, BUT: it may very well be that401401- * ft_interrupt_seen is already set to 1 when we enter here402402- * in which case schedule() gets never called, and403403- * TASK_RUNNING never set. This has the funny effect that we404404- * execute all the code until we leave kernel space, but then405405- * the task is stopped (a task CANNOT be preempted while in406406- * kernel mode. Sending a pair of SIGSTOP/SIGCONT to the407407- * tasks wakes it up again. Funny! :-)408408- */409409- current->state = TASK_RUNNING; 410410- if (ft_interrupt_seen) { /* woken up by interrupt */411411- ft_interrupt_seen = 0;412412- TRACE_EXIT 0;413413- }414414- /* Original comment:415415- * In first instance, next statement seems unnecessary since416416- * it will be cleared in fdc_command. However, a small part of417417- * the software seems to rely on this being cleared here418418- * (ftape_close might fail) so stick to it until things get fixed !419419- */420420- /* My deeply sought of knowledge:421421- * Behold NO! It is obvious. fdc_reset() doesn't call fdc_command()422422- * but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to423423- * be reset here.424424- */425425- ft_interrupt_seen = 0; /* clear for next call */426426- if (!resetting) {427427- resetting = 1; /* break infinite recursion if reset fails */428428- TRACE(ft_t_any, "cleanup reset");429429- fdc_reset();430430- resetting = 0;431431- }432432- TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;433433-}434434-435435-/* Start/stop drive motor. Enable DMA mode.436436- */437437-void fdc_motor(int motor)438438-{439439- int unit = ft_drive_sel;440440- int data = unit | FDC_RESET_NOT | FDC_DMA_MODE;441441- TRACE_FUN(ft_t_any);442442-443443- ftape_motor = motor;444444- if (ftape_motor) {445445- data |= FDC_MOTOR_0 << unit;446446- TRACE(ft_t_noise, "turning motor %d on", unit);447447- } else {448448- TRACE(ft_t_noise, "turning motor %d off", unit);449449- }450450- if (ft_mach2) {451451- outb_p(data, fdc.dor2);452452- } else {453453- outb_p(data, fdc.dor);454454- }455455- ftape_sleep(10 * FT_MILLISECOND);456456- TRACE_EXIT;457457-}458458-459459-static void fdc_update_dsr(void)460460-{461461- TRACE_FUN(ft_t_any);462462-463463- TRACE(ft_t_flow, "rate = %d Kbps, precomp = %d ns",464464- fdc_data_rate, fdc_precomp);465465- if (fdc.type >= i82077) {466466- outb_p((fdc_rate_code & 0x03) | fdc_prec_code, fdc.dsr);467467- } else {468468- outb_p(fdc_rate_code & 0x03, fdc.ccr);469469- }470470- TRACE_EXIT;471471-}472472-473473-void fdc_set_write_precomp(int precomp)474474-{475475- TRACE_FUN(ft_t_any);476476-477477- TRACE(ft_t_noise, "New precomp: %d nsec", precomp);478478- fdc_precomp = precomp;479479- /* write precompensation can be set in multiples of 41.67 nsec.480480- * round the parameter to the nearest multiple and convert it481481- * into a fdc setting. Note that 0 means default to the fdc,482482- * 7 is used instead of that.483483- */484484- fdc_prec_code = ((fdc_precomp + 21) / 42) << 2;485485- if (fdc_prec_code == 0 || fdc_prec_code > (6 << 2)) {486486- fdc_prec_code = 7 << 2;487487- }488488- fdc_update_dsr();489489- TRACE_EXIT;490490-}491491-492492-/* Reprogram the 82078 registers to use Data Rate Table 1 on all drives.493493- */494494-static void fdc_set_drive_specs(void)495495-{496496- __u8 cmd[] = { FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};497497- int result;498498- TRACE_FUN(ft_t_any);499499-500500- TRACE(ft_t_flow, "Setting of drive specs called");501501- if (fdc.type >= i82078_1) {502502- cmd[1] = (0 << 5) | (2 << 2);503503- cmd[2] = (1 << 5) | (2 << 2);504504- cmd[3] = (2 << 5) | (2 << 2);505505- cmd[4] = (3 << 5) | (2 << 2);506506- result = fdc_command(cmd, NR_ITEMS(cmd));507507- if (result < 0) {508508- TRACE(ft_t_err, "Setting of drive specs failed");509509- }510510- }511511- TRACE_EXIT;512512-}513513-514514-/* Select clock for fdc, must correspond with tape drive setting !515515- * This also influences the fdc timing so we must adjust some values.516516- */517517-int fdc_set_data_rate(int rate)518518-{519519- int bad_rate = 0;520520- TRACE_FUN(ft_t_any);521521-522522- /* Select clock for fdc, must correspond with tape drive setting !523523- * This also influences the fdc timing so we must adjust some values.524524- */525525- TRACE(ft_t_fdc_dma, "new rate = %d", rate);526526- switch (rate) {527527- case 250:528528- fdc_rate_code = fdc_data_rate_250;529529- break;530530- case 500:531531- fdc_rate_code = fdc_data_rate_500;532532- break;533533- case 1000:534534- if (fdc.type < i82077) {535535- bad_rate = 1;536536- } else {537537- fdc_rate_code = fdc_data_rate_1000;538538- }539539- break;540540- case 2000:541541- if (fdc.type < i82078_1) {542542- bad_rate = 1;543543- } else {544544- fdc_rate_code = fdc_data_rate_2000;545545- }546546- break;547547- default:548548- bad_rate = 1;549549- }550550- if (bad_rate) {551551- TRACE_ABORT(-EIO,552552- ft_t_fdc_dma, "%d is not a valid data rate", rate);553553- }554554- fdc_data_rate = rate;555555- fdc_update_dsr();556556- fdc_set_seek_rate(fdc_seek_rate); /* clock changed! */557557- ftape_udelay(1000);558558- TRACE_EXIT 0;559559-}560560-561561-/* keep the unit select if keep_select is != 0,562562- */563563-static void fdc_dor_reset(int keep_select)564564-{565565- __u8 fdc_ctl = ft_drive_sel;566566-567567- if (keep_select != 0) {568568- fdc_ctl |= FDC_DMA_MODE;569569- if (ftape_motor) {570570- fdc_ctl |= FDC_MOTOR_0 << ft_drive_sel;571571- }572572- }573573- ftape_udelay(10); /* ??? but seems to be necessary */574574- if (ft_mach2) {575575- outb_p(fdc_ctl & 0x0f, fdc.dor);576576- outb_p(fdc_ctl, fdc.dor2);577577- } else {578578- outb_p(fdc_ctl, fdc.dor);579579- }580580- fdc_usec_wait(10); /* delay >= 14 fdc clocks */581581- if (keep_select == 0) {582582- fdc_ctl = 0;583583- }584584- fdc_ctl |= FDC_RESET_NOT;585585- if (ft_mach2) {586586- outb_p(fdc_ctl & 0x0f, fdc.dor);587587- outb_p(fdc_ctl, fdc.dor2);588588- } else {589589- outb_p(fdc_ctl, fdc.dor);590590- }591591-}592592-593593-/* Reset the floppy disk controller. Leave the ftape_unit selected.594594- */595595-void fdc_reset(void)596596-{597597- int st0;598598- int i;599599- int dummy;600600- unsigned long flags;601601- TRACE_FUN(ft_t_any);602602-603603- spin_lock_irqsave(&fdc_io_lock, flags);604604-605605- fdc_dor_reset(1); /* keep unit selected */606606-607607- fdc_mode = fdc_idle;608608-609609- /* maybe the spin_lock_irq* pair is not necessary, BUT:610610- * the following line MUST be here. Otherwise fdc_interrupt_wait()611611- * won't wait. Note that fdc_reset() is called from 612612- * ftape_dumb_stop() when the fdc is busy transferring data. In this613613- * case fdc_isr() MOST PROBABLY sets ft_interrupt_seen, and tries614614- * to get the result bytes from the fdc etc. CLASH.615615- */616616- ft_interrupt_seen = 0;617617-618618- /* Program data rate619619- */620620- fdc_update_dsr(); /* restore data rate and precomp */621621-622622- spin_unlock_irqrestore(&fdc_io_lock, flags);623623-624624- /*625625- * Wait for first polling cycle to complete626626- */627627- if (fdc_interrupt_wait(1 * FT_SECOND) < 0) {628628- TRACE(ft_t_err, "no drive polling interrupt!");629629- } else { /* clear all disk-changed statuses */630630- for (i = 0; i < 4; ++i) {631631- if(fdc_sense_interrupt_status(&st0, &dummy) != 0) {632632- TRACE(ft_t_err, "sense failed for %d", i);633633- }634634- if (i == ft_drive_sel) {635635- ftape_current_cylinder = dummy;636636- }637637- }638638- TRACE(ft_t_noise, "drive polling completed");639639- }640640- /*641641- * SPECIFY COMMAND642642- */643643- fdc_set_seek_rate(fdc_seek_rate);644644- /*645645- * DRIVE SPECIFICATION COMMAND (if fdc type known)646646- */647647- if (fdc.type >= i82078_1) {648648- fdc_set_drive_specs();649649- }650650- TRACE_EXIT;651651-}652652-653653-#if !defined(CLK_48MHZ)654654-# define CLK_48MHZ 1655655-#endif656656-657657-/* When we're done, put the fdc into reset mode so that the regular658658- * floppy disk driver will figure out that something is wrong and659659- * initialize the controller the way it wants.660660- */661661-void fdc_disable(void)662662-{663663- __u8 cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00};664664- __u8 cmd2[] = {FDC_LOCK};665665- __u8 cmd3[] = {FDC_UNLOCK};666666- __u8 stat[1];667667- TRACE_FUN(ft_t_flow);668668-669669- if (!fdc_fifo_locked) {670670- fdc_reset();671671- TRACE_EXIT;672672- }673673- if (fdc_issue_command(cmd3, 1, stat, 1) < 0 || stat[0] != 0x00) {674674- fdc_dor_reset(0);675675- TRACE_ABORT(/**/, ft_t_bug, 676676- "couldn't unlock fifo, configuration remains changed");677677- }678678- fdc_fifo_locked = 0;679679- if (CLK_48MHZ && fdc.type >= i82078) {680680- cmd1[0] |= FDC_CLK48_BIT;681681- }682682- cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1);683683- if (fdc_command(cmd1, NR_ITEMS(cmd1)) < 0) {684684- fdc_dor_reset(0);685685- TRACE_ABORT(/**/, ft_t_bug,686686- "couldn't reconfigure fifo to old state");687687- }688688- if (fdc_lock_state &&689689- fdc_issue_command(cmd2, 1, stat, 1) < 0) {690690- fdc_dor_reset(0);691691- TRACE_ABORT(/**/, ft_t_bug, "couldn't lock old state again");692692- }693693- TRACE(ft_t_noise, "fifo restored: %sabled, thr. %d, %slocked",694694- fdc_fifo_state ? "en" : "dis",695695- fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");696696- fdc_dor_reset(0);697697- TRACE_EXIT;698698-}699699-700700-/* Specify FDC seek-rate (milliseconds)701701- */702702-static int fdc_set_seek_rate(int seek_rate)703703-{704704- /* set step rate, dma mode, and minimal head load and unload times705705- */706706- __u8 in[3] = { FDC_SPECIFY, 1, (1 << 1)};707707-708708- fdc_seek_rate = seek_rate;709709- in[1] |= (16 - (fdc_data_rate * fdc_seek_rate) / 500) << 4;710710-711711- return fdc_command(in, 3);712712-}713713-714714-/* Sense drive status: get unit's drive status (ST3)715715- */716716-int fdc_sense_drive_status(int *st3)717717-{718718- __u8 out[2];719719- __u8 in[1];720720- TRACE_FUN(ft_t_any);721721-722722- out[0] = FDC_SENSED;723723- out[1] = ft_drive_sel;724724- TRACE_CATCH(fdc_issue_command(out, 2, in, 1),);725725- *st3 = in[0];726726- TRACE_EXIT 0;727727-}728728-729729-/* Sense Interrupt Status command:730730- * should be issued at the end of each seek.731731- * get ST0 and current cylinder.732732- */733733-int fdc_sense_interrupt_status(int *st0, int *current_cylinder)734734-{735735- __u8 out[1];736736- __u8 in[2];737737- TRACE_FUN(ft_t_any);738738-739739- out[0] = FDC_SENSEI;740740- TRACE_CATCH(fdc_issue_command(out, 1, in, 2),);741741- *st0 = in[0];742742- *current_cylinder = in[1];743743- TRACE_EXIT 0;744744-}745745-746746-/* step to track747747- */748748-int fdc_seek(int track)749749-{750750- __u8 out[3];751751- int st0, pcn;752752-#ifdef TESTING753753- unsigned int time;754754-#endif755755- TRACE_FUN(ft_t_any);756756-757757- out[0] = FDC_SEEK;758758- out[1] = ft_drive_sel;759759- out[2] = track;760760-#ifdef TESTING761761- time = ftape_timestamp();762762-#endif763763- /* We really need this command to work !764764- */765765- ft_seek_completed = 0;766766- TRACE_CATCH(fdc_command(out, 3),767767- fdc_reset();768768- TRACE(ft_t_noise, "destination was: %d, resetting FDC...",769769- track));770770- /* Handle interrupts until ft_seek_completed or timeout.771771- */772772- for (;;) {773773- TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),);774774- if (ft_seek_completed) {775775- TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),);776776- if ((st0 & ST0_SEEK_END) == 0) {777777- TRACE_ABORT(-EIO, ft_t_err,778778- "no seek-end after seek completion !??");779779- }780780- break;781781- }782782- }783783-#ifdef TESTING784784- time = ftape_timediff(time, ftape_timestamp()) / abs(track - ftape_current_cylinder);785785- if ((time < 900 || time > 3100) && abs(track - ftape_current_cylinder) > 5) {786786- TRACE(ft_t_warn, "Wrong FDC STEP interval: %d usecs (%d)",787787- time, track - ftape_current_cylinder);788788- }789789-#endif790790- /* Verify whether we issued the right tape command.791791- */792792- /* Verify that we seek to the proper track. */793793- if (pcn != track) {794794- TRACE_ABORT(-EIO, ft_t_err, "bad seek..");795795- }796796- ftape_current_cylinder = track;797797- TRACE_EXIT 0;798798-}799799-800800-static int perpend_mode; /* set if fdc is in perpendicular mode */801801-802802-static int perpend_off(void)803803-{804804- __u8 perpend[] = {FDC_PERPEND, 0x00};805805- TRACE_FUN(ft_t_any);806806-807807- if (perpend_mode) {808808- /* Turn off perpendicular mode */809809- perpend[1] = 0x80;810810- TRACE_CATCH(fdc_command(perpend, 2),811811- TRACE(ft_t_err,"Perpendicular mode exit failed!"));812812- perpend_mode = 0;813813- }814814- TRACE_EXIT 0;815815-}816816-817817-static int handle_perpend(int segment_id)818818-{819819- __u8 perpend[] = {FDC_PERPEND, 0x00};820820- TRACE_FUN(ft_t_any);821821-822822- /* When writing QIC-3020 tapes, turn on perpendicular mode823823- * if tape is moving in forward direction (even tracks).824824- */825825- if (ft_qic_std == QIC_TAPE_QIC3020 &&826826- ((segment_id / ft_segments_per_track) & 1) == 0) {827827-/* FIXME: some i82077 seem to support perpendicular mode as828828- * well. 829829- */830830-#if 0831831- if (fdc.type < i82077AA) {}832832-#else833833- if (fdc.type < i82077 && ft_data_rate < 1000) {834834-#endif835835- /* fdc does not support perpendicular mode: complain 836836- */837837- TRACE_ABORT(-EIO, ft_t_err,838838- "Your FDC does not support QIC-3020.");839839- }840840- perpend[1] = 0x03 /* 0x83 + (0x4 << ft_drive_sel) */ ;841841- TRACE_CATCH(fdc_command(perpend, 2),842842- TRACE(ft_t_err,"Perpendicular mode entry failed!"));843843- TRACE(ft_t_flow, "Perpendicular mode set");844844- perpend_mode = 1;845845- TRACE_EXIT 0;846846- }847847- TRACE_EXIT perpend_off();848848-}849849-850850-static inline void fdc_setup_dma(char mode,851851- volatile void *addr, unsigned int count)852852-{853853- /* Program the DMA controller.854854- */855855- disable_dma(fdc.dma);856856- clear_dma_ff(fdc.dma);857857- set_dma_mode(fdc.dma, mode);858858- set_dma_addr(fdc.dma, virt_to_bus((void*)addr));859859- set_dma_count(fdc.dma, count);860860- enable_dma(fdc.dma);861861-}862862-863863-/* Setup fdc and dma for formatting the next segment864864- */865865-int fdc_setup_formatting(buffer_struct * buff)866866-{867867- unsigned long flags;868868- __u8 out[6] = {869869- FDC_FORMAT, 0x00, 3, 4 * FT_SECTORS_PER_SEGMENT, 0x00, 0x6b870870- };871871- TRACE_FUN(ft_t_any);872872-873873- TRACE_CATCH(handle_perpend(buff->segment_id),);874874- /* Program the DMA controller.875875- */876876- TRACE(ft_t_fdc_dma,877877- "phys. addr. = %lx", virt_to_bus((void*) buff->ptr));878878- spin_lock_irqsave(&fdc_io_lock, flags);879879- fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4);880880- /* Issue FDC command to start reading/writing.881881- */882882- out[1] = ft_drive_sel;883883- out[4] = buff->gap3;884884- TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)),885885- restore_flags(flags); fdc_mode = fdc_idle);886886- spin_unlock_irqrestore(&fdc_io_lock, flags);887887- TRACE_EXIT 0;888888-}889889-890890-891891-/* Setup Floppy Disk Controller and DMA to read or write the next cluster892892- * of good sectors from or to the current segment.893893- */894894-int fdc_setup_read_write(buffer_struct * buff, __u8 operation)895895-{896896- unsigned long flags;897897- __u8 out[9];898898- int dma_mode;899899- TRACE_FUN(ft_t_any);900900-901901- switch(operation) {902902- case FDC_VERIFY:903903- if (fdc.type < i82077) {904904- operation = FDC_READ;905905- }906906- case FDC_READ:907907- case FDC_READ_DELETED:908908- dma_mode = DMA_MODE_READ;909909- TRACE(ft_t_fdc_dma, "xfer %d sectors to 0x%p",910910- buff->sector_count, buff->ptr);911911- TRACE_CATCH(perpend_off(),);912912- break;913913- case FDC_WRITE_DELETED:914914- TRACE(ft_t_noise, "deleting segment %d", buff->segment_id);915915- case FDC_WRITE:916916- dma_mode = DMA_MODE_WRITE;917917- /* When writing QIC-3020 tapes, turn on perpendicular mode918918- * if tape is moving in forward direction (even tracks).919919- */920920- TRACE_CATCH(handle_perpend(buff->segment_id),);921921- TRACE(ft_t_fdc_dma, "xfer %d sectors from 0x%p",922922- buff->sector_count, buff->ptr);923923- break;924924- default:925925- TRACE_ABORT(-EIO,926926- ft_t_bug, "bug: invalid operation parameter");927927- }928928- TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr));929929- spin_lock_irqsave(&fdc_io_lock, flags);930930- if (operation != FDC_VERIFY) {931931- fdc_setup_dma(dma_mode, buff->ptr,932932- FT_SECTOR_SIZE * buff->sector_count);933933- }934934- /* Issue FDC command to start reading/writing.935935- */936936- out[0] = operation;937937- out[1] = ft_drive_sel;938938- out[2] = buff->cyl;939939- out[3] = buff->head;940940- out[4] = buff->sect + buff->sector_offset;941941- out[5] = 3; /* Sector size of 1K. */942942- out[6] = out[4] + buff->sector_count - 1; /* last sector */943943- out[7] = 109; /* Gap length. */944944- out[8] = 0xff; /* No limit to transfer size. */945945- TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",946946- out[2], out[3], out[4], out[6] - out[4] + 1);947947- spin_unlock_irqrestore(&fdc_io_lock, flags);948948- TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle);949949- TRACE_EXIT 0;950950-}951951-952952-int fdc_fifo_threshold(__u8 threshold,953953- int *fifo_state, int *lock_state, int *fifo_thr)954954-{955955- const __u8 cmd0[] = {FDC_DUMPREGS};956956- __u8 cmd1[] = {FDC_CONFIGURE, 0, (0x0f & (threshold - 1)), 0};957957- const __u8 cmd2[] = {FDC_LOCK};958958- const __u8 cmd3[] = {FDC_UNLOCK};959959- __u8 reg[10];960960- __u8 stat;961961- int i;962962- int result;963963- TRACE_FUN(ft_t_any);964964-965965- if (CLK_48MHZ && fdc.type >= i82078) {966966- cmd1[0] |= FDC_CLK48_BIT;967967- }968968- /* Dump fdc internal registers for examination969969- */970970- TRACE_CATCH(fdc_command(cmd0, NR_ITEMS(cmd0)),971971- TRACE(ft_t_warn, "dumpreg cmd failed, fifo unchanged"));972972- /* Now read fdc internal registers from fifo973973- */974974- for (i = 0; i < (int)NR_ITEMS(reg); ++i) {975975- fdc_read(®[i]);976976- TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]);977977- }978978- if (fifo_state && lock_state && fifo_thr) {979979- *fifo_state = (reg[8] & 0x20) == 0;980980- *lock_state = reg[7] & 0x80;981981- *fifo_thr = 1 + (reg[8] & 0x0f);982982- }983983- TRACE(ft_t_noise,984984- "original fifo state: %sabled, threshold %d, %slocked",985985- ((reg[8] & 0x20) == 0) ? "en" : "dis",986986- 1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not ");987987- /* If fdc is already locked, unlock it first ! */988988- if (reg[7] & 0x80) {989989- fdc_ready_wait(100);990990- TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1),991991- TRACE(ft_t_bug, "FDC unlock command failed, "992992- "configuration unchanged"));993993- }994994- fdc_fifo_locked = 0;995995- /* Enable fifo and set threshold at xx bytes to allow a996996- * reasonably large latency and reduce number of dma bursts.997997- */998998- fdc_ready_wait(100);999999- if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) {10001000- TRACE(ft_t_bug, "configure cmd failed, fifo unchanged");10011001- }10021002- /* Now lock configuration so reset will not change it10031003- */10041004- if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 ||10051005- stat != 0x10) {10061006- TRACE_ABORT(-EIO, ft_t_bug,10071007- "FDC lock command failed, stat = 0x%02x", stat);10081008- }10091009- fdc_fifo_locked = 1;10101010- TRACE_EXIT result;10111011-}10121012-10131013-static int fdc_fifo_enable(void)10141014-{10151015- TRACE_FUN(ft_t_any);10161016-10171017- if (fdc_fifo_locked) {10181018- TRACE_ABORT(0, ft_t_warn, "Fifo not enabled because locked");10191019- }10201020- TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,10211021- &fdc_fifo_state,10221022- &fdc_lock_state,10231023- &fdc_fifo_thr),);10241024- TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,10251025- NULL, NULL, NULL),);10261026- TRACE_EXIT 0;10271027-}10281028-10291029-/* Determine fd controller type 10301030- */10311031-static __u8 fdc_save_state[2];10321032-10331033-static int fdc_probe(void)10341034-{10351035- __u8 cmd[1];10361036- __u8 stat[16]; /* must be able to hold dumpregs & save results */10371037- int i;10381038- TRACE_FUN(ft_t_any);10391039-10401040- /* Try to find out what kind of fd controller we have to deal with10411041- * Scheme borrowed from floppy driver:10421042- * first try if FDC_DUMPREGS command works10431043- * (this indicates that we have a 82072 or better)10441044- * then try the FDC_VERSION command (82072 doesn't support this)10451045- * then try the FDC_UNLOCK command (some older 82077's don't support this)10461046- * then try the FDC_PARTID command (82078's support this)10471047- */10481048- cmd[0] = FDC_DUMPREGS;10491049- if (fdc_issue_command(cmd, 1, stat, 1) != 0) {10501050- TRACE_ABORT(no_fdc, ft_t_bug, "No FDC found");10511051- }10521052- if (stat[0] == 0x80) {10531053- /* invalid command: must be pre 82072 */10541054- TRACE_ABORT(i8272,10551055- ft_t_warn, "Type 8272A/765A compatible FDC found");10561056- }10571057- fdc_result(&stat[1], 9);10581058- fdc_save_state[0] = stat[7];10591059- fdc_save_state[1] = stat[8];10601060- cmd[0] = FDC_VERSION;10611061- if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {10621062- TRACE_ABORT(i8272, ft_t_warn, "Type 82072 FDC found");10631063- }10641064- if (*stat != 0x90) {10651065- TRACE_ABORT(i8272, ft_t_warn, "Unknown FDC found");10661066- }10671067- cmd[0] = FDC_UNLOCK;10681068- if(fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] != 0x00) {10691069- TRACE_ABORT(i8272, ft_t_warn,10701070- "Type pre-1991 82077 FDC found, "10711071- "treating it like a 82072");10721072- }10731073- if (fdc_save_state[0] & 0x80) { /* was locked */10741074- cmd[0] = FDC_LOCK; /* restore lock */10751075- (void)fdc_issue_command(cmd, 1, stat, 1);10761076- TRACE(ft_t_warn, "FDC is already locked");10771077- }10781078- /* Test for a i82078 FDC */10791079- cmd[0] = FDC_PARTID;10801080- if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {10811081- /* invalid command: not a i82078xx type FDC */10821082- for (i = 0; i < 4; ++i) {10831083- outb_p(i, fdc.tdr);10841084- if ((inb_p(fdc.tdr) & 0x03) != i) {10851085- TRACE_ABORT(i82077,10861086- ft_t_warn, "Type 82077 FDC found");10871087- }10881088- }10891089- TRACE_ABORT(i82077AA, ft_t_warn, "Type 82077AA FDC found");10901090- }10911091- /* FDC_PARTID cmd succeeded */10921092- switch (stat[0] >> 5) {10931093- case 0x0:10941094- /* i82078SL or i82078-1. The SL part cannot run at10951095- * 2Mbps (the SL and -1 dies are identical; they are10961096- * speed graded after production, according to Intel).10971097- * Some SL's can be detected by doing a SAVE cmd and10981098- * look at bit 7 of the first byte (the SEL3V# bit).10991099- * If it is 0, the part runs off 3Volts, and hence it11001100- * is a SL.11011101- */11021102- cmd[0] = FDC_SAVE;11031103- if(fdc_issue_command(cmd, 1, stat, 16) < 0) {11041104- TRACE(ft_t_err, "FDC_SAVE failed. Dunno why");11051105- /* guess we better claim the fdc to be a i82078 */11061106- TRACE_ABORT(i82078,11071107- ft_t_warn,11081108- "Type i82078 FDC (i suppose) found");11091109- }11101110- if ((stat[0] & FDC_SEL3V_BIT)) {11111111- /* fdc running off 5Volts; Pray that it's a i82078-111121112- */11131113- TRACE_ABORT(i82078_1, ft_t_warn,11141114- "Type i82078-1 or 5Volt i82078SL FDC found");11151115- }11161116- TRACE_ABORT(i82078, ft_t_warn,11171117- "Type 3Volt i82078SL FDC (1Mbps) found");11181118- case 0x1:11191119- case 0x2: /* S82078B */11201120- /* The '78B isn't '78 compatible. Detect it as a '77AA */11211121- TRACE_ABORT(i82077AA, ft_t_warn, "Type i82077AA FDC found");11221122- case 0x3: /* NSC PC8744 core; used in several super-IO chips */11231123- TRACE_ABORT(i82077AA,11241124- ft_t_warn, "Type 82077AA compatible FDC found");11251125- default:11261126- TRACE(ft_t_warn, "A previously undetected FDC found");11271127- TRACE_ABORT(i82077AA, ft_t_warn,11281128- "Treating it as a 82077AA. Please report partid= %d",11291129- stat[0]);11301130- } /* switch(stat[ 0] >> 5) */11311131- TRACE_EXIT no_fdc;11321132-}11331133-11341134-static int fdc_request_regions(void)11351135-{11361136- TRACE_FUN(ft_t_flow);11371137-11381138- if (ft_mach2 || ft_probe_fc10) {11391139- if (!request_region(fdc.sra, 8, "fdc (ft)")) {11401140-#ifndef BROKEN_FLOPPY_DRIVER11411141- TRACE_EXIT -EBUSY;11421142-#else11431143- TRACE(ft_t_warn,11441144-"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);11451145-#endif11461146- }11471147- } else {11481148- if (!request_region(fdc.sra, 6, "fdc (ft)")) {11491149-#ifndef BROKEN_FLOPPY_DRIVER11501150- TRACE_EXIT -EBUSY;11511151-#else11521152- TRACE(ft_t_warn,11531153-"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);11541154-#endif11551155- }11561156- if (!request_region(fdc.sra + 7, 1, "fdc (ft)")) {11571157-#ifndef BROKEN_FLOPPY_DRIVER11581158- release_region(fdc.sra, 6);11591159- TRACE_EXIT -EBUSY;11601160-#else11611161- TRACE(ft_t_warn,11621162-"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra + 7);11631163-#endif11641164- }11651165- }11661166- TRACE_EXIT 0;11671167-}11681168-11691169-void fdc_release_regions(void)11701170-{11711171- TRACE_FUN(ft_t_flow);11721172-11731173- if (fdc.sra != 0) {11741174- if (fdc.dor2 != 0) {11751175- release_region(fdc.sra, 8);11761176- } else {11771177- release_region(fdc.sra, 6);11781178- release_region(fdc.dir, 1);11791179- }11801180- }11811181- TRACE_EXIT;11821182-}11831183-11841184-static int fdc_config_regs(unsigned int fdc_base, 11851185- unsigned int fdc_irq, 11861186- unsigned int fdc_dma)11871187-{11881188- TRACE_FUN(ft_t_flow);11891189-11901190- fdc.irq = fdc_irq;11911191- fdc.dma = fdc_dma;11921192- fdc.sra = fdc_base;11931193- fdc.srb = fdc_base + 1;11941194- fdc.dor = fdc_base + 2;11951195- fdc.tdr = fdc_base + 3;11961196- fdc.msr = fdc.dsr = fdc_base + 4;11971197- fdc.fifo = fdc_base + 5;11981198- fdc.dir = fdc.ccr = fdc_base + 7;11991199- fdc.dor2 = (ft_mach2 || ft_probe_fc10) ? fdc_base + 6 : 0;12001200- TRACE_CATCH(fdc_request_regions(), fdc.sra = 0);12011201- TRACE_EXIT 0;12021202-}12031203-12041204-static int fdc_config(void)12051205-{12061206- static int already_done;12071207- TRACE_FUN(ft_t_any);12081208-12091209- if (already_done) {12101210- TRACE_CATCH(fdc_request_regions(),);12111211- *(fdc.hook) = fdc_isr; /* hook our handler in */12121212- TRACE_EXIT 0;12131213- }12141214- if (ft_probe_fc10) {12151215- int fc_type;12161216-12171217- TRACE_CATCH(fdc_config_regs(ft_fdc_base,12181218- ft_fdc_irq, ft_fdc_dma),);12191219- fc_type = fc10_enable();12201220- if (fc_type != 0) {12211221- TRACE(ft_t_warn, "FC-%c0 controller found", '0' + fc_type);12221222- fdc.type = fc10;12231223- fdc.hook = &do_ftape;12241224- *(fdc.hook) = fdc_isr; /* hook our handler in */12251225- already_done = 1;12261226- TRACE_EXIT 0;12271227- } else {12281228- TRACE(ft_t_warn, "FC-10/20 controller not found");12291229- fdc_release_regions();12301230- fdc.type = no_fdc;12311231- ft_probe_fc10 = 0;12321232- ft_fdc_base = 0x3f0;12331233- ft_fdc_irq = 6;12341234- ft_fdc_dma = 2;12351235- }12361236- }12371237- TRACE(ft_t_warn, "fdc base: 0x%x, irq: %d, dma: %d", 12381238- ft_fdc_base, ft_fdc_irq, ft_fdc_dma);12391239- TRACE_CATCH(fdc_config_regs(ft_fdc_base, ft_fdc_irq, ft_fdc_dma),);12401240- fdc.hook = &do_ftape;12411241- *(fdc.hook) = fdc_isr; /* hook our handler in */12421242- already_done = 1;12431243- TRACE_EXIT 0;12441244-}12451245-12461246-static irqreturn_t ftape_interrupt(int irq, void *dev_id)12471247-{12481248- void (*handler) (void) = *fdc.hook;12491249- int handled = 0;12501250- TRACE_FUN(ft_t_any);12511251-12521252- *fdc.hook = NULL;12531253- if (handler) {12541254- handled = 1;12551255- handler();12561256- } else {12571257- TRACE(ft_t_bug, "Unexpected ftape interrupt");12581258- }12591259- TRACE_EXIT IRQ_RETVAL(handled);12601260-}12611261-12621262-static int fdc_grab_irq_and_dma(void)12631263-{12641264- TRACE_FUN(ft_t_any);12651265-12661266- if (fdc.hook == &do_ftape) {12671267- /* Get fast interrupt handler.12681268- */12691269- if (request_irq(fdc.irq, ftape_interrupt,12701270- IRQF_DISABLED, "ft", ftape_id)) {12711271- TRACE_ABORT(-EIO, ft_t_bug,12721272- "Unable to grab IRQ%d for ftape driver",12731273- fdc.irq);12741274- }12751275- if (request_dma(fdc.dma, ftape_id)) {12761276- free_irq(fdc.irq, ftape_id);12771277- TRACE_ABORT(-EIO, ft_t_bug,12781278- "Unable to grab DMA%d for ftape driver",12791279- fdc.dma);12801280- }12811281- }12821282- if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {12831283- /* Using same dma channel or irq as standard fdc, need12841284- * to disable the dma-gate on the std fdc. This12851285- * couldn't be done in the floppy driver as some12861286- * laptops are using the dma-gate to enter a low power12871287- * or even suspended state :-(12881288- */12891289- outb_p(FDC_RESET_NOT, 0x3f2);12901290- TRACE(ft_t_noise, "DMA-gate on standard fdc disabled");12911291- }12921292- TRACE_EXIT 0;12931293-}12941294-12951295-int fdc_release_irq_and_dma(void)12961296-{12971297- TRACE_FUN(ft_t_any);12981298-12991299- if (fdc.hook == &do_ftape) {13001300- disable_dma(fdc.dma); /* just in case... */13011301- free_dma(fdc.dma);13021302- free_irq(fdc.irq, ftape_id);13031303- }13041304- if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {13051305- /* Using same dma channel as standard fdc, need to13061306- * disable the dma-gate on the std fdc. This couldn't13071307- * be done in the floppy driver as some laptops are13081308- * using the dma-gate to enter a low power or even13091309- * suspended state :-(13101310- */13111311- outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);13121312- TRACE(ft_t_noise, "DMA-gate on standard fdc enabled again");13131313- }13141314- TRACE_EXIT 0;13151315-}13161316-13171317-int fdc_init(void)13181318-{13191319- TRACE_FUN(ft_t_any);13201320-13211321- /* find a FDC to use */13221322- TRACE_CATCH(fdc_config(),);13231323- TRACE_CATCH(fdc_grab_irq_and_dma(), fdc_release_regions());13241324- ftape_motor = 0;13251325- fdc_catch_stray_interrupts(0); /* clear number of awainted13261326- * stray interrupte 13271327- */13281328- fdc_catch_stray_interrupts(1); /* one always comes (?) */13291329- TRACE(ft_t_flow, "resetting fdc");13301330- fdc_set_seek_rate(2); /* use nominal QIC step rate */13311331- fdc_reset(); /* init fdc & clear track counters */13321332- if (fdc.type == no_fdc) { /* no FC-10 or FC-20 found */13331333- fdc.type = fdc_probe();13341334- fdc_reset(); /* update with new knowledge */13351335- }13361336- if (fdc.type == no_fdc) {13371337- fdc_release_irq_and_dma();13381338- fdc_release_regions();13391339- TRACE_EXIT -ENXIO;13401340- }13411341- if (fdc.type >= i82077) {13421342- if (fdc_fifo_enable() < 0) {13431343- TRACE(ft_t_warn, "couldn't enable fdc fifo !");13441344- } else {13451345- TRACE(ft_t_flow, "fdc fifo enabled and locked");13461346- }13471347- }13481348- TRACE_EXIT 0;13491349-}
-252
drivers/char/ftape/lowlevel/fdc-io.h
···11-#ifndef _FDC_IO_H22-#define _FDC_IO_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-io.h,v $2424- * $Revision: 1.3 $2525- * $Date: 1997/10/05 19:18:06 $2626- *2727- * This file contains the declarations for the low level2828- * functions that communicate with the floppy disk controller,2929- * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for3030- * Linux.3131- */3232-3333-#include <linux/fdreg.h>3434-3535-#include "../lowlevel/ftape-bsm.h"3636-3737-#define FDC_SK_BIT (0x20)3838-#define FDC_MT_BIT (0x80)3939-4040-#define FDC_READ (FD_READ & ~(FDC_SK_BIT | FDC_MT_BIT))4141-#define FDC_WRITE (FD_WRITE & ~FDC_MT_BIT)4242-#define FDC_READ_DELETED (0x4c)4343-#define FDC_WRITE_DELETED (0x49)4444-#define FDC_VERIFY (0x56)4545-#define FDC_READID (0x4a)4646-#define FDC_SENSED (0x04)4747-#define FDC_SENSEI (FD_SENSEI)4848-#define FDC_FORMAT (FD_FORMAT)4949-#define FDC_RECAL (FD_RECALIBRATE)5050-#define FDC_SEEK (FD_SEEK)5151-#define FDC_SPECIFY (FD_SPECIFY)5252-#define FDC_RECALIBR (FD_RECALIBRATE)5353-#define FDC_VERSION (FD_VERSION)5454-#define FDC_PERPEND (FD_PERPENDICULAR)5555-#define FDC_DUMPREGS (FD_DUMPREGS)5656-#define FDC_LOCK (FD_LOCK)5757-#define FDC_UNLOCK (FD_UNLOCK)5858-#define FDC_CONFIGURE (FD_CONFIGURE)5959-#define FDC_DRIVE_SPEC (0x8e) /* i82078 has this (any others?) */6060-#define FDC_PARTID (0x18) /* i82078 has this */6161-#define FDC_SAVE (0x2e) /* i82078 has this (any others?) */6262-#define FDC_RESTORE (0x4e) /* i82078 has this (any others?) */6363-6464-#define FDC_STATUS_MASK (STATUS_BUSY | STATUS_DMA | STATUS_DIR | STATUS_READY)6565-#define FDC_DATA_READY (STATUS_READY)6666-#define FDC_DATA_OUTPUT (STATUS_DIR)6767-#define FDC_DATA_READY_MASK (STATUS_READY | STATUS_DIR)6868-#define FDC_DATA_OUT_READY (STATUS_READY | STATUS_DIR)6969-#define FDC_DATA_IN_READY (STATUS_READY)7070-#define FDC_BUSY (STATUS_BUSY)7171-#define FDC_CLK48_BIT (0x80)7272-#define FDC_SEL3V_BIT (0x40)7373-7474-#define ST0_INT_MASK (ST0_INTR)7575-#define FDC_INT_NORMAL (ST0_INTR & 0x00)7676-#define FDC_INT_ABNORMAL (ST0_INTR & 0x40)7777-#define FDC_INT_INVALID (ST0_INTR & 0x80)7878-#define FDC_INT_READYCH (ST0_INTR & 0xC0)7979-#define ST0_SEEK_END (ST0_SE)8080-#define ST3_TRACK_0 (ST3_TZ)8181-8282-#define FDC_RESET_NOT (0x04)8383-#define FDC_DMA_MODE (0x08)8484-#define FDC_MOTOR_0 (0x10)8585-#define FDC_MOTOR_1 (0x20)8686-8787-typedef struct {8888- void (**hook) (void); /* our wedge into the isr */8989- enum {9090- no_fdc, i8272, i82077, i82077AA, fc10,9191- i82078, i82078_19292- } type; /* FDC type */9393- unsigned int irq; /* FDC irq nr */9494- unsigned int dma; /* FDC dma channel nr */9595- __u16 sra; /* Status register A (PS/2 only) */9696- __u16 srb; /* Status register B (PS/2 only) */9797- __u16 dor; /* Digital output register */9898- __u16 tdr; /* Tape Drive Register (82077SL-1 &9999- 82078 only) */100100- __u16 msr; /* Main Status Register */101101- __u16 dsr; /* Datarate Select Register (8207x only) */102102- __u16 fifo; /* Data register / Fifo on 8207x */103103- __u16 dir; /* Digital Input Register */104104- __u16 ccr; /* Configuration Control Register */105105- __u16 dor2; /* Alternate dor on MACH-2 controller,106106- also used with FC-10, meaning unknown */107107-} fdc_config_info;108108-109109-typedef enum {110110- fdc_data_rate_250 = 2,111111- fdc_data_rate_300 = 1, /* any fdc in default configuration */112112- fdc_data_rate_500 = 0,113113- fdc_data_rate_1000 = 3,114114- fdc_data_rate_2000 = 1, /* i82078-1: when using Data Rate Table #2 */115115-} fdc_data_rate_type;116116-117117-typedef enum {118118- fdc_idle = 0,119119- fdc_reading_data = FDC_READ,120120- fdc_seeking = FDC_SEEK,121121- fdc_writing_data = FDC_WRITE,122122- fdc_deleting = FDC_WRITE_DELETED,123123- fdc_reading_id = FDC_READID,124124- fdc_recalibrating = FDC_RECAL,125125- fdc_formatting = FDC_FORMAT,126126- fdc_verifying = FDC_VERIFY127127-} fdc_mode_enum;128128-129129-typedef enum {130130- waiting = 0,131131- reading,132132- writing,133133- formatting,134134- verifying,135135- deleting,136136- done,137137- error,138138- mmapped,139139-} buffer_state_enum;140140-141141-typedef struct {142142- __u8 *address;143143- volatile buffer_state_enum status;144144- volatile __u8 *ptr;145145- volatile unsigned int bytes;146146- volatile unsigned int segment_id;147147-148148- /* bitmap for remainder of segment not yet handled.149149- * one bit set for each bad sector that must be skipped.150150- */151151- volatile SectorMap bad_sector_map;152152-153153- /* bitmap with bad data blocks in data buffer.154154- * the errors in this map may be retried.155155- */156156- volatile SectorMap soft_error_map;157157-158158- /* bitmap with bad data blocks in data buffer159159- * the errors in this map may not be retried.160160- */161161- volatile SectorMap hard_error_map;162162-163163- /* retry counter for soft errors.164164- */165165- volatile int retry;166166-167167- /* sectors to skip on retry ???168168- */169169- volatile unsigned int skip;170170-171171- /* nr of data blocks in data buffer172172- */173173- volatile unsigned int data_offset;174174-175175- /* offset in segment for first sector to be handled.176176- */177177- volatile unsigned int sector_offset;178178-179179- /* size of cluster of good sectors to be handled.180180- */181181- volatile unsigned int sector_count;182182-183183- /* size of remaining part of segment to be handled.184184- */185185- volatile unsigned int remaining;186186-187187- /* points to next segment (contiguous) to be handled,188188- * or is zero if no read-ahead is allowed.189189- */190190- volatile unsigned int next_segment;191191-192192- /* flag being set if deleted data was read.193193- */194194- volatile int deleted;195195-196196- /* floppy coordinates of first sector in segment */197197- volatile __u8 head;198198- volatile __u8 cyl;199199- volatile __u8 sect;200200-201201- /* gap to use when formatting */202202- __u8 gap3;203203- /* flag set when buffer is mmaped */204204- int mmapped;205205-} buffer_struct;206206-207207-/*208208- * fdc-io.c defined public variables209209- */210210-extern volatile fdc_mode_enum fdc_mode;211211-extern int fdc_setup_error; /* outdated ??? */212212-extern wait_queue_head_t ftape_wait_intr;213213-extern volatile int ftape_current_cylinder; /* track nr FDC thinks we're on */214214-extern volatile __u8 fdc_head; /* FDC head */215215-extern volatile __u8 fdc_cyl; /* FDC track */216216-extern volatile __u8 fdc_sect; /* FDC sector */217217-extern fdc_config_info fdc; /* FDC hardware configuration */218218-219219-extern unsigned int ft_fdc_base;220220-extern unsigned int ft_fdc_irq;221221-extern unsigned int ft_fdc_dma;222222-extern unsigned int ft_fdc_threshold;223223-extern unsigned int ft_fdc_rate_limit;224224-extern int ft_probe_fc10;225225-extern int ft_mach2;226226-/*227227- * fdc-io.c defined public functions228228- */229229-extern void fdc_catch_stray_interrupts(int count);230230-extern int fdc_ready_wait(unsigned int timeout);231231-extern int fdc_command(const __u8 * cmd_data, int cmd_len);232232-extern int fdc_result(__u8 * res_data, int res_len);233233-extern int fdc_interrupt_wait(unsigned int time);234234-extern int fdc_seek(int track);235235-extern int fdc_sense_drive_status(int *st3);236236-extern void fdc_motor(int motor);237237-extern void fdc_reset(void);238238-extern void fdc_disable(void);239239-extern int fdc_fifo_threshold(__u8 threshold,240240- int *fifo_state, int *lock_state, int *fifo_thr);241241-extern void fdc_wait_calibrate(void);242242-extern int fdc_sense_interrupt_status(int *st0, int *current_cylinder);243243-extern void fdc_save_drive_specs(void);244244-extern void fdc_restore_drive_specs(void);245245-extern int fdc_set_data_rate(int rate);246246-extern void fdc_set_write_precomp(int precomp);247247-extern int fdc_release_irq_and_dma(void);248248-extern void fdc_release_regions(void);249249-extern int fdc_init(void);250250-extern int fdc_setup_read_write(buffer_struct * buff, __u8 operation);251251-extern int fdc_setup_formatting(buffer_struct * buff);252252-#endif
-1170
drivers/char/ftape/lowlevel/fdc-isr.c
···11-/*22- * Copyright (C) 1994-1996 Bas Laarhoven,33- * (C) 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.c,v $2121- * $Revision: 1.9 $2222- * $Date: 1997/10/17 23:01:53 $2323- *2424- * This file contains the interrupt service routine and2525- * associated code for the QIC-40/80/3010/3020 floppy-tape driver2626- * "ftape" for Linux.2727- */2828-2929-#include <asm/io.h>3030-#include <asm/dma.h>3131-3232-#define volatile /* */3333-3434-#include <linux/ftape.h>3535-#include <linux/qic117.h>3636-#include "../lowlevel/ftape-tracing.h"3737-#include "../lowlevel/fdc-isr.h"3838-#include "../lowlevel/fdc-io.h"3939-#include "../lowlevel/ftape-ctl.h"4040-#include "../lowlevel/ftape-rw.h"4141-#include "../lowlevel/ftape-io.h"4242-#include "../lowlevel/ftape-calibr.h"4343-#include "../lowlevel/ftape-bsm.h"4444-4545-/* Global vars.4646- */4747-volatile int ft_expected_stray_interrupts;4848-volatile int ft_interrupt_seen;4949-volatile int ft_seek_completed;5050-volatile int ft_hide_interrupt;5151-/* Local vars.5252- */5353-typedef enum {5454- no_error = 0, id_am_error = 0x01, id_crc_error = 0x02,5555- data_am_error = 0x04, data_crc_error = 0x08,5656- no_data_error = 0x10, overrun_error = 0x20,5757-} error_cause;5858-static int stop_read_ahead;5959-6060-6161-static void print_error_cause(int cause)6262-{6363- TRACE_FUN(ft_t_any);6464-6565- switch (cause) {6666- case no_data_error:6767- TRACE(ft_t_noise, "no data error");6868- break;6969- case id_am_error:7070- TRACE(ft_t_noise, "id am error");7171- break;7272- case id_crc_error:7373- TRACE(ft_t_noise, "id crc error");7474- break;7575- case data_am_error:7676- TRACE(ft_t_noise, "data am error");7777- break;7878- case data_crc_error:7979- TRACE(ft_t_noise, "data crc error");8080- break;8181- case overrun_error:8282- TRACE(ft_t_noise, "overrun error");8383- break;8484- default:;8585- }8686- TRACE_EXIT;8787-}8888-8989-static char *fdc_mode_txt(fdc_mode_enum mode)9090-{9191- switch (mode) {9292- case fdc_idle:9393- return "fdc_idle";9494- case fdc_reading_data:9595- return "fdc_reading_data";9696- case fdc_seeking:9797- return "fdc_seeking";9898- case fdc_writing_data:9999- return "fdc_writing_data";100100- case fdc_reading_id:101101- return "fdc_reading_id";102102- case fdc_recalibrating:103103- return "fdc_recalibrating";104104- case fdc_formatting:105105- return "fdc_formatting";106106- case fdc_verifying:107107- return "fdc_verifying";108108- default:109109- return "unknown";110110- }111111-}112112-113113-static inline error_cause decode_irq_cause(fdc_mode_enum mode, __u8 st[])114114-{115115- error_cause cause = no_error;116116- TRACE_FUN(ft_t_any);117117-118118- /* Valid st[], decode cause of interrupt.119119- */120120- switch (st[0] & ST0_INT_MASK) {121121- case FDC_INT_NORMAL:122122- TRACE(ft_t_fdc_dma,"normal completion: %s",fdc_mode_txt(mode));123123- break;124124- case FDC_INT_ABNORMAL:125125- TRACE(ft_t_flow, "abnormal completion %s", fdc_mode_txt(mode));126126- TRACE(ft_t_fdc_dma, "ST0: 0x%02x, ST1: 0x%02x, ST2: 0x%02x",127127- st[0], st[1], st[2]);128128- TRACE(ft_t_fdc_dma,129129- "C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x",130130- st[3], st[4], st[5], st[6]);131131- if (st[1] & 0x01) {132132- if (st[2] & 0x01) {133133- cause = data_am_error;134134- } else {135135- cause = id_am_error;136136- }137137- } else if (st[1] & 0x20) {138138- if (st[2] & 0x20) {139139- cause = data_crc_error;140140- } else {141141- cause = id_crc_error;142142- }143143- } else if (st[1] & 0x04) {144144- cause = no_data_error;145145- } else if (st[1] & 0x10) {146146- cause = overrun_error;147147- }148148- print_error_cause(cause);149149- break;150150- case FDC_INT_INVALID:151151- TRACE(ft_t_flow, "invalid completion %s", fdc_mode_txt(mode));152152- break;153153- case FDC_INT_READYCH:154154- if (st[0] & ST0_SEEK_END) {155155- TRACE(ft_t_flow, "drive poll completed");156156- } else {157157- TRACE(ft_t_flow, "ready change %s",fdc_mode_txt(mode));158158- }159159- break;160160- default:161161- break;162162- }163163- TRACE_EXIT cause;164164-}165165-166166-static void update_history(error_cause cause)167167-{168168- switch (cause) {169169- case id_am_error:170170- ft_history.id_am_errors++;171171- break;172172- case id_crc_error:173173- ft_history.id_crc_errors++;174174- break;175175- case data_am_error:176176- ft_history.data_am_errors++;177177- break;178178- case data_crc_error:179179- ft_history.data_crc_errors++;180180- break;181181- case overrun_error:182182- ft_history.overrun_errors++;183183- break;184184- case no_data_error:185185- ft_history.no_data_errors++;186186- break;187187- default:;188188- }189189-}190190-191191-static void skip_bad_sector(buffer_struct * buff)192192-{193193- TRACE_FUN(ft_t_any);194194-195195- /* Mark sector as soft error and skip it196196- */197197- if (buff->remaining > 0) {198198- ++buff->sector_offset;199199- ++buff->data_offset;200200- --buff->remaining;201201- buff->ptr += FT_SECTOR_SIZE;202202- buff->bad_sector_map >>= 1;203203- } else {204204- /* Hey, what is this????????????? C code: if we shift 205205- * more than 31 bits, we get no shift. That's bad!!!!!!206206- */207207- ++buff->sector_offset; /* hack for error maps */208208- TRACE(ft_t_warn, "skipping last sector in segment");209209- }210210- TRACE_EXIT;211211-}212212-213213-static void update_error_maps(buffer_struct * buff, unsigned int error_offset)214214-{215215- int hard = 0;216216- TRACE_FUN(ft_t_any);217217-218218- if (buff->retry < FT_SOFT_RETRIES) {219219- buff->soft_error_map |= (1 << error_offset);220220- } else {221221- buff->hard_error_map |= (1 << error_offset);222222- buff->soft_error_map &= ~buff->hard_error_map;223223- buff->retry = -1; /* will be set to 0 in setup_segment */224224- hard = 1;225225- }226226- TRACE(ft_t_noise, "sector %d : %s error\n"227227- KERN_INFO "hard map: 0x%08lx\n"228228- KERN_INFO "soft map: 0x%08lx",229229- FT_SECTOR(error_offset), hard ? "hard" : "soft",230230- (long) buff->hard_error_map, (long) buff->soft_error_map);231231- TRACE_EXIT;232232-}233233-234234-static void print_progress(buffer_struct *buff, error_cause cause)235235-{236236- TRACE_FUN(ft_t_any);237237-238238- switch (cause) {239239- case no_error: 240240- TRACE(ft_t_flow,"%d Sector(s) transferred", buff->sector_count);241241- break;242242- case no_data_error:243243- TRACE(ft_t_flow, "Sector %d not found",244244- FT_SECTOR(buff->sector_offset));245245- break;246246- case overrun_error:247247- /* got an overrun error on the first byte, must be a248248- * hardware problem249249- */250250- TRACE(ft_t_bug,251251- "Unexpected error: failing DMA or FDC controller ?");252252- break;253253- case data_crc_error:254254- TRACE(ft_t_flow, "Error in sector %d",255255- FT_SECTOR(buff->sector_offset - 1));256256- break;257257- case id_crc_error:258258- case id_am_error:259259- case data_am_error:260260- TRACE(ft_t_flow, "Error in sector %d",261261- FT_SECTOR(buff->sector_offset));262262- break;263263- default:264264- TRACE(ft_t_flow, "Unexpected error at sector %d",265265- FT_SECTOR(buff->sector_offset));266266- break;267267- }268268- TRACE_EXIT;269269-}270270-271271-/*272272- * Error cause: Amount xferred: Action:273273- *274274- * id_am_error 0 mark bad and skip275275- * id_crc_error 0 mark bad and skip276276- * data_am_error 0 mark bad and skip277277- * data_crc_error % 1024 mark bad and skip278278- * no_data_error 0 retry on write279279- * mark bad and skip on read280280- * overrun_error [ 0..all-1 ] mark bad and skip281281- * no_error all continue282282- */283283-284284-/* the arg `sector' is returned by the fdc and tells us at which sector we285285- * are positioned at (relative to starting sector of segment)286286- */287287-static void determine_verify_progress(buffer_struct *buff,288288- error_cause cause,289289- __u8 sector)290290-{291291- TRACE_FUN(ft_t_any);292292-293293- if (cause == no_error && sector == 1) {294294- buff->sector_offset = FT_SECTORS_PER_SEGMENT;295295- buff->remaining = 0;296296- if (TRACE_LEVEL >= ft_t_flow) {297297- print_progress(buff, cause);298298- }299299- } else {300300- buff->sector_offset = sector - buff->sect;301301- buff->remaining = FT_SECTORS_PER_SEGMENT - buff->sector_offset;302302- TRACE(ft_t_noise, "%ssector offset: 0x%04x", 303303- (cause == no_error) ? "unexpected " : "",304304- buff->sector_offset);305305- switch (cause) {306306- case overrun_error:307307- break;308308-#if 0309309- case no_data_error:310310- buff->retry = FT_SOFT_RETRIES;311311- if (buff->hard_error_map &&312312- buff->sector_offset > 1 &&313313- (buff->hard_error_map & 314314- (1 << (buff->sector_offset-2)))) {315315- buff->retry --;316316- }317317- break;318318-#endif319319- default:320320- buff->retry = FT_SOFT_RETRIES;321321- break;322322- }323323- if (TRACE_LEVEL >= ft_t_flow) {324324- print_progress(buff, cause);325325- }326326- /* Sector_offset points to the problem area Now adjust327327- * sector_offset so it always points one past he failing328328- * sector. I.e. skip the bad sector.329329- */330330- ++buff->sector_offset;331331- --buff->remaining;332332- update_error_maps(buff, buff->sector_offset - 1);333333- }334334- TRACE_EXIT;335335-}336336-337337-static void determine_progress(buffer_struct *buff,338338- error_cause cause,339339- __u8 sector)340340-{341341- unsigned int dma_residue;342342- TRACE_FUN(ft_t_any);343343-344344- /* Using less preferred order of disable_dma and345345- * get_dma_residue because this seems to fail on at least one346346- * system if reversed!347347- */348348- dma_residue = get_dma_residue(fdc.dma);349349- disable_dma(fdc.dma);350350- if (cause != no_error || dma_residue != 0) {351351- TRACE(ft_t_noise, "%sDMA residue: 0x%04x", 352352- (cause == no_error) ? "unexpected " : "",353353- dma_residue);354354- /* adjust to actual value: */355355- if (dma_residue == 0) {356356- /* this happens sometimes with overrun errors.357357- * I don't know whether we could ignore the358358- * overrun error. Play save.359359- */360360- buff->sector_count --;361361- } else {362362- buff->sector_count -= ((dma_residue + 363363- (FT_SECTOR_SIZE - 1)) /364364- FT_SECTOR_SIZE);365365- }366366- }367367- /* Update var's influenced by the DMA operation.368368- */369369- if (buff->sector_count > 0) {370370- buff->sector_offset += buff->sector_count;371371- buff->data_offset += buff->sector_count;372372- buff->ptr += (buff->sector_count *373373- FT_SECTOR_SIZE);374374- buff->remaining -= buff->sector_count;375375- buff->bad_sector_map >>= buff->sector_count;376376- }377377- if (TRACE_LEVEL >= ft_t_flow) {378378- print_progress(buff, cause);379379- }380380- if (cause != no_error) {381381- if (buff->remaining == 0) {382382- TRACE(ft_t_warn, "foo?\n"383383- KERN_INFO "count : %d\n"384384- KERN_INFO "offset: %d\n"385385- KERN_INFO "soft : %08x\n"386386- KERN_INFO "hard : %08x",387387- buff->sector_count,388388- buff->sector_offset,389389- buff->soft_error_map,390390- buff->hard_error_map);391391- }392392- /* Sector_offset points to the problem area, except if we got393393- * a data_crc_error. In that case it points one past the394394- * failing sector.395395- *396396- * Now adjust sector_offset so it always points one past he397397- * failing sector. I.e. skip the bad sector. 398398- */399399- if (cause != data_crc_error) {400400- skip_bad_sector(buff);401401- }402402- update_error_maps(buff, buff->sector_offset - 1);403403- }404404- TRACE_EXIT;405405-}406406-407407-static int calc_steps(int cmd)408408-{409409- if (ftape_current_cylinder > cmd) {410410- return ftape_current_cylinder - cmd;411411- } else {412412- return ftape_current_cylinder + cmd;413413- }414414-}415415-416416-static void pause_tape(int retry, int mode)417417-{418418- int result;419419- __u8 out[3] = {FDC_SEEK, ft_drive_sel, 0};420420- TRACE_FUN(ft_t_any);421421-422422- /* We'll use a raw seek command to get the tape to rewind and423423- * stop for a retry.424424- */425425- ++ft_history.rewinds;426426- if (qic117_cmds[ftape_current_command].non_intr) {427427- TRACE(ft_t_warn, "motion command may be issued too soon");428428- }429429- if (retry && (mode == fdc_reading_data ||430430- mode == fdc_reading_id ||431431- mode == fdc_verifying)) {432432- ftape_current_command = QIC_MICRO_STEP_PAUSE;433433- ftape_might_be_off_track = 1;434434- } else {435435- ftape_current_command = QIC_PAUSE;436436- }437437- out[2] = calc_steps(ftape_current_command);438438- result = fdc_command(out, 3); /* issue QIC_117 command */439439- ftape_current_cylinder = out[ 2];440440- if (result < 0) {441441- TRACE(ft_t_noise, "qic-pause failed, status = %d", result);442442- } else {443443- ft_location.known = 0;444444- ft_runner_status = idle;445445- ft_hide_interrupt = 1;446446- ftape_tape_running = 0;447447- }448448- TRACE_EXIT;449449-}450450-451451-static void continue_xfer(buffer_struct *buff,452452- fdc_mode_enum mode, 453453- unsigned int skip)454454-{455455- int write = 0;456456- TRACE_FUN(ft_t_any);457457-458458- if (mode == fdc_writing_data || mode == fdc_deleting) {459459- write = 1;460460- }461461- /* This part can be removed if it never happens462462- */463463- if (skip > 0 &&464464- (ft_runner_status != running ||465465- (write && (buff->status != writing)) ||466466- (!write && (buff->status != reading && 467467- buff->status != verifying)))) {468468- TRACE(ft_t_err, "unexpected runner/buffer state %d/%d",469469- ft_runner_status, buff->status);470470- buff->status = error;471471- /* finish this buffer: */472472- (void)ftape_next_buffer(ft_queue_head);473473- ft_runner_status = aborting;474474- fdc_mode = fdc_idle;475475- } else if (buff->remaining > 0 && ftape_calc_next_cluster(buff) > 0) {476476- /* still sectors left in current segment, continue477477- * with this segment478478- */479479- if (fdc_setup_read_write(buff, mode) < 0) {480480- /* failed, abort operation481481- */482482- buff->bytes = buff->ptr - buff->address;483483- buff->status = error;484484- /* finish this buffer: */485485- (void)ftape_next_buffer(ft_queue_head);486486- ft_runner_status = aborting;487487- fdc_mode = fdc_idle;488488- }489489- } else {490490- /* current segment completed491491- */492492- unsigned int last_segment = buff->segment_id;493493- int eot = ((last_segment + 1) % ft_segments_per_track) == 0;494494- unsigned int next = buff->next_segment; /* 0 means stop ! */495495-496496- buff->bytes = buff->ptr - buff->address;497497- buff->status = done;498498- buff = ftape_next_buffer(ft_queue_head);499499- if (eot) {500500- /* finished last segment on current track,501501- * can't continue502502- */503503- ft_runner_status = logical_eot;504504- fdc_mode = fdc_idle;505505- TRACE_EXIT;506506- }507507- if (next <= 0) {508508- /* don't continue with next segment509509- */510510- TRACE(ft_t_noise, "no %s allowed, stopping tape",511511- (write) ? "write next" : "read ahead");512512- pause_tape(0, mode);513513- ft_runner_status = idle; /* not quite true until514514- * next irq 515515- */516516- TRACE_EXIT;517517- }518518- /* continue with next segment519519- */520520- if (buff->status != waiting) {521521- TRACE(ft_t_noise, "all input buffers %s, pausing tape",522522- (write) ? "empty" : "full");523523- pause_tape(0, mode);524524- ft_runner_status = idle; /* not quite true until525525- * next irq 526526- */527527- TRACE_EXIT;528528- }529529- if (write && next != buff->segment_id) {530530- TRACE(ft_t_noise, 531531- "segments out of order, aborting write");532532- ft_runner_status = do_abort;533533- fdc_mode = fdc_idle;534534- TRACE_EXIT;535535- }536536- ftape_setup_new_segment(buff, next, 0);537537- if (stop_read_ahead) {538538- buff->next_segment = 0;539539- stop_read_ahead = 0;540540- }541541- if (ftape_calc_next_cluster(buff) == 0 ||542542- fdc_setup_read_write(buff, mode) != 0) {543543- TRACE(ft_t_err, "couldn't start %s-ahead",544544- write ? "write" : "read");545545- ft_runner_status = do_abort;546546- fdc_mode = fdc_idle;547547- } else {548548- /* keep on going */549549- switch (ft_driver_state) {550550- case reading: buff->status = reading; break;551551- case verifying: buff->status = verifying; break;552552- case writing: buff->status = writing; break;553553- case deleting: buff->status = deleting; break;554554- default:555555- TRACE(ft_t_err, 556556- "BUG: ft_driver_state %d should be one out of "557557- "{reading, writing, verifying, deleting}",558558- ft_driver_state);559559- buff->status = write ? writing : reading;560560- break;561561- }562562- }563563- }564564- TRACE_EXIT;565565-}566566-567567-static void retry_sector(buffer_struct *buff, 568568- int mode,569569- unsigned int skip)570570-{571571- TRACE_FUN(ft_t_any);572572-573573- TRACE(ft_t_noise, "%s error, will retry",574574- (mode == fdc_writing_data || mode == fdc_deleting) ? "write" : "read");575575- pause_tape(1, mode);576576- ft_runner_status = aborting;577577- buff->status = error;578578- buff->skip = skip;579579- TRACE_EXIT;580580-}581581-582582-static unsigned int find_resume_point(buffer_struct *buff)583583-{584584- int i = 0;585585- SectorMap mask;586586- SectorMap map;587587- TRACE_FUN(ft_t_any);588588-589589- /* This function is to be called after all variables have been590590- * updated to point past the failing sector.591591- * If there are any soft errors before the failing sector,592592- * find the first soft error and return the sector offset.593593- * Otherwise find the last hard error.594594- * Note: there should always be at least one hard or soft error !595595- */596596- if (buff->sector_offset < 1 || buff->sector_offset > 32) {597597- TRACE(ft_t_bug, "BUG: sector_offset = %d",598598- buff->sector_offset);599599- TRACE_EXIT 0;600600- }601601- if (buff->sector_offset >= 32) { /* C-limitation on shift ! */602602- mask = 0xffffffff;603603- } else {604604- mask = (1 << buff->sector_offset) - 1;605605- }606606- map = buff->soft_error_map & mask;607607- if (map) {608608- while ((map & (1 << i)) == 0) {609609- ++i;610610- }611611- TRACE(ft_t_noise, "at sector %d", FT_SECTOR(i));612612- } else {613613- map = buff->hard_error_map & mask;614614- i = buff->sector_offset - 1;615615- if (map) {616616- while ((map & (1 << i)) == 0) {617617- --i;618618- }619619- TRACE(ft_t_noise, "after sector %d", FT_SECTOR(i));620620- ++i; /* first sector after last hard error */621621- } else {622622- TRACE(ft_t_bug, "BUG: no soft or hard errors");623623- }624624- }625625- TRACE_EXIT i;626626-}627627-628628-/* check possible dma residue when formatting, update position record in629629- * buffer struct. This is, of course, modelled after determine_progress(), but630630- * we don't need to set up for retries because the format process cannot be631631- * interrupted (except at the end of the tape track).632632- */633633-static int determine_fmt_progress(buffer_struct *buff, error_cause cause)634634-{635635- unsigned int dma_residue;636636- TRACE_FUN(ft_t_any);637637-638638- /* Using less preferred order of disable_dma and639639- * get_dma_residue because this seems to fail on at least one640640- * system if reversed!641641- */642642- dma_residue = get_dma_residue(fdc.dma);643643- disable_dma(fdc.dma);644644- if (cause != no_error || dma_residue != 0) {645645- TRACE(ft_t_info, "DMA residue = 0x%04x", dma_residue);646646- fdc_mode = fdc_idle;647647- switch(cause) {648648- case no_error:649649- ft_runner_status = aborting;650650- buff->status = idle;651651- break;652652- case overrun_error:653653- /* got an overrun error on the first byte, must be a654654- * hardware problem 655655- */656656- TRACE(ft_t_bug, 657657- "Unexpected error: failing DMA controller ?");658658- ft_runner_status = do_abort;659659- buff->status = error;660660- break;661661- default:662662- TRACE(ft_t_noise, "Unexpected error at segment %d",663663- buff->segment_id);664664- ft_runner_status = do_abort;665665- buff->status = error;666666- break;667667- }668668- TRACE_EXIT -EIO; /* can only retry entire track in format mode669669- */670670- }671671- /* Update var's influenced by the DMA operation.672672- */673673- buff->ptr += FT_SECTORS_PER_SEGMENT * 4;674674- buff->bytes -= FT_SECTORS_PER_SEGMENT * 4;675675- buff->remaining -= FT_SECTORS_PER_SEGMENT;676676- buff->segment_id ++; /* done with segment */677677- TRACE_EXIT 0;678678-}679679-680680-/*681681- * Continue formatting, switch buffers if there is no data left in682682- * current buffer. This is, of course, modelled after683683- * continue_xfer(), but we don't need to set up for retries because684684- * the format process cannot be interrupted (except at the end of the685685- * tape track).686686- */687687-static void continue_formatting(buffer_struct *buff)688688-{689689- TRACE_FUN(ft_t_any);690690-691691- if (buff->remaining <= 0) { /* no space left in dma buffer */692692- unsigned int next = buff->next_segment; 693693-694694- if (next == 0) { /* end of tape track */695695- buff->status = done;696696- ft_runner_status = logical_eot;697697- fdc_mode = fdc_idle;698698- TRACE(ft_t_noise, "Done formatting track %d",699699- ft_location.track);700700- TRACE_EXIT;701701- }702702- /*703703- * switch to next buffer!704704- */705705- buff->status = done;706706- buff = ftape_next_buffer(ft_queue_head);707707-708708- if (buff->status != waiting || next != buff->segment_id) {709709- goto format_setup_error;710710- }711711- }712712- if (fdc_setup_formatting(buff) < 0) {713713- goto format_setup_error;714714- }715715- buff->status = formatting;716716- TRACE(ft_t_fdc_dma, "Formatting segment %d on track %d",717717- buff->segment_id, ft_location.track);718718- TRACE_EXIT;719719- format_setup_error:720720- ft_runner_status = do_abort;721721- fdc_mode = fdc_idle;722722- buff->status = error;723723- TRACE(ft_t_err, "Error setting up for segment %d on track %d",724724- buff->segment_id, ft_location.track);725725- TRACE_EXIT;726726-727727-}728728-729729-/* this handles writing, read id, reading and formatting730730- */731731-static void handle_fdc_busy(buffer_struct *buff)732732-{733733- static int no_data_error_count;734734- int retry = 0;735735- error_cause cause;736736- __u8 in[7];737737- int skip;738738- fdc_mode_enum fmode = fdc_mode;739739- TRACE_FUN(ft_t_any);740740-741741- if (fdc_result(in, 7) < 0) { /* better get it fast ! */742742- TRACE(ft_t_err, 743743- "Probably fatal error during FDC Result Phase\n"744744- KERN_INFO745745- "drive may hang until (power on) reset :-(");746746- /* what to do next ????747747- */748748- TRACE_EXIT;749749- }750750- cause = decode_irq_cause(fdc_mode, in);751751-#ifdef TESTING752752- { int i;753753- for (i = 0; i < (int)ft_nr_buffers; ++i)754754- TRACE(ft_t_any, "buffer[%d] status: %d, segment_id: %d",755755- i, ft_buffer[i]->status, ft_buffer[i]->segment_id);756756- }757757-#endif758758- if (fmode == fdc_reading_data && ft_driver_state == verifying) {759759- fmode = fdc_verifying;760760- }761761- switch (fmode) {762762- case fdc_verifying:763763- if (ft_runner_status == aborting ||764764- ft_runner_status == do_abort) {765765- TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode));766766- break;767767- }768768- if (buff->retry > 0) {769769- TRACE(ft_t_flow, "this is retry nr %d", buff->retry);770770- }771771- switch (cause) {772772- case no_error:773773- no_data_error_count = 0;774774- determine_verify_progress(buff, cause, in[5]);775775- if (in[2] & 0x40) {776776- /* This should not happen when verifying777777- */778778- TRACE(ft_t_warn,779779- "deleted data in segment %d/%d",780780- buff->segment_id,781781- FT_SECTOR(buff->sector_offset - 1));782782- buff->remaining = 0; /* abort transfer */783783- buff->hard_error_map = EMPTY_SEGMENT;784784- skip = 1;785785- } else {786786- skip = 0;787787- }788788- continue_xfer(buff, fdc_mode, skip);789789- break;790790- case no_data_error:791791- no_data_error_count ++;792792- case overrun_error:793793- retry ++;794794- case id_am_error:795795- case id_crc_error:796796- case data_am_error:797797- case data_crc_error:798798- determine_verify_progress(buff, cause, in[5]); 799799- if (cause == no_data_error) {800800- if (no_data_error_count >= 2) {801801- TRACE(ft_t_warn,802802- "retrying because of successive "803803- "no data errors");804804- no_data_error_count = 0;805805- } else {806806- retry --;807807- }808808- } else {809809- no_data_error_count = 0;810810- }811811- if (retry) {812812- skip = find_resume_point(buff);813813- } else {814814- skip = buff->sector_offset;815815- }816816- if (retry && skip < 32) {817817- retry_sector(buff, fdc_mode, skip);818818- } else {819819- continue_xfer(buff, fdc_mode, skip);820820- }821821- update_history(cause);822822- break;823823- default:824824- /* Don't know why this could happen 825825- * but find out.826826- */827827- determine_verify_progress(buff, cause, in[5]);828828- retry_sector(buff, fdc_mode, 0);829829- TRACE(ft_t_err, "Error: unexpected error");830830- break;831831- }832832- break;833833- case fdc_reading_data:834834-#ifdef TESTING835835- /* I'm sorry, but: NOBODY ever used this trace836836- * messages for ages. I guess that Bas was the last person837837- * that ever really used this (thank you, between the lines)838838- */839839- if (cause == no_error) {840840- TRACE(ft_t_flow,"reading segment %d",buff->segment_id);841841- } else {842842- TRACE(ft_t_noise, "error reading segment %d",843843- buff->segment_id);844844- TRACE(ft_t_noise, "\n"845845- KERN_INFO846846- "IRQ:C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x\n"847847- KERN_INFO848848- "BUF:C: 0x%02x, H: 0x%02x, R: 0x%02x",849849- in[3], in[4], in[5], in[6],850850- buff->cyl, buff->head, buff->sect);851851- }852852-#endif853853- if (ft_runner_status == aborting ||854854- ft_runner_status == do_abort) {855855- TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode));856856- break;857857- }858858- if (buff->bad_sector_map == FAKE_SEGMENT) {859859- /* This condition occurs when reading a `fake'860860- * sector that's not accessible. Doesn't861861- * really matter as we would have ignored it862862- * anyway !863863- *864864- * Chance is that we're past the next segment865865- * now, so the next operation may fail and866866- * result in a retry. 867867- */868868- buff->remaining = 0; /* skip failing sector */869869- /* buff->ptr = buff->address; */870870- /* fake success: */871871- continue_xfer(buff, fdc_mode, 1);872872- /* trace calls are expensive: place them AFTER873873- * the real stuff has been done.874874- * 875875- */876876- TRACE(ft_t_noise, "skipping empty segment %d (read), size? %d",877877- buff->segment_id, buff->ptr - buff->address);878878- TRACE_EXIT;879879- }880880- if (buff->retry > 0) {881881- TRACE(ft_t_flow, "this is retry nr %d", buff->retry);882882- }883883- switch (cause) {884884- case no_error:885885- determine_progress(buff, cause, in[5]);886886- if (in[2] & 0x40) {887887- /* Handle deleted data in header segments.888888- * Skip segment and force read-ahead.889889- */890890- TRACE(ft_t_warn,891891- "deleted data in segment %d/%d",892892- buff->segment_id,893893- FT_SECTOR(buff->sector_offset - 1));894894- buff->deleted = 1;895895- buff->remaining = 0;/*abort transfer */896896- buff->soft_error_map |=897897- (-1L << buff->sector_offset);898898- if (buff->segment_id == 0) {899899- /* stop on next segment */900900- stop_read_ahead = 1;901901- }902902- /* force read-ahead: */903903- buff->next_segment = 904904- buff->segment_id + 1;905905- skip = (FT_SECTORS_PER_SEGMENT - 906906- buff->sector_offset);907907- } else {908908- skip = 0;909909- }910910- continue_xfer(buff, fdc_mode, skip);911911- break;912912- case no_data_error:913913- /* Tape started too far ahead of or behind the914914- * right sector. This may also happen in the915915- * middle of a segment !916916- *917917- * Handle no-data as soft error. If next918918- * sector fails too, a retry (with needed919919- * reposition) will follow.920920- */921921- retry ++;922922- case id_am_error:923923- case id_crc_error:924924- case data_am_error:925925- case data_crc_error:926926- case overrun_error:927927- retry += (buff->soft_error_map != 0 ||928928- buff->hard_error_map != 0);929929- determine_progress(buff, cause, in[5]); 930930-#if 1 || defined(TESTING)931931- if (cause == overrun_error) retry ++;932932-#endif933933- if (retry) {934934- skip = find_resume_point(buff);935935- } else {936936- skip = buff->sector_offset;937937- }938938- /* Try to resume with next sector on single939939- * errors (let ecc correct it), but retry on940940- * no_data (we'll be past the target when we941941- * get here so we cannot retry) or on942942- * multiple errors (reduce chance on ecc943943- * failure).944944- */945945- /* cH: 23/02/97: if the last sector in the 946946- * segment was a hard error, then there is 947947- * no sense in a retry. This occasion seldom948948- * occurs but ... @:���`@%&�$949949- */950950- if (retry && skip < 32) {951951- retry_sector(buff, fdc_mode, skip);952952- } else {953953- continue_xfer(buff, fdc_mode, skip);954954- }955955- update_history(cause);956956- break;957957- default:958958- /* Don't know why this could happen 959959- * but find out.960960- */961961- determine_progress(buff, cause, in[5]);962962- retry_sector(buff, fdc_mode, 0);963963- TRACE(ft_t_err, "Error: unexpected error");964964- break;965965- }966966- break;967967- case fdc_reading_id:968968- if (cause == no_error) {969969- fdc_cyl = in[3];970970- fdc_head = in[4];971971- fdc_sect = in[5];972972- TRACE(ft_t_fdc_dma,973973- "id read: C: 0x%02x, H: 0x%02x, R: 0x%02x",974974- fdc_cyl, fdc_head, fdc_sect);975975- } else { /* no valid information, use invalid sector */976976- fdc_cyl = fdc_head = fdc_sect = 0;977977- TRACE(ft_t_flow, "Didn't find valid sector Id");978978- }979979- fdc_mode = fdc_idle;980980- break;981981- case fdc_deleting:982982- case fdc_writing_data:983983-#ifdef TESTING984984- if (cause == no_error) {985985- TRACE(ft_t_flow, "writing segment %d", buff->segment_id);986986- } else {987987- TRACE(ft_t_noise, "error writing segment %d",988988- buff->segment_id);989989- }990990-#endif991991- if (ft_runner_status == aborting ||992992- ft_runner_status == do_abort) {993993- TRACE(ft_t_flow, "aborting %s",fdc_mode_txt(fdc_mode));994994- break;995995- }996996- if (buff->retry > 0) {997997- TRACE(ft_t_flow, "this is retry nr %d", buff->retry);998998- }999999- if (buff->bad_sector_map == FAKE_SEGMENT) {10001000- /* This condition occurs when trying to write to a10011001- * `fake' sector that's not accessible. Doesn't really10021002- * matter as it isn't used anyway ! Might be located10031003- * at wrong segment, then we'll fail on the next10041004- * segment.10051005- */10061006- TRACE(ft_t_noise, "skipping empty segment (write)");10071007- buff->remaining = 0; /* skip failing sector */10081008- /* fake success: */10091009- continue_xfer(buff, fdc_mode, 1);10101010- break;10111011- }10121012- switch (cause) {10131013- case no_error:10141014- determine_progress(buff, cause, in[5]);10151015- continue_xfer(buff, fdc_mode, 0);10161016- break;10171017- case no_data_error:10181018- case id_am_error:10191019- case id_crc_error:10201020- case data_am_error:10211021- case overrun_error:10221022- update_history(cause);10231023- determine_progress(buff, cause, in[5]);10241024- skip = find_resume_point(buff);10251025- retry_sector(buff, fdc_mode, skip);10261026- break;10271027- default:10281028- if (in[1] & 0x02) {10291029- TRACE(ft_t_err, "media not writable");10301030- } else {10311031- TRACE(ft_t_bug, "unforeseen write error");10321032- }10331033- fdc_mode = fdc_idle;10341034- break;10351035- }10361036- break; /* fdc_deleting || fdc_writing_data */10371037- case fdc_formatting:10381038- /* The interrupt comes after formatting a segment. We then10391039- * have to set up QUICKLY for the next segment. But10401040- * afterwards, there is plenty of time.10411041- */10421042- switch (cause) {10431043- case no_error:10441044- /* would like to keep most of the formatting stuff10451045- * outside the isr code, but timing is too critical10461046- */10471047- if (determine_fmt_progress(buff, cause) >= 0) {10481048- continue_formatting(buff);10491049- }10501050- break;10511051- case no_data_error:10521052- case id_am_error:10531053- case id_crc_error:10541054- case data_am_error:10551055- case overrun_error:10561056- default:10571057- determine_fmt_progress(buff, cause);10581058- update_history(cause);10591059- if (in[1] & 0x02) {10601060- TRACE(ft_t_err, "media not writable");10611061- } else {10621062- TRACE(ft_t_bug, "unforeseen write error");10631063- }10641064- break;10651065- } /* cause */10661066- break;10671067- default:10681068- TRACE(ft_t_warn, "Warning: unexpected irq during: %s",10691069- fdc_mode_txt(fdc_mode));10701070- fdc_mode = fdc_idle;10711071- break;10721072- }10731073- TRACE_EXIT;10741074-}10751075-10761076-/* FDC interrupt service routine.10771077- */10781078-void fdc_isr(void)10791079-{10801080- static int isr_active;10811081-#ifdef TESTING10821082- unsigned int t0 = ftape_timestamp();10831083-#endif10841084- TRACE_FUN(ft_t_any);10851085-10861086- if (isr_active++) {10871087- --isr_active;10881088- TRACE(ft_t_bug, "BUG: nested interrupt, not good !");10891089- *fdc.hook = fdc_isr; /* hook our handler into the fdc10901090- * code again 10911091- */10921092- TRACE_EXIT;10931093- }10941094- sti();10951095- if (inb_p(fdc.msr) & FDC_BUSY) { /* Entering Result Phase */10961096- ft_hide_interrupt = 0;10971097- handle_fdc_busy(ftape_get_buffer(ft_queue_head));10981098- if (ft_runner_status == do_abort) {10991099- /* cease operation, remember tape position11001100- */11011101- TRACE(ft_t_flow, "runner aborting");11021102- ft_runner_status = aborting;11031103- ++ft_expected_stray_interrupts;11041104- }11051105- } else { /* !FDC_BUSY */11061106- /* clear interrupt, cause should be gotten by issuing11071107- * a Sense Interrupt Status command.11081108- */11091109- if (fdc_mode == fdc_recalibrating || fdc_mode == fdc_seeking) {11101110- if (ft_hide_interrupt) {11111111- int st0;11121112- int pcn;11131113-11141114- if (fdc_sense_interrupt_status(&st0, &pcn) < 0)11151115- TRACE(ft_t_err,11161116- "sense interrupt status failed");11171117- ftape_current_cylinder = pcn;11181118- TRACE(ft_t_flow, "handled hidden interrupt");11191119- }11201120- ft_seek_completed = 1;11211121- fdc_mode = fdc_idle;11221122- } else if (!waitqueue_active(&ftape_wait_intr)) {11231123- if (ft_expected_stray_interrupts == 0) {11241124- TRACE(ft_t_warn, "unexpected stray interrupt");11251125- } else {11261126- TRACE(ft_t_flow, "expected stray interrupt");11271127- --ft_expected_stray_interrupts;11281128- }11291129- } else {11301130- if (fdc_mode == fdc_reading_data ||11311131- fdc_mode == fdc_verifying ||11321132- fdc_mode == fdc_writing_data ||11331133- fdc_mode == fdc_deleting ||11341134- fdc_mode == fdc_formatting ||11351135- fdc_mode == fdc_reading_id) {11361136- if (inb_p(fdc.msr) & FDC_BUSY) {11371137- TRACE(ft_t_bug,11381138- "***** FDC failure, busy too late");11391139- } else {11401140- TRACE(ft_t_bug,11411141- "***** FDC failure, no busy");11421142- }11431143- } else {11441144- TRACE(ft_t_fdc_dma, "awaited stray interrupt");11451145- }11461146- }11471147- ft_hide_interrupt = 0;11481148- }11491149- /* Handle sleep code.11501150- */11511151- if (!ft_hide_interrupt) {11521152- ft_interrupt_seen ++;11531153- if (waitqueue_active(&ftape_wait_intr)) {11541154- wake_up_interruptible(&ftape_wait_intr);11551155- }11561156- } else {11571157- TRACE(ft_t_flow, "hiding interrupt while %s", 11581158- waitqueue_active(&ftape_wait_intr) ? "waiting":"active");11591159- }11601160-#ifdef TESTING11611161- t0 = ftape_timediff(t0, ftape_timestamp());11621162- if (t0 >= 1000) {11631163- /* only tell us about long calls */11641164- TRACE(ft_t_noise, "isr() duration: %5d usec", t0);11651165- }11661166-#endif11671167- *fdc.hook = fdc_isr; /* hook our handler into the fdc code again */11681168- --isr_active;11691169- TRACE_EXIT;11701170-}
-55
drivers/char/ftape/lowlevel/fdc-isr.h
···11-#ifndef _FDC_ISR_H22-#define _FDC_ISR_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:07 $2626- *2727- * This file declares the global variables necessary to2828- * synchronize the interrupt service routine (isr) with the2929- * remainder of the QIC-40/80/3010/3020 floppy-tape driver3030- * "ftape" for Linux.3131- */3232-3333-/*3434- * fdc-isr.c defined public variables3535- */3636-extern volatile int ft_expected_stray_interrupts; /* masks stray interrupts */3737-extern volatile int ft_seek_completed; /* flag set by isr */3838-extern volatile int ft_interrupt_seen; /* flag set by isr */3939-extern volatile int ft_hide_interrupt; /* flag set by isr */4040-4141-/*4242- * fdc-io.c defined public functions4343- */4444-extern void fdc_isr(void);4545-4646-/*4747- * A kernel hook that steals one interrupt from the floppy4848- * driver (Should be fixed when the new fdc driver gets ready)4949- * See the linux kernel source files:5050- * drivers/block/floppy.c & drivers/block/blk.h5151- * for the details.5252- */5353-extern void (*do_floppy) (void);5454-5555-#endif
-491
drivers/char/ftape/lowlevel/ftape-bsm.c
···11-/*22- * Copyright (C) 1994-1996 Bas Laarhoven,33- * (C) 1996-1997 Claus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-bsm.c,v $2121- * $Revision: 1.3 $2222- * $Date: 1997/10/05 19:15:15 $2323- *2424- * This file contains the bad-sector map handling code for2525- * the QIC-117 floppy tape driver for Linux.2626- * QIC-40, QIC-80, QIC-3010 and QIC-3020 maps are implemented.2727- */2828-2929-#include <linux/string.h>3030-3131-#include <linux/ftape.h>3232-#include "../lowlevel/ftape-tracing.h"3333-#include "../lowlevel/ftape-bsm.h"3434-#include "../lowlevel/ftape-ctl.h"3535-#include "../lowlevel/ftape-rw.h"3636-3737-/* Global vars.3838- */3939-4040-/* Local vars.4141- */4242-static __u8 *bad_sector_map;4343-static SectorCount *bsm_hash_ptr; 4444-4545-typedef enum {4646- forward, backward4747-} mode_type;4848-4949-#if 05050-static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map);5151-#endif5252-5353-#if 05454-/* fix_tape converts a normal QIC-80 tape into a 'wide' tape.5555- * For testing purposes only !5656- */5757-void fix_tape(__u8 * buffer, ft_format_type new_code)5858-{5959- static __u8 list[BAD_SECTOR_MAP_SIZE];6060- SectorMap *src_ptr = (SectorMap *) list;6161- __u8 *dst_ptr = bad_sector_map;6262- SectorMap map;6363- unsigned int sector = 1;6464- int i;6565-6666- if (format_code != fmt_var && format_code != fmt_big) {6767- memcpy(list, bad_sector_map, sizeof(list));6868- memset(bad_sector_map, 0, sizeof(bad_sector_map));6969- while ((__u8 *) src_ptr - list < sizeof(list)) {7070- map = *src_ptr++;7171- if (map == EMPTY_SEGMENT) {7272- *(SectorMap *) dst_ptr = 0x800000 + sector;7373- dst_ptr += 3;7474- sector += SECTORS_PER_SEGMENT;7575- } else {7676- for (i = 0; i < SECTORS_PER_SEGMENT; ++i) {7777- if (map & 1) {7878- *(SewctorMap *) dst_ptr = sector;7979- dst_ptr += 3;8080- }8181- map >>= 1;8282- ++sector;8383- }8484- }8585- }8686- }8787- bad_sector_map_changed = 1;8888- *(buffer + 4) = new_code; /* put new format code */8989- if (format_code != fmt_var && new_code == fmt_big) {9090- PUT4(buffer, FT_6_HSEG_1, (__u32)GET2(buffer, 6));9191- PUT4(buffer, FT_6_HSEG_2, (__u32)GET2(buffer, 8));9292- PUT4(buffer, FT_6_FRST_SEG, (__u32)GET2(buffer, 10));9393- PUT4(buffer, FT_6_LAST_SEG, (__u32)GET2(buffer, 12));9494- memset(buffer+6, '\0', 8);9595- }9696- format_code = new_code;9797-}9898-9999-#endif100100-101101-/* given buffer that contains a header segment, find the end of102102- * of the bsm list103103- */104104-__u8 * ftape_find_end_of_bsm_list(__u8 * address)105105-{106106- __u8 *ptr = address + FT_HEADER_END; /* start of bsm list */107107- __u8 *limit = address + FT_SEGMENT_SIZE;108108- while (ptr + 2 < limit) {109109- if (ptr[0] || ptr[1] || ptr[2]) {110110- ptr += 3;111111- } else {112112- return ptr;113113- }114114- }115115- return NULL;116116-}117117-118118-static inline void put_sector(SectorCount *ptr, unsigned int sector)119119-{120120- ptr->bytes[0] = sector & 0xff;121121- sector >>= 8;122122- ptr->bytes[1] = sector & 0xff;123123- sector >>= 8;124124- ptr->bytes[2] = sector & 0xff;125125-}126126-127127-static inline unsigned int get_sector(SectorCount *ptr)128128-{129129-#if 1130130- unsigned int sector;131131-132132- sector = ptr->bytes[0];133133- sector += ptr->bytes[1] << 8;134134- sector += ptr->bytes[2] << 16;135135-136136- return sector;137137-#else138138- /* GET4 gets the next four bytes in Intel little endian order139139- * and converts them to host byte order and handles unaligned140140- * access.141141- */142142- return (GET4(ptr, 0) & 0x00ffffff); /* back to host byte order */143143-#endif144144-}145145-146146-static void bsm_debug_fake(void)147147-{148148- /* for testing of bad sector handling at end of tape149149- */150150-#if 0151151- ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 3,152152- 0x000003e0;153153- ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 2,154154- 0xff3fffff;155155- ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 1,156156- 0xffffe000;157157-#endif158158- /* Enable to test bad sector handling159159- */160160-#if 0161161- ftape_put_bad_sector_entry(30, 0xfffffffe)162162- ftape_put_bad_sector_entry(32, 0x7fffffff);163163- ftape_put_bad_sector_entry(34, 0xfffeffff);164164- ftape_put_bad_sector_entry(36, 0x55555555);165165- ftape_put_bad_sector_entry(38, 0xffffffff);166166- ftape_put_bad_sector_entry(50, 0xffff0000);167167- ftape_put_bad_sector_entry(51, 0xffffffff);168168- ftape_put_bad_sector_entry(52, 0xffffffff);169169- ftape_put_bad_sector_entry(53, 0x0000ffff);170170-#endif171171- /* Enable when testing multiple volume tar dumps.172172- */173173-#if 0174174- {175175- int i;176176-177177- for (i = ft_first_data_segment;178178- i <= ft_last_data_segment - 7; ++i) {179179- ftape_put_bad_sector_entry(i, EMPTY_SEGMENT);180180- }181181- }182182-#endif183183- /* Enable when testing bit positions in *_error_map184184- */185185-#if 0186186- {187187- int i;188188-189189- for (i = first_data_segment; i <= last_data_segment; ++i) {190190- ftape_put_bad_sector_entry(i,191191- ftape_get_bad_sector_entry(i) 192192- | 0x00ff00ff);193193- }194194- }195195-#endif196196-}197197-198198-static void print_bad_sector_map(void)199199-{200200- unsigned int good_sectors;201201- unsigned int total_bad = 0;202202- int i;203203- TRACE_FUN(ft_t_flow);204204-205205- if (ft_format_code == fmt_big || 206206- ft_format_code == fmt_var || 207207- ft_format_code == fmt_1100ft) {208208- SectorCount *ptr = (SectorCount *)bad_sector_map;209209- unsigned int sector;210210- __u16 *ptr16;211211-212212- while((sector = get_sector(ptr++)) != 0) {213213- if ((ft_format_code == fmt_big || 214214- ft_format_code == fmt_var) &&215215- sector & 0x800000) {216216- total_bad += FT_SECTORS_PER_SEGMENT - 3;217217- TRACE(ft_t_noise, "bad segment at sector: %6d",218218- sector & 0x7fffff);219219- } else {220220- ++total_bad;221221- TRACE(ft_t_noise, "bad sector: %6d", sector);222222- }223223- }224224- /* Display old ftape's end-of-file marks225225- */226226- ptr16 = (__u16*)ptr;227227- while ((sector = get_unaligned(ptr16++)) != 0) {228228- TRACE(ft_t_noise, "Old ftape eof mark: %4d/%2d",229229- sector, get_unaligned(ptr16++));230230- }231231- } else { /* fixed size format */232232- for (i = ft_first_data_segment;233233- i < (int)(ft_segments_per_track * ft_tracks_per_tape); ++i) {234234- SectorMap map = ((SectorMap *) bad_sector_map)[i];235235-236236- if (map) {237237- TRACE(ft_t_noise,238238- "bsm for segment %4d: 0x%08x", i, (unsigned int)map);239239- total_bad += ((map == EMPTY_SEGMENT)240240- ? FT_SECTORS_PER_SEGMENT - 3241241- : count_ones(map));242242- }243243- }244244- }245245- good_sectors =246246- ((ft_segments_per_track * ft_tracks_per_tape - ft_first_data_segment)247247- * (FT_SECTORS_PER_SEGMENT - 3)) - total_bad;248248- TRACE(ft_t_info, "%d Kb usable on this tape", good_sectors);249249- if (total_bad == 0) {250250- TRACE(ft_t_info,251251- "WARNING: this tape has no bad blocks registered !");252252- } else {253253- TRACE(ft_t_info, "%d bad sectors", total_bad);254254- }255255- TRACE_EXIT;256256-}257257-258258-259259-void ftape_extract_bad_sector_map(__u8 * buffer)260260-{261261- TRACE_FUN(ft_t_any);262262-263263- /* Fill the bad sector map with the contents of buffer.264264- */265265- if (ft_format_code == fmt_var || ft_format_code == fmt_big) {266266- /* QIC-3010/3020 and wide QIC-80 tapes no longer have a failed267267- * sector log but use this area to extend the bad sector map.268268- */269269- bad_sector_map = &buffer[FT_HEADER_END];270270- } else {271271- /* non-wide QIC-80 tapes have a failed sector log area that272272- * mustn't be included in the bad sector map.273273- */274274- bad_sector_map = &buffer[FT_FSL + FT_FSL_SIZE];275275- }276276- if (ft_format_code == fmt_1100ft || 277277- ft_format_code == fmt_var ||278278- ft_format_code == fmt_big) {279279- bsm_hash_ptr = (SectorCount *)bad_sector_map;280280- } else {281281- bsm_hash_ptr = NULL;282282- }283283- bsm_debug_fake();284284- if (TRACE_LEVEL >= ft_t_info) {285285- print_bad_sector_map();286286- }287287- TRACE_EXIT;288288-}289289-290290-static inline SectorMap cvt2map(unsigned int sector)291291-{292292- return 1 << (((sector & 0x7fffff) - 1) % FT_SECTORS_PER_SEGMENT);293293-}294294-295295-static inline int cvt2segment(unsigned int sector)296296-{297297- return ((sector & 0x7fffff) - 1) / FT_SECTORS_PER_SEGMENT;298298-}299299-300300-static int forward_seek_entry(int segment_id, 301301- SectorCount **ptr, 302302- SectorMap *map)303303-{304304- unsigned int sector;305305- int segment;306306-307307- do {308308- sector = get_sector((*ptr)++);309309- segment = cvt2segment(sector);310310- } while (sector != 0 && segment < segment_id);311311- (*ptr) --; /* point to first sector >= segment_id */312312- /* Get all sectors in segment_id313313- */314314- if (sector == 0 || segment != segment_id) {315315- *map = 0;316316- return 0;317317- } else if ((sector & 0x800000) &&318318- (ft_format_code == fmt_var || ft_format_code == fmt_big)) {319319- *map = EMPTY_SEGMENT;320320- return FT_SECTORS_PER_SEGMENT;321321- } else {322322- int count = 1;323323- SectorCount *tmp_ptr = (*ptr) + 1;324324-325325- *map = cvt2map(sector);326326- while ((sector = get_sector(tmp_ptr++)) != 0 &&327327- (segment = cvt2segment(sector)) == segment_id) {328328- *map |= cvt2map(sector);329329- ++count;330330- }331331- return count;332332- }333333-}334334-335335-static int backwards_seek_entry(int segment_id,336336- SectorCount **ptr,337337- SectorMap *map)338338-{339339- unsigned int sector;340340- int segment; /* max unsigned int */341341-342342- if (*ptr <= (SectorCount *)bad_sector_map) {343343- *map = 0;344344- return 0;345345- }346346- do {347347- sector = get_sector(--(*ptr));348348- segment = cvt2segment(sector);349349- } while (*ptr > (SectorCount *)bad_sector_map && segment > segment_id);350350- if (segment > segment_id) { /* at start of list, no entry found */351351- *map = 0;352352- return 0;353353- } else if (segment < segment_id) {354354- /* before smaller entry, adjust for overshoot */355355- (*ptr) ++;356356- *map = 0;357357- return 0;358358- } else if ((sector & 0x800000) &&359359- (ft_format_code == fmt_big || ft_format_code == fmt_var)) {360360- *map = EMPTY_SEGMENT;361361- return FT_SECTORS_PER_SEGMENT;362362- } else { /* get all sectors in segment_id */363363- int count = 1;364364-365365- *map = cvt2map(sector);366366- while(*ptr > (SectorCount *)bad_sector_map) {367367- sector = get_sector(--(*ptr));368368- segment = cvt2segment(sector);369369- if (segment != segment_id) {370370- break;371371- }372372- *map |= cvt2map(sector);373373- ++count;374374- }375375- if (segment < segment_id) {376376- (*ptr) ++;377377- }378378- return count;379379- }380380-}381381-382382-#if 0383383-static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map)384384-{385385- SectorCount *ptr = (SectorCount *)bad_sector_map;386386- int count;387387- int new_count;388388- SectorMap map;389389- TRACE_FUN(ft_t_any);390390-391391- if (ft_format_code == fmt_1100ft || 392392- ft_format_code == fmt_var || 393393- ft_format_code == fmt_big) {394394- count = forward_seek_entry(segment_id, &ptr, &map);395395- new_count = count_ones(new_map);396396- /* If format code == 4 put empty segment instead of 32397397- * bad sectors.398398- */399399- if (ft_format_code == fmt_var || ft_format_code == fmt_big) {400400- if (new_count == FT_SECTORS_PER_SEGMENT) {401401- new_count = 1;402402- }403403- if (count == FT_SECTORS_PER_SEGMENT) {404404- count = 1;405405- }406406- }407407- if (count != new_count) {408408- /* insert (or delete if < 0) new_count - count409409- * entries. Move trailing part of list410410- * including terminating 0.411411- */412412- SectorCount *hi_ptr = ptr;413413-414414- do {415415- } while (get_sector(hi_ptr++) != 0);416416- /* Note: ptr is of type byte *, and each bad sector417417- * consumes 3 bytes.418418- */419419- memmove(ptr + new_count, ptr + count,420420- (size_t)(hi_ptr - (ptr + count))*sizeof(SectorCount));421421- }422422- TRACE(ft_t_noise, "putting map 0x%08x at %p, segment %d",423423- (unsigned int)new_map, ptr, segment_id);424424- if (new_count == 1 && new_map == EMPTY_SEGMENT) {425425- put_sector(ptr++, (0x800001 + 426426- segment_id * 427427- FT_SECTORS_PER_SEGMENT));428428- } else {429429- int i = 0;430430-431431- while (new_map) {432432- if (new_map & 1) {433433- put_sector(ptr++, 434434- 1 + segment_id * 435435- FT_SECTORS_PER_SEGMENT + i);436436- }437437- ++i;438438- new_map >>= 1;439439- }440440- }441441- } else {442442- ((SectorMap *) bad_sector_map)[segment_id] = new_map;443443- }444444- TRACE_EXIT;445445-}446446-#endif /* 0 */447447-448448-SectorMap ftape_get_bad_sector_entry(int segment_id)449449-{450450- if (ft_used_header_segment == -1) {451451- /* When reading header segment we'll need a blank map.452452- */453453- return 0;454454- } else if (bsm_hash_ptr != NULL) {455455- /* Invariants:456456- * map - mask value returned on last call.457457- * bsm_hash_ptr - points to first sector greater or equal to458458- * first sector in last_referenced segment.459459- * last_referenced - segment id used in the last call,460460- * sector and map belong to this id.461461- * This code is designed for sequential access and retries.462462- * For true random access it may have to be redesigned.463463- */464464- static int last_reference = -1;465465- static SectorMap map;466466-467467- if (segment_id > last_reference) {468468- /* Skip all sectors before segment_id469469- */470470- forward_seek_entry(segment_id, &bsm_hash_ptr, &map);471471- } else if (segment_id < last_reference) {472472- /* Skip backwards until begin of buffer or473473- * first sector in segment_id 474474- */475475- backwards_seek_entry(segment_id, &bsm_hash_ptr, &map);476476- } /* segment_id == last_reference : keep map */477477- last_reference = segment_id;478478- return map;479479- } else {480480- return ((SectorMap *) bad_sector_map)[segment_id];481481- }482482-}483483-484484-/* This is simply here to prevent us from overwriting other kernel485485- * data. Writes will result in NULL Pointer dereference.486486- */487487-void ftape_init_bsm(void)488488-{489489- bad_sector_map = NULL;490490- bsm_hash_ptr = NULL;491491-}
-66
drivers/char/ftape/lowlevel/ftape-bsm.h
···11-#ifndef _FTAPE_BSM_H22-#define _FTAPE_BSM_H33-44-/*55- * Copyright (C) 1994-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-bsm.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:07 $2626- *2727- * This file contains definitions for the bad sector map handling2828- * routines for the QIC-117 floppy-tape driver for Linux.2929- */3030-3131-#include <linux/ftape.h>3232-#include <linux/ftape-header-segment.h>3333-3434-#define EMPTY_SEGMENT (0xffffffff)3535-#define FAKE_SEGMENT (0xfffffffe)3636-3737-/* maximum (format code 4) bad sector map size (bytes).3838- */3939-#define BAD_SECTOR_MAP_SIZE (29 * SECTOR_SIZE - 256)4040-4141-/* format code 4 bad sector entry, ftape uses this4242- * internally for all format codes4343- */4444-typedef __u32 SectorMap;4545-/* variable and 1100 ft bad sector map entry. These three bytes represent4646- * a single sector address measured from BOT. 4747- */4848-typedef struct NewSectorMap { 4949- __u8 bytes[3];5050-} SectorCount;5151-5252-5353-/*5454- * ftape-bsm.c defined global vars.5555- */5656-5757-/*5858- * ftape-bsm.c defined global functions.5959- */6060-extern void update_bad_sector_map(__u8 * buffer);6161-extern void ftape_extract_bad_sector_map(__u8 * buffer);6262-extern SectorMap ftape_get_bad_sector_entry(int segment_id);6363-extern __u8 *ftape_find_end_of_bsm_list(__u8 * address);6464-extern void ftape_init_bsm(void);6565-6666-#endif
-130
drivers/char/ftape/lowlevel/ftape-buffer.c
···11-/*22- * Copyright (C) 1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $2020- * $Revision: 1.3 $2121- * $Date: 1997/10/16 23:33:11 $2222- *2323- * This file contains the allocator/dealloctor for ftape's dynamic dma2424- * buffer.2525- */2626-2727-#include <linux/slab.h>2828-#include <linux/mm.h>2929-#include <linux/mman.h>3030-#include <asm/dma.h>3131-3232-#include <linux/ftape.h>3333-#include "../lowlevel/ftape-rw.h"3434-#include "../lowlevel/ftape-read.h"3535-#include "../lowlevel/ftape-tracing.h"3636-#include "../lowlevel/ftape-buffer.h"3737-3838-/* DMA'able memory allocation stuff.3939- */4040-4141-static inline void *dmaalloc(size_t size)4242-{4343- unsigned long addr;4444-4545- if (size == 0) {4646- return NULL;4747- }4848- addr = __get_dma_pages(GFP_KERNEL, get_order(size));4949- if (addr) {5050- struct page *page;5151-5252- for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)5353- SetPageReserved(page);5454- }5555- return (void *)addr;5656-}5757-5858-static inline void dmafree(void *addr, size_t size)5959-{6060- if (size > 0) {6161- struct page *page;6262-6363- for (page = virt_to_page((unsigned long)addr);6464- page < virt_to_page((unsigned long)addr+size); page++)6565- ClearPageReserved(page);6666- free_pages((unsigned long) addr, get_order(size));6767- }6868-}6969-7070-static int add_one_buffer(void)7171-{7272- TRACE_FUN(ft_t_flow);7373-7474- if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) {7575- TRACE_EXIT -ENOMEM;7676- }7777- ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL);7878- if (ft_buffer[ft_nr_buffers] == NULL) {7979- TRACE_EXIT -ENOMEM;8080- }8181- memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct));8282- ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE);8383- if (ft_buffer[ft_nr_buffers]->address == NULL) {8484- kfree(ft_buffer[ft_nr_buffers]);8585- ft_buffer[ft_nr_buffers] = NULL;8686- TRACE_EXIT -ENOMEM;8787- }8888- ft_nr_buffers ++;8989- TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p",9090- ft_nr_buffers,9191- ft_buffer[ft_nr_buffers-1],9292- ft_buffer[ft_nr_buffers-1]->address);9393- TRACE_EXIT 0;9494-}9595-9696-static void del_one_buffer(void)9797-{9898- TRACE_FUN(ft_t_flow);9999- if (ft_nr_buffers > 0) {100100- TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p",101101- ft_nr_buffers,102102- ft_buffer[ft_nr_buffers-1],103103- ft_buffer[ft_nr_buffers-1]->address);104104- ft_nr_buffers --;105105- dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE);106106- kfree(ft_buffer[ft_nr_buffers]);107107- ft_buffer[ft_nr_buffers] = NULL;108108- }109109- TRACE_EXIT;110110-}111111-112112-int ftape_set_nr_buffers(int cnt)113113-{114114- int delta = cnt - ft_nr_buffers;115115- TRACE_FUN(ft_t_flow);116116-117117- if (delta > 0) {118118- while (delta--) {119119- if (add_one_buffer() < 0) {120120- TRACE_EXIT -ENOMEM;121121- }122122- }123123- } else if (delta < 0) {124124- while (delta++) {125125- del_one_buffer();126126- }127127- }128128- ftape_zap_read_buffers();129129- TRACE_EXIT 0;130130-}
-32
drivers/char/ftape/lowlevel/ftape-buffer.h
···11-#ifndef _FTAPE_BUFFER_H22-#define _FTAPE_BUFFER_H33-44-/*55- * Copyright (C) 1997 Claus-Justus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:18:08 $2525- *2626- * This file contains the allocator/dealloctor for ftape's dynamic dma2727- * buffer.2828- */2929-3030-extern int ftape_set_nr_buffers(int cnt);3131-3232-#endif
-275
drivers/char/ftape/lowlevel/ftape-calibr.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven.33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.c,v $2020- * $Revision: 1.2 $2121- * $Date: 1997/10/05 19:18:08 $2222- *2323- * GP calibration routine for processor speed dependent2424- * functions.2525- */2626-2727-#include <linux/errno.h>2828-#include <linux/jiffies.h>2929-#include <asm/system.h>3030-#include <asm/io.h>3131-#if defined(__alpha__)3232-# include <asm/hwrpb.h>3333-#elif defined(__x86_64__)3434-# include <asm/msr.h>3535-# include <asm/timex.h>3636-#elif defined(__i386__)3737-# include <linux/timex.h>3838-#endif3939-#include <linux/ftape.h>4040-#include "../lowlevel/ftape-tracing.h"4141-#include "../lowlevel/ftape-calibr.h"4242-#include "../lowlevel/fdc-io.h"4343-4444-#undef DEBUG4545-4646-#if !defined(__alpha__) && !defined(__i386__) && !defined(__x86_64__)4747-# error Ftape is not implemented for this architecture!4848-#endif4949-5050-#if defined(__alpha__) || defined(__x86_64__)5151-static unsigned long ps_per_cycle = 0;5252-#endif5353-5454-static spinlock_t calibr_lock;5555-5656-/*5757- * Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is5858- * too slow for certain timeouts (and that clock doesn't even tick5959- * when interrupts are disabled). For that reason, the 8254 timer is6060- * used directly to implement fine-grained timeouts. However, on6161- * Alpha PCs, the 8254 is *not* used to implement the clock tick6262- * (which is 1024 Hz, normally) and the 8254 timer runs at some6363- * "random" frequency (it seems to run at 18Hz, but it's not safe to6464- * rely on this value). Instead, we use the Alpha's "rpcc"6565- * instruction to read cycle counts. As this is a 32 bit counter,6666- * it will overflow only once per 30 seconds (on a 200MHz machine),6767- * which is plenty.6868- */6969-7070-unsigned int ftape_timestamp(void)7171-{7272-#if defined(__alpha__)7373- unsigned long r;7474-7575- asm volatile ("rpcc %0" : "=r" (r));7676- return r;7777-#elif defined(__x86_64__)7878- unsigned long r;7979- rdtscl(r);8080- return r;8181-#elif defined(__i386__)8282-8383-/*8484- * Note that there is some time between counter underflowing and jiffies8585- * increasing, so the code below won't always give correct output.8686- * -Vojtech8787- */8888-8989- unsigned long flags;9090- __u16 lo;9191- __u16 hi;9292-9393- spin_lock_irqsave(&calibr_lock, flags);9494- outb_p(0x00, 0x43); /* latch the count ASAP */9595- lo = inb_p(0x40); /* read the latched count */9696- lo |= inb(0x40) << 8;9797- hi = jiffies;9898- spin_unlock_irqrestore(&calibr_lock, flags);9999- return ((hi + 1) * (unsigned int) LATCH) - lo; /* downcounter ! */100100-#endif101101-}102102-103103-static unsigned int short_ftape_timestamp(void)104104-{105105-#if defined(__alpha__) || defined(__x86_64__)106106- return ftape_timestamp();107107-#elif defined(__i386__)108108- unsigned int count;109109- unsigned long flags;110110-111111- spin_lock_irqsave(&calibr_lock, flags);112112- outb_p(0x00, 0x43); /* latch the count ASAP */113113- count = inb_p(0x40); /* read the latched count */114114- count |= inb(0x40) << 8;115115- spin_unlock_irqrestore(&calibr_lock, flags);116116- return (LATCH - count); /* normal: downcounter */117117-#endif118118-}119119-120120-static unsigned int diff(unsigned int t0, unsigned int t1)121121-{122122-#if defined(__alpha__) || defined(__x86_64__)123123- return (t1 - t0);124124-#elif defined(__i386__)125125- /*126126- * This is tricky: to work for both short and full ftape_timestamps127127- * we'll have to discriminate between these.128128- * If it _looks_ like short stamps with wrapping around we'll129129- * asume it are. This will generate a small error if it really130130- * was a (very large) delta from full ftape_timestamps.131131- */132132- return (t1 <= t0 && t0 <= LATCH) ? t1 + LATCH - t0 : t1 - t0;133133-#endif134134-}135135-136136-static unsigned int usecs(unsigned int count)137137-{138138-#if defined(__alpha__) || defined(__x86_64__)139139- return (ps_per_cycle * count) / 1000000UL;140140-#elif defined(__i386__)141141- return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);142142-#endif143143-}144144-145145-unsigned int ftape_timediff(unsigned int t0, unsigned int t1)146146-{147147- /*148148- * Calculate difference in usec for ftape_timestamp results t0 & t1.149149- * Note that on the i386 platform with short time-stamps, the150150- * maximum allowed timespan is 1/HZ or we'll lose ticks!151151- */152152- return usecs(diff(t0, t1));153153-}154154-155155-/* To get an indication of the I/O performance,156156- * measure the duration of the inb() function.157157- */158158-static void time_inb(void)159159-{160160- int i;161161- int t0, t1;162162- unsigned long flags;163163- int status;164164- TRACE_FUN(ft_t_any);165165-166166- spin_lock_irqsave(&calibr_lock, flags);167167- t0 = short_ftape_timestamp();168168- for (i = 0; i < 1000; ++i) {169169- status = inb(fdc.msr);170170- }171171- t1 = short_ftape_timestamp();172172- spin_unlock_irqrestore(&calibr_lock, flags);173173- TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1));174174- TRACE_EXIT;175175-}176176-177177-static void init_clock(void)178178-{179179- TRACE_FUN(ft_t_any);180180-181181-#if defined(__x86_64__)182182- ps_per_cycle = 1000000000UL / cpu_khz;183183-#elif defined(__alpha__)184184- extern struct hwrpb_struct *hwrpb;185185- ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;186186-#endif187187- TRACE_EXIT;188188-}189189-190190-/*191191- * Input: function taking int count as parameter.192192- * pointers to calculated calibration variables.193193- */194194-void ftape_calibrate(char *name,195195- void (*fun) (unsigned int), 196196- unsigned int *calibr_count, 197197- unsigned int *calibr_time)198198-{199199- static int first_time = 1;200200- int i;201201- unsigned int tc = 0;202202- unsigned int count;203203- unsigned int time;204204-#if defined(__i386__)205205- unsigned int old_tc = 0;206206- unsigned int old_count = 1;207207- unsigned int old_time = 1;208208-#endif209209- TRACE_FUN(ft_t_flow);210210-211211- if (first_time) { /* get idea of I/O performance */212212- init_clock();213213- time_inb();214214- first_time = 0;215215- }216216- /* value of timeout must be set so that on very slow systems217217- * it will give a time less than one jiffy, and on218218- * very fast systems it'll give reasonable precision.219219- */220220-221221- count = 40;222222- for (i = 0; i < 15; ++i) {223223- unsigned int t0;224224- unsigned int t1;225225- unsigned int once;226226- unsigned int multiple;227227- unsigned long flags;228228-229229- *calibr_count =230230- *calibr_time = count; /* set TC to 1 */231231- spin_lock_irqsave(&calibr_lock, flags);232232- fun(0); /* dummy, get code into cache */233233- t0 = short_ftape_timestamp();234234- fun(0); /* overhead + one test */235235- t1 = short_ftape_timestamp();236236- once = diff(t0, t1);237237- t0 = short_ftape_timestamp();238238- fun(count); /* overhead + count tests */239239- t1 = short_ftape_timestamp();240240- multiple = diff(t0, t1);241241- spin_unlock_irqrestore(&calibr_lock, flags);242242- time = ftape_timediff(0, multiple - once);243243- tc = (1000 * time) / (count - 1);244244- TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",245245- usecs(once), count - 1, usecs(multiple), tc);246246-#if defined(__alpha__) || defined(__x86_64__)247247- /*248248- * Increase the calibration count exponentially until the249249- * calibration time exceeds 100 ms.250250- */251251- if (time >= 100*1000) {252252- break;253253- }254254-#elif defined(__i386__)255255- /*256256- * increase the count until the resulting time nears 2/HZ,257257- * then the tc will drop sharply because we lose LATCH counts.258258- */259259- if (tc <= old_tc / 2) {260260- time = old_time;261261- count = old_count;262262- break;263263- }264264- old_tc = tc;265265- old_count = count;266266- old_time = time;267267-#endif268268- count *= 2;269269- }270270- *calibr_count = count - 1;271271- *calibr_time = time;272272- TRACE(ft_t_info, "TC for `%s()' = %d nsec (at %d counts)",273273- name, (1000 * *calibr_time) / *calibr_count, *calibr_count);274274- TRACE_EXIT;275275-}
-37
drivers/char/ftape/lowlevel/ftape-calibr.h
···11-#ifndef _FTAPE_CALIBR_H22-#define _FTAPE_CALIBR_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.h,v $2323- * $Revision: 1.1 $2424- * $Date: 1997/09/19 09:05:26 $2525- *2626- * This file contains a gp calibration routine for2727- * hardware dependent timeout functions.2828- */2929-3030-extern void ftape_calibrate(char *name,3131- void (*fun) (unsigned int),3232- unsigned int *calibr_count,3333- unsigned int *calibr_time);3434-extern unsigned int ftape_timestamp(void);3535-extern unsigned int ftape_timediff(unsigned int t0, unsigned int t1);3636-3737-#endif /* _FTAPE_CALIBR_H */
-896
drivers/char/ftape/lowlevel/ftape-ctl.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven,33- * 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.c,v $2121- * $Revision: 1.4 $2222- * $Date: 1997/11/11 14:37:44 $2323- *2424- * This file contains the non-read/write ftape functions for the2525- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.2626- */2727-2828-#include <linux/errno.h>2929-#include <linux/mm.h>3030-#include <linux/mman.h>3131-3232-#include <linux/ftape.h>3333-#include <linux/qic117.h>3434-#include <asm/uaccess.h>3535-#include <asm/io.h>3636-3737-/* ease porting between pre-2.4.x and later kernels */3838-#define vma_get_pgoff(v) ((v)->vm_pgoff)3939-4040-#include "../lowlevel/ftape-tracing.h"4141-#include "../lowlevel/ftape-io.h"4242-#include "../lowlevel/ftape-ctl.h"4343-#include "../lowlevel/ftape-write.h"4444-#include "../lowlevel/ftape-read.h"4545-#include "../lowlevel/ftape-rw.h"4646-#include "../lowlevel/ftape-bsm.h"4747-4848-/* Global vars.4949- */5050-ftape_info ftape_status = {5151-/* vendor information */5252- { 0, }, /* drive type */5353-/* data rates */5454- 500, /* used data rate */5555- 500, /* drive max rate */5656- 500, /* fdc max rate */5757-/* drive selection, either FTAPE_SEL_A/B/C/D */5858- -1, /* drive selection */5959-/* flags set after decode the drive and tape status */6060- 0, /* formatted */6161- 1, /* no tape */6262- 1, /* write protected */6363- 1, /* new tape */6464-/* values of last queried drive/tape status and error */6565- {{0,}}, /* last error code */6666- {{0,}}, /* drive status, configuration, tape status */6767-/* cartridge geometry */6868- 20, /* tracks_per_tape */6969- 102, /* segments_per_track */7070-/* location of header segments, etc. */7171- -1, /* used_header_segment */7272- -1, /* header_segment_1 */7373- -1, /* header_segment_2 */7474- -1, /* first_data_segment */7575- -1, /* last_data_segment */7676-/* the format code as stored in the header segment */7777- fmt_normal, /* format code */7878-/* the default for the qic std: unknown */7979- -1,8080-/* is tape running? */8181- idle, /* runner_state */8282-/* is tape reading/writing/verifying/formatting/deleting */8383- idle, /* driver state */8484-/* flags fatal hardware error */8585- 1, /* failure */8686-/* history record */8787- { 0, } /* history record */8888-};8989-9090-int ftape_segments_per_head = 1020;9191-int ftape_segments_per_cylinder = 4;9292-int ftape_init_drive_needed = 1; /* need to be global for ftape_reset_drive()9393- * in ftape-io.c9494- */9595-9696-/* Local vars.9797- */9898-static const vendor_struct vendors[] = QIC117_VENDORS;9999-static const wakeup_method methods[] = WAKEUP_METHODS;100100-101101-const ftape_info *ftape_get_status(void)102102-{103103-#if defined(STATUS_PARANOYA)104104- static ftape_info get_status;105105-106106- get_status = ftape_status;107107- return &get_status;108108-#else109109- return &ftape_status; /* maybe return only a copy of it to assure 110110- * read only access111111- */112112-#endif113113-}114114-115115-static int ftape_not_operational(int status)116116-{117117- /* return true if status indicates tape can not be used.118118- */119119- return ((status ^ QIC_STATUS_CARTRIDGE_PRESENT) &120120- (QIC_STATUS_ERROR |121121- QIC_STATUS_CARTRIDGE_PRESENT |122122- QIC_STATUS_NEW_CARTRIDGE));123123-}124124-125125-int ftape_seek_to_eot(void)126126-{127127- int status;128128- TRACE_FUN(ft_t_any);129129-130130- TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);131131- while ((status & QIC_STATUS_AT_EOT) == 0) {132132- if (ftape_not_operational(status)) {133133- TRACE_EXIT -EIO;134134- }135135- TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_FORWARD,136136- ftape_timeout.rewind,&status),);137137- }138138- TRACE_EXIT 0;139139-}140140-141141-int ftape_seek_to_bot(void)142142-{143143- int status;144144- TRACE_FUN(ft_t_any);145145-146146- TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);147147- while ((status & QIC_STATUS_AT_BOT) == 0) {148148- if (ftape_not_operational(status)) {149149- TRACE_EXIT -EIO;150150- }151151- TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_REVERSE,152152- ftape_timeout.rewind,&status),);153153- }154154- TRACE_EXIT 0;155155-}156156-157157-static int ftape_new_cartridge(void)158158-{159159- ft_location.track = -1; /* force seek on first access */160160- ftape_zap_read_buffers();161161- ftape_zap_write_buffers();162162- return 0;163163-}164164-165165-int ftape_abort_operation(void)166166-{167167- int result = 0;168168- int status;169169- TRACE_FUN(ft_t_flow);170170-171171- if (ft_runner_status == running) {172172- TRACE(ft_t_noise, "aborting runner, waiting");173173-174174- ft_runner_status = do_abort;175175- /* set timeout so that the tape will run to logical EOT176176- * if we missed the last sector and there are no queue pulses.177177- */178178- result = ftape_dumb_stop();179179- }180180- if (ft_runner_status != idle) {181181- if (ft_runner_status == do_abort) {182182- TRACE(ft_t_noise, "forcing runner abort");183183- }184184- TRACE(ft_t_noise, "stopping tape");185185- result = ftape_stop_tape(&status);186186- ft_location.known = 0;187187- ft_runner_status = idle;188188- }189189- ftape_reset_buffer();190190- ftape_zap_read_buffers();191191- ftape_set_state(idle);192192- TRACE_EXIT result;193193-}194194-195195-static int lookup_vendor_id(unsigned int vendor_id)196196-{197197- int i = 0;198198-199199- while (vendors[i].vendor_id != vendor_id) {200200- if (++i >= NR_ITEMS(vendors)) {201201- return -1;202202- }203203- }204204- return i;205205-}206206-207207-static void ftape_detach_drive(void)208208-{209209- TRACE_FUN(ft_t_any);210210-211211- TRACE(ft_t_flow, "disabling tape drive and fdc");212212- ftape_put_drive_to_sleep(ft_drive_type.wake_up);213213- fdc_catch_stray_interrupts(1); /* one always comes */214214- fdc_disable();215215- fdc_release_irq_and_dma();216216- fdc_release_regions();217217- TRACE_EXIT;218218-}219219-220220-static void clear_history(void)221221-{222222- ft_history.used = 0;223223- ft_history.id_am_errors =224224- ft_history.id_crc_errors =225225- ft_history.data_am_errors =226226- ft_history.data_crc_errors =227227- ft_history.overrun_errors =228228- ft_history.no_data_errors =229229- ft_history.retries =230230- ft_history.crc_errors =231231- ft_history.crc_failures =232232- ft_history.ecc_failures =233233- ft_history.corrected =234234- ft_history.defects =235235- ft_history.rewinds = 0;236236-}237237-238238-static int ftape_activate_drive(vendor_struct * drive_type)239239-{240240- int result = 0;241241- TRACE_FUN(ft_t_flow);242242-243243- /* If we already know the drive type, wake it up.244244- * Else try to find out what kind of drive is attached.245245- */246246- if (drive_type->wake_up != unknown_wake_up) {247247- TRACE(ft_t_flow, "enabling tape drive and fdc");248248- result = ftape_wakeup_drive(drive_type->wake_up);249249- if (result < 0) {250250- TRACE(ft_t_err, "known wakeup method failed");251251- }252252- } else {253253- wake_up_types method;254254- const ft_trace_t old_tracing = TRACE_LEVEL;255255- if (TRACE_LEVEL < ft_t_flow) {256256- SET_TRACE_LEVEL(ft_t_bug);257257- }258258-259259- /* Try to awaken the drive using all known methods.260260- * Lower tracing for a while.261261- */262262- for (method=no_wake_up; method < NR_ITEMS(methods); ++method) {263263- drive_type->wake_up = method;264264-#ifdef CONFIG_FT_TWO_DRIVES265265- /* Test setup for dual drive configuration.266266- * /dev/rft2 uses mountain wakeup267267- * /dev/rft3 uses colorado wakeup268268- * Other systems will use the normal scheme.269269- */270270- if ((ft_drive_sel < 2) ||271271- (ft_drive_sel == 2 && method == FT_WAKE_UP_1) ||272272- (ft_drive_sel == 3 && method == FT_WAKE_UP_2)) {273273- result=ftape_wakeup_drive(drive_type->wake_up);274274- } else {275275- result = -EIO;276276- }277277-#else278278- result = ftape_wakeup_drive(drive_type->wake_up);279279-#endif280280- if (result >= 0) {281281- TRACE(ft_t_warn, "drive wakeup method: %s",282282- methods[drive_type->wake_up].name);283283- break;284284- }285285- }286286- SET_TRACE_LEVEL(old_tracing);287287-288288- if (method >= NR_ITEMS(methods)) {289289- /* no response at all, cannot open this drive */290290- drive_type->wake_up = unknown_wake_up;291291- TRACE(ft_t_err, "no tape drive found !");292292- result = -ENODEV;293293- }294294- }295295- TRACE_EXIT result;296296-}297297-298298-static int ftape_get_drive_status(void)299299-{300300- int result;301301- int status;302302- TRACE_FUN(ft_t_flow);303303-304304- ft_no_tape = ft_write_protected = 0;305305- /* Tape drive is activated now.306306- * First clear error status if present.307307- */308308- do {309309- result = ftape_ready_wait(ftape_timeout.reset, &status);310310- if (result < 0) {311311- if (result == -ETIME) {312312- TRACE(ft_t_err, "ftape_ready_wait timeout");313313- } else if (result == -EINTR) {314314- TRACE(ft_t_err, "ftape_ready_wait aborted");315315- } else {316316- TRACE(ft_t_err, "ftape_ready_wait failed");317317- }318318- TRACE_EXIT -EIO;319319- }320320- /* Clear error condition (drive is ready !)321321- */322322- if (status & QIC_STATUS_ERROR) {323323- unsigned int error;324324- qic117_cmd_t command;325325-326326- TRACE(ft_t_err, "error status set");327327- result = ftape_report_error(&error, &command, 1);328328- if (result < 0) {329329- TRACE(ft_t_err,330330- "report_error_code failed: %d", result);331331- /* hope it's working next time */332332- ftape_reset_drive();333333- TRACE_EXIT -EIO;334334- } else if (error != 0) {335335- TRACE(ft_t_noise, "error code : %d", error);336336- TRACE(ft_t_noise, "error command: %d", command);337337- }338338- }339339- if (status & QIC_STATUS_NEW_CARTRIDGE) {340340- unsigned int error;341341- qic117_cmd_t command;342342- const ft_trace_t old_tracing = TRACE_LEVEL;343343- SET_TRACE_LEVEL(ft_t_bug);344344-345345- /* Undocumented feature: Must clear (not present!)346346- * error here or we'll fail later.347347- */348348- ftape_report_error(&error, &command, 1);349349-350350- SET_TRACE_LEVEL(old_tracing);351351- TRACE(ft_t_info, "status: new cartridge");352352- ft_new_tape = 1;353353- } else {354354- ft_new_tape = 0;355355- }356356- FT_SIGNAL_EXIT(_DONT_BLOCK);357357- } while (status & QIC_STATUS_ERROR);358358-359359- ft_no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT);360360- ft_write_protected = (status & QIC_STATUS_WRITE_PROTECT) != 0;361361- if (ft_no_tape) {362362- TRACE(ft_t_warn, "no cartridge present");363363- } else {364364- if (ft_write_protected) {365365- TRACE(ft_t_noise, "Write protected cartridge");366366- }367367- }368368- TRACE_EXIT 0;369369-}370370-371371-static void ftape_log_vendor_id(void)372372-{373373- int vendor_index;374374- TRACE_FUN(ft_t_flow);375375-376376- ftape_report_vendor_id(&ft_drive_type.vendor_id);377377- vendor_index = lookup_vendor_id(ft_drive_type.vendor_id);378378- if (ft_drive_type.vendor_id == UNKNOWN_VENDOR &&379379- ft_drive_type.wake_up == wake_up_colorado) {380380- vendor_index = 0;381381- /* hack to get rid of all this mail */382382- ft_drive_type.vendor_id = 0;383383- }384384- if (vendor_index < 0) {385385- /* Unknown vendor id, first time opening device. The386386- * drive_type remains set to type found at wakeup387387- * time, this will probably keep the driver operating388388- * for this new vendor. 389389- */390390- TRACE(ft_t_warn, "\n"391391- KERN_INFO "============ unknown vendor id ===========\n"392392- KERN_INFO "A new, yet unsupported tape drive is found\n"393393- KERN_INFO "Please report the following values:\n"394394- KERN_INFO " Vendor id : 0x%04x\n"395395- KERN_INFO " Wakeup method : %s\n"396396- KERN_INFO "And a description of your tape drive\n"397397- KERN_INFO "to "THE_FTAPE_MAINTAINER"\n"398398- KERN_INFO "==========================================",399399- ft_drive_type.vendor_id,400400- methods[ft_drive_type.wake_up].name);401401- ft_drive_type.speed = 0; /* unknown */402402- } else {403403- ft_drive_type.name = vendors[vendor_index].name;404404- ft_drive_type.speed = vendors[vendor_index].speed;405405- TRACE(ft_t_info, "tape drive type: %s", ft_drive_type.name);406406- /* scan all methods for this vendor_id in table */407407- while(ft_drive_type.wake_up != vendors[vendor_index].wake_up) {408408- if (vendor_index < NR_ITEMS(vendors) - 1 &&409409- vendors[vendor_index + 1].vendor_id 410410- == 411411- ft_drive_type.vendor_id) {412412- ++vendor_index;413413- } else {414414- break;415415- }416416- }417417- if (ft_drive_type.wake_up != vendors[vendor_index].wake_up) {418418- TRACE(ft_t_warn, "\n"419419- KERN_INFO "==========================================\n"420420- KERN_INFO "wakeup type mismatch:\n"421421- KERN_INFO "found: %s, expected: %s\n"422422- KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n"423423- KERN_INFO "==========================================",424424- methods[ft_drive_type.wake_up].name,425425- methods[vendors[vendor_index].wake_up].name);426426- }427427- }428428- TRACE_EXIT;429429-}430430-431431-void ftape_calc_timeouts(unsigned int qic_std,432432- unsigned int data_rate,433433- unsigned int tape_len)434434-{435435- int speed; /* deci-ips ! */436436- int ff_speed;437437- int length;438438- TRACE_FUN(ft_t_any);439439-440440- /* tape transport speed441441- * data rate: QIC-40 QIC-80 QIC-3010 QIC-3020442442- *443443- * 250 Kbps 25 ips n/a n/a n/a444444- * 500 Kbps 50 ips 34 ips 22.6 ips n/a445445- * 1 Mbps n/a 68 ips 45.2 ips 22.6 ips446446- * 2 Mbps n/a n/a n/a 45.2 ips447447- *448448- * fast tape transport speed is at least 68 ips.449449- */450450- switch (qic_std) {451451- case QIC_TAPE_QIC40:452452- speed = (data_rate == 250) ? 250 : 500;453453- break;454454- case QIC_TAPE_QIC80:455455- speed = (data_rate == 500) ? 340 : 680;456456- break;457457- case QIC_TAPE_QIC3010:458458- speed = (data_rate == 500) ? 226 : 452;459459- break;460460- case QIC_TAPE_QIC3020:461461- speed = (data_rate == 1000) ? 226 : 452;462462- break;463463- default:464464- TRACE(ft_t_bug, "Unknown qic_std (bug) ?");465465- speed = 500;466466- break;467467- }468468- if (ft_drive_type.speed == 0) {469469- unsigned long t0;470470- static int dt = 0; /* keep gcc from complaining */471471- static int first_time = 1;472472-473473- /* Measure the time it takes to wind to EOT and back to BOT.474474- * If the tape length is known, calculate the rewind speed.475475- * Else keep the time value for calculation of the rewind476476- * speed later on, when the length _is_ known.477477- * Ask for a report only when length and speed are both known.478478- */479479- if (first_time) {480480- ftape_seek_to_bot();481481- t0 = jiffies;482482- ftape_seek_to_eot();483483- ftape_seek_to_bot();484484- dt = (int) (((jiffies - t0) * FT_USPT) / 1000);485485- if (dt < 1) {486486- dt = 1; /* prevent div by zero on failures */487487- }488488- first_time = 0;489489- TRACE(ft_t_info,490490- "trying to determine seek timeout, got %d msec",491491- dt);492492- }493493- if (tape_len != 0) {494494- ft_drive_type.speed = 495495- (2 * 12 * tape_len * 1000) / dt;496496- TRACE(ft_t_warn, "\n"497497- KERN_INFO "==========================================\n"498498- KERN_INFO "drive type: %s\n"499499- KERN_INFO "delta time = %d ms, length = %d ft\n"500500- KERN_INFO "has a maximum tape speed of %d ips\n"501501- KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n"502502- KERN_INFO "==========================================",503503- ft_drive_type.name, dt, tape_len, 504504- ft_drive_type.speed);505505- }506506- }507507- /* Handle unknown length tapes as very long ones. We'll508508- * determine the actual length from a header segment later.509509- * This is normal for all modern (Wide,TR1/2/3) formats.510510- */511511- if (tape_len <= 0) {512512- TRACE(ft_t_noise,513513- "Unknown tape length, using maximal timeouts");514514- length = QIC_TOP_TAPE_LEN; /* use worst case values */515515- } else {516516- length = tape_len; /* use actual values */517517- }518518- if (ft_drive_type.speed == 0) {519519- ff_speed = speed; 520520- } else {521521- ff_speed = ft_drive_type.speed;522522- }523523- /* time to go from bot to eot at normal speed (data rate):524524- * time = (1+delta) * length (ft) * 12 (inch/ft) / speed (ips)525525- * delta = 10 % for seek speed, 20 % for rewind speed.526526- */527527- ftape_timeout.seek = (length * 132 * FT_SECOND) / speed;528528- ftape_timeout.rewind = (length * 144 * FT_SECOND) / (10 * ff_speed);529529- ftape_timeout.reset = 20 * FT_SECOND + ftape_timeout.rewind;530530- TRACE(ft_t_noise, "timeouts for speed = %d, length = %d\n"531531- KERN_INFO "seek timeout : %d sec\n"532532- KERN_INFO "rewind timeout: %d sec\n"533533- KERN_INFO "reset timeout : %d sec",534534- speed, length,535535- (ftape_timeout.seek + 500) / 1000,536536- (ftape_timeout.rewind + 500) / 1000,537537- (ftape_timeout.reset + 500) / 1000);538538- TRACE_EXIT;539539-}540540-541541-/* This function calibrates the datarate (i.e. determines the maximal542542- * usable data rate) and sets the global variable ft_qic_std to qic_std543543- *544544- */545545-int ftape_calibrate_data_rate(unsigned int qic_std)546546-{547547- int rate = ft_fdc_rate_limit;548548- int result;549549- TRACE_FUN(ft_t_flow);550550-551551- ft_qic_std = qic_std;552552-553553- if (ft_qic_std == -1) {554554- TRACE_ABORT(-EIO, ft_t_err,555555- "Unable to determine data rate if QIC standard is unknown");556556- }557557-558558- /* Select highest rate supported by both fdc and drive.559559- * Start with highest rate supported by the fdc.560560- */561561- while (fdc_set_data_rate(rate) < 0 && rate > 250) {562562- rate /= 2;563563- }564564- TRACE(ft_t_info,565565- "Highest FDC supported data rate: %d Kbps", rate);566566- ft_fdc_max_rate = rate;567567- do {568568- result = ftape_set_data_rate(rate, ft_qic_std);569569- } while (result == -EINVAL && (rate /= 2) > 250);570570- if (result < 0) {571571- TRACE_ABORT(-EIO, ft_t_err, "set datarate failed");572572- }573573- ft_data_rate = rate;574574- TRACE_EXIT 0;575575-}576576-577577-static int ftape_init_drive(void)578578-{579579- int status;580580- qic_model model;581581- unsigned int qic_std;582582- unsigned int data_rate;583583- TRACE_FUN(ft_t_flow);584584-585585- ftape_init_drive_needed = 0; /* don't retry if this fails ? */586586- TRACE_CATCH(ftape_report_raw_drive_status(&status),);587587- if (status & QIC_STATUS_CARTRIDGE_PRESENT) {588588- if (!(status & QIC_STATUS_AT_BOT)) {589589- /* Antique drives will get here after a soft reset,590590- * modern ones only if the driver is loaded when the591591- * tape wasn't rewound properly.592592- */593593- /* Tape should be at bot if new cartridge ! */594594- ftape_seek_to_bot();595595- }596596- if (!(status & QIC_STATUS_REFERENCED)) {597597- TRACE(ft_t_flow, "starting seek_load_point");598598- TRACE_CATCH(ftape_command_wait(QIC_SEEK_LOAD_POINT,599599- ftape_timeout.reset,600600- &status),);601601- }602602- }603603- ft_formatted = (status & QIC_STATUS_REFERENCED) != 0;604604- if (!ft_formatted) {605605- TRACE(ft_t_warn, "Warning: tape is not formatted !");606606- }607607-608608- /* report configuration aborts when ftape_tape_len == -1609609- * unknown qic_std is okay if not formatted.610610- */611611- TRACE_CATCH(ftape_report_configuration(&model,612612- &data_rate,613613- &qic_std,614614- &ftape_tape_len),);615615-616616- /* Maybe add the following to the /proc entry617617- */618618- TRACE(ft_t_info, "%s drive @ %d Kbps",619619- (model == prehistoric) ? "prehistoric" :620620- ((model == pre_qic117c) ? "pre QIC-117C" :621621- ((model == post_qic117b) ? "post QIC-117B" :622622- "post QIC-117D")), data_rate);623623-624624- if (ft_formatted) {625625- /* initialize ft_used_data_rate to maximum value 626626- * and set ft_qic_std627627- */628628- TRACE_CATCH(ftape_calibrate_data_rate(qic_std),);629629- if (ftape_tape_len == 0) {630630- TRACE(ft_t_info, "unknown length QIC-%s tape",631631- (ft_qic_std == QIC_TAPE_QIC40) ? "40" :632632- ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :633633- ((ft_qic_std == QIC_TAPE_QIC3010) 634634- ? "3010" : "3020")));635635- } else {636636- TRACE(ft_t_info, "%d ft. QIC-%s tape", ftape_tape_len,637637- (ft_qic_std == QIC_TAPE_QIC40) ? "40" :638638- ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :639639- ((ft_qic_std == QIC_TAPE_QIC3010)640640- ? "3010" : "3020")));641641- }642642- ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);643643- /* soft write-protect QIC-40/QIC-80 cartridges used with a644644- * Colorado T3000 drive. Buggy hardware!645645- */646646- if ((ft_drive_type.vendor_id == 0x011c6) &&647647- ((ft_qic_std == QIC_TAPE_QIC40 ||648648- ft_qic_std == QIC_TAPE_QIC80) &&649649- !ft_write_protected)) {650650- TRACE(ft_t_warn, "\n"651651- KERN_INFO "The famous Colorado T3000 bug:\n"652652- KERN_INFO "%s drives can't write QIC40 and QIC80\n"653653- KERN_INFO "cartridges but don't set the write-protect flag!",654654- ft_drive_type.name);655655- ft_write_protected = 1;656656- }657657- } else {658658- /* Doesn't make too much sense to set the data rate659659- * because we don't know what to use for the write660660- * precompensation.661661- * Need to do this again when formatting the cartridge.662662- */663663- ft_data_rate = data_rate;664664- ftape_calc_timeouts(QIC_TAPE_QIC40,665665- data_rate,666666- ftape_tape_len);667667- }668668- ftape_new_cartridge();669669- TRACE_EXIT 0;670670-}671671-672672-static void ftape_munmap(void)673673-{674674- int i;675675- TRACE_FUN(ft_t_flow);676676-677677- for (i = 0; i < ft_nr_buffers; i++) {678678- ft_buffer[i]->mmapped = 0;679679- }680680- TRACE_EXIT;681681-}682682-683683-/* Map the dma buffers into the virtual address range given by vma.684684- * We only check the caller doesn't map non-existent buffers. We685685- * don't check for multiple mappings.686686- */687687-int ftape_mmap(struct vm_area_struct *vma)688688-{689689- int num_buffers;690690- int i;691691- TRACE_FUN(ft_t_flow);692692-693693- if (ft_failure) {694694- TRACE_EXIT -ENODEV;695695- }696696- if (!(vma->vm_flags & (VM_READ|VM_WRITE))) {697697- TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access");698698- }699699- if (vma_get_pgoff(vma) != 0) {700700- TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0");701701- }702702- if ((vma->vm_end - vma->vm_start) % FT_BUFF_SIZE != 0) {703703- TRACE_ABORT(-EINVAL, ft_t_err,704704- "size = %ld, should be a multiple of %d",705705- vma->vm_end - vma->vm_start,706706- FT_BUFF_SIZE);707707- }708708- num_buffers = (vma->vm_end - vma->vm_start) / FT_BUFF_SIZE;709709- if (num_buffers > ft_nr_buffers) {710710- TRACE_ABORT(-EINVAL,711711- ft_t_err, "size = %ld, should be less than %d",712712- vma->vm_end - vma->vm_start,713713- ft_nr_buffers * FT_BUFF_SIZE);714714- }715715- if (ft_driver_state != idle) {716716- /* this also clears the buffer states 717717- */718718- ftape_abort_operation();719719- } else {720720- ftape_reset_buffer();721721- }722722- for (i = 0; i < num_buffers; i++) {723723- unsigned long pfn;724724-725725- pfn = virt_to_phys(ft_buffer[i]->address) >> PAGE_SHIFT;726726- TRACE_CATCH(remap_pfn_range(vma, vma->vm_start +727727- i * FT_BUFF_SIZE,728728- pfn,729729- FT_BUFF_SIZE,730730- vma->vm_page_prot),731731- _res = -EAGAIN);732732- TRACE(ft_t_noise, "remapped dma buffer @ %p to location @ %p",733733- ft_buffer[i]->address,734734- (void *)(vma->vm_start + i * FT_BUFF_SIZE));735735- }736736- for (i = 0; i < num_buffers; i++) {737737- memset(ft_buffer[i]->address, 0xAA, FT_BUFF_SIZE);738738- ft_buffer[i]->mmapped++;739739- } 740740- TRACE_EXIT 0;741741-}742742-743743-static void ftape_init_driver(void); /* forward declaration */744744-745745-/* OPEN routine called by kernel-interface code746746- */747747-int ftape_enable(int drive_selection)748748-{749749- TRACE_FUN(ft_t_any);750750-751751- if (ft_drive_sel == -1 || ft_drive_sel != drive_selection) {752752- /* Other selection than last time753753- */754754- ftape_init_driver();755755- }756756- ft_drive_sel = FTAPE_SEL(drive_selection);757757- ft_failure = 0;758758- TRACE_CATCH(fdc_init(),); /* init & detect fdc */759759- TRACE_CATCH(ftape_activate_drive(&ft_drive_type),760760- fdc_disable();761761- fdc_release_irq_and_dma();762762- fdc_release_regions());763763- TRACE_CATCH(ftape_get_drive_status(), ftape_detach_drive());764764- if (ft_drive_type.vendor_id == UNKNOWN_VENDOR) {765765- ftape_log_vendor_id();766766- }767767- if (ft_new_tape) {768768- ftape_init_drive_needed = 1;769769- }770770- if (!ft_no_tape && ftape_init_drive_needed) {771771- TRACE_CATCH(ftape_init_drive(), ftape_detach_drive());772772- }773773- ftape_munmap(); /* clear the mmap flag */774774- clear_history();775775- TRACE_EXIT 0;776776-}777777-778778-/* release routine called by the high level interface modules779779- * zftape or sftape.780780- */781781-void ftape_disable(void)782782-{783783- int i;784784- TRACE_FUN(ft_t_any);785785-786786- for (i = 0; i < ft_nr_buffers; i++) {787787- if (ft_buffer[i]->mmapped) {788788- TRACE(ft_t_noise, "first byte of buffer %d: 0x%02x",789789- i, *ft_buffer[i]->address);790790- }791791- }792792- if (sigtestsetmask(¤t->pending.signal, _DONT_BLOCK) && 793793- !(sigtestsetmask(¤t->pending.signal, _NEVER_BLOCK)) &&794794- ftape_tape_running) {795795- TRACE(ft_t_warn,796796- "Interrupted by fatal signal and tape still running");797797- ftape_dumb_stop();798798- ftape_abort_operation(); /* it's annoying */799799- } else {800800- ftape_set_state(idle);801801- }802802- ftape_detach_drive();803803- if (ft_history.used) {804804- TRACE(ft_t_info, "== Non-fatal errors this run: ==");805805- TRACE(ft_t_info, "fdc isr statistics:\n"806806- KERN_INFO " id_am_errors : %3d\n"807807- KERN_INFO " id_crc_errors : %3d\n"808808- KERN_INFO " data_am_errors : %3d\n"809809- KERN_INFO " data_crc_errors : %3d\n"810810- KERN_INFO " overrun_errors : %3d\n"811811- KERN_INFO " no_data_errors : %3d\n"812812- KERN_INFO " retries : %3d",813813- ft_history.id_am_errors, ft_history.id_crc_errors,814814- ft_history.data_am_errors, ft_history.data_crc_errors,815815- ft_history.overrun_errors, ft_history.no_data_errors,816816- ft_history.retries);817817- if (ft_history.used & 1) {818818- TRACE(ft_t_info, "ecc statistics:\n"819819- KERN_INFO " crc_errors : %3d\n"820820- KERN_INFO " crc_failures : %3d\n"821821- KERN_INFO " ecc_failures : %3d\n"822822- KERN_INFO " sectors corrected: %3d",823823- ft_history.crc_errors, ft_history.crc_failures,824824- ft_history.ecc_failures, ft_history.corrected);825825- }826826- if (ft_history.defects > 0) {827827- TRACE(ft_t_warn, "Warning: %d media defects!",828828- ft_history.defects);829829- }830830- if (ft_history.rewinds > 0) {831831- TRACE(ft_t_info, "tape motion statistics:\n"832832- KERN_INFO "repositions : %3d",833833- ft_history.rewinds);834834- }835835- }836836- ft_failure = 1;837837- TRACE_EXIT;838838-}839839-840840-static void ftape_init_driver(void)841841-{842842- TRACE_FUN(ft_t_flow);843843-844844- ft_drive_type.vendor_id = UNKNOWN_VENDOR;845845- ft_drive_type.speed = 0;846846- ft_drive_type.wake_up = unknown_wake_up;847847- ft_drive_type.name = "Unknown";848848-849849- ftape_timeout.seek = 650 * FT_SECOND;850850- ftape_timeout.reset = 670 * FT_SECOND;851851- ftape_timeout.rewind = 650 * FT_SECOND;852852- ftape_timeout.head_seek = 15 * FT_SECOND;853853- ftape_timeout.stop = 5 * FT_SECOND;854854- ftape_timeout.pause = 16 * FT_SECOND;855855-856856- ft_qic_std = -1;857857- ftape_tape_len = 0; /* unknown */858858- ftape_current_command = 0;859859- ftape_current_cylinder = -1;860860-861861- ft_segments_per_track = 102;862862- ftape_segments_per_head = 1020;863863- ftape_segments_per_cylinder = 4;864864- ft_tracks_per_tape = 20;865865-866866- ft_failure = 1;867867-868868- ft_formatted = 0;869869- ft_no_tape = 1;870870- ft_write_protected = 1;871871- ft_new_tape = 1;872872-873873- ft_driver_state = idle;874874-875875- ft_data_rate = 876876- ft_fdc_max_rate = 500;877877- ft_drive_max_rate = 0; /* triggers set_rate_test() */878878-879879- ftape_init_drive_needed = 1;880880-881881- ft_header_segment_1 = -1;882882- ft_header_segment_2 = -1;883883- ft_used_header_segment = -1;884884- ft_first_data_segment = -1;885885- ft_last_data_segment = -1;886886-887887- ft_location.track = -1;888888- ft_location.known = 0;889889-890890- ftape_tape_running = 0;891891- ftape_might_be_off_track = 1;892892-893893- ftape_new_cartridge(); /* init some tape related variables */894894- ftape_init_bsm();895895- TRACE_EXIT;896896-}
-162
drivers/char/ftape/lowlevel/ftape-ctl.h
···11-#ifndef _FTAPE_CTL_H22-#define _FTAPE_CTL_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:09 $2626- *2727- * This file contains the non-standard IOCTL related definitions2828- * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for2929- * Linux.3030- */3131-3232-#include <linux/ioctl.h>3333-#include <linux/mtio.h>3434-#include <linux/ftape-vendors.h>3535-3636-#include "../lowlevel/ftape-rw.h"3737-#include <linux/ftape-header-segment.h>3838-3939-typedef struct {4040- int used; /* any reading or writing done */4141- /* isr statistics */4242- unsigned int id_am_errors; /* id address mark not found */4343- unsigned int id_crc_errors; /* crc error in id address mark */4444- unsigned int data_am_errors; /* data address mark not found */4545- unsigned int data_crc_errors; /* crc error in data field */4646- unsigned int overrun_errors; /* fdc access timing problem */4747- unsigned int no_data_errors; /* sector not found */4848- unsigned int retries; /* number of tape retries */4949- /* ecc statistics */5050- unsigned int crc_errors; /* crc error in data */5151- unsigned int crc_failures; /* bad data without crc error */5252- unsigned int ecc_failures; /* failed to correct */5353- unsigned int corrected; /* total sectors corrected */5454- /* general statistics */5555- unsigned int rewinds; /* number of tape rewinds */5656- unsigned int defects; /* bad sectors due to media defects */5757-} history_record;5858-5959-/* this structure contains * ALL * information that we want6060- * our child modules to know about, but don't want them to6161- * modify. 6262- */6363-typedef struct {6464- /* vendor information */6565- vendor_struct fti_drive_type;6666- /* data rates */6767- unsigned int fti_used_data_rate;6868- unsigned int fti_drive_max_rate;6969- unsigned int fti_fdc_max_rate;7070- /* drive selection, either FTAPE_SEL_A/B/C/D */7171- int fti_drive_sel; 7272- /* flags set after decode the drive and tape status */7373- unsigned int fti_formatted :1;7474- unsigned int fti_no_tape :1;7575- unsigned int fti_write_protected:1;7676- unsigned int fti_new_tape :1;7777- /* values of last queried drive/tape status and error */7878- ft_drive_error fti_last_error;7979- ft_drive_status fti_last_status;8080- /* cartridge geometry */8181- unsigned int fti_tracks_per_tape;8282- unsigned int fti_segments_per_track;8383- /* location of header segments, etc. */8484- int fti_used_header_segment;8585- int fti_header_segment_1;8686- int fti_header_segment_2;8787- int fti_first_data_segment;8888- int fti_last_data_segment;8989- /* the format code as stored in the header segment */9090- ft_format_type fti_format_code;9191- /* the following is the sole reason for the ftape_set_status() call */9292- unsigned int fti_qic_std;9393- /* is tape running? */9494- volatile enum runner_status_enum fti_runner_status;9595- /* is tape reading/writing/verifying/formatting/deleting */9696- buffer_state_enum fti_state;9797- /* flags fatal hardware error */9898- unsigned int fti_failure:1;9999- /* history record */100100- history_record fti_history;101101-} ftape_info;102102-103103-/* vendor information */104104-#define ft_drive_type ftape_status.fti_drive_type105105-/* data rates */106106-#define ft_data_rate ftape_status.fti_used_data_rate107107-#define ft_drive_max_rate ftape_status.fti_drive_max_rate108108-#define ft_fdc_max_rate ftape_status.fti_fdc_max_rate109109-/* drive selection, either FTAPE_SEL_A/B/C/D */110110-#define ft_drive_sel ftape_status.fti_drive_sel111111-/* flags set after decode the drive and tape status */112112-#define ft_formatted ftape_status.fti_formatted113113-#define ft_no_tape ftape_status.fti_no_tape114114-#define ft_write_protected ftape_status.fti_write_protected115115-#define ft_new_tape ftape_status.fti_new_tape116116-/* values of last queried drive/tape status and error */117117-#define ft_last_error ftape_status.fti_last_error118118-#define ft_last_status ftape_status.fti_last_status119119-/* cartridge geometry */120120-#define ft_tracks_per_tape ftape_status.fti_tracks_per_tape121121-#define ft_segments_per_track ftape_status.fti_segments_per_track122122-/* the format code as stored in the header segment */123123-#define ft_format_code ftape_status.fti_format_code124124-/* the qic status as returned by report drive configuration */125125-#define ft_qic_std ftape_status.fti_qic_std126126-#define ft_used_header_segment ftape_status.fti_used_header_segment127127-#define ft_header_segment_1 ftape_status.fti_header_segment_1128128-#define ft_header_segment_2 ftape_status.fti_header_segment_2129129-#define ft_first_data_segment ftape_status.fti_first_data_segment130130-#define ft_last_data_segment ftape_status.fti_last_data_segment131131-/* is tape running? */132132-#define ft_runner_status ftape_status.fti_runner_status133133-/* is tape reading/writing/verifying/formatting/deleting */134134-#define ft_driver_state ftape_status.fti_state135135-/* flags fatal hardware error */136136-#define ft_failure ftape_status.fti_failure137137-/* history record */138138-#define ft_history ftape_status.fti_history139139-140140-/*141141- * ftape-ctl.c defined global vars.142142- */143143-extern ftape_info ftape_status;144144-extern int ftape_segments_per_head;145145-extern int ftape_segments_per_cylinder;146146-extern int ftape_init_drive_needed;147147-148148-/*149149- * ftape-ctl.c defined global functions.150150- */151151-extern int ftape_mmap(struct vm_area_struct *vma);152152-extern int ftape_enable(int drive_selection);153153-extern void ftape_disable(void);154154-extern int ftape_seek_to_bot(void);155155-extern int ftape_seek_to_eot(void);156156-extern int ftape_abort_operation(void);157157-extern void ftape_calc_timeouts(unsigned int qic_std,158158- unsigned int data_rate,159159- unsigned int tape_len);160160-extern int ftape_calibrate_data_rate(unsigned int qic_std);161161-extern const ftape_info *ftape_get_status(void);162162-#endif
-853
drivers/char/ftape/lowlevel/ftape-ecc.c
···11-/*22- *33- * Copyright (c) 1993 Ning and David Mosberger.44-55- This is based on code originally written by Bas Laarhoven (bas@vimec.nl)66- and David L. Brown, Jr., and incorporates improvements suggested by77- Kai Harrekilde-Petersen.88-99- This program is free software; you can redistribute it and/or1010- modify it under the terms of the GNU General Public License as1111- published by the Free Software Foundation; either version 2, or (at1212- your option) any later version.1313-1414- This program is distributed in the hope that it will be useful, but1515- WITHOUT ANY WARRANTY; without even the implied warranty of1616- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1717- General Public License for more details.1818-1919- You should have received a copy of the GNU General Public License2020- along with this program; see the file COPYING. If not, write to2121- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,2222- USA.2323-2424- *2525- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.c,v $2626- * $Revision: 1.3 $2727- * $Date: 1997/10/05 19:18:10 $2828- *2929- * This file contains the Reed-Solomon error correction code 3030- * for the QIC-40/80 floppy-tape driver for Linux.3131- */3232-3333-#include <linux/ftape.h>3434-3535-#include "../lowlevel/ftape-tracing.h"3636-#include "../lowlevel/ftape-ecc.h"3737-3838-/* Machines that are big-endian should define macro BIG_ENDIAN.3939- * Unfortunately, there doesn't appear to be a standard include file4040- * that works for all OSs.4141- */4242-4343-#if defined(__sparc__) || defined(__hppa)4444-#define BIG_ENDIAN4545-#endif /* __sparc__ || __hppa */4646-4747-#if defined(__mips__)4848-#error Find a smart way to determine the Endianness of the MIPS CPU4949-#endif5050-5151-/* Notice: to minimize the potential for confusion, we use r to5252- * denote the independent variable of the polynomials in the5353- * Galois Field GF(2^8). We reserve x for polynomials that5454- * that have coefficients in GF(2^8).5555- * 5656- * The Galois Field in which coefficient arithmetic is performed are5757- * the polynomials over Z_2 (i.e., 0 and 1) modulo the irreducible5858- * polynomial f(r), where f(r)=r^8 + r^7 + r^2 + r + 1. A polynomial5959- * is represented as a byte with the MSB as the coefficient of r^7 and6060- * the LSB as the coefficient of r^0. For example, the binary6161- * representation of f(x) is 0x187 (of course, this doesn't fit into 86262- * bits). In this field, the polynomial r is a primitive element.6363- * That is, r^i with i in 0,...,255 enumerates all elements in the6464- * field.6565- *6666- * The generator polynomial for the QIC-80 ECC is6767- *6868- * g(x) = x^3 + r^105*x^2 + r^105*x + 16969- *7070- * which can be factored into:7171- *7272- * g(x) = (x-r^-1)(x-r^0)(x-r^1)7373- *7474- * the byte representation of the coefficients are:7575- *7676- * r^105 = 0xc07777- * r^-1 = 0xc37878- * r^0 = 0x017979- * r^1 = 0x028080- *8181- * Notice that r^-1 = r^254 as exponent arithmetic is performed8282- * modulo 2^8-1 = 255.8383- *8484- * For more information on Galois Fields and Reed-Solomon codes, refer8585- * to any good book. I found _An Introduction to Error Correcting8686- * Codes with Applications_ by S. A. Vanstone and P. C. van Oorschot8787- * to be a good introduction into the former. _CODING THEORY: The8888- * Essentials_ I found very useful for its concise description of8989- * Reed-Solomon encoding/decoding.9090- *9191- */9292-9393-typedef __u8 Matrix[3][3];9494-9595-/*9696- * gfpow[] is defined such that gfpow[i] returns r^i if9797- * i is in the range [0..255].9898- */9999-static const __u8 gfpow[] =100100-{101101- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,102102- 0x87, 0x89, 0x95, 0xad, 0xdd, 0x3d, 0x7a, 0xf4,103103- 0x6f, 0xde, 0x3b, 0x76, 0xec, 0x5f, 0xbe, 0xfb,104104- 0x71, 0xe2, 0x43, 0x86, 0x8b, 0x91, 0xa5, 0xcd,105105- 0x1d, 0x3a, 0x74, 0xe8, 0x57, 0xae, 0xdb, 0x31,106106- 0x62, 0xc4, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x67,107107- 0xce, 0x1b, 0x36, 0x6c, 0xd8, 0x37, 0x6e, 0xdc,108108- 0x3f, 0x7e, 0xfc, 0x7f, 0xfe, 0x7b, 0xf6, 0x6b,109109- 0xd6, 0x2b, 0x56, 0xac, 0xdf, 0x39, 0x72, 0xe4,110110- 0x4f, 0x9e, 0xbb, 0xf1, 0x65, 0xca, 0x13, 0x26,111111- 0x4c, 0x98, 0xb7, 0xe9, 0x55, 0xaa, 0xd3, 0x21,112112- 0x42, 0x84, 0x8f, 0x99, 0xb5, 0xed, 0x5d, 0xba,113113- 0xf3, 0x61, 0xc2, 0x03, 0x06, 0x0c, 0x18, 0x30,114114- 0x60, 0xc0, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0,115115- 0x47, 0x8e, 0x9b, 0xb1, 0xe5, 0x4d, 0x9a, 0xb3,116116- 0xe1, 0x45, 0x8a, 0x93, 0xa1, 0xc5, 0x0d, 0x1a,117117- 0x34, 0x68, 0xd0, 0x27, 0x4e, 0x9c, 0xbf, 0xf9,118118- 0x75, 0xea, 0x53, 0xa6, 0xcb, 0x11, 0x22, 0x44,119119- 0x88, 0x97, 0xa9, 0xd5, 0x2d, 0x5a, 0xb4, 0xef,120120- 0x59, 0xb2, 0xe3, 0x41, 0x82, 0x83, 0x81, 0x85,121121- 0x8d, 0x9d, 0xbd, 0xfd, 0x7d, 0xfa, 0x73, 0xe6,122122- 0x4b, 0x96, 0xab, 0xd1, 0x25, 0x4a, 0x94, 0xaf,123123- 0xd9, 0x35, 0x6a, 0xd4, 0x2f, 0x5e, 0xbc, 0xff,124124- 0x79, 0xf2, 0x63, 0xc6, 0x0b, 0x16, 0x2c, 0x58,125125- 0xb0, 0xe7, 0x49, 0x92, 0xa3, 0xc1, 0x05, 0x0a,126126- 0x14, 0x28, 0x50, 0xa0, 0xc7, 0x09, 0x12, 0x24,127127- 0x48, 0x90, 0xa7, 0xc9, 0x15, 0x2a, 0x54, 0xa8,128128- 0xd7, 0x29, 0x52, 0xa4, 0xcf, 0x19, 0x32, 0x64,129129- 0xc8, 0x17, 0x2e, 0x5c, 0xb8, 0xf7, 0x69, 0xd2,130130- 0x23, 0x46, 0x8c, 0x9f, 0xb9, 0xf5, 0x6d, 0xda,131131- 0x33, 0x66, 0xcc, 0x1f, 0x3e, 0x7c, 0xf8, 0x77,132132- 0xee, 0x5b, 0xb6, 0xeb, 0x51, 0xa2, 0xc3, 0x01133133-};134134-135135-/*136136- * This is a log table. That is, gflog[r^i] returns i (modulo f(r)).137137- * gflog[0] is undefined and the first element is therefore not valid.138138- */139139-static const __u8 gflog[256] =140140-{141141- 0xff, 0x00, 0x01, 0x63, 0x02, 0xc6, 0x64, 0x6a,142142- 0x03, 0xcd, 0xc7, 0xbc, 0x65, 0x7e, 0x6b, 0x2a,143143- 0x04, 0x8d, 0xce, 0x4e, 0xc8, 0xd4, 0xbd, 0xe1,144144- 0x66, 0xdd, 0x7f, 0x31, 0x6c, 0x20, 0x2b, 0xf3,145145- 0x05, 0x57, 0x8e, 0xe8, 0xcf, 0xac, 0x4f, 0x83,146146- 0xc9, 0xd9, 0xd5, 0x41, 0xbe, 0x94, 0xe2, 0xb4,147147- 0x67, 0x27, 0xde, 0xf0, 0x80, 0xb1, 0x32, 0x35,148148- 0x6d, 0x45, 0x21, 0x12, 0x2c, 0x0d, 0xf4, 0x38,149149- 0x06, 0x9b, 0x58, 0x1a, 0x8f, 0x79, 0xe9, 0x70,150150- 0xd0, 0xc2, 0xad, 0xa8, 0x50, 0x75, 0x84, 0x48,151151- 0xca, 0xfc, 0xda, 0x8a, 0xd6, 0x54, 0x42, 0x24,152152- 0xbf, 0x98, 0x95, 0xf9, 0xe3, 0x5e, 0xb5, 0x15,153153- 0x68, 0x61, 0x28, 0xba, 0xdf, 0x4c, 0xf1, 0x2f,154154- 0x81, 0xe6, 0xb2, 0x3f, 0x33, 0xee, 0x36, 0x10,155155- 0x6e, 0x18, 0x46, 0xa6, 0x22, 0x88, 0x13, 0xf7,156156- 0x2d, 0xb8, 0x0e, 0x3d, 0xf5, 0xa4, 0x39, 0x3b,157157- 0x07, 0x9e, 0x9c, 0x9d, 0x59, 0x9f, 0x1b, 0x08,158158- 0x90, 0x09, 0x7a, 0x1c, 0xea, 0xa0, 0x71, 0x5a,159159- 0xd1, 0x1d, 0xc3, 0x7b, 0xae, 0x0a, 0xa9, 0x91,160160- 0x51, 0x5b, 0x76, 0x72, 0x85, 0xa1, 0x49, 0xeb,161161- 0xcb, 0x7c, 0xfd, 0xc4, 0xdb, 0x1e, 0x8b, 0xd2,162162- 0xd7, 0x92, 0x55, 0xaa, 0x43, 0x0b, 0x25, 0xaf,163163- 0xc0, 0x73, 0x99, 0x77, 0x96, 0x5c, 0xfa, 0x52,164164- 0xe4, 0xec, 0x5f, 0x4a, 0xb6, 0xa2, 0x16, 0x86,165165- 0x69, 0xc5, 0x62, 0xfe, 0x29, 0x7d, 0xbb, 0xcc,166166- 0xe0, 0xd3, 0x4d, 0x8c, 0xf2, 0x1f, 0x30, 0xdc,167167- 0x82, 0xab, 0xe7, 0x56, 0xb3, 0x93, 0x40, 0xd8,168168- 0x34, 0xb0, 0xef, 0x26, 0x37, 0x0c, 0x11, 0x44,169169- 0x6f, 0x78, 0x19, 0x9a, 0x47, 0x74, 0xa7, 0xc1,170170- 0x23, 0x53, 0x89, 0xfb, 0x14, 0x5d, 0xf8, 0x97,171171- 0x2e, 0x4b, 0xb9, 0x60, 0x0f, 0xed, 0x3e, 0xe5,172172- 0xf6, 0x87, 0xa5, 0x17, 0x3a, 0xa3, 0x3c, 0xb7173173-};174174-175175-/* This is a multiplication table for the factor 0xc0 (i.e., r^105 (mod f(r)).176176- * gfmul_c0[f] returns r^105 * f(r) (modulo f(r)).177177- */178178-static const __u8 gfmul_c0[256] =179179-{180180- 0x00, 0xc0, 0x07, 0xc7, 0x0e, 0xce, 0x09, 0xc9,181181- 0x1c, 0xdc, 0x1b, 0xdb, 0x12, 0xd2, 0x15, 0xd5,182182- 0x38, 0xf8, 0x3f, 0xff, 0x36, 0xf6, 0x31, 0xf1,183183- 0x24, 0xe4, 0x23, 0xe3, 0x2a, 0xea, 0x2d, 0xed,184184- 0x70, 0xb0, 0x77, 0xb7, 0x7e, 0xbe, 0x79, 0xb9,185185- 0x6c, 0xac, 0x6b, 0xab, 0x62, 0xa2, 0x65, 0xa5,186186- 0x48, 0x88, 0x4f, 0x8f, 0x46, 0x86, 0x41, 0x81,187187- 0x54, 0x94, 0x53, 0x93, 0x5a, 0x9a, 0x5d, 0x9d,188188- 0xe0, 0x20, 0xe7, 0x27, 0xee, 0x2e, 0xe9, 0x29,189189- 0xfc, 0x3c, 0xfb, 0x3b, 0xf2, 0x32, 0xf5, 0x35,190190- 0xd8, 0x18, 0xdf, 0x1f, 0xd6, 0x16, 0xd1, 0x11,191191- 0xc4, 0x04, 0xc3, 0x03, 0xca, 0x0a, 0xcd, 0x0d,192192- 0x90, 0x50, 0x97, 0x57, 0x9e, 0x5e, 0x99, 0x59,193193- 0x8c, 0x4c, 0x8b, 0x4b, 0x82, 0x42, 0x85, 0x45,194194- 0xa8, 0x68, 0xaf, 0x6f, 0xa6, 0x66, 0xa1, 0x61,195195- 0xb4, 0x74, 0xb3, 0x73, 0xba, 0x7a, 0xbd, 0x7d,196196- 0x47, 0x87, 0x40, 0x80, 0x49, 0x89, 0x4e, 0x8e,197197- 0x5b, 0x9b, 0x5c, 0x9c, 0x55, 0x95, 0x52, 0x92,198198- 0x7f, 0xbf, 0x78, 0xb8, 0x71, 0xb1, 0x76, 0xb6,199199- 0x63, 0xa3, 0x64, 0xa4, 0x6d, 0xad, 0x6a, 0xaa,200200- 0x37, 0xf7, 0x30, 0xf0, 0x39, 0xf9, 0x3e, 0xfe,201201- 0x2b, 0xeb, 0x2c, 0xec, 0x25, 0xe5, 0x22, 0xe2,202202- 0x0f, 0xcf, 0x08, 0xc8, 0x01, 0xc1, 0x06, 0xc6,203203- 0x13, 0xd3, 0x14, 0xd4, 0x1d, 0xdd, 0x1a, 0xda,204204- 0xa7, 0x67, 0xa0, 0x60, 0xa9, 0x69, 0xae, 0x6e,205205- 0xbb, 0x7b, 0xbc, 0x7c, 0xb5, 0x75, 0xb2, 0x72,206206- 0x9f, 0x5f, 0x98, 0x58, 0x91, 0x51, 0x96, 0x56,207207- 0x83, 0x43, 0x84, 0x44, 0x8d, 0x4d, 0x8a, 0x4a,208208- 0xd7, 0x17, 0xd0, 0x10, 0xd9, 0x19, 0xde, 0x1e,209209- 0xcb, 0x0b, 0xcc, 0x0c, 0xc5, 0x05, 0xc2, 0x02,210210- 0xef, 0x2f, 0xe8, 0x28, 0xe1, 0x21, 0xe6, 0x26,211211- 0xf3, 0x33, 0xf4, 0x34, 0xfd, 0x3d, 0xfa, 0x3a212212-};213213-214214-215215-/* Returns V modulo 255 provided V is in the range -255,-254,...,509.216216- */217217-static inline __u8 mod255(int v)218218-{219219- if (v > 0) {220220- if (v < 255) {221221- return v;222222- } else {223223- return v - 255;224224- }225225- } else {226226- return v + 255;227227- }228228-}229229-230230-231231-/* Add two numbers in the field. Addition in this field is equivalent232232- * to a bit-wise exclusive OR operation---subtraction is therefore233233- * identical to addition.234234- */235235-static inline __u8 gfadd(__u8 a, __u8 b)236236-{237237- return a ^ b;238238-}239239-240240-241241-/* Add two vectors of numbers in the field. Each byte in A and B gets242242- * added individually.243243- */244244-static inline unsigned long gfadd_long(unsigned long a, unsigned long b)245245-{246246- return a ^ b;247247-}248248-249249-250250-/* Multiply two numbers in the field:251251- */252252-static inline __u8 gfmul(__u8 a, __u8 b)253253-{254254- if (a && b) {255255- return gfpow[mod255(gflog[a] + gflog[b])];256256- } else {257257- return 0;258258- }259259-}260260-261261-262262-/* Just like gfmul, except we have already looked up the log of the263263- * second number.264264- */265265-static inline __u8 gfmul_exp(__u8 a, int b)266266-{267267- if (a) {268268- return gfpow[mod255(gflog[a] + b)];269269- } else {270270- return 0;271271- }272272-}273273-274274-275275-/* Just like gfmul_exp, except that A is a vector of numbers. That276276- * is, each byte in A gets multiplied by gfpow[mod255(B)].277277- */278278-static inline unsigned long gfmul_exp_long(unsigned long a, int b)279279-{280280- __u8 t;281281-282282- if (sizeof(long) == 4) {283283- return (284284- ((t = (__u32)a >> 24 & 0xff) ?285285- (((__u32) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |286286- ((t = (__u32)a >> 16 & 0xff) ?287287- (((__u32) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |288288- ((t = (__u32)a >> 8 & 0xff) ?289289- (((__u32) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |290290- ((t = (__u32)a >> 0 & 0xff) ?291291- (((__u32) gfpow[mod255(gflog[t] + b)]) << 0) : 0));292292- } else if (sizeof(long) == 8) {293293- return (294294- ((t = (__u64)a >> 56 & 0xff) ?295295- (((__u64) gfpow[mod255(gflog[t] + b)]) << 56) : 0) |296296- ((t = (__u64)a >> 48 & 0xff) ?297297- (((__u64) gfpow[mod255(gflog[t] + b)]) << 48) : 0) |298298- ((t = (__u64)a >> 40 & 0xff) ?299299- (((__u64) gfpow[mod255(gflog[t] + b)]) << 40) : 0) |300300- ((t = (__u64)a >> 32 & 0xff) ?301301- (((__u64) gfpow[mod255(gflog[t] + b)]) << 32) : 0) |302302- ((t = (__u64)a >> 24 & 0xff) ?303303- (((__u64) gfpow[mod255(gflog[t] + b)]) << 24) : 0) |304304- ((t = (__u64)a >> 16 & 0xff) ?305305- (((__u64) gfpow[mod255(gflog[t] + b)]) << 16) : 0) |306306- ((t = (__u64)a >> 8 & 0xff) ?307307- (((__u64) gfpow[mod255(gflog[t] + b)]) << 8) : 0) |308308- ((t = (__u64)a >> 0 & 0xff) ?309309- (((__u64) gfpow[mod255(gflog[t] + b)]) << 0) : 0));310310- } else {311311- TRACE_FUN(ft_t_any);312312- TRACE_ABORT(-1, ft_t_err, "Error: size of long is %d bytes",313313- (int)sizeof(long));314314- }315315-}316316-317317-318318-/* Divide two numbers in the field. Returns a/b (modulo f(x)).319319- */320320-static inline __u8 gfdiv(__u8 a, __u8 b)321321-{322322- if (!b) {323323- TRACE_FUN(ft_t_any);324324- TRACE_ABORT(0xff, ft_t_bug, "Error: division by zero");325325- } else if (a == 0) {326326- return 0;327327- } else {328328- return gfpow[mod255(gflog[a] - gflog[b])];329329- }330330-}331331-332332-333333-/* The following functions return the inverse of the matrix of the334334- * linear system that needs to be solved to determine the error335335- * magnitudes. The first deals with matrices of rank 3, while the336336- * second deals with matrices of rank 2. The error indices are passed337337- * in arguments L0,..,L2 (0=first sector, 31=last sector). The error338338- * indices must be sorted in ascending order, i.e., L0<L1<L2.339339- *340340- * The linear system that needs to be solved for the error magnitudes341341- * is A * b = s, where s is the known vector of syndromes, b is the342342- * vector of error magnitudes and A in the ORDER=3 case:343343- *344344- * A_3 = {{1/r^L[0], 1/r^L[1], 1/r^L[2]},345345- * { 1, 1, 1},346346- * { r^L[0], r^L[1], r^L[2]}} 347347- */348348-static inline int gfinv3(__u8 l0,349349- __u8 l1, 350350- __u8 l2, 351351- Matrix Ainv)352352-{353353- __u8 det;354354- __u8 t20, t10, t21, t12, t01, t02;355355- int log_det;356356-357357- /* compute some intermediate results: */358358- t20 = gfpow[l2 - l0]; /* t20 = r^l2/r^l0 */359359- t10 = gfpow[l1 - l0]; /* t10 = r^l1/r^l0 */360360- t21 = gfpow[l2 - l1]; /* t21 = r^l2/r^l1 */361361- t12 = gfpow[l1 - l2 + 255]; /* t12 = r^l1/r^l2 */362362- t01 = gfpow[l0 - l1 + 255]; /* t01 = r^l0/r^l1 */363363- t02 = gfpow[l0 - l2 + 255]; /* t02 = r^l0/r^l2 */364364- /* Calculate the determinant of matrix A_3^-1 (sometimes365365- * called the Vandermonde determinant):366366- */367367- det = gfadd(t20, gfadd(t10, gfadd(t21, gfadd(t12, gfadd(t01, t02)))));368368- if (!det) {369369- TRACE_FUN(ft_t_any);370370- TRACE_ABORT(0, ft_t_err,371371- "Inversion failed (3 CRC errors, >0 CRC failures)");372372- }373373- log_det = 255 - gflog[det];374374-375375- /* Now, calculate all of the coefficients:376376- */377377- Ainv[0][0]= gfmul_exp(gfadd(gfpow[l1], gfpow[l2]), log_det);378378- Ainv[0][1]= gfmul_exp(gfadd(t21, t12), log_det);379379- Ainv[0][2]= gfmul_exp(gfadd(gfpow[255 - l1], gfpow[255 - l2]),log_det);380380-381381- Ainv[1][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l2]), log_det);382382- Ainv[1][1]= gfmul_exp(gfadd(t20, t02), log_det);383383- Ainv[1][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l2]),log_det);384384-385385- Ainv[2][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l1]), log_det);386386- Ainv[2][1]= gfmul_exp(gfadd(t10, t01), log_det);387387- Ainv[2][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l1]),log_det);388388-389389- return 1;390390-}391391-392392-393393-static inline int gfinv2(__u8 l0, __u8 l1, Matrix Ainv)394394-{395395- __u8 det;396396- __u8 t1, t2;397397- int log_det;398398-399399- t1 = gfpow[255 - l0];400400- t2 = gfpow[255 - l1];401401- det = gfadd(t1, t2);402402- if (!det) {403403- TRACE_FUN(ft_t_any);404404- TRACE_ABORT(0, ft_t_err,405405- "Inversion failed (2 CRC errors, >0 CRC failures)");406406- }407407- log_det = 255 - gflog[det];408408-409409- /* Now, calculate all of the coefficients:410410- */411411- Ainv[0][0] = Ainv[1][0] = gfpow[log_det];412412-413413- Ainv[0][1] = gfmul_exp(t2, log_det);414414- Ainv[1][1] = gfmul_exp(t1, log_det);415415-416416- return 1;417417-}418418-419419-420420-/* Multiply matrix A by vector S and return result in vector B. M is421421- * assumed to be of order NxN, S and B of order Nx1.422422- */423423-static inline void gfmat_mul(int n, Matrix A, 424424- __u8 *s, __u8 *b)425425-{426426- int i, j;427427- __u8 dot_prod;428428-429429- for (i = 0; i < n; ++i) {430430- dot_prod = 0;431431- for (j = 0; j < n; ++j) {432432- dot_prod = gfadd(dot_prod, gfmul(A[i][j], s[j]));433433- }434434- b[i] = dot_prod;435435- }436436-}437437-438438-439439-440440-/* The Reed Solomon ECC codes are computed over the N-th byte of each441441- * block, where N=SECTOR_SIZE. There are up to 29 blocks of data, and442442- * 3 blocks of ECC. The blocks are stored contiguously in memory. A443443- * segment, consequently, is assumed to have at least 4 blocks: one or444444- * more data blocks plus three ECC blocks.445445- *446446- * Notice: In QIC-80 speak, a CRC error is a sector with an incorrect447447- * CRC. A CRC failure is a sector with incorrect data, but448448- * a valid CRC. In the error control literature, the former449449- * is usually called "erasure", the latter "error."450450- */451451-/* Compute the parity bytes for C columns of data, where C is the452452- * number of bytes that fit into a long integer. We use a linear453453- * feed-back register to do this. The parity bytes P[0], P[STRIDE],454454- * P[2*STRIDE] are computed such that:455455- *456456- * x^k * p(x) + m(x) = 0 (modulo g(x))457457- *458458- * where k = NBLOCKS,459459- * p(x) = P[0] + P[STRIDE]*x + P[2*STRIDE]*x^2, and460460- * m(x) = sum_{i=0}^k m_i*x^i.461461- * m_i = DATA[i*SECTOR_SIZE]462462- */463463-static inline void set_parity(unsigned long *data,464464- int nblocks, 465465- unsigned long *p, 466466- int stride)467467-{468468- unsigned long p0, p1, p2, t1, t2, *end;469469-470470- end = data + nblocks * (FT_SECTOR_SIZE / sizeof(long));471471- p0 = p1 = p2 = 0;472472- while (data < end) {473473- /* The new parity bytes p0_i, p1_i, p2_i are computed474474- * from the old values p0_{i-1}, p1_{i-1}, p2_{i-1}475475- * recursively as:476476- *477477- * p0_i = p1_{i-1} + r^105 * (m_{i-1} - p0_{i-1})478478- * p1_i = p2_{i-1} + r^105 * (m_{i-1} - p0_{i-1})479479- * p2_i = (m_{i-1} - p0_{i-1})480480- *481481- * With the initial condition: p0_0 = p1_0 = p2_0 = 0.482482- */483483- t1 = gfadd_long(*data, p0);484484- /*485485- * Multiply each byte in t1 by 0xc0:486486- */487487- if (sizeof(long) == 4) {488488- t2= (((__u32) gfmul_c0[(__u32)t1 >> 24 & 0xff]) << 24 |489489- ((__u32) gfmul_c0[(__u32)t1 >> 16 & 0xff]) << 16 |490490- ((__u32) gfmul_c0[(__u32)t1 >> 8 & 0xff]) << 8 |491491- ((__u32) gfmul_c0[(__u32)t1 >> 0 & 0xff]) << 0);492492- } else if (sizeof(long) == 8) {493493- t2= (((__u64) gfmul_c0[(__u64)t1 >> 56 & 0xff]) << 56 |494494- ((__u64) gfmul_c0[(__u64)t1 >> 48 & 0xff]) << 48 |495495- ((__u64) gfmul_c0[(__u64)t1 >> 40 & 0xff]) << 40 |496496- ((__u64) gfmul_c0[(__u64)t1 >> 32 & 0xff]) << 32 |497497- ((__u64) gfmul_c0[(__u64)t1 >> 24 & 0xff]) << 24 |498498- ((__u64) gfmul_c0[(__u64)t1 >> 16 & 0xff]) << 16 |499499- ((__u64) gfmul_c0[(__u64)t1 >> 8 & 0xff]) << 8 |500500- ((__u64) gfmul_c0[(__u64)t1 >> 0 & 0xff]) << 0);501501- } else {502502- TRACE_FUN(ft_t_any);503503- TRACE(ft_t_err, "Error: long is of size %d",504504- (int) sizeof(long));505505- TRACE_EXIT;506506- }507507- p0 = gfadd_long(t2, p1);508508- p1 = gfadd_long(t2, p2);509509- p2 = t1;510510- data += FT_SECTOR_SIZE / sizeof(long);511511- }512512- *p = p0;513513- p += stride;514514- *p = p1;515515- p += stride;516516- *p = p2;517517- return;518518-}519519-520520-521521-/* Compute the 3 syndrome values. DATA should point to the first byte522522- * of the column for which the syndromes are desired. The syndromes523523- * are computed over the first NBLOCKS of rows. The three bytes will524524- * be placed in S[0], S[1], and S[2].525525- *526526- * S[i] is the value of the "message" polynomial m(x) evaluated at the527527- * i-th root of the generator polynomial g(x).528528- *529529- * As g(x)=(x-r^-1)(x-1)(x-r^1) we evaluate the message polynomial at530530- * x=r^-1 to get S[0], at x=r^0=1 to get S[1], and at x=r to get S[2].531531- * This could be done directly and efficiently via the Horner scheme.532532- * However, it would require multiplication tables for the factors533533- * r^-1 (0xc3) and r (0x02). The following scheme does not require534534- * any multiplication tables beyond what's needed for set_parity()535535- * anyway and is slightly faster if there are no errors and slightly536536- * slower if there are errors. The latter is hopefully the infrequent537537- * case.538538- *539539- * To understand the alternative algorithm, notice that set_parity(m,540540- * k, p) computes parity bytes such that:541541- *542542- * x^k * p(x) = m(x) (modulo g(x)).543543- *544544- * That is, to evaluate m(r^m), where r^m is a root of g(x), we can545545- * simply evaluate (r^m)^k*p(r^m). Also, notice that p is 0 if and546546- * only if s is zero. That is, if all parity bytes are 0, we know547547- * there is no error in the data and consequently there is no need to548548- * compute s(x) at all! In all other cases, we compute s(x) from p(x)549549- * by evaluating (r^m)^k*p(r^m) for m=-1, m=0, and m=1. The p(x)550550- * polynomial is evaluated via the Horner scheme.551551- */552552-static int compute_syndromes(unsigned long *data, int nblocks, unsigned long *s)553553-{554554- unsigned long p[3];555555-556556- set_parity(data, nblocks, p, 1);557557- if (p[0] | p[1] | p[2]) {558558- /* Some of the checked columns do not have a zero559559- * syndrome. For simplicity, we compute the syndromes560560- * for all columns that we have computed the561561- * remainders for.562562- */563563- s[0] = gfmul_exp_long(564564- gfadd_long(p[0], 565565- gfmul_exp_long(566566- gfadd_long(p[1], 567567- gfmul_exp_long(p[2], -1)),568568- -1)), 569569- -nblocks);570570- s[1] = gfadd_long(gfadd_long(p[2], p[1]), p[0]);571571- s[2] = gfmul_exp_long(572572- gfadd_long(p[0], 573573- gfmul_exp_long(574574- gfadd_long(p[1],575575- gfmul_exp_long(p[2], 1)),576576- 1)),577577- nblocks);578578- return 0;579579- } else {580580- return 1;581581- }582582-}583583-584584-585585-/* Correct the block in the column pointed to by DATA. There are NBAD586586- * CRC errors and their indices are in BAD_LOC[0], up to587587- * BAD_LOC[NBAD-1]. If NBAD>1, Ainv holds the inverse of the matrix588588- * of the linear system that needs to be solved to determine the error589589- * magnitudes. S[0], S[1], and S[2] are the syndrome values. If row590590- * j gets corrected, then bit j will be set in CORRECTION_MAP.591591- */592592-static inline int correct_block(__u8 *data, int nblocks,593593- int nbad, int *bad_loc, Matrix Ainv,594594- __u8 *s,595595- SectorMap * correction_map)596596-{597597- int ncorrected = 0;598598- int i;599599- __u8 t1, t2;600600- __u8 c0, c1, c2; /* check bytes */601601- __u8 error_mag[3], log_error_mag;602602- __u8 *dp, l, e;603603- TRACE_FUN(ft_t_any);604604-605605- switch (nbad) {606606- case 0:607607- /* might have a CRC failure: */608608- if (s[0] == 0) {609609- /* more than one error */610610- TRACE_ABORT(-1, ft_t_err,611611- "ECC failed (0 CRC errors, >1 CRC failures)");612612- }613613- t1 = gfdiv(s[1], s[0]);614614- if ((bad_loc[nbad++] = gflog[t1]) >= nblocks) {615615- TRACE(ft_t_err,616616- "ECC failed (0 CRC errors, >1 CRC failures)");617617- TRACE_ABORT(-1, ft_t_err,618618- "attempt to correct data at %d", bad_loc[0]);619619- }620620- error_mag[0] = s[1];621621- break;622622- case 1:623623- t1 = gfadd(gfmul_exp(s[1], bad_loc[0]), s[2]);624624- t2 = gfadd(gfmul_exp(s[0], bad_loc[0]), s[1]);625625- if (t1 == 0 && t2 == 0) {626626- /* one erasure, no error: */627627- Ainv[0][0] = gfpow[bad_loc[0]];628628- } else if (t1 == 0 || t2 == 0) {629629- /* one erasure and more than one error: */630630- TRACE_ABORT(-1, ft_t_err,631631- "ECC failed (1 erasure, >1 error)");632632- } else {633633- /* one erasure, one error: */634634- if ((bad_loc[nbad++] = gflog[gfdiv(t1, t2)]) 635635- >= nblocks) {636636- TRACE(ft_t_err, "ECC failed "637637- "(1 CRC errors, >1 CRC failures)");638638- TRACE_ABORT(-1, ft_t_err,639639- "attempt to correct data at %d",640640- bad_loc[1]);641641- }642642- if (!gfinv2(bad_loc[0], bad_loc[1], Ainv)) {643643- /* inversion failed---must have more644644- * than one error 645645- */646646- TRACE_EXIT -1;647647- }648648- }649649- /* FALL THROUGH TO ERROR MAGNITUDE COMPUTATION:650650- */651651- case 2:652652- case 3:653653- /* compute error magnitudes: */654654- gfmat_mul(nbad, Ainv, s, error_mag);655655- break;656656-657657- default:658658- TRACE_ABORT(-1, ft_t_err,659659- "Internal Error: number of CRC errors > 3");660660- }661661-662662- /* Perform correction by adding ERROR_MAG[i] to the byte at663663- * offset BAD_LOC[i]. Also add the value of the computed664664- * error polynomial to the syndrome values. If the correction665665- * was successful, the resulting check bytes should be zero666666- * (i.e., the corrected data is a valid code word).667667- */668668- c0 = s[0];669669- c1 = s[1];670670- c2 = s[2];671671- for (i = 0; i < nbad; ++i) {672672- e = error_mag[i];673673- if (e) {674674- /* correct the byte at offset L by magnitude E: */675675- l = bad_loc[i];676676- dp = &data[l * FT_SECTOR_SIZE];677677- *dp = gfadd(*dp, e);678678- *correction_map |= 1 << l;679679- ++ncorrected;680680-681681- log_error_mag = gflog[e];682682- c0 = gfadd(c0, gfpow[mod255(log_error_mag - l)]);683683- c1 = gfadd(c1, e);684684- c2 = gfadd(c2, gfpow[mod255(log_error_mag + l)]);685685- }686686- }687687- if (c0 || c1 || c2) {688688- TRACE_ABORT(-1, ft_t_err,689689- "ECC self-check failed, too many errors");690690- }691691- TRACE_EXIT ncorrected;692692-}693693-694694-695695-#if defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID)696696-697697-/* Perform a sanity check on the computed parity bytes:698698- */699699-static int sanity_check(unsigned long *data, int nblocks)700700-{701701- TRACE_FUN(ft_t_any);702702- unsigned long s[3];703703-704704- if (!compute_syndromes(data, nblocks, s)) {705705- TRACE_ABORT(0, ft_bug,706706- "Internal Error: syndrome self-check failed");707707- }708708- TRACE_EXIT 1;709709-}710710-711711-#endif /* defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID) */712712-713713-/* Compute the parity for an entire segment of data.714714- */715715-int ftape_ecc_set_segment_parity(struct memory_segment *mseg)716716-{717717- int i;718718- __u8 *parity_bytes;719719-720720- parity_bytes = &mseg->data[(mseg->blocks - 3) * FT_SECTOR_SIZE];721721- for (i = 0; i < FT_SECTOR_SIZE; i += sizeof(long)) {722722- set_parity((unsigned long *) &mseg->data[i], mseg->blocks - 3,723723- (unsigned long *) &parity_bytes[i],724724- FT_SECTOR_SIZE / sizeof(long));725725-#ifdef ECC_PARANOID726726- if (!sanity_check((unsigned long *) &mseg->data[i],727727- mseg->blocks)) {728728- return -1;729729- }730730-#endif /* ECC_PARANOID */731731- }732732- return 0;733733-}734734-735735-736736-/* Checks and corrects (if possible) the segment MSEG. Returns one of737737- * ECC_OK, ECC_CORRECTED, and ECC_FAILED.738738- */739739-int ftape_ecc_correct_data(struct memory_segment *mseg)740740-{741741- int col, i, result;742742- int ncorrected = 0;743743- int nerasures = 0; /* # of erasures (CRC errors) */744744- int erasure_loc[3]; /* erasure locations */745745- unsigned long ss[3];746746- __u8 s[3];747747- Matrix Ainv;748748- TRACE_FUN(ft_t_flow);749749-750750- mseg->corrected = 0;751751-752752- /* find first column that has non-zero syndromes: */753753- for (col = 0; col < FT_SECTOR_SIZE; col += sizeof(long)) {754754- if (!compute_syndromes((unsigned long *) &mseg->data[col],755755- mseg->blocks, ss)) {756756- /* something is wrong---have to fix things */757757- break;758758- }759759- }760760- if (col >= FT_SECTOR_SIZE) {761761- /* all syndromes are ok, therefore nothing to correct */762762- TRACE_EXIT ECC_OK;763763- }764764- /* count the number of CRC errors if there were any: */765765- if (mseg->read_bad) {766766- for (i = 0; i < mseg->blocks; i++) {767767- if (BAD_CHECK(mseg->read_bad, i)) {768768- if (nerasures >= 3) {769769- /* this is too much for ECC */770770- TRACE_ABORT(ECC_FAILED, ft_t_err,771771- "ECC failed (>3 CRC errors)");772772- } /* if */773773- erasure_loc[nerasures++] = i;774774- }775775- }776776- }777777- /*778778- * If there are at least 2 CRC errors, determine inverse of matrix779779- * of linear system to be solved:780780- */781781- switch (nerasures) {782782- case 2:783783- if (!gfinv2(erasure_loc[0], erasure_loc[1], Ainv)) {784784- TRACE_EXIT ECC_FAILED;785785- }786786- break;787787- case 3:788788- if (!gfinv3(erasure_loc[0], erasure_loc[1],789789- erasure_loc[2], Ainv)) {790790- TRACE_EXIT ECC_FAILED;791791- }792792- break;793793- default:794794- /* this is not an error condition... */795795- break;796796- }797797-798798- do {799799- for (i = 0; i < sizeof(long); ++i) {800800- s[0] = ss[0];801801- s[1] = ss[1];802802- s[2] = ss[2];803803- if (s[0] | s[1] | s[2]) {804804-#ifdef BIG_ENDIAN805805- result = correct_block(806806- &mseg->data[col + sizeof(long) - 1 - i],807807- mseg->blocks,808808- nerasures,809809- erasure_loc,810810- Ainv,811811- s,812812- &mseg->corrected);813813-#else814814- result = correct_block(&mseg->data[col + i],815815- mseg->blocks,816816- nerasures,817817- erasure_loc,818818- Ainv,819819- s,820820- &mseg->corrected);821821-#endif822822- if (result < 0) {823823- TRACE_EXIT ECC_FAILED;824824- }825825- ncorrected += result;826826- }827827- ss[0] >>= 8;828828- ss[1] >>= 8;829829- ss[2] >>= 8;830830- }831831-832832-#ifdef ECC_SANITY_CHECK833833- if (!sanity_check((unsigned long *) &mseg->data[col],834834- mseg->blocks)) {835835- TRACE_EXIT ECC_FAILED;836836- }837837-#endif /* ECC_SANITY_CHECK */838838-839839- /* find next column with non-zero syndromes: */840840- while ((col += sizeof(long)) < FT_SECTOR_SIZE) {841841- if (!compute_syndromes((unsigned long *)842842- &mseg->data[col], mseg->blocks, ss)) {843843- /* something is wrong---have to fix things */844844- break;845845- }846846- }847847- } while (col < FT_SECTOR_SIZE);848848- if (ncorrected && nerasures == 0) {849849- TRACE(ft_t_warn, "block contained error not caught by CRC");850850- }851851- TRACE((ncorrected > 0) ? ft_t_noise : ft_t_any, "number of corrections: %d", ncorrected);852852- TRACE_EXIT ncorrected ? ECC_CORRECTED : ECC_OK;853853-}
-84
drivers/char/ftape/lowlevel/ftape-ecc.h
···11-#ifndef _FTAPE_ECC_H_22-#define _FTAPE_ECC_H_33-44-/*55- * Copyright (C) 1993 Ning and David Mosberger.66- * Original:77- * Copyright (C) 1993 Bas Laarhoven.88- * Copyright (C) 1992 David L. Brown, Jr.99-1010- This program is free software; you can redistribute it and/or1111- modify it under the terms of the GNU General Public License as1212- published by the Free Software Foundation; either version 2, or (at1313- your option) any later version.1414-1515- This program is distributed in the hope that it will be useful, but1616- WITHOUT ANY WARRANTY; without even the implied warranty of1717- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1818- General Public License for more details.1919-2020- You should have received a copy of the GNU General Public License2121- along with this program; see the file COPYING. If not, write to2222- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,2323- USA.2424-2525- *2626- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.h,v $2727- * $Revision: 1.2 $2828- * $Date: 1997/10/05 19:18:11 $2929- *3030- * This file contains the definitions for the3131- * Reed-Solomon error correction code 3232- * for the QIC-40/80 tape streamer device driver.3333- */3434-3535-#include "../lowlevel/ftape-bsm.h"3636-3737-#define BAD_CLEAR(entry) ((entry)=0)3838-#define BAD_SET(entry,sector) ((entry)|=(1<<(sector)))3939-#define BAD_CHECK(entry,sector) ((entry)&(1<<(sector)))4040-4141-/*4242- * Return values for ecc_correct_data:4343- */4444-enum {4545- ECC_OK, /* Data was correct. */4646- ECC_CORRECTED, /* Correctable error in data. */4747- ECC_FAILED, /* Could not correct data. */4848-};4949-5050-/*5151- * Representation of an in memory segment. MARKED_BAD lists the5252- * sectors that were marked bad during formatting. If the N-th sector5353- * in a segment is marked bad, bit 1<<N will be set in MARKED_BAD.5454- * The sectors should be read in from the disk and packed, as if the5555- * bad sectors were not there, and the segment just contained fewer5656- * sectors. READ_SECTORS is a bitmap of errors encountered while5757- * reading the data. These offsets are relative to the packed data.5858- * BLOCKS is a count of the sectors not marked bad. This is just to5959- * prevent having to count the zero bits in MARKED_BAD each time this6060- * is needed. DATA is the actual sector packed data from (or to) the6161- * tape.6262- */6363- struct memory_segment {6464- SectorMap marked_bad;6565- SectorMap read_bad;6666- int blocks;6767- __u8 *data;6868- SectorMap corrected;6969- };7070-7171-/*7272- * ecc.c defined global variables:7373- */7474-#ifdef TEST7575-extern int ftape_ecc_tracing;7676-#endif7777-7878-/*7979- * ecc.c defined global functions:8080- */8181-extern int ftape_ecc_correct_data(struct memory_segment *data);8282-extern int ftape_ecc_set_segment_parity(struct memory_segment *data);8383-8484-#endif /* _FTAPE_ECC_H_ */
-344
drivers/char/ftape/lowlevel/ftape-format.c
···11-/*22- * Copyright (C) 1997 Claus-Justus Heine.33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.c,v $2020- * $Revision: 1.2.4.1 $2121- * $Date: 1997/11/14 16:05:39 $2222- *2323- * This file contains the code to support formatting of floppy2424- * tape cartridges with the QIC-40/80/3010/3020 floppy-tape2525- * driver "ftape" for Linux.2626- */2727-2828-#include <linux/string.h>2929-#include <linux/errno.h>3030-3131-#include <linux/ftape.h>3232-#include <linux/qic117.h>3333-#include "../lowlevel/ftape-tracing.h"3434-#include "../lowlevel/ftape-io.h"3535-#include "../lowlevel/ftape-ctl.h"3636-#include "../lowlevel/ftape-rw.h"3737-#include "../lowlevel/ftape-ecc.h"3838-#include "../lowlevel/ftape-bsm.h"3939-#include "../lowlevel/ftape-format.h"4040-4141-#if defined(TESTING)4242-#define FT_FMT_SEGS_PER_BUF 504343-#else4444-#define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT))4545-#endif4646-4747-static spinlock_t ftape_format_lock;4848-4949-/*5050- * first segment of the new buffer5151- */5252-static int switch_segment;5353-5454-/*5555- * at most 256 segments fit into one 32 kb buffer. Even TR-1 cartridges have5656- * more than this many segments per track, so better be careful.5757- *5858- * buffer_struct *buff: buffer to store the formatting coordinates in5959- * int start: starting segment for this buffer.6060- * int spt: segments per track6161- *6262- * Note: segment ids are relative to the start of the track here.6363- */6464-static void setup_format_buffer(buffer_struct *buff, int start, int spt,6565- __u8 gap3)6666-{6767- int to_do = spt - start;6868- TRACE_FUN(ft_t_flow);6969-7070- if (to_do > FT_FMT_SEGS_PER_BUF) {7171- to_do = FT_FMT_SEGS_PER_BUF;7272- }7373- buff->ptr = buff->address;7474- buff->remaining = to_do * FT_SECTORS_PER_SEGMENT; /* # sectors */7575- buff->bytes = buff->remaining * 4; /* need 4 bytes per sector */7676- buff->gap3 = gap3;7777- buff->segment_id = start;7878- buff->next_segment = start + to_do;7979- if (buff->next_segment >= spt) {8080- buff->next_segment = 0; /* 0 means: stop runner */8181- }8282- buff->status = waiting; /* tells the isr that it can use8383- * this buffer8484- */8585- TRACE_EXIT;8686-}8787-8888-8989-/*9090- * start formatting a new track.9191- */9292-int ftape_format_track(const unsigned int track, const __u8 gap3)9393-{9494- unsigned long flags;9595- buffer_struct *tail, *head;9696- int status;9797- TRACE_FUN(ft_t_flow);9898-9999- TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);100100- if (track & 1) {101101- if (!(status & QIC_STATUS_AT_EOT)) {102102- TRACE_CATCH(ftape_seek_to_eot(),);103103- }104104- } else {105105- if (!(status & QIC_STATUS_AT_BOT)) {106106- TRACE_CATCH(ftape_seek_to_bot(),);107107- }108108- }109109- ftape_abort_operation(); /* this sets ft_head = ft_tail = 0 */110110- ftape_set_state(formatting);111111-112112- TRACE(ft_t_noise,113113- "Formatting track %d, logical: from segment %d to %d",114114- track, track * ft_segments_per_track, 115115- (track + 1) * ft_segments_per_track - 1);116116-117117- /*118118- * initialize the buffer switching protocol for this track119119- */120120- head = ftape_get_buffer(ft_queue_head); /* tape isn't running yet */121121- tail = ftape_get_buffer(ft_queue_tail); /* tape isn't running yet */122122- switch_segment = 0;123123- do {124124- FT_SIGNAL_EXIT(_DONT_BLOCK);125125- setup_format_buffer(tail, switch_segment,126126- ft_segments_per_track, gap3);127127- switch_segment = tail->next_segment;128128- } while ((switch_segment != 0) &&129129- ((tail = ftape_next_buffer(ft_queue_tail)) != head));130130- /* go */131131- head->status = formatting;132132- TRACE_CATCH(ftape_seek_head_to_track(track),);133133- TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD),);134134- spin_lock_irqsave(&ftape_format_lock, flags);135135- TRACE_CATCH(fdc_setup_formatting(head), restore_flags(flags));136136- spin_unlock_irqrestore(&ftape_format_lock, flags);137137- TRACE_EXIT 0;138138-}139139-140140-/* return segment id of segment currently being formatted and do the141141- * buffer switching stuff.142142- */143143-int ftape_format_status(unsigned int *segment_id)144144-{145145- buffer_struct *tail = ftape_get_buffer(ft_queue_tail);146146- int result;147147- TRACE_FUN(ft_t_flow);148148-149149- while (switch_segment != 0 &&150150- ftape_get_buffer(ft_queue_head) != tail) {151151- FT_SIGNAL_EXIT(_DONT_BLOCK);152152- /* need more buffers, first wait for empty buffer153153- */154154- TRACE_CATCH(ftape_wait_segment(formatting),);155155- /* don't worry for gap3. If we ever hit this piece of code,156156- * then all buffer already have the correct gap3 set!157157- */158158- setup_format_buffer(tail, switch_segment,159159- ft_segments_per_track, tail->gap3);160160- switch_segment = tail->next_segment;161161- if (switch_segment != 0) {162162- tail = ftape_next_buffer(ft_queue_tail);163163- }164164- }165165- /* should runner stop ?166166- */167167- if (ft_runner_status == aborting || ft_runner_status == do_abort) {168168- buffer_struct *head = ftape_get_buffer(ft_queue_head);169169- TRACE(ft_t_warn, "Error formatting segment %d",170170- ftape_get_buffer(ft_queue_head)->segment_id);171171- (void)ftape_abort_operation();172172- TRACE_EXIT (head->status != error) ? -EAGAIN : -EIO;173173- }174174- /*175175- * don't care if the timer expires, this is just kind of a176176- * "select" operation that lets the calling process sleep177177- * until something has happened178178- */179179- if (fdc_interrupt_wait(5 * FT_SECOND) < 0) {180180- TRACE(ft_t_noise, "End of track %d at segment %d",181181- ft_location.track,182182- ftape_get_buffer(ft_queue_head)->segment_id);183183- result = 1; /* end of track, unlock module */184184- } else {185185- result = 0;186186- }187187- /*188188- * the calling process should use the seg id to determine189189- * which parts of the dma buffers can be safely overwritten190190- * with new data.191191- */192192- *segment_id = ftape_get_buffer(ft_queue_head)->segment_id;193193- /*194194- * Internally we start counting segment ids from the start of195195- * each track when formatting, but externally we keep them196196- * relative to the start of the tape:197197- */198198- *segment_id += ft_location.track * ft_segments_per_track;199199- TRACE_EXIT result;200200-}201201-202202-/*203203- * The segment id is relative to the start of the tape204204- */205205-int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm)206206-{207207- int result;208208- int verify_done = 0;209209- TRACE_FUN(ft_t_flow);210210-211211- TRACE(ft_t_noise, "Verifying segment %d", segment_id);212212-213213- if (ft_driver_state != verifying) {214214- TRACE(ft_t_noise, "calling ftape_abort_operation");215215- if (ftape_abort_operation() < 0) {216216- TRACE(ft_t_err, "ftape_abort_operation failed");217217- TRACE_EXIT -EIO;218218- }219219- }220220- *bsm = 0x00000000;221221- ftape_set_state(verifying);222222- for (;;) {223223- buffer_struct *tail;224224- /*225225- * Allow escape from this loop on signal226226- */227227- FT_SIGNAL_EXIT(_DONT_BLOCK);228228- /*229229- * Search all full buffers for the first matching the230230- * wanted segment. Clear other buffers on the fly.231231- */232232- tail = ftape_get_buffer(ft_queue_tail);233233- while (!verify_done && tail->status == done) {234234- /*235235- * Allow escape from this loop on signal !236236- */237237- FT_SIGNAL_EXIT(_DONT_BLOCK);238238- if (tail->segment_id == segment_id) {239239- /* If out buffer is already full,240240- * return its contents. 241241- */242242- TRACE(ft_t_flow, "found segment in cache: %d",243243- segment_id);244244- if ((tail->soft_error_map |245245- tail->hard_error_map) != 0) {246246- TRACE(ft_t_info,"bsm[%d] = 0x%08lx",247247- segment_id,248248- (unsigned long)249249- (tail->soft_error_map |250250- tail->hard_error_map));251251- *bsm = (tail->soft_error_map |252252- tail->hard_error_map);253253- }254254- verify_done = 1;255255- } else {256256- TRACE(ft_t_flow,"zapping segment in cache: %d",257257- tail->segment_id);258258- }259259- tail->status = waiting;260260- tail = ftape_next_buffer(ft_queue_tail);261261- }262262- if (!verify_done && tail->status == verifying) {263263- if (tail->segment_id == segment_id) {264264- switch(ftape_wait_segment(verifying)) {265265- case 0:266266- break;267267- case -EINTR:268268- TRACE_ABORT(-EINTR, ft_t_warn,269269- "interrupted by "270270- "non-blockable signal");271271- break;272272- default:273273- ftape_abort_operation();274274- ftape_set_state(verifying);275275- /* be picky */276276- TRACE_ABORT(-EIO, ft_t_warn,277277- "wait_segment failed");278278- }279279- } else {280280- /* We're reading the wrong segment,281281- * stop runner.282282- */283283- TRACE(ft_t_noise, "verifying wrong segment");284284- ftape_abort_operation();285285- ftape_set_state(verifying);286286- }287287- }288288- /* should runner stop ?289289- */290290- if (ft_runner_status == aborting) {291291- buffer_struct *head = ftape_get_buffer(ft_queue_head);292292- if (head->status == error ||293293- head->status == verifying) {294294- /* no data or overrun error */295295- head->status = waiting;296296- }297297- TRACE_CATCH(ftape_dumb_stop(),);298298- } else {299299- /* If just passed last segment on tape: wait300300- * for BOT or EOT mark. Sets ft_runner_status to301301- * idle if at lEOT and successful 302302- */303303- TRACE_CATCH(ftape_handle_logical_eot(),);304304- }305305- if (verify_done) {306306- TRACE_EXIT 0;307307- }308308- /* Now at least one buffer is idle!309309- * Restart runner & tape if needed.310310- */311311- /* We could optimize the following a little bit. We know that 312312- * the bad sector map is empty.313313- */314314- tail = ftape_get_buffer(ft_queue_tail);315315- if (tail->status == waiting) {316316- buffer_struct *head = ftape_get_buffer(ft_queue_head);317317-318318- ftape_setup_new_segment(head, segment_id, -1);319319- ftape_calc_next_cluster(head);320320- if (ft_runner_status == idle) {321321- result = ftape_start_tape(segment_id,322322- head->sector_offset);323323- switch(result) {324324- case 0:325325- break;326326- case -ETIME:327327- case -EINTR:328328- TRACE_ABORT(result, ft_t_err, "Error: "329329- "segment %d unreachable",330330- segment_id);331331- break;332332- default:333333- *bsm = EMPTY_SEGMENT;334334- TRACE_EXIT 0;335335- break;336336- }337337- }338338- head->status = verifying;339339- fdc_setup_read_write(head, FDC_VERIFY);340340- }341341- }342342- /* not reached */343343- TRACE_EXIT -EIO;344344-}
-37
drivers/char/ftape/lowlevel/ftape-format.h
···11-#ifndef _FTAPE_FORMAT_H22-#define _FTAPE_FORMAT_H33-44-/*55- * Copyright (C) 1996-1997 Claus-Justus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:18:13 $2525- *2626- * This file contains the low level definitions for the2727- * formatting support for the QIC-40/80/3010/3020 floppy-tape2828- * driver "ftape" for Linux.2929- */3030-3131-#ifdef __KERNEL__3232-extern int ftape_format_track(const unsigned int track, const __u8 gap3);3333-extern int ftape_format_status(unsigned int *segment_id);3434-extern int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm);3535-#endif /* __KERNEL__ */3636-3737-#endif
-160
drivers/char/ftape/lowlevel/ftape-init.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven,33- * (C) 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * This file contains the code that interfaces the kernel2121- * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.2222- */2323-2424-#include <linux/module.h>2525-#include <linux/errno.h>2626-#include <linux/fs.h>2727-#include <linux/kernel.h>2828-#include <linux/signal.h>2929-#include <linux/major.h>3030-3131-#include <linux/ftape.h>3232-#include <linux/init.h>3333-#include <linux/qic117.h>3434-#ifdef CONFIG_ZFTAPE3535-#include <linux/zftape.h>3636-#endif3737-3838-#include "../lowlevel/ftape-init.h"3939-#include "../lowlevel/ftape-io.h"4040-#include "../lowlevel/ftape-read.h"4141-#include "../lowlevel/ftape-write.h"4242-#include "../lowlevel/ftape-ctl.h"4343-#include "../lowlevel/ftape-rw.h"4444-#include "../lowlevel/fdc-io.h"4545-#include "../lowlevel/ftape-buffer.h"4646-#include "../lowlevel/ftape-proc.h"4747-#include "../lowlevel/ftape-tracing.h"4848-4949-5050-#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)5151-static int ft_tracing = -1;5252-#endif5353-5454-5555-/* Called by modules package when installing the driver5656- * or by kernel during the initialization phase5757- */5858-static int __init ftape_init(void)5959-{6060- TRACE_FUN(ft_t_flow);6161-6262-#ifdef MODULE6363-#ifndef CONFIG_FT_NO_TRACE_AT_ALL6464- if (ft_tracing != -1) {6565- ftape_tracing = ft_tracing;6666- }6767-#endif6868- printk(KERN_INFO FTAPE_VERSION "\n");6969- if (TRACE_LEVEL >= ft_t_info) {7070- printk(7171-KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n"7272-KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n"7373-KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"7474-KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n");7575- }7676-#else /* !MODULE */7777- /* print a short no-nonsense boot message */7878- printk(KERN_INFO FTAPE_VERSION "\n");7979-#endif /* MODULE */8080- TRACE(ft_t_info, "installing QIC-117 floppy tape hardware drive ... ");8181- TRACE(ft_t_info, "ftape_init @ 0x%p", ftape_init);8282- /* Allocate the DMA buffers. They are deallocated at cleanup() time.8383- */8484-#ifdef TESTING8585-#ifdef MODULE8686- while (ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS) < 0) {8787- ftape_sleep(FT_SECOND/20);8888- if (signal_pending(current)) {8989- (void)ftape_set_nr_buffers(0);9090- TRACE(ft_t_bug,9191- "Killed by signal while allocating buffers.");9292- TRACE_ABORT(-EINTR, 9393- ft_t_bug, "Free up memory and retry");9494- }9595- }9696-#else9797- TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),9898- (void)ftape_set_nr_buffers(0));9999-#endif100100-#else101101- TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS),102102- (void)ftape_set_nr_buffers(0));103103-#endif104104- ft_drive_sel = -1;105105- ft_failure = 1; /* inhibit any operation but open */106106- ftape_udelay_calibrate(); /* must be before fdc_wait_calibrate ! */107107- fdc_wait_calibrate();108108-#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)109109- (void)ftape_proc_init();110110-#endif111111-#ifdef CONFIG_ZFTAPE112112- (void)zft_init();113113-#endif114114- TRACE_EXIT 0;115115-}116116-117117-module_param(ft_fdc_base, uint, 0);118118-MODULE_PARM_DESC(ft_fdc_base, "Base address of FDC controller.");119119-module_param(ft_fdc_irq, uint, 0);120120-MODULE_PARM_DESC(ft_fdc_irq, "IRQ (interrupt channel) to use.");121121-module_param(ft_fdc_dma, uint, 0);122122-MODULE_PARM_DESC(ft_fdc_dma, "DMA channel to use.");123123-module_param(ft_fdc_threshold, uint, 0);124124-MODULE_PARM_DESC(ft_fdc_threshold, "Threshold of the FDC Fifo.");125125-module_param(ft_fdc_rate_limit, uint, 0);126126-MODULE_PARM_DESC(ft_fdc_rate_limit, "Maximal data rate for FDC.");127127-module_param(ft_probe_fc10, bool, 0);128128-MODULE_PARM_DESC(ft_probe_fc10,129129- "If non-zero, probe for a Colorado FC-10/FC-20 controller.");130130-module_param(ft_mach2, bool, 0);131131-MODULE_PARM_DESC(ft_mach2,132132- "If non-zero, probe for a Mountain MACH-2 controller.");133133-#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL)134134-module_param(ft_tracing, int, 0644);135135-MODULE_PARM_DESC(ft_tracing,136136- "Amount of debugging output, 0 <= tracing <= 8, default 3.");137137-#endif138138-139139-MODULE_AUTHOR(140140- "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl), "141141- "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no), "142142- "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)");143143-MODULE_DESCRIPTION(144144- "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives.");145145-MODULE_LICENSE("GPL");146146-147147-static void __exit ftape_exit(void)148148-{149149- TRACE_FUN(ft_t_flow);150150-151151-#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)152152- ftape_proc_destroy();153153-#endif154154- (void)ftape_set_nr_buffers(0);155155- printk(KERN_INFO "ftape: unloaded.\n");156156- TRACE_EXIT;157157-}158158-159159-module_init(ftape_init);160160-module_exit(ftape_exit);
-43
drivers/char/ftape/lowlevel/ftape-init.h
···11-#ifndef _FTAPE_INIT_H22-#define _FTAPE_INIT_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-init.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:16 $2626- *2727- * This file contains the definitions for the interface to 2828- * the Linux kernel for floppy tape driver ftape.2929- *3030- */3131-3232-#include <linux/linkage.h>3333-#include <linux/signal.h>3434-3535-#define _NEVER_BLOCK (sigmask(SIGKILL) | sigmask(SIGSTOP))3636-#define _DONT_BLOCK (_NEVER_BLOCK | sigmask(SIGINT))3737-#define _DO_BLOCK (sigmask(SIGPIPE))3838-3939-#ifndef QIC117_TAPE_MAJOR4040-#define QIC117_TAPE_MAJOR 274141-#endif4242-4343-#endif
-992
drivers/char/ftape/lowlevel/ftape-io.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven,33- * (C) 1996 Kai Harrekilde-Petersen,44- * (C) 1997 Claus-Justus Heine.55-66- This program is free software; you can redistribute it and/or modify77- it under the terms of the GNU General Public License as published by88- the Free Software Foundation; either version 2, or (at your option)99- any later version.1010-1111- This program is distributed in the hope that it will be useful,1212- but WITHOUT ANY WARRANTY; without even the implied warranty of1313- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414- GNU General Public License for more details.1515-1616- You should have received a copy of the GNU General Public License1717- along with this program; see the file COPYING. If not, write to1818- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1919-2020- *2121- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.c,v $2222- * $Revision: 1.4 $2323- * $Date: 1997/11/11 14:02:36 $2424- *2525- * This file contains the general control functions for the2626- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.2727- */2828-2929-#include <linux/errno.h>3030-#include <linux/sched.h>3131-#include <linux/mm.h>3232-#include <asm/system.h>3333-#include <linux/ioctl.h>3434-#include <linux/mtio.h>3535-#include <linux/delay.h>3636-3737-#include <linux/ftape.h>3838-#include <linux/qic117.h>3939-#include "../lowlevel/ftape-tracing.h"4040-#include "../lowlevel/fdc-io.h"4141-#include "../lowlevel/ftape-io.h"4242-#include "../lowlevel/ftape-ctl.h"4343-#include "../lowlevel/ftape-rw.h"4444-#include "../lowlevel/ftape-write.h"4545-#include "../lowlevel/ftape-read.h"4646-#include "../lowlevel/ftape-init.h"4747-#include "../lowlevel/ftape-calibr.h"4848-4949-/* Global vars.5050- */5151-/* NOTE: sectors start numbering at 1, all others at 0 ! */5252-ft_timeout_table ftape_timeout;5353-unsigned int ftape_tape_len;5454-volatile qic117_cmd_t ftape_current_command;5555-const struct qic117_command_table qic117_cmds[] = QIC117_COMMANDS;5656-int ftape_might_be_off_track;5757-5858-/* Local vars.5959- */6060-static int diagnostic_mode;6161-static unsigned int ftape_udelay_count;6262-static unsigned int ftape_udelay_time;6363-6464-void ftape_udelay(unsigned int usecs)6565-{6666- volatile int count = (ftape_udelay_count * usecs +6767- ftape_udelay_count - 1) / ftape_udelay_time;6868- volatile int i;6969-7070- while (count-- > 0) {7171- for (i = 0; i < 20; ++i);7272- }7373-}7474-7575-void ftape_udelay_calibrate(void)7676-{7777- ftape_calibrate("ftape_udelay",7878- ftape_udelay, &ftape_udelay_count, &ftape_udelay_time);7979-}8080-8181-/* Delay (msec) routine.8282- */8383-void ftape_sleep(unsigned int time)8484-{8585- TRACE_FUN(ft_t_any);8686-8787- time *= 1000; /* msecs -> usecs */8888- if (time < FT_USPT) {8989- /* Time too small for scheduler, do a busy wait ! */9090- ftape_udelay(time);9191- } else {9292- long timeout;9393- unsigned long flags;9494- unsigned int ticks = (time + FT_USPT - 1) / FT_USPT;9595-9696- TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks);9797- timeout = ticks;9898- save_flags(flags);9999- sti();100100- msleep_interruptible(jiffies_to_msecs(timeout));101101- /* Mmm. Isn't current->blocked == 0xffffffff ?102102- */103103- if (signal_pending(current)) {104104- TRACE(ft_t_err, "awoken by non-blocked signal :-(");105105- }106106- restore_flags(flags);107107- }108108- TRACE_EXIT;109109-}110110-111111-/* send a command or parameter to the drive112112- * Generates # of step pulses.113113- */114114-static inline int ft_send_to_drive(int arg)115115-{116116- /* Always wait for a command_timeout period to separate117117- * individuals commands and/or parameters.118118- */119119- ftape_sleep(3 * FT_MILLISECOND);120120- /* Keep cylinder nr within range, step towards home if possible.121121- */122122- if (ftape_current_cylinder >= arg) {123123- return fdc_seek(ftape_current_cylinder - arg);124124- } else {125125- return fdc_seek(ftape_current_cylinder + arg);126126- }127127-}128128-129129-/* forward */ int ftape_report_raw_drive_status(int *status);130130-131131-static int ft_check_cmd_restrictions(qic117_cmd_t command)132132-{133133- int status = -1;134134- TRACE_FUN(ft_t_any);135135-136136- TRACE(ft_t_flow, "%s", qic117_cmds[command].name);137137- /* A new motion command during an uninterruptible (motion)138138- * command requires a ready status before the new command can139139- * be issued. Otherwise a new motion command needs to be140140- * checked against required status.141141- */142142- if (qic117_cmds[command].cmd_type == motion &&143143- qic117_cmds[ftape_current_command].non_intr) {144144- ftape_report_raw_drive_status(&status);145145- if ((status & QIC_STATUS_READY) == 0) {146146- TRACE(ft_t_noise,147147- "motion cmd (%d) during non-intr cmd (%d)",148148- command, ftape_current_command);149149- TRACE(ft_t_noise, "waiting until drive gets ready");150150- ftape_ready_wait(ftape_timeout.seek,151151- &status);152152- }153153- }154154- if (qic117_cmds[command].mask != 0) {155155- __u8 difference;156156- /* Some commands do require a certain status:157157- */158158- if (status == -1) { /* not yet set */159159- ftape_report_raw_drive_status(&status);160160- }161161- difference = ((status ^ qic117_cmds[command].state) &162162- qic117_cmds[command].mask);163163- /* Wait until the drive gets164164- * ready. This may last forever if165165- * the drive never gets ready... 166166- */167167- while ((difference & QIC_STATUS_READY) != 0) {168168- TRACE(ft_t_noise, "command %d issued while not ready",169169- command);170170- TRACE(ft_t_noise, "waiting until drive gets ready");171171- if (ftape_ready_wait(ftape_timeout.seek,172172- &status) == -EINTR) {173173- /* Bail out on signal !174174- */175175- TRACE_ABORT(-EINTR, ft_t_warn,176176- "interrupted by non-blockable signal");177177- }178178- difference = ((status ^ qic117_cmds[command].state) &179179- qic117_cmds[command].mask);180180- }181181- while ((difference & QIC_STATUS_ERROR) != 0) {182182- int err;183183- qic117_cmd_t cmd;184184-185185- TRACE(ft_t_noise,186186- "command %d issued while error pending",187187- command);188188- TRACE(ft_t_noise, "clearing error status");189189- ftape_report_error(&err, &cmd, 1);190190- ftape_report_raw_drive_status(&status);191191- difference = ((status ^ qic117_cmds[command].state) &192192- qic117_cmds[command].mask);193193- if ((difference & QIC_STATUS_ERROR) != 0) {194194- /* Bail out on fatal signal !195195- */196196- FT_SIGNAL_EXIT(_NEVER_BLOCK);197197- }198198- }199199- if (difference) {200200- /* Any remaining difference can't be solved201201- * here. 202202- */203203- if (difference & (QIC_STATUS_CARTRIDGE_PRESENT |204204- QIC_STATUS_NEW_CARTRIDGE |205205- QIC_STATUS_REFERENCED)) {206206- TRACE(ft_t_warn,207207- "Fatal: tape removed or reinserted !");208208- ft_failure = 1;209209- } else {210210- TRACE(ft_t_err, "wrong state: 0x%02x should be: 0x%02x",211211- status & qic117_cmds[command].mask,212212- qic117_cmds[command].state);213213- }214214- TRACE_EXIT -EIO;215215- }216216- if (~status & QIC_STATUS_READY & qic117_cmds[command].mask) {217217- TRACE_ABORT(-EBUSY, ft_t_err, "Bad: still busy!");218218- }219219- }220220- TRACE_EXIT 0;221221-}222222-223223-/* Issue a tape command:224224- */225225-int ftape_command(qic117_cmd_t command)226226-{227227- int result = 0;228228- static int level;229229- TRACE_FUN(ft_t_any);230230-231231- if ((unsigned int)command > NR_ITEMS(qic117_cmds)) {232232- /* This is a bug we'll want to know about too.233233- */234234- TRACE_ABORT(-EIO, ft_t_bug, "bug - bad command: %d", command);235235- }236236- if (++level > 5) { /* This is a bug we'll want to know about. */237237- --level;238238- TRACE_ABORT(-EIO, ft_t_bug, "bug - recursion for command: %d",239239- command);240240- }241241- /* disable logging and restriction check for some commands,242242- * check all other commands that have a prescribed starting243243- * status.244244- */245245- if (diagnostic_mode) {246246- TRACE(ft_t_flow, "diagnostic command %d", command);247247- } else if (command == QIC_REPORT_DRIVE_STATUS ||248248- command == QIC_REPORT_NEXT_BIT) {249249- TRACE(ft_t_any, "%s", qic117_cmds[command].name);250250- } else {251251- TRACE_CATCH(ft_check_cmd_restrictions(command), --level);252252- }253253- /* Now all conditions are met or result was < 0.254254- */255255- result = ft_send_to_drive((unsigned int)command);256256- if (qic117_cmds[command].cmd_type == motion &&257257- command != QIC_LOGICAL_FORWARD && command != QIC_STOP_TAPE) {258258- ft_location.known = 0;259259- }260260- ftape_current_command = command;261261- --level;262262- TRACE_EXIT result;263263-}264264-265265-/* Send a tape command parameter:266266- * Generates command # of step pulses.267267- * Skips tape-status call !268268- */269269-int ftape_parameter(unsigned int parameter)270270-{271271- TRACE_FUN(ft_t_any);272272-273273- TRACE(ft_t_flow, "called with parameter = %d", parameter);274274- TRACE_EXIT ft_send_to_drive(parameter + 2);275275-}276276-277277-/* Wait for the drive to get ready.278278- * timeout time in milli-seconds279279- * Returned status is valid if result != -EIO280280- *281281- * Should we allow to be killed by SIGINT? (^C)282282- * Would be nice at least for large timeouts.283283- */284284-int ftape_ready_wait(unsigned int timeout, int *status)285285-{286286- unsigned long t0;287287- unsigned int poll_delay;288288- int signal_retries;289289- TRACE_FUN(ft_t_any);290290-291291- /* the following ** REALLY ** reduces the system load when292292- * e.g. one simply rewinds or retensions. The tape is slow 293293- * anyway. It is really not necessary to detect error 294294- * conditions with 1/10 seconds granularity295295- *296296- * On my AMD 133MHZ 486: 100 ms: 23% system load297297- * 1 sec: 5%298298- * 5 sec: 0.6%, yeah299299- */300300- if (timeout <= FT_SECOND) {301301- poll_delay = 100 * FT_MILLISECOND;302302- signal_retries = 20; /* two seconds */303303- } else if (timeout < 20 * FT_SECOND) {304304- TRACE(ft_t_flow, "setting poll delay to 1 second");305305- poll_delay = FT_SECOND;306306- signal_retries = 2; /* two seconds */307307- } else {308308- TRACE(ft_t_flow, "setting poll delay to 5 seconds");309309- poll_delay = 5 * FT_SECOND;310310- signal_retries = 1; /* five seconds */311311- }312312- for (;;) {313313- t0 = jiffies;314314- TRACE_CATCH(ftape_report_raw_drive_status(status),);315315- if (*status & QIC_STATUS_READY) {316316- TRACE_EXIT 0;317317- }318318- if (!signal_retries--) {319319- FT_SIGNAL_EXIT(_NEVER_BLOCK);320320- }321321- if ((int)timeout >= 0) {322322- /* this will fail when jiffies wraps around about323323- * once every year :-)324324- */325325- timeout -= ((jiffies - t0) * FT_SECOND) / HZ;326326- if (timeout <= 0) {327327- TRACE_ABORT(-ETIME, ft_t_err, "timeout");328328- }329329- ftape_sleep(poll_delay);330330- timeout -= poll_delay;331331- } else {332332- ftape_sleep(poll_delay);333333- }334334- }335335- TRACE_EXIT -ETIME;336336-}337337-338338-/* Issue command and wait up to timeout milli seconds for drive ready339339- */340340-int ftape_command_wait(qic117_cmd_t command, unsigned int timeout, int *status)341341-{342342- int result;343343-344344- /* Drive should be ready, issue command345345- */346346- result = ftape_command(command);347347- if (result >= 0) {348348- result = ftape_ready_wait(timeout, status);349349- }350350- return result;351351-}352352-353353-static int ftape_parameter_wait(unsigned int parm, unsigned int timeout, int *status)354354-{355355- int result;356356-357357- /* Drive should be ready, issue command358358- */359359- result = ftape_parameter(parm);360360- if (result >= 0) {361361- result = ftape_ready_wait(timeout, status);362362- }363363- return result;364364-}365365-366366-/*--------------------------------------------------------------------------367367- * Report operations368368- */369369-370370-/* Query the drive about its status. The command is sent and371371- result_length bits of status are returned (2 extra bits are read372372- for start and stop). */373373-374374-int ftape_report_operation(int *status,375375- qic117_cmd_t command,376376- int result_length)377377-{378378- int i, st3;379379- unsigned int t0;380380- unsigned int dt;381381- TRACE_FUN(ft_t_any);382382-383383- TRACE_CATCH(ftape_command(command),);384384- t0 = ftape_timestamp();385385- i = 0;386386- do {387387- ++i;388388- ftape_sleep(3 * FT_MILLISECOND); /* see remark below */389389- TRACE_CATCH(fdc_sense_drive_status(&st3),);390390- dt = ftape_timediff(t0, ftape_timestamp());391391- /* Ack should be asserted within Ttimout + Tack = 6 msec.392392- * Looks like some drives fail to do this so extend this393393- * period to 300 msec.394394- */395395- } while (!(st3 & ST3_TRACK_0) && dt < 300000);396396- if (!(st3 & ST3_TRACK_0)) {397397- TRACE(ft_t_err,398398- "No acknowledge after %u msec. (%i iter)", dt / 1000, i);399399- TRACE_ABORT(-EIO, ft_t_err, "timeout on Acknowledge");400400- }401401- /* dt may be larger than expected because of other tasks402402- * scheduled while we were sleeping.403403- */404404- if (i > 1 && dt > 6000) {405405- TRACE(ft_t_err, "Acknowledge after %u msec. (%i iter)",406406- dt / 1000, i);407407- }408408- *status = 0;409409- for (i = 0; i < result_length + 1; i++) {410410- TRACE_CATCH(ftape_command(QIC_REPORT_NEXT_BIT),);411411- TRACE_CATCH(fdc_sense_drive_status(&st3),);412412- if (i < result_length) {413413- *status |= ((st3 & ST3_TRACK_0) ? 1 : 0) << i;414414- } else if ((st3 & ST3_TRACK_0) == 0) {415415- TRACE_ABORT(-EIO, ft_t_err, "missing status stop bit");416416- }417417- }418418- /* this command will put track zero and index back into normal state */419419- (void)ftape_command(QIC_REPORT_NEXT_BIT);420420- TRACE_EXIT 0;421421-}422422-423423-/* Report the current drive status. */424424-425425-int ftape_report_raw_drive_status(int *status)426426-{427427- int result;428428- int count = 0;429429- TRACE_FUN(ft_t_any);430430-431431- do {432432- result = ftape_report_operation(status,433433- QIC_REPORT_DRIVE_STATUS, 8);434434- } while (result < 0 && ++count <= 3);435435- if (result < 0) {436436- TRACE_ABORT(-EIO, ft_t_err,437437- "report_operation failed after %d trials", count);438438- }439439- if ((*status & 0xff) == 0xff) {440440- TRACE_ABORT(-EIO, ft_t_err,441441- "impossible drive status 0xff");442442- }443443- if (*status & QIC_STATUS_READY) {444444- ftape_current_command = QIC_NO_COMMAND; /* completed */445445- }446446- ft_last_status.status.drive_status = (__u8)(*status & 0xff);447447- TRACE_EXIT 0;448448-}449449-450450-int ftape_report_drive_status(int *status)451451-{452452- TRACE_FUN(ft_t_any);453453-454454- TRACE_CATCH(ftape_report_raw_drive_status(status),);455455- if (*status & QIC_STATUS_NEW_CARTRIDGE ||456456- !(*status & QIC_STATUS_CARTRIDGE_PRESENT)) {457457- ft_failure = 1; /* will inhibit further operations */458458- TRACE_EXIT -EIO;459459- }460460- if (*status & QIC_STATUS_READY && *status & QIC_STATUS_ERROR) {461461- /* Let caller handle all errors */462462- TRACE_ABORT(1, ft_t_warn, "warning: error status set!");463463- }464464- TRACE_EXIT 0;465465-}466466-467467-int ftape_report_error(unsigned int *error,468468- qic117_cmd_t *command, int report)469469-{470470- static const ftape_error ftape_errors[] = QIC117_ERRORS;471471- int code;472472- TRACE_FUN(ft_t_any);473473-474474- TRACE_CATCH(ftape_report_operation(&code, QIC_REPORT_ERROR_CODE, 16),);475475- *error = (unsigned int)(code & 0xff);476476- *command = (qic117_cmd_t)((code>>8)&0xff);477477- /* remember hardware status, maybe useful for status ioctls478478- */479479- ft_last_error.error.command = (__u8)*command;480480- ft_last_error.error.error = (__u8)*error;481481- if (!report) {482482- TRACE_EXIT 0;483483- }484484- if (*error == 0) {485485- TRACE_ABORT(0, ft_t_info, "No error");486486- }487487- TRACE(ft_t_info, "errorcode: %d", *error);488488- if (*error < NR_ITEMS(ftape_errors)) {489489- TRACE(ft_t_noise, "%sFatal ERROR:",490490- (ftape_errors[*error].fatal ? "" : "Non-"));491491- TRACE(ft_t_noise, "%s ...", ftape_errors[*error].message);492492- } else {493493- TRACE(ft_t_noise, "Unknown ERROR !");494494- }495495- if ((unsigned int)*command < NR_ITEMS(qic117_cmds) &&496496- qic117_cmds[*command].name != NULL) {497497- TRACE(ft_t_noise, "... caused by command \'%s\'",498498- qic117_cmds[*command].name);499499- } else {500500- TRACE(ft_t_noise, "... caused by unknown command %d",501501- *command);502502- }503503- TRACE_EXIT 0;504504-}505505-506506-int ftape_report_configuration(qic_model *model,507507- unsigned int *rate,508508- int *qic_std,509509- int *tape_len)510510-{511511- int result;512512- int config;513513- int status;514514- static const unsigned int qic_rates[ 4] = { 250, 2000, 500, 1000 };515515- TRACE_FUN(ft_t_any);516516-517517- result = ftape_report_operation(&config,518518- QIC_REPORT_DRIVE_CONFIGURATION, 8);519519- if (result < 0) {520520- ft_last_status.status.drive_config = (__u8)0x00;521521- *model = prehistoric;522522- *rate = 500;523523- *qic_std = QIC_TAPE_QIC40;524524- *tape_len = 205;525525- TRACE_EXIT 0;526526- } else {527527- ft_last_status.status.drive_config = (__u8)(config & 0xff);528528- }529529- *rate = qic_rates[(config & QIC_CONFIG_RATE_MASK) >> QIC_CONFIG_RATE_SHIFT];530530- result = ftape_report_operation(&status, QIC_REPORT_TAPE_STATUS, 8);531531- if (result < 0) {532532- ft_last_status.status.tape_status = (__u8)0x00;533533- /* pre- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is valid.534534- */535535- *qic_std = (config & QIC_CONFIG_80) ?536536- QIC_TAPE_QIC80 : QIC_TAPE_QIC40;537537- /* ?? how's about 425ft tapes? */538538- *tape_len = (config & QIC_CONFIG_LONG) ? 307 : 0;539539- *model = pre_qic117c;540540- result = 0;541541- } else {542542- ft_last_status.status.tape_status = (__u8)(status & 0xff);543543- *model = post_qic117b;544544- TRACE(ft_t_any, "report tape status result = %02x", status);545545- /* post- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is546546- * invalid. 547547- */548548- switch (status & QIC_TAPE_STD_MASK) {549549- case QIC_TAPE_QIC40:550550- case QIC_TAPE_QIC80:551551- case QIC_TAPE_QIC3020:552552- case QIC_TAPE_QIC3010:553553- *qic_std = status & QIC_TAPE_STD_MASK;554554- break;555555- default:556556- *qic_std = -1;557557- break;558558- }559559- switch (status & QIC_TAPE_LEN_MASK) {560560- case QIC_TAPE_205FT:561561- /* 205 or 425+ ft 550 Oe tape */562562- *tape_len = 0;563563- break;564564- case QIC_TAPE_307FT:565565- /* 307.5 ft 550 Oe Extended Length (XL) tape */566566- *tape_len = 307;567567- break;568568- case QIC_TAPE_VARIABLE:569569- /* Variable length 550 Oe tape */570570- *tape_len = 0;571571- break;572572- case QIC_TAPE_1100FT:573573- /* 1100 ft 550 Oe tape */574574- *tape_len = 1100;575575- break;576576- case QIC_TAPE_FLEX:577577- /* Variable length 900 Oe tape */578578- *tape_len = 0;579579- break;580580- default:581581- *tape_len = -1;582582- break;583583- }584584- if (*qic_std == -1 || *tape_len == -1) {585585- TRACE(ft_t_any,586586- "post qic-117b spec drive with unknown tape");587587- }588588- result = *tape_len == -1 ? -EIO : 0;589589- if (status & QIC_TAPE_WIDE) {590590- switch (*qic_std) {591591- case QIC_TAPE_QIC80:592592- TRACE(ft_t_info, "TR-1 tape detected");593593- break;594594- case QIC_TAPE_QIC3010:595595- TRACE(ft_t_info, "TR-2 tape detected");596596- break;597597- case QIC_TAPE_QIC3020:598598- TRACE(ft_t_info, "TR-3 tape detected");599599- break;600600- default:601601- TRACE(ft_t_warn,602602- "Unknown Travan tape type detected");603603- break;604604- }605605- }606606- }607607- TRACE_EXIT (result < 0) ? -EIO : 0;608608-}609609-610610-static int ftape_report_rom_version(int *version)611611-{612612-613613- if (ftape_report_operation(version, QIC_REPORT_ROM_VERSION, 8) < 0) {614614- return -EIO;615615- } else {616616- return 0;617617- }618618-}619619-620620-void ftape_report_vendor_id(unsigned int *id)621621-{622622- int result;623623- TRACE_FUN(ft_t_any);624624-625625- /* We'll try to get a vendor id from the drive. First626626- * according to the QIC-117 spec, a 16-bit id is requested.627627- * If that fails we'll try an 8-bit version, otherwise we'll628628- * try an undocumented query.629629- */630630- result = ftape_report_operation((int *) id, QIC_REPORT_VENDOR_ID, 16);631631- if (result < 0) {632632- result = ftape_report_operation((int *) id,633633- QIC_REPORT_VENDOR_ID, 8);634634- if (result < 0) {635635- /* The following is an undocumented call found636636- * in the CMS code.637637- */638638- result = ftape_report_operation((int *) id, 24, 8);639639- if (result < 0) {640640- *id = UNKNOWN_VENDOR;641641- } else {642642- TRACE(ft_t_noise, "got old 8 bit id: %04x",643643- *id);644644- *id |= 0x20000;645645- }646646- } else {647647- TRACE(ft_t_noise, "got 8 bit id: %04x", *id);648648- *id |= 0x10000;649649- }650650- } else {651651- TRACE(ft_t_noise, "got 16 bit id: %04x", *id);652652- }653653- if (*id == 0x0047) {654654- int version;655655- int sign;656656-657657- if (ftape_report_rom_version(&version) < 0) {658658- TRACE(ft_t_bug, "report rom version failed");659659- TRACE_EXIT;660660- }661661- TRACE(ft_t_noise, "CMS rom version: %d", version);662662- ftape_command(QIC_ENTER_DIAGNOSTIC_1);663663- ftape_command(QIC_ENTER_DIAGNOSTIC_1);664664- diagnostic_mode = 1;665665- if (ftape_report_operation(&sign, 9, 8) < 0) {666666- unsigned int error;667667- qic117_cmd_t command;668668-669669- ftape_report_error(&error, &command, 1);670670- ftape_command(QIC_ENTER_PRIMARY_MODE);671671- diagnostic_mode = 0;672672- TRACE_EXIT; /* failure ! */673673- } else {674674- TRACE(ft_t_noise, "CMS signature: %02x", sign);675675- }676676- if (sign == 0xa5) {677677- result = ftape_report_operation(&sign, 37, 8);678678- if (result < 0) {679679- if (version >= 63) {680680- *id = 0x8880;681681- TRACE(ft_t_noise,682682- "This is an Iomega drive !");683683- } else {684684- *id = 0x0047;685685- TRACE(ft_t_noise,686686- "This is a real CMS drive !");687687- }688688- } else {689689- *id = 0x0047;690690- TRACE(ft_t_noise, "CMS status: %d", sign);691691- }692692- } else {693693- *id = UNKNOWN_VENDOR;694694- }695695- ftape_command(QIC_ENTER_PRIMARY_MODE);696696- diagnostic_mode = 0;697697- }698698- TRACE_EXIT;699699-}700700-701701-static int qic_rate_code(unsigned int rate)702702-{703703- switch (rate) {704704- case 250:705705- return QIC_CONFIG_RATE_250;706706- case 500:707707- return QIC_CONFIG_RATE_500;708708- case 1000:709709- return QIC_CONFIG_RATE_1000;710710- case 2000:711711- return QIC_CONFIG_RATE_2000;712712- default:713713- return QIC_CONFIG_RATE_500;714714- }715715-}716716-717717-static int ftape_set_rate_test(unsigned int *max_rate)718718-{719719- unsigned int error;720720- qic117_cmd_t command;721721- int status;722722- int supported = 0;723723- TRACE_FUN(ft_t_any);724724-725725- /* Check if the drive does support the select rate command726726- * by testing all different settings. If any one is accepted727727- * we assume the command is supported, else not.728728- */729729- for (*max_rate = 2000; *max_rate >= 250; *max_rate /= 2) {730730- if (ftape_command(QIC_SELECT_RATE) < 0) {731731- continue;732732- } 733733- if (ftape_parameter_wait(qic_rate_code(*max_rate),734734- 1 * FT_SECOND, &status) < 0) {735735- continue;736736- }737737- if (status & QIC_STATUS_ERROR) {738738- ftape_report_error(&error, &command, 0);739739- continue;740740- }741741- supported = 1; /* did accept a request */742742- break;743743- }744744- TRACE(ft_t_noise, "Select Rate command is%s supported", 745745- supported ? "" : " not");746746- TRACE_EXIT supported;747747-}748748-749749-int ftape_set_data_rate(unsigned int new_rate /* Kbps */, unsigned int qic_std)750750-{751751- int status;752752- int result = 0;753753- unsigned int data_rate = new_rate;754754- static int supported;755755- int rate_changed = 0;756756- qic_model dummy_model;757757- unsigned int dummy_qic_std, dummy_tape_len;758758- TRACE_FUN(ft_t_any);759759-760760- if (ft_drive_max_rate == 0) { /* first time */761761- supported = ftape_set_rate_test(&ft_drive_max_rate);762762- }763763- if (supported) {764764- ftape_command(QIC_SELECT_RATE);765765- result = ftape_parameter_wait(qic_rate_code(new_rate),766766- 1 * FT_SECOND, &status);767767- if (result >= 0 && !(status & QIC_STATUS_ERROR)) {768768- rate_changed = 1;769769- }770770- }771771- TRACE_CATCH(result = ftape_report_configuration(&dummy_model,772772- &data_rate, 773773- &dummy_qic_std,774774- &dummy_tape_len),);775775- if (data_rate != new_rate) {776776- if (!supported) {777777- TRACE(ft_t_warn, "Rate change not supported!");778778- } else if (rate_changed) {779779- TRACE(ft_t_warn, "Requested: %d, got %d",780780- new_rate, data_rate);781781- } else {782782- TRACE(ft_t_warn, "Rate change failed!");783783- }784784- result = -EINVAL;785785- }786786- /*787787- * Set data rate and write precompensation as specified:788788- *789789- * | QIC-40/80 | QIC-3010/3020790790- * rate | precomp | precomp791791- * ----------+-------------+--------------792792- * 250 Kbps. | 250 ns. | 0 ns.793793- * 500 Kbps. | 125 ns. | 0 ns.794794- * 1 Mbps. | 42 ns. | 0 ns.795795- * 2 Mbps | N/A | 0 ns.796796- */797797- if ((qic_std == QIC_TAPE_QIC40 && data_rate > 500) || 798798- (qic_std == QIC_TAPE_QIC80 && data_rate > 1000)) {799799- TRACE_ABORT(-EINVAL,800800- ft_t_warn, "Datarate too high for QIC-mode");801801- }802802- TRACE_CATCH(fdc_set_data_rate(data_rate),_res = -EINVAL);803803- ft_data_rate = data_rate;804804- if (qic_std == QIC_TAPE_QIC40 || qic_std == QIC_TAPE_QIC80) {805805- switch (data_rate) {806806- case 250:807807- fdc_set_write_precomp(250);808808- break;809809- default:810810- case 500:811811- fdc_set_write_precomp(125);812812- break;813813- case 1000:814814- fdc_set_write_precomp(42);815815- break;816816- }817817- } else {818818- fdc_set_write_precomp(0);819819- }820820- TRACE_EXIT result;821821-}822822-823823-/* The next two functions are used to cope with excessive overrun errors824824- */825825-int ftape_increase_threshold(void)826826-{827827- TRACE_FUN(ft_t_flow);828828-829829- if (fdc.type < i82077 || ft_fdc_threshold >= 12) {830830- TRACE_ABORT(-EIO, ft_t_err, "cannot increase fifo threshold");831831- }832832- if (fdc_fifo_threshold(++ft_fdc_threshold, NULL, NULL, NULL) < 0) {833833- TRACE(ft_t_err, "cannot increase fifo threshold");834834- ft_fdc_threshold --;835835- fdc_reset();836836- }837837- TRACE(ft_t_info, "New FIFO threshold: %d", ft_fdc_threshold);838838- TRACE_EXIT 0;839839-}840840-841841-int ftape_half_data_rate(void)842842-{843843- if (ft_data_rate < 500) {844844- return -1;845845- }846846- if (ftape_set_data_rate(ft_data_rate / 2, ft_qic_std) < 0) {847847- return -EIO;848848- }849849- ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);850850- return 0;851851-}852852-853853-/* Seek the head to the specified track.854854- */855855-int ftape_seek_head_to_track(unsigned int track)856856-{857857- int status;858858- TRACE_FUN(ft_t_any);859859-860860- ft_location.track = -1; /* remains set in case of error */861861- if (track >= ft_tracks_per_tape) {862862- TRACE_ABORT(-EINVAL, ft_t_bug, "track out of bounds");863863- }864864- TRACE(ft_t_flow, "seeking track %d", track);865865- TRACE_CATCH(ftape_command(QIC_SEEK_HEAD_TO_TRACK),);866866- TRACE_CATCH(ftape_parameter_wait(track, ftape_timeout.head_seek,867867- &status),);868868- ft_location.track = track;869869- ftape_might_be_off_track = 0;870870- TRACE_EXIT 0;871871-}872872-873873-int ftape_wakeup_drive(wake_up_types method)874874-{875875- int status;876876- int motor_on = 0;877877- TRACE_FUN(ft_t_any);878878-879879- switch (method) {880880- case wake_up_colorado:881881- TRACE_CATCH(ftape_command(QIC_PHANTOM_SELECT),);882882- TRACE_CATCH(ftape_parameter(0 /* ft_drive_sel ?? */),);883883- break;884884- case wake_up_mountain:885885- TRACE_CATCH(ftape_command(QIC_SOFT_SELECT),);886886- ftape_sleep(FT_MILLISECOND); /* NEEDED */887887- TRACE_CATCH(ftape_parameter(18),);888888- break;889889- case wake_up_insight:890890- ftape_sleep(100 * FT_MILLISECOND);891891- motor_on = 1;892892- fdc_motor(motor_on); /* enable is done by motor-on */893893- case no_wake_up:894894- break;895895- default:896896- TRACE_EXIT -ENODEV; /* unknown wakeup method */897897- break;898898- }899899- /* If wakeup succeeded we shouldn't get an error here..900900- */901901- TRACE_CATCH(ftape_report_raw_drive_status(&status),902902- if (motor_on) {903903- fdc_motor(0);904904- });905905- TRACE_EXIT 0;906906-}907907-908908-int ftape_put_drive_to_sleep(wake_up_types method)909909-{910910- TRACE_FUN(ft_t_any);911911-912912- switch (method) {913913- case wake_up_colorado:914914- TRACE_CATCH(ftape_command(QIC_PHANTOM_DESELECT),);915915- break;916916- case wake_up_mountain:917917- TRACE_CATCH(ftape_command(QIC_SOFT_DESELECT),);918918- break;919919- case wake_up_insight:920920- fdc_motor(0); /* enable is done by motor-on */921921- case no_wake_up: /* no wakeup / no sleep ! */922922- break;923923- default:924924- TRACE_EXIT -ENODEV; /* unknown wakeup method */925925- }926926- TRACE_EXIT 0;927927-}928928-929929-int ftape_reset_drive(void)930930-{931931- int result = 0;932932- int status;933933- unsigned int err_code;934934- qic117_cmd_t err_command;935935- int i;936936- TRACE_FUN(ft_t_any);937937-938938- /* We want to re-establish contact with our drive. Fire a939939- * number of reset commands (single step pulses) and pray for940940- * success.941941- */942942- for (i = 0; i < 2; ++i) {943943- TRACE(ft_t_flow, "Resetting fdc");944944- fdc_reset();945945- ftape_sleep(10 * FT_MILLISECOND);946946- TRACE(ft_t_flow, "Reset command to drive");947947- result = ftape_command(QIC_RESET);948948- if (result == 0) {949949- ftape_sleep(1 * FT_SECOND); /* drive not950950- * accessible951951- * during 1 second952952- */953953- TRACE(ft_t_flow, "Re-selecting drive");954954-955955- /* Strange, the QIC-117 specs don't mention956956- * this but the drive gets deselected after a957957- * soft reset ! So we need to enable it958958- * again.959959- */960960- if (ftape_wakeup_drive(ft_drive_type.wake_up) < 0) {961961- TRACE(ft_t_err, "Wakeup failed !");962962- }963963- TRACE(ft_t_flow, "Waiting until drive gets ready");964964- result= ftape_ready_wait(ftape_timeout.reset, &status);965965- if (result == 0 && (status & QIC_STATUS_ERROR)) {966966- result = ftape_report_error(&err_code,967967- &err_command, 1);968968- if (result == 0 && err_code == 27) {969969- /* Okay, drive saw reset970970- * command and responded as it971971- * should972972- */973973- break;974974- } else {975975- result = -EIO;976976- }977977- } else {978978- result = -EIO;979979- }980980- }981981- FT_SIGNAL_EXIT(_DONT_BLOCK);982982- }983983- if (result != 0) {984984- TRACE(ft_t_err, "General failure to reset tape drive");985985- } else {986986- /* Restore correct settings: keep original rate 987987- */988988- ftape_set_data_rate(ft_data_rate, ft_qic_std);989989- }990990- ftape_init_drive_needed = 1;991991- TRACE_EXIT result;992992-}
-90
drivers/char/ftape/lowlevel/ftape-io.h
···11-#ifndef _FTAPE_IO_H22-#define _FTAPE_IO_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven,66- * (C) 1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:18 $2626- *2727- * This file contains definitions for the glue part of the2828- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.2929- */3030-3131-#include <linux/qic117.h>3232-#include <linux/ftape-vendors.h>3333-3434-typedef struct {3535- unsigned int seek;3636- unsigned int reset;3737- unsigned int rewind;3838- unsigned int head_seek;3939- unsigned int stop;4040- unsigned int pause;4141-} ft_timeout_table;4242-4343-typedef enum {4444- prehistoric, pre_qic117c, post_qic117b, post_qic117d 4545-} qic_model;4646-4747-/*4848- * ftape-io.c defined global vars.4949- */5050-extern ft_timeout_table ftape_timeout;5151-extern unsigned int ftape_tape_len;5252-extern volatile qic117_cmd_t ftape_current_command;5353-extern const struct qic117_command_table qic117_cmds[];5454-extern int ftape_might_be_off_track;5555-5656-/*5757- * ftape-io.c defined global functions.5858- */5959-extern void ftape_udelay(unsigned int usecs);6060-extern void ftape_udelay_calibrate(void);6161-extern void ftape_sleep(unsigned int time);6262-extern void ftape_report_vendor_id(unsigned int *id);6363-extern int ftape_command(qic117_cmd_t command);6464-extern int ftape_command_wait(qic117_cmd_t command,6565- unsigned int timeout,6666- int *status);6767-extern int ftape_parameter(unsigned int parameter);6868-extern int ftape_report_operation(int *status,6969- qic117_cmd_t command,7070- int result_length);7171-extern int ftape_report_configuration(qic_model *model,7272- unsigned int *rate,7373- int *qic_std,7474- int *tape_len);7575-extern int ftape_report_drive_status(int *status);7676-extern int ftape_report_raw_drive_status(int *status);7777-extern int ftape_report_status(int *status);7878-extern int ftape_ready_wait(unsigned int timeout, int *status);7979-extern int ftape_seek_head_to_track(unsigned int track);8080-extern int ftape_set_data_rate(unsigned int new_rate, unsigned int qic_std);8181-extern int ftape_report_error(unsigned int *error,8282- qic117_cmd_t *command,8383- int report);8484-extern int ftape_reset_drive(void);8585-extern int ftape_put_drive_to_sleep(wake_up_types method);8686-extern int ftape_wakeup_drive(wake_up_types method);8787-extern int ftape_increase_threshold(void);8888-extern int ftape_half_data_rate(void);8989-9090-#endif
-214
drivers/char/ftape/lowlevel/ftape-proc.c
···11-/*22- * Copyright (C) 1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.c,v $2020- * $Revision: 1.11 $2121- * $Date: 1997/10/24 14:47:37 $2222- *2323- * This file contains the procfs interface for the2424- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.2525-2626- * Old code removed, switched to dynamic proc entry.2727- */2828-2929-3030-#if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)3131-3232-#include <linux/proc_fs.h>3333-3434-#include <linux/ftape.h>3535-#include <linux/init.h>3636-#include <linux/qic117.h>3737-3838-#include "../lowlevel/ftape-io.h"3939-#include "../lowlevel/ftape-ctl.h"4040-#include "../lowlevel/ftape-proc.h"4141-#include "../lowlevel/ftape-tracing.h"4242-4343-static size_t get_driver_info(char *buf)4444-{4545- const char *debug_level[] = { "bugs" ,4646- "errors",4747- "warnings",4848- "informational",4949- "noisy",5050- "program flow",5151- "fdc and dma",5252- "data flow",5353- "anything" };5454-5555- return sprintf(buf,5656- "version : %s\n"5757- "used data rate: %d kbit/sec\n"5858- "dma memory : %d kb\n"5959- "debug messages: %s\n",6060- FTAPE_VERSION,6161- ft_data_rate,6262- FT_BUFF_SIZE * ft_nr_buffers >> 10,6363- debug_level[TRACE_LEVEL]);6464-}6565-6666-static size_t get_tapedrive_info(char *buf)6767-{ 6868- return sprintf(buf,6969- "vendor id : 0x%04x\n"7070- "drive name: %s\n"7171- "wind speed: %d ips\n"7272- "wakeup : %s\n"7373- "max. rate : %d kbit/sec\n",7474- ft_drive_type.vendor_id,7575- ft_drive_type.name,7676- ft_drive_type.speed,7777- ((ft_drive_type.wake_up == no_wake_up)7878- ? "No wakeup needed" :7979- ((ft_drive_type.wake_up == wake_up_colorado)8080- ? "Colorado" :8181- ((ft_drive_type.wake_up == wake_up_mountain)8282- ? "Mountain" :8383- ((ft_drive_type.wake_up == wake_up_insight)8484- ? "Motor on" :8585- "Unknown")))),8686- ft_drive_max_rate);8787-}8888-8989-static size_t get_cartridge_info(char *buf)9090-{9191- if (ftape_init_drive_needed) {9292- return sprintf(buf, "uninitialized\n");9393- }9494- if (ft_no_tape) {9595- return sprintf(buf, "no cartridge inserted\n");9696- }9797- return sprintf(buf,9898- "segments : %5d\n"9999- "tracks : %5d\n"100100- "length : %5dft\n"101101- "formatted : %3s\n"102102- "writable : %3s\n"103103- "QIC spec. : QIC-%s\n"104104- "fmt-code : %1d\n",105105- ft_segments_per_track,106106- ft_tracks_per_tape,107107- ftape_tape_len,108108- (ft_formatted == 1) ? "yes" : "no",109109- (ft_write_protected == 1) ? "no" : "yes",110110- ((ft_qic_std == QIC_TAPE_QIC40) ? "40" :111111- ((ft_qic_std == QIC_TAPE_QIC80) ? "80" :112112- ((ft_qic_std == QIC_TAPE_QIC3010) ? "3010" :113113- ((ft_qic_std == QIC_TAPE_QIC3020) ? "3020" :114114- "???")))),115115- ft_format_code);116116-}117117-118118-static size_t get_controller_info(char *buf)119119-{120120- const char *fdc_name[] = { "no fdc",121121- "i8272",122122- "i82077",123123- "i82077AA",124124- "Colorado FC-10 or FC-20",125125- "i82078",126126- "i82078_1" };127127-128128- return sprintf(buf,129129- "FDC type : %s\n"130130- "FDC base : 0x%03x\n"131131- "FDC irq : %d\n"132132- "FDC dma : %d\n"133133- "FDC thr. : %d\n"134134- "max. rate : %d kbit/sec\n",135135- ft_mach2 ? "Mountain MACH-2" : fdc_name[fdc.type],136136- fdc.sra, fdc.irq, fdc.dma,137137- ft_fdc_threshold, ft_fdc_max_rate);138138-}139139-140140-static size_t get_history_info(char *buf)141141-{142142- size_t len;143143-144144- len = sprintf(buf,145145- "\nFDC isr statistics\n"146146- " id_am_errors : %3d\n"147147- " id_crc_errors : %3d\n"148148- " data_am_errors : %3d\n"149149- " data_crc_errors : %3d\n"150150- " overrun_errors : %3d\n"151151- " no_data_errors : %3d\n"152152- " retries : %3d\n",153153- ft_history.id_am_errors, ft_history.id_crc_errors,154154- ft_history.data_am_errors, ft_history.data_crc_errors,155155- ft_history.overrun_errors, ft_history.no_data_errors,156156- ft_history.retries);157157- len += sprintf(buf + len,158158- "\nECC statistics\n"159159- " crc_errors : %3d\n"160160- " crc_failures : %3d\n"161161- " ecc_failures : %3d\n"162162- " sectors corrected: %3d\n",163163- ft_history.crc_errors, ft_history.crc_failures,164164- ft_history.ecc_failures, ft_history.corrected);165165- len += sprintf(buf + len,166166- "\ntape quality statistics\n"167167- " media defects : %3d\n",168168- ft_history.defects);169169- len += sprintf(buf + len,170170- "\ntape motion statistics\n"171171- " repositions : %3d\n",172172- ft_history.rewinds);173173- return len;174174-}175175-176176-static int ftape_read_proc(char *page, char **start, off_t off,177177- int count, int *eof, void *data)178178-{179179- char *ptr = page;180180- size_t len;181181-182182- ptr += sprintf(ptr, "Kernel Driver\n\n");183183- ptr += get_driver_info(ptr);184184- ptr += sprintf(ptr, "\nTape Drive\n\n");185185- ptr += get_tapedrive_info(ptr);186186- ptr += sprintf(ptr, "\nFDC Controller\n\n");187187- ptr += get_controller_info(ptr);188188- ptr += sprintf(ptr, "\nTape Cartridge\n\n");189189- ptr += get_cartridge_info(ptr);190190- ptr += sprintf(ptr, "\nHistory Record\n\n");191191- ptr += get_history_info(ptr);192192-193193- len = strlen(page);194194- *start = NULL;195195- if (off+count >= len) {196196- *eof = 1;197197- } else {198198- *eof = 0;199199- }200200- return len;201201-}202202-203203-int __init ftape_proc_init(void)204204-{205205- return create_proc_read_entry("ftape", 0, &proc_root,206206- ftape_read_proc, NULL) != NULL;207207-}208208-209209-void ftape_proc_destroy(void)210210-{211211- remove_proc_entry("ftape", &proc_root);212212-}213213-214214-#endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */
-35
drivers/char/ftape/lowlevel/ftape-proc.h
···11-#ifndef _FTAPE_PROC_H22-#define _FTAPE_PROC_H33-44-/*55- * Copyright (C) 1997 Claus-Justus Heine66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:18:20 $2525- *2626- * This file contains definitions for the procfs interface of the2727- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.2828- */2929-3030-#include <linux/proc_fs.h>3131-3232-extern int ftape_proc_init(void);3333-extern void ftape_proc_destroy(void);3434-3535-#endif
-621
drivers/char/ftape/lowlevel/ftape-read.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven,33- * (C) 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.c,v $2121- * $Revision: 1.6 $2222- * $Date: 1997/10/21 14:39:22 $2323- *2424- * This file contains the reading code2525- * for the QIC-117 floppy-tape driver for Linux.2626- *2727- */2828-2929-#include <linux/string.h>3030-#include <linux/errno.h>3131-#include <linux/mm.h>3232-3333-#include <linux/ftape.h>3434-#include <linux/qic117.h>3535-#include "../lowlevel/ftape-tracing.h"3636-#include "../lowlevel/ftape-read.h"3737-#include "../lowlevel/ftape-io.h"3838-#include "../lowlevel/ftape-ctl.h"3939-#include "../lowlevel/ftape-rw.h"4040-#include "../lowlevel/ftape-write.h"4141-#include "../lowlevel/ftape-ecc.h"4242-#include "../lowlevel/ftape-bsm.h"4343-4444-/* Global vars.4545- */4646-4747-/* Local vars.4848- */4949-5050-void ftape_zap_read_buffers(void)5151-{5252- int i;5353-5454- for (i = 0; i < ft_nr_buffers; ++i) {5555-/* changed to "fit" with dynamic allocation of tape_buffer. --khp */5656- ft_buffer[i]->status = waiting;5757- ft_buffer[i]->bytes = 0;5858- ft_buffer[i]->skip = 0;5959- ft_buffer[i]->retry = 0;6060- }6161-/* ftape_reset_buffer(); */6262-}6363-6464-static SectorMap convert_sector_map(buffer_struct * buff)6565-{6666- int i = 0;6767- SectorMap bad_map = ftape_get_bad_sector_entry(buff->segment_id);6868- SectorMap src_map = buff->soft_error_map | buff->hard_error_map;6969- SectorMap dst_map = 0;7070- TRACE_FUN(ft_t_any);7171-7272- if (bad_map || src_map) {7373- TRACE(ft_t_flow, "bad_map = 0x%08lx", (long) bad_map);7474- TRACE(ft_t_flow, "src_map = 0x%08lx", (long) src_map);7575- }7676- while (bad_map) {7777- while ((bad_map & 1) == 0) {7878- if (src_map & 1) {7979- dst_map |= (1 << i);8080- }8181- src_map >>= 1;8282- bad_map >>= 1;8383- ++i;8484- }8585- /* (bad_map & 1) == 1 */8686- src_map >>= 1;8787- bad_map >>= 1;8888- }8989- if (src_map) {9090- dst_map |= (src_map << i);9191- }9292- if (dst_map) {9393- TRACE(ft_t_flow, "dst_map = 0x%08lx", (long) dst_map);9494- }9595- TRACE_EXIT dst_map;9696-}9797-9898-static int correct_and_copy_fraction(buffer_struct *buff, __u8 * destination,9999- int start, int size)100100-{101101- struct memory_segment mseg;102102- int result;103103- SectorMap read_bad;104104- TRACE_FUN(ft_t_any);105105-106106- mseg.read_bad = convert_sector_map(buff);107107- mseg.marked_bad = 0; /* not used... */108108- mseg.blocks = buff->bytes / FT_SECTOR_SIZE;109109- mseg.data = buff->address;110110- /* If there are no data sectors we can skip this segment.111111- */112112- if (mseg.blocks <= 3) {113113- TRACE_ABORT(0, ft_t_noise, "empty segment");114114- }115115- read_bad = mseg.read_bad;116116- ft_history.crc_errors += count_ones(read_bad);117117- result = ftape_ecc_correct_data(&mseg);118118- if (read_bad != 0 || mseg.corrected != 0) {119119- TRACE(ft_t_noise, "crc error map: 0x%08lx", (unsigned long)read_bad);120120- TRACE(ft_t_noise, "corrected map: 0x%08lx", (unsigned long)mseg.corrected);121121- ft_history.corrected += count_ones(mseg.corrected);122122- }123123- if (result == ECC_CORRECTED || result == ECC_OK) {124124- if (result == ECC_CORRECTED) {125125- TRACE(ft_t_info, "ecc corrected segment: %d", buff->segment_id);126126- }127127- if(start < 0) {128128- start= 0;129129- }130130- if((start+size) > ((mseg.blocks - 3) * FT_SECTOR_SIZE)) {131131- size = (mseg.blocks - 3) * FT_SECTOR_SIZE - start;132132- } 133133- if (size < 0) {134134- size= 0;135135- }136136- if(size > 0) {137137- memcpy(destination + start, mseg.data + start, size);138138- }139139- if ((read_bad ^ mseg.corrected) & mseg.corrected) {140140- /* sectors corrected without crc errors set */141141- ft_history.crc_failures++;142142- }143143- TRACE_EXIT size; /* (mseg.blocks - 3) * FT_SECTOR_SIZE; */144144- } else {145145- ft_history.ecc_failures++;146146- TRACE_ABORT(-EAGAIN,147147- ft_t_err, "ecc failure on segment %d",148148- buff->segment_id);149149- }150150- TRACE_EXIT 0;151151-}152152-153153-/* Read given segment into buffer at address.154154- */155155-int ftape_read_segment_fraction(const int segment_id,156156- void *address, 157157- const ft_read_mode_t read_mode,158158- const int start,159159- const int size)160160-{161161- int result = 0;162162- int retry = 0;163163- int bytes_read = 0;164164- int read_done = 0;165165- TRACE_FUN(ft_t_flow);166166-167167- ft_history.used |= 1;168168- TRACE(ft_t_data_flow, "segment_id = %d", segment_id);169169- if (ft_driver_state != reading) {170170- TRACE(ft_t_noise, "calling ftape_abort_operation");171171- TRACE_CATCH(ftape_abort_operation(),);172172- ftape_set_state(reading);173173- }174174- for(;;) {175175- buffer_struct *tail;176176- /* Allow escape from this loop on signal !177177- */178178- FT_SIGNAL_EXIT(_DONT_BLOCK);179179- /* Search all full buffers for the first matching the180180- * wanted segment. Clear other buffers on the fly.181181- */182182- tail = ftape_get_buffer(ft_queue_tail);183183- while (!read_done && tail->status == done) {184184- /* Allow escape from this loop on signal !185185- */186186- FT_SIGNAL_EXIT(_DONT_BLOCK);187187- if (tail->segment_id == segment_id) {188188- /* If out buffer is already full,189189- * return its contents. 190190- */191191- TRACE(ft_t_flow, "found segment in cache: %d",192192- segment_id);193193- if (tail->deleted) {194194- /* Return a value that195195- * read_header_segment196196- * understands. As this197197- * should only occur when198198- * searching for the header199199- * segments it shouldn't be200200- * misinterpreted elsewhere.201201- */202202- TRACE_EXIT 0;203203- }204204- result = correct_and_copy_fraction(205205- tail,206206- address,207207- start,208208- size);209209- TRACE(ft_t_flow, "segment contains (bytes): %d",210210- result);211211- if (result < 0) {212212- if (result != -EAGAIN) {213213- TRACE_EXIT result;214214- }215215- /* keep read_done == 0, will216216- * trigger217217- * ftape_abort_operation218218- * because reading wrong219219- * segment.220220- */221221- TRACE(ft_t_err, "ecc failed, retry");222222- ++retry;223223- } else {224224- read_done = 1;225225- bytes_read = result;226226- }227227- } else {228228- TRACE(ft_t_flow,"zapping segment in cache: %d",229229- tail->segment_id);230230- }231231- tail->status = waiting;232232- tail = ftape_next_buffer(ft_queue_tail);233233- }234234- if (!read_done && tail->status == reading) {235235- if (tail->segment_id == segment_id) {236236- switch(ftape_wait_segment(reading)) {237237- case 0:238238- break;239239- case -EINTR:240240- TRACE_ABORT(-EINTR, ft_t_warn,241241- "interrupted by "242242- "non-blockable signal");243243- break;244244- default:245245- TRACE(ft_t_noise,246246- "wait_segment failed");247247- ftape_abort_operation();248248- ftape_set_state(reading);249249- break;250250- }251251- } else {252252- /* We're reading the wrong segment,253253- * stop runner.254254- */255255- TRACE(ft_t_noise, "reading wrong segment");256256- ftape_abort_operation();257257- ftape_set_state(reading);258258- }259259- }260260- /* should runner stop ?261261- */262262- if (ft_runner_status == aborting) {263263- buffer_struct *head = ftape_get_buffer(ft_queue_head);264264- switch(head->status) {265265- case error:266266- ft_history.defects += 267267- count_ones(head->hard_error_map);268268- case reading:269269- head->status = waiting;270270- break;271271- default:272272- break;273273- }274274- TRACE_CATCH(ftape_dumb_stop(),);275275- } else {276276- /* If just passed last segment on tape: wait277277- * for BOT or EOT mark. Sets ft_runner_status to278278- * idle if at lEOT and successful 279279- */280280- TRACE_CATCH(ftape_handle_logical_eot(),);281281- }282282- /* If we got a segment: quit, or else retry up to limit.283283- *284284- * If segment to read is empty, do not start runner for it,285285- * but wait for next read call.286286- */287287- if (read_done ||288288- ftape_get_bad_sector_entry(segment_id) == EMPTY_SEGMENT ) {289289- /* bytes_read = 0; should still be zero */290290- TRACE_EXIT bytes_read;291291-292292- }293293- if (retry > FT_RETRIES_ON_ECC_ERROR) {294294- ft_history.defects++;295295- TRACE_ABORT(-ENODATA, ft_t_err,296296- "too many retries on ecc failure");297297- }298298- /* Now at least one buffer is empty !299299- * Restart runner & tape if needed.300300- */301301- TRACE(ft_t_any, "head: %d, tail: %d, ft_runner_status: %d",302302- ftape_buffer_id(ft_queue_head),303303- ftape_buffer_id(ft_queue_tail),304304- ft_runner_status);305305- TRACE(ft_t_any, "buffer[].status, [head]: %d, [tail]: %d",306306- ftape_get_buffer(ft_queue_head)->status,307307- ftape_get_buffer(ft_queue_tail)->status);308308- tail = ftape_get_buffer(ft_queue_tail);309309- if (tail->status == waiting) {310310- buffer_struct *head = ftape_get_buffer(ft_queue_head);311311-312312- ftape_setup_new_segment(head, segment_id, -1);313313- if (read_mode == FT_RD_SINGLE) {314314- /* disable read-ahead */315315- head->next_segment = 0;316316- }317317- ftape_calc_next_cluster(head);318318- if (ft_runner_status == idle) {319319- result = ftape_start_tape(segment_id,320320- head->sector_offset);321321- if (result < 0) {322322- TRACE_ABORT(result, ft_t_err, "Error: "323323- "segment %d unreachable",324324- segment_id);325325- }326326- }327327- head->status = reading;328328- fdc_setup_read_write(head, FDC_READ);329329- }330330- }331331- /* not reached */332332- TRACE_EXIT -EIO;333333-}334334-335335-int ftape_read_header_segment(__u8 *address)336336-{337337- int result;338338- int header_segment;339339- int first_failed = 0;340340- int status;341341- TRACE_FUN(ft_t_flow);342342-343343- ft_used_header_segment = -1;344344- TRACE_CATCH(ftape_report_drive_status(&status),);345345- TRACE(ft_t_flow, "reading...");346346- /* We're looking for the first header segment.347347- * A header segment cannot contain bad sectors, therefor at the348348- * tape start, segments with bad sectors are (according to QIC-40/80)349349- * written with deleted data marks and must be skipped.350350- */351351- memset(address, '\0', (FT_SECTORS_PER_SEGMENT - 3) * FT_SECTOR_SIZE); 352352- result = 0;353353-#define HEADER_SEGMENT_BOUNDARY 68 /* why not 42? */354354- for (header_segment = 0;355355- header_segment < HEADER_SEGMENT_BOUNDARY && result == 0;356356- ++header_segment) {357357- /* Set no read-ahead, the isr will force read-ahead whenever358358- * it encounters deleted data !359359- */360360- result = ftape_read_segment(header_segment,361361- address,362362- FT_RD_SINGLE);363363- if (result < 0 && !first_failed) {364364- TRACE(ft_t_err, "header segment damaged, trying backup");365365- first_failed = 1;366366- result = 0; /* force read of next (backup) segment */367367- }368368- }369369- if (result < 0 || header_segment >= HEADER_SEGMENT_BOUNDARY) {370370- TRACE_ABORT(-EIO, ft_t_err,371371- "no readable header segment found");372372- }373373- TRACE_CATCH(ftape_abort_operation(),);374374- ft_used_header_segment = header_segment;375375- result = ftape_decode_header_segment(address);376376- TRACE_EXIT result;377377-}378378-379379-int ftape_decode_header_segment(__u8 *address)380380-{381381- unsigned int max_floppy_side;382382- unsigned int max_floppy_track;383383- unsigned int max_floppy_sector;384384- unsigned int new_tape_len;385385- TRACE_FUN(ft_t_flow);386386-387387- if (GET4(address, FT_SIGNATURE) == FT_D2G_MAGIC) {388388- /* Ditto 2GB header segment. They encrypt the bad sector map.389389- * We decrypt it and store them in normal format.390390- * I hope this is correct.391391- */392392- int i;393393- TRACE(ft_t_warn,394394- "Found Ditto 2GB tape, "395395- "trying to decrypt bad sector map");396396- for (i=256; i < 29 * FT_SECTOR_SIZE; i++) {397397- address[i] = ~(address[i] - (i&0xff));398398- }399399- PUT4(address, 0,FT_HSEG_MAGIC);400400- } else if (GET4(address, FT_SIGNATURE) != FT_HSEG_MAGIC) {401401- TRACE_ABORT(-EIO, ft_t_err,402402- "wrong signature in header segment");403403- }404404- ft_format_code = (ft_format_type) address[FT_FMT_CODE];405405- if (ft_format_code != fmt_big) {406406- ft_header_segment_1 = GET2(address, FT_HSEG_1);407407- ft_header_segment_2 = GET2(address, FT_HSEG_2);408408- ft_first_data_segment = GET2(address, FT_FRST_SEG);409409- ft_last_data_segment = GET2(address, FT_LAST_SEG);410410- } else {411411- ft_header_segment_1 = GET4(address, FT_6_HSEG_1);412412- ft_header_segment_2 = GET4(address, FT_6_HSEG_2);413413- ft_first_data_segment = GET4(address, FT_6_FRST_SEG);414414- ft_last_data_segment = GET4(address, FT_6_LAST_SEG);415415- }416416- TRACE(ft_t_noise, "first data segment: %d", ft_first_data_segment);417417- TRACE(ft_t_noise, "last data segment: %d", ft_last_data_segment);418418- TRACE(ft_t_noise, "header segments are %d and %d",419419- ft_header_segment_1, ft_header_segment_2);420420-421421- /* Verify tape parameters...422422- * QIC-40/80 spec: tape_parameters:423423- *424424- * segments-per-track segments_per_track425425- * tracks-per-cartridge tracks_per_tape426426- * max-floppy-side (segments_per_track *427427- * tracks_per_tape - 1) /428428- * ftape_segments_per_head429429- * max-floppy-track ftape_segments_per_head /430430- * ftape_segments_per_cylinder - 1431431- * max-floppy-sector ftape_segments_per_cylinder *432432- * FT_SECTORS_PER_SEGMENT433433- */434434- ft_segments_per_track = GET2(address, FT_SPT);435435- ft_tracks_per_tape = address[FT_TPC];436436- max_floppy_side = address[FT_FHM];437437- max_floppy_track = address[FT_FTM];438438- max_floppy_sector = address[FT_FSM];439439- TRACE(ft_t_noise, "(fmt/spt/tpc/fhm/ftm/fsm) = %d/%d/%d/%d/%d/%d",440440- ft_format_code, ft_segments_per_track, ft_tracks_per_tape,441441- max_floppy_side, max_floppy_track, max_floppy_sector);442442- new_tape_len = ftape_tape_len;443443- switch (ft_format_code) {444444- case fmt_425ft:445445- new_tape_len = 425;446446- break;447447- case fmt_normal:448448- if (ftape_tape_len == 0) { /* otherwise 307 ft */449449- new_tape_len = 205;450450- }451451- break;452452- case fmt_1100ft:453453- new_tape_len = 1100;454454- break;455455- case fmt_var:{456456- int segments_per_1000_inch = 1; /* non-zero default for switch */457457- switch (ft_qic_std) {458458- case QIC_TAPE_QIC40:459459- segments_per_1000_inch = 332;460460- break;461461- case QIC_TAPE_QIC80:462462- segments_per_1000_inch = 488;463463- break;464464- case QIC_TAPE_QIC3010:465465- segments_per_1000_inch = 730;466466- break;467467- case QIC_TAPE_QIC3020:468468- segments_per_1000_inch = 1430;469469- break;470470- }471471- new_tape_len = (1000 * ft_segments_per_track +472472- (segments_per_1000_inch - 1)) / segments_per_1000_inch;473473- break;474474- }475475- case fmt_big:{476476- int segments_per_1000_inch = 1; /* non-zero default for switch */477477- switch (ft_qic_std) {478478- case QIC_TAPE_QIC40:479479- segments_per_1000_inch = 332;480480- break;481481- case QIC_TAPE_QIC80:482482- segments_per_1000_inch = 488;483483- break;484484- case QIC_TAPE_QIC3010:485485- segments_per_1000_inch = 730;486486- break;487487- case QIC_TAPE_QIC3020:488488- segments_per_1000_inch = 1430;489489- break;490490- default:491491- TRACE_ABORT(-EIO, ft_t_bug,492492- "%x QIC-standard with fmt-code %d, please report",493493- ft_qic_std, ft_format_code);494494- }495495- new_tape_len = ((1000 * ft_segments_per_track +496496- (segments_per_1000_inch - 1)) / 497497- segments_per_1000_inch);498498- break;499499- }500500- default:501501- TRACE_ABORT(-EIO, ft_t_err,502502- "unknown tape format, please report !");503503- }504504- if (new_tape_len != ftape_tape_len) {505505- ftape_tape_len = new_tape_len;506506- TRACE(ft_t_info, "calculated tape length is %d ft",507507- ftape_tape_len);508508- ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);509509- }510510- if (ft_segments_per_track == 0 && ft_tracks_per_tape == 0 &&511511- max_floppy_side == 0 && max_floppy_track == 0 &&512512- max_floppy_sector == 0) {513513- /* QIC-40 Rev E and earlier has no values in the header.514514- */515515- ft_segments_per_track = 68;516516- ft_tracks_per_tape = 20;517517- max_floppy_side = 1;518518- max_floppy_track = 169;519519- max_floppy_sector = 128;520520- }521521- /* This test will compensate for the wrong parameter on tapes522522- * formatted by Conner software.523523- */524524- if (ft_segments_per_track == 150 &&525525- ft_tracks_per_tape == 28 &&526526- max_floppy_side == 7 &&527527- max_floppy_track == 149 &&528528- max_floppy_sector == 128) {529529-TRACE(ft_t_info, "the famous CONNER bug: max_floppy_side off by one !");530530- max_floppy_side = 6;531531- }532532- /* These tests will compensate for the wrong parameter on tapes533533- * formatted by ComByte Windows software.534534- *535535- * First, for 205 foot tapes536536- */537537- if (ft_segments_per_track == 100 &&538538- ft_tracks_per_tape == 28 &&539539- max_floppy_side == 9 &&540540- max_floppy_track == 149 &&541541- max_floppy_sector == 128) {542542-TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");543543- max_floppy_side = 4;544544- }545545- /* Next, for 307 foot tapes. */546546- if (ft_segments_per_track == 150 &&547547- ft_tracks_per_tape == 28 &&548548- max_floppy_side == 9 &&549549- max_floppy_track == 149 &&550550- max_floppy_sector == 128) {551551-TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");552552- max_floppy_side = 6;553553- }554554- /* This test will compensate for the wrong parameter on tapes555555- * formatted by Colorado Windows software.556556- */557557- if (ft_segments_per_track == 150 &&558558- ft_tracks_per_tape == 28 &&559559- max_floppy_side == 6 &&560560- max_floppy_track == 150 &&561561- max_floppy_sector == 128) {562562-TRACE(ft_t_info, "the famous Colorado bug: max_floppy_track off by one !");563563- max_floppy_track = 149;564564- }565565- ftape_segments_per_head = ((max_floppy_sector/FT_SECTORS_PER_SEGMENT) *566566- (max_floppy_track + 1));567567- /* This test will compensate for some bug reported by Dima568568- * Brodsky. Seems to be a Colorado bug, either. (freebee569569- * Imation tape shipped together with Colorado T3000570570- */571571- if ((ft_format_code == fmt_var || ft_format_code == fmt_big) &&572572- ft_tracks_per_tape == 50 &&573573- max_floppy_side == 54 &&574574- max_floppy_track == 255 &&575575- max_floppy_sector == 128) {576576-TRACE(ft_t_info, "the famous ??? bug: max_floppy_track off by one !");577577- max_floppy_track = 254;578578- }579579- /*580580- * Verify drive_configuration with tape parameters581581- */582582- if (ftape_segments_per_head == 0 || ftape_segments_per_cylinder == 0 ||583583- ((ft_segments_per_track * ft_tracks_per_tape - 1) / ftape_segments_per_head584584- != max_floppy_side) ||585585- (ftape_segments_per_head / ftape_segments_per_cylinder - 1 != max_floppy_track) ||586586- (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT != max_floppy_sector)587587-#ifdef TESTING588588- || ((ft_format_code == fmt_var || ft_format_code == fmt_big) && 589589- (max_floppy_track != 254 || max_floppy_sector != 128))590590-#endif591591- ) {592592- char segperheadz = ftape_segments_per_head ? ' ' : '?';593593- char segpercylz = ftape_segments_per_cylinder ? ' ' : '?';594594- TRACE(ft_t_err,"Tape parameters inconsistency, please report");595595- TRACE(ft_t_err, "reported = %d/%d/%d/%d/%d/%d",596596- ft_format_code,597597- ft_segments_per_track,598598- ft_tracks_per_tape,599599- max_floppy_side,600600- max_floppy_track,601601- max_floppy_sector);602602- TRACE(ft_t_err, "required = %d/%d/%d/%d%c/%d%c/%d",603603- ft_format_code,604604- ft_segments_per_track,605605- ft_tracks_per_tape,606606- ftape_segments_per_head ?607607- ((ft_segments_per_track * ft_tracks_per_tape -1) / 608608- ftape_segments_per_head ) :609609- (ft_segments_per_track * ft_tracks_per_tape -1),610610- segperheadz,611611- ftape_segments_per_cylinder ?612612- (ftape_segments_per_head / 613613- ftape_segments_per_cylinder - 1 ) :614614- ftape_segments_per_head - 1,615615- segpercylz,616616- (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT));617617- TRACE_EXIT -EIO;618618- }619619- ftape_extract_bad_sector_map(address);620620- TRACE_EXIT 0;621621-}
-51
drivers/char/ftape/lowlevel/ftape-read.h
···11-#ifndef _FTAPE_READ_H22-#define _FTAPE_READ_H33-44-/*55- * Copyright (C) 1994-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:22 $2626- *2727- * This file contains the definitions for the read functions2828- * for the QIC-117 floppy-tape driver for Linux.2929- *3030- */3131-3232-/* ftape-read.c defined global functions.3333- */3434-typedef enum {3535- FT_RD_SINGLE = 0,3636- FT_RD_AHEAD = 1,3737-} ft_read_mode_t;3838-3939-extern int ftape_read_header_segment(__u8 *address);4040-extern int ftape_decode_header_segment(__u8 *address);4141-extern int ftape_read_segment_fraction(const int segment,4242- void *address, 4343- const ft_read_mode_t read_mode,4444- const int start,4545- const int size);4646-#define ftape_read_segment(segment, address, read_mode) \4747- ftape_read_segment_fraction(segment, address, read_mode, \4848- 0, FT_SEGMENT_SIZE)4949-extern void ftape_zap_read_buffers(void);5050-5151-#endif /* _FTAPE_READ_H */
-1092
drivers/char/ftape/lowlevel/ftape-rw.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven,33- * (C) 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-rw.c,v $2121- * $Revision: 1.7 $2222- * $Date: 1997/10/28 14:26:49 $2323- *2424- * This file contains some common code for the segment read and2525- * segment write routines for the QIC-117 floppy-tape driver for2626- * Linux.2727- */2828-2929-#include <linux/string.h>3030-#include <linux/errno.h>3131-3232-#include <linux/ftape.h>3333-#include <linux/qic117.h>3434-#include "../lowlevel/ftape-tracing.h"3535-#include "../lowlevel/ftape-rw.h"3636-#include "../lowlevel/fdc-io.h"3737-#include "../lowlevel/ftape-init.h"3838-#include "../lowlevel/ftape-io.h"3939-#include "../lowlevel/ftape-ctl.h"4040-#include "../lowlevel/ftape-read.h"4141-#include "../lowlevel/ftape-ecc.h"4242-#include "../lowlevel/ftape-bsm.h"4343-4444-/* Global vars.4545- */4646-int ft_nr_buffers;4747-buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS];4848-static volatile int ft_head;4949-static volatile int ft_tail; /* not volatile but need same type as head */5050-int fdc_setup_error;5151-location_record ft_location = {-1, 0};5252-volatile int ftape_tape_running;5353-5454-/* Local vars.5555- */5656-static int overrun_count_offset;5757-static int inhibit_correction;5858-5959-/* maxmimal allowed overshoot when fast seeking6060- */6161-#define OVERSHOOT_LIMIT 106262-6363-/* Increment cyclic buffer nr.6464- */6565-buffer_struct *ftape_next_buffer(ft_buffer_queue_t pos)6666-{6767- switch (pos) {6868- case ft_queue_head:6969- if (++ft_head >= ft_nr_buffers) {7070- ft_head = 0;7171- }7272- return ft_buffer[ft_head];7373- case ft_queue_tail:7474- if (++ft_tail >= ft_nr_buffers) {7575- ft_tail = 0;7676- }7777- return ft_buffer[ft_tail];7878- default:7979- return NULL;8080- }8181-}8282-int ftape_buffer_id(ft_buffer_queue_t pos)8383-{8484- switch(pos) {8585- case ft_queue_head: return ft_head;8686- case ft_queue_tail: return ft_tail;8787- default: return -1;8888- }8989-}9090-buffer_struct *ftape_get_buffer(ft_buffer_queue_t pos)9191-{9292- switch(pos) {9393- case ft_queue_head: return ft_buffer[ft_head];9494- case ft_queue_tail: return ft_buffer[ft_tail];9595- default: return NULL;9696- }9797-}9898-void ftape_reset_buffer(void)9999-{100100- ft_head = ft_tail = 0;101101-}102102-103103-buffer_state_enum ftape_set_state(buffer_state_enum new_state)104104-{105105- buffer_state_enum old_state = ft_driver_state;106106-107107- ft_driver_state = new_state;108108- return old_state;109109-}110110-/* Calculate Floppy Disk Controller and DMA parameters for a segment.111111- * head: selects buffer struct in array.112112- * offset: number of physical sectors to skip (including bad ones).113113- * count: number of physical sectors to handle (including bad ones).114114- */115115-static int setup_segment(buffer_struct * buff, 116116- int segment_id,117117- unsigned int sector_offset, 118118- unsigned int sector_count, 119119- int retry)120120-{121121- SectorMap offset_mask;122122- SectorMap mask;123123- TRACE_FUN(ft_t_any);124124-125125- buff->segment_id = segment_id;126126- buff->sector_offset = sector_offset;127127- buff->remaining = sector_count;128128- buff->head = segment_id / ftape_segments_per_head;129129- buff->cyl = (segment_id % ftape_segments_per_head) / ftape_segments_per_cylinder;130130- buff->sect = (segment_id % ftape_segments_per_cylinder) * FT_SECTORS_PER_SEGMENT + 1;131131- buff->deleted = 0;132132- offset_mask = (1 << buff->sector_offset) - 1;133133- mask = ftape_get_bad_sector_entry(segment_id) & offset_mask;134134- while (mask) {135135- if (mask & 1) {136136- offset_mask >>= 1; /* don't count bad sector */137137- }138138- mask >>= 1;139139- }140140- buff->data_offset = count_ones(offset_mask); /* good sectors to skip */141141- buff->ptr = buff->address + buff->data_offset * FT_SECTOR_SIZE;142142- TRACE(ft_t_flow, "data offset = %d sectors", buff->data_offset);143143- if (retry) {144144- buff->soft_error_map &= offset_mask; /* keep skipped part */145145- } else {146146- buff->hard_error_map = buff->soft_error_map = 0;147147- }148148- buff->bad_sector_map = ftape_get_bad_sector_entry(buff->segment_id);149149- if (buff->bad_sector_map != 0) {150150- TRACE(ft_t_noise, "segment: %d, bad sector map: %08lx",151151- buff->segment_id, (long)buff->bad_sector_map);152152- } else {153153- TRACE(ft_t_flow, "segment: %d", buff->segment_id);154154- }155155- if (buff->sector_offset > 0) {156156- buff->bad_sector_map >>= buff->sector_offset;157157- }158158- if (buff->sector_offset != 0 || buff->remaining != FT_SECTORS_PER_SEGMENT) {159159- TRACE(ft_t_flow, "sector offset = %d, count = %d",160160- buff->sector_offset, buff->remaining);161161- }162162- /* Segments with 3 or less sectors are not written with valid163163- * data because there is no space left for the ecc. The164164- * data written is whatever happens to be in the buffer.165165- * Reading such a segment will return a zero byte-count.166166- * To allow us to read/write segments with all bad sectors167167- * we fake one readable sector in the segment. This168168- * prevents having to handle these segments in a very169169- * special way. It is not important if the reading of this170170- * bad sector fails or not (the data is ignored). It is171171- * only read to keep the driver running.172172- *173173- * The QIC-40/80 spec. has no information on how to handle174174- * this case, so this is my interpretation. 175175- */176176- if (buff->bad_sector_map == EMPTY_SEGMENT) {177177- TRACE(ft_t_flow, "empty segment %d, fake first sector good",178178- buff->segment_id);179179- if (buff->ptr != buff->address) {180180- TRACE(ft_t_bug, "This is a bug: %p/%p",181181- buff->ptr, buff->address);182182- }183183- buff->bad_sector_map = FAKE_SEGMENT;184184- }185185- fdc_setup_error = 0;186186- buff->next_segment = segment_id + 1;187187- TRACE_EXIT 0;188188-}189189-190190-/* Calculate Floppy Disk Controller and DMA parameters for a new segment.191191- */192192-int ftape_setup_new_segment(buffer_struct * buff, int segment_id, int skip)193193-{194194- int result = 0;195195- static int old_segment_id = -1;196196- static buffer_state_enum old_ft_driver_state = idle;197197- int retry = 0;198198- unsigned offset = 0;199199- int count = FT_SECTORS_PER_SEGMENT;200200- TRACE_FUN(ft_t_flow);201201-202202- TRACE(ft_t_flow, "%s segment %d (old = %d)",203203- (ft_driver_state == reading || ft_driver_state == verifying) 204204- ? "reading" : "writing",205205- segment_id, old_segment_id);206206- if (ft_driver_state != old_ft_driver_state) { /* when verifying */207207- old_segment_id = -1;208208- old_ft_driver_state = ft_driver_state;209209- }210210- if (segment_id == old_segment_id) {211211- ++buff->retry;212212- ++ft_history.retries;213213- TRACE(ft_t_flow, "setting up for retry nr %d", buff->retry);214214- retry = 1;215215- if (skip && buff->skip > 0) { /* allow skip on retry */216216- offset = buff->skip;217217- count -= offset;218218- TRACE(ft_t_flow, "skipping %d sectors", offset);219219- }220220- } else {221221- buff->retry = 0;222222- buff->skip = 0;223223- old_segment_id = segment_id;224224- }225225- result = setup_segment(buff, segment_id, offset, count, retry);226226- TRACE_EXIT result;227227-}228228-229229-/* Determine size of next cluster of good sectors.230230- */231231-int ftape_calc_next_cluster(buffer_struct * buff)232232-{233233- /* Skip bad sectors.234234- */235235- while (buff->remaining > 0 && (buff->bad_sector_map & 1) != 0) {236236- buff->bad_sector_map >>= 1;237237- ++buff->sector_offset;238238- --buff->remaining;239239- }240240- /* Find next cluster of good sectors241241- */242242- if (buff->bad_sector_map == 0) { /* speed up */243243- buff->sector_count = buff->remaining;244244- } else {245245- SectorMap map = buff->bad_sector_map;246246-247247- buff->sector_count = 0;248248- while (buff->sector_count < buff->remaining && (map & 1) == 0) {249249- ++buff->sector_count;250250- map >>= 1;251251- }252252- }253253- return buff->sector_count;254254-}255255-256256-/* if just passed the last segment on a track, wait for BOT257257- * or EOT mark.258258- */259259-int ftape_handle_logical_eot(void)260260-{261261- TRACE_FUN(ft_t_flow);262262-263263- if (ft_runner_status == logical_eot) {264264- int status;265265-266266- TRACE(ft_t_noise, "tape at logical EOT");267267- TRACE_CATCH(ftape_ready_wait(ftape_timeout.seek, &status),);268268- if ((status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) {269269- TRACE_ABORT(-EIO, ft_t_err, "eot/bot not reached");270270- }271271- ft_runner_status = end_of_tape;272272- }273273- if (ft_runner_status == end_of_tape) {274274- TRACE(ft_t_noise, "runner stopped because of logical EOT");275275- ft_runner_status = idle;276276- }277277- TRACE_EXIT 0;278278-}279279-280280-static int check_bot_eot(int status)281281-{282282- TRACE_FUN(ft_t_flow);283283-284284- if (status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) {285285- ft_location.bot = ((ft_location.track & 1) == 0 ?286286- (status & QIC_STATUS_AT_BOT) != 0:287287- (status & QIC_STATUS_AT_EOT) != 0);288288- ft_location.eot = !ft_location.bot;289289- ft_location.segment = (ft_location.track +290290- (ft_location.bot ? 0 : 1)) * ft_segments_per_track - 1;291291- ft_location.sector = -1;292292- ft_location.known = 1;293293- TRACE(ft_t_flow, "tape at logical %s",294294- ft_location.bot ? "bot" : "eot");295295- TRACE(ft_t_flow, "segment = %d", ft_location.segment);296296- } else {297297- ft_location.known = 0;298298- }299299- TRACE_EXIT ft_location.known;300300-}301301-302302-/* Read Id of first sector passing tape head.303303- */304304-static int ftape_read_id(void)305305-{306306- int status;307307- __u8 out[2];308308- TRACE_FUN(ft_t_any);309309-310310- /* Assume tape is running on entry, be able to handle311311- * situation where it stopped or is stopping.312312- */313313- ft_location.known = 0; /* default is location not known */314314- out[0] = FDC_READID;315315- out[1] = ft_drive_sel;316316- TRACE_CATCH(fdc_command(out, 2),);317317- switch (fdc_interrupt_wait(20 * FT_SECOND)) {318318- case 0:319319- if (fdc_sect == 0) {320320- if (ftape_report_drive_status(&status) >= 0 &&321321- (status & QIC_STATUS_READY)) {322322- ftape_tape_running = 0;323323- TRACE(ft_t_flow, "tape has stopped");324324- check_bot_eot(status);325325- }326326- } else {327327- ft_location.known = 1;328328- ft_location.segment = (ftape_segments_per_head329329- * fdc_head330330- + ftape_segments_per_cylinder331331- * fdc_cyl332332- + (fdc_sect - 1)333333- / FT_SECTORS_PER_SEGMENT);334334- ft_location.sector = ((fdc_sect - 1)335335- % FT_SECTORS_PER_SEGMENT);336336- ft_location.eot = ft_location.bot = 0;337337- }338338- break;339339- case -ETIME:340340- /* Didn't find id on tape, must be near end: Wait341341- * until stopped.342342- */343343- if (ftape_ready_wait(FT_FOREVER, &status) >= 0) {344344- ftape_tape_running = 0;345345- TRACE(ft_t_flow, "tape has stopped");346346- check_bot_eot(status);347347- }348348- break;349349- default:350350- /* Interrupted or otherwise failing351351- * fdc_interrupt_wait() 352352- */353353- TRACE(ft_t_err, "fdc_interrupt_wait failed");354354- break;355355- }356356- if (!ft_location.known) {357357- TRACE_ABORT(-EIO, ft_t_flow, "no id found");358358- }359359- if (ft_location.sector == 0) {360360- TRACE(ft_t_flow, "passing segment %d/%d",361361- ft_location.segment, ft_location.sector);362362- } else {363363- TRACE(ft_t_fdc_dma, "passing segment %d/%d",364364- ft_location.segment, ft_location.sector);365365- }366366- TRACE_EXIT 0;367367-}368368-369369-static int logical_forward(void)370370-{371371- ftape_tape_running = 1;372372- return ftape_command(QIC_LOGICAL_FORWARD);373373-}374374-375375-int ftape_stop_tape(int *pstatus)376376-{377377- int retry = 0;378378- int result;379379- TRACE_FUN(ft_t_flow);380380-381381- do {382382- result = ftape_command_wait(QIC_STOP_TAPE,383383- ftape_timeout.stop, pstatus);384384- if (result == 0) {385385- if ((*pstatus & QIC_STATUS_READY) == 0) {386386- result = -EIO;387387- } else {388388- ftape_tape_running = 0;389389- }390390- }391391- } while (result < 0 && ++retry <= 3);392392- if (result < 0) {393393- TRACE(ft_t_err, "failed ! (fatal)");394394- }395395- TRACE_EXIT result;396396-}397397-398398-int ftape_dumb_stop(void)399399-{400400- int result;401401- int status;402402- TRACE_FUN(ft_t_flow);403403-404404- /* Abort current fdc operation if it's busy (probably read405405- * or write operation pending) with a reset.406406- */407407- if (fdc_ready_wait(100 /* usec */) < 0) {408408- TRACE(ft_t_noise, "aborting fdc operation");409409- fdc_reset();410410- }411411- /* Reading id's after the last segment on a track may fail412412- * but eventually the drive will become ready (logical eot).413413- */414414- result = ftape_report_drive_status(&status);415415- ft_location.known = 0;416416- do {417417- if (result == 0 && status & QIC_STATUS_READY) {418418- /* Tape is not running any more.419419- */420420- TRACE(ft_t_noise, "tape already halted");421421- check_bot_eot(status);422422- ftape_tape_running = 0;423423- } else if (ftape_tape_running) {424424- /* Tape is (was) still moving.425425- */426426-#ifdef TESTING427427- ftape_read_id();428428-#endif429429- result = ftape_stop_tape(&status);430430- } else {431431- /* Tape not yet ready but stopped.432432- */433433- result = ftape_ready_wait(ftape_timeout.pause,&status);434434- }435435- } while (ftape_tape_running436436- && !(sigtestsetmask(¤t->pending.signal, _NEVER_BLOCK)));437437-#ifndef TESTING438438- ft_location.known = 0;439439-#endif440440- if (ft_runner_status == aborting || ft_runner_status == do_abort) {441441- ft_runner_status = idle;442442- }443443- TRACE_EXIT result;444444-}445445-446446-/* Wait until runner has finished tail buffer.447447- *448448- */449449-int ftape_wait_segment(buffer_state_enum state)450450-{451451- int status;452452- int result = 0;453453- TRACE_FUN(ft_t_flow);454454-455455- while (ft_buffer[ft_tail]->status == state) {456456- TRACE(ft_t_flow, "state: %d", ft_buffer[ft_tail]->status);457457- /* First buffer still being worked on, wait up to timeout.458458- *459459- * Note: we check two times for being killed. 50460460- * seconds are quite long. Note that461461- * fdc_interrupt_wait() is not killable by any462462- * means. ftape_read_segment() wants us to return463463- * -EINTR in case of a signal. 464464- */465465- FT_SIGNAL_EXIT(_DONT_BLOCK);466466- result = fdc_interrupt_wait(50 * FT_SECOND);467467- FT_SIGNAL_EXIT(_DONT_BLOCK);468468- if (result < 0) {469469- TRACE_ABORT(result,470470- ft_t_err, "fdc_interrupt_wait failed");471471- }472472- if (fdc_setup_error) {473473- /* recover... FIXME */474474- TRACE_ABORT(-EIO, ft_t_err, "setup error");475475- }476476- }477477- if (ft_buffer[ft_tail]->status != error) {478478- TRACE_EXIT 0;479479- }480480- TRACE_CATCH(ftape_report_drive_status(&status),);481481- TRACE(ft_t_noise, "ftape_report_drive_status: 0x%02x", status);482482- if ((status & QIC_STATUS_READY) && 483483- (status & QIC_STATUS_ERROR)) {484484- unsigned int error;485485- qic117_cmd_t command;486486-487487- /* Report and clear error state.488488- * In case the drive can't operate at the selected489489- * rate, select the next lower data rate.490490- */491491- ftape_report_error(&error, &command, 1);492492- if (error == 31 && command == QIC_LOGICAL_FORWARD) {493493- /* drive does not accept this data rate */494494- if (ft_data_rate > 250) {495495- TRACE(ft_t_info,496496- "Probable data rate conflict");497497- TRACE(ft_t_info,498498- "Lowering data rate to %d Kbps",499499- ft_data_rate / 2);500500- ftape_half_data_rate();501501- if (ft_buffer[ft_tail]->retry > 0) {502502- /* give it a chance */503503- --ft_buffer[ft_tail]->retry;504504- }505505- } else {506506- /* no rate is accepted... */507507- TRACE(ft_t_err, "We're dead :(");508508- }509509- } else {510510- TRACE(ft_t_err, "Unknown error");511511- }512512- TRACE_EXIT -EIO; /* g.p. error */513513- }514514- TRACE_EXIT 0;515515-}516516-517517-/* forward */ static int seek_forward(int segment_id, int fast);518518-519519-static int fast_seek(int count, int reverse)520520-{521521- int result = 0;522522- int status;523523- TRACE_FUN(ft_t_flow);524524-525525- if (count > 0) {526526- /* If positioned at begin or end of tape, fast seeking needs527527- * special treatment.528528- * Starting from logical bot needs a (slow) seek to the first529529- * segment before the high speed seek. Most drives do this530530- * automatically but some older don't, so we treat them531531- * all the same.532532- * Starting from logical eot is even more difficult because533533- * we cannot (slow) reverse seek to the last segment.534534- * TO BE IMPLEMENTED.535535- */536536- inhibit_correction = 0;537537- if (ft_location.known &&538538- ((ft_location.bot && !reverse) ||539539- (ft_location.eot && reverse))) {540540- if (!reverse) {541541- /* (slow) skip to first segment on a track542542- */543543- seek_forward(ft_location.track * ft_segments_per_track, 0);544544- --count;545545- } else {546546- /* When seeking backwards from547547- * end-of-tape the number of erased548548- * gaps found seems to be higher than549549- * expected. Therefor the drive must550550- * skip some more segments than551551- * calculated, but we don't know how552552- * many. Thus we will prevent the553553- * re-calculation of offset and554554- * overshoot when seeking backwards.555555- */556556- inhibit_correction = 1;557557- count += 3; /* best guess */558558- }559559- }560560- } else {561561- TRACE(ft_t_flow, "warning: zero or negative count: %d", count);562562- }563563- if (count > 0) {564564- int i;565565- int nibbles = count > 255 ? 3 : 2;566566-567567- if (count > 4095) {568568- TRACE(ft_t_noise, "skipping clipped at 4095 segment");569569- count = 4095;570570- }571571- /* Issue this tape command first. */572572- if (!reverse) {573573- TRACE(ft_t_noise, "skipping %d segment(s)", count);574574- result = ftape_command(nibbles == 3 ?575575- QIC_SKIP_EXTENDED_FORWARD : QIC_SKIP_FORWARD);576576- } else {577577- TRACE(ft_t_noise, "backing up %d segment(s)", count);578578- result = ftape_command(nibbles == 3 ?579579- QIC_SKIP_EXTENDED_REVERSE : QIC_SKIP_REVERSE);580580- }581581- if (result < 0) {582582- TRACE(ft_t_noise, "Skip command failed");583583- } else {584584- --count; /* 0 means one gap etc. */585585- for (i = 0; i < nibbles; ++i) {586586- if (result >= 0) {587587- result = ftape_parameter(count & 15);588588- count /= 16;589589- }590590- }591591- result = ftape_ready_wait(ftape_timeout.rewind, &status);592592- if (result >= 0) {593593- ftape_tape_running = 0;594594- }595595- }596596- }597597- TRACE_EXIT result;598598-}599599-600600-static int validate(int id)601601-{602602- /* Check to see if position found is off-track as reported603603- * once. Because all tracks in one direction lie next to604604- * each other, if off-track the error will be approximately605605- * 2 * ft_segments_per_track.606606- */607607- if (ft_location.track == -1) {608608- return 1; /* unforseen situation, don't generate error */609609- } else {610610- /* Use margin of ft_segments_per_track on both sides611611- * because ftape needs some margin and the error we're612612- * looking for is much larger !613613- */614614- int lo = (ft_location.track - 1) * ft_segments_per_track;615615- int hi = (ft_location.track + 2) * ft_segments_per_track;616616-617617- return (id >= lo && id < hi);618618- }619619-}620620-621621-static int seek_forward(int segment_id, int fast)622622-{623623- int failures = 0;624624- int count;625625- static int margin = 1; /* fixed: stop this before target */626626- static int overshoot = 1;627627- static int min_count = 8;628628- int expected = -1;629629- int target = segment_id - margin;630630- int fast_seeking;631631- int prev_segment = ft_location.segment;632632- TRACE_FUN(ft_t_flow);633633-634634- if (!ft_location.known) {635635- TRACE_ABORT(-EIO, ft_t_err,636636- "fatal: cannot seek from unknown location");637637- }638638- if (!validate(segment_id)) {639639- ftape_sleep(1 * FT_SECOND);640640- ft_failure = 1;641641- TRACE_ABORT(-EIO, ft_t_err,642642- "fatal: head off track (bad hardware?)");643643- }644644- TRACE(ft_t_noise, "from %d/%d to %d/0 - %d",645645- ft_location.segment, ft_location.sector,segment_id,margin);646646- count = target - ft_location.segment - overshoot;647647- fast_seeking = (fast &&648648- count > (min_count + (ft_location.bot ? 1 : 0)));649649- if (fast_seeking) {650650- TRACE(ft_t_noise, "fast skipping %d segments", count);651651- expected = segment_id - margin;652652- fast_seek(count, 0);653653- }654654- if (!ftape_tape_running) {655655- logical_forward();656656- }657657- while (ft_location.segment < segment_id) {658658- /* This requires at least one sector in a (bad) segment to659659- * have a valid and readable sector id !660660- * It looks like this is not guaranteed, so we must try661661- * to find a way to skip an EMPTY_SEGMENT. !!! FIXME !!!662662- */663663- if (ftape_read_id() < 0 || !ft_location.known ||664664- sigtestsetmask(¤t->pending.signal, _DONT_BLOCK)) {665665- ft_location.known = 0;666666- if (!ftape_tape_running ||667667- ++failures > FT_SECTORS_PER_SEGMENT) {668668- TRACE_ABORT(-EIO, ft_t_err,669669- "read_id failed completely");670670- }671671- FT_SIGNAL_EXIT(_DONT_BLOCK);672672- TRACE(ft_t_flow, "read_id failed, retry (%d)",673673- failures);674674- continue;675675- }676676- if (fast_seeking) {677677- TRACE(ft_t_noise, "ended at %d/%d (%d,%d)",678678- ft_location.segment, ft_location.sector,679679- overshoot, inhibit_correction);680680- if (!inhibit_correction &&681681- (ft_location.segment < expected ||682682- ft_location.segment > expected + margin)) {683683- int error = ft_location.segment - expected;684684- TRACE(ft_t_noise,685685- "adjusting overshoot from %d to %d",686686- overshoot, overshoot + error);687687- overshoot += error;688688- /* All overshoots have the same689689- * direction, so it should never690690- * become negative, but who knows.691691- */692692- if (overshoot < -5 ||693693- overshoot > OVERSHOOT_LIMIT) {694694- if (overshoot < 0) {695695- /* keep sane value */696696- overshoot = -5;697697- } else {698698- /* keep sane value */699699- overshoot = OVERSHOOT_LIMIT;700700- }701701- TRACE(ft_t_noise,702702- "clipped overshoot to %d",703703- overshoot);704704- }705705- }706706- fast_seeking = 0;707707- }708708- if (ft_location.known) {709709- if (ft_location.segment > prev_segment + 1) {710710- TRACE(ft_t_noise,711711- "missed segment %d while skipping",712712- prev_segment + 1);713713- }714714- prev_segment = ft_location.segment;715715- }716716- }717717- if (ft_location.segment > segment_id) {718718- TRACE_ABORT(-EIO,719719- ft_t_noise, "failed: skip ended at segment %d/%d",720720- ft_location.segment, ft_location.sector);721721- }722722- TRACE_EXIT 0;723723-}724724-725725-static int skip_reverse(int segment_id, int *pstatus)726726-{727727- int failures = 0;728728- static int overshoot = 1;729729- static int min_rewind = 2; /* 1 + overshoot */730730- static const int margin = 1; /* stop this before target */731731- int expected = 0;732732- int count = 1;733733- int short_seek;734734- int target = segment_id - margin;735735- TRACE_FUN(ft_t_flow);736736-737737- if (ft_location.known && !validate(segment_id)) {738738- ftape_sleep(1 * FT_SECOND);739739- ft_failure = 1;740740- TRACE_ABORT(-EIO, ft_t_err,741741- "fatal: head off track (bad hardware?)");742742- }743743- do {744744- if (!ft_location.known) {745745- TRACE(ft_t_warn, "warning: location not known");746746- }747747- TRACE(ft_t_noise, "from %d/%d to %d/0 - %d",748748- ft_location.segment, ft_location.sector,749749- segment_id, margin);750750- /* min_rewind == 1 + overshoot_when_doing_minimum_rewind751751- * overshoot == overshoot_when_doing_larger_rewind752752- * Initially min_rewind == 1 + overshoot, optimization753753- * of both values will be done separately.754754- * overshoot and min_rewind can be negative as both are755755- * sums of three components:756756- * any_overshoot == rewind_overshoot - 757757- * stop_overshoot -758758- * start_overshoot759759- */760760- if (ft_location.segment - target - (min_rewind - 1) < 1) {761761- short_seek = 1;762762- } else {763763- count = ft_location.segment - target - overshoot;764764- short_seek = (count < 1);765765- }766766- if (short_seek) {767767- count = 1; /* do shortest rewind */768768- expected = ft_location.segment - min_rewind;769769- if (expected/ft_segments_per_track != ft_location.track) {770770- expected = (ft_location.track * 771771- ft_segments_per_track);772772- }773773- } else {774774- expected = target;775775- }776776- fast_seek(count, 1);777777- logical_forward();778778- if (ftape_read_id() < 0 || !ft_location.known ||779779- (sigtestsetmask(¤t->pending.signal, _DONT_BLOCK))) {780780- if ((!ftape_tape_running && !ft_location.known) ||781781- ++failures > FT_SECTORS_PER_SEGMENT) {782782- TRACE_ABORT(-EIO, ft_t_err,783783- "read_id failed completely");784784- }785785- FT_SIGNAL_EXIT(_DONT_BLOCK);786786- TRACE_CATCH(ftape_report_drive_status(pstatus),);787787- TRACE(ft_t_noise, "ftape_read_id failed, retry (%d)",788788- failures);789789- continue;790790- }791791- TRACE(ft_t_noise, "ended at %d/%d (%d,%d,%d)", 792792- ft_location.segment, ft_location.sector,793793- min_rewind, overshoot, inhibit_correction);794794- if (!inhibit_correction &&795795- (ft_location.segment < expected ||796796- ft_location.segment > expected + margin)) {797797- int error = expected - ft_location.segment;798798- if (short_seek) {799799- TRACE(ft_t_noise,800800- "adjusting min_rewind from %d to %d",801801- min_rewind, min_rewind + error);802802- min_rewind += error;803803- if (min_rewind < -5) {804804- /* is this right ? FIXME ! */805805- /* keep sane value */806806- min_rewind = -5;807807- TRACE(ft_t_noise, 808808- "clipped min_rewind to %d",809809- min_rewind);810810- }811811- } else {812812- TRACE(ft_t_noise,813813- "adjusting overshoot from %d to %d",814814- overshoot, overshoot + error);815815- overshoot += error;816816- if (overshoot < -5 ||817817- overshoot > OVERSHOOT_LIMIT) {818818- if (overshoot < 0) {819819- /* keep sane value */820820- overshoot = -5;821821- } else {822822- /* keep sane value */823823- overshoot = OVERSHOOT_LIMIT;824824- }825825- TRACE(ft_t_noise,826826- "clipped overshoot to %d",827827- overshoot);828828- }829829- }830830- }831831- } while (ft_location.segment > segment_id);832832- if (ft_location.known) {833833- TRACE(ft_t_noise, "current location: %d/%d",834834- ft_location.segment, ft_location.sector);835835- }836836- TRACE_EXIT 0;837837-}838838-839839-static int determine_position(void)840840-{841841- int retry = 0;842842- int status;843843- int result;844844- TRACE_FUN(ft_t_flow);845845-846846- if (!ftape_tape_running) {847847- /* This should only happen if tape is stopped by isr.848848- */849849- TRACE(ft_t_flow, "waiting for tape stop");850850- if (ftape_ready_wait(ftape_timeout.pause, &status) < 0) {851851- TRACE(ft_t_flow, "drive still running (fatal)");852852- ftape_tape_running = 1; /* ? */853853- }854854- } else {855855- ftape_report_drive_status(&status);856856- }857857- if (status & QIC_STATUS_READY) {858858- /* Drive must be ready to check error state !859859- */860860- TRACE(ft_t_flow, "drive is ready");861861- if (status & QIC_STATUS_ERROR) {862862- unsigned int error;863863- qic117_cmd_t command;864864-865865- /* Report and clear error state, try to continue.866866- */867867- TRACE(ft_t_flow, "error status set");868868- ftape_report_error(&error, &command, 1);869869- ftape_ready_wait(ftape_timeout.reset, &status);870870- ftape_tape_running = 0; /* ? */871871- }872872- if (check_bot_eot(status)) {873873- if (ft_location.bot) {874874- if ((status & QIC_STATUS_READY) == 0) {875875- /* tape moving away from876876- * bot/eot, let's see if we877877- * can catch up with the first878878- * segment on this track.879879- */880880- } else {881881- TRACE(ft_t_flow,882882- "start tape from logical bot");883883- logical_forward(); /* start moving */884884- }885885- } else {886886- if ((status & QIC_STATUS_READY) == 0) {887887- TRACE(ft_t_noise, "waiting for logical end of track");888888- result = ftape_ready_wait(ftape_timeout.reset, &status);889889- /* error handling needed ? */890890- } else {891891- TRACE(ft_t_noise,892892- "tape at logical end of track");893893- }894894- }895895- } else {896896- TRACE(ft_t_flow, "start tape");897897- logical_forward(); /* start moving */898898- ft_location.known = 0; /* not cleared by logical forward ! */899899- }900900- }901901- /* tape should be moving now, start reading id's902902- */903903- while (!ft_location.known &&904904- retry++ < FT_SECTORS_PER_SEGMENT &&905905- (result = ftape_read_id()) < 0) {906906-907907- TRACE(ft_t_flow, "location unknown");908908-909909- /* exit on signal910910- */911911- FT_SIGNAL_EXIT(_DONT_BLOCK);912912-913913- /* read-id somehow failed, tape may914914- * have reached end or some other915915- * error happened.916916- */917917- TRACE(ft_t_flow, "read-id failed");918918- TRACE_CATCH(ftape_report_drive_status(&status),);919919- TRACE(ft_t_err, "ftape_report_drive_status: 0x%02x", status);920920- if (status & QIC_STATUS_READY) {921921- ftape_tape_running = 0;922922- TRACE(ft_t_noise, "tape stopped for unknown reason! "923923- "status = 0x%02x", status);924924- if (status & QIC_STATUS_ERROR ||925925- !check_bot_eot(status)) {926926- /* oops, tape stopped but not at end!927927- */928928- TRACE_EXIT -EIO;929929- }930930- }931931- }932932- TRACE(ft_t_flow,933933- "tape is positioned at segment %d", ft_location.segment);934934- TRACE_EXIT ft_location.known ? 0 : -EIO;935935-}936936-937937-/* Get the tape running and position it just before the938938- * requested segment.939939- * Seek tape-track and reposition as needed.940940- */941941-int ftape_start_tape(int segment_id, int sector_offset)942942-{943943- int track = segment_id / ft_segments_per_track;944944- int result = -EIO;945945- int status;946946- static int last_segment = -1;947947- static int bad_bus_timing = 0;948948- /* number of segments passing the head between starting the tape949949- * and being able to access the first sector.950950- */951951- static int start_offset = 1;952952- int retry;953953- TRACE_FUN(ft_t_flow);954954-955955- /* If sector_offset > 0, seek into wanted segment instead of956956- * into previous.957957- * This allows error recovery if a part of the segment is bad958958- * (erased) causing the tape drive to generate an index pulse959959- * thus causing a no-data error before the requested sector960960- * is reached.961961- */962962- ftape_tape_running = 0;963963- TRACE(ft_t_noise, "target segment: %d/%d%s", segment_id, sector_offset,964964- ft_buffer[ft_head]->retry > 0 ? " retry" : "");965965- if (ft_buffer[ft_head]->retry > 0) { /* this is a retry */966966- int dist = segment_id - last_segment;967967-968968- if ((int)ft_history.overrun_errors < overrun_count_offset) {969969- overrun_count_offset = ft_history.overrun_errors;970970- } else if (dist < 0 || dist > 50) {971971- overrun_count_offset = ft_history.overrun_errors;972972- } else if ((ft_history.overrun_errors -973973- overrun_count_offset) >= 8) {974974- if (ftape_increase_threshold() >= 0) {975975- --ft_buffer[ft_head]->retry;976976- overrun_count_offset =977977- ft_history.overrun_errors;978978- TRACE(ft_t_warn, "increased threshold because "979979- "of excessive overrun errors");980980- } else if (!bad_bus_timing && ft_data_rate >= 1000) {981981- ftape_half_data_rate();982982- --ft_buffer[ft_head]->retry;983983- bad_bus_timing = 1;984984- overrun_count_offset =985985- ft_history.overrun_errors;986986- TRACE(ft_t_warn, "reduced datarate because "987987- "of excessive overrun errors");988988- }989989- }990990- }991991- last_segment = segment_id;992992- if (ft_location.track != track ||993993- (ftape_might_be_off_track && ft_buffer[ft_head]->retry== 0)) {994994- /* current track unknown or not equal to destination995995- */996996- ftape_ready_wait(ftape_timeout.seek, &status);997997- ftape_seek_head_to_track(track);998998- /* overrun_count_offset = ft_history.overrun_errors; */999999- }10001000- result = -EIO;10011001- retry = 0;10021002- while (result < 0 &&10031003- retry++ <= 5 &&10041004- !ft_failure &&10051005- !(sigtestsetmask(¤t->pending.signal, _DONT_BLOCK))) {10061006-10071007- if (retry && start_offset < 5) {10081008- start_offset ++;10091009- }10101010- /* Check if we are able to catch the requested10111011- * segment in time.10121012- */10131013- if ((ft_location.known || (determine_position() == 0)) &&10141014- ft_location.segment >=10151015- (segment_id -10161016- ((ftape_tape_running || ft_location.bot)10171017- ? 0 : start_offset))) {10181018- /* Too far ahead (in or past target segment).10191019- */10201020- if (ftape_tape_running) {10211021- if ((result = ftape_stop_tape(&status)) < 0) {10221022- TRACE(ft_t_err,10231023- "stop tape failed with code %d",10241024- result);10251025- break;10261026- }10271027- TRACE(ft_t_noise, "tape stopped");10281028- ftape_tape_running = 0;10291029- }10301030- TRACE(ft_t_noise, "repositioning");10311031- ++ft_history.rewinds;10321032- if (segment_id % ft_segments_per_track < start_offset){10331033- TRACE(ft_t_noise, "end of track condition\n"10341034- KERN_INFO "segment_id : %d\n"10351035- KERN_INFO "ft_segments_per_track: %d\n"10361036- KERN_INFO "start_offset : %d",10371037- segment_id, ft_segments_per_track, 10381038- start_offset);10391039-10401040- /* If seeking to first segments on10411041- * track better do a complete rewind10421042- * to logical begin of track to get a10431043- * more steady tape motion. 10441044- */10451045- result = ftape_command_wait(10461046- (ft_location.track & 1)10471047- ? QIC_PHYSICAL_FORWARD10481048- : QIC_PHYSICAL_REVERSE,10491049- ftape_timeout.rewind, &status);10501050- check_bot_eot(status); /* update location */10511051- } else {10521052- result= skip_reverse(segment_id - start_offset,10531053- &status);10541054- }10551055- }10561056- if (!ft_location.known) {10571057- TRACE(ft_t_bug, "panic: location not known");10581058- result = -EIO;10591059- continue; /* while() will check for failure */10601060- }10611061- TRACE(ft_t_noise, "current segment: %d/%d",10621062- ft_location.segment, ft_location.sector);10631063- /* We're on the right track somewhere before the10641064- * wanted segment. Start tape movement if needed and10651065- * skip to just before or inside the requested10661066- * segment. Keep tape running. 10671067- */10681068- result = 0;10691069- if (ft_location.segment < 10701070- (segment_id - ((ftape_tape_running || ft_location.bot)10711071- ? 0 : start_offset))) {10721072- if (sector_offset > 0) {10731073- result = seek_forward(segment_id,10741074- retry <= 3);10751075- } else {10761076- result = seek_forward(segment_id - 1,10771077- retry <= 3);10781078- }10791079- }10801080- if (result == 0 &&10811081- ft_location.segment !=10821082- (segment_id - (sector_offset > 0 ? 0 : 1))) {10831083- result = -EIO;10841084- }10851085- }10861086- if (result < 0) {10871087- TRACE(ft_t_err, "failed to reposition");10881088- } else {10891089- ft_runner_status = running;10901090- }10911091- TRACE_EXIT result;10921092-}
-111
drivers/char/ftape/lowlevel/ftape-rw.h
···11-#ifndef _FTAPE_RW_H22-#define _FTAPE_RW_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-rw.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:25 $2626- *2727- * This file contains the definitions for the read and write2828- * functions for the QIC-117 floppy-tape driver for Linux.2929- *3030- * Claus-Justus Heine (1996/09/20): Add definition of format code 63131- * Claus-Justus Heine (1996/10/04): Changed GET/PUT macros to cast to (__u8 *)3232- *3333- */3434-3535-#include "../lowlevel/fdc-io.h"3636-#include "../lowlevel/ftape-init.h"3737-#include "../lowlevel/ftape-bsm.h"3838-3939-#include <asm/unaligned.h>4040-4141-#define GET2(address, offset) get_unaligned((__u16*)((__u8 *)address + offset))4242-#define GET4(address, offset) get_unaligned((__u32*)((__u8 *)address + offset))4343-#define GET8(address, offset) get_unaligned((__u64*)((__u8 *)address + offset))4444-#define PUT2(address, offset , value) put_unaligned((value), (__u16*)((__u8 *)address + offset))4545-#define PUT4(address, offset , value) put_unaligned((value), (__u32*)((__u8 *)address + offset))4646-#define PUT8(address, offset , value) put_unaligned((value), (__u64*)((__u8 *)address + offset))4747-4848-enum runner_status_enum {4949- idle = 0,5050- running,5151- do_abort,5252- aborting,5353- logical_eot,5454- end_of_tape,5555-};5656-5757-typedef enum ft_buffer_queue {5858- ft_queue_head = 0,5959- ft_queue_tail = 16060-} ft_buffer_queue_t;6161-6262-6363-typedef struct {6464- int track; /* tape head position */6565- volatile int segment; /* current segment */6666- volatile int sector; /* sector offset within current segment */6767- volatile unsigned int bot; /* logical begin of track */6868- volatile unsigned int eot; /* logical end of track */6969- volatile unsigned int known; /* validates bot, segment, sector */7070-} location_record;7171-7272-/* Count nr of 1's in pattern.7373- */7474-static inline int count_ones(unsigned long mask)7575-{7676- int bits;7777-7878- for (bits = 0; mask != 0; mask >>= 1) {7979- if (mask & 1) {8080- ++bits;8181- }8282- }8383- return bits;8484-}8585-8686-#define FT_MAX_NR_BUFFERS 16 /* arbitrary value */8787-/* ftape-rw.c defined global vars.8888- */8989-extern buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS];9090-extern int ft_nr_buffers;9191-extern location_record ft_location;9292-extern volatile int ftape_tape_running;9393-9494-/* ftape-rw.c defined global functions.9595- */9696-extern int ftape_setup_new_segment(buffer_struct * buff,9797- int segment_id,9898- int offset);9999-extern int ftape_calc_next_cluster(buffer_struct * buff);100100-extern buffer_struct *ftape_next_buffer (ft_buffer_queue_t pos);101101-extern buffer_struct *ftape_get_buffer (ft_buffer_queue_t pos);102102-extern int ftape_buffer_id (ft_buffer_queue_t pos);103103-extern void ftape_reset_buffer(void);104104-extern void ftape_tape_parameters(__u8 drive_configuration);105105-extern int ftape_wait_segment(buffer_state_enum state);106106-extern int ftape_dumb_stop(void);107107-extern int ftape_start_tape(int segment_id, int offset);108108-extern int ftape_stop_tape(int *pstatus);109109-extern int ftape_handle_logical_eot(void);110110-extern buffer_state_enum ftape_set_state(buffer_state_enum new_state);111111-#endif /* _FTAPE_RW_H */
-104
drivers/char/ftape/lowlevel/ftape-setup.c
···11-/* 22- * Copyright (C) 1996, 1997 Claus-Justus Heine.33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-setup.c,v $2020- * $Revision: 1.7 $2121- * $Date: 1997/10/10 09:57:06 $2222- *2323- * This file contains the code for processing the kernel command2424- * line options for the QIC-40/80/3010/3020 floppy-tape driver2525- * "ftape" for Linux.2626- */2727-2828-#include <linux/string.h>2929-#include <linux/errno.h>3030-#include <linux/mm.h>3131-3232-#include <linux/ftape.h>3333-#include <linux/init.h>3434-#include "../lowlevel/ftape-tracing.h"3535-#include "../lowlevel/fdc-io.h"3636-3737-static struct param_table {3838- const char *name;3939- int *var;4040- int def_param;4141- int min;4242- int max;4343-} config_params[] __initdata = {4444-#ifndef CONFIG_FT_NO_TRACE_AT_ALL4545- { "tracing", &ftape_tracing, 3, ft_t_bug, ft_t_any},4646-#endif4747- { "ioport", &ft_fdc_base, CONFIG_FT_FDC_BASE, 0x0, 0xfff},4848- { "irq", &ft_fdc_irq, CONFIG_FT_FDC_IRQ, 2, 15},4949- { "dma", &ft_fdc_dma, CONFIG_FT_FDC_DMA, 0, 3},5050- { "threshold", &ft_fdc_threshold, CONFIG_FT_FDC_THR, 1, 16},5151- { "datarate", &ft_fdc_rate_limit, CONFIG_FT_FDC_MAX_RATE, 500, 2000},5252- { "fc10", &ft_probe_fc10, CONFIG_FT_PROBE_FC10, 0, 1},5353- { "mach2", &ft_mach2, CONFIG_FT_MACH2, 0, 1}5454-};5555-5656-static int __init ftape_setup(char *str)5757-{5858- int i;5959- int param;6060- int ints[2];6161-6262- TRACE_FUN(ft_t_flow);6363-6464- str = get_options(str, ARRAY_SIZE(ints), ints);6565- if (str) {6666- for (i=0; i < NR_ITEMS(config_params); i++) {6767- if (strcmp(str,config_params[i].name) == 0){6868- if (ints[0]) {6969- param = ints[1];7070- } else {7171- param = config_params[i].def_param;7272- }7373- if (param < config_params[i].min ||7474- param > config_params[i].max) {7575- TRACE(ft_t_err,7676- "parameter %s out of range %d ... %d",7777- config_params[i].name,7878- config_params[i].min,7979- config_params[i].max);8080- goto out;8181- }8282- if(config_params[i].var) {8383- TRACE(ft_t_info, "%s=%d", str, param);8484- *config_params[i].var = param;8585- }8686- goto out;8787- }8888- }8989- }9090- if (str) {9191- TRACE(ft_t_err, "unknown ftape option [%s]", str);9292-9393- TRACE(ft_t_err, "allowed options are:");9494- for (i=0; i < NR_ITEMS(config_params); i++) {9595- TRACE(ft_t_err, " %s",config_params[i].name);9696- }9797- } else {9898- TRACE(ft_t_err, "botched ftape option");9999- }100100- out:101101- TRACE_EXIT 1;102102-}103103-104104-__setup("ftape=", ftape_setup);
-118
drivers/char/ftape/lowlevel/ftape-tracing.c
···11-/*22- * Copyright (C) 1993-1996 Bas Laarhoven,33- * (C) 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-tracing.c,v $2121- * $Revision: 1.2 $2222- * $Date: 1997/10/05 19:18:27 $2323- *2424- * This file contains the reading code2525- * for the QIC-117 floppy-tape driver for Linux.2626- */2727-2828-#include <linux/ftape.h>2929-#include "../lowlevel/ftape-tracing.h"3030-3131-/* Global vars.3232- */3333-/* tracing3434- * set it to: to log :3535- * 0 bugs3636- * 1 + errors3737- * 2 + warnings3838- * 3 + information3939- * 4 + more information4040- * 5 + program flow4141- * 6 + fdc/dma info4242- * 7 + data flow4343- * 8 + everything else4444- */4545-ft_trace_t ftape_tracing = ft_t_info; /* Default level: information and up */4646-int ftape_function_nest_level;4747-4848-/* Local vars.4949- */5050-static __u8 trace_id;5151-static char spacing[] = "* ";5252-5353-void ftape_trace_call(const char *file, const char *name)5454-{5555- char *indent;5656-5757- /* Since printk seems not to work with "%*s" format5858- * we'll use this work-around.5959- */6060- if (ftape_function_nest_level < 0) {6161- printk(KERN_INFO "function nest level (%d) < 0\n",6262- ftape_function_nest_level);6363- ftape_function_nest_level = 0;6464- }6565- if (ftape_function_nest_level < sizeof(spacing)) {6666- indent = (spacing +6767- sizeof(spacing) - 1 -6868- ftape_function_nest_level);6969- } else {7070- indent = spacing;7171- }7272- printk(KERN_INFO "[%03d]%s+%s (%s)\n",7373- (int) trace_id++, indent, file, name);7474-}7575-7676-void ftape_trace_exit(const char *file, const char *name)7777-{7878- char *indent;7979-8080- /* Since printk seems not to work with "%*s" format8181- * we'll use this work-around.8282- */8383- if (ftape_function_nest_level < 0) {8484- printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level);8585- ftape_function_nest_level = 0;8686- }8787- if (ftape_function_nest_level < sizeof(spacing)) {8888- indent = (spacing +8989- sizeof(spacing) - 1 -9090- ftape_function_nest_level);9191- } else {9292- indent = spacing;9393- }9494- printk(KERN_INFO "[%03d]%s-%s (%s)\n",9595- (int) trace_id++, indent, file, name);9696-}9797-9898-void ftape_trace_log(const char *file, const char *function)9999-{100100- char *indent;101101-102102- /* Since printk seems not to work with "%*s" format103103- * we'll use this work-around.104104- */105105- if (ftape_function_nest_level < 0) {106106- printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level);107107- ftape_function_nest_level = 0;108108- }109109- if (ftape_function_nest_level < sizeof(spacing)) {110110- indent = (spacing + 111111- sizeof(spacing) - 1 - 112112- ftape_function_nest_level);113113- } else {114114- indent = spacing;115115- }116116- printk(KERN_INFO "[%03d]%s%s (%s) - ", 117117- (int) trace_id++, indent, file, function);118118-}
-179
drivers/char/ftape/lowlevel/ftape-tracing.h
···11-#ifndef _FTAPE_TRACING_H22-#define _FTAPE_TRACING_H33-44-/*55- * Copyright (C) 1994-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-tracing.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:18:28 $2626- *2727- * This file contains definitions that eases the debugging of the2828- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.2929- */3030-3131-#include <linux/kernel.h>3232-3333-/*3434- * Be very careful with TRACE_EXIT and TRACE_ABORT.3535- *3636- * if (something) TRACE_EXIT error;3737- *3838- * will NOT work. Use3939- *4040- * if (something) {4141- * TRACE_EXIT error;4242- * }4343- *4444- * instead. Maybe a bit dangerous, but save lots of lines of code.4545- */4646-4747-#define LL_X "%d/%d KB"4848-#define LL(x) (unsigned int)((__u64)(x)>>10), (unsigned int)((x)&1023)4949-5050-typedef enum {5151- ft_t_nil = -1,5252- ft_t_bug,5353- ft_t_err,5454- ft_t_warn,5555- ft_t_info,5656- ft_t_noise,5757- ft_t_flow,5858- ft_t_fdc_dma,5959- ft_t_data_flow,6060- ft_t_any6161-} ft_trace_t;6262-6363-#ifdef CONFIG_FT_NO_TRACE_AT_ALL6464-/* the compiler will optimize away most TRACE() macros6565- */6666-#define FT_TRACE_TOP_LEVEL ft_t_bug6767-#define TRACE_FUN(level) do {} while(0)6868-#define TRACE_EXIT return6969-#define TRACE(l, m, i...) \7070-{ \7171- if ((ft_trace_t)(l) == FT_TRACE_TOP_LEVEL) { \7272- printk(KERN_INFO"ftape%s(%s):\n" \7373- KERN_INFO m".\n" ,__FILE__, __FUNCTION__ , ##i); \7474- } \7575-}7676-#define SET_TRACE_LEVEL(l) if ((l) == (l)) do {} while(0)7777-#define TRACE_LEVEL FT_TRACE_TOP_LEVEL7878-7979-#else8080-8181-#ifdef CONFIG_FT_NO_TRACE8282-/* the compiler will optimize away many TRACE() macros8383- * the ftape_simple_trace_call() function simply increments 8484- * the function nest level.8585- */ 8686-#define FT_TRACE_TOP_LEVEL ft_t_warn8787-#define TRACE_FUN(level) ftape_function_nest_level++8888-#define TRACE_EXIT ftape_function_nest_level--; return8989-9090-#else9191-#ifdef CONFIG_FT_FULL_DEBUG9292-#define FT_TRACE_TOP_LEVEL ft_t_any9393-#else9494-#define FT_TRACE_TOP_LEVEL ft_t_flow9595-#endif9696-#define TRACE_FUN(level) \9797- const ft_trace_t _tracing = level; \9898- if (ftape_tracing >= (ft_trace_t)(level) && \9999- (ft_trace_t)(level) <= FT_TRACE_TOP_LEVEL) \100100- ftape_trace_call(__FILE__, __FUNCTION__); \101101- ftape_function_nest_level ++;102102-103103-#define TRACE_EXIT \104104- --ftape_function_nest_level; \105105- if (ftape_tracing >= (ft_trace_t)(_tracing) && \106106- (ft_trace_t)(_tracing) <= FT_TRACE_TOP_LEVEL) \107107- ftape_trace_exit(__FILE__, __FUNCTION__); \108108- return109109-110110-#endif111111-112112-#define TRACE(l, m, i...) \113113-{ \114114- if (ftape_tracing >= (ft_trace_t)(l) && \115115- (ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \116116- ftape_trace_log(__FILE__, __FUNCTION__); \117117- printk(m".\n" ,##i); \118118- } \119119-}120120-121121-#define SET_TRACE_LEVEL(l) \122122-{ \123123- if ((ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \124124- ftape_tracing = (ft_trace_t)(l); \125125- } else { \126126- ftape_tracing = FT_TRACE_TOP_LEVEL; \127127- } \128128-}129129-#define TRACE_LEVEL \130130-((ftape_tracing <= FT_TRACE_TOP_LEVEL) ? ftape_tracing : FT_TRACE_TOP_LEVEL)131131-132132-133133-/* Global variables declared in tracing.c134134- */135135-extern ft_trace_t ftape_tracing; /* sets default level */136136-extern int ftape_function_nest_level;137137-138138-/* Global functions declared in tracing.c139139- */140140-extern void ftape_trace_call(const char *file, const char *name);141141-extern void ftape_trace_exit(const char *file, const char *name);142142-extern void ftape_trace_log (const char *file, const char *name);143143-144144-#endif /* !defined(CONFIG_FT_NO_TRACE_AT_ALL) */145145-146146-/*147147- * Abort with a message.148148- */149149-#define TRACE_ABORT(res, i...) \150150-{ \151151- TRACE(i); \152152- TRACE_EXIT res; \153153-}154154-155155-/* The following transforms the common "if(result < 0) ... " into a156156- * one-liner.157157- */158158-#define _TRACE_CATCH(level, fun, action) \159159-{ \160160- int _res = (fun); \161161- if (_res < 0) { \162162- do { action /* */ ; } while(0); \163163- TRACE_ABORT(_res, level, "%s failed: %d", #fun, _res); \164164- } \165165-}166166-167167-#define TRACE_CATCH(fun, fail) _TRACE_CATCH(ft_t_err, fun, fail)168168-169169-/* Abort the current function when signalled. This doesn't belong here,170170- * but rather into ftape-rw.h (maybe)171171- */172172-#define FT_SIGNAL_EXIT(sig_mask) \173173- if (sigtestsetmask(¤t->pending.signal, sig_mask)) { \174174- TRACE_ABORT(-EINTR, \175175- ft_t_warn, \176176- "interrupted by non-blockable signal"); \177177- }178178-179179-#endif /* _FTAPE_TRACING_H */
-336
drivers/char/ftape/lowlevel/ftape-write.c
···11-/*22- * Copyright (C) 1993-1995 Bas Laarhoven,33- * (C) 1996-1997 Claus-Justus Heine.44-55- This program is free software; you can redistribute it and/or modify66- it under the terms of the GNU General Public License as published by77- the Free Software Foundation; either version 2, or (at your option)88- any later version.99-1010- This program is distributed in the hope that it will be useful,1111- but WITHOUT ANY WARRANTY; without even the implied warranty of1212- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- GNU General Public License for more details.1414-1515- You should have received a copy of the GNU General Public License1616- along with this program; see the file COPYING. If not, write to1717- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.c,v $2121- * $Revision: 1.3.4.1 $2222- * $Date: 1997/11/14 18:07:04 $2323- *2424- * This file contains the writing code2525- * for the QIC-117 floppy-tape driver for Linux.2626- */2727-2828-#include <linux/string.h>2929-#include <linux/errno.h>3030-#include <linux/mm.h>3131-3232-#include <linux/ftape.h>3333-#include <linux/qic117.h>3434-#include "../lowlevel/ftape-tracing.h"3535-#include "../lowlevel/ftape-write.h"3636-#include "../lowlevel/ftape-read.h"3737-#include "../lowlevel/ftape-io.h"3838-#include "../lowlevel/ftape-ctl.h"3939-#include "../lowlevel/ftape-rw.h"4040-#include "../lowlevel/ftape-ecc.h"4141-#include "../lowlevel/ftape-bsm.h"4242-#include "../lowlevel/fdc-isr.h"4343-4444-/* Global vars.4545- */4646-4747-/* Local vars.4848- */4949-static int last_write_failed;5050-5151-void ftape_zap_write_buffers(void)5252-{5353- int i;5454-5555- for (i = 0; i < ft_nr_buffers; ++i) {5656- ft_buffer[i]->status = done;5757- }5858- ftape_reset_buffer();5959-}6060-6161-static int copy_and_gen_ecc(void *destination, 6262- const void *source,6363- const SectorMap bad_sector_map)6464-{6565- int result;6666- struct memory_segment mseg;6767- int bads = count_ones(bad_sector_map);6868- TRACE_FUN(ft_t_any);6969-7070- if (bads > 0) {7171- TRACE(ft_t_noise, "bad sectors in map: %d", bads);7272- }7373- if (bads + 3 >= FT_SECTORS_PER_SEGMENT) {7474- TRACE(ft_t_noise, "empty segment");7575- mseg.blocks = 0; /* skip entire segment */7676- result = 0; /* nothing written */7777- } else {7878- mseg.blocks = FT_SECTORS_PER_SEGMENT - bads;7979- mseg.data = destination;8080- memcpy(mseg.data, source, (mseg.blocks - 3) * FT_SECTOR_SIZE);8181- result = ftape_ecc_set_segment_parity(&mseg);8282- if (result < 0) {8383- TRACE(ft_t_err, "ecc_set_segment_parity failed");8484- } else {8585- result = (mseg.blocks - 3) * FT_SECTOR_SIZE;8686- }8787- }8888- TRACE_EXIT result;8989-}9090-9191-9292-int ftape_start_writing(const ft_write_mode_t mode)9393-{9494- buffer_struct *head = ftape_get_buffer(ft_queue_head);9595- int segment_id = head->segment_id;9696- int result;9797- buffer_state_enum wanted_state = (mode == FT_WR_DELETE9898- ? deleting9999- : writing);100100- TRACE_FUN(ft_t_flow);101101-102102- if ((ft_driver_state != wanted_state) || head->status != waiting) {103103- TRACE_EXIT 0;104104- }105105- ftape_setup_new_segment(head, segment_id, 1);106106- if (mode == FT_WR_SINGLE) {107107- /* stop tape instead of pause */108108- head->next_segment = 0;109109- }110110- ftape_calc_next_cluster(head); /* prepare */111111- head->status = ft_driver_state; /* either writing or deleting */112112- if (ft_runner_status == idle) {113113- TRACE(ft_t_noise,114114- "starting runner for segment %d", segment_id);115115- TRACE_CATCH(ftape_start_tape(segment_id,head->sector_offset),);116116- } else {117117- TRACE(ft_t_noise, "runner not idle, not starting tape");118118- }119119- /* go */120120- result = fdc_setup_read_write(head, (mode == FT_WR_DELETE121121- ? FDC_WRITE_DELETED : FDC_WRITE));122122- ftape_set_state(wanted_state); /* should not be necessary */123123- TRACE_EXIT result;124124-}125125-126126-/* Wait until all data is actually written to tape.127127- * 128128- * There is a problem: when the tape runs into logical EOT, then this129129- * failes. We need to restart the runner in this case.130130- */131131-int ftape_loop_until_writes_done(void)132132-{133133- buffer_struct *head;134134- TRACE_FUN(ft_t_flow);135135-136136- while ((ft_driver_state == writing || ft_driver_state == deleting) && 137137- ftape_get_buffer(ft_queue_head)->status != done) {138138- /* set the runner status to idle if at lEOT */139139- TRACE_CATCH(ftape_handle_logical_eot(), last_write_failed = 1);140140- /* restart the tape if necessary */141141- if (ft_runner_status == idle) {142142- TRACE(ft_t_noise, "runner is idle, restarting");143143- if (ft_driver_state == deleting) {144144- TRACE_CATCH(ftape_start_writing(FT_WR_DELETE),145145- last_write_failed = 1);146146- } else {147147- TRACE_CATCH(ftape_start_writing(FT_WR_MULTI),148148- last_write_failed = 1);149149- }150150- }151151- TRACE(ft_t_noise, "tail: %d, head: %d", 152152- ftape_buffer_id(ft_queue_tail),153153- ftape_buffer_id(ft_queue_head));154154- TRACE_CATCH(fdc_interrupt_wait(5 * FT_SECOND),155155- last_write_failed = 1);156156- head = ftape_get_buffer(ft_queue_head);157157- if (head->status == error) {158158- /* Allow escape from loop when signaled !159159- */160160- FT_SIGNAL_EXIT(_DONT_BLOCK);161161- if (head->hard_error_map != 0) {162162- /* Implement hard write error recovery here163163- */164164- }165165- /* retry this one */166166- head->status = waiting;167167- if (ft_runner_status == aborting) {168168- ftape_dumb_stop();169169- }170170- if (ft_runner_status != idle) {171171- TRACE_ABORT(-EIO, ft_t_err,172172- "unexpected state: "173173- "ft_runner_status != idle");174174- }175175- ftape_start_writing(ft_driver_state == deleting176176- ? FT_WR_MULTI : FT_WR_DELETE);177177- }178178- TRACE(ft_t_noise, "looping until writes done");179179- }180180- ftape_set_state(idle);181181- TRACE_EXIT 0;182182-}183183-184184-/* Write given segment from buffer at address to tape.185185- */186186-static int write_segment(const int segment_id,187187- const void *address, 188188- const ft_write_mode_t write_mode)189189-{190190- int bytes_written = 0;191191- buffer_struct *tail;192192- buffer_state_enum wanted_state = (write_mode == FT_WR_DELETE193193- ? deleting : writing);194194- TRACE_FUN(ft_t_flow);195195-196196- TRACE(ft_t_noise, "segment_id = %d", segment_id);197197- if (ft_driver_state != wanted_state) {198198- if (ft_driver_state == deleting ||199199- wanted_state == deleting) {200200- TRACE_CATCH(ftape_loop_until_writes_done(),);201201- }202202- TRACE(ft_t_noise, "calling ftape_abort_operation");203203- TRACE_CATCH(ftape_abort_operation(),);204204- ftape_zap_write_buffers();205205- ftape_set_state(wanted_state);206206- }207207- /* if all buffers full we'll have to wait...208208- */209209- ftape_wait_segment(wanted_state);210210- tail = ftape_get_buffer(ft_queue_tail);211211- switch(tail->status) {212212- case done:213213- ft_history.defects += count_ones(tail->hard_error_map);214214- break;215215- case waiting:216216- /* this could happen with multiple EMPTY_SEGMENTs, but217217- * shouldn't happen any more as we re-start the runner even218218- * with an empty segment.219219- */220220- bytes_written = -EAGAIN;221221- break;222222- case error:223223- /* setup for a retry224224- */225225- tail->status = waiting;226226- bytes_written = -EAGAIN; /* force retry */227227- if (tail->hard_error_map != 0) {228228- TRACE(ft_t_warn, 229229- "warning: %d hard error(s) in written segment",230230- count_ones(tail->hard_error_map));231231- TRACE(ft_t_noise, "hard_error_map = 0x%08lx", 232232- (long)tail->hard_error_map);233233- /* Implement hard write error recovery here234234- */235235- }236236- break;237237- default:238238- TRACE_ABORT(-EIO, ft_t_err,239239- "wait for empty segment failed, tail status: %d",240240- tail->status);241241- }242242- /* should runner stop ?243243- */244244- if (ft_runner_status == aborting) {245245- buffer_struct *head = ftape_get_buffer(ft_queue_head);246246- if (head->status == wanted_state) {247247- head->status = done; /* ???? */248248- }249249- /* don't call abort_operation(), we don't want to zap250250- * the dma buffers251251- */252252- TRACE_CATCH(ftape_dumb_stop(),);253253- } else {254254- /* If just passed last segment on tape: wait for BOT255255- * or EOT mark. Sets ft_runner_status to idle if at lEOT256256- * and successful 257257- */258258- TRACE_CATCH(ftape_handle_logical_eot(),);259259- }260260- if (tail->status == done) {261261- /* now at least one buffer is empty, fill it with our262262- * data. skip bad sectors and generate ecc.263263- * copy_and_gen_ecc return nr of bytes written, range264264- * 0..29 Kb inclusive! 265265- *266266- * Empty segments are handled inside coyp_and_gen_ecc()267267- */268268- if (write_mode != FT_WR_DELETE) {269269- TRACE_CATCH(bytes_written = copy_and_gen_ecc(270270- tail->address, address,271271- ftape_get_bad_sector_entry(segment_id)),);272272- }273273- tail->segment_id = segment_id;274274- tail->status = waiting;275275- tail = ftape_next_buffer(ft_queue_tail);276276- }277277- /* Start tape only if all buffers full or flush mode.278278- * This will give higher probability of streaming.279279- */280280- if (ft_runner_status != running && 281281- ((tail->status == waiting &&282282- ftape_get_buffer(ft_queue_head) == tail) ||283283- write_mode != FT_WR_ASYNC)) {284284- TRACE_CATCH(ftape_start_writing(write_mode),);285285- }286286- TRACE_EXIT bytes_written;287287-}288288-289289-/* Write as much as fits from buffer to the given segment on tape290290- * and handle retries.291291- * Return the number of bytes written (>= 0), or:292292- * -EIO write failed293293- * -EINTR interrupted by signal294294- * -ENOSPC device full295295- */296296-int ftape_write_segment(const int segment_id,297297- const void *buffer, 298298- const ft_write_mode_t flush)299299-{300300- int retry = 0;301301- int result;302302- TRACE_FUN(ft_t_flow);303303-304304- ft_history.used |= 2;305305- if (segment_id >= ft_tracks_per_tape*ft_segments_per_track) {306306- /* tape full */307307- TRACE_ABORT(-ENOSPC, ft_t_err,308308- "invalid segment id: %d (max %d)", 309309- segment_id, 310310- ft_tracks_per_tape * ft_segments_per_track -1);311311- }312312- for (;;) {313313- if ((result = write_segment(segment_id, buffer, flush)) >= 0) {314314- if (result == 0) { /* empty segment */315315- TRACE(ft_t_noise,316316- "empty segment, nothing written");317317- }318318- TRACE_EXIT result;319319- }320320- if (result == -EAGAIN) {321321- if (++retry > 100) { /* give up */322322- TRACE_ABORT(-EIO, ft_t_err,323323- "write failed, >100 retries in segment");324324- }325325- TRACE(ft_t_warn, "write error, retry %d (%d)",326326- retry,327327- ftape_get_buffer(ft_queue_tail)->segment_id);328328- } else {329329- TRACE_ABORT(result, ft_t_err,330330- "write_segment failed, error: %d", result);331331- }332332- /* Allow escape from loop when signaled !333333- */334334- FT_SIGNAL_EXIT(_DONT_BLOCK);335335- }336336-}
-53
drivers/char/ftape/lowlevel/ftape-write.h
···11-#ifndef _FTAPE_WRITE_H22-#define _FTAPE_WRITE_H33-44-/*55- * Copyright (C) 1994-1995 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.h,v $2424- $Author: claus $2525- *2626- $Revision: 1.2 $2727- $Date: 1997/10/05 19:18:30 $2828- $State: Exp $2929- *3030- * This file contains the definitions for the write functions3131- * for the QIC-117 floppy-tape driver for Linux.3232- *3333- */3434-3535-3636-/* ftape-write.c defined global functions.3737- */3838-typedef enum {3939- FT_WR_ASYNC = 0, /* start tape only when all buffers are full */4040- FT_WR_MULTI = 1, /* start tape, but don't necessarily stop */4141- FT_WR_SINGLE = 2, /* write a single segment and stop afterwards */4242- FT_WR_DELETE = 3 /* write deleted data marks */4343-} ft_write_mode_t;4444-4545-extern int ftape_start_writing(const ft_write_mode_t mode);4646-extern int ftape_write_segment(const int segment,4747- const void *address, 4848- const ft_write_mode_t flushing);4949-extern void ftape_zap_write_buffers(void);5050-extern int ftape_loop_until_writes_done(void);5151-5252-#endif /* _FTAPE_WRITE_H */5353-
-87
drivers/char/ftape/lowlevel/ftape_syms.c
···11-/*22- * Copyright (C) 1996-1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape_syms.c,v $2020- * $Revision: 1.4 $2121- * $Date: 1997/10/17 00:03:51 $2222- *2323- * This file contains the symbols that the ftape low level2424- * part of the QIC-40/80/3010/3020 floppy-tape driver "ftape"2525- * exports to its high level clients2626- */2727-2828-#include <linux/module.h>2929-3030-#include <linux/ftape.h>3131-#include "../lowlevel/ftape-tracing.h"3232-#include "../lowlevel/ftape-init.h"3333-#include "../lowlevel/fdc-io.h"3434-#include "../lowlevel/ftape-read.h"3535-#include "../lowlevel/ftape-write.h"3636-#include "../lowlevel/ftape-io.h"3737-#include "../lowlevel/ftape-ctl.h"3838-#include "../lowlevel/ftape-rw.h"3939-#include "../lowlevel/ftape-bsm.h"4040-#include "../lowlevel/ftape-buffer.h"4141-#include "../lowlevel/ftape-format.h"4242-4343-/* bad sector handling from ftape-bsm.c */4444-EXPORT_SYMBOL(ftape_get_bad_sector_entry);4545-EXPORT_SYMBOL(ftape_find_end_of_bsm_list);4646-/* from ftape-rw.c */4747-EXPORT_SYMBOL(ftape_set_state);4848-/* from ftape-ctl.c */4949-EXPORT_SYMBOL(ftape_seek_to_bot);5050-EXPORT_SYMBOL(ftape_seek_to_eot);5151-EXPORT_SYMBOL(ftape_abort_operation);5252-EXPORT_SYMBOL(ftape_get_status);5353-EXPORT_SYMBOL(ftape_enable);5454-EXPORT_SYMBOL(ftape_disable);5555-EXPORT_SYMBOL(ftape_mmap);5656-EXPORT_SYMBOL(ftape_calibrate_data_rate);5757-/* from ftape-io.c */5858-EXPORT_SYMBOL(ftape_reset_drive);5959-EXPORT_SYMBOL(ftape_command);6060-EXPORT_SYMBOL(ftape_parameter);6161-EXPORT_SYMBOL(ftape_ready_wait);6262-EXPORT_SYMBOL(ftape_report_operation);6363-EXPORT_SYMBOL(ftape_report_error);6464-/* from ftape-read.c */6565-EXPORT_SYMBOL(ftape_read_segment_fraction);6666-EXPORT_SYMBOL(ftape_zap_read_buffers);6767-EXPORT_SYMBOL(ftape_read_header_segment);6868-EXPORT_SYMBOL(ftape_decode_header_segment);6969-/* from ftape-write.c */7070-EXPORT_SYMBOL(ftape_write_segment);7171-EXPORT_SYMBOL(ftape_start_writing);7272-EXPORT_SYMBOL(ftape_loop_until_writes_done);7373-/* from ftape-buffer.h */7474-EXPORT_SYMBOL(ftape_set_nr_buffers);7575-/* from ftape-format.h */7676-EXPORT_SYMBOL(ftape_format_track);7777-EXPORT_SYMBOL(ftape_format_status);7878-EXPORT_SYMBOL(ftape_verify_segment);7979-/* from tracing.c */8080-#ifndef CONFIG_FT_NO_TRACE_AT_ALL8181-EXPORT_SYMBOL(ftape_tracing);8282-EXPORT_SYMBOL(ftape_function_nest_level);8383-EXPORT_SYMBOL(ftape_trace_call);8484-EXPORT_SYMBOL(ftape_trace_exit);8585-EXPORT_SYMBOL(ftape_trace_log);8686-#endif8787-
-36
drivers/char/ftape/zftape/Makefile
···11-#22-# Copyright (C) 1996, 1997 Claus-Justus Heine.33-#44-# This program is free software; you can redistribute it and/or modify55-# it under the terms of the GNU General Public License as published by66-# the Free Software Foundation; either version 2, or (at your option)77-# any later version.88-# 99-# This program is distributed in the hope that it will be useful,1010-# but WITHOUT ANY WARRANTY; without even the implied warranty of1111-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212-# GNU General Public License for more details.1313-# 1414-# You should have received a copy of the GNU General Public License1515-# along with this program; see the file COPYING. If not, write to1616-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-#1818-# $Source: /homes/cvs/ftape-stacked/ftape/zftape/Makefile,v $1919-# $Revision: 1.4 $2020-# $Date: 1997/10/05 19:18:58 $2121-#2222-# Makefile for the QIC-40/80/3010/3020 zftape interface VFS to2323-# ftape2424-#2525-2626-2727-# ZFT_OBSOLETE - enable the MTIOC_ZFTAPE_GETBLKSZ ioctl. You should2828-# leave this enabled for compatibility with taper.2929-3030-obj-$(CONFIG_ZFTAPE) += zftape.o3131-3232-zftape-objs := zftape-rw.o zftape-ctl.o zftape-read.o \3333- zftape-write.o zftape-vtbl.o zftape-eof.o \3434- zftape-init.o zftape-buffers.o zftape_syms.o3535-3636-EXTRA_CFLAGS := -DZFT_OBSOLETE
-149
drivers/char/ftape/zftape/zftape-buffers.c
···11-/*22- * Copyright (C) 1995-1997 Claus-Justus Heine.33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-buffers.c,v $2020- * $Revision: 1.2 $2121- * $Date: 1997/10/05 19:18:59 $2222- *2323- * This file contains the dynamic buffer allocation routines 2424- * of zftape2525- */2626-2727-#include <linux/errno.h>2828-#include <linux/mm.h>2929-#include <linux/slab.h>3030-#include <linux/delay.h>3131-3232-#include <linux/zftape.h>3333-3434-#include <linux/vmalloc.h>3535-3636-#include "../zftape/zftape-init.h"3737-#include "../zftape/zftape-eof.h"3838-#include "../zftape/zftape-ctl.h"3939-#include "../zftape/zftape-write.h"4040-#include "../zftape/zftape-read.h"4141-#include "../zftape/zftape-rw.h"4242-#include "../zftape/zftape-vtbl.h"4343-4444-/* global variables4545- */4646-4747-/* local varibales4848- */4949-static unsigned int used_memory;5050-static unsigned int peak_memory;5151-5252-void zft_memory_stats(void)5353-{5454- TRACE_FUN(ft_t_flow);5555-5656- TRACE(ft_t_noise, "Memory usage (vmalloc allocations):\n"5757- KERN_INFO "total allocated: %d\n"5858- KERN_INFO "peak allocation: %d",5959- used_memory, peak_memory);6060- peak_memory = used_memory;6161- TRACE_EXIT;6262-}6363-6464-int zft_vcalloc_once(void *new, size_t size)6565-{6666- TRACE_FUN(ft_t_flow);6767- if (zft_vmalloc_once(new, size) < 0) {6868- TRACE_EXIT -ENOMEM;6969- }7070- memset(*(void **)new, '\0', size);7171- TRACE_EXIT 0;7272-}7373-int zft_vmalloc_once(void *new, size_t size)7474-{7575- TRACE_FUN(ft_t_flow);7676-7777- if (*(void **)new != NULL || size == 0) {7878- TRACE_EXIT 0;7979- }8080- if ((*(void **)new = vmalloc(size)) == NULL) {8181- TRACE_EXIT -ENOMEM;8282- }8383- used_memory += size;8484- if (peak_memory < used_memory) {8585- peak_memory = used_memory;8686- }8787- TRACE_ABORT(0, ft_t_noise,8888- "allocated buffer @ %p, %zd bytes", *(void **)new, size);8989-}9090-int zft_vmalloc_always(void *new, size_t size)9191-{9292- TRACE_FUN(ft_t_flow);9393-9494- zft_vfree(new, size);9595- TRACE_EXIT zft_vmalloc_once(new, size);9696-}9797-void zft_vfree(void *old, size_t size)9898-{9999- TRACE_FUN(ft_t_flow);100100-101101- if (*(void **)old) {102102- vfree(*(void **)old);103103- used_memory -= size;104104- TRACE(ft_t_noise, "released buffer @ %p, %zd bytes",105105- *(void **)old, size);106106- *(void **)old = NULL;107107- }108108- TRACE_EXIT;109109-}110110-111111-void *zft_kmalloc(size_t size)112112-{113113- void *new;114114-115115- while ((new = kmalloc(size, GFP_KERNEL)) == NULL) {116116- msleep_interruptible(100);117117- }118118- memset(new, 0, size);119119- used_memory += size;120120- if (peak_memory < used_memory) {121121- peak_memory = used_memory;122122- }123123- return new;124124-}125125-126126-void zft_kfree(void *old, size_t size)127127-{128128- kfree(old);129129- used_memory -= size;130130-}131131-132132-/* there are some more buffers that are allocated on demand.133133- * cleanup_module() calles this function to be sure to have released134134- * them 135135- */136136-void zft_uninit_mem(void)137137-{138138- TRACE_FUN(ft_t_flow);139139-140140- zft_vfree(&zft_hseg_buf, FT_SEGMENT_SIZE);141141- zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); zft_deblock_segment = -1;142142- zft_free_vtbl();143143- if (zft_cmpr_lock(0 /* don't load */) == 0) {144144- (*zft_cmpr_ops->cleanup)();145145- (*zft_cmpr_ops->reset)(); /* unlock it again */146146- }147147- zft_memory_stats();148148- TRACE_EXIT;149149-}
-55
drivers/char/ftape/zftape/zftape-buffers.h
···11-#ifndef _FTAPE_DYNMEM_H22-#define _FTAPE_DYNMEM_H33-44-/*55- * Copyright (C) 1995-1997 Claus-Justus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-buffers.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:18:59 $2525- *2626- * memory allocation routines.2727- *2828- */2929-3030-/* we do not allocate all of the really large buffer memory before3131- * someone tries to open the drive. ftape_open() may fail with3232- * -ENOMEM, but that's better having 200k of vmalloced memory which3333- * cannot be swapped out.3434- */3535-3636-extern void zft_memory_stats(void);3737-extern int zft_vmalloc_once(void *new, size_t size);3838-extern int zft_vcalloc_once(void *new, size_t size);3939-extern int zft_vmalloc_always(void *new, size_t size);4040-extern void zft_vfree(void *old, size_t size);4141-extern void *zft_kmalloc(size_t size);4242-extern void zft_kfree(void *old, size_t size);4343-4444-/* called by cleanup_module() 4545- */4646-extern void zft_uninit_mem(void);4747-4848-#endif4949-5050-5151-5252-5353-5454-5555-
-1417
drivers/char/ftape/zftape/zftape-ctl.c
···11-/* 22- * Copyright (C) 1996, 1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.c,v $2020- * $Revision: 1.2.6.2 $2121- * $Date: 1997/11/14 18:07:33 $2222- *2323- * This file contains the non-read/write zftape functions2424- * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.2525- */2626-2727-#include <linux/errno.h>2828-#include <linux/mm.h>2929-#include <linux/module.h>3030-#include <linux/fcntl.h>3131-3232-#include <linux/zftape.h>3333-3434-#include <asm/uaccess.h>3535-3636-#include "../zftape/zftape-init.h"3737-#include "../zftape/zftape-eof.h"3838-#include "../zftape/zftape-ctl.h"3939-#include "../zftape/zftape-write.h"4040-#include "../zftape/zftape-read.h"4141-#include "../zftape/zftape-rw.h"4242-#include "../zftape/zftape-vtbl.h"4343-4444-/* Global vars.4545- */4646-int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */4747-int zft_header_read;4848-int zft_offline;4949-unsigned int zft_unit;5050-int zft_resid;5151-int zft_mt_compression;5252-5353-/* Local vars.5454- */5555-static int going_offline;5656-5757-typedef int (mt_fun)(int *argptr);5858-typedef int (*mt_funp)(int *argptr);5959-typedef struct6060-{6161- mt_funp function;6262- unsigned offline : 1; /* op permitted if offline or no_tape */6363- unsigned write_protected : 1; /* op permitted if write-protected */6464- unsigned not_formatted : 1; /* op permitted if tape not formatted */6565- unsigned raw_mode : 1; /* op permitted if zft_mode == 0 */6666- unsigned need_idle_state : 1; /* need to call def_idle_state */6767- char *name;6868-} fun_entry;6969-7070-static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop,7171- mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity,7272- mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf,7373- mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression;7474-7575-static fun_entry mt_funs[]=7676-{ 7777- {mt_reset , 1, 1, 1, 1, 0, "MT_RESET" }, /* 0 */7878- {mt_fsf , 0, 1, 0, 0, 1, "MT_FSF" },7979- {mt_bsf , 0, 1, 0, 0, 1, "MT_BSF" },8080- {mt_fsr , 0, 1, 0, 1, 1, "MT_FSR" },8181- {mt_bsr , 0, 1, 0, 1, 1, "MT_BSR" },8282- {mt_weof , 0, 0, 0, 0, 0, "MT_WEOF" }, /* 5 */8383- {mt_rew , 0, 1, 1, 1, 0, "MT_REW" },8484- {mt_offl , 0, 1, 1, 1, 0, "MT_OFFL" },8585- {mt_nop , 1, 1, 1, 1, 0, "MT_NOP" },8686- {mt_reten , 0, 1, 1, 1, 0, "MT_RETEN" },8787- {mt_bsfm , 0, 1, 0, 0, 1, "MT_BSFM" }, /* 10 */8888- {mt_fsfm , 0, 1, 0, 0, 1, "MT_FSFM" },8989- {mt_eom , 0, 1, 0, 0, 1, "MT_EOM" },9090- {mt_erase , 0, 0, 0, 1, 0, "MT_ERASE" },9191- {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS1" },9292- {mt_ras2 , 0, 0, 0, 1, 0, "MT_RAS2" },9393- {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS3" },9494- {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },9595- {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },9696- {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },9797- {mt_setblk , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */9898- {mt_setdensity , 1, 1, 1, 1, 0, "MT_SETDENSITY"},9999- {mt_seek , 0, 1, 0, 1, 1, "MT_SEEK" },100100- {mt_dummy , 0, 1, 0, 1, 1, "MT_TELL" }, /* wr-only ?! */101101- {mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" },102102- {mt_dummy , 1, 1, 1, 1, 0, "MT_FSS" }, /* 25 */103103- {mt_dummy , 1, 1, 1, 1, 0, "MT_BSS" },104104- {mt_dummy , 1, 1, 1, 1, 0, "MT_WSM" },105105- {mt_dummy , 1, 1, 1, 1, 0, "MT_LOCK" },106106- {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOCK"},107107- {mt_dummy , 1, 1, 1, 1, 0, "MT_LOAD" }, /* 30 */108108- {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOAD"},109109- {mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"},110110- {mt_dummy , 1, 1, 1, 1, 0, "MT_SETPART"},111111- {mt_dummy , 1, 1, 1, 1, 0, "MT_MKPART"}112112-}; 113113-114114-#define NR_MT_CMDS NR_ITEMS(mt_funs)115115-116116-void zft_reset_position(zft_position *pos)117117-{118118- TRACE_FUN(ft_t_flow);119119-120120- pos->seg_byte_pos =121121- pos->volume_pos = 0;122122- if (zft_header_read) {123123- /* need to keep track of the volume table and124124- * compression map. We therefor simply125125- * position at the beginning of the first126126- * volume. This covers old ftape archives as127127- * well has various flavours of the128128- * compression map segments. The worst case is129129- * that the compression map shows up as a130130- * additional volume in front of all others.131131- */132132- pos->seg_pos = zft_find_volume(0)->start_seg;133133- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);134134- } else {135135- pos->tape_pos = 0;136136- pos->seg_pos = -1;137137- }138138- zft_just_before_eof = 0;139139- zft_deblock_segment = -1;140140- zft_io_state = zft_idle;141141- zft_zap_read_buffers();142142- zft_prevent_flush();143143- /* unlock the compresison module if it is loaded.144144- * The zero arg means not to try to load the module.145145- */146146- if (zft_cmpr_lock(0) == 0) {147147- (*zft_cmpr_ops->reset)(); /* unlock */148148- }149149- TRACE_EXIT;150150-}151151-152152-static void zft_init_driver(void)153153-{154154- TRACE_FUN(ft_t_flow);155155-156156- zft_resid =157157- zft_header_read =158158- zft_old_ftape =159159- zft_offline =160160- zft_write_protected =161161- going_offline =162162- zft_mt_compression =163163- zft_header_changed =164164- zft_volume_table_changed =165165- zft_written_segments = 0;166166- zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;167167- zft_reset_position(&zft_pos); /* does most of the stuff */168168- ftape_zap_read_buffers();169169- ftape_set_state(idle);170170- TRACE_EXIT;171171-}172172-173173-int zft_def_idle_state(void)174174-{ 175175- int result = 0;176176- TRACE_FUN(ft_t_flow);177177-178178- if (!zft_header_read) {179179- result = zft_read_header_segments();180180- } else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) {181181- /* don't move past eof182182- */183183- (void)zft_close_volume(&zft_pos);184184- }185185- if (ftape_abort_operation() < 0) {186186- TRACE(ft_t_warn, "ftape_abort_operation() failed");187187- result = -EIO;188188- }189189- /* clear remaining read buffers */190190- zft_zap_read_buffers();191191- zft_io_state = zft_idle;192192- TRACE_EXIT result;193193-}194194-195195-/*****************************************************************************196196- * *197197- * functions for the MTIOCTOP commands *198198- * *199199- *****************************************************************************/200200-201201-static int mt_dummy(int *dummy)202202-{203203- TRACE_FUN(ft_t_flow);204204-205205- TRACE_EXIT -ENOSYS;206206-}207207-208208-static int mt_reset(int *dummy)209209-{ 210210- TRACE_FUN(ft_t_flow);211211-212212- (void)ftape_seek_to_bot();213213- TRACE_CATCH(ftape_reset_drive(),214214- zft_init_driver(); zft_uninit_mem(); zft_offline = 1);215215- /* fake a re-open of the device. This will set all flage and 216216- * allocate buffers as appropriate. The new tape condition will217217- * force the open routine to do anything we need.218218- */219219- TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),);220220- TRACE_EXIT 0;221221-}222222-223223-static int mt_fsf(int *arg)224224-{225225- int result;226226- TRACE_FUN(ft_t_flow);227227-228228- result = zft_skip_volumes(*arg, &zft_pos);229229- zft_just_before_eof = 0;230230- TRACE_EXIT result;231231-}232232-233233-static int mt_bsf(int *arg)234234-{235235- int result = 0;236236- TRACE_FUN(ft_t_flow);237237-238238- if (*arg != 0) {239239- result = zft_skip_volumes(-*arg + 1, &zft_pos);240240- }241241- TRACE_EXIT result;242242-}243243-244244-static int seek_block(__s64 data_offset,245245- __s64 block_increment,246246- zft_position *pos)247247-{ 248248- int result = 0;249249- __s64 new_block_pos;250250- __s64 vol_block_count;251251- const zft_volinfo *volume;252252- int exceed;253253- TRACE_FUN(ft_t_flow);254254-255255- volume = zft_find_volume(pos->seg_pos);256256- if (volume->start_seg == 0 || volume->end_seg == 0) {257257- TRACE_EXIT -EIO;258258- }259259- new_block_pos = (zft_div_blksz(data_offset, volume->blk_sz)260260- + block_increment);261261- vol_block_count = zft_div_blksz(volume->size, volume->blk_sz);262262- if (new_block_pos < 0) {263263- TRACE(ft_t_noise,264264- "new_block_pos " LL_X " < 0", LL(new_block_pos));265265- zft_resid = (int)new_block_pos;266266- new_block_pos = 0;267267- exceed = 1;268268- } else if (new_block_pos > vol_block_count) {269269- TRACE(ft_t_noise,270270- "new_block_pos " LL_X " exceeds size of volume " LL_X,271271- LL(new_block_pos), LL(vol_block_count));272272- zft_resid = (int)(vol_block_count - new_block_pos);273273- new_block_pos = vol_block_count;274274- exceed = 1;275275- } else {276276- exceed = 0;277277- }278278- if (zft_use_compression && volume->use_compression) {279279- TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);280280- result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume,281281- zft_deblock_buf);282282- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);283283- pos->tape_pos += pos->seg_byte_pos;284284- } else {285285- pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz);286286- pos->tape_pos = zft_calc_tape_pos(volume->start_seg);287287- pos->tape_pos += pos->volume_pos;288288- pos->seg_pos = zft_calc_seg_byte_coord(&pos->seg_byte_pos,289289- pos->tape_pos);290290- }291291- zft_just_before_eof = volume->size == pos->volume_pos;292292- if (zft_just_before_eof) {293293- /* why this? because zft_file_no checks agains start294294- * and end segment of a volume. We do not want to295295- * advance to the next volume with this function.296296- */297297- TRACE(ft_t_noise, "set zft_just_before_eof");298298- zft_position_before_eof(pos, volume);299299- }300300- TRACE(ft_t_noise, "\n"301301- KERN_INFO "new_seg_pos : %d\n"302302- KERN_INFO "new_tape_pos: " LL_X "\n"303303- KERN_INFO "vol_size : " LL_X "\n"304304- KERN_INFO "seg_byte_pos: %d\n"305305- KERN_INFO "blk_sz : %d", 306306- pos->seg_pos, LL(pos->tape_pos),307307- LL(volume->size), pos->seg_byte_pos,308308- volume->blk_sz);309309- if (!exceed) {310310- zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos,311311- volume->blk_sz);312312- }313313- if (zft_resid < 0) {314314- zft_resid = -zft_resid;315315- }316316- TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result;317317-} 318318-319319-static int mt_fsr(int *arg)320320-{ 321321- int result;322322- TRACE_FUN(ft_t_flow);323323-324324- result = seek_block(zft_pos.volume_pos, *arg, &zft_pos);325325- TRACE_EXIT result;326326-}327327-328328-static int mt_bsr(int *arg)329329-{ 330330- int result;331331- TRACE_FUN(ft_t_flow);332332-333333- result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos);334334- TRACE_EXIT result;335335-}336336-337337-static int mt_weof(int *arg)338338-{339339- int result;340340- TRACE_FUN(ft_t_flow);341341-342342- TRACE_CATCH(zft_flush_buffers(),);343343- result = zft_weof(*arg, &zft_pos);344344- TRACE_EXIT result;345345-}346346-347347-static int mt_rew(int *dummy)348348-{ 349349- int result;350350- TRACE_FUN(ft_t_flow);351351-352352- if(zft_header_read) {353353- (void)zft_def_idle_state();354354- }355355- result = ftape_seek_to_bot();356356- zft_reset_position(&zft_pos);357357- TRACE_EXIT result;358358-}359359-360360-static int mt_offl(int *dummy)361361-{362362- int result;363363- TRACE_FUN(ft_t_flow);364364-365365- going_offline= 1;366366- result = mt_rew(NULL);367367- TRACE_EXIT result;368368-}369369-370370-static int mt_nop(int *dummy)371371-{372372- TRACE_FUN(ft_t_flow);373373- /* should we set tape status?374374- */375375- if (!zft_offline) { /* offline includes no_tape */376376- (void)zft_def_idle_state();377377- }378378- TRACE_EXIT 0; 379379-}380380-381381-static int mt_reten(int *dummy)382382-{ 383383- int result;384384- TRACE_FUN(ft_t_flow);385385-386386- if(zft_header_read) {387387- (void)zft_def_idle_state();388388- }389389- result = ftape_seek_to_eot();390390- if (result >= 0) {391391- result = ftape_seek_to_bot();392392- }393393- TRACE_EXIT(result);394394-}395395-396396-static int fsfbsfm(int arg, zft_position *pos)397397-{ 398398- const zft_volinfo *vtbl;399399- __s64 block_pos;400400- TRACE_FUN(ft_t_flow);401401-402402- /* What to do? This should seek to the next file-mark and403403- * position BEFORE. That is, a next write would just extend404404- * the current file. Well. Let's just seek to the end of the405405- * current file, if count == 1. If count > 1, then do a406406- * "mt_fsf(count - 1)", and then seek to the end of that file.407407- * If count == 0, do nothing408408- */409409- if (arg == 0) {410410- TRACE_EXIT 0;411411- }412412- zft_just_before_eof = 0;413413- TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos),414414- if (arg > 0) {415415- zft_resid ++; 416416- });417417- vtbl = zft_find_volume(pos->seg_pos);418418- block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz);419419- (void)seek_block(0, block_pos, pos);420420- if (pos->volume_pos != vtbl->size) {421421- zft_just_before_eof = 0;422422- zft_resid = 1;423423- /* we didn't managed to go there */424424- TRACE_ABORT(-EIO, ft_t_err, 425425- "wanted file position " LL_X ", arrived at " LL_X, 426426- LL(vtbl->size), LL(pos->volume_pos));427427- }428428- zft_just_before_eof = 1;429429- TRACE_EXIT 0; 430430-}431431-432432-static int mt_bsfm(int *arg)433433-{434434- int result;435435- TRACE_FUN(ft_t_flow);436436-437437- result = fsfbsfm(-*arg, &zft_pos);438438- TRACE_EXIT result;439439-}440440-441441-static int mt_fsfm(int *arg)442442-{443443- int result;444444- TRACE_FUN(ft_t_flow);445445-446446- result = fsfbsfm(*arg, &zft_pos);447447- TRACE_EXIT result;448448-}449449-450450-static int mt_eom(int *dummy)451451-{ 452452- TRACE_FUN(ft_t_flow);453453-454454- zft_skip_to_eom(&zft_pos);455455- TRACE_EXIT 0;456456-}457457-458458-static int mt_erase(int *dummy)459459-{460460- int result;461461- TRACE_FUN(ft_t_flow);462462-463463- result = zft_erase();464464- TRACE_EXIT result;465465-}466466-467467-static int mt_ras2(int *dummy)468468-{469469- int result;470470- TRACE_FUN(ft_t_flow);471471-472472- result = -ENOSYS;473473- TRACE_EXIT result;474474-} 475475-476476-/* Sets the new blocksize in BYTES477477- *478478- */479479-static int mt_setblk(int *new_size)480480-{481481- TRACE_FUN(ft_t_flow);482482-483483- if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) {484484- TRACE_ABORT(-EINVAL, ft_t_info,485485- "desired blk_sz (%d) should be <= %d bytes",486486- *new_size, ZFT_MAX_BLK_SZ);487487- }488488- if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) {489489- TRACE_ABORT(-EINVAL, ft_t_info,490490- "desired blk_sz (%d) must be a multiple of %d bytes",491491- *new_size, FT_SECTOR_SIZE);492492- }493493- if (*new_size == 0) {494494- if (zft_use_compression) {495495- TRACE_ABORT(-EINVAL, ft_t_info,496496- "Variable block size not yet "497497- "supported with compression");498498- }499499- *new_size = 1;500500- }501501- zft_blk_sz = *new_size;502502- TRACE_EXIT 0;503503-} 504504-505505-static int mt_setdensity(int *arg)506506-{507507- TRACE_FUN(ft_t_flow);508508-509509- SET_TRACE_LEVEL(*arg);510510- TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL);511511- if ((int)TRACE_LEVEL != *arg) {512512- TRACE_EXIT -EINVAL;513513- }514514- TRACE_EXIT 0;515515-} 516516-517517-static int mt_seek(int *new_block_pos)518518-{ 519519- int result= 0; 520520- TRACE_FUN(ft_t_any);521521-522522- result = seek_block(0, (__s64)*new_block_pos, &zft_pos);523523- TRACE_EXIT result;524524-}525525-526526-/* OK, this is totally different from SCSI, but the worst thing that can 527527- * happen is that there is not enough defragmentated memory that can be 528528- * allocated. Also, there is a hardwired limit of 16 dma buffers in the 529529- * stock ftape module. This shouldn't bring the system down.530530- *531531- * NOTE: the argument specifies the total number of dma buffers to use.532532- * The driver needs at least 3 buffers to function at all.533533- * 534534- */535535-static int mt_setdrvbuffer(int *cnt)536536-{537537- TRACE_FUN(ft_t_flow);538538-539539- if (*cnt < 3) {540540- TRACE_EXIT -EINVAL;541541- }542542- TRACE_CATCH(ftape_set_nr_buffers(*cnt),);543543- TRACE_EXIT 0;544544-}545545-/* return the block position from start of volume 546546- */547547-static int mt_tell(int *arg)548548-{549549- TRACE_FUN(ft_t_flow);550550-551551- *arg = zft_div_blksz(zft_pos.volume_pos,552552- zft_find_volume(zft_pos.seg_pos)->blk_sz);553553- TRACE_EXIT 0;554554-}555555-556556-static int mt_compression(int *arg)557557-{558558- TRACE_FUN(ft_t_flow);559559-560560- /* Ok. We could also check whether compression is available at561561- * all by trying to load the compression module. We could562562- * also check for a block size of 1 byte which is illegal563563- * with compression. Instead of doing it here we rely on564564- * zftape_write() to do the proper checks.565565- */566566- if ((unsigned int)*arg > 1) {567567- TRACE_EXIT -EINVAL;568568- }569569- if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */570570- TRACE_ABORT(-EINVAL, ft_t_info,571571- "Compression not yet supported "572572- "with variable block size");573573- }574574- zft_mt_compression = *arg;575575- if ((zft_unit & ZFT_ZIP_MODE) == 0) {576576- zft_use_compression = zft_mt_compression;577577- }578578- TRACE_EXIT 0;579579-}580580-581581-/* check whether write access is allowed. Write access is denied when582582- * + zft_write_protected == 1 -- this accounts for either hard write 583583- * protection of the cartridge or for 584584- * O_RDONLY access mode of the tape device585585- * + zft_offline == 1 -- this meany that there is either no tape 586586- * or that the MTOFFLINE ioctl has been 587587- * previously issued (`soft eject')588588- * + ft_formatted == 0 -- this means that the cartridge is not589589- * formatted590590- * Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try591591- * to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we592592- * deny writes when593593- * + zft_qic_mode ==1 && 594594- * (!zft_tape_at_lbot() && -- tape no at logical BOT595595- * !(zft_tape_at_eom() || -- tape not at logical EOM (or EOD)596596- * (zft_tape_at_eom() &&597597- * zft_old_ftape()))) -- we can't add new volume to tapes 598598- * written by old ftape because ftape599599- * don't use the volume table600600- *601601- * when the drive is in true raw mode (aka /dev/rawft0) then we don't 602602- * care about LBOT and EOM conditions. This device is intended for a 603603- * user level program that wants to truly implement the QIC-80 compliance604604- * at the logical data layout level of the cartridge, i.e. implement all605605- * that volume table and volume directory stuff etc.<606606- */607607-int zft_check_write_access(zft_position *pos)608608-{609609- TRACE_FUN(ft_t_flow);610610-611611- if (zft_offline) { /* offline includes no_tape */612612- TRACE_ABORT(-ENXIO,613613- ft_t_info, "tape is offline or no cartridge");614614- }615615- if (!ft_formatted) {616616- TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");617617- } 618618- if (zft_write_protected) {619619- TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected");620620- } 621621- if (zft_qic_mode) {622622- /* check BOT condition */623623- if (!zft_tape_at_lbot(pos)) {624624- /* protect cartridges written by old ftape if625625- * not at BOT because they use the vtbl626626- * segment for storing data627627- */628628- if (zft_old_ftape) {629629- TRACE_ABORT(-EACCES, ft_t_warn, 630630- "Cannot write to cartridges written by old ftape when not at BOT");631631- }632632- /* not at BOT, but allow writes at EOD, of course633633- */634634- if (!zft_tape_at_eod(pos)) {635635- TRACE_ABORT(-EACCES, ft_t_info,636636- "tape not at BOT and not at EOD");637637- }638638- }639639- /* fine. Now the tape is either at BOT or at EOD. */640640- }641641- /* or in raw mode in which case we don't care about BOT and EOD */642642- TRACE_EXIT 0;643643-}644644-645645-/* OPEN routine called by kernel-interface code646646- *647647- * NOTE: this is also called by mt_reset() with dev_minor == -1648648- * to fake a reopen after a reset.649649- */650650-int _zft_open(unsigned int dev_minor, unsigned int access_mode)651651-{652652- static unsigned int tape_unit;653653- static unsigned int file_access_mode;654654- int result;655655- TRACE_FUN(ft_t_flow);656656-657657- if ((int)dev_minor == -1) {658658- /* fake reopen */659659- zft_unit = tape_unit;660660- access_mode = file_access_mode;661661- zft_init_driver(); /* reset all static data to defaults */662662- } else {663663- tape_unit = dev_minor;664664- file_access_mode = access_mode;665665- if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) {666666- TRACE_ABORT(-ENXIO, ft_t_err,667667- "ftape_enable failed: %d", result);668668- }669669- if (ft_new_tape || ft_no_tape || !ft_formatted ||670670- (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) ||671671- (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) {672672- /* reset all static data to defaults,673673- */674674- zft_init_driver(); 675675- }676676- zft_unit = dev_minor;677677- }678678- zft_set_flags(zft_unit); /* decode the minor bits */679679- if (zft_blk_sz == 1 && zft_use_compression) {680680- ftape_disable(); /* resets ft_no_tape */681681- TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet "682682- "supported with compression");683683- }684684- /* no need for most of the buffers when no tape or not685685- * formatted. for the read/write operations, it is the686686- * regardless whether there is no tape, a not-formatted tape687687- * or the whether the driver is soft offline. 688688- * Nevertheless we allow some ioctls with non-formatted tapes, 689689- * like rewind and reset.690690- */691691- if (ft_no_tape || !ft_formatted) {692692- zft_uninit_mem();693693- }694694- if (ft_no_tape) {695695- zft_offline = 1; /* so we need not test two variables */696696- }697697- if ((access_mode == O_WRONLY || access_mode == O_RDWR) &&698698- (ft_write_protected || ft_no_tape)) {699699- ftape_disable(); /* resets ft_no_tape */700700- TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS,701701- ft_t_warn, "wrong access mode %s cartridge",702702- ft_no_tape ? "without a" : "with write protected");703703- }704704- zft_write_protected = (access_mode == O_RDONLY || 705705- ft_write_protected != 0);706706- if (zft_write_protected) {707707- TRACE(ft_t_noise,708708- "read only access mode: %d, "709709- "drive write protected: %d", 710710- access_mode == O_RDONLY,711711- ft_write_protected != 0);712712- }713713- if (!zft_offline) {714714- TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE),715715- ftape_disable());716716- }717717- /* zft_seg_pos should be greater than the vtbl segpos but not718718- * if in compatibility mode and only after we read in the719719- * header segments720720- *721721- * might also be a problem if the user makes a backup with a722722- * *qft* device and rewinds it with a raw device.723723- */724724- if (zft_qic_mode &&725725- !zft_old_ftape &&726726- zft_pos.seg_pos >= 0 &&727727- zft_header_read && 728728- zft_pos.seg_pos <= ft_first_data_segment) {729729- TRACE(ft_t_noise, "you probably mixed up the zftape devices!");730730- zft_reset_position(&zft_pos); 731731- }732732- TRACE_EXIT 0;733733-}734734-735735-/* RELEASE routine called by kernel-interface code736736- */737737-int _zft_close(void)738738-{739739- int result = 0;740740- TRACE_FUN(ft_t_flow);741741-742742- if (zft_offline) {743743- /* call the hardware release routine. Puts the drive offline */744744- ftape_disable();745745- TRACE_EXIT 0;746746- }747747- if (!(ft_write_protected || zft_old_ftape)) {748748- result = zft_flush_buffers();749749- TRACE(ft_t_noise, "writing file mark at current position");750750- if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) {751751- zft_move_past_eof(&zft_pos);752752- }753753- if ((zft_tape_at_lbot(&zft_pos) ||754754- !(zft_unit & FTAPE_NO_REWIND))) {755755- if (result >= 0) {756756- result = zft_update_header_segments();757757- } else {758758- TRACE(ft_t_err,759759- "Error: unable to update header segments");760760- }761761- }762762- }763763- ftape_abort_operation();764764- if (!(zft_unit & FTAPE_NO_REWIND)) {765765- TRACE(ft_t_noise, "rewinding tape");766766- if (ftape_seek_to_bot() < 0 && result >= 0) {767767- result = -EIO; /* keep old value */768768- }769769- zft_reset_position(&zft_pos);770770- } 771771- zft_zap_read_buffers();772772- /* now free up memory as much as possible. We don't destroy773773- * the deblock buffer if it containes a valid segment.774774- */775775- if (zft_deblock_segment == -1) {776776- zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); 777777- }778778- /* high level driver status, forces creation of a new volume779779- * when calling ftape_write again and not zft_just_before_eof780780- */781781- zft_io_state = zft_idle; 782782- if (going_offline) {783783- zft_init_driver();784784- zft_uninit_mem();785785- going_offline = 0;786786- zft_offline = 1;787787- } else if (zft_cmpr_lock(0 /* don't load */) == 0) {788788- (*zft_cmpr_ops->reset)(); /* unlock it again */789789- }790790- zft_memory_stats();791791- /* call the hardware release routine. Puts the drive offline */792792- ftape_disable();793793- TRACE_EXIT result;794794-}795795-796796-/*797797- * the wrapper function around the wrapper MTIOCTOP ioctl798798- */799799-static int mtioctop(struct mtop *mtop, int arg_size)800800-{801801- int result = 0;802802- fun_entry *mt_fun_entry;803803- TRACE_FUN(ft_t_flow);804804-805805- if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) {806806- TRACE_EXIT -EINVAL;807807- }808808- TRACE(ft_t_noise, "calling MTIOCTOP command: %s",809809- mt_funs[mtop->mt_op].name);810810- mt_fun_entry= &mt_funs[mtop->mt_op];811811- zft_resid = mtop->mt_count;812812- if (!mt_fun_entry->offline && zft_offline) {813813- if (ft_no_tape) {814814- TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");815815- } else {816816- TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");817817- }818818- }819819- if (!mt_fun_entry->not_formatted && !ft_formatted) {820820- TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");821821- }822822- if (!mt_fun_entry->write_protected) {823823- TRACE_CATCH(zft_check_write_access(&zft_pos),);824824- }825825- if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) {826826- TRACE_CATCH(zft_def_idle_state(),);827827- }828828- if (!zft_qic_mode && !mt_fun_entry->raw_mode) {829829- TRACE_ABORT(-EACCES, ft_t_info, 830830-"Drive needs to be in QIC-80 compatibility mode for this command");831831- }832832- result = (mt_fun_entry->function)(&mtop->mt_count);833833- if (zft_tape_at_lbot(&zft_pos)) {834834- TRACE_CATCH(zft_update_header_segments(),);835835- }836836- if (result >= 0) {837837- zft_resid = 0;838838- }839839- TRACE_EXIT result;840840-}841841-842842-/*843843- * standard MTIOCGET ioctl844844- */845845-static int mtiocget(struct mtget *mtget, int arg_size)846846-{847847- const zft_volinfo *volume;848848- __s64 max_tape_pos;849849- TRACE_FUN(ft_t_flow);850850-851851- if (arg_size != sizeof(struct mtget)) {852852- TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",853853- arg_size);854854- }855855- mtget->mt_type = ft_drive_type.vendor_id + 0x800000;856856- mtget->mt_dsreg = ft_last_status.space;857857- mtget->mt_erreg = ft_last_error.space; /* error register */858858- mtget->mt_resid = zft_resid; /* residuum of writes, reads and859859- * MTIOCTOP commands 860860- */861861- if (!zft_offline) { /* neither no_tape nor soft offline */862862- mtget->mt_gstat = GMT_ONLINE(~0UL);863863- /* should rather return the status of the cartridge864864- * than the access mode of the file, therefor use865865- * ft_write_protected, not zft_write_protected 866866- */867867- if (ft_write_protected) {868868- mtget->mt_gstat |= GMT_WR_PROT(~0UL);869869- }870870- if(zft_header_read) { /* this catches non-formatted */871871- volume = zft_find_volume(zft_pos.seg_pos);872872- mtget->mt_fileno = volume->count;873873- max_tape_pos = zft_capacity - zft_blk_sz;874874- if (zft_use_compression) {875875- max_tape_pos -= ZFT_CMPR_OVERHEAD;876876- }877877- if (zft_tape_at_eod(&zft_pos)) {878878- mtget->mt_gstat |= GMT_EOD(~0UL);879879- }880880- if (zft_pos.tape_pos > max_tape_pos) {881881- mtget->mt_gstat |= GMT_EOT(~0UL);882882- }883883- mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos,884884- volume->blk_sz);885885- if (zft_just_before_eof) {886886- mtget->mt_gstat |= GMT_EOF(~0UL);887887- }888888- if (zft_tape_at_lbot(&zft_pos)) {889889- mtget->mt_gstat |= GMT_BOT(~0UL);890890- }891891- } else {892892- mtget->mt_fileno = mtget->mt_blkno = -1;893893- if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) {894894- mtget->mt_gstat |= GMT_BOT(~0UL);895895- }896896- }897897- } else {898898- if (ft_no_tape) {899899- mtget->mt_gstat = GMT_DR_OPEN(~0UL);900900- } else {901901- mtget->mt_gstat = 0UL;902902- }903903- mtget->mt_fileno = mtget->mt_blkno = -1;904904- }905905- TRACE_EXIT 0;906906-}907907-908908-#ifdef MTIOCRDFTSEG909909-/*910910- * Read a floppy tape segment. This is useful for manipulating the911911- * volume table, and read the old header segment before re-formatting912912- * the cartridge.913913- */914914-static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size)915915-{916916- TRACE_FUN(ft_t_flow);917917-918918- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG");919919- if (zft_qic_mode) {920920- TRACE_ABORT(-EACCES, ft_t_info,921921- "driver needs to be in raw mode for this ioctl");922922- } 923923- if (arg_size != sizeof(struct mtftseg)) {924924- TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",925925- arg_size);926926- }927927- if (zft_offline) {928928- TRACE_EXIT -ENXIO;929929- }930930- if (mtftseg->mt_mode != FT_RD_SINGLE &&931931- mtftseg->mt_mode != FT_RD_AHEAD) {932932- TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode");933933- }934934- if (!ft_formatted) {935935- TRACE_EXIT -EACCES; /* -ENXIO ? */936936-937937- }938938- if (!zft_header_read) {939939- TRACE_CATCH(zft_def_idle_state(),);940940- }941941- if (mtftseg->mt_segno > ft_last_data_segment) {942942- TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large");943943- }944944- mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno,945945- zft_deblock_buf,946946- mtftseg->mt_mode);947947- if (mtftseg->mt_result < 0) {948948- /* a negativ result is not an ioctl error. if949949- * the user wants to read damaged tapes,950950- * it's up to her/him951951- */952952- TRACE_EXIT 0;953953- }954954- if (copy_to_user(mtftseg->mt_data,955955- zft_deblock_buf,956956- mtftseg->mt_result) != 0) {957957- TRACE_EXIT -EFAULT;958958- }959959- TRACE_EXIT 0;960960-}961961-#endif962962-963963-#ifdef MTIOCWRFTSEG964964-/*965965- * write a floppy tape segment. This version features writing of966966- * deleted address marks, and gracefully ignores the (software)967967- * ft_formatted flag to support writing of header segments after968968- * formatting.969969- */970970-static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size)971971-{972972- int result;973973- TRACE_FUN(ft_t_flow);974974-975975- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG");976976- if (zft_write_protected || zft_qic_mode) {977977- TRACE_EXIT -EACCES;978978- } 979979- if (arg_size != sizeof(struct mtftseg)) {980980- TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",981981- arg_size);982982- }983983- if (zft_offline) {984984- TRACE_EXIT -ENXIO;985985- }986986- if (mtftseg->mt_mode != FT_WR_ASYNC && 987987- mtftseg->mt_mode != FT_WR_MULTI &&988988- mtftseg->mt_mode != FT_WR_SINGLE &&989989- mtftseg->mt_mode != FT_WR_DELETE) {990990- TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode");991991- }992992- /*993993- * We don't check for ft_formatted, because this gives994994- * only the software status of the driver.995995- *996996- * We assume that the user knows what it is997997- * doing. And rely on the low level stuff to fail998998- * when the tape isn't formatted. We only make sure999999- * that The header segment buffer is allocated,10001000- * because it holds the bad sector map.10011001- */10021002- if (zft_hseg_buf == NULL) {10031003- TRACE_EXIT -ENXIO;10041004- }10051005- if (mtftseg->mt_mode != FT_WR_DELETE) {10061006- if (copy_from_user(zft_deblock_buf, 10071007- mtftseg->mt_data,10081008- FT_SEGMENT_SIZE) != 0) {10091009- TRACE_EXIT -EFAULT;10101010- }10111011- }10121012- mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno, 10131013- zft_deblock_buf,10141014- mtftseg->mt_mode);10151015- if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) {10161016- /* 10171017- * a negativ result is not an ioctl error. if10181018- * the user wants to write damaged tapes,10191019- * it's up to her/him10201020- */10211021- if ((result = ftape_loop_until_writes_done()) < 0) {10221022- mtftseg->mt_result = result;10231023- }10241024- }10251025- TRACE_EXIT 0;10261026-}10271027-#endif10281028-10291029-#ifdef MTIOCVOLINFO10301030-/*10311031- * get information about volume positioned at.10321032- */10331033-static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size)10341034-{10351035- const zft_volinfo *volume;10361036- TRACE_FUN(ft_t_flow);10371037-10381038- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO");10391039- if (arg_size != sizeof(struct mtvolinfo)) {10401040- TRACE_ABORT(-EINVAL,10411041- ft_t_info, "bad argument size: %d", arg_size);10421042- }10431043- if (zft_offline) {10441044- TRACE_EXIT -ENXIO;10451045- }10461046- if (!ft_formatted) {10471047- TRACE_EXIT -EACCES;10481048- }10491049- TRACE_CATCH(zft_def_idle_state(),);10501050- volume = zft_find_volume(zft_pos.seg_pos);10511051- volinfo->mt_volno = volume->count;10521052- volinfo->mt_blksz = volume->blk_sz == 1 ? 0 : volume->blk_sz;10531053- volinfo->mt_size = volume->size >> 10;10541054- volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) -10551055- (zft_calc_tape_pos(volume->start_seg) >> 10));10561056- volinfo->mt_cmpr = volume->use_compression;10571057- TRACE_EXIT 0;10581058-}10591059-#endif10601060-10611061-#ifdef ZFT_OBSOLETE 10621062-static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size)10631063-{10641064- TRACE_FUN(ft_t_flow);10651065-10661066- TRACE(ft_t_noise, "\n"10671067- KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n"10681068- KERN_INFO "This ioctl is here merely for compatibility.\n"10691069- KERN_INFO "Please use MTIOCVOLINFO instead");10701070- if (arg_size != sizeof(struct mtblksz)) {10711071- TRACE_ABORT(-EINVAL,10721072- ft_t_info, "bad argument size: %d", arg_size);10731073- }10741074- if (zft_offline) {10751075- TRACE_EXIT -ENXIO;10761076- }10771077- if (!ft_formatted) {10781078- TRACE_EXIT -EACCES;10791079- }10801080- TRACE_CATCH(zft_def_idle_state(),);10811081- blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz;10821082- TRACE_EXIT 0;10831083-}10841084-#endif10851085-10861086-#ifdef MTIOCGETSIZE10871087-/*10881088- * get the capacity of the tape cartridge.10891089- */10901090-static int mtiocgetsize(struct mttapesize *size, int arg_size)10911091-{10921092- TRACE_FUN(ft_t_flow);10931093-10941094- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE");10951095- if (arg_size != sizeof(struct mttapesize)) {10961096- TRACE_ABORT(-EINVAL,10971097- ft_t_info, "bad argument size: %d", arg_size);10981098- }10991099- if (zft_offline) {11001100- TRACE_EXIT -ENXIO;11011101- }11021102- if (!ft_formatted) {11031103- TRACE_EXIT -EACCES;11041104- }11051105- TRACE_CATCH(zft_def_idle_state(),);11061106- size->mt_capacity = (unsigned int)(zft_capacity>>10);11071107- size->mt_used = (unsigned int)(zft_get_eom_pos()>>10);11081108- TRACE_EXIT 0;11091109-}11101110-#endif11111111-11121112-static int mtiocpos(struct mtpos *mtpos, int arg_size)11131113-{11141114- int result;11151115- TRACE_FUN(ft_t_flow);11161116-11171117- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS");11181118- if (arg_size != sizeof(struct mtpos)) {11191119- TRACE_ABORT(-EINVAL,11201120- ft_t_info, "bad argument size: %d", arg_size);11211121- }11221122- result = mt_tell((int *)&mtpos->mt_blkno);11231123- TRACE_EXIT result;11241124-}11251125-11261126-#ifdef MTIOCFTFORMAT11271127-/*11281128- * formatting of floppy tape cartridges. This is intended to be used11291129- * together with the MTIOCFTCMD ioctl and the new mmap feature 11301130- */11311131-11321132-/* 11331133- * This function uses ftape_decode_header_segment() to inform the low11341134- * level ftape module about the new parameters.11351135- *11361136- * It erases the hseg_buf. The calling process must specify all11371137- * parameters to assure proper operation.11381138- *11391139- * return values: -EINVAL - wrong argument size11401140- * -EINVAL - if ftape_decode_header_segment() failed.11411141- */11421142-static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf)11431143-{11441144- ft_trace_t old_level = TRACE_LEVEL;11451145- TRACE_FUN(ft_t_flow);11461146-11471147- TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS");11481148- memset(hseg_buf, 0, FT_SEGMENT_SIZE);11491149- PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC);11501150-11511151- /* fill in user specified parameters11521152- */11531153- hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode;11541154- PUT2(hseg_buf, FT_SPT, p->ft_spt);11551155- hseg_buf[FT_TPC] = (__u8)p->ft_tpc;11561156- hseg_buf[FT_FHM] = (__u8)p->ft_fhm;11571157- hseg_buf[FT_FTM] = (__u8)p->ft_ftm;11581158-11591159- /* fill in sane defaults to make ftape happy.11601160- */ 11611161- hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */11621162- if (p->ft_fmtcode == fmt_big) {11631163- PUT4(hseg_buf, FT_6_HSEG_1, 0);11641164- PUT4(hseg_buf, FT_6_HSEG_2, 1);11651165- PUT4(hseg_buf, FT_6_FRST_SEG, 2);11661166- PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1);11671167- } else {11681168- PUT2(hseg_buf, FT_HSEG_1, 0);11691169- PUT2(hseg_buf, FT_HSEG_2, 1);11701170- PUT2(hseg_buf, FT_FRST_SEG, 2);11711171- PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1);11721172- }11731173-11741174- /* Synchronize with the low level module. This is particularly11751175- * needed for unformatted cartridges as the QIC std was previously 11761176- * unknown BUT is needed to set data rate and to calculate timeouts.11771177- */11781178- TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK),11791179- _res = -EINVAL);11801180-11811181- /* The following will also recalcualte the timeouts for the tape11821182- * length and QIC std we want to format to.11831183- * abort with -EINVAL rather than -EIO11841184- */11851185- SET_TRACE_LEVEL(ft_t_warn);11861186- TRACE_CATCH(ftape_decode_header_segment(hseg_buf),11871187- SET_TRACE_LEVEL(old_level); _res = -EINVAL);11881188- SET_TRACE_LEVEL(old_level);11891189- TRACE_EXIT 0;11901190-}11911191-11921192-/*11931193- * Return the internal SOFTWARE status of the kernel driver. This does11941194- * NOT query the tape drive about its status.11951195- */11961196-static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer)11971197-{11981198- TRACE_FUN(ft_t_flow);11991199-12001200- TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS");12011201- p->ft_qicstd = ft_qic_std;12021202- p->ft_fmtcode = ft_format_code;12031203- p->ft_fhm = hseg_buffer[FT_FHM];12041204- p->ft_ftm = hseg_buffer[FT_FTM];12051205- p->ft_spt = ft_segments_per_track;12061206- p->ft_tpc = ft_tracks_per_tape;12071207- TRACE_EXIT 0;12081208-}12091209-12101210-static int mtiocftformat(struct mtftformat *mtftformat, int arg_size)12111211-{12121212- int result;12131213- union fmt_arg *arg = &mtftformat->fmt_arg;12141214- TRACE_FUN(ft_t_flow);12151215-12161216- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT");12171217- if (zft_offline) {12181218- if (ft_no_tape) {12191219- TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");12201220- } else {12211221- TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");12221222- }12231223- }12241224- if (zft_qic_mode) {12251225- TRACE_ABORT(-EACCES, ft_t_info,12261226- "driver needs to be in raw mode for this ioctl");12271227- } 12281228- if (zft_hseg_buf == NULL) {12291229- TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);12301230- }12311231- zft_header_read = 0;12321232- switch(mtftformat->fmt_op) {12331233- case FTFMT_SET_PARMS:12341234- TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),);12351235- TRACE_EXIT 0;12361236- case FTFMT_GET_PARMS:12371237- TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),);12381238- TRACE_EXIT 0;12391239- case FTFMT_FORMAT_TRACK:12401240- if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) ||12411241- (!ft_formatted && zft_write_protected)) {12421242- TRACE_ABORT(-EACCES, ft_t_info, "Write access denied");12431243- }12441244- TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track,12451245- arg->fmt_track.ft_gap3),);12461246- TRACE_EXIT 0;12471247- case FTFMT_STATUS:12481248- TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),);12491249- TRACE_EXIT 0;12501250- case FTFMT_VERIFY:12511251- TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment,12521252- (SectorMap *)&arg->fmt_verify.ft_bsm),);12531253- TRACE_EXIT 0;12541254- default:12551255- TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation");12561256- }12571257- TRACE_EXIT result;12581258-}12591259-#endif12601260-12611261-#ifdef MTIOCFTCMD12621262-/*12631263- * send a QIC-117 command to the drive, with optional timeouts,12641264- * parameter and result bits. This is intended to be used together12651265- * with the formatting ioctl.12661266- */12671267-static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)12681268-{12691269- int i;12701270- TRACE_FUN(ft_t_flow);12711271-12721272- TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");12731273- if (!capable(CAP_SYS_ADMIN)) {12741274- TRACE_ABORT(-EPERM, ft_t_info,12751275- "need CAP_SYS_ADMIN capability to send raw qic-117 commands");12761276- }12771277- if (zft_qic_mode) {12781278- TRACE_ABORT(-EACCES, ft_t_info,12791279- "driver needs to be in raw mode for this ioctl");12801280- } 12811281- if (arg_size != sizeof(struct mtftcmd)) {12821282- TRACE_ABORT(-EINVAL,12831283- ft_t_info, "bad argument size: %d", arg_size);12841284- }12851285- if (ftcmd->ft_wait_before) {12861286- TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before,12871287- &ftcmd->ft_status),);12881288- }12891289- if (ftcmd->ft_status & QIC_STATUS_ERROR)12901290- goto ftmtcmd_error;12911291- if (ftcmd->ft_result_bits != 0) {12921292- TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result,12931293- ftcmd->ft_cmd,12941294- ftcmd->ft_result_bits),);12951295- } else {12961296- TRACE_CATCH(ftape_command(ftcmd->ft_cmd),);12971297- if (ftcmd->ft_status & QIC_STATUS_ERROR)12981298- goto ftmtcmd_error;12991299- for (i = 0; i < ftcmd->ft_parm_cnt; i++) {13001300- TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),);13011301- if (ftcmd->ft_status & QIC_STATUS_ERROR)13021302- goto ftmtcmd_error;13031303- }13041304- }13051305- if (ftcmd->ft_wait_after != 0) {13061306- TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after,13071307- &ftcmd->ft_status),);13081308- }13091309-ftmtcmd_error: 13101310- if (ftcmd->ft_status & QIC_STATUS_ERROR) {13111311- TRACE(ft_t_noise, "error status set");13121312- TRACE_CATCH(ftape_report_error(&ftcmd->ft_error,13131313- &ftcmd->ft_cmd, 1),);13141314- }13151315- TRACE_EXIT 0; /* this is not an i/o error */13161316-}13171317-#endif13181318-13191319-/* IOCTL routine called by kernel-interface code13201320- */13211321-int _zft_ioctl(unsigned int command, void __user * arg)13221322-{13231323- int result;13241324- union { struct mtop mtop;13251325- struct mtget mtget;13261326- struct mtpos mtpos;13271327-#ifdef MTIOCRDFTSEG13281328- struct mtftseg mtftseg;13291329-#endif13301330-#ifdef MTIOCVOLINFO13311331- struct mtvolinfo mtvolinfo;13321332-#endif13331333-#ifdef MTIOCGETSIZE13341334- struct mttapesize mttapesize;13351335-#endif13361336-#ifdef MTIOCFTFORMAT13371337- struct mtftformat mtftformat;13381338-#endif13391339-#ifdef ZFT_OBSOLETE13401340- struct mtblksz mtblksz;13411341-#endif13421342-#ifdef MTIOCFTCMD13431343- struct mtftcmd mtftcmd;13441344-#endif13451345- } krnl_arg;13461346- int arg_size = _IOC_SIZE(command);13471347- int dir = _IOC_DIR(command);13481348- TRACE_FUN(ft_t_flow);13491349-13501350- /* This check will only catch arguments that are too large !13511351- */13521352- if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) {13531353- TRACE_ABORT(-EINVAL,13541354- ft_t_info, "bad argument size: %d", arg_size);13551355- }13561356- if (dir & _IOC_WRITE) {13571357- if (copy_from_user(&krnl_arg, arg, arg_size) != 0) {13581358- TRACE_EXIT -EFAULT;13591359- }13601360- }13611361- TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command);13621362- switch (command) {13631363- case MTIOCTOP:13641364- result = mtioctop(&krnl_arg.mtop, arg_size);13651365- break;13661366- case MTIOCGET:13671367- result = mtiocget(&krnl_arg.mtget, arg_size);13681368- break;13691369- case MTIOCPOS:13701370- result = mtiocpos(&krnl_arg.mtpos, arg_size);13711371- break;13721372-#ifdef MTIOCVOLINFO13731373- case MTIOCVOLINFO:13741374- result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size);13751375- break;13761376-#endif13771377-#ifdef ZFT_OBSOLETE13781378- case MTIOC_ZFTAPE_GETBLKSZ:13791379- result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size);13801380- break;13811381-#endif13821382-#ifdef MTIOCRDFTSEG13831383- case MTIOCRDFTSEG: /* read a segment via ioctl */13841384- result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size);13851385- break;13861386-#endif13871387-#ifdef MTIOCWRFTSEG13881388- case MTIOCWRFTSEG: /* write a segment via ioctl */13891389- result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size);13901390- break;13911391-#endif13921392-#ifdef MTIOCGETSIZE13931393- case MTIOCGETSIZE:13941394- result = mtiocgetsize(&krnl_arg.mttapesize, arg_size);13951395- break;13961396-#endif13971397-#ifdef MTIOCFTFORMAT13981398- case MTIOCFTFORMAT:13991399- result = mtiocftformat(&krnl_arg.mtftformat, arg_size);14001400- break;14011401-#endif14021402-#ifdef MTIOCFTCMD14031403- case MTIOCFTCMD:14041404- result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size);14051405- break;14061406-#endif14071407- default:14081408- result = -EINVAL;14091409- break;14101410- }14111411- if ((result >= 0) && (dir & _IOC_READ)) {14121412- if (copy_to_user(arg, &krnl_arg, arg_size) != 0) {14131413- TRACE_EXIT -EFAULT;14141414- }14151415- }14161416- TRACE_EXIT result;14171417-}
-58
drivers/char/ftape/zftape/zftape-ctl.h
···11-#ifndef _ZFTAPE_CTL_H22-#define _ZFTAPE_CTL_H33-44-/*55- * Copyright (C) 1996, 1997 Claus-Justus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version. 1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:19:02 $2525- *2626- * This file contains the non-standard IOCTL related definitions2727- * for the QIC-40/80 floppy-tape driver for Linux.2828- */2929-3030-#include <linux/ioctl.h>3131-#include <linux/mtio.h>3232-3333-#include "../zftape/zftape-rw.h"3434-3535-#ifdef CONFIG_ZFTAPE_MODULE3636-#define ftape_status (*zft_status)3737-#endif3838-3939-extern int zft_offline;4040-extern int zft_mt_compression;4141-extern int zft_write_protected;4242-extern int zft_header_read;4343-extern unsigned int zft_unit;4444-extern int zft_resid;4545-4646-extern void zft_reset_position(zft_position *pos);4747-extern int zft_check_write_access(zft_position *pos);4848-extern int zft_def_idle_state(void);4949-5050-/* hooks for the VFS interface 5151- */5252-extern int _zft_open(unsigned int dev_minor, unsigned int access_mode);5353-extern int _zft_close(void);5454-extern int _zft_ioctl(unsigned int command, void __user *arg);5555-#endif5656-5757-5858-
-199
drivers/char/ftape/zftape/zftape-eof.c
···11-/*22- * I use these routines just to decide when I have to fake a 33- * volume-table to preserve compatibility to original ftape.44- */55-/*66- * Copyright (C) 1994-1995 Bas Laarhoven.77- * 88- * Modified for zftape 1996, 1997 Claus Heine.99-1010- This program is free software; you can redistribute it and/or modify1111- it under the terms of the GNU General Public License as published by1212- the Free Software Foundation; either version 2, or (at your option)1313- any later version.1414-1515- This program is distributed in the hope that it will be useful,1616- but WITHOUT ANY WARRANTY; without even the implied warranty of1717- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1818- GNU General Public License for more details.1919-2020- You should have received a copy of the GNU General Public License2121- along with this program; see the file COPYING. If not, write to2222- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2323-2424- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.c,v $2525- * $Revision: 1.2 $2626- * $Date: 1997/10/05 19:19:02 $2727- *2828- * This file contains the eof mark handling code2929- * for the QIC-40/80 floppy-tape driver for Linux.3030- */3131-3232-#include <linux/string.h>3333-#include <linux/errno.h>3434-3535-#include <linux/zftape.h>3636-3737-#include "../zftape/zftape-init.h"3838-#include "../zftape/zftape-rw.h"3939-#include "../zftape/zftape-eof.h"4040-4141-/* Global vars.4242- */4343-4444-/* a copy of the failed sector log from the header segment.4545- */4646-eof_mark_union *zft_eof_map;4747-4848-/* number of eof marks (entries in bad sector log) on tape.4949- */5050-int zft_nr_eof_marks = -1;5151-5252-5353-/* Local vars.5454- */5555-5656-static char linux_tape_label[] = "Linux raw format V";5757-enum { 5858- min_fmt_version = 1, max_fmt_version = 2 5959-};6060-static unsigned ftape_fmt_version = 0;6161-6262-6363-/* Ftape (mis)uses the bad sector log to record end-of-file marks.6464- * Initially (when the tape is erased) all entries in the bad sector6565- * log are added to the tape's bad sector map. The bad sector log then6666- * is cleared.6767- *6868- * The bad sector log normally contains entries of the form: 6969- * even 16-bit word: segment number of bad sector 7070- * odd 16-bit word: encoded date7171- * There can be a total of 448 entries (1792 bytes).7272- *7373- * My guess is that no program is using this bad sector log (the *7474- * format seems useless as there is no indication of the bad sector7575- * itself, only the segment) However, if any program does use the bad7676- * sector log, the format used by ftape will let the program think7777- * there are some bad sectors and no harm is done.7878- * 7979- * The eof mark entries that ftape stores in the bad sector log: even8080- * 16-bit word: segment number of eof mark odd 16-bit word: sector8181- * number of eof mark [1..32]8282- * 8383- * The zft_eof_map as maintained is a sorted list of eof mark entries.8484- *8585- *8686- * The tape name field in the header segments is used to store a linux8787- * tape identification string and a version number. This way the tape8888- * can be recognized as a Linux raw format tape when using tools under8989- * other OS's.9090- *9191- * 'Wide' QIC tapes (format code 4) don't have a failed sector list9292- * anymore. That space is used for the (longer) bad sector map that9393- * now is a variable length list too. We now store our end-of-file9494- * marker list after the bad-sector-map on tape. The list is delimited9595- * by a (__u32) 0 entry.9696- */9797-9898-int zft_ftape_validate_label(char *label)9999-{100100- static char tmp_label[45];101101- int result = 0;102102- TRACE_FUN(ft_t_any);103103-104104- memcpy(tmp_label, label, FT_LABEL_SZ);105105- tmp_label[FT_LABEL_SZ] = '\0';106106- TRACE(ft_t_noise, "tape label = `%s'", tmp_label);107107- ftape_fmt_version = 0;108108- if (memcmp(label, linux_tape_label, strlen(linux_tape_label)) == 0) {109109- int pos = strlen(linux_tape_label);110110- while (label[pos] >= '0' && label[pos] <= '9') {111111- ftape_fmt_version *= 10;112112- ftape_fmt_version = label[ pos++] - '0';113113- }114114- result = (ftape_fmt_version >= min_fmt_version &&115115- ftape_fmt_version <= max_fmt_version);116116- }117117- TRACE(ft_t_noise, "format version = %d", ftape_fmt_version);118118- TRACE_EXIT result;119119-}120120-121121-static __u8 * find_end_of_eof_list(__u8 * ptr, __u8 * limit)122122-{123123- while (ptr + 3 < limit) {124124-125125- if (get_unaligned((__u32*)ptr)) {126126- ptr += sizeof(__u32);127127- } else {128128- return ptr;129129- }130130- }131131- return NULL;132132-}133133-134134-void zft_ftape_extract_file_marks(__u8* address)135135-{136136- int i;137137- TRACE_FUN(ft_t_any);138138-139139- zft_eof_map = NULL;140140- if (ft_format_code == fmt_var || ft_format_code == fmt_big) {141141- __u8* end;142142- __u8* start = ftape_find_end_of_bsm_list(address);143143-144144- zft_nr_eof_marks = 0;145145- if (start) {146146- start += 3; /* skip end of list mark */147147- end = find_end_of_eof_list(start, 148148- address + FT_SEGMENT_SIZE);149149- if (end && end - start <= FT_FSL_SIZE) {150150- zft_nr_eof_marks = ((end - start) / 151151- sizeof(eof_mark_union));152152- zft_eof_map = (eof_mark_union *)start;153153- } else {154154- TRACE(ft_t_err,155155- "EOF Mark List is too long or damaged!");156156- }157157- } else {158158- TRACE(ft_t_err, 159159- "Bad Sector List is too long or damaged !");160160- }161161- } else {162162- zft_eof_map = (eof_mark_union *)&address[FT_FSL];163163- zft_nr_eof_marks = GET2(address, FT_FSL_CNT);164164- }165165- TRACE(ft_t_noise, "number of file marks: %d", zft_nr_eof_marks);166166- if (ftape_fmt_version == 1) {167167- TRACE(ft_t_info, "swapping version 1 fields");168168- /* version 1 format uses swapped sector and segment169169- * fields, correct that ! 170170- */171171- for (i = 0; i < zft_nr_eof_marks; ++i) {172172- __u16 tmp = GET2(&zft_eof_map[i].mark.segment,0);173173- PUT2(&zft_eof_map[i].mark.segment, 0, 174174- GET2(&zft_eof_map[i].mark.date,0));175175- PUT2(&zft_eof_map[i].mark.date, 0, tmp);176176- }177177- }178178- for (i = 0; i < zft_nr_eof_marks; ++i) {179179- TRACE(ft_t_noise, "eof mark: %5d/%2d",180180- GET2(&zft_eof_map[i].mark.segment, 0), 181181- GET2(&zft_eof_map[i].mark.date,0));182182- }183183- TRACE_EXIT;184184-}185185-186186-void zft_clear_ftape_file_marks(void)187187-{188188- TRACE_FUN(ft_t_flow);189189- /* Clear failed sector log: remove all tape marks. We190190- * don't use old ftape-style EOF-marks.191191- */192192- TRACE(ft_t_info, "Clearing old ftape's eof map");193193- memset(zft_eof_map, 0, zft_nr_eof_marks * sizeof(__u32));194194- zft_nr_eof_marks = 0;195195- PUT2(zft_hseg_buf, FT_FSL_CNT, 0); /* nr of eof-marks */196196- zft_header_changed = 1;197197- zft_update_label(zft_hseg_buf);198198- TRACE_EXIT;199199-}
-52
drivers/char/ftape/zftape/zftape-eof.h
···11-#ifndef _ZFTAPE_EOF_H22-#define _ZFTAPE_EOF_H33-44-/*55- * Copyright (C) 1994-1995 Bas Laarhoven.66- * adaptaed for zftape 1996, 1997 by Claus Heine77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.h,v $2424- * $Revision: 1.2 $2525- * $Date: 1997/10/05 19:19:03 $2626- *2727- * Definitions and declarations for the end of file markers2828- * for the QIC-40/80 floppy-tape driver for Linux.2929- */3030-3131-#include <linux/ftape-header-segment.h>3232-#include "../zftape/zftape-buffers.h"3333-/* failed sector log size (only used if format code != 4).3434- */3535-3636-typedef union {3737- ft_fsl_entry mark;3838- __u32 entry;3939-} eof_mark_union;4040-4141-/* ftape-eof.c defined global vars.4242- */4343-extern int zft_nr_eof_marks;4444-extern eof_mark_union *zft_eof_map;4545-4646-/* ftape-eof.c defined global functions.4747- */4848-extern void zft_ftape_extract_file_marks(__u8* address);4949-extern int zft_ftape_validate_label(char* label);5050-extern void zft_clear_ftape_file_marks(void);5151-5252-#endif
-377
drivers/char/ftape/zftape/zftape-init.c
···11-/*22- * Copyright (C) 1996, 1997 Claus-Justus Heine.33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * This file contains the code that registers the zftape frontend 2020- * to the ftape floppy tape driver for Linux2121- */2222-2323-#include <linux/module.h>2424-#include <linux/errno.h>2525-#include <linux/fs.h>2626-#include <linux/kernel.h>2727-#include <linux/signal.h>2828-#include <linux/major.h>2929-#include <linux/slab.h>3030-#ifdef CONFIG_KMOD3131-#include <linux/kmod.h>3232-#endif3333-#include <linux/fcntl.h>3434-#include <linux/smp_lock.h>3535-3636-#include <linux/zftape.h>3737-#include <linux/init.h>3838-#include <linux/device.h>3939-4040-#include "../zftape/zftape-init.h"4141-#include "../zftape/zftape-read.h"4242-#include "../zftape/zftape-write.h"4343-#include "../zftape/zftape-ctl.h"4444-#include "../zftape/zftape-buffers.h"4545-4646-MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine "4747- "(claus@momo.math.rwth-aachen.de)");4848-MODULE_DESCRIPTION(ZFTAPE_VERSION " - "4949- "VFS interface for the Linux floppy tape driver. "5050- "Support for QIC-113 compatible volume table "5151- "and builtin compression (lzrw3 algorithm)");5252-MODULE_SUPPORTED_DEVICE("char-major-27");5353-MODULE_LICENSE("GPL");5454-5555-/* Global vars.5656- */5757-struct zft_cmpr_ops *zft_cmpr_ops = NULL;5858-const ftape_info *zft_status;5959-6060-/* Local vars.6161- */6262-static unsigned long busy_flag;6363-6464-static sigset_t orig_sigmask;6565-6666-/* the interface to the kernel vfs layer6767- */6868-6969-/* Note about llseek():7070- *7171- * st.c and tpqic.c update fp->f_pos but don't implment llseek() and7272- * initialize the llseek component of the file_ops struct with NULL.7373- * This means that the user will get the default seek, but the tape7474- * device will not respect the new position, but happily read from the7575- * old position. Think a zftape specific llseek() function would be7676- * better, returning -ESPIPE. TODO.7777- */7878-7979-static int zft_open (struct inode *ino, struct file *filep);8080-static int zft_close(struct inode *ino, struct file *filep);8181-static int zft_ioctl(struct inode *ino, struct file *filep,8282- unsigned int command, unsigned long arg);8383-static int zft_mmap(struct file *filep, struct vm_area_struct *vma);8484-static ssize_t zft_read (struct file *fp, char __user *buff,8585- size_t req_len, loff_t *ppos);8686-static ssize_t zft_write(struct file *fp, const char __user *buff,8787- size_t req_len, loff_t *ppos);8888-8989-static const struct file_operations zft_cdev =9090-{9191- .owner = THIS_MODULE,9292- .read = zft_read,9393- .write = zft_write,9494- .ioctl = zft_ioctl,9595- .mmap = zft_mmap,9696- .open = zft_open,9797- .release = zft_close,9898-};9999-100100-static struct class *zft_class;101101-102102-/* Open floppy tape device103103- */104104-static int zft_open(struct inode *ino, struct file *filep)105105-{106106- int result;107107- TRACE_FUN(ft_t_flow);108108-109109- nonseekable_open(ino, filep);110110- TRACE(ft_t_flow, "called for minor %d", iminor(ino));111111- if ( test_and_set_bit(0,&busy_flag) ) {112112- TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");113113- }114114- if ((iminor(ino) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))115115- > 116116- FTAPE_SEL_D) {117117- clear_bit(0,&busy_flag);118118- TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr");119119- }120120- orig_sigmask = current->blocked;121121- sigfillset(¤t->blocked);122122- result = _zft_open(iminor(ino), filep->f_flags & O_ACCMODE);123123- if (result < 0) {124124- current->blocked = orig_sigmask; /* restore mask */125125- clear_bit(0,&busy_flag);126126- TRACE_ABORT(result, ft_t_err, "_ftape_open failed");127127- } else {128128- /* Mask signals that will disturb proper operation of the129129- * program that is calling.130130- */131131- current->blocked = orig_sigmask;132132- sigaddsetmask (¤t->blocked, _DO_BLOCK);133133- TRACE_EXIT 0;134134- }135135-}136136-137137-/* Close floppy tape device138138- */139139-static int zft_close(struct inode *ino, struct file *filep)140140-{141141- int result;142142- TRACE_FUN(ft_t_flow);143143-144144- if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit) {145145- TRACE(ft_t_err, "failed: not busy or wrong unit");146146- TRACE_EXIT 0;147147- }148148- sigfillset(¤t->blocked);149149- result = _zft_close();150150- if (result < 0) {151151- TRACE(ft_t_err, "_zft_close failed");152152- }153153- current->blocked = orig_sigmask; /* restore before open state */154154- clear_bit(0,&busy_flag);155155- TRACE_EXIT 0;156156-}157157-158158-/* Ioctl for floppy tape device159159- */160160-static int zft_ioctl(struct inode *ino, struct file *filep,161161- unsigned int command, unsigned long arg)162162-{163163- int result = -EIO;164164- sigset_t old_sigmask;165165- TRACE_FUN(ft_t_flow);166166-167167- if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {168168- TRACE_ABORT(-EIO, ft_t_err,169169- "failed: not busy, failure or wrong unit");170170- }171171- old_sigmask = current->blocked; /* save mask */172172- sigfillset(¤t->blocked);173173- /* This will work as long as sizeof(void *) == sizeof(long) */174174- result = _zft_ioctl(command, (void __user *) arg);175175- current->blocked = old_sigmask; /* restore mask */176176- TRACE_EXIT result;177177-}178178-179179-/* Ioctl for floppy tape device180180- */181181-static int zft_mmap(struct file *filep, struct vm_area_struct *vma)182182-{183183- int result = -EIO;184184- sigset_t old_sigmask;185185- TRACE_FUN(ft_t_flow);186186-187187- if ( !test_bit(0,&busy_flag) || 188188- iminor(filep->f_dentry->d_inode) != zft_unit || 189189- ft_failure)190190- {191191- TRACE_ABORT(-EIO, ft_t_err,192192- "failed: not busy, failure or wrong unit");193193- }194194- old_sigmask = current->blocked; /* save mask */195195- sigfillset(¤t->blocked);196196- if ((result = ftape_mmap(vma)) >= 0) {197197-#ifndef MSYNC_BUG_WAS_FIXED198198- static struct vm_operations_struct dummy = { NULL, };199199- vma->vm_ops = &dummy;200200-#endif201201- }202202- current->blocked = old_sigmask; /* restore mask */203203- TRACE_EXIT result;204204-}205205-206206-/* Read from floppy tape device207207- */208208-static ssize_t zft_read(struct file *fp, char __user *buff,209209- size_t req_len, loff_t *ppos)210210-{211211- int result = -EIO;212212- sigset_t old_sigmask;213213- struct inode *ino = fp->f_dentry->d_inode;214214- TRACE_FUN(ft_t_flow);215215-216216- TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);217217- if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {218218- TRACE_ABORT(-EIO, ft_t_err,219219- "failed: not busy, failure or wrong unit");220220- }221221- old_sigmask = current->blocked; /* save mask */222222- sigfillset(¤t->blocked);223223- result = _zft_read(buff, req_len);224224- current->blocked = old_sigmask; /* restore mask */225225- TRACE(ft_t_data_flow, "return with count: %d", result);226226- TRACE_EXIT result;227227-}228228-229229-/* Write to tape device230230- */231231-static ssize_t zft_write(struct file *fp, const char __user *buff,232232- size_t req_len, loff_t *ppos)233233-{234234- int result = -EIO;235235- sigset_t old_sigmask;236236- struct inode *ino = fp->f_dentry->d_inode;237237- TRACE_FUN(ft_t_flow);238238-239239- TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);240240- if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {241241- TRACE_ABORT(-EIO, ft_t_err,242242- "failed: not busy, failure or wrong unit");243243- }244244- old_sigmask = current->blocked; /* save mask */245245- sigfillset(¤t->blocked);246246- result = _zft_write(buff, req_len);247247- current->blocked = old_sigmask; /* restore mask */248248- TRACE(ft_t_data_flow, "return with count: %d", result);249249- TRACE_EXIT result;250250-}251251-252252-/* END OF VFS INTERFACE 253253- * 254254- *****************************************************************************/255255-256256-/* driver/module initialization257257- */258258-259259-/* the compression module has to call this function to hook into the zftape 260260- * code261261- */262262-int zft_cmpr_register(struct zft_cmpr_ops *new_ops)263263-{264264- TRACE_FUN(ft_t_flow);265265-266266- if (zft_cmpr_ops != NULL) {267267- TRACE_EXIT -EBUSY;268268- } else {269269- zft_cmpr_ops = new_ops;270270- TRACE_EXIT 0;271271- }272272-}273273-274274-/* lock the zft-compressor() module.275275- */276276-int zft_cmpr_lock(int try_to_load)277277-{278278- if (zft_cmpr_ops == NULL) {279279-#ifdef CONFIG_KMOD280280- if (try_to_load) {281281- request_module("zft-compressor");282282- if (zft_cmpr_ops == NULL) {283283- return -ENOSYS;284284- }285285- } else {286286- return -ENOSYS;287287- }288288-#else289289- return -ENOSYS;290290-#endif291291- }292292- (*zft_cmpr_ops->lock)();293293- return 0;294294-}295295-296296-#ifdef CONFIG_ZFT_COMPRESSOR297297-extern int zft_compressor_init(void);298298-#endif299299-300300-/* Called by modules package when installing the driver or by kernel301301- * during the initialization phase302302- */303303-int __init zft_init(void)304304-{305305- int i;306306- TRACE_FUN(ft_t_flow);307307-308308-#ifdef MODULE309309- printk(KERN_INFO ZFTAPE_VERSION "\n");310310- if (TRACE_LEVEL >= ft_t_info) {311311- printk(312312-KERN_INFO313313-"(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"314314-KERN_INFO315315-"vfs interface for ftape floppy tape driver.\n"316316-KERN_INFO317317-"Support for QIC-113 compatible volume table, dynamic memory allocation\n"318318-KERN_INFO319319-"and builtin compression (lzrw3 algorithm).\n");320320- }321321-#else /* !MODULE */322322- /* print a short no-nonsense boot message */323323- printk(KERN_INFO ZFTAPE_VERSION "\n");324324-#endif /* MODULE */325325- TRACE(ft_t_info, "zft_init @ 0x%p", zft_init);326326- TRACE(ft_t_info,327327- "installing zftape VFS interface for ftape driver ...");328328- TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);329329-330330- zft_class = class_create(THIS_MODULE, "zft");331331- for (i = 0; i < 4; i++) {332332- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);333333- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);334334- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);335335- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);336336- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);337337- class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);338338- }339339-340340-#ifdef CONFIG_ZFT_COMPRESSOR341341- (void)zft_compressor_init();342342-#endif343343- zft_status = ftape_get_status(); /* fetch global data of ftape 344344- * hardware driver 345345- */346346- TRACE_EXIT 0;347347-}348348-349349-350350-/* Called by modules package when removing the driver 351351- */352352-static void zft_exit(void)353353-{354354- int i;355355- TRACE_FUN(ft_t_flow);356356-357357- if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {358358- TRACE(ft_t_warn, "failed");359359- } else {360360- TRACE(ft_t_info, "successful");361361- }362362- for (i = 0; i < 4; i++) {363363- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));364364- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));365365- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));366366- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));367367- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));368368- class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));369369- }370370- class_destroy(zft_class);371371- zft_uninit_mem(); /* release remaining memory, if any */372372- printk(KERN_INFO "zftape successfully unloaded.\n");373373- TRACE_EXIT;374374-}375375-376376-module_init(zft_init);377377-module_exit(zft_exit);
-77
drivers/char/ftape/zftape/zftape-init.h
···11-#ifndef _ZFTAPE_INIT_H22-#define _ZFTAPE_INIT_H33-44-/*55- * Copyright (C) 1996, 1997 Claus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-init.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:19:05 $2525- *2626- * This file contains definitions and macro for the vfs 2727- * interface defined by zftape2828- *2929- */3030-3131-#include <linux/ftape-header-segment.h>3232-3333-#include "../lowlevel/ftape-tracing.h"3434-#include "../lowlevel/ftape-ctl.h"3535-#include "../lowlevel/ftape-read.h"3636-#include "../lowlevel/ftape-write.h"3737-#include "../lowlevel/ftape-bsm.h"3838-#include "../lowlevel/ftape-io.h"3939-#include "../lowlevel/ftape-buffer.h"4040-#include "../lowlevel/ftape-format.h"4141-4242-#include "../zftape/zftape-rw.h"4343-4444-#ifdef MODULE4545-#define ftape_status (*zft_status)4646-#endif4747-4848-extern const ftape_info *zft_status; /* needed for zftape-vtbl.h */4949-5050-#include "../zftape/zftape-vtbl.h"5151-5252-struct zft_cmpr_ops {5353- int (*write)(int *write_cnt,5454- __u8 *dst_buf, const int seg_sz,5555- const __u8 __user *src_buf, const int req_len, 5656- const zft_position *pos, const zft_volinfo *volume);5757- int (*read)(int *read_cnt,5858- __u8 __user *dst_buf, const int req_len,5959- const __u8 *src_buf, const int seg_sz,6060- const zft_position *pos, const zft_volinfo *volume);6161- int (*seek)(unsigned int new_block_pos,6262- zft_position *pos, const zft_volinfo *volume,6363- __u8 *buffer);6464- void (*lock) (void);6565- void (*reset) (void);6666- void (*cleanup)(void);6767-};6868-6969-extern struct zft_cmpr_ops *zft_cmpr_ops;7070-/* zftape-init.c defined global functions.7171- */7272-extern int zft_cmpr_register(struct zft_cmpr_ops *new_ops);7373-extern int zft_cmpr_lock(int try_to_load);7474-7575-#endif7676-7777-
-377
drivers/char/ftape/zftape/zftape-read.c
···11-/*22- * Copyright (C) 1996, 1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-read.c,v $2020- * $Revision: 1.2 $2121- * $Date: 1997/10/05 19:19:06 $2222- *2323- * This file contains the high level reading code2424- * for the QIC-117 floppy-tape driver for Linux.2525- */2626-2727-#include <linux/errno.h>2828-#include <linux/mm.h>2929-3030-#include <linux/zftape.h>3131-3232-#include <asm/uaccess.h>3333-3434-#include "../zftape/zftape-init.h"3535-#include "../zftape/zftape-eof.h"3636-#include "../zftape/zftape-ctl.h"3737-#include "../zftape/zftape-write.h"3838-#include "../zftape/zftape-read.h"3939-#include "../zftape/zftape-rw.h"4040-#include "../zftape/zftape-vtbl.h"4141-4242-/* Global vars.4343- */4444-int zft_just_before_eof;4545-4646-/* Local vars.4747- */4848-static int buf_len_rd;4949-5050-void zft_zap_read_buffers(void)5151-{5252- buf_len_rd = 0;5353-}5454-5555-int zft_read_header_segments(void) 5656-{5757- TRACE_FUN(ft_t_flow);5858-5959- zft_header_read = 0;6060- TRACE_CATCH(zft_vmalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);6161- TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);6262- TRACE(ft_t_info, "Segments written since first format: %d",6363- (int)GET4(zft_hseg_buf, FT_SEG_CNT));6464- zft_qic113 = (ft_format_code != fmt_normal &&6565- ft_format_code != fmt_1100ft &&6666- ft_format_code != fmt_425ft);6767- TRACE(ft_t_info, "ft_first_data_segment: %d, ft_last_data_segment: %d", 6868- ft_first_data_segment, ft_last_data_segment);6969- zft_capacity = zft_get_capacity();7070- zft_old_ftape = zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]);7171- if (zft_old_ftape) {7272- TRACE(ft_t_info, 7373-"Found old ftaped tape, emulating eof marks, entering read-only mode");7474- zft_ftape_extract_file_marks(zft_hseg_buf);7575- TRACE_CATCH(zft_fake_volume_headers(zft_eof_map, 7676- zft_nr_eof_marks),);7777- } else {7878- /* the specs say that the volume table must be7979- * initialized with zeroes during formatting, so it8080- * MUST be readable, i.e. contain vaid ECC8181- * information. 8282- */8383- TRACE_CATCH(ftape_read_segment(ft_first_data_segment, 8484- zft_deblock_buf, 8585- FT_RD_SINGLE),);8686- TRACE_CATCH(zft_extract_volume_headers(zft_deblock_buf),);8787- }8888- zft_header_read = 1;8989- zft_set_flags(zft_unit);9090- zft_reset_position(&zft_pos);9191- TRACE_EXIT 0;9292-}9393-9494-int zft_fetch_segment_fraction(const unsigned int segment, void *buffer,9595- const ft_read_mode_t read_mode,9696- const unsigned int start,9797- const unsigned int size)9898-{9999- int seg_sz;100100- TRACE_FUN(ft_t_flow);101101-102102- if (segment == zft_deblock_segment) {103103- TRACE(ft_t_data_flow,104104- "re-using segment %d already in deblock buffer",105105- segment);106106- seg_sz = zft_get_seg_sz(segment);107107- if (start > seg_sz) {108108- TRACE_ABORT(-EINVAL, ft_t_bug,109109- "trying to read beyond end of segment:\n"110110- KERN_INFO "seg_sz : %d\n"111111- KERN_INFO "start : %d\n"112112- KERN_INFO "segment: %d",113113- seg_sz, start, segment);114114- }115115- if ((start + size) > seg_sz) {116116- TRACE_EXIT seg_sz - start;117117- }118118- TRACE_EXIT size;119119- }120120- seg_sz = ftape_read_segment_fraction(segment, buffer, read_mode,121121- start, size);122122- TRACE(ft_t_data_flow, "segment %d, result %d", segment, seg_sz);123123- if ((int)seg_sz >= 0 && start == 0 && size == FT_SEGMENT_SIZE) {124124- /* this implicitly assumes that we are always called with125125- * buffer == zft_deblock_buf 126126- */127127- zft_deblock_segment = segment;128128- } else {129129- zft_deblock_segment = -1;130130- }131131- TRACE_EXIT seg_sz;132132-}133133-134134-/*135135- * out:136136- *137137- * int *read_cnt: the number of bytes we removed from the138138- * zft_deblock_buf (result)139139- *140140- * int *to_do : the remaining size of the read-request. Is changed.141141- *142142- * in:143143- *144144- * char *buff : buff is the address of the upper part of the user145145- * buffer, that hasn't been filled with data yet.146146- * int buf_pos_read: copy of buf_pos_rd147147- * int buf_len_read: copy of buf_len_rd148148- * char *zft_deblock_buf: ftape_zft_deblock_buf149149- *150150- * returns the amount of data actually copied to the user-buffer151151- *152152- * to_do MUST NOT SHRINK except to indicate an EOT. In this case to_do153153- * has to be set to 0. We cannot return -ENOSPC, because we return the154154- * amount of data actually * copied to the user-buffer155155- */156156-static int zft_simple_read (int *read_cnt, 157157- __u8 __user *dst_buf, 158158- const int to_do, 159159- const __u8 *src_buf, 160160- const int seg_sz, 161161- const zft_position *pos,162162- const zft_volinfo *volume)163163-{164164- TRACE_FUN(ft_t_flow);165165-166166- if (seg_sz - pos->seg_byte_pos < to_do) {167167- *read_cnt = seg_sz - pos->seg_byte_pos;168168- } else {169169- *read_cnt = to_do;170170- }171171- if (copy_to_user(dst_buf, 172172- src_buf + pos->seg_byte_pos, *read_cnt) != 0) {173173- TRACE_EXIT -EFAULT;174174- }175175- TRACE(ft_t_noise, "nr bytes just read: %d", *read_cnt);176176- TRACE_EXIT *read_cnt;177177-}178178-179179-/* req_len: gets clipped due to EOT of EOF.180180- * req_clipped: is a flag indicating whether req_len was clipped or not181181- * volume: contains information on current volume (blk_sz etc.)182182- */183183-static int check_read_access(int *req_len, 184184- const zft_volinfo **volume,185185- int *req_clipped, 186186- const zft_position *pos)187187-{188188- static __s64 remaining;189189- static int eod;190190- TRACE_FUN(ft_t_flow);191191-192192- if (zft_io_state != zft_reading) {193193- if (zft_offline) { /* offline includes no_tape */194194- TRACE_ABORT(-ENXIO, ft_t_warn,195195- "tape is offline or no cartridge");196196- }197197- if (!ft_formatted) {198198- TRACE_ABORT(-EACCES,199199- ft_t_warn, "tape is not formatted");200200- }201201- /* now enter defined state, read header segment if not202202- * already done and flush write buffers203203- */204204- TRACE_CATCH(zft_def_idle_state(),);205205- zft_io_state = zft_reading;206206- if (zft_tape_at_eod(pos)) {207207- eod = 1;208208- TRACE_EXIT 1;209209- }210210- eod = 0;211211- *volume = zft_find_volume(pos->seg_pos);212212- /* get the space left until EOF */213213- remaining = zft_check_for_eof(*volume, pos);214214- buf_len_rd = 0;215215- TRACE(ft_t_noise, "remaining: " LL_X ", vol_no: %d",216216- LL(remaining), (*volume)->count);217217- } else if (zft_tape_at_eod(pos)) {218218- if (++eod > 2) {219219- TRACE_EXIT -EIO; /* st.c also returns -EIO */220220- } else {221221- TRACE_EXIT 1;222222- }223223- }224224- if ((*req_len % (*volume)->blk_sz) != 0) {225225- /* this message is informational only. The user gets the226226- * proper return value227227- */228228- TRACE_ABORT(-EINVAL, ft_t_info,229229- "req_len %d not a multiple of block size %d",230230- *req_len, (*volume)->blk_sz);231231- }232232- /* As GNU tar doesn't accept partial read counts when the233233- * multiple volume flag is set, we make sure to return the234234- * requested amount of data. Except, of course, at the end of235235- * the tape or file mark. 236236- */237237- remaining -= *req_len;238238- if (remaining <= 0) {239239- TRACE(ft_t_noise, 240240- "clipped request from %d to %d.", 241241- *req_len, (int)(*req_len + remaining));242242- *req_len += remaining;243243- *req_clipped = 1;244244- } else {245245- *req_clipped = 0;246246- }247247- TRACE_EXIT 0;248248-}249249-250250-/* this_segs_size: the current segment's size.251251- * buff: the USER-SPACE buffer provided by the calling function.252252- * req_len: how much data should be read at most.253253- * volume: contains information on current volume (blk_sz etc.)254254- */ 255255-static int empty_deblock_buf(__u8 __user *usr_buf, const int req_len,256256- const __u8 *src_buf, const int seg_sz,257257- zft_position *pos,258258- const zft_volinfo *volume)259259-{260260- int cnt;261261- int result = 0;262262- TRACE_FUN(ft_t_flow);263263-264264- TRACE(ft_t_data_flow, "this_segs_size: %d", seg_sz);265265- if (zft_use_compression && volume->use_compression) {266266- TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);267267- TRACE_CATCH(result= (*zft_cmpr_ops->read)(&cnt,268268- usr_buf, req_len,269269- src_buf, seg_sz,270270- pos, volume),);271271- } else { 272272- TRACE_CATCH(result= zft_simple_read (&cnt,273273- usr_buf, req_len,274274- src_buf, seg_sz,275275- pos, volume),);276276- }277277- pos->volume_pos += result;278278- pos->tape_pos += cnt;279279- pos->seg_byte_pos += cnt;280280- buf_len_rd -= cnt; /* remaining bytes in buffer */281281- TRACE(ft_t_data_flow, "buf_len_rd: %d, cnt: %d", buf_len_rd, cnt);282282- if(pos->seg_byte_pos >= seg_sz) {283283- pos->seg_pos++;284284- pos->seg_byte_pos = 0;285285- }286286- TRACE(ft_t_data_flow, "bytes moved out of deblock-buffer: %d", cnt);287287- TRACE_EXIT result;288288-}289289-290290-291291-/* note: we store the segment id of the segment that is inside the292292- * deblock buffer. This spares a lot of ftape_read_segment()s when we293293- * use small block-sizes. The block-size may be 1kb (SECTOR_SIZE). In294294- * this case a MTFSR 28 maybe still inside the same segment.295295- */296296-int _zft_read(char __user *buff, int req_len)297297-{298298- int req_clipped;299299- int result = 0;300300- int bytes_read = 0;301301- static unsigned int seg_sz = 0;302302- static const zft_volinfo *volume = NULL;303303- TRACE_FUN(ft_t_flow);304304-305305- zft_resid = req_len;306306- result = check_read_access(&req_len, &volume,307307- &req_clipped, &zft_pos);308308- switch(result) {309309- case 0: 310310- break; /* nothing special */311311- case 1: 312312- TRACE(ft_t_noise, "EOD reached");313313- TRACE_EXIT 0; /* EOD */314314- default:315315- TRACE_ABORT(result, ft_t_noise,316316- "check_read_access() failed with result %d",317317- result);318318- TRACE_EXIT result;319319- }320320- while (req_len > 0) { 321321- /* Allow escape from this loop on signal !322322- */323323- FT_SIGNAL_EXIT(_DONT_BLOCK);324324- /* buf_len_rd == 0 means that we need to read a new325325- * segment.326326- */327327- if (buf_len_rd == 0) {328328- while((result = zft_fetch_segment(zft_pos.seg_pos,329329- zft_deblock_buf,330330- FT_RD_AHEAD)) == 0) {331331- zft_pos.seg_pos ++;332332- zft_pos.seg_byte_pos = 0;333333- }334334- if (result < 0) {335335- zft_resid -= bytes_read;336336- TRACE_ABORT(result, ft_t_noise,337337- "zft_fetch_segment(): %d",338338- result);339339- }340340- seg_sz = result;341341- buf_len_rd = seg_sz - zft_pos.seg_byte_pos;342342- }343343- TRACE_CATCH(result = empty_deblock_buf(buff, 344344- req_len,345345- zft_deblock_buf, 346346- seg_sz, 347347- &zft_pos,348348- volume),349349- zft_resid -= bytes_read);350350- TRACE(ft_t_data_flow, "bytes just read: %d", result);351351- bytes_read += result; /* what we got so far */352352- buff += result; /* index in user-buffer */353353- req_len -= result; /* what's left from req_len */354354- } /* while (req_len > 0) */355355- if (req_clipped) {356356- TRACE(ft_t_data_flow,357357- "maybe partial count because of eof mark");358358- if (zft_just_before_eof && bytes_read == 0) {359359- /* req_len was > 0, but user didn't get360360- * anything the user has read in the eof-mark 361361- */362362- zft_move_past_eof(&zft_pos);363363- ftape_abort_operation();364364- } else {365365- /* don't skip to the next file before the user366366- * tried to read a second time past EOF Just367367- * mark that we are at EOF and maybe decrement368368- * zft_seg_pos to stay in the same volume;369369- */370370- zft_just_before_eof = 1;371371- zft_position_before_eof(&zft_pos, volume);372372- TRACE(ft_t_noise, "just before eof");373373- }374374- }375375- zft_resid -= result; /* for MTSTATUS */376376- TRACE_EXIT bytes_read;377377-}
-53
drivers/char/ftape/zftape/zftape-read.h
···11-#ifndef _ZFTAPE_READ_H22-#define _ZFTAPE_READ_H33-44-/*55- * Copyright (C) 1996, 1997 Claus-Justus Heine66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-read.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:19:07 $2525- *2626- * This file contains the definitions for the read functions2727- * for the zftape driver for Linux.2828- *2929- */3030-3131-#include "../lowlevel/ftape-read.h"3232-3333-/* ftape-read.c defined global vars.3434- */3535-extern int zft_just_before_eof;3636-3737-/* ftape-read.c defined global functions.3838- */3939-extern void zft_zap_read_buffers(void);4040-extern int zft_read_header_segments(void);4141-extern int zft_fetch_segment_fraction(const unsigned int segment,4242- void *buffer,4343- const ft_read_mode_t read_mode,4444- const unsigned int start,4545- const unsigned int size);4646-#define zft_fetch_segment(segment, address, read_mode) \4747- zft_fetch_segment_fraction(segment, address, read_mode, \4848- 0, FT_SEGMENT_SIZE)4949-/* hook for the VFS interface5050- */5151-extern int _zft_read(char __user *buff, int req_len);5252-5353-#endif /* _ZFTAPE_READ_H */
-375
drivers/char/ftape/zftape/zftape-rw.c
···11-/*22- * Copyright (C) 1996, 1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.c,v $2020- * $Revision: 1.2 $2121- * $Date: 1997/10/05 19:19:08 $2222- *2323- * This file contains some common code for the r/w code for2424- * zftape.2525- */2626-2727-#include <linux/errno.h>2828-#include <linux/mm.h>2929-3030-#include <linux/zftape.h>3131-#include "../zftape/zftape-init.h"3232-#include "../zftape/zftape-eof.h"3333-#include "../zftape/zftape-ctl.h"3434-#include "../zftape/zftape-write.h"3535-#include "../zftape/zftape-read.h"3636-#include "../zftape/zftape-rw.h"3737-#include "../zftape/zftape-vtbl.h"3838-3939-/* Global vars.4040- */4141-4242-__u8 *zft_deblock_buf;4343-__u8 *zft_hseg_buf;4444-int zft_deblock_segment = -1;4545-zft_status_enum zft_io_state = zft_idle;4646-int zft_header_changed;4747-int zft_qic113; /* conform to old specs. and old zftape */4848-int zft_use_compression;4949-zft_position zft_pos = {5050- -1, /* seg_pos */5151- 0, /* seg_byte_pos */5252- 0, /* tape_pos */5353- 0 /* volume_pos */5454-};5555-unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;5656-__s64 zft_capacity;5757-5858-unsigned int zft_written_segments;5959-int zft_label_changed;6060-6161-/* Local vars.6262- */6363-6464-unsigned int zft_get_seg_sz(unsigned int segment)6565-{6666- int size;6767- TRACE_FUN(ft_t_any);6868-6969- size = FT_SEGMENT_SIZE - 7070- count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;7171- if (size > 0) {7272- TRACE_EXIT (unsigned)size; 7373- } else {7474- TRACE_EXIT 0;7575- }7676-}7777-7878-/* ftape_set_flags(). Claus-Justus Heine, 1994/19957979- */8080-void zft_set_flags(unsigned minor_unit)8181-{ 8282- TRACE_FUN(ft_t_flow);8383-8484- zft_use_compression = zft_qic_mode = 0;8585- switch (minor_unit & ZFT_MINOR_OP_MASK) {8686- case (ZFT_Q80_MODE | ZFT_ZIP_MODE):8787- case ZFT_ZIP_MODE:8888- zft_use_compression = 1;8989- case 0:9090- case ZFT_Q80_MODE:9191- zft_qic_mode = 1;9292- if (zft_mt_compression) { /* override the default */9393- zft_use_compression = 1;9494- }9595- break;9696- case ZFT_RAW_MODE:9797- TRACE(ft_t_noise, "switching to raw mode");9898- break;9999- default:100100- TRACE(ft_t_warn, "Warning:\n"101101- KERN_INFO "Wrong combination of minor device bits.\n"102102- KERN_INFO "Switching to raw read-only mode.");103103- zft_write_protected = 1;104104- break;105105- }106106- TRACE_EXIT;107107-}108108-109109-/* computes the segment and byte offset inside the segment110110- * corresponding to tape_pos.111111- *112112- * tape_pos gives the offset in bytes from the beginning of the113113- * ft_first_data_segment *seg_byte_pos is the offset in the current114114- * segment in bytes115115- *116116- * Of, if this routine was called often one should cache the last data117117- * pos it was called with, but actually this is only needed in118118- * ftape_seek_block(), that is, almost never.119119- */120120-int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)121121-{122122- int segment;123123- int seg_sz;124124- TRACE_FUN(ft_t_flow);125125-126126- if (tape_pos == 0) {127127- *seg_byte_pos = 0;128128- segment = ft_first_data_segment;129129- } else {130130- seg_sz = 0;131131-132132- for (segment = ft_first_data_segment; 133133- ((tape_pos > 0) && (segment <= ft_last_data_segment));134134- segment++) {135135- seg_sz = zft_get_seg_sz(segment); 136136- tape_pos -= seg_sz;137137- }138138- if(tape_pos >= 0) {139139- /* the case tape_pos > != 0 means that the140140- * argument tape_pos lies beyond the EOT.141141- */142142- *seg_byte_pos= 0;143143- } else { /* tape_pos < 0 */144144- segment--;145145- *seg_byte_pos= tape_pos + seg_sz;146146- }147147- }148148- TRACE_EXIT(segment);149149-}150150-151151-/* ftape_calc_tape_pos().152152- *153153- * computes the offset in bytes from the beginning of the154154- * ft_first_data_segment inverse to ftape_calc_seg_byte_coord155155- *156156- * We should do some caching. But how:157157- *158158- * Each time the header segments are read in, this routine is called159159- * with ft_tracks_per_tape*segments_per_track argumnet. So this should be160160- * the time to reset the cache.161161- *162162- * Also, it might be in the future that the bad sector map gets163163- * changed. -> reset the cache164164- */165165-static int seg_pos;166166-static __s64 tape_pos;167167-168168-__s64 zft_get_capacity(void)169169-{170170- seg_pos = ft_first_data_segment;171171- tape_pos = 0;172172-173173- while (seg_pos <= ft_last_data_segment) {174174- tape_pos += zft_get_seg_sz(seg_pos ++);175175- }176176- return tape_pos;177177-}178178-179179-__s64 zft_calc_tape_pos(int segment)180180-{181181- int d1, d2, d3;182182- TRACE_FUN(ft_t_any);183183-184184- if (segment > ft_last_data_segment) {185185- TRACE_EXIT zft_capacity;186186- }187187- if (segment < ft_first_data_segment) {188188- TRACE_EXIT 0;189189- }190190- d2 = segment - seg_pos;191191- if (-d2 > 10) {192192- d1 = segment - ft_first_data_segment;193193- if (-d2 > d1) {194194- tape_pos = 0;195195- seg_pos = ft_first_data_segment;196196- d2 = d1;197197- }198198- }199199- if (d2 > 10) {200200- d3 = ft_last_data_segment - segment;201201- if (d2 > d3) {202202- tape_pos = zft_capacity;203203- seg_pos = ft_last_data_segment + 1;204204- d2 = -d3;205205- }206206- } 207207- if (d2 > 0) {208208- while (seg_pos < segment) {209209- tape_pos += zft_get_seg_sz(seg_pos++);210210- }211211- } else {212212- while (seg_pos > segment) {213213- tape_pos -= zft_get_seg_sz(--seg_pos);214214- }215215- }216216- TRACE(ft_t_noise, "new cached pos: %d", seg_pos);217217-218218- TRACE_EXIT tape_pos;219219-}220220-221221-/* copy Z-label string to buffer, keeps track of the correct offset in222222- * `buffer' 223223- */224224-void zft_update_label(__u8 *buffer)225225-{ 226226- TRACE_FUN(ft_t_flow);227227-228228- if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL, 229229- sizeof(ZFTAPE_LABEL)-1) != 0) {230230- TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"",231231- &buffer[FT_LABEL], ZFTAPE_LABEL);232232- strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);233233- memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ', 234234- FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));235235- PUT4(buffer, FT_LABEL_DATE, 0);236236- zft_label_changed = zft_header_changed = 1; /* changed */237237- }238238- TRACE_EXIT;239239-}240240-241241-int zft_verify_write_segments(unsigned int segment, 242242- __u8 *data, size_t size,243243- __u8 *buffer)244244-{245245- int result;246246- __u8 *write_buf;247247- __u8 *src_buf;248248- int single;249249- int seg_pos;250250- int seg_sz;251251- int remaining;252252- ft_write_mode_t write_mode;253253- TRACE_FUN(ft_t_flow);254254-255255- seg_pos = segment;256256- seg_sz = zft_get_seg_sz(seg_pos);257257- src_buf = data;258258- single = size <= seg_sz;259259- remaining = size;260260- do {261261- TRACE(ft_t_noise, "\n"262262- KERN_INFO "remaining: %d\n"263263- KERN_INFO "seg_sz : %d\n"264264- KERN_INFO "segment : %d",265265- remaining, seg_sz, seg_pos);266266- if (remaining == seg_sz) {267267- write_buf = src_buf;268268- write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;269269- remaining = 0;270270- } else if (remaining > seg_sz) {271271- write_buf = src_buf;272272- write_mode = FT_WR_ASYNC; /* don't start tape */273273- remaining -= seg_sz;274274- } else { /* remaining < seg_sz */275275- write_buf = buffer;276276- memcpy(write_buf, src_buf, remaining);277277- memset(&write_buf[remaining],'\0',seg_sz-remaining);278278- write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;279279- remaining = 0;280280- }281281- if ((result = ftape_write_segment(seg_pos, 282282- write_buf, 283283- write_mode)) != seg_sz) {284284- TRACE(ft_t_err, "Error: "285285- "Couldn't write segment %d", seg_pos);286286- TRACE_EXIT result < 0 ? result : -EIO; /* bail out */287287- }288288- zft_written_segments ++;289289- seg_sz = zft_get_seg_sz(++seg_pos);290290- src_buf += result;291291- } while (remaining > 0);292292- if (ftape_get_status()->fti_state == writing) {293293- TRACE_CATCH(ftape_loop_until_writes_done(),);294294- TRACE_CATCH(ftape_abort_operation(),);295295- zft_prevent_flush();296296- }297297- seg_pos = segment;298298- src_buf = data;299299- remaining = size;300300- do {301301- TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer, 302302- single ? FT_RD_SINGLE303303- : FT_RD_AHEAD),);304304- if (memcmp(src_buf, buffer, 305305- remaining > result ? result : remaining) != 0) {306306- TRACE_ABORT(-EIO, ft_t_err,307307- "Failed to verify written segment %d",308308- seg_pos);309309- }310310- remaining -= result;311311- TRACE(ft_t_noise, "verify successful:\n"312312- KERN_INFO "segment : %d\n"313313- KERN_INFO "segsize : %d\n"314314- KERN_INFO "remaining: %d",315315- seg_pos, result, remaining);316316- src_buf += seg_sz;317317- seg_pos++;318318- } while (remaining > 0);319319- TRACE_EXIT size;320320-}321321-322322-323323-/* zft_erase(). implemented compression-handling324324- *325325- * calculate the first data-segment when using/not using compression.326326- *327327- * update header-segment and compression-map-segment.328328- */329329-int zft_erase(void)330330-{331331- int result = 0;332332- TRACE_FUN(ft_t_flow);333333-334334- if (!zft_header_read) {335335- TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,336336- FT_SEGMENT_SIZE),);337337- /* no need to read the vtbl and compression map */338338- TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);339339- if ((zft_old_ftape = 340340- zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {341341- zft_ftape_extract_file_marks(zft_hseg_buf);342342- }343343- TRACE(ft_t_noise,344344- "ft_first_data_segment: %d, ft_last_data_segment: %d", 345345- ft_first_data_segment, ft_last_data_segment);346346- zft_qic113 = (ft_format_code != fmt_normal &&347347- ft_format_code != fmt_1100ft &&348348- ft_format_code != fmt_425ft);349349- }350350- if (zft_old_ftape) {351351- zft_clear_ftape_file_marks();352352- zft_old_ftape = 0; /* no longer old ftape */353353- }354354- PUT2(zft_hseg_buf, FT_CMAP_START, 0);355355- zft_volume_table_changed = 1;356356- zft_capacity = zft_get_capacity();357357- zft_init_vtbl();358358- /* the rest must be done in ftape_update_header_segments 359359- */360360- zft_header_read = 1;361361- zft_header_changed = 1; /* force update of timestamp */362362- result = zft_update_header_segments();363363-364364- ftape_abort_operation();365365-366366- zft_reset_position(&zft_pos);367367- zft_set_flags (zft_unit);368368- TRACE_EXIT result;369369-}370370-371371-unsigned int zft_get_time(void) 372372-{373373- unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */374374- return date;375375-}
-101
drivers/char/ftape/zftape/zftape-rw.h
···11-#ifndef _ZFTAPE_RW_H22-#define _ZFTAPE_RW_H33-44-/*55- * Copyright (C) 1996, 1997 Claus-Justus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:19:09 $2525- *2626- * This file contains the definitions for the read and write2727- * functions for the QIC-117 floppy-tape driver for Linux.2828- *2929- */3030-3131-#include "../zftape/zftape-buffers.h"3232-3333-#define SEGMENTS_PER_TAPE (ft_segments_per_track * ft_tracks_per_tape)3434-3535-/* QIC-113 Rev. G says that `a maximum of 63488 raw bytes may be3636- * compressed into a single frame'.3737- * Maybe we should stick to 32kb to make it more `beautiful'3838- */3939-#define ZFT_MAX_BLK_SZ (62*1024) /* bytes */4040-#if !defined(CONFIG_ZFT_DFLT_BLK_SZ)4141-# define CONFIG_ZFT_DFLT_BLK_SZ (10*1024) /* bytes, default of gnu tar */4242-#elif CONFIG_ZFT_DFLT_BLK_SZ == 04343-# undef CONFIG_ZFT_DFLT_BLK_SZ4444-# define CONFIG_ZFT_DFLT_BLK_SZ 14545-#elif (CONFIG_ZFT_DFLT_BLK_SZ % 1024) != 04646-# error CONFIG_ZFT_DFLT_BLK_SZ must be 1 or a multiple of 10244747-#endif4848-/* The *optional* compression routines need some overhead per tape4949- * block for their purposes. Instead of asking the actual compression5050- * implementation how much it needs, we restrict this overhead to be5151- * maximal of ZFT_CMPT_OVERHEAD size. We need this for EOT5252- * conditions. The tape is assumed to be logical at EOT when the5353- * distance from the physical EOT is less than 5454- * one tape block + ZFT_CMPR_OVERHEAD 5555- */5656-#define ZFT_CMPR_OVERHEAD 16 /* bytes */5757-5858-typedef enum5959-{ 6060- zft_idle = 0,6161- zft_reading,6262- zft_writing,6363-} zft_status_enum;6464-6565-typedef struct /* all values measured in bytes */6666-{6767- int seg_pos; /* segment currently positioned at */6868- int seg_byte_pos; /* offset in current segment */ 6969- __s64 tape_pos; /* real offset from BOT */7070- __s64 volume_pos; /* pos. in uncompressed data stream in7171- * current volume 7272- */7373-} zft_position; 7474-7575-extern zft_position zft_pos;7676-extern __u8 *zft_deblock_buf;7777-extern __u8 *zft_hseg_buf;7878-extern int zft_deblock_segment;7979-extern zft_status_enum zft_io_state;8080-extern int zft_header_changed;8181-extern int zft_qic113; /* conform to old specs. and old zftape */8282-extern int zft_use_compression;8383-extern unsigned int zft_blk_sz;8484-extern __s64 zft_capacity;8585-extern unsigned int zft_written_segments;8686-extern int zft_label_changed;8787-8888-/* zftape-rw.c exported functions8989- */9090-extern unsigned int zft_get_seg_sz(unsigned int segment);9191-extern void zft_set_flags(unsigned int minor_unit);9292-extern int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos);9393-extern __s64 zft_calc_tape_pos(int segment);9494-extern __s64 zft_get_capacity(void);9595-extern void zft_update_label(__u8 *buffer);9696-extern int zft_erase(void);9797-extern int zft_verify_write_segments(unsigned int segment, 9898- __u8 *data, size_t size, __u8 *buffer);9999-extern unsigned int zft_get_time(void);100100-#endif /* _ZFTAPE_RW_H */101101-
-757
drivers/char/ftape/zftape/zftape-vtbl.c
···11-/*22- * Copyright (c) 1995-1997 Claus-Justus Heine 33-44- This program is free software; you can redistribute it and/or55- modify it under the terms of the GNU General Public License as66- published by the Free Software Foundation; either version 2, or (at77- your option) any later version.88-99- This program is distributed in the hope that it will be useful, but1010- WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1212- General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,1717- USA.1818-1919- *2020- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.c,v $2121- * $Revision: 1.7.6.1 $2222- * $Date: 1997/11/24 13:48:31 $2323- *2424- * This file defines a volume table as defined in various QIC2525- * standards.2626- * 2727- * This is a minimal implementation, just allowing ordinary DOS2828- * :( prgrams to identify the cartridge as used.2929- */3030-3131-#include <linux/errno.h>3232-#include <linux/mm.h>3333-#include <linux/slab.h>3434-3535-#include <linux/zftape.h>3636-#include "../zftape/zftape-init.h"3737-#include "../zftape/zftape-eof.h"3838-#include "../zftape/zftape-ctl.h"3939-#include "../zftape/zftape-write.h"4040-#include "../zftape/zftape-read.h"4141-#include "../zftape/zftape-rw.h"4242-#include "../zftape/zftape-vtbl.h"4343-4444-#define ZFT_CMAP_HACK /* leave this defined to hide the compression map */4545-4646-/*4747- * global variables 4848- */4949-int zft_qic_mode = 1; /* use the vtbl */5050-int zft_old_ftape; /* prevents old ftaped tapes to be overwritten */5151-int zft_volume_table_changed; /* for write_header_segments() */5252-5353-/*5454- * private variables (only exported for inline functions)5555- */5656-LIST_HEAD(zft_vtbl);5757-5858-/* We could also allocate these dynamically when extracting the volume table5959- * sizeof(zft_volinfo) is about 32 or something close to that6060- */6161-static zft_volinfo tape_vtbl;6262-static zft_volinfo eot_vtbl;6363-static zft_volinfo *cur_vtbl;6464-6565-static inline void zft_new_vtbl_entry(void)6666-{6767- struct list_head *tmp = &zft_last_vtbl->node;6868- zft_volinfo *new = zft_kmalloc(sizeof(zft_volinfo));6969-7070- list_add(&new->node, tmp);7171- new->count = zft_eom_vtbl->count ++;7272-}7373-7474-void zft_free_vtbl(void)7575-{7676- for (;;) {7777- struct list_head *tmp = zft_vtbl.prev;7878- zft_volinfo *vtbl;7979-8080- if (tmp == &zft_vtbl)8181- break;8282- list_del(tmp);8383- vtbl = list_entry(tmp, zft_volinfo, node);8484- zft_kfree(vtbl, sizeof(zft_volinfo));8585- }8686- INIT_LIST_HEAD(&zft_vtbl);8787- cur_vtbl = NULL;8888-}8989-9090-/* initialize vtbl, called by ftape_new_cartridge()9191- */9292-void zft_init_vtbl(void)9393-{ 9494- zft_volinfo *new;9595-9696- zft_free_vtbl();9797-9898- /* Create the two dummy vtbl entries9999- */100100- new = zft_kmalloc(sizeof(zft_volinfo));101101- list_add(&new->node, &zft_vtbl);102102- new = zft_kmalloc(sizeof(zft_volinfo));103103- list_add(&new->node, &zft_vtbl);104104- zft_head_vtbl->end_seg = ft_first_data_segment;105105- zft_head_vtbl->blk_sz = zft_blk_sz;106106- zft_head_vtbl->count = -1;107107- zft_eom_vtbl->start_seg = ft_first_data_segment + 1;108108- zft_eom_vtbl->end_seg = ft_last_data_segment + 1;109109- zft_eom_vtbl->blk_sz = zft_blk_sz;110110- zft_eom_vtbl->count = 0;111111-112112- /* Reset the pointer for zft_find_volume()113113- */114114- cur_vtbl = zft_eom_vtbl;115115-116116- /* initialize the dummy vtbl entries for zft_qic_mode == 0117117- */118118- eot_vtbl.start_seg = ft_last_data_segment + 1;119119- eot_vtbl.end_seg = ft_last_data_segment + 1;120120- eot_vtbl.blk_sz = zft_blk_sz;121121- eot_vtbl.count = -1;122122- tape_vtbl.start_seg = ft_first_data_segment;123123- tape_vtbl.end_seg = ft_last_data_segment;124124- tape_vtbl.blk_sz = zft_blk_sz;125125- tape_vtbl.size = zft_capacity;126126- tape_vtbl.count = 0;127127-}128128-129129-/* check for a valid VTBL signature. 130130- */131131-static int vtbl_signature_valid(__u8 signature[4])132132-{133133- const char *vtbl_ids[] = VTBL_IDS; /* valid signatures */134134- int j;135135-136136- for (j = 0; 137137- (j < NR_ITEMS(vtbl_ids)) && (memcmp(signature, vtbl_ids[j], 4) != 0);138138- j++);139139- return j < NR_ITEMS(vtbl_ids);140140-}141141-142142-/* We used to store the block-size of the volume in the volume-label,143143- * using the keyword "blocksize". The blocksize written to the144144- * volume-label is in bytes.145145- *146146- * We use this now only for compatibility with old zftape version. We147147- * store the blocksize directly as binary number in the vendor148148- * extension part of the volume entry.149149- */150150-static int check_volume_label(const char *label, int *blk_sz)151151-{ 152152- int valid_format;153153- char *blocksize;154154- TRACE_FUN(ft_t_flow);155155-156156- TRACE(ft_t_noise, "called with \"%s\" / \"%s\"", label, ZFT_VOL_NAME);157157- if (strncmp(label, ZFT_VOL_NAME, strlen(ZFT_VOL_NAME)) != 0) {158158- *blk_sz = 1; /* smallest block size that we allow */159159- valid_format = 0;160160- } else {161161- TRACE(ft_t_noise, "got old style zftape vtbl entry");162162- /* get the default blocksize */163163- /* use the kernel strstr() */164164- blocksize= strstr(label, " blocksize ");165165- if (blocksize) {166166- blocksize += strlen(" blocksize ");167167- for(*blk_sz= 0; 168168- *blocksize >= '0' && *blocksize <= '9'; 169169- blocksize++) {170170- *blk_sz *= 10;171171- *blk_sz += *blocksize - '0';172172- }173173- if (*blk_sz > ZFT_MAX_BLK_SZ) {174174- *blk_sz= 1;175175- valid_format= 0;176176- } else {177177- valid_format = 1;178178- }179179- } else {180180- *blk_sz= 1;181181- valid_format= 0;182182- }183183- }184184- TRACE_EXIT valid_format;185185-}186186-187187-/* check for a zftape volume188188- */189189-static int check_volume(__u8 *entry, zft_volinfo *volume)190190-{191191- TRACE_FUN(ft_t_flow);192192-193193- if(strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,194194- strlen(ZFTAPE_SIG)) == 0) {195195- TRACE(ft_t_noise, "got new style zftape vtbl entry");196196- volume->blk_sz = GET2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ);197197- volume->qic113 = entry[VTBL_EXT+EXT_ZFTAPE_QIC113];198198- TRACE_EXIT 1;199199- } else {200200- TRACE_EXIT check_volume_label(&entry[VTBL_DESC], &volume->blk_sz);201201- }202202-}203203-204204-205205-/* create zftape specific vtbl entry, the volume bounds are inserted206206- * in the calling function, zft_create_volume_headers()207207- */208208-static void create_zft_volume(__u8 *entry, zft_volinfo *vtbl)209209-{210210- TRACE_FUN(ft_t_flow);211211-212212- memset(entry, 0, VTBL_SIZE);213213- memcpy(&entry[VTBL_SIG], VTBL_ID, 4);214214- sprintf(&entry[VTBL_DESC], ZFT_VOL_NAME" %03d", vtbl->count);215215- entry[VTBL_FLAGS] = (VTBL_FL_NOT_VERIFIED | VTBL_FL_SEG_SPANNING);216216- entry[VTBL_M_NO] = 1; /* multi_cartridge_count */217217- strcpy(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG);218218- PUT2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ, vtbl->blk_sz);219219- if (zft_qic113) {220220- PUT8(entry, VTBL_DATA_SIZE, vtbl->size);221221- entry[VTBL_CMPR] = VTBL_CMPR_UNREG; 222222- if (vtbl->use_compression) { /* use compression: */223223- entry[VTBL_CMPR] |= VTBL_CMPR_USED;224224- }225225- entry[VTBL_EXT+EXT_ZFTAPE_QIC113] = 1;226226- } else {227227- PUT4(entry, VTBL_DATA_SIZE, vtbl->size);228228- entry[VTBL_K_CMPR] = VTBL_CMPR_UNREG; 229229- if (vtbl->use_compression) { /* use compression: */230230- entry[VTBL_K_CMPR] |= VTBL_CMPR_USED;231231- }232232- }233233- if (ft_format_code == fmt_big) {234234- /* SCSI like vtbl, store the number of used235235- * segments as 4 byte value 236236- */237237- PUT4(entry, VTBL_SCSI_SEGS, vtbl->end_seg-vtbl->start_seg + 1);238238- } else {239239- /* normal, QIC-80MC like vtbl 240240- */241241- PUT2(entry, VTBL_START, vtbl->start_seg);242242- PUT2(entry, VTBL_END, vtbl->end_seg);243243- }244244- TRACE_EXIT;245245-}246246-247247-/* this one creates the volume headers for each volume. It is assumed248248- * that buffer already contains the old volume-table, so that vtbl249249- * entries without the zft_volume flag set can savely be ignored.250250- */251251-static void zft_create_volume_headers(__u8 *buffer)252252-{ 253253- __u8 *entry;254254- struct list_head *tmp;255255- zft_volinfo *vtbl;256256- TRACE_FUN(ft_t_flow);257257-258258-#ifdef ZFT_CMAP_HACK259259- if((strncmp(&buffer[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,260260- strlen(ZFTAPE_SIG)) == 0) && 261261- buffer[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {262262- TRACE(ft_t_noise, "deleting cmap volume");263263- memmove(buffer, buffer + VTBL_SIZE,264264- FT_SEGMENT_SIZE - VTBL_SIZE);265265- }266266-#endif267267- entry = buffer;268268- for (tmp = zft_head_vtbl->node.next;269269- tmp != &zft_eom_vtbl->node;270270- tmp = tmp->next) {271271- vtbl = list_entry(tmp, zft_volinfo, node);272272- /* we now fill in the values only for newly created volumes.273273- */274274- if (vtbl->new_volume) {275275- create_zft_volume(entry, vtbl);276276- vtbl->new_volume = 0; /* clear the flag */277277- }278278-279279- DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], vtbl);280280- entry += VTBL_SIZE;281281- }282282- memset(entry, 0, FT_SEGMENT_SIZE - zft_eom_vtbl->count * VTBL_SIZE);283283- TRACE_EXIT;284284-}285285-286286-/* write volume table to tape. Calls zft_create_volume_headers()287287- */288288-int zft_update_volume_table(unsigned int segment)289289-{290290- int result = 0;291291- __u8 *verify_buf = NULL;292292- TRACE_FUN(ft_t_flow);293293-294294- TRACE_CATCH(result = ftape_read_segment(ft_first_data_segment, 295295- zft_deblock_buf,296296- FT_RD_SINGLE),);297297- zft_create_volume_headers(zft_deblock_buf);298298- TRACE(ft_t_noise, "writing volume table segment %d", segment);299299- if (zft_vmalloc_once(&verify_buf, FT_SEGMENT_SIZE) == 0) {300300- TRACE_CATCH(zft_verify_write_segments(segment, 301301- zft_deblock_buf, result,302302- verify_buf),303303- zft_vfree(&verify_buf, FT_SEGMENT_SIZE));304304- zft_vfree(&verify_buf, FT_SEGMENT_SIZE);305305- } else {306306- TRACE_CATCH(ftape_write_segment(segment, zft_deblock_buf, 307307- FT_WR_SINGLE),);308308- }309309- TRACE_EXIT 0;310310-}311311-312312-/* non zftape volumes are handled in raw mode. Thus we need to313313- * calculate the raw amount of data contained in those segments. 314314- */315315-static void extract_alien_volume(__u8 *entry, zft_volinfo *vtbl)316316-{317317- TRACE_FUN(ft_t_flow);318318-319319- vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) -320320- zft_calc_tape_pos(zft_last_vtbl->start_seg));321321- vtbl->use_compression = 0;322322- vtbl->qic113 = zft_qic113;323323- if (vtbl->qic113) {324324- TRACE(ft_t_noise, 325325- "Fake alien volume's size from " LL_X " to " LL_X, 326326- LL(GET8(entry, VTBL_DATA_SIZE)), LL(vtbl->size));327327- } else {328328- TRACE(ft_t_noise,329329- "Fake alien volume's size from %d to " LL_X, 330330- (int)GET4(entry, VTBL_DATA_SIZE), LL(vtbl->size));331331- }332332- TRACE_EXIT;333333-}334334-335335-336336-/* extract an zftape specific volume337337- */338338-static void extract_zft_volume(__u8 *entry, zft_volinfo *vtbl)339339-{340340- TRACE_FUN(ft_t_flow);341341-342342- if (vtbl->qic113) {343343- vtbl->size = GET8(entry, VTBL_DATA_SIZE);344344- vtbl->use_compression = 345345- (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0; 346346- } else {347347- vtbl->size = GET4(entry, VTBL_DATA_SIZE);348348- if (entry[VTBL_K_CMPR] & VTBL_CMPR_UNREG) {349349- vtbl->use_compression = 350350- (entry[VTBL_K_CMPR] & VTBL_CMPR_USED) != 0;351351- } else if (entry[VTBL_CMPR] & VTBL_CMPR_UNREG) {352352- vtbl->use_compression = 353353- (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0; 354354- } else {355355- TRACE(ft_t_warn, "Geeh! There is something wrong:\n"356356- KERN_INFO "QIC compression (Rev = K): %x\n"357357- KERN_INFO "QIC compression (Rev > K): %x",358358- entry[VTBL_K_CMPR], entry[VTBL_CMPR]);359359- }360360- }361361- TRACE_EXIT;362362-}363363-364364-/* extract the volume table from buffer. "buffer" must already contain365365- * the vtbl-segment 366366- */367367-int zft_extract_volume_headers(__u8 *buffer)368368-{ 369369- __u8 *entry;370370- TRACE_FUN(ft_t_flow);371371-372372- zft_init_vtbl();373373- entry = buffer;374374-#ifdef ZFT_CMAP_HACK375375- if ((strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,376376- strlen(ZFTAPE_SIG)) == 0) &&377377- entry[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {378378- TRACE(ft_t_noise, "ignoring cmap volume");379379- entry += VTBL_SIZE;380380- } 381381-#endif382382- /* the end of the vtbl is indicated by an invalid signature 383383- */384384- while (vtbl_signature_valid(&entry[VTBL_SIG]) &&385385- (entry - buffer) < FT_SEGMENT_SIZE) {386386- zft_new_vtbl_entry();387387- if (ft_format_code == fmt_big) {388388- /* SCSI like vtbl, stores only the number of389389- * segments used 390390- */391391- unsigned int num_segments= GET4(entry, VTBL_SCSI_SEGS);392392- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;393393- zft_last_vtbl->end_seg = 394394- zft_last_vtbl->start_seg + num_segments - 1;395395- } else {396396- /* `normal', QIC-80 like vtbl 397397- */398398- zft_last_vtbl->start_seg = GET2(entry, VTBL_START);399399- zft_last_vtbl->end_seg = GET2(entry, VTBL_END);400400- }401401- zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;402402- /* check if we created this volume and get the403403- * blk_sz 404404- */405405- zft_last_vtbl->zft_volume = check_volume(entry, zft_last_vtbl);406406- if (zft_last_vtbl->zft_volume == 0) {407407- extract_alien_volume(entry, zft_last_vtbl);408408- } else {409409- extract_zft_volume(entry, zft_last_vtbl);410410- }411411- DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], zft_last_vtbl);412412- entry +=VTBL_SIZE;413413- }414414-#if 0415415-/*416416- * undefine to test end of tape handling417417- */418418- zft_new_vtbl_entry();419419- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;420420- zft_last_vtbl->end_seg = ft_last_data_segment - 10;421421- zft_last_vtbl->blk_sz = zft_blk_sz;422422- zft_last_vtbl->zft_volume = 1;423423- zft_last_vtbl->qic113 = zft_qic113;424424- zft_last_vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1)425425- - zft_calc_tape_pos(zft_last_vtbl->start_seg));426426-#endif427427- TRACE_EXIT 0;428428-}429429-430430-/* this functions translates the failed_sector_log, misused as431431- * EOF-marker list, into a virtual volume table. The table mustn't be432432- * written to tape, because this would occupy the first data segment,433433- * which should be the volume table, but is actually the first segment434434- * that is filled with data (when using standard ftape). We assume,435435- * that we get a non-empty failed_sector_log.436436- */437437-int zft_fake_volume_headers (eof_mark_union *eof_map, int num_failed_sectors)438438-{439439- unsigned int segment, sector;440440- int have_eom = 0;441441- int vol_no;442442- TRACE_FUN(ft_t_flow);443443-444444- if ((num_failed_sectors >= 2) &&445445- (GET2(&eof_map[num_failed_sectors - 1].mark.segment, 0) 446446- == 447447- GET2(&eof_map[num_failed_sectors - 2].mark.segment, 0) + 1) &&448448- (GET2(&eof_map[num_failed_sectors - 1].mark.date, 0) == 1)) {449449- /* this should be eom. We keep the remainder of the450450- * tape as another volume.451451- */452452- have_eom = 1;453453- }454454- zft_init_vtbl();455455- zft_eom_vtbl->start_seg = ft_first_data_segment;456456- for(vol_no = 0; vol_no < num_failed_sectors - have_eom; vol_no ++) {457457- zft_new_vtbl_entry();458458-459459- segment = GET2(&eof_map[vol_no].mark.segment, 0);460460- sector = GET2(&eof_map[vol_no].mark.date, 0);461461-462462- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;463463- zft_last_vtbl->end_seg = segment;464464- zft_eom_vtbl->start_seg = segment + 1;465465- zft_last_vtbl->blk_sz = 1;466466- zft_last_vtbl->size = 467467- (zft_calc_tape_pos(zft_last_vtbl->end_seg)468468- - zft_calc_tape_pos(zft_last_vtbl->start_seg)469469- + (sector-1) * FT_SECTOR_SIZE);470470- TRACE(ft_t_noise, 471471- "failed sector log: segment: %d, sector: %d", 472472- segment, sector);473473- DUMP_VOLINFO(ft_t_noise, "Faked volume", zft_last_vtbl);474474- }475475- if (!have_eom) {476476- zft_new_vtbl_entry();477477- zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;478478- zft_last_vtbl->end_seg = ft_last_data_segment;479479- zft_eom_vtbl->start_seg = ft_last_data_segment + 1;480480- zft_last_vtbl->size = zft_capacity;481481- zft_last_vtbl->size -= zft_calc_tape_pos(zft_last_vtbl->start_seg);482482- zft_last_vtbl->blk_sz = 1;483483- DUMP_VOLINFO(ft_t_noise, "Faked volume",zft_last_vtbl);484484- }485485- TRACE_EXIT 0;486486-}487487-488488-/* update the internal volume table489489- *490490- * if before start of last volume: erase all following volumes if491491- * inside a volume: set end of volume to infinity492492- *493493- * this function is intended to be called every time _ftape_write() is494494- * called495495- *496496- * return: 0 if no new volume was created, 1 if a new volume was497497- * created498498- *499499- * NOTE: we don't need to check for zft_mode as ftape_write() does500500- * that already. This function gets never called without accessing501501- * zftape via the *qft* devices 502502- */503503-504504-int zft_open_volume(zft_position *pos, int blk_sz, int use_compression)505505-{ 506506- TRACE_FUN(ft_t_flow);507507-508508- if (!zft_qic_mode) {509509- TRACE_EXIT 0;510510- }511511- if (zft_tape_at_lbot(pos)) {512512- zft_init_vtbl();513513- if(zft_old_ftape) {514514- /* clear old ftape's eof marks */515515- zft_clear_ftape_file_marks();516516- zft_old_ftape = 0; /* no longer old ftape */517517- }518518- zft_reset_position(pos);519519- }520520- if (pos->seg_pos != zft_last_vtbl->end_seg + 1) {521521- TRACE_ABORT(-EIO, ft_t_bug, 522522- "BUG: seg_pos: %d, zft_last_vtbl->end_seg: %d", 523523- pos->seg_pos, zft_last_vtbl->end_seg);524524- } 525525- TRACE(ft_t_noise, "create new volume");526526- if (zft_eom_vtbl->count >= ZFT_MAX_VOLUMES) {527527- TRACE_ABORT(-ENOSPC, ft_t_err,528528- "Error: maxmimal number of volumes exhausted "529529- "(maxmimum is %d)", ZFT_MAX_VOLUMES);530530- }531531- zft_new_vtbl_entry();532532- pos->volume_pos = pos->seg_byte_pos = 0;533533- zft_last_vtbl->start_seg = pos->seg_pos;534534- zft_last_vtbl->end_seg = ft_last_data_segment; /* infinity */535535- zft_last_vtbl->blk_sz = blk_sz;536536- zft_last_vtbl->size = zft_capacity;537537- zft_last_vtbl->zft_volume = 1;538538- zft_last_vtbl->use_compression = use_compression;539539- zft_last_vtbl->qic113 = zft_qic113;540540- zft_last_vtbl->new_volume = 1;541541- zft_last_vtbl->open = 1;542542- zft_volume_table_changed = 1;543543- zft_eom_vtbl->start_seg = ft_last_data_segment + 1;544544- TRACE_EXIT 0;545545-}546546-547547-/* perform mtfsf, mtbsf, not allowed without zft_qic_mode548548- */549549-int zft_skip_volumes(int count, zft_position *pos)550550-{ 551551- const zft_volinfo *vtbl;552552- TRACE_FUN(ft_t_flow);553553-554554- TRACE(ft_t_noise, "count: %d", count);555555-556556- vtbl= zft_find_volume(pos->seg_pos);557557- while (count > 0 && vtbl != zft_eom_vtbl) {558558- vtbl = list_entry(vtbl->node.next, zft_volinfo, node);559559- count --;560560- }561561- while (count < 0 && vtbl != zft_first_vtbl) {562562- vtbl = list_entry(vtbl->node.prev, zft_volinfo, node);563563- count ++;564564- }565565- pos->seg_pos = vtbl->start_seg;566566- pos->seg_byte_pos = 0;567567- pos->volume_pos = 0;568568- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);569569- zft_just_before_eof = vtbl->size == 0;570570- if (zft_cmpr_ops) {571571- (*zft_cmpr_ops->reset)();572572- }573573- zft_deblock_segment = -1; /* no need to keep cache */574574- TRACE(ft_t_noise, "repositioning to:\n"575575- KERN_INFO "zft_seg_pos : %d\n"576576- KERN_INFO "zft_seg_byte_pos : %d\n"577577- KERN_INFO "zft_tape_pos : " LL_X "\n"578578- KERN_INFO "zft_volume_pos : " LL_X "\n"579579- KERN_INFO "file number : %d",580580- pos->seg_pos, pos->seg_byte_pos, 581581- LL(pos->tape_pos), LL(pos->volume_pos), vtbl->count);582582- zft_resid = count < 0 ? -count : count;583583- TRACE_EXIT zft_resid ? -EINVAL : 0;584584-}585585-586586-/* the following simply returns the raw data position of the EOM587587- * marker, MTIOCSIZE ioctl 588588- */589589-__s64 zft_get_eom_pos(void)590590-{591591- if (zft_qic_mode) {592592- return zft_calc_tape_pos(zft_eom_vtbl->start_seg);593593- } else {594594- /* there is only one volume in raw mode */595595- return zft_capacity;596596- }597597-}598598-599599-/* skip to eom, used for MTEOM600600- */601601-void zft_skip_to_eom(zft_position *pos)602602-{603603- TRACE_FUN(ft_t_flow);604604- pos->seg_pos = zft_eom_vtbl->start_seg;605605- pos->seg_byte_pos = 606606- pos->volume_pos = 607607- zft_just_before_eof = 0;608608- pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);609609- TRACE(ft_t_noise, "ftape positioned to segment %d, data pos " LL_X, 610610- pos->seg_pos, LL(pos->tape_pos));611611- TRACE_EXIT;612612-}613613-614614-/* write an EOF-marker by setting zft_last_vtbl->end_seg to seg_pos.615615- * NOTE: this function assumes that zft_last_vtbl points to a valid616616- * vtbl entry617617- *618618- * NOTE: this routine always positions before the EOF marker619619- */620620-int zft_close_volume(zft_position *pos)621621-{622622- TRACE_FUN(ft_t_any);623623-624624- if (zft_vtbl_empty || !zft_last_vtbl->open) { /* should not happen */625625- TRACE(ft_t_noise, "There are no volumes to finish");626626- TRACE_EXIT -EIO;627627- }628628- if (pos->seg_byte_pos == 0 && 629629- pos->seg_pos != zft_last_vtbl->start_seg) {630630- pos->seg_pos --;631631- pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);632632- }633633- zft_last_vtbl->end_seg = pos->seg_pos;634634- zft_last_vtbl->size = pos->volume_pos;635635- zft_volume_table_changed = 1;636636- zft_just_before_eof = 1;637637- zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;638638- zft_last_vtbl->open = 0; /* closed */639639- TRACE_EXIT 0;640640-}641641-642642-/* write count file-marks at current position. 643643- *644644- * The tape is positioned after the eof-marker, that is at byte 0 of645645- * the segment following the eof-marker646646- *647647- * this function is only allowed in zft_qic_mode648648- *649649- * Only allowed when tape is at BOT or EOD.650650- */651651-int zft_weof(unsigned int count, zft_position *pos)652652-{653653-654654- TRACE_FUN(ft_t_flow);655655-656656- if (!count) { /* write zero EOF marks should be a real no-op */657657- TRACE_EXIT 0;658658- }659659- zft_volume_table_changed = 1;660660- if (zft_tape_at_lbot(pos)) {661661- zft_init_vtbl();662662- if(zft_old_ftape) {663663- /* clear old ftape's eof marks */664664- zft_clear_ftape_file_marks();665665- zft_old_ftape = 0; /* no longer old ftape */666666- }667667- }668668- if (zft_last_vtbl->open) {669669- zft_close_volume(pos);670670- zft_move_past_eof(pos);671671- count --;672672- }673673- /* now it's easy, just append eof-marks, that is empty674674- * volumes, to the end of the already recorded media.675675- */676676- while (count > 0 && 677677- pos->seg_pos <= ft_last_data_segment && 678678- zft_eom_vtbl->count < ZFT_MAX_VOLUMES) {679679- TRACE(ft_t_noise,680680- "Writing zero sized file at segment %d", pos->seg_pos);681681- zft_new_vtbl_entry();682682- zft_last_vtbl->start_seg = pos->seg_pos;683683- zft_last_vtbl->end_seg = pos->seg_pos;684684- zft_last_vtbl->size = 0;685685- zft_last_vtbl->blk_sz = zft_blk_sz;686686- zft_last_vtbl->zft_volume = 1;687687- zft_last_vtbl->use_compression = 0;688688- pos->tape_pos += zft_get_seg_sz(pos->seg_pos);689689- zft_eom_vtbl->start_seg = ++ pos->seg_pos;690690- count --;691691- } 692692- if (count > 0) {693693- /* there are two possibilities: end of tape, or the694694- * maximum number of files is exhausted.695695- */696696- zft_resid = count;697697- TRACE(ft_t_noise,"Number of marks NOT written: %d", zft_resid);698698- if (zft_eom_vtbl->count == ZFT_MAX_VOLUMES) {699699- TRACE_ABORT(-EINVAL, ft_t_warn,700700- "maximum allowed number of files "701701- "exhausted: %d", ZFT_MAX_VOLUMES);702702- } else {703703- TRACE_ABORT(-ENOSPC,704704- ft_t_noise, "reached end of tape");705705- }706706- }707707- TRACE_EXIT 0;708708-}709709-710710-const zft_volinfo *zft_find_volume(unsigned int seg_pos)711711-{712712- TRACE_FUN(ft_t_flow);713713-714714- TRACE(ft_t_any, "called with seg_pos %d",seg_pos);715715- if (!zft_qic_mode) {716716- if (seg_pos > ft_last_data_segment) {717717- TRACE_EXIT &eot_vtbl;718718- }719719- tape_vtbl.blk_sz = zft_blk_sz;720720- TRACE_EXIT &tape_vtbl;721721- }722722- if (seg_pos < zft_first_vtbl->start_seg) {723723- TRACE_EXIT (cur_vtbl = zft_first_vtbl);724724- }725725- while (seg_pos > cur_vtbl->end_seg) {726726- cur_vtbl = list_entry(cur_vtbl->node.next, zft_volinfo, node);727727- TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);728728- }729729- while (seg_pos < cur_vtbl->start_seg) {730730- cur_vtbl = list_entry(cur_vtbl->node.prev, zft_volinfo, node);731731- TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);732732- }733733- if (seg_pos > cur_vtbl->end_seg || seg_pos < cur_vtbl->start_seg) {734734- TRACE(ft_t_bug, "This cannot happen");735735- }736736- DUMP_VOLINFO(ft_t_noise, "", cur_vtbl);737737- TRACE_EXIT cur_vtbl;738738-}739739-740740-/* this function really assumes that we are just before eof741741- */742742-void zft_move_past_eof(zft_position *pos)743743-{ 744744- TRACE_FUN(ft_t_flow);745745-746746- TRACE(ft_t_noise, "old seg. pos: %d", pos->seg_pos);747747- pos->tape_pos += zft_get_seg_sz(pos->seg_pos++) - pos->seg_byte_pos;748748- pos->seg_byte_pos = 0;749749- pos->volume_pos = 0;750750- if (zft_cmpr_ops) {751751- (*zft_cmpr_ops->reset)();752752- }753753- zft_just_before_eof = 0;754754- zft_deblock_segment = -1; /* no need to cache it anymore */755755- TRACE(ft_t_noise, "new seg. pos: %d", pos->seg_pos);756756- TRACE_EXIT;757757-}
-227
drivers/char/ftape/zftape/zftape-vtbl.h
···11-#ifndef _ZFTAPE_VTBL_H22-#define _ZFTAPE_VTBL_H33-44-/*55- * Copyright (c) 1995-1997 Claus-Justus Heine66-77- This program is free software; you can redistribute it and/or88- modify it under the terms of the GNU General Public License as99- published by the Free Software Foundation; either version 2, or (at1010- your option) any later version.1111-1212- This program is distributed in the hope that it will be useful, but1313- WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1515- General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,2020- USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.h,v $2424- * $Revision: 1.3 $2525- * $Date: 1997/10/28 14:30:09 $2626- *2727- * This file defines a volume table as defined in the QIC-802828- * development standards.2929- */3030-3131-#include <linux/list.h>3232-3333-#include "../lowlevel/ftape-tracing.h"3434-3535-#include "../zftape/zftape-eof.h"3636-#include "../zftape/zftape-ctl.h"3737-#include "../zftape/zftape-rw.h"3838-3939-#define VTBL_SIZE 128 /* bytes */4040-4141-/* The following are offsets in the vtbl. */4242-#define VTBL_SIG 04343-#define VTBL_START 44444-#define VTBL_END 64545-#define VTBL_DESC 84646-#define VTBL_DATE 524747-#define VTBL_FLAGS 564848-#define VTBL_FL_VENDOR_SPECIFIC (1<<0)4949-#define VTBL_FL_MUTLI_CARTRIDGE (1<<1)5050-#define VTBL_FL_NOT_VERIFIED (1<<2)5151-#define VTBL_FL_REDIR_INHIBIT (1<<3)5252-#define VTBL_FL_SEG_SPANNING (1<<4)5353-#define VTBL_FL_DIRECTORY_LAST (1<<5)5454-#define VTBL_FL_RESERVED_6 (1<<6)5555-#define VTBL_FL_RESERVED_7 (1<<7)5656-#define VTBL_M_NO 575757-#define VTBL_EXT 585858-#define EXT_ZFTAPE_SIG 05959-#define EXT_ZFTAPE_BLKSZ 106060-#define EXT_ZFTAPE_CMAP 126161-#define EXT_ZFTAPE_QIC113 136262-#define VTBL_PWD 846363-#define VTBL_DIR_SIZE 926464-#define VTBL_DATA_SIZE 966565-#define VTBL_OS_VERSION 1046666-#define VTBL_SRC_DRIVE 1066767-#define VTBL_DEV 1226868-#define VTBL_RESERVED_1 1236969-#define VTBL_CMPR 1247070-#define VTBL_CMPR_UNREG 0x3f7171-#define VTBL_CMPR_USED 0x807272-#define VTBL_FMT 1257373-#define VTBL_RESERVED_2 1267474-#define VTBL_RESERVED_3 1277575-/* compatibility with pre revision K */7676-#define VTBL_K_CMPR 120 7777-7878-/* the next is used by QIC-3020 tapes with format code 6 (>2^167979- * segments) It is specified in QIC-113, Rev. G, Section 5 (SCSI8080- * volume table). The difference is simply, that we only store the8181- * number of segments used, not the starting segment.8282- */8383-#define VTBL_SCSI_SEGS 4 /* is a 4 byte value */8484-8585-/* one vtbl is 128 bytes, that results in a maximum number of8686- * 29*1024/128 = 232 volumes.8787- */8888-#define ZFT_MAX_VOLUMES (FT_SEGMENT_SIZE/VTBL_SIZE)8989-#define VTBL_ID "VTBL"9090-#define VTBL_IDS { VTBL_ID, "XTBL", "UTID", "EXVT" } /* other valid ids */9191-#define ZFT_VOL_NAME "zftape volume" /* volume label used by me */9292-#define ZFTAPE_SIG "LINUX ZFT"9393-9494-/* global variables9595- */9696-typedef struct zft_internal_vtbl9797-{9898- struct list_head node;9999- int count;100100- unsigned int start_seg; /* 32 bits are enough for now */101101- unsigned int end_seg; /* 32 bits are enough for now */102102- __s64 size; /* uncompressed size */103103- unsigned int blk_sz; /* block size for this volume */104104- unsigned int zft_volume :1; /* zftape created this volume */105105- unsigned int use_compression:1; /* compressed volume */106106- unsigned int qic113 :1; /* layout of compressed block107107- * info and vtbl conforms to108108- * QIC-113, Rev. G 109109- */110110- unsigned int new_volume :1; /* it was created by us, this111111- * run. this allows the112112- * fields that aren't really113113- * used by zftape to be filled114114- * in by some user level115115- * program.116116- */117117- unsigned int open :1; /* just in progress of being 118118- * written119119- */120120-} zft_volinfo;121121-122122-extern struct list_head zft_vtbl;123123-#define zft_head_vtbl list_entry(zft_vtbl.next, zft_volinfo, node)124124-#define zft_eom_vtbl list_entry(zft_vtbl.prev, zft_volinfo, node)125125-#define zft_last_vtbl list_entry(zft_eom_vtbl->node.prev, zft_volinfo, node)126126-#define zft_first_vtbl list_entry(zft_head_vtbl->node.next, zft_volinfo, node)127127-#define zft_vtbl_empty (zft_eom_vtbl->node.prev == &zft_head_vtbl->node)128128-129129-#define DUMP_VOLINFO(level, desc, info) \130130-{ \131131- char tmp[21]; \132132- strlcpy(tmp, desc, sizeof(tmp)); \133133- TRACE(level, "Volume %d:\n" \134134- KERN_INFO "description : %s\n" \135135- KERN_INFO "first segment: %d\n" \136136- KERN_INFO "last segment: %d\n" \137137- KERN_INFO "size : " LL_X "\n" \138138- KERN_INFO "block size : %d\n" \139139- KERN_INFO "compression : %d\n" \140140- KERN_INFO "zftape volume: %d\n" \141141- KERN_INFO "QIC-113 conf.: %d", \142142- (info)->count, tmp, (info)->start_seg, (info)->end_seg, \143143- LL((info)->size), (info)->blk_sz, \144144- (info)->use_compression != 0, (info)->zft_volume != 0, \145145- (info)->qic113 != 0); \146146-}147147-148148-extern int zft_qic_mode;149149-extern int zft_old_ftape;150150-extern int zft_volume_table_changed;151151-152152-/* exported functions */153153-extern void zft_init_vtbl (void);154154-extern void zft_free_vtbl (void);155155-extern int zft_extract_volume_headers(__u8 *buffer);156156-extern int zft_update_volume_table (unsigned int segment);157157-extern int zft_open_volume (zft_position *pos,158158- int blk_sz, int use_compression);159159-extern int zft_close_volume (zft_position *pos);160160-extern const zft_volinfo *zft_find_volume(unsigned int seg_pos);161161-extern int zft_skip_volumes (int count, zft_position *pos);162162-extern __s64 zft_get_eom_pos (void);163163-extern void zft_skip_to_eom (zft_position *pos);164164-extern int zft_fake_volume_headers (eof_mark_union *eof_map, 165165- int num_failed_sectors);166166-extern int zft_weof (unsigned int count, zft_position *pos);167167-extern void zft_move_past_eof (zft_position *pos);168168-169169-static inline int zft_tape_at_eod (const zft_position *pos);170170-static inline int zft_tape_at_lbot (const zft_position *pos);171171-static inline void zft_position_before_eof (zft_position *pos, 172172- const zft_volinfo *volume);173173-static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,174174- const zft_position *pos);175175-176176-/* this function decrements the zft_seg_pos counter if we are right177177- * at the beginning of a segment. This is to handle fsfm/bsfm -- we178178- * need to position before the eof mark. NOTE: zft_tape_pos is not179179- * changed 180180- */181181-static inline void zft_position_before_eof(zft_position *pos, 182182- const zft_volinfo *volume)183183-{ 184184- TRACE_FUN(ft_t_flow);185185-186186- if (pos->seg_pos == volume->end_seg + 1 && pos->seg_byte_pos == 0) {187187- pos->seg_pos --;188188- pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);189189- }190190- TRACE_EXIT;191191-}192192-193193-/* Mmmh. Is the position at the end of the last volume, that is right194194- * before the last EOF mark also logical an EOD condition?195195- */196196-static inline int zft_tape_at_eod(const zft_position *pos)197197-{ 198198- TRACE_FUN(ft_t_any);199199-200200- if (zft_qic_mode) {201201- TRACE_EXIT (pos->seg_pos >= zft_eom_vtbl->start_seg ||202202- zft_last_vtbl->open);203203- } else {204204- TRACE_EXIT pos->seg_pos > ft_last_data_segment;205205- }206206-}207207-208208-static inline int zft_tape_at_lbot(const zft_position *pos)209209-{210210- if (zft_qic_mode) {211211- return (pos->seg_pos <= zft_first_vtbl->start_seg &&212212- pos->volume_pos == 0);213213- } else {214214- return (pos->seg_pos <= ft_first_data_segment && 215215- pos->volume_pos == 0);216216- }217217-}218218-219219-/* This one checks for EOF. return remaing space (may be negative) 220220- */221221-static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,222222- const zft_position *pos)223223-{ 224224- return (__s64)(vtbl->size - pos->volume_pos);225225-}226226-227227-#endif /* _ZFTAPE_VTBL_H */
-483
drivers/char/ftape/zftape/zftape-write.c
···11-/*22- * Copyright (C) 1996, 1997 Claus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.c,v $2020- * $Revision: 1.3 $2121- * $Date: 1997/11/06 00:50:29 $2222- *2323- * This file contains the writing code2424- * for the QIC-117 floppy-tape driver for Linux.2525- */2626-2727-#include <linux/errno.h>2828-#include <linux/mm.h>2929-3030-#include <linux/zftape.h>3131-3232-#include <asm/uaccess.h>3333-3434-#include "../zftape/zftape-init.h"3535-#include "../zftape/zftape-eof.h"3636-#include "../zftape/zftape-ctl.h"3737-#include "../zftape/zftape-write.h"3838-#include "../zftape/zftape-read.h"3939-#include "../zftape/zftape-rw.h"4040-#include "../zftape/zftape-vtbl.h"4141-4242-/* Global vars.4343- */4444-4545-/* Local vars.4646- */4747-static int last_write_failed;4848-static int need_flush;4949-5050-void zft_prevent_flush(void)5151-{5252- need_flush = 0;5353-}5454-5555-static int zft_write_header_segments(__u8* buffer)5656-{5757- int header_1_ok = 0;5858- int header_2_ok = 0;5959- unsigned int time_stamp;6060- TRACE_FUN(ft_t_noise);6161-6262- TRACE_CATCH(ftape_abort_operation(),);6363- ftape_seek_to_bot(); /* prevents extra rewind */6464- if (GET4(buffer, 0) != FT_HSEG_MAGIC) {6565- TRACE_ABORT(-EIO, ft_t_err,6666- "wrong header signature found, aborting");6767- } 6868- /* Be optimistic: */6969- PUT4(buffer, FT_SEG_CNT,7070- zft_written_segments + GET4(buffer, FT_SEG_CNT) + 2);7171- if ((time_stamp = zft_get_time()) != 0) {7272- PUT4(buffer, FT_WR_DATE, time_stamp);7373- if (zft_label_changed) {7474- PUT4(buffer, FT_LABEL_DATE, time_stamp);7575- }7676- }7777- TRACE(ft_t_noise,7878- "writing first header segment %d", ft_header_segment_1);7979- header_1_ok = zft_verify_write_segments(ft_header_segment_1, 8080- buffer, FT_SEGMENT_SIZE,8181- zft_deblock_buf) >= 0;8282- TRACE(ft_t_noise,8383- "writing second header segment %d", ft_header_segment_2);8484- header_2_ok = zft_verify_write_segments(ft_header_segment_2, 8585- buffer, FT_SEGMENT_SIZE,8686- zft_deblock_buf) >= 0;8787- if (!header_1_ok) {8888- TRACE(ft_t_warn, "Warning: "8989- "update of first header segment failed");9090- }9191- if (!header_2_ok) {9292- TRACE(ft_t_warn, "Warning: "9393- "update of second header segment failed");9494- }9595- if (!header_1_ok && !header_2_ok) {9696- TRACE_ABORT(-EIO, ft_t_err, "Error: "9797- "update of both header segments failed.");9898- }9999- TRACE_EXIT 0;100100-}101101-102102-int zft_update_header_segments(void)103103-{104104- TRACE_FUN(ft_t_noise);105105-106106- /* must NOT use zft_write_protected, as it also includes the107107- * file access mode. But we also want to update when soft108108- * write protection is enabled (O_RDONLY)109109- */110110- if (ft_write_protected || zft_old_ftape) {111111- TRACE_ABORT(0, ft_t_noise, "Tape set read-only: no update");112112- } 113113- if (!zft_header_read) {114114- TRACE_ABORT(0, ft_t_noise, "Nothing to update");115115- }116116- if (!zft_header_changed) {117117- zft_header_changed = zft_written_segments > 0;118118- }119119- if (!zft_header_changed && !zft_volume_table_changed) {120120- TRACE_ABORT(0, ft_t_noise, "Nothing to update");121121- }122122- TRACE(ft_t_noise, "Updating header segments");123123- if (ftape_get_status()->fti_state == writing) {124124- TRACE_CATCH(ftape_loop_until_writes_done(),);125125- }126126- TRACE_CATCH(ftape_abort_operation(),);127127-128128- zft_deblock_segment = -1; /* invalidate the cache */129129- if (zft_header_changed) {130130- TRACE_CATCH(zft_write_header_segments(zft_hseg_buf),);131131- }132132- if (zft_volume_table_changed) {133133- TRACE_CATCH(zft_update_volume_table(ft_first_data_segment),);134134- }135135- zft_header_changed =136136- zft_volume_table_changed = 137137- zft_label_changed =138138- zft_written_segments = 0;139139- TRACE_CATCH(ftape_abort_operation(),);140140- ftape_seek_to_bot();141141- TRACE_EXIT 0;142142-}143143-144144-static int read_merge_buffer(int seg_pos, __u8 *buffer, int offset, int seg_sz)145145-{146146- int result = 0;147147- const ft_trace_t old_tracing = TRACE_LEVEL;148148- TRACE_FUN(ft_t_flow);149149-150150- if (zft_qic_mode) {151151- /* writing in the middle of a volume is NOT allowed152152- *153153- */154154- TRACE(ft_t_noise, "No need to read a segment");155155- memset(buffer + offset, 0, seg_sz - offset);156156- TRACE_EXIT 0;157157- }158158- TRACE(ft_t_any, "waiting");159159- ftape_start_writing(FT_WR_MULTI);160160- TRACE_CATCH(ftape_loop_until_writes_done(),);161161-162162- TRACE(ft_t_noise, "trying to read segment %d from offset %d",163163- seg_pos, offset);164164- SET_TRACE_LEVEL(ft_t_bug);165165- result = zft_fetch_segment_fraction(seg_pos, buffer, 166166- FT_RD_SINGLE,167167- offset, seg_sz - offset);168168- SET_TRACE_LEVEL(old_tracing);169169- if (result != (seg_sz - offset)) {170170- TRACE(ft_t_noise, "Ignore error: read_segment() result: %d",171171- result);172172- memset(buffer + offset, 0, seg_sz - offset);173173- }174174- TRACE_EXIT 0;175175-}176176-177177-/* flush the write buffer to tape and write an eof-marker at the178178- * current position if not in raw mode. This function always179179- * positions the tape before the eof-marker. _ftape_close() should180180- * then advance to the next segment.181181- *182182- * the parameter "finish_volume" describes whether to position before183183- * or after the possibly created file-mark. We always position after184184- * the file-mark when called from ftape_close() and a flush was needed185185- * (that is ftape_write() was the last tape operation before calling186186- * ftape_flush) But we always position before the file-mark when this187187- * function get's called from outside ftape_close() 188188- */189189-int zft_flush_buffers(void)190190-{191191- int result;192192- int data_remaining;193193- int this_segs_size;194194- TRACE_FUN(ft_t_flow);195195-196196- TRACE(ft_t_data_flow,197197- "entered, ftape_state = %d", ftape_get_status()->fti_state);198198- if (ftape_get_status()->fti_state != writing && !need_flush) {199199- TRACE_ABORT(0, ft_t_noise, "no need for flush");200200- }201201- zft_io_state = zft_idle; /* triggers some initializations for the202202- * read and write routines 203203- */204204- if (last_write_failed) {205205- ftape_abort_operation();206206- TRACE_EXIT -EIO;207207- }208208- TRACE(ft_t_noise, "flushing write buffers");209209- this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);210210- if (this_segs_size == zft_pos.seg_byte_pos) {211211- zft_pos.seg_pos ++;212212- data_remaining = zft_pos.seg_byte_pos = 0;213213- } else {214214- data_remaining = zft_pos.seg_byte_pos;215215- }216216- /* If there is any data not written to tape yet, append zero's217217- * up to the end of the sector (if using compression) or merge218218- * it with the data existing on the tape Then write the219219- * segment(s) to tape.220220- */221221- TRACE(ft_t_noise, "Position:\n"222222- KERN_INFO "seg_pos : %d\n"223223- KERN_INFO "byte pos : %d\n"224224- KERN_INFO "remaining: %d",225225- zft_pos.seg_pos, zft_pos.seg_byte_pos, data_remaining);226226- if (data_remaining > 0) {227227- do {228228- this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);229229- if (this_segs_size > data_remaining) {230230- TRACE_CATCH(read_merge_buffer(zft_pos.seg_pos,231231- zft_deblock_buf,232232- data_remaining,233233- this_segs_size),234234- last_write_failed = 1);235235- }236236- result = ftape_write_segment(zft_pos.seg_pos, 237237- zft_deblock_buf,238238- FT_WR_MULTI);239239- if (result != this_segs_size) {240240- TRACE(ft_t_err, "flush buffers failed");241241- zft_pos.tape_pos -= zft_pos.seg_byte_pos;242242- zft_pos.seg_byte_pos = 0;243243-244244- last_write_failed = 1;245245- TRACE_EXIT result;246246- }247247- zft_written_segments ++;248248- TRACE(ft_t_data_flow,249249- "flush, moved out buffer: %d", result);250250- /* need next segment for more data (empty segments?)251251- */252252- if (result < data_remaining) { 253253- if (result > 0) { 254254- /* move remainder to buffer beginning 255255- */256256- memmove(zft_deblock_buf, 257257- zft_deblock_buf + result,258258- FT_SEGMENT_SIZE - result);259259- }260260- } 261261- data_remaining -= result;262262- zft_pos.seg_pos ++;263263- } while (data_remaining > 0);264264- TRACE(ft_t_any, "result: %d", result);265265- zft_deblock_segment = --zft_pos.seg_pos;266266- if (data_remaining == 0) { /* first byte next segment */267267- zft_pos.seg_byte_pos = this_segs_size;268268- } else { /* after data previous segment, data_remaining < 0 */269269- zft_pos.seg_byte_pos = data_remaining + result;270270- }271271- } else {272272- TRACE(ft_t_noise, "zft_deblock_buf empty");273273- zft_pos.seg_pos --;274274- zft_pos.seg_byte_pos = zft_get_seg_sz (zft_pos.seg_pos);275275- ftape_start_writing(FT_WR_MULTI);276276- }277277- TRACE(ft_t_any, "waiting");278278- if ((result = ftape_loop_until_writes_done()) < 0) {279279- /* that's really bad. What to to with zft_tape_pos? 280280- */281281- TRACE(ft_t_err, "flush buffers failed");282282- }283283- TRACE(ft_t_any, "zft_seg_pos: %d, zft_seg_byte_pos: %d",284284- zft_pos.seg_pos, zft_pos.seg_byte_pos);285285- last_write_failed =286286- need_flush = 0;287287- TRACE_EXIT result;288288-}289289-290290-/* return-value: the number of bytes removed from the user-buffer291291- *292292- * out: 293293- * int *write_cnt: how much actually has been moved to the294294- * zft_deblock_buf295295- * int req_len : MUST NOT BE CHANGED, except at EOT, in 296296- * which case it may be adjusted297297- * in : 298298- * char *buff : the user buffer299299- * int buf_pos_write : copy of buf_len_wr int300300- * this_segs_size : the size in bytes of the actual segment301301- * char302302- * *zft_deblock_buf : zft_deblock_buf303303- */304304-static int zft_simple_write(int *cnt,305305- __u8 *dst_buf, const int seg_sz,306306- const __u8 __user *src_buf, const int req_len, 307307- const zft_position *pos,const zft_volinfo *volume)308308-{309309- int space_left;310310- TRACE_FUN(ft_t_flow);311311-312312- /* volume->size holds the tape capacity while volume is open */313313- if (pos->tape_pos + volume->blk_sz > volume->size) {314314- TRACE_EXIT -ENOSPC;315315- }316316- /* remaining space in this segment, NOT zft_deblock_buf317317- */318318- space_left = seg_sz - pos->seg_byte_pos;319319- *cnt = req_len < space_left ? req_len : space_left;320320- if (copy_from_user(dst_buf + pos->seg_byte_pos, src_buf, *cnt) != 0) {321321- TRACE_EXIT -EFAULT;322322- }323323- TRACE_EXIT *cnt;324324-}325325-326326-static int check_write_access(int req_len,327327- const zft_volinfo **volume,328328- zft_position *pos,329329- const unsigned int blk_sz)330330-{331331- int result;332332- TRACE_FUN(ft_t_flow);333333-334334- if ((req_len % zft_blk_sz) != 0) {335335- TRACE_ABORT(-EINVAL, ft_t_info,336336- "write-count %d must be multiple of block-size %d",337337- req_len, blk_sz);338338- }339339- if (zft_io_state == zft_writing) {340340- /* all other error conditions have been checked earlier341341- */342342- TRACE_EXIT 0;343343- }344344- zft_io_state = zft_idle;345345- TRACE_CATCH(zft_check_write_access(pos),);346346- /* If we haven't read the header segment yet, do it now.347347- * This will verify the configuration, get the bad sector348348- * table and read the volume table segment 349349- */350350- if (!zft_header_read) {351351- TRACE_CATCH(zft_read_header_segments(),);352352- }353353- /* fine. Now the tape is either at BOT or at EOD,354354- * Write start of volume now355355- */356356- TRACE_CATCH(zft_open_volume(pos, blk_sz, zft_use_compression),);357357- *volume = zft_find_volume(pos->seg_pos);358358- DUMP_VOLINFO(ft_t_noise, "", *volume);359359- zft_just_before_eof = 0;360360- /* now merge with old data if necessary */361361- if (!zft_qic_mode && pos->seg_byte_pos != 0){362362- result = zft_fetch_segment(pos->seg_pos,363363- zft_deblock_buf,364364- FT_RD_SINGLE);365365- if (result < 0) {366366- if (result == -EINTR || result == -ENOSPC) {367367- TRACE_EXIT result;368368- }369369- TRACE(ft_t_noise, 370370- "ftape_read_segment() result: %d. "371371- "This might be normal when using "372372- "a newly\nformatted tape", result);373373- memset(zft_deblock_buf, '\0', pos->seg_byte_pos);374374- }375375- }376376- zft_io_state = zft_writing;377377- TRACE_EXIT 0;378378-}379379-380380-static int fill_deblock_buf(__u8 *dst_buf, const int seg_sz,381381- zft_position *pos, const zft_volinfo *volume,382382- const char __user *usr_buf, const int req_len)383383-{384384- int cnt = 0;385385- int result = 0;386386- TRACE_FUN(ft_t_flow);387387-388388- if (seg_sz == 0) {389389- TRACE_ABORT(0, ft_t_data_flow, "empty segment");390390- }391391- TRACE(ft_t_data_flow, "\n"392392- KERN_INFO "remaining req_len: %d\n"393393- KERN_INFO " buf_pos: %d", 394394- req_len, pos->seg_byte_pos);395395- /* zft_deblock_buf will not contain a valid segment any longer */396396- zft_deblock_segment = -1;397397- if (zft_use_compression) {398398- TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);399399- TRACE_CATCH(result= (*zft_cmpr_ops->write)(&cnt,400400- dst_buf, seg_sz,401401- usr_buf, req_len,402402- pos, volume),);403403- } else {404404- TRACE_CATCH(result= zft_simple_write(&cnt,405405- dst_buf, seg_sz,406406- usr_buf, req_len,407407- pos, volume),);408408- }409409- pos->volume_pos += result;410410- pos->seg_byte_pos += cnt;411411- pos->tape_pos += cnt;412412- TRACE(ft_t_data_flow, "\n"413413- KERN_INFO "removed from user-buffer : %d bytes.\n"414414- KERN_INFO "copied to zft_deblock_buf: %d bytes.\n"415415- KERN_INFO "zft_tape_pos : " LL_X " bytes.",416416- result, cnt, LL(pos->tape_pos));417417- TRACE_EXIT result;418418-}419419-420420-421421-/* called by the kernel-interface routine "zft_write()"422422- */423423-int _zft_write(const char __user *buff, int req_len)424424-{425425- int result = 0;426426- int written = 0;427427- int write_cnt;428428- int seg_sz;429429- static const zft_volinfo *volume = NULL;430430- TRACE_FUN(ft_t_flow);431431-432432- zft_resid = req_len; 433433- last_write_failed = 1; /* reset to 0 when successful */434434- /* check if write is allowed 435435- */436436- TRACE_CATCH(check_write_access(req_len, &volume,&zft_pos,zft_blk_sz),);437437- while (req_len > 0) {438438- /* Allow us to escape from this loop with a signal !439439- */440440- FT_SIGNAL_EXIT(_DONT_BLOCK);441441- seg_sz = zft_get_seg_sz(zft_pos.seg_pos);442442- if ((write_cnt = fill_deblock_buf(zft_deblock_buf,443443- seg_sz,444444- &zft_pos,445445- volume,446446- buff,447447- req_len)) < 0) {448448- zft_resid -= written;449449- if (write_cnt == -ENOSPC) {450450- /* leave the remainder to flush_buffers()451451- */452452- TRACE(ft_t_info, "No space left on device");453453- last_write_failed = 0;454454- if (!need_flush) {455455- need_flush = written > 0;456456- }457457- TRACE_EXIT written > 0 ? written : -ENOSPC;458458- } else {459459- TRACE_EXIT result;460460- }461461- }462462- if (zft_pos.seg_byte_pos == seg_sz) {463463- TRACE_CATCH(ftape_write_segment(zft_pos.seg_pos, 464464- zft_deblock_buf,465465- FT_WR_ASYNC),466466- zft_resid -= written);467467- zft_written_segments ++;468468- zft_pos.seg_byte_pos = 0;469469- zft_deblock_segment = zft_pos.seg_pos;470470- ++zft_pos.seg_pos;471471- }472472- written += write_cnt;473473- buff += write_cnt;474474- req_len -= write_cnt;475475- } /* while (req_len > 0) */476476- TRACE(ft_t_data_flow, "remaining in blocking buffer: %d",477477- zft_pos.seg_byte_pos);478478- TRACE(ft_t_data_flow, "just written bytes: %d", written);479479- last_write_failed = 0;480480- zft_resid -= written;481481- need_flush = need_flush || written > 0;482482- TRACE_EXIT written; /* bytes written */483483-}
-38
drivers/char/ftape/zftape/zftape-write.h
···11-#ifndef _ZFTAPE_WRITE_H22-#define _ZFTAPE_WRITE_H33-44-/*55- * Copyright (C) 1996, 1997 Claus-Justus Heine66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:19:13 $2525- *2626- * This file contains the definitions for the write functions2727- * for the zftape driver for Linux.2828- *2929- */3030-3131-extern int zft_flush_buffers(void);3232-extern int zft_update_header_segments(void);3333-extern void zft_prevent_flush(void);3434-3535-/* hook for the VFS interface 3636- */3737-extern int _zft_write(const char __user *buff, int req_len);3838-#endif /* _ZFTAPE_WRITE_H */
-43
drivers/char/ftape/zftape/zftape_syms.c
···11-/*22- * Copyright (C) 1997 Claus-Justus Heine33-44- This program is free software; you can redistribute it and/or modify55- it under the terms of the GNU General Public License as published by66- the Free Software Foundation; either version 2, or (at your option)77- any later version.88-99- This program is distributed in the hope that it will be useful,1010- but WITHOUT ANY WARRANTY; without even the implied warranty of1111- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- GNU General Public License for more details.1313-1414- You should have received a copy of the GNU General Public License1515- along with this program; see the file COPYING. If not, write to1616- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.1717-1818- *1919- * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape_syms.c,v $2020- * $Revision: 1.3 $2121- * $Date: 1997/10/05 19:19:14 $2222- *2323- * This file contains the symbols that the zftape frontend to 2424- * the ftape floppy tape driver exports 2525- */ 2626-2727-#include <linux/module.h>2828-2929-#include <linux/zftape.h>3030-3131-#include "../zftape/zftape-init.h"3232-#include "../zftape/zftape-read.h"3333-#include "../zftape/zftape-buffers.h"3434-#include "../zftape/zftape-ctl.h"3535-3636-/* zftape-init.c */3737-EXPORT_SYMBOL(zft_cmpr_register);3838-/* zftape-read.c */3939-EXPORT_SYMBOL(zft_fetch_segment_fraction);4040-/* zftape-buffers.c */4141-EXPORT_SYMBOL(zft_vmalloc_once);4242-EXPORT_SYMBOL(zft_vmalloc_always);4343-EXPORT_SYMBOL(zft_vfree);
···11-#ifndef _FTAPE_HEADER_SEGMENT_H22-#define _FTAPE_HEADER_SEGMENT_H33-44-/*55- * Copyright (C) 1996-1997 Claus-Justus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-header-segment.h,v $2323- * $Revision: 1.2 $2424- * $Date: 1997/10/05 19:19:28 $2525- *2626- * This file defines some offsets into the header segment of a2727- * floppy tape cartridge. For use with the QIC-40/80/3010/30202828- * floppy-tape driver "ftape" for Linux.2929- */3030-3131-#define FT_SIGNATURE 0 /* must be 0xaa55aa55 */3232-#define FT_FMT_CODE 43333-#define FT_REV_LEVEL 5 /* only for QIC-80 since. Rev. L (== 0x0c) */3434-#define FT_HSEG_1 6 /* first header segment, except for format code 6 */3535-#define FT_HSEG_2 8 /* second header segment, except for format code 6 */3636-#define FT_FRST_SEG 10 /* first data segment, except for format code 6 */3737-#define FT_LAST_SEG 12 /* last data segment, except for format code 6 */3838-#define FT_FMT_DATE 14 /* date and time of most recent format, see below */3939-#define FT_WR_DATE 18 /* date and time of most recent write or format */4040-#define FT_SPT 24 /* segments per track */4141-#define FT_TPC 26 /* tracks per cartridge */4242-#define FT_FHM 27 /* floppy drive head (maximum of it) */4343-#define FT_FTM 28 /* floppy track max. */4444-#define FT_FSM 29 /* floppy sector max. (128) */4545-#define FT_LABEL 30 /* floppy tape label */4646-#define FT_LABEL_DATE 74 /* date and time the tape label was written */4747-#define FT_LABEL_SZ (FT_LABEL_DATE - FT_LABEL)4848-#define FT_CMAP_START 78 /* starting segment of compression map */4949-#define FT_FMT_ERROR 128 /* must be set to 0xff if remainder gets lost during5050- * tape format5151- */5252-#define FT_SEG_CNT 130 /* number of seg. written, formatted or verified5353- * through lifetime of tape (why not read?)5454- */5555-#define FT_INIT_DATE 138 /* date and time of initial tape format */5656-#define FT_FMT_CNT 142 /* number of times tape has been formatted */5757-#define FT_FSL_CNT 144 /* number of segments in failed sector log */5858-#define FT_MK_CODE 146 /* id string of tape manufacturer */5959-#define FT_LOT_CODE 190 /* tape manufacturer lot code */6060-#define FT_6_HSEG_1 234 /* first header segment for format code 6 */6161-#define FT_6_HSEG_2 238 /* second header segment for format code 6 */6262-#define FT_6_FRST_SEG 242 /* first data segment for format code 6 */6363-#define FT_6_LAST_SEG 246 /* last data segment for format code 6 */6464-6565-#define FT_FSL 2566666-#define FT_HEADER_END 256 /* space beyond this point:6767- * format codes 2, 3 and 5: 6868- * - failed sector log until byte 20476969- * - bad sector map in the reamining part of segment7070- * format codes 4 and 6:7171- * - bad sector map starts hear7272- */7373-7474-7575-/* value to be stored at the FT_SIGNATURE offset 7676- */7777-#define FT_HSEG_MAGIC 0xaa55aa557878-#define FT_D2G_MAGIC 0x82288228 /* Ditto 2GB */7979-8080-/* data and time encoding: */8181-#define FT_YEAR_SHIFT 258282-#define FT_YEAR_MASK 0xfe0000008383-#define FT_YEAR_0 19708484-#define FT_YEAR_MAX 1278585-#define FT_YEAR(year) ((((year)-FT_YEAR_0)<<FT_YEAR_SHIFT)&FT_YEAR_MASK)8686-8787-#define FT_TIME_SHIFT 08888-#define FT_TIME_MASK 0x01FFFFFF8989-#define FT_TIME_MAX 0x01ea6dff /* last second of a year */9090-#define FT_TIME(mo,d,h,m,s) \9191- ((((s)+60*((m)+60*((h)+24*((d)+31*(mo))))) & FT_TIME_MASK))9292-9393-#define FT_TIME_STAMP(y,mo,d,h,m,s) (FT_YEAR(y) | FT_TIME(mo,d,h,m,s))9494-9595-/* values for the format code field */9696-typedef enum {9797- fmt_normal = 2, /* QIC-80 post Rev. B 205Ft or 307Ft tape */9898- fmt_1100ft = 3, /* QIC-80 post Rev. B 1100Ft tape */9999- fmt_var = 4, /* QIC-80 post Rev. B variabel length format */100100- fmt_425ft = 5, /* QIC-80 post Rev. B 425Ft tape */101101- fmt_big = 6 /* QIC-3010/3020 variable length tape with more 102102- * than 2^16 segments per tape103103- */104104-} ft_format_type;105105-106106-/* definitions for the failed sector log */107107-#define FT_FSL_SIZE (2 * FT_SECTOR_SIZE - FT_HEADER_END)108108-#define FT_FSL_MAX_ENTRIES (FT_FSL_SIZE/sizeof(__u32))109109-110110-typedef struct ft_fsl_entry {111111- __u16 segment;112112- __u16 date;113113-} __attribute__ ((packed)) ft_fsl_entry;114114-115115-116116-/* date encoding for the failed sector log 117117- * month: 1..12, day: 1..31, year: 1970..2097118118- */119119-#define FT_FSL_TIME_STAMP(y,m,d) \120120- (((((y) - FT_YEAR_0)<<9)&0xfe00) | (((m)<<5)&0x01e0) | ((d)&0x001f))121121-122122-#endif /* _FTAPE_HEADER_SEGMENT_H */
-137
include/linux/ftape-vendors.h
···11-#ifndef _FTAPE_VENDORS_H22-#define _FTAPE_VENDORS_H33-44-/*55- * Copyright (C) 1993-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-vendors.h,v $2424- * $Revision: 1.6 $2525- * $Date: 1997/10/09 15:38:11 $2626- *2727- * This file contains the supported drive types with their2828- * QIC-117 spec. vendor code and drive dependent configuration2929- * information.3030- */3131-3232-typedef enum {3333- unknown_wake_up = 0,3434- no_wake_up,3535- wake_up_colorado,3636- wake_up_mountain,3737- wake_up_insight,3838-} wake_up_types;3939-4040-typedef struct {4141- wake_up_types wake_up; /* see wake_up_types */4242- char *name; /* Text describing the drive */4343-} wakeup_method;4444-4545-/* Note: order of entries in WAKEUP_METHODS must be so that a variable4646- * of type wake_up_types can be used as an index in the array.4747- */4848-#define WAKEUP_METHODS { \4949- { unknown_wake_up, "Unknown" }, \5050- { no_wake_up, "None" }, \5151- { wake_up_colorado, "Colorado" }, \5252- { wake_up_mountain, "Mountain" }, \5353- { wake_up_insight, "Motor-on" }, \5454-}5555-5656-typedef struct {5757- unsigned int vendor_id; /* vendor id from drive */5858- int speed; /* maximum tape transport speed (ips) */5959- wake_up_types wake_up; /* see wake_up_types */6060- char *name; /* Text describing the drive */6161-} vendor_struct;6262-6363-#define UNKNOWN_VENDOR (-1)6464-6565-#define QIC117_VENDORS { \6666-/* see _vendor_struct */ \6767- { 0x00000, 82, wake_up_colorado, "Colorado DJ-10 (old)" }, \6868- { 0x00047, 90, wake_up_colorado, "Colorado DJ-10/DJ-20" }, \6969- { 0x011c2, 84, wake_up_colorado, "Colorado 700" }, \7070- { 0x011c3, 90, wake_up_colorado, "Colorado 1400" }, \7171- { 0x011c4, 84, wake_up_colorado, "Colorado DJ-10/DJ-20 (new)" }, \7272- { 0x011c5, 84, wake_up_colorado, "HP Colorado T1000" }, \7373- { 0x011c6, 90, wake_up_colorado, "HP Colorado T3000" }, \7474- { 0x00005, 45, wake_up_mountain, "Archive 5580i" }, \7575- { 0x10005, 50, wake_up_insight, "Insight 80Mb, Irwin 80SX" }, \7676- { 0x00140, 74, wake_up_mountain, "Archive S.Hornet [Identity/Escom]" }, \7777- { 0x00146, 72, wake_up_mountain, "Archive 31250Q [Escom]" }, \7878- { 0x0014a, 100, wake_up_mountain, "Archive XL9250i [Conner/Escom]" }, \7979- { 0x0014c, 98, wake_up_mountain, "Conner C250MQT" }, \8080- { 0x0014e, 80, wake_up_mountain, "Conner C250MQ" }, \8181- { 0x00150, 80, wake_up_mountain, "Conner TSM420R/TST800R" }, \8282- { 0x00152, 80, wake_up_mountain, "Conner TSM850R" }, \8383- { 0x00156, 80, wake_up_mountain, "Conner TSM850R/1700R/TST3200R" }, \8484- { 0x00180, 0, wake_up_mountain, "Summit SE 150" }, \8585- { 0x00181, 85, wake_up_mountain, "Summit SE 250, Mountain FS8000" }, \8686- { 0x001c1, 82, no_wake_up, "Wangtek 3040F" }, \8787- { 0x001c8, 64, no_wake_up, "Wangtek 3080F" }, \8888- { 0x001c8, 64, wake_up_colorado, "Wangtek 3080F" }, \8989- { 0x001ca, 67, no_wake_up, "Wangtek 3080F (new)" }, \9090- { 0x001cc, 77, wake_up_colorado, "Wangtek 3200 / Teac 700" }, \9191- { 0x001cd, 75, wake_up_colorado, "Reveal TB1400" }, \9292- { 0x00380, 85, wake_up_colorado, "Exabyte Eagle-96" }, \9393- { 0x00381, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \9494- { 0x00382, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \9595- { 0x003ce, 77, wake_up_colorado, "Teac 800" }, \9696- { 0x003cf, 0, wake_up_colorado, "Teac FT3010TR" }, \9797- { 0x08880, 64, no_wake_up, "Iomega 250, Ditto 800" }, \9898- { 0x08880, 64, wake_up_colorado, "Iomega 250, Ditto 800" }, \9999- { 0x08880, 64, wake_up_insight, "Iomega 250, Ditto 800" }, \100100- { 0x08881, 80, wake_up_colorado, "Iomega 700" }, \101101- { 0x08882, 80, wake_up_colorado, "Iomega 3200" }, \102102- { 0x08883, 80, wake_up_colorado, "Iomega DITTO 2GB" }, \103103- { 0x00021, 70, no_wake_up, "AIWA CT-803" }, \104104- { 0x004c0, 80, no_wake_up, "AIWA TD-S1600" }, \105105- { 0x00021, 0, wake_up_mountain, "COREtape QIC80" }, \106106- { 0x00441, 0, wake_up_mountain, "ComByte DoublePlay" }, \107107- { 0x00481, 127, wake_up_mountain, "PERTEC MyTape 800" }, \108108- { 0x00483, 130, wake_up_mountain, "PERTEC MyTape 3200" }, \109109- { UNKNOWN_VENDOR, 0, no_wake_up, "unknown" } \110110-}111111-112112-#define QIC117_MAKE_CODES { \113113- { 0, "Unassigned" }, \114114- { 1, "Alloy Computer Products" }, \115115- { 2, "3M" }, \116116- { 3, "Tandberg Data" }, \117117- { 4, "Colorado" }, \118118- { 5, "Archive/Conner" }, \119119- { 6, "Mountain/Summit Memory Systems" }, \120120- { 7, "Wangtek/Rexon/Tecmar" }, \121121- { 8, "Sony" }, \122122- { 9, "Cipher Data Products" }, \123123- { 10, "Irwin Magnetic Systems" }, \124124- { 11, "Braemar" }, \125125- { 12, "Verbatim" }, \126126- { 13, "Core International" }, \127127- { 14, "Exabyte" }, \128128- { 15, "Teac" }, \129129- { 16, "Gigatek" }, \130130- { 17, "ComByte" }, \131131- { 18, "PERTEC Memories" }, \132132- { 19, "Aiwa" }, \133133- { 71, "Colorado" }, \134134- { 546, "Iomega Inc" }, \135135-}136136-137137-#endif /* _FTAPE_VENDORS_H */
-201
include/linux/ftape.h
···11-#ifndef _FTAPE_H22-#define _FTAPE_H33-44-/*55- * Copyright (C) 1994-1996 Bas Laarhoven,66- * (C) 1996-1997 Claus-Justus Heine.77-88- This program is free software; you can redistribute it and/or modify99- it under the terms of the GNU General Public License as published by1010- the Free Software Foundation; either version 2, or (at your option)1111- any later version.1212-1313- This program is distributed in the hope that it will be useful,1414- but WITHOUT ANY WARRANTY; without even the implied warranty of1515- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- GNU General Public License for more details.1717-1818- You should have received a copy of the GNU General Public License1919- along with this program; see the file COPYING. If not, write to2020- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2121-2222- *2323- * $Source: /homes/cvs/ftape-stacked/include/linux/ftape.h,v $2424- * $Revision: 1.17.6.4 $2525- * $Date: 1997/11/25 01:52:54 $2626- *2727- * This file contains global definitions, typedefs and macro's2828- * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.2929- */3030-3131-#define FTAPE_VERSION "ftape v3.04d 25/11/97"3232-3333-#ifdef __KERNEL__3434-#include <linux/interrupt.h>3535-#include <linux/mm.h>3636-#endif3737-#include <linux/types.h>3838-#include <linux/mtio.h>3939-4040-#define FT_SECTOR(x) (x+1) /* sector offset into real sector */4141-#define FT_SECTOR_SIZE 10244242-#define FT_SECTORS_PER_SEGMENT 324343-#define FT_ECC_SECTORS 34444-#define FT_SEGMENT_SIZE ((FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS) * FT_SECTOR_SIZE)4545-#define FT_BUFF_SIZE (FT_SECTORS_PER_SEGMENT * FT_SECTOR_SIZE)4646-4747-/*4848- * bits of the minor device number that define drive selection4949- * methods. Could be used one day to access multiple tape5050- * drives on the same controller.5151- */5252-#define FTAPE_SEL_A 05353-#define FTAPE_SEL_B 15454-#define FTAPE_SEL_C 25555-#define FTAPE_SEL_D 35656-#define FTAPE_SEL_MASK 35757-#define FTAPE_SEL(unit) ((unit) & FTAPE_SEL_MASK)5858-#define FTAPE_NO_REWIND 4 /* mask for minor nr */5959-6060-/* the following two may be reported when MTIOCGET is requested ... */6161-typedef union {6262- struct {6363- __u8 error;6464- __u8 command;6565- } error;6666- long space;6767-} ft_drive_error;6868-typedef union {6969- struct {7070- __u8 drive_status;7171- __u8 drive_config;7272- __u8 tape_status;7373- } status;7474- long space;7575-} ft_drive_status;7676-7777-#ifdef __KERNEL__7878-7979-#define FT_RQM_DELAY 128080-#define FT_MILLISECOND 18181-#define FT_SECOND 10008282-#define FT_FOREVER -18383-#ifndef HZ8484-#error "HZ undefined."8585-#endif8686-#define FT_USPT (1000000/HZ) /* microseconds per tick */8787-8888-/* This defines the number of retries that the driver will allow8989- * before giving up (and letting a higher level handle the error).9090- */9191-#ifdef TESTING9292-#define FT_SOFT_RETRIES 1 /* number of low level retries */9393-#define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */9494-#else9595-#define FT_SOFT_RETRIES 6 /* number of low level retries (triple) */9696-#define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */9797-#endif9898-9999-#ifndef THE_FTAPE_MAINTAINER100100-#define THE_FTAPE_MAINTAINER "the ftape maintainer"101101-#endif102102-103103-/* Initialize missing configuration parameters.104104- */105105-#ifndef CONFIG_FT_NR_BUFFERS106106-# define CONFIG_FT_NR_BUFFERS 3107107-#endif108108-#ifndef CONFIG_FT_FDC_THR109109-# define CONFIG_FT_FDC_THR 8110110-#endif111111-#ifndef CONFIG_FT_FDC_MAX_RATE112112-# define CONFIG_FT_FDC_MAX_RATE 2000113113-#endif114114-#ifndef CONFIG_FT_FDC_BASE115115-# define CONFIG_FT_FDC_BASE 0116116-#endif117117-#ifndef CONFIG_FT_FDC_IRQ118118-# define CONFIG_FT_FDC_IRQ 0119119-#endif120120-#ifndef CONFIG_FT_FDC_DMA121121-# define CONFIG_FT_FDC_DMA 0122122-#endif123123-124124-/* Turn some booleans into numbers.125125- */126126-#ifdef CONFIG_FT_PROBE_FC10127127-# undef CONFIG_FT_PROBE_FC10128128-# define CONFIG_FT_PROBE_FC10 1129129-#else130130-# define CONFIG_FT_PROBE_FC10 0131131-#endif132132-#ifdef CONFIG_FT_MACH2133133-# undef CONFIG_FT_MACH2134134-# define CONFIG_FT_MACH2 1135135-#else136136-# define CONFIG_FT_MACH2 0137137-#endif138138-139139-/* Insert default settings140140- */141141-#if CONFIG_FT_PROBE_FC10 == 1142142-# if CONFIG_FT_FDC_BASE == 0143143-# undef CONFIG_FT_FDC_BASE144144-# define CONFIG_FT_FDC_BASE 0x180145145-# endif146146-# if CONFIG_FT_FDC_IRQ == 0147147-# undef CONFIG_FT_FDC_IRQ148148-# define CONFIG_FT_FDC_IRQ 9149149-# endif150150-# if CONFIG_FT_FDC_DMA == 0151151-# undef CONFIG_FT_FDC_DMA152152-# define CONFIG_FT_FDC_DMA 3153153-# endif154154-#elif CONFIG_FT_MACH2 == 1 /* CONFIG_FT_PROBE_FC10 == 1 */155155-# if CONFIG_FT_FDC_BASE == 0156156-# undef CONFIG_FT_FDC_BASE157157-# define CONFIG_FT_FDC_BASE 0x1E0158158-# endif159159-# if CONFIG_FT_FDC_IRQ == 0160160-# undef CONFIG_FT_FDC_IRQ161161-# define CONFIG_FT_FDC_IRQ 6162162-# endif163163-# if CONFIG_FT_FDC_DMA == 0164164-# undef CONFIG_FT_FDC_DMA165165-# define CONFIG_FT_FDC_DMA 2166166-# endif167167-#elif defined(CONFIG_FT_ALT_FDC) /* CONFIG_FT_MACH2 */168168-# if CONFIG_FT_FDC_BASE == 0169169-# undef CONFIG_FT_FDC_BASE170170-# define CONFIG_FT_FDC_BASE 0x370171171-# endif172172-# if CONFIG_FT_FDC_IRQ == 0173173-# undef CONFIG_FT_FDC_IRQ174174-# define CONFIG_FT_FDC_IRQ 6175175-# endif176176-# if CONFIG_FT_FDC_DMA == 0177177-# undef CONFIG_FT_FDC_DMA178178-# define CONFIG_FT_FDC_DMA 2179179-# endif180180-#else /* CONFIG_FT_ALT_FDC */181181-# if CONFIG_FT_FDC_BASE == 0182182-# undef CONFIG_FT_FDC_BASE183183-# define CONFIG_FT_FDC_BASE 0x3f0184184-# endif185185-# if CONFIG_FT_FDC_IRQ == 0186186-# undef CONFIG_FT_FDC_IRQ187187-# define CONFIG_FT_FDC_IRQ 6188188-# endif189189-# if CONFIG_FT_FDC_DMA == 0190190-# undef CONFIG_FT_FDC_DMA191191-# define CONFIG_FT_FDC_DMA 2192192-# endif193193-#endif /* standard FDC */194194-195195-/* some useful macro's196196- */197197-#define NR_ITEMS(x) (int)(sizeof(x)/ sizeof(*x))198198-199199-#endif /* __KERNEL__ */200200-201201-#endif
-87
include/linux/zftape.h
···11-#ifndef _ZFTAPE_H22-#define _ZFTAPE_H33-44-/*55- * Copyright (C) 1996, 1997 Claus-Justus Heine.66-77- This program is free software; you can redistribute it and/or modify88- it under the terms of the GNU General Public License as published by99- the Free Software Foundation; either version 2, or (at your option)1010- any later version.1111-1212- This program is distributed in the hope that it will be useful,1313- but WITHOUT ANY WARRANTY; without even the implied warranty of1414- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515- GNU General Public License for more details.1616-1717- You should have received a copy of the GNU General Public License1818- along with this program; see the file COPYING. If not, write to1919- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.2020-2121- *2222- * $Source: /homes/cvs/ftape-stacked/include/linux/zftape.h,v $2323- * $Revision: 1.12 $2424- * $Date: 1997/10/21 11:02:37 $2525- *2626- * Special ioctl and other global info for the zftape VFS2727- * interface for the QIC-40/80/3010/3020 floppy-tape driver for2828- * Linux.2929- */3030-3131-#define ZFTAPE_VERSION "zftape for " FTAPE_VERSION3232-3333-#include <linux/ftape.h>3434-3535-#define ZFTAPE_LABEL "Ftape - The Linux Floppy Tape Project!"3636-3737-/* Bits of the minor device number that control the operation mode */3838-#define ZFT_Q80_MODE (1 << 3)3939-#define ZFT_ZIP_MODE (1 << 4)4040-#define ZFT_RAW_MODE (1 << 5)4141-#define ZFT_MINOR_OP_MASK (ZFT_Q80_MODE | \4242- ZFT_ZIP_MODE | \4343- ZFT_RAW_MODE)4444-#define ZFT_MINOR_MASK (FTAPE_SEL_MASK | \4545- ZFT_MINOR_OP_MASK | \4646- FTAPE_NO_REWIND)4747-4848-#ifdef ZFT_OBSOLETE4949-struct mtblksz {5050- unsigned int mt_blksz;5151-};5252-#define MTIOC_ZFTAPE_GETBLKSZ _IOR('m', 104, struct mtblksz)5353-#endif5454-5555-#ifdef __KERNEL__5656-5757-extern int zft_init(void);5858-5959-static inline __s64 zft_div_blksz(__s64 value, __u32 blk_sz)6060-{6161- if (blk_sz == 1) {6262- return value;6363- } else {6464- return (__s64)(((__u32)(value >> 10) + (blk_sz >> 10) - 1) 6565- / (blk_sz >> 10));6666- } 6767-}6868-6969-static inline __s64 zft_mul_blksz(__s64 value, __u32 blk_sz)7070-{7171- if (blk_sz == 1) {7272- return value;7373- } else {7474- /* if blk_sz != 1, then it is a multiple of 1024. In7575- * this case, `value' will also fit into 32 bits.7676- * 7777- * Actually, this limits the capacity to 427878- * bits. This is (2^32)*1024, roughly a thousand7979- * times 2GB, or 3 Terabytes. Hopefully this is enough8080- */8181- return(__s64)(((__u32)(value)*(blk_sz>>10))<<10);8282- }8383-}8484-8585-#endif8686-8787-#endif