diff options
301 files changed, 5435 insertions, 22261 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 02457ec9c94f..f08ca9535733 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
@@ -104,8 +104,6 @@ firmware_class/ | |||
104 | - request_firmware() hotplug interface info. | 104 | - request_firmware() hotplug interface info. |
105 | floppy.txt | 105 | floppy.txt |
106 | - notes and driver options for the floppy disk driver. | 106 | - notes and driver options for the floppy disk driver. |
107 | ftape.txt | ||
108 | - notes about the floppy tape device driver. | ||
109 | hayes-esp.txt | 107 | hayes-esp.txt |
110 | - info on using the Hayes ESP serial driver. | 108 | - info on using the Hayes ESP serial driver. |
111 | highuid.txt | 109 | highuid.txt |
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index f81819364b7a..226ecf2ffd56 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -234,14 +234,6 @@ Who: Jean Delvare <khali@linux-fr.org> | |||
234 | 234 | ||
235 | --------------------------- | 235 | --------------------------- |
236 | 236 | ||
237 | What: ftape | ||
238 | When: 2.6.20 | ||
239 | Why: Orphaned for ages. SMP bugs long unfixed. Few users left | ||
240 | in the world. | ||
241 | Who: Jeff Garzik <jeff@garzik.org> | ||
242 | |||
243 | --------------------------- | ||
244 | |||
245 | What: IPv4 only connection tracking/NAT/helpers | 237 | What: IPv4 only connection tracking/NAT/helpers |
246 | When: 2.6.22 | 238 | When: 2.6.22 |
247 | Why: The new layer 3 independant connection tracking replaces the old | 239 | Why: The new layer 3 independant connection tracking replaces the old |
diff --git a/Documentation/ftape.txt b/Documentation/ftape.txt deleted file mode 100644 index 7d8bb3384031..000000000000 --- a/Documentation/ftape.txt +++ /dev/null | |||
@@ -1,307 +0,0 @@ | |||
1 | Intro | ||
2 | ===== | ||
3 | |||
4 | This file describes some issues involved when using the "ftape" | ||
5 | floppy tape device driver that comes with the Linux kernel. | ||
6 | |||
7 | ftape has a home page at | ||
8 | |||
9 | http://ftape.dot-heine.de/ | ||
10 | |||
11 | which contains further information about ftape. Please cross check | ||
12 | this WWW address against the address given (if any) in the MAINTAINERS | ||
13 | file located in the top level directory of the Linux kernel source | ||
14 | tree. | ||
15 | |||
16 | NOTE: This is an unmaintained set of drivers, and it is not guaranteed to work. | ||
17 | If you are interested in taking over maintenance, contact Claus-Justus Heine | ||
18 | <ch@dot-heine.de>, the former maintainer. | ||
19 | |||
20 | Contents | ||
21 | ======== | ||
22 | |||
23 | A minus 1: Ftape documentation | ||
24 | |||
25 | A. Changes | ||
26 | 1. Goal | ||
27 | 2. I/O Block Size | ||
28 | 3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape) | ||
29 | 4. Formatting | ||
30 | 5. Interchanging cartridges with other operating systems | ||
31 | |||
32 | B. Debugging Output | ||
33 | 1. Introduction | ||
34 | 2. Tuning the debugging output | ||
35 | |||
36 | C. Boot and load time configuration | ||
37 | 1. Setting boot time parameters | ||
38 | 2. Module load time parameters | ||
39 | 3. Ftape boot- and load time options | ||
40 | 4. Example kernel parameter setting | ||
41 | 5. Example module parameter setting | ||
42 | |||
43 | D. Support and contacts | ||
44 | |||
45 | ******************************************************************************* | ||
46 | |||
47 | A minus 1. Ftape documentation | ||
48 | ============================== | ||
49 | |||
50 | Unluckily, the ftape-HOWTO is out of date. This really needs to be | ||
51 | changed. Up to date documentation as well as recent development | ||
52 | versions of ftape and useful links to related topics can be found at | ||
53 | the ftape home page at | ||
54 | |||
55 | http://ftape.dot-heine.de/ | ||
56 | |||
57 | ******************************************************************************* | ||
58 | |||
59 | A. Changes | ||
60 | ========== | ||
61 | |||
62 | 1. Goal | ||
63 | ~~~~ | ||
64 | The goal of all that incompatibilities was to give ftape an interface | ||
65 | that resembles the interface provided by SCSI tape drives as close | ||
66 | as possible. Thus any Unix backup program that is known to work | ||
67 | with SCSI tape drives should also work. | ||
68 | |||
69 | The concept of a fixed block size for read/write transfers is | ||
70 | rather unrelated to this SCSI tape compatibility at the file system | ||
71 | interface level. It developed out of a feature of zftape, a | ||
72 | block wise user transparent on-the-fly compression. That compression | ||
73 | support will not be dropped in future releases for compatibility | ||
74 | reasons with previous releases of zftape. | ||
75 | |||
76 | 2. I/O Block Size | ||
77 | ~~~~~~~~~~~~~~ | ||
78 | The block size defaults to 10k which is the default block size of | ||
79 | GNU tar. | ||
80 | |||
81 | The block size can be tuned either during kernel configuration or | ||
82 | at runtime with the MTIOCTOP ioctl using the MTSETBLK operation | ||
83 | (i.e. do "mt -f /dev/qft0" setblk #BLKSZ). A block size of 0 | ||
84 | switches to variable block size mode i.e. "mt setblk 0" switches | ||
85 | off the block size restriction. However, this disables zftape's | ||
86 | built in on-the-fly compression which doesn't work with variable | ||
87 | block size mode. | ||
88 | |||
89 | The BLKSZ parameter must be given as a byte count and must be a | ||
90 | multiple of 32k or 0, i.e. use "mt setblk 32768" to switch to a | ||
91 | block size of 32k. | ||
92 | |||
93 | The typical symptom of a block size mismatch is an "invalid | ||
94 | argument" error message. | ||
95 | |||
96 | 3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape) | ||
97 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
98 | zftape (the file system interface of ftape-3.x) denies write access | ||
99 | to the tape cartridge when it isn't positioned either at BOT or | ||
100 | EOD. | ||
101 | |||
102 | 4. Formatting | ||
103 | ~~~~~~~~~~ | ||
104 | ftape DOES support formatting of floppy tape cartridges. You need the | ||
105 | `ftformat' program that is shipped with the modules version of ftape. | ||
106 | Please get the latest version of ftape from | ||
107 | |||
108 | ftp://sunsite.unc.edu/pub/Linux/kernel/tapes | ||
109 | |||
110 | or from the ftape home page at | ||
111 | |||
112 | http://ftape.dot-heine.de/ | ||
113 | |||
114 | `ftformat' is contained in the `./contrib/' subdirectory of that | ||
115 | separate ftape package. | ||
116 | |||
117 | 5. Interchanging cartridges with other operating systems | ||
118 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
119 | |||
120 | The internal emulation of Unix tape device file marks has changed | ||
121 | completely. ftape now uses the volume table segment as specified | ||
122 | by the QIC-40/80/3010/3020/113 standards to emulate file marks. As | ||
123 | a consequence there is limited support to interchange cartridges | ||
124 | with other operating systems. | ||
125 | |||
126 | To be more precise: ftape will detect volumes written by other OS's | ||
127 | programs and other OS's programs will detect volumes written by | ||
128 | ftape. | ||
129 | |||
130 | However, it isn't possible to extract the data dumped to the tape | ||
131 | by some MSDOS program with ftape. This exceeds the scope of a | ||
132 | kernel device driver. If you need such functionality, then go ahead | ||
133 | and write a user space utility that is able to do that. ftape already | ||
134 | provides all kernel level support necessary to do that. | ||
135 | |||
136 | ******************************************************************************* | ||
137 | |||
138 | B. Debugging Output | ||
139 | ================ | ||
140 | |||
141 | 1. Introduction | ||
142 | ~~~~~~~~~~~~ | ||
143 | The ftape driver can be very noisy in that is can print lots of | ||
144 | debugging messages to the kernel log files and the system console. | ||
145 | While this is useful for debugging it might be annoying during | ||
146 | normal use and enlarges the size of the driver by several kilobytes. | ||
147 | |||
148 | To reduce the size of the driver you can trim the maximal amount of | ||
149 | debugging information available during kernel configuration. Please | ||
150 | refer to the kernel configuration script and its on-line help | ||
151 | functionality. | ||
152 | |||
153 | The amount of debugging output maps to the "tracing" boot time | ||
154 | option and the "ft_tracing" modules option as follows: | ||
155 | |||
156 | 0 bugs | ||
157 | 1 + errors (with call-stack dump) | ||
158 | 2 + warnings | ||
159 | 3 + information | ||
160 | 4 + more information | ||
161 | 5 + program flow | ||
162 | 6 + fdc/dma info | ||
163 | 7 + data flow | ||
164 | 8 + everything else | ||
165 | |||
166 | 2. Tuning the debugging output | ||
167 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
168 | To reduce the amount of debugging output printed to the system | ||
169 | console you can | ||
170 | |||
171 | i) trim the debugging output at run-time with | ||
172 | |||
173 | mt -f /dev/nqft0 setdensity #DBGLVL | ||
174 | |||
175 | where "#DBGLVL" is a number between 0 and 9 | ||
176 | |||
177 | ii) trim the debugging output at module load time with | ||
178 | |||
179 | modprobe ftape ft_tracing=#DBGLVL | ||
180 | |||
181 | Of course, this applies only if you have configured ftape to be | ||
182 | compiled as a module. | ||
183 | |||
184 | iii) trim the debugging output during system boot time. Add the | ||
185 | following to the kernel command line: | ||
186 | |||
187 | ftape=#DBGLVL,tracing | ||
188 | |||
189 | Please refer also to the next section if you don't know how to | ||
190 | set boot time parameters. | ||
191 | |||
192 | ******************************************************************************* | ||
193 | |||
194 | C. Boot and load time configuration | ||
195 | ================================ | ||
196 | |||
197 | 1. Setting boot time parameters | ||
198 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
199 | Assuming that you use lilo, the LI)nux LO)ader, boot time kernel | ||
200 | parameters can be set by adding a line | ||
201 | |||
202 | append some_kernel_boot_time_parameter | ||
203 | |||
204 | to `/etc/lilo.conf' or at real boot time by typing in the options | ||
205 | at the prompt provided by LILO. I can't give you advice on how to | ||
206 | specify those parameters with other loaders as I don't use them. | ||
207 | |||
208 | For ftape, each "some_kernel_boot_time_parameter" looks like | ||
209 | "ftape=value,option". As an example, the debugging output can be | ||
210 | increased with | ||
211 | |||
212 | ftape=4,tracing | ||
213 | |||
214 | NOTE: the value precedes the option name. | ||
215 | |||
216 | 2. Module load time parameters | ||
217 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
218 | Module parameters can be specified either directly when invoking | ||
219 | the program 'modprobe' at the shell prompt: | ||
220 | |||
221 | modprobe ftape ft_tracing=4 | ||
222 | |||
223 | or by editing the file `/etc/modprobe.conf' in which case they take | ||
224 | effect each time when the module is loaded with `modprobe' (please | ||
225 | refer to the respective manual pages). Thus, you should add a line | ||
226 | |||
227 | options ftape ft_tracing=4 | ||
228 | |||
229 | to `/etc/modprobe.conf` if you intend to increase the debugging | ||
230 | output of the driver. | ||
231 | |||
232 | |||
233 | 3. Ftape boot- and load time options | ||
234 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
235 | |||
236 | i. Controlling the amount of debugging output | ||
237 | DBGLVL has to be replaced by a number between 0 and 8. | ||
238 | |||
239 | module | kernel command line | ||
240 | -----------------------|---------------------- | ||
241 | ft_tracing=DBGLVL | ftape=DBGLVL,tracing | ||
242 | |||
243 | ii. Hardware setup | ||
244 | BASE is the base address of your floppy disk controller, | ||
245 | IRQ and DMA give its interrupt and DMA channel, respectively. | ||
246 | BOOL is an integer, "0" means "no"; any other value means | ||
247 | "yes". You don't need to specify anything if connecting your tape | ||
248 | drive to the standard floppy disk controller. All of these | ||
249 | values have reasonable defaults. The defaults can be modified | ||
250 | during kernel configuration, i.e. while running "make config", | ||
251 | "make menuconfig" or "make xconfig" in the top level directory | ||
252 | of the Linux kernel source tree. Please refer also to the on | ||
253 | line documentation provided during that kernel configuration | ||
254 | process. | ||
255 | |||
256 | ft_probe_fc10 is set to a non-zero value if you wish for ftape to | ||
257 | probe for a Colorado FC-10 or FC-20 controller. | ||
258 | |||
259 | ft_mach2 is set to a non-zero value if you wish for ftape to probe | ||
260 | for a Mountain MACH-2 controller. | ||
261 | |||
262 | module | kernel command line | ||
263 | -----------------------|---------------------- | ||
264 | ft_fdc_base=BASE | ftape=BASE,ioport | ||
265 | ft_fdc_irq=IRQ | ftape=IRQ,irq | ||
266 | ft_fdc_dma=DMA | ftape=DMA,dma | ||
267 | ft_probe_fc10=BOOL | ftape=BOOL,fc10 | ||
268 | ft_mach2=BOOL | ftape=BOOL,mach2 | ||
269 | ft_fdc_threshold=THR | ftape=THR,threshold | ||
270 | ft_fdc_rate_limit=RATE | ftape=RATE,datarate | ||
271 | |||
272 | 4. Example kernel parameter setting | ||
273 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
274 | To configure ftape to probe for a Colorado FC-10/FC-20 controller | ||
275 | and to increase the amount of debugging output a little bit, add | ||
276 | the following line to `/etc/lilo.conf': | ||
277 | |||
278 | append ftape=1,fc10 ftape=4,tracing | ||
279 | |||
280 | 5. Example module parameter setting | ||
281 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
282 | To do the same, but with ftape compiled as a loadable kernel | ||
283 | module, add the following line to `/etc/modprobe.conf': | ||
284 | |||
285 | options ftape ft_probe_fc10=1 ft_tracing=4 | ||
286 | |||
287 | ******************************************************************************* | ||
288 | |||
289 | D. Support and contacts | ||
290 | ==================== | ||
291 | |||
292 | Ftape is distributed under the GNU General Public License. There is | ||
293 | absolutely no warranty for this software. However, you can reach | ||
294 | the current maintainer of the ftape package under the email address | ||
295 | given in the MAINTAINERS file which is located in the top level | ||
296 | directory of the Linux kernel source tree. There you'll find also | ||
297 | the relevant mailing list to use as a discussion forum and the web | ||
298 | page to query for the most recent documentation, related work and | ||
299 | development versions of ftape. | ||
300 | |||
301 | Changelog: | ||
302 | ========== | ||
303 | |||
304 | ~1996: Original Document | ||
305 | |||
306 | 10-24-2004: General cleanup and updating, noting additional module options. | ||
307 | James Nelson <james4765@gmail.com> | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 67473849f20e..15e4fed127f6 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -557,9 +557,6 @@ and is between 256 and 4096 characters. It is defined in the file | |||
557 | floppy= [HW] | 557 | floppy= [HW] |
558 | See Documentation/floppy.txt. | 558 | See Documentation/floppy.txt. |
559 | 559 | ||
560 | ftape= [HW] Floppy Tape subsystem debugging options. | ||
561 | See Documentation/ftape.txt. | ||
562 | |||
563 | gamecon.map[2|3]= | 560 | gamecon.map[2|3]= |
564 | [HW,JOY] Multisystem joystick and NES/SNES/PSX pad | 561 | [HW,JOY] Multisystem joystick and NES/SNES/PSX pad |
565 | support via parallel port (up to 5 devices per port) | 562 | support via parallel port (up to 5 devices per port) |
diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO index d684a6ac69a8..22f82f21bc60 100644 --- a/Documentation/s390/CommonIO +++ b/Documentation/s390/CommonIO | |||
@@ -74,7 +74,7 @@ Command line parameters | |||
74 | 74 | ||
75 | Note: While already known devices can be added to the list of devices to be | 75 | Note: While already known devices can be added to the list of devices to be |
76 | ignored, there will be no effect on then. However, if such a device | 76 | ignored, there will be no effect on then. However, if such a device |
77 | disappears and then reappeares, it will then be ignored. | 77 | disappears and then reappears, it will then be ignored. |
78 | 78 | ||
79 | For example, | 79 | For example, |
80 | "echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore" | 80 | "echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore" |
@@ -82,7 +82,7 @@ Command line parameters | |||
82 | devices. | 82 | devices. |
83 | 83 | ||
84 | The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward | 84 | The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward |
85 | compatibilty, by the device number in hexadecimal (0xabcd or abcd). | 85 | compatibility, by the device number in hexadecimal (0xabcd or abcd). |
86 | 86 | ||
87 | 87 | ||
88 | * /proc/s390dbf/cio_*/ (S/390 debug feature) | 88 | * /proc/s390dbf/cio_*/ (S/390 debug feature) |
diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt index 4dd25ee549e9..3f9ddbc23b27 100644 --- a/Documentation/s390/Debugging390.txt +++ b/Documentation/s390/Debugging390.txt | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | Overview of Document: | 8 | Overview of Document: |
9 | ===================== | 9 | ===================== |
10 | This document is intended to give an good overview of how to debug | 10 | This document is intended to give a good overview of how to debug |
11 | Linux for s/390 & z/Architecture. It isn't intended as a complete reference & not a | 11 | Linux for s/390 & z/Architecture. It isn't intended as a complete reference & not a |
12 | tutorial on the fundamentals of C & assembly. It doesn't go into | 12 | tutorial on the fundamentals of C & assembly. It doesn't go into |
13 | 390 IO in any detail. It is intended to complement the documents in the | 13 | 390 IO in any detail. It is intended to complement the documents in the |
@@ -300,7 +300,7 @@ On z/Architecture our page indexes are now 2k in size | |||
300 | but only mess with 2 segment indices each time we mess with | 300 | but only mess with 2 segment indices each time we mess with |
301 | a PMD. | 301 | a PMD. |
302 | 302 | ||
303 | 3) As z/Architecture supports upto a massive 5-level page table lookup we | 303 | 3) As z/Architecture supports up to a massive 5-level page table lookup we |
304 | can only use 3 currently on Linux ( as this is all the generic kernel | 304 | can only use 3 currently on Linux ( as this is all the generic kernel |
305 | currently supports ) however this may change in future | 305 | currently supports ) however this may change in future |
306 | this allows us to access ( according to my sums ) | 306 | this allows us to access ( according to my sums ) |
@@ -502,7 +502,7 @@ Notes: | |||
502 | ------ | 502 | ------ |
503 | 1) The only requirement is that registers which are used | 503 | 1) The only requirement is that registers which are used |
504 | by the callee are saved, e.g. the compiler is perfectly | 504 | by the callee are saved, e.g. the compiler is perfectly |
505 | capible of using r11 for purposes other than a frame a | 505 | capable of using r11 for purposes other than a frame a |
506 | frame pointer if a frame pointer is not needed. | 506 | frame pointer if a frame pointer is not needed. |
507 | 2) In functions with variable arguments e.g. printf the calling procedure | 507 | 2) In functions with variable arguments e.g. printf the calling procedure |
508 | is identical to one without variable arguments & the same number of | 508 | is identical to one without variable arguments & the same number of |
@@ -846,7 +846,7 @@ of time searching for debugging info. The following self explanatory line should | |||
846 | instead if the code isn't compiled -g, as it is much faster: | 846 | instead if the code isn't compiled -g, as it is much faster: |
847 | objdump --disassemble-all --syms vmlinux > vmlinux.lst | 847 | objdump --disassemble-all --syms vmlinux > vmlinux.lst |
848 | 848 | ||
849 | As hard drive space is valuble most of us use the following approach. | 849 | As hard drive space is valuable most of us use the following approach. |
850 | 1) Look at the emitted psw on the console to find the crash address in the kernel. | 850 | 1) Look at the emitted psw on the console to find the crash address in the kernel. |
851 | 2) Look at the file System.map ( in the linux directory ) produced when building | 851 | 2) Look at the file System.map ( in the linux directory ) produced when building |
852 | the kernel to find the closest address less than the current PSW to find the | 852 | the kernel to find the closest address less than the current PSW to find the |
@@ -902,7 +902,7 @@ A. It is a tool for intercepting calls to the kernel & logging them | |||
902 | to a file & on the screen. | 902 | to a file & on the screen. |
903 | 903 | ||
904 | Q. What use is it ? | 904 | Q. What use is it ? |
905 | A. You can used it to find out what files a particular program opens. | 905 | A. You can use it to find out what files a particular program opens. |
906 | 906 | ||
907 | 907 | ||
908 | 908 | ||
@@ -911,7 +911,7 @@ Example 1 | |||
911 | If you wanted to know does ping work but didn't have the source | 911 | If you wanted to know does ping work but didn't have the source |
912 | strace ping -c 1 127.0.0.1 | 912 | strace ping -c 1 127.0.0.1 |
913 | & then look at the man pages for each of the syscalls below, | 913 | & then look at the man pages for each of the syscalls below, |
914 | ( In fact this is sometimes easier than looking at some spagetti | 914 | ( In fact this is sometimes easier than looking at some spaghetti |
915 | source which conditionally compiles for several architectures ). | 915 | source which conditionally compiles for several architectures ). |
916 | Not everything that it throws out needs to make sense immediately. | 916 | Not everything that it throws out needs to make sense immediately. |
917 | 917 | ||
@@ -1037,7 +1037,7 @@ e.g. man strace, man alarm, man socket. | |||
1037 | 1037 | ||
1038 | Performance Debugging | 1038 | Performance Debugging |
1039 | ===================== | 1039 | ===================== |
1040 | gcc is capible of compiling in profiling code just add the -p option | 1040 | gcc is capable of compiling in profiling code just add the -p option |
1041 | to the CFLAGS, this obviously affects program size & performance. | 1041 | to the CFLAGS, this obviously affects program size & performance. |
1042 | This can be used by the gprof gnu profiling tool or the | 1042 | This can be used by the gprof gnu profiling tool or the |
1043 | gcov the gnu code coverage tool ( code coverage is a means of testing | 1043 | gcov the gnu code coverage tool ( code coverage is a means of testing |
@@ -1419,7 +1419,7 @@ On a SMP guest issue a command to all CPUs try prefixing the command with cpu al | |||
1419 | To issue a command to a particular cpu try cpu <cpu number> e.g. | 1419 | To issue a command to a particular cpu try cpu <cpu number> e.g. |
1420 | CPU 01 TR I R 2000.3000 | 1420 | CPU 01 TR I R 2000.3000 |
1421 | If you are running on a guest with several cpus & you have a IO related problem | 1421 | If you are running on a guest with several cpus & you have a IO related problem |
1422 | & cannot follow the flow of code but you know it isnt smp related. | 1422 | & cannot follow the flow of code but you know it isn't smp related. |
1423 | from the bash prompt issue | 1423 | from the bash prompt issue |
1424 | shutdown -h now or halt. | 1424 | shutdown -h now or halt. |
1425 | do a Q CPUS to find out how many cpus you have | 1425 | do a Q CPUS to find out how many cpus you have |
@@ -1602,7 +1602,7 @@ V000FFFD0 00010400 80010802 8001085A 000FFFA0 | |||
1602 | our 3rd return address is 8001085A | 1602 | our 3rd return address is 8001085A |
1603 | 1603 | ||
1604 | as the 04B52002 looks suspiciously like rubbish it is fair to assume that the kernel entry routines | 1604 | as the 04B52002 looks suspiciously like rubbish it is fair to assume that the kernel entry routines |
1605 | for the sake of optimisation dont set up a backchain. | 1605 | for the sake of optimisation don't set up a backchain. |
1606 | 1606 | ||
1607 | now look at System.map to see if the addresses make any sense. | 1607 | now look at System.map to see if the addresses make any sense. |
1608 | 1608 | ||
@@ -1638,11 +1638,11 @@ more useful information. | |||
1638 | 1638 | ||
1639 | Unlike other bus architectures modern 390 systems do their IO using mostly | 1639 | Unlike other bus architectures modern 390 systems do their IO using mostly |
1640 | fibre optics & devices such as tapes & disks can be shared between several mainframes, | 1640 | fibre optics & devices such as tapes & disks can be shared between several mainframes, |
1641 | also S390 can support upto 65536 devices while a high end PC based system might be choking | 1641 | also S390 can support up to 65536 devices while a high end PC based system might be choking |
1642 | with around 64. Here is some of the common IO terminology | 1642 | with around 64. Here is some of the common IO terminology |
1643 | 1643 | ||
1644 | Subchannel: | 1644 | Subchannel: |
1645 | This is the logical number most IO commands use to talk to an IO device there can be upto | 1645 | This is the logical number most IO commands use to talk to an IO device there can be up to |
1646 | 0x10000 (65536) of these in a configuration typically there is a few hundred. Under VM | 1646 | 0x10000 (65536) of these in a configuration typically there is a few hundred. Under VM |
1647 | for simplicity they are allocated contiguously, however on the native hardware they are not | 1647 | for simplicity they are allocated contiguously, however on the native hardware they are not |
1648 | they typically stay consistent between boots provided no new hardware is inserted or removed. | 1648 | they typically stay consistent between boots provided no new hardware is inserted or removed. |
@@ -1651,7 +1651,7 @@ HALT SUBCHANNEL,MODIFY SUBCHANNEL,RESUME SUBCHANNEL,START SUBCHANNEL,STORE SUBCH | |||
1651 | TEST SUBCHANNEL ) we use this as the ID of the device we wish to talk to, the most | 1651 | TEST SUBCHANNEL ) we use this as the ID of the device we wish to talk to, the most |
1652 | important of these instructions are START SUBCHANNEL ( to start IO ), TEST SUBCHANNEL ( to check | 1652 | important of these instructions are START SUBCHANNEL ( to start IO ), TEST SUBCHANNEL ( to check |
1653 | whether the IO completed successfully ), & HALT SUBCHANNEL ( to kill IO ), a subchannel | 1653 | whether the IO completed successfully ), & HALT SUBCHANNEL ( to kill IO ), a subchannel |
1654 | can have up to 8 channel paths to a device this offers redunancy if one is not available. | 1654 | can have up to 8 channel paths to a device this offers redundancy if one is not available. |
1655 | 1655 | ||
1656 | 1656 | ||
1657 | Device Number: | 1657 | Device Number: |
@@ -1659,7 +1659,7 @@ This number remains static & Is closely tied to the hardware, there are 65536 of | |||
1659 | also they are made up of a CHPID ( Channel Path ID, the most significant 8 bits ) | 1659 | also they are made up of a CHPID ( Channel Path ID, the most significant 8 bits ) |
1660 | & another lsb 8 bits. These remain static even if more devices are inserted or removed | 1660 | & another lsb 8 bits. These remain static even if more devices are inserted or removed |
1661 | from the hardware, there is a 1 to 1 mapping between Subchannels & Device Numbers provided | 1661 | from the hardware, there is a 1 to 1 mapping between Subchannels & Device Numbers provided |
1662 | devices arent inserted or removed. | 1662 | devices aren't inserted or removed. |
1663 | 1663 | ||
1664 | Channel Control Words: | 1664 | Channel Control Words: |
1665 | CCWS are linked lists of instructions initially pointed to by an operation request block (ORB), | 1665 | CCWS are linked lists of instructions initially pointed to by an operation request block (ORB), |
@@ -1674,7 +1674,7 @@ concurrently, you check how the IO went on by issuing a TEST SUBCHANNEL at each | |||
1674 | from which you receive an Interruption response block (IRB). If you get channel & device end | 1674 | from which you receive an Interruption response block (IRB). If you get channel & device end |
1675 | status in the IRB without channel checks etc. your IO probably went okay. If you didn't you | 1675 | status in the IRB without channel checks etc. your IO probably went okay. If you didn't you |
1676 | probably need a doctor to examine the IRB & extended status word etc. | 1676 | probably need a doctor to examine the IRB & extended status word etc. |
1677 | If an error occurs, more sophistocated control units have a facitity known as | 1677 | If an error occurs, more sophisticated control units have a facility known as |
1678 | concurrent sense this means that if an error occurs Extended sense information will | 1678 | concurrent sense this means that if an error occurs Extended sense information will |
1679 | be presented in the Extended status word in the IRB if not you have to issue a | 1679 | be presented in the Extended status word in the IRB if not you have to issue a |
1680 | subsequent SENSE CCW command after the test subchannel. | 1680 | subsequent SENSE CCW command after the test subchannel. |
@@ -1749,7 +1749,7 @@ Interface (OEMI). | |||
1749 | This byte wide Parallel channel path/bus has parity & data on the "Bus" cable | 1749 | This byte wide Parallel channel path/bus has parity & data on the "Bus" cable |
1750 | & control lines on the "Tag" cable. These can operate in byte multiplex mode for | 1750 | & control lines on the "Tag" cable. These can operate in byte multiplex mode for |
1751 | sharing between several slow devices or burst mode & monopolize the channel for the | 1751 | sharing between several slow devices or burst mode & monopolize the channel for the |
1752 | whole burst. Upto 256 devices can be addressed on one of these cables. These cables are | 1752 | whole burst. Up to 256 devices can be addressed on one of these cables. These cables are |
1753 | about one inch in diameter. The maximum unextended length supported by these cables is | 1753 | about one inch in diameter. The maximum unextended length supported by these cables is |
1754 | 125 Meters but this can be extended up to 2km with a fibre optic channel extended | 1754 | 125 Meters but this can be extended up to 2km with a fibre optic channel extended |
1755 | such as a 3044. The maximum burst speed supported is 4.5 megabytes per second however | 1755 | such as a 3044. The maximum burst speed supported is 4.5 megabytes per second however |
@@ -1759,7 +1759,7 @@ One of these paths can be daisy chained to up to 8 control units. | |||
1759 | 1759 | ||
1760 | ESCON if fibre optic it is also called FICON | 1760 | ESCON if fibre optic it is also called FICON |
1761 | Was introduced by IBM in 1990. Has 2 fibre optic cables & uses either leds or lasers | 1761 | Was introduced by IBM in 1990. Has 2 fibre optic cables & uses either leds or lasers |
1762 | for communication at a signaling rate of upto 200 megabits/sec. As 10bits are transferred | 1762 | for communication at a signaling rate of up to 200 megabits/sec. As 10bits are transferred |
1763 | for every 8 bits info this drops to 160 megabits/sec & to 18.6 Megabytes/sec once | 1763 | for every 8 bits info this drops to 160 megabits/sec & to 18.6 Megabytes/sec once |
1764 | control info & CRC are added. ESCON only operates in burst mode. | 1764 | control info & CRC are added. ESCON only operates in burst mode. |
1765 | 1765 | ||
@@ -1767,7 +1767,7 @@ ESCONs typical max cable length is 3km for the led version & 20km for the laser | |||
1767 | known as XDF ( extended distance facility ). This can be further extended by using an | 1767 | known as XDF ( extended distance facility ). This can be further extended by using an |
1768 | ESCON director which triples the above mentioned ranges. Unlike Bus & Tag as ESCON is | 1768 | ESCON director which triples the above mentioned ranges. Unlike Bus & Tag as ESCON is |
1769 | serial it uses a packet switching architecture the standard Bus & Tag control protocol | 1769 | serial it uses a packet switching architecture the standard Bus & Tag control protocol |
1770 | is however present within the packets. Upto 256 devices can be attached to each control | 1770 | is however present within the packets. Up to 256 devices can be attached to each control |
1771 | unit that uses one of these interfaces. | 1771 | unit that uses one of these interfaces. |
1772 | 1772 | ||
1773 | Common 390 Devices include: | 1773 | Common 390 Devices include: |
@@ -2050,7 +2050,7 @@ list test.c:1,10 | |||
2050 | 2050 | ||
2051 | directory: | 2051 | directory: |
2052 | Adds directories to be searched for source if gdb cannot find the source. | 2052 | Adds directories to be searched for source if gdb cannot find the source. |
2053 | (note it is a bit sensititive about slashes) | 2053 | (note it is a bit sensitive about slashes) |
2054 | e.g. To add the root of the filesystem to the searchpath do | 2054 | e.g. To add the root of the filesystem to the searchpath do |
2055 | directory // | 2055 | directory // |
2056 | 2056 | ||
@@ -2152,7 +2152,7 @@ program as if it just crashed on your system, it is usually called core & create | |||
2152 | current working directory. | 2152 | current working directory. |
2153 | This is very useful in that a customer can mail a core dump to a technical support department | 2153 | This is very useful in that a customer can mail a core dump to a technical support department |
2154 | & the technical support department can reconstruct what happened. | 2154 | & the technical support department can reconstruct what happened. |
2155 | Provided the have an identical copy of this program with debugging symbols compiled in & | 2155 | Provided they have an identical copy of this program with debugging symbols compiled in & |
2156 | the source base of this build is available. | 2156 | the source base of this build is available. |
2157 | In short it is far more useful than something like a crash log could ever hope to be. | 2157 | In short it is far more useful than something like a crash log could ever hope to be. |
2158 | 2158 | ||
diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt index 32a96cc39215..05a2b4f7e38f 100644 --- a/Documentation/s390/cds.txt +++ b/Documentation/s390/cds.txt | |||
@@ -98,7 +98,7 @@ The following chapters describe the I/O related interface routines the | |||
98 | Linux/390 common device support (CDS) provides to allow for device specific | 98 | Linux/390 common device support (CDS) provides to allow for device specific |
99 | driver implementations on the IBM ESA/390 hardware platform. Those interfaces | 99 | driver implementations on the IBM ESA/390 hardware platform. Those interfaces |
100 | intend to provide the functionality required by every device driver | 100 | intend to provide the functionality required by every device driver |
101 | implementaion to allow to drive a specific hardware device on the ESA/390 | 101 | implementation to allow to drive a specific hardware device on the ESA/390 |
102 | platform. Some of the interface routines are specific to Linux/390 and some | 102 | platform. Some of the interface routines are specific to Linux/390 and some |
103 | of them can be found on other Linux platforms implementations too. | 103 | of them can be found on other Linux platforms implementations too. |
104 | Miscellaneous function prototypes, data declarations, and macro definitions | 104 | Miscellaneous function prototypes, data declarations, and macro definitions |
@@ -114,7 +114,7 @@ the ESA/390 architecture has implemented a so called channel subsystem, that | |||
114 | provides a unified view of the devices physically attached to the systems. | 114 | provides a unified view of the devices physically attached to the systems. |
115 | Though the ESA/390 hardware platform knows about a huge variety of different | 115 | Though the ESA/390 hardware platform knows about a huge variety of different |
116 | peripheral attachments like disk devices (aka. DASDs), tapes, communication | 116 | peripheral attachments like disk devices (aka. DASDs), tapes, communication |
117 | controllers, etc. they can all by accessed by a well defined access method and | 117 | controllers, etc. they can all be accessed by a well defined access method and |
118 | they are presenting I/O completion a unified way : I/O interruptions. Every | 118 | they are presenting I/O completion a unified way : I/O interruptions. Every |
119 | single device is uniquely identified to the system by a so called subchannel, | 119 | single device is uniquely identified to the system by a so called subchannel, |
120 | where the ESA/390 architecture allows for 64k devices be attached. | 120 | where the ESA/390 architecture allows for 64k devices be attached. |
@@ -338,7 +338,7 @@ DOIO_REPORT_ALL - report all interrupt conditions | |||
338 | The ccw_device_start() function returns : | 338 | The ccw_device_start() function returns : |
339 | 339 | ||
340 | 0 - successful completion or request successfully initiated | 340 | 0 - successful completion or request successfully initiated |
341 | -EBUSY - The device is currently processing a previous I/O request, or ther is | 341 | -EBUSY - The device is currently processing a previous I/O request, or there is |
342 | a status pending at the device. | 342 | a status pending at the device. |
343 | -ENODEV - cdev is invalid, the device is not operational or the ccw_device is | 343 | -ENODEV - cdev is invalid, the device is not operational or the ccw_device is |
344 | not online. | 344 | not online. |
@@ -361,7 +361,7 @@ first: | |||
361 | -EIO: the common I/O layer terminated the request due to an error state | 361 | -EIO: the common I/O layer terminated the request due to an error state |
362 | 362 | ||
363 | If the concurrent sense flag in the extended status word in the irb is set, the | 363 | If the concurrent sense flag in the extended status word in the irb is set, the |
364 | field irb->scsw.count describes the numer of device specific sense bytes | 364 | field irb->scsw.count describes the number of device specific sense bytes |
365 | available in the extended control word irb->scsw.ecw[0]. No device sensing by | 365 | available in the extended control word irb->scsw.ecw[0]. No device sensing by |
366 | the device driver itself is required. | 366 | the device driver itself is required. |
367 | 367 | ||
@@ -410,7 +410,7 @@ ccw_device_start() must be called disabled and with the ccw device lock held. | |||
410 | 410 | ||
411 | The device driver is allowed to issue the next ccw_device_start() call from | 411 | The device driver is allowed to issue the next ccw_device_start() call from |
412 | within its interrupt handler already. It is not required to schedule a | 412 | within its interrupt handler already. It is not required to schedule a |
413 | bottom-half, unless an non deterministically long running error recovery procedure | 413 | bottom-half, unless a non deterministically long running error recovery procedure |
414 | or similar needs to be scheduled. During I/O processing the Linux/390 generic | 414 | or similar needs to be scheduled. During I/O processing the Linux/390 generic |
415 | I/O device driver support has already obtained the IRQ lock, i.e. the handler | 415 | I/O device driver support has already obtained the IRQ lock, i.e. the handler |
416 | must not try to obtain it again when calling ccw_device_start() or we end in a | 416 | must not try to obtain it again when calling ccw_device_start() or we end in a |
@@ -431,7 +431,7 @@ information prior to device-end the device driver urgently relies on. In this | |||
431 | case all I/O interruptions are presented to the device driver until final | 431 | case all I/O interruptions are presented to the device driver until final |
432 | status is recognized. | 432 | status is recognized. |
433 | 433 | ||
434 | If a device is able to recover from asynchronosly presented I/O errors, it can | 434 | If a device is able to recover from asynchronously presented I/O errors, it can |
435 | perform overlapping I/O using the DOIO_EARLY_NOTIFICATION flag. While some | 435 | perform overlapping I/O using the DOIO_EARLY_NOTIFICATION flag. While some |
436 | devices always report channel-end and device-end together, with a single | 436 | devices always report channel-end and device-end together, with a single |
437 | interrupt, others present primary status (channel-end) when the channel is | 437 | interrupt, others present primary status (channel-end) when the channel is |
diff --git a/Documentation/s390/crypto/crypto-API.txt b/Documentation/s390/crypto/crypto-API.txt index 41a8b07da05a..71ae6ca9f2c2 100644 --- a/Documentation/s390/crypto/crypto-API.txt +++ b/Documentation/s390/crypto/crypto-API.txt | |||
@@ -17,8 +17,8 @@ arch/s390/crypto directory. | |||
17 | 2. Probing for availability of MSA | 17 | 2. Probing for availability of MSA |
18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
19 | It should be possible to use Kernels with the z990 crypto implementations both | 19 | It should be possible to use Kernels with the z990 crypto implementations both |
20 | on machines with MSA available an on those without MSA (pre z990 or z990 | 20 | on machines with MSA available and on those without MSA (pre z990 or z990 |
21 | without MSA). Therefore a simple probing mechanisms has been implemented: | 21 | without MSA). Therefore a simple probing mechanism has been implemented: |
22 | In the init function of each crypto module the availability of MSA and of the | 22 | In the init function of each crypto module the availability of MSA and of the |
23 | respective crypto algorithm in particular will be tested. If the algorithm is | 23 | respective crypto algorithm in particular will be tested. If the algorithm is |
24 | available the module will load and register its algorithm with the crypto API. | 24 | available the module will load and register its algorithm with the crypto API. |
@@ -26,7 +26,7 @@ available the module will load and register its algorithm with the crypto API. | |||
26 | If the respective crypto algorithm is not available, the init function will | 26 | If the respective crypto algorithm is not available, the init function will |
27 | return -ENOSYS. In that case a fallback to the standard software implementation | 27 | return -ENOSYS. In that case a fallback to the standard software implementation |
28 | of the crypto algorithm must be taken ( -> the standard crypto modules are | 28 | of the crypto algorithm must be taken ( -> the standard crypto modules are |
29 | also build when compiling the kernel). | 29 | also built when compiling the kernel). |
30 | 30 | ||
31 | 31 | ||
32 | 3. Ensuring z990 crypto module preference | 32 | 3. Ensuring z990 crypto module preference |
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt index 000230cd26db..0eb7c58916de 100644 --- a/Documentation/s390/s390dbf.txt +++ b/Documentation/s390/s390dbf.txt | |||
@@ -36,7 +36,7 @@ switches to the next debug area. This is done in order to be sure | |||
36 | that the records which describe the origin of the exception are not | 36 | that the records which describe the origin of the exception are not |
37 | overwritten when a wrap around for the current area occurs. | 37 | overwritten when a wrap around for the current area occurs. |
38 | 38 | ||
39 | The debug areas itselve are also ordered in form of a ring buffer. | 39 | The debug areas themselves are also ordered in form of a ring buffer. |
40 | When an exception is thrown in the last debug area, the following debug | 40 | When an exception is thrown in the last debug area, the following debug |
41 | entries are then written again in the very first area. | 41 | entries are then written again in the very first area. |
42 | 42 | ||
@@ -55,7 +55,7 @@ The debug logs can be inspected in a live system through entries in | |||
55 | the debugfs-filesystem. Under the toplevel directory "s390dbf" there is | 55 | the debugfs-filesystem. Under the toplevel directory "s390dbf" there is |
56 | a directory for each registered component, which is named like the | 56 | a directory for each registered component, which is named like the |
57 | corresponding component. The debugfs normally should be mounted to | 57 | corresponding component. The debugfs normally should be mounted to |
58 | /sys/kernel/debug therefore the debug feature can be accessed unter | 58 | /sys/kernel/debug therefore the debug feature can be accessed under |
59 | /sys/kernel/debug/s390dbf. | 59 | /sys/kernel/debug/s390dbf. |
60 | 60 | ||
61 | The content of the directories are files which represent different views | 61 | The content of the directories are files which represent different views |
@@ -87,11 +87,11 @@ There are currently 2 possible triggers, which stop the debug feature | |||
87 | globally. The first possibility is to use the "debug_active" sysctl. If | 87 | globally. The first possibility is to use the "debug_active" sysctl. If |
88 | set to 1 the debug feature is running. If "debug_active" is set to 0 the | 88 | set to 1 the debug feature is running. If "debug_active" is set to 0 the |
89 | debug feature is turned off. | 89 | debug feature is turned off. |
90 | The second trigger which stops the debug feature is an kernel oops. | 90 | The second trigger which stops the debug feature is a kernel oops. |
91 | That prevents the debug feature from overwriting debug information that | 91 | That prevents the debug feature from overwriting debug information that |
92 | happened before the oops. After an oops you can reactivate the debug feature | 92 | happened before the oops. After an oops you can reactivate the debug feature |
93 | by piping 1 to /proc/sys/s390dbf/debug_active. Nevertheless, its not | 93 | by piping 1 to /proc/sys/s390dbf/debug_active. Nevertheless, its not |
94 | suggested to use an oopsed kernel in an production environment. | 94 | suggested to use an oopsed kernel in a production environment. |
95 | If you want to disallow the deactivation of the debug feature, you can use | 95 | If you want to disallow the deactivation of the debug feature, you can use |
96 | the "debug_stoppable" sysctl. If you set "debug_stoppable" to 0 the debug | 96 | the "debug_stoppable" sysctl. If you set "debug_stoppable" to 0 the debug |
97 | feature cannot be stopped. If the debug feature is already stopped, it | 97 | feature cannot be stopped. If the debug feature is already stopped, it |
diff --git a/MAINTAINERS b/MAINTAINERS index fd3b2ca0c031..5dff26814a06 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1166,11 +1166,6 @@ P: David Howells | |||
1166 | M: dhowells@redhat.com | 1166 | M: dhowells@redhat.com |
1167 | S: Maintained | 1167 | S: Maintained |
1168 | 1168 | ||
1169 | FTAPE/QIC-117 | ||
1170 | L: linux-tape@vger.kernel.org | ||
1171 | W: http://sourceforge.net/projects/ftape | ||
1172 | S: Orphan | ||
1173 | |||
1174 | FUSE: FILESYSTEM IN USERSPACE | 1169 | FUSE: FILESYSTEM IN USERSPACE |
1175 | P: Miklos Szeredi | 1170 | P: Miklos Szeredi |
1176 | M: miklos@szeredi.hu | 1171 | M: miklos@szeredi.hu |
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c index 20563e52c622..4664b55f623e 100644 --- a/arch/i386/kernel/acpi/cstate.c +++ b/arch/i386/kernel/acpi/cstate.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/acpi.h> | 12 | #include <linux/acpi.h> |
13 | #include <linux/cpu.h> | 13 | #include <linux/cpu.h> |
14 | #include <linux/sched.h> | ||
14 | 15 | ||
15 | #include <acpi/processor.h> | 16 | #include <acpi/processor.h> |
16 | #include <asm/acpi.h> | 17 | #include <asm/acpi.h> |
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 583c238e17fb..535f9794fba1 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/sched.h> | ||
2 | #include <linux/spinlock.h> | 3 | #include <linux/spinlock.h> |
3 | #include <linux/list.h> | 4 | #include <linux/list.h> |
4 | #include <asm/alternative.h> | 5 | #include <asm/alternative.h> |
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c index 2d8703b7ce65..bad8b4420709 100644 --- a/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
21 | #include <asm/cpu.h> | 21 | #include <asm/cpu.h> |
22 | #include <linux/notifier.h> | 22 | #include <linux/notifier.h> |
23 | #include <linux/jiffies.h> | ||
23 | #include <asm/therm_throt.h> | 24 | #include <asm/therm_throt.h> |
24 | 25 | ||
25 | /* How long to wait between reporting thermal events */ | 26 | /* How long to wait between reporting thermal events */ |
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index c1bc22c6d0d8..aa70dde54228 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig | |||
@@ -173,7 +173,7 @@ config CLOCK_DIV | |||
173 | On many SoC style CPUs the master CPU clock is also used to drive | 173 | On many SoC style CPUs the master CPU clock is also used to drive |
174 | on-chip peripherals. The clock that is distributed to these | 174 | on-chip peripherals. The clock that is distributed to these |
175 | peripherals is sometimes a fixed ratio of the master clock | 175 | peripherals is sometimes a fixed ratio of the master clock |
176 | frequency. If so then set this to the divider ration of the | 176 | frequency. If so then set this to the divider ratio of the |
177 | master clock to the peripheral clock. If not sure then select 1. | 177 | master clock to the peripheral clock. If not sure then select 1. |
178 | 178 | ||
179 | config OLDMASK | 179 | config OLDMASK |
@@ -192,7 +192,7 @@ config PILOT3 | |||
192 | Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII. | 192 | Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII. |
193 | 193 | ||
194 | config XCOPILOT_BUGS | 194 | config XCOPILOT_BUGS |
195 | bool " (X)Copilot support" | 195 | bool "(X)Copilot support" |
196 | depends on PILOT3 | 196 | depends on PILOT3 |
197 | help | 197 | help |
198 | Support the bugs of Xcopilot. | 198 | Support the bugs of Xcopilot. |
@@ -216,20 +216,20 @@ config DRAGEN2 | |||
216 | Support for the DragenEngine II board. | 216 | Support for the DragenEngine II board. |
217 | 217 | ||
218 | config DIRECT_IO_ACCESS | 218 | config DIRECT_IO_ACCESS |
219 | bool " Allow user to access IO directly" | 219 | bool "Allow user to access IO directly" |
220 | depends on (UCSIMM || UCDIMM || DRAGEN2) | 220 | depends on (UCSIMM || UCDIMM || DRAGEN2) |
221 | help | 221 | help |
222 | Disable the CPU internal registers protection in user mode, | 222 | Disable the CPU internal registers protection in user mode, |
223 | to allow a user application to read/write them. | 223 | to allow a user application to read/write them. |
224 | 224 | ||
225 | config INIT_LCD | 225 | config INIT_LCD |
226 | bool " Initialize LCD" | 226 | bool "Initialize LCD" |
227 | depends on (UCSIMM || UCDIMM || DRAGEN2) | 227 | depends on (UCSIMM || UCDIMM || DRAGEN2) |
228 | help | 228 | help |
229 | Initialize the LCD controller of the 68x328 processor. | 229 | Initialize the LCD controller of the 68x328 processor. |
230 | 230 | ||
231 | config MEMORY_RESERVE | 231 | config MEMORY_RESERVE |
232 | int " Memory reservation (MiB)" | 232 | int "Memory reservation (MiB)" |
233 | depends on (UCSIMM || UCDIMM) | 233 | depends on (UCSIMM || UCDIMM) |
234 | help | 234 | help |
235 | Reserve certain memory regions on 68x328 based boards. | 235 | Reserve certain memory regions on 68x328 based boards. |
@@ -409,7 +409,7 @@ config MOD5272 | |||
409 | Support for the Netburner MOD-5272 board. | 409 | Support for the Netburner MOD-5272 board. |
410 | 410 | ||
411 | config ROMFS_FROM_ROM | 411 | config ROMFS_FROM_ROM |
412 | bool " ROMFS image not RAM resident" | 412 | bool "ROMFS image not RAM resident" |
413 | depends on (NETtel || SNAPGEAR) | 413 | depends on (NETtel || SNAPGEAR) |
414 | help | 414 | help |
415 | The ROMfs filesystem will stay resident in the FLASH/ROM, not be | 415 | The ROMfs filesystem will stay resident in the FLASH/ROM, not be |
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index c18a83306953..941955dc3b7c 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c | |||
@@ -290,7 +290,7 @@ void dump(struct pt_regs *fp) | |||
290 | unsigned char *tp; | 290 | unsigned char *tp; |
291 | int i; | 291 | int i; |
292 | 292 | ||
293 | printk(KERN_EMERG "\nCURRENT PROCESS:\n\n"); | 293 | printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" KERN_EMERG "\n"); |
294 | printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid); | 294 | printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid); |
295 | 295 | ||
296 | if (current->mm) { | 296 | if (current->mm) { |
@@ -301,7 +301,8 @@ void dump(struct pt_regs *fp) | |||
301 | (int) current->mm->end_data, | 301 | (int) current->mm->end_data, |
302 | (int) current->mm->end_data, | 302 | (int) current->mm->end_data, |
303 | (int) current->mm->brk); | 303 | (int) current->mm->brk); |
304 | printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n", | 304 | printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n" |
305 | KERN_EMERG "\n", | ||
305 | (int) current->mm->start_stack, | 306 | (int) current->mm->start_stack, |
306 | (int)(((unsigned long) current) + THREAD_SIZE)); | 307 | (int)(((unsigned long) current) + THREAD_SIZE)); |
307 | } | 308 | } |
@@ -312,36 +313,35 @@ void dump(struct pt_regs *fp) | |||
312 | fp->d0, fp->d1, fp->d2, fp->d3); | 313 | fp->d0, fp->d1, fp->d2, fp->d3); |
313 | printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", | 314 | printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", |
314 | fp->d4, fp->d5, fp->a0, fp->a1); | 315 | fp->d4, fp->d5, fp->a0, fp->a1); |
315 | printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) rdusp(), | 316 | printk(KERN_EMERG "\n" KERN_EMERG "USP: %08x TRAPFRAME: %08x\n", |
316 | (unsigned int) fp); | 317 | (unsigned int) rdusp(), (unsigned int) fp); |
317 | 318 | ||
318 | printk(KERN_EMERG "\nCODE:"); | 319 | printk(KERN_EMERG "\n" KERN_EMERG "CODE:"); |
319 | tp = ((unsigned char *) fp->pc) - 0x20; | 320 | tp = ((unsigned char *) fp->pc) - 0x20; |
320 | for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { | 321 | for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { |
321 | if ((i % 0x10) == 0) | 322 | if ((i % 0x10) == 0) |
322 | printk(KERN_EMERG "\n%08x: ", (int) (tp + i)); | 323 | printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); |
323 | printk(KERN_EMERG "%08x ", (int) *sp++); | 324 | printk("%08x ", (int) *sp++); |
324 | } | 325 | } |
325 | printk(KERN_EMERG "\n"); | 326 | printk("\n" KERN_EMERG "\n"); |
326 | 327 | ||
327 | printk(KERN_EMERG "\nKERNEL STACK:"); | 328 | printk(KERN_EMERG "KERNEL STACK:"); |
328 | tp = ((unsigned char *) fp) - 0x40; | 329 | tp = ((unsigned char *) fp) - 0x40; |
329 | for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { | 330 | for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { |
330 | if ((i % 0x10) == 0) | 331 | if ((i % 0x10) == 0) |
331 | printk(KERN_EMERG "\n%08x: ", (int) (tp + i)); | 332 | printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); |
332 | printk(KERN_EMERG "%08x ", (int) *sp++); | 333 | printk("%08x ", (int) *sp++); |
333 | } | 334 | } |
334 | printk(KERN_EMERG "\n"); | 335 | printk("\n" KERN_EMERG "\n"); |
335 | printk(KERN_EMERG "\n"); | ||
336 | 336 | ||
337 | printk(KERN_EMERG "\nUSER STACK:"); | 337 | printk(KERN_EMERG "USER STACK:"); |
338 | tp = (unsigned char *) (rdusp() - 0x10); | 338 | tp = (unsigned char *) (rdusp() - 0x10); |
339 | for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { | 339 | for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { |
340 | if ((i % 0x10) == 0) | 340 | if ((i % 0x10) == 0) |
341 | printk(KERN_EMERG "\n%08x: ", (int) (tp + i)); | 341 | printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); |
342 | printk(KERN_EMERG "%08x ", (int) *sp++); | 342 | printk("%08x ", (int) *sp++); |
343 | } | 343 | } |
344 | printk(KERN_EMERG "\n\n"); | 344 | printk("\n" KERN_EMERG "\n"); |
345 | } | 345 | } |
346 | 346 | ||
347 | /* | 347 | /* |
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c index 7b21959eaeae..9cf2e4d1fc77 100644 --- a/arch/m68knommu/kernel/setup.c +++ b/arch/m68knommu/kernel/setup.c | |||
@@ -36,10 +36,7 @@ | |||
36 | #include <asm/setup.h> | 36 | #include <asm/setup.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/machdep.h> | 38 | #include <asm/machdep.h> |
39 | |||
40 | #ifdef CONFIG_BLK_DEV_INITRD | ||
41 | #include <asm/pgtable.h> | 39 | #include <asm/pgtable.h> |
42 | #endif | ||
43 | 40 | ||
44 | unsigned long memory_start; | 41 | unsigned long memory_start; |
45 | unsigned long memory_end; | 42 | unsigned long memory_end; |
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c index c3494b8447d1..3265b2d734db 100644 --- a/arch/m68knommu/kernel/sys_m68k.c +++ b/arch/m68knommu/kernel/sys_m68k.c | |||
@@ -137,7 +137,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg) | |||
137 | asmlinkage int sys_ipc (uint call, int first, int second, | 137 | asmlinkage int sys_ipc (uint call, int first, int second, |
138 | int third, void *ptr, long fifth) | 138 | int third, void *ptr, long fifth) |
139 | { | 139 | { |
140 | int version; | 140 | int version, ret; |
141 | 141 | ||
142 | version = call >> 16; /* hack for backward compatibility */ | 142 | version = call >> 16; /* hack for backward compatibility */ |
143 | call &= 0xffff; | 143 | call &= 0xffff; |
@@ -190,6 +190,27 @@ asmlinkage int sys_ipc (uint call, int first, int second, | |||
190 | default: | 190 | default: |
191 | return -EINVAL; | 191 | return -EINVAL; |
192 | } | 192 | } |
193 | if (call <= SHMCTL) | ||
194 | switch (call) { | ||
195 | case SHMAT: | ||
196 | switch (version) { | ||
197 | default: { | ||
198 | ulong raddr; | ||
199 | ret = do_shmat (first, ptr, second, &raddr); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | return put_user (raddr, (ulong __user *) third); | ||
203 | } | ||
204 | } | ||
205 | case SHMDT: | ||
206 | return sys_shmdt (ptr); | ||
207 | case SHMGET: | ||
208 | return sys_shmget (first, second, third); | ||
209 | case SHMCTL: | ||
210 | return sys_shmctl (first, second, ptr); | ||
211 | default: | ||
212 | return -ENOSYS; | ||
213 | } | ||
193 | 214 | ||
194 | return -EINVAL; | 215 | return -EINVAL; |
195 | } | 216 | } |
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index 17649d2543ef..9129b3a5258b 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c | |||
@@ -127,11 +127,12 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
127 | if (stack + 1 > endstack) | 127 | if (stack + 1 > endstack) |
128 | break; | 128 | break; |
129 | if (i % 8 == 0) | 129 | if (i % 8 == 0) |
130 | printk(KERN_EMERG "\n "); | 130 | printk("\n" KERN_EMERG " "); |
131 | printk(KERN_EMERG " %08lx", *stack++); | 131 | printk(" %08lx", *stack++); |
132 | } | 132 | } |
133 | printk("\n"); | ||
133 | 134 | ||
134 | printk(KERN_EMERG "\nCall Trace:"); | 135 | printk(KERN_EMERG "Call Trace:"); |
135 | i = 0; | 136 | i = 0; |
136 | while (stack + 1 <= endstack) { | 137 | while (stack + 1 <= endstack) { |
137 | addr = *stack++; | 138 | addr = *stack++; |
@@ -146,12 +147,12 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
146 | if (((addr >= (unsigned long) &_start) && | 147 | if (((addr >= (unsigned long) &_start) && |
147 | (addr <= (unsigned long) &_etext))) { | 148 | (addr <= (unsigned long) &_etext))) { |
148 | if (i % 4 == 0) | 149 | if (i % 4 == 0) |
149 | printk(KERN_EMERG "\n "); | 150 | printk("\n" KERN_EMERG " "); |
150 | printk(KERN_EMERG " [<%08lx>]", addr); | 151 | printk(" [<%08lx>]", addr); |
151 | i++; | 152 | i++; |
152 | } | 153 | } |
153 | } | 154 | } |
154 | printk(KERN_EMERG "\n"); | 155 | printk("\n"); |
155 | } | 156 | } |
156 | 157 | ||
157 | void bad_super_trap(struct frame *fp) | 158 | void bad_super_trap(struct frame *fp) |
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S index f2edb6498cd9..b9aa0ca29bfb 100644 --- a/arch/m68knommu/platform/5307/head.S +++ b/arch/m68knommu/platform/5307/head.S | |||
@@ -64,6 +64,26 @@ | |||
64 | negl %d0 /* negate bits */ | 64 | negl %d0 /* negate bits */ |
65 | .endm | 65 | .endm |
66 | 66 | ||
67 | #elif defined(CONFIG_M520x) | ||
68 | .macro GET_MEM_SIZE | ||
69 | clrl %d0 | ||
70 | movel MCF_MBAR+MCFSIM_SDCS0, %d2 /* Get SDRAM chip select 0 config */ | ||
71 | andl #0x1f, %d2 /* Get only the chip select size */ | ||
72 | beq 3f /* Check if it is enabled */ | ||
73 | addql #1, %d2 /* Form exponent */ | ||
74 | moveql #1, %d0 | ||
75 | lsll %d2, %d0 /* 2 ^ exponent */ | ||
76 | 3: | ||
77 | movel MCF_MBAR+MCFSIM_SDCS1, %d2 /* Get SDRAM chip select 1 config */ | ||
78 | andl #0x1f, %d2 /* Get only the chip select size */ | ||
79 | beq 4f /* Check if it is enabled */ | ||
80 | addql #1, %d2 /* Form exponent */ | ||
81 | moveql #1, %d1 | ||
82 | lsll %d2, %d1 /* 2 ^ exponent */ | ||
83 | addl %d1, %d0 /* Total size of SDRAM in d0 */ | ||
84 | 4: | ||
85 | .endm | ||
86 | |||
67 | #else | 87 | #else |
68 | #error "ERROR: I don't know how to probe your boards memory size?" | 88 | #error "ERROR: I don't know how to probe your boards memory size?" |
69 | #endif | 89 | #endif |
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S index 2ea51479f13a..2ef06242398b 100644 --- a/arch/m68knommu/platform/68360/head-ram.S +++ b/arch/m68knommu/platform/68360/head-ram.S | |||
@@ -25,6 +25,7 @@ | |||
25 | .global _periph_base | 25 | .global _periph_base |
26 | 26 | ||
27 | #define RAMEND (CONFIG_RAMBASE + CONFIG_RAMSIZE) | 27 | #define RAMEND (CONFIG_RAMBASE + CONFIG_RAMSIZE) |
28 | #define ROMEND (CONFIG_ROMBASE + CONFIG_ROMSIZE) | ||
28 | 29 | ||
29 | #define REGB 0x1000 | 30 | #define REGB 0x1000 |
30 | #define PEPAR (_dprbase + REGB + 0x0016) | 31 | #define PEPAR (_dprbase + REGB + 0x0016) |
@@ -175,7 +176,7 @@ configure_chip_select_0: | |||
175 | move.l %d0, BR0 | 176 | move.l %d0, BR0 |
176 | 177 | ||
177 | configure_chip_select_1: | 178 | configure_chip_select_1: |
178 | move.l #__rom_end, %d0 | 179 | move.l #ROMEND, %d0 |
179 | subi.l #__rom_start, %d0 | 180 | subi.l #__rom_start, %d0 |
180 | subq.l #0x01, %d0 | 181 | subq.l #0x01, %d0 |
181 | eori.l #SIM_OR_MASK, %d0 | 182 | eori.l #SIM_OR_MASK, %d0 |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 245b81bc7157..583d9ff0a571 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -33,9 +33,6 @@ config GENERIC_CALIBRATE_DELAY | |||
33 | config GENERIC_TIME | 33 | config GENERIC_TIME |
34 | def_bool y | 34 | def_bool y |
35 | 35 | ||
36 | config GENERIC_BUST_SPINLOCK | ||
37 | bool | ||
38 | |||
39 | mainmenu "Linux Kernel Configuration" | 36 | mainmenu "Linux Kernel Configuration" |
40 | 37 | ||
41 | config S390 | 38 | config S390 |
@@ -181,7 +178,7 @@ config PACK_STACK | |||
181 | 178 | ||
182 | config SMALL_STACK | 179 | config SMALL_STACK |
183 | bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb" | 180 | bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb" |
184 | depends on PACK_STACK | 181 | depends on PACK_STACK && !LOCKDEP |
185 | help | 182 | help |
186 | If you say Y here and the compiler supports the -mkernel-backchain | 183 | If you say Y here and the compiler supports the -mkernel-backchain |
187 | option the kernel will use a smaller kernel stack size. For 31 bit | 184 | option the kernel will use a smaller kernel stack size. For 31 bit |
diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 5deb9f7544a1..6598e5268573 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile | |||
@@ -35,6 +35,9 @@ cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900) | |||
35 | cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) | 35 | cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) |
36 | cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109) | 36 | cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109) |
37 | 37 | ||
38 | #KBUILD_IMAGE is necessary for make rpm | ||
39 | KBUILD_IMAGE :=arch/s390/boot/image | ||
40 | |||
38 | # | 41 | # |
39 | # Prevent tail-call optimizations, to get clearer backtraces: | 42 | # Prevent tail-call optimizations, to get clearer backtraces: |
40 | # | 43 | # |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index aa978978d3d1..a81881c9b297 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | EXTRA_AFLAGS := -traditional | 5 | EXTRA_AFLAGS := -traditional |
6 | 6 | ||
7 | obj-y := bitmap.o traps.o time.o process.o \ | 7 | obj-y := bitmap.o traps.o time.o process.o reset.o \ |
8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ | 8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ |
9 | semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o | 9 | semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o |
10 | 10 | ||
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index 1eae74e72f95..a5972f1541fe 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c | |||
@@ -21,14 +21,15 @@ static DEFINE_SPINLOCK(cpcmd_lock); | |||
21 | static char cpcmd_buf[241]; | 21 | static char cpcmd_buf[241]; |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * the caller of __cpcmd has to ensure that the response buffer is below 2 GB | 24 | * __cpcmd has some restrictions over cpcmd |
25 | * - the response buffer must reside below 2GB (if any) | ||
26 | * - __cpcmd is unlocked and therefore not SMP-safe | ||
25 | */ | 27 | */ |
26 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | 28 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) |
27 | { | 29 | { |
28 | unsigned long flags, cmdlen; | 30 | unsigned cmdlen; |
29 | int return_code, return_len; | 31 | int return_code, return_len; |
30 | 32 | ||
31 | spin_lock_irqsave(&cpcmd_lock, flags); | ||
32 | cmdlen = strlen(cmd); | 33 | cmdlen = strlen(cmd); |
33 | BUG_ON(cmdlen > 240); | 34 | BUG_ON(cmdlen > 240); |
34 | memcpy(cpcmd_buf, cmd, cmdlen); | 35 | memcpy(cpcmd_buf, cmd, cmdlen); |
@@ -74,7 +75,6 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
74 | : "+d" (reg3) : "d" (reg2) : "cc"); | 75 | : "+d" (reg3) : "d" (reg2) : "cc"); |
75 | return_code = (int) reg3; | 76 | return_code = (int) reg3; |
76 | } | 77 | } |
77 | spin_unlock_irqrestore(&cpcmd_lock, flags); | ||
78 | if (response_code != NULL) | 78 | if (response_code != NULL) |
79 | *response_code = return_code; | 79 | *response_code = return_code; |
80 | return return_len; | 80 | return return_len; |
@@ -82,15 +82,18 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
82 | 82 | ||
83 | EXPORT_SYMBOL(__cpcmd); | 83 | EXPORT_SYMBOL(__cpcmd); |
84 | 84 | ||
85 | #ifdef CONFIG_64BIT | ||
86 | int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | 85 | int cpcmd(const char *cmd, char *response, int rlen, int *response_code) |
87 | { | 86 | { |
88 | char *lowbuf; | 87 | char *lowbuf; |
89 | int len; | 88 | int len; |
89 | unsigned long flags; | ||
90 | 90 | ||
91 | if ((rlen == 0) || (response == NULL) | 91 | if ((rlen == 0) || (response == NULL) |
92 | || !((unsigned long)response >> 31)) | 92 | || !((unsigned long)response >> 31)) { |
93 | spin_lock_irqsave(&cpcmd_lock, flags); | ||
93 | len = __cpcmd(cmd, response, rlen, response_code); | 94 | len = __cpcmd(cmd, response, rlen, response_code); |
95 | spin_unlock_irqrestore(&cpcmd_lock, flags); | ||
96 | } | ||
94 | else { | 97 | else { |
95 | lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); | 98 | lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); |
96 | if (!lowbuf) { | 99 | if (!lowbuf) { |
@@ -98,7 +101,9 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
98 | "cpcmd: could not allocate response buffer\n"); | 101 | "cpcmd: could not allocate response buffer\n"); |
99 | return -ENOMEM; | 102 | return -ENOMEM; |
100 | } | 103 | } |
104 | spin_lock_irqsave(&cpcmd_lock, flags); | ||
101 | len = __cpcmd(cmd, lowbuf, rlen, response_code); | 105 | len = __cpcmd(cmd, lowbuf, rlen, response_code); |
106 | spin_unlock_irqrestore(&cpcmd_lock, flags); | ||
102 | memcpy(response, lowbuf, rlen); | 107 | memcpy(response, lowbuf, rlen); |
103 | kfree(lowbuf); | 108 | kfree(lowbuf); |
104 | } | 109 | } |
@@ -106,4 +111,3 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
106 | } | 111 | } |
107 | 112 | ||
108 | EXPORT_SYMBOL(cpcmd); | 113 | EXPORT_SYMBOL(cpcmd); |
109 | #endif /* CONFIG_64BIT */ | ||
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 0cf59bb7a857..8f8c802f1bcf 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
@@ -418,24 +418,6 @@ start: | |||
418 | .gotr: | 418 | .gotr: |
419 | l %r10,.tbl # EBCDIC to ASCII table | 419 | l %r10,.tbl # EBCDIC to ASCII table |
420 | tr 0(240,%r8),0(%r10) | 420 | tr 0(240,%r8),0(%r10) |
421 | stidp __LC_CPUID # Are we running on VM maybe | ||
422 | cli __LC_CPUID,0xff | ||
423 | bnz .test | ||
424 | .long 0x83300060 # diag 3,0,x'0060' - storage size | ||
425 | b .done | ||
426 | .test: | ||
427 | mvc 0x68(8),.pgmnw # set up pgm check handler | ||
428 | l %r2,.fourmeg | ||
429 | lr %r3,%r2 | ||
430 | bctr %r3,%r0 # 4M-1 | ||
431 | .loop: iske %r0,%r3 | ||
432 | ar %r3,%r2 | ||
433 | .pgmx: | ||
434 | sr %r3,%r2 | ||
435 | la %r3,1(%r3) | ||
436 | .done: | ||
437 | l %r1,.memsize | ||
438 | st %r3,ARCH_OFFSET(%r1) | ||
439 | slr %r0,%r0 | 421 | slr %r0,%r0 |
440 | st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11) | 422 | st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11) |
441 | st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11) | 423 | st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11) |
@@ -443,9 +425,6 @@ start: | |||
443 | .tbl: .long _ebcasc # translate table | 425 | .tbl: .long _ebcasc # translate table |
444 | .cmd: .long COMMAND_LINE # address of command line buffer | 426 | .cmd: .long COMMAND_LINE # address of command line buffer |
445 | .parm: .long PARMAREA | 427 | .parm: .long PARMAREA |
446 | .memsize: .long memory_size | ||
447 | .fourmeg: .long 0x00400000 # 4M | ||
448 | .pgmnw: .long 0x00080000,.pgmx | ||
449 | .lowcase: | 428 | .lowcase: |
450 | .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 | 429 | .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 |
451 | .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f | 430 | .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f |
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 0a2c929486ab..4388b3309e0c 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S | |||
@@ -131,10 +131,11 @@ startup_continue: | |||
131 | .long init_thread_union | 131 | .long init_thread_union |
132 | .Lpmask: | 132 | .Lpmask: |
133 | .byte 0 | 133 | .byte 0 |
134 | .align 8 | 134 | .align 8 |
135 | .Lpcext:.long 0x00080000,0x80000000 | 135 | .Lpcext:.long 0x00080000,0x80000000 |
136 | .Lcr: | 136 | .Lcr: |
137 | .long 0x00 # place holder for cr0 | 137 | .long 0x00 # place holder for cr0 |
138 | .align 8 | ||
138 | .Lwaitsclp: | 139 | .Lwaitsclp: |
139 | .long 0x010a0000,0x80000000 + .Lsclph | 140 | .long 0x010a0000,0x80000000 + .Lsclph |
140 | .Lrcp: | 141 | .Lrcp: |
@@ -156,7 +157,7 @@ startup_continue: | |||
156 | slr %r4,%r4 # set start of chunk to zero | 157 | slr %r4,%r4 # set start of chunk to zero |
157 | slr %r5,%r5 # set end of chunk to zero | 158 | slr %r5,%r5 # set end of chunk to zero |
158 | slr %r6,%r6 # set access code to zero | 159 | slr %r6,%r6 # set access code to zero |
159 | la %r10, MEMORY_CHUNKS # number of chunks | 160 | la %r10,MEMORY_CHUNKS # number of chunks |
160 | .Lloop: | 161 | .Lloop: |
161 | tprot 0(%r5),0 # test protection of first byte | 162 | tprot 0(%r5),0 # test protection of first byte |
162 | ipm %r7 | 163 | ipm %r7 |
@@ -176,8 +177,6 @@ startup_continue: | |||
176 | st %r0,4(%r3) # store size of chunk | 177 | st %r0,4(%r3) # store size of chunk |
177 | st %r6,8(%r3) # store type of chunk | 178 | st %r6,8(%r3) # store type of chunk |
178 | la %r3,12(%r3) | 179 | la %r3,12(%r3) |
179 | l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size | ||
180 | st %r5,0(%r4) # store last end to memory size | ||
181 | ahi %r10,-1 # update chunk number | 180 | ahi %r10,-1 # update chunk number |
182 | .Lchkloop: | 181 | .Lchkloop: |
183 | lr %r6,%r7 # set access code to last cc | 182 | lr %r6,%r7 # set access code to last cc |
@@ -292,7 +291,6 @@ startup_continue: | |||
292 | .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg | 291 | .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg |
293 | .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte | 292 | .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte |
294 | .Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c | 293 | .Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c |
295 | .Lmemsize:.long memory_size | ||
296 | .Lmchunk:.long memory_chunk | 294 | .Lmchunk:.long memory_chunk |
297 | .Lmflags:.long machine_flags | 295 | .Lmflags:.long machine_flags |
298 | .Lbss_bgn: .long __bss_start | 296 | .Lbss_bgn: .long __bss_start |
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 42f54d482441..c526279e1123 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S | |||
@@ -70,7 +70,20 @@ startup_continue: | |||
70 | sgr %r5,%r5 # set src,length and pad to zero | 70 | sgr %r5,%r5 # set src,length and pad to zero |
71 | mvcle %r2,%r4,0 # clear mem | 71 | mvcle %r2,%r4,0 # clear mem |
72 | jo .-4 # branch back, if not finish | 72 | jo .-4 # branch back, if not finish |
73 | # set program check new psw mask | ||
74 | mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) | ||
75 | larl %r1,.Lslowmemdetect # set program check address | ||
76 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
77 | lghi %r1,0xc | ||
78 | diag %r0,%r1,0x260 # get memory size of virtual machine | ||
79 | cgr %r0,%r1 # different? -> old detection routine | ||
80 | jne .Lslowmemdetect | ||
81 | aghi %r1,1 # size is one more than end | ||
82 | larl %r2,memory_chunk | ||
83 | stg %r1,8(%r2) # store size of chunk | ||
84 | j .Ldonemem | ||
73 | 85 | ||
86 | .Lslowmemdetect: | ||
74 | l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word | 87 | l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word |
75 | .Lservicecall: | 88 | .Lservicecall: |
76 | stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts | 89 | stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts |
@@ -139,8 +152,6 @@ startup_continue: | |||
139 | .int 0x100000 | 152 | .int 0x100000 |
140 | 153 | ||
141 | .Lfchunk: | 154 | .Lfchunk: |
142 | # set program check new psw mask | ||
143 | mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) | ||
144 | 155 | ||
145 | # | 156 | # |
146 | # find memory chunks. | 157 | # find memory chunks. |
@@ -175,8 +186,6 @@ startup_continue: | |||
175 | stg %r0,8(%r3) # store size of chunk | 186 | stg %r0,8(%r3) # store size of chunk |
176 | st %r6,20(%r3) # store type of chunk | 187 | st %r6,20(%r3) # store type of chunk |
177 | la %r3,24(%r3) | 188 | la %r3,24(%r3) |
178 | larl %r8,memory_size | ||
179 | stg %r5,0(%r8) # store memory size | ||
180 | ahi %r10,-1 # update chunk number | 189 | ahi %r10,-1 # update chunk number |
181 | .Lchkloop: | 190 | .Lchkloop: |
182 | lr %r6,%r7 # set access code to last cc | 191 | lr %r6,%r7 # set access code to last cc |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 1f5e782b3d05..a36bea1188d9 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -13,12 +13,21 @@ | |||
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/reboot.h> | 15 | #include <linux/reboot.h> |
16 | #include <linux/ctype.h> | ||
16 | #include <asm/smp.h> | 17 | #include <asm/smp.h> |
17 | #include <asm/setup.h> | 18 | #include <asm/setup.h> |
18 | #include <asm/cpcmd.h> | 19 | #include <asm/cpcmd.h> |
19 | #include <asm/cio.h> | 20 | #include <asm/cio.h> |
21 | #include <asm/ebcdic.h> | ||
22 | #include <asm/reset.h> | ||
20 | 23 | ||
21 | #define IPL_PARM_BLOCK_VERSION 0 | 24 | #define IPL_PARM_BLOCK_VERSION 0 |
25 | #define LOADPARM_LEN 8 | ||
26 | |||
27 | extern char s390_readinfo_sccb[]; | ||
28 | #define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010) | ||
29 | #define SCCB_LOADPARM (&s390_readinfo_sccb[24]) | ||
30 | #define SCCB_FLAG (s390_readinfo_sccb[91]) | ||
22 | 31 | ||
23 | enum ipl_type { | 32 | enum ipl_type { |
24 | IPL_TYPE_NONE = 1, | 33 | IPL_TYPE_NONE = 1, |
@@ -289,9 +298,25 @@ static struct attribute_group ipl_fcp_attr_group = { | |||
289 | 298 | ||
290 | /* CCW ipl device attributes */ | 299 | /* CCW ipl device attributes */ |
291 | 300 | ||
301 | static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page) | ||
302 | { | ||
303 | char loadparm[LOADPARM_LEN + 1] = {}; | ||
304 | |||
305 | if (!SCCB_VALID) | ||
306 | return sprintf(page, "#unknown#\n"); | ||
307 | memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN); | ||
308 | EBCASC(loadparm, LOADPARM_LEN); | ||
309 | strstrip(loadparm); | ||
310 | return sprintf(page, "%s\n", loadparm); | ||
311 | } | ||
312 | |||
313 | static struct subsys_attribute sys_ipl_ccw_loadparm_attr = | ||
314 | __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); | ||
315 | |||
292 | static struct attribute *ipl_ccw_attrs[] = { | 316 | static struct attribute *ipl_ccw_attrs[] = { |
293 | &sys_ipl_type_attr.attr, | 317 | &sys_ipl_type_attr.attr, |
294 | &sys_ipl_device_attr.attr, | 318 | &sys_ipl_device_attr.attr, |
319 | &sys_ipl_ccw_loadparm_attr.attr, | ||
295 | NULL, | 320 | NULL, |
296 | }; | 321 | }; |
297 | 322 | ||
@@ -348,8 +373,57 @@ static struct attribute_group reipl_fcp_attr_group = { | |||
348 | DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", | 373 | DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", |
349 | reipl_block_ccw->ipl_info.ccw.devno); | 374 | reipl_block_ccw->ipl_info.ccw.devno); |
350 | 375 | ||
376 | static void reipl_get_ascii_loadparm(char *loadparm) | ||
377 | { | ||
378 | memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param, | ||
379 | LOADPARM_LEN); | ||
380 | EBCASC(loadparm, LOADPARM_LEN); | ||
381 | loadparm[LOADPARM_LEN] = 0; | ||
382 | strstrip(loadparm); | ||
383 | } | ||
384 | |||
385 | static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page) | ||
386 | { | ||
387 | char buf[LOADPARM_LEN + 1]; | ||
388 | |||
389 | reipl_get_ascii_loadparm(buf); | ||
390 | return sprintf(page, "%s\n", buf); | ||
391 | } | ||
392 | |||
393 | static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys, | ||
394 | const char *buf, size_t len) | ||
395 | { | ||
396 | int i, lp_len; | ||
397 | |||
398 | /* ignore trailing newline */ | ||
399 | lp_len = len; | ||
400 | if ((len > 0) && (buf[len - 1] == '\n')) | ||
401 | lp_len--; | ||
402 | /* loadparm can have max 8 characters and must not start with a blank */ | ||
403 | if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' '))) | ||
404 | return -EINVAL; | ||
405 | /* loadparm can only contain "a-z,A-Z,0-9,SP,." */ | ||
406 | for (i = 0; i < lp_len; i++) { | ||
407 | if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') || | ||
408 | (buf[i] == '.')) | ||
409 | continue; | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | /* initialize loadparm with blanks */ | ||
413 | memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN); | ||
414 | /* copy and convert to ebcdic */ | ||
415 | memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len); | ||
416 | ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN); | ||
417 | return len; | ||
418 | } | ||
419 | |||
420 | static struct subsys_attribute sys_reipl_ccw_loadparm_attr = | ||
421 | __ATTR(loadparm, 0644, reipl_ccw_loadparm_show, | ||
422 | reipl_ccw_loadparm_store); | ||
423 | |||
351 | static struct attribute *reipl_ccw_attrs[] = { | 424 | static struct attribute *reipl_ccw_attrs[] = { |
352 | &sys_reipl_ccw_device_attr.attr, | 425 | &sys_reipl_ccw_device_attr.attr, |
426 | &sys_reipl_ccw_loadparm_attr.attr, | ||
353 | NULL, | 427 | NULL, |
354 | }; | 428 | }; |
355 | 429 | ||
@@ -502,23 +576,6 @@ static struct subsys_attribute dump_type_attr = | |||
502 | 576 | ||
503 | static decl_subsys(dump, NULL, NULL); | 577 | static decl_subsys(dump, NULL, NULL); |
504 | 578 | ||
505 | #ifdef CONFIG_SMP | ||
506 | static void dump_smp_stop_all(void) | ||
507 | { | ||
508 | int cpu; | ||
509 | preempt_disable(); | ||
510 | for_each_online_cpu(cpu) { | ||
511 | if (cpu == smp_processor_id()) | ||
512 | continue; | ||
513 | while (signal_processor(cpu, sigp_stop) == sigp_busy) | ||
514 | udelay(10); | ||
515 | } | ||
516 | preempt_enable(); | ||
517 | } | ||
518 | #else | ||
519 | #define dump_smp_stop_all() do { } while (0) | ||
520 | #endif | ||
521 | |||
522 | /* | 579 | /* |
523 | * Shutdown actions section | 580 | * Shutdown actions section |
524 | */ | 581 | */ |
@@ -571,11 +628,14 @@ void do_reipl(void) | |||
571 | { | 628 | { |
572 | struct ccw_dev_id devid; | 629 | struct ccw_dev_id devid; |
573 | static char buf[100]; | 630 | static char buf[100]; |
631 | char loadparm[LOADPARM_LEN + 1]; | ||
574 | 632 | ||
575 | switch (reipl_type) { | 633 | switch (reipl_type) { |
576 | case IPL_TYPE_CCW: | 634 | case IPL_TYPE_CCW: |
635 | reipl_get_ascii_loadparm(loadparm); | ||
577 | printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n", | 636 | printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n", |
578 | reipl_block_ccw->ipl_info.ccw.devno); | 637 | reipl_block_ccw->ipl_info.ccw.devno); |
638 | printk(KERN_EMERG "loadparm = '%s'\n", loadparm); | ||
579 | break; | 639 | break; |
580 | case IPL_TYPE_FCP: | 640 | case IPL_TYPE_FCP: |
581 | printk(KERN_EMERG "reboot on fcp device:\n"); | 641 | printk(KERN_EMERG "reboot on fcp device:\n"); |
@@ -588,12 +648,19 @@ void do_reipl(void) | |||
588 | switch (reipl_method) { | 648 | switch (reipl_method) { |
589 | case IPL_METHOD_CCW_CIO: | 649 | case IPL_METHOD_CCW_CIO: |
590 | devid.devno = reipl_block_ccw->ipl_info.ccw.devno; | 650 | devid.devno = reipl_block_ccw->ipl_info.ccw.devno; |
651 | if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno) | ||
652 | diag308(DIAG308_IPL, NULL); | ||
591 | devid.ssid = 0; | 653 | devid.ssid = 0; |
592 | reipl_ccw_dev(&devid); | 654 | reipl_ccw_dev(&devid); |
593 | break; | 655 | break; |
594 | case IPL_METHOD_CCW_VM: | 656 | case IPL_METHOD_CCW_VM: |
595 | sprintf(buf, "IPL %X", reipl_block_ccw->ipl_info.ccw.devno); | 657 | if (strlen(loadparm) == 0) |
596 | cpcmd(buf, NULL, 0, NULL); | 658 | sprintf(buf, "IPL %X", |
659 | reipl_block_ccw->ipl_info.ccw.devno); | ||
660 | else | ||
661 | sprintf(buf, "IPL %X LOADPARM '%s'", | ||
662 | reipl_block_ccw->ipl_info.ccw.devno, loadparm); | ||
663 | __cpcmd(buf, NULL, 0, NULL); | ||
597 | break; | 664 | break; |
598 | case IPL_METHOD_CCW_DIAG: | 665 | case IPL_METHOD_CCW_DIAG: |
599 | diag308(DIAG308_SET, reipl_block_ccw); | 666 | diag308(DIAG308_SET, reipl_block_ccw); |
@@ -607,16 +674,17 @@ void do_reipl(void) | |||
607 | diag308(DIAG308_IPL, NULL); | 674 | diag308(DIAG308_IPL, NULL); |
608 | break; | 675 | break; |
609 | case IPL_METHOD_FCP_RO_VM: | 676 | case IPL_METHOD_FCP_RO_VM: |
610 | cpcmd("IPL", NULL, 0, NULL); | 677 | __cpcmd("IPL", NULL, 0, NULL); |
611 | break; | 678 | break; |
612 | case IPL_METHOD_NONE: | 679 | case IPL_METHOD_NONE: |
613 | default: | 680 | default: |
614 | if (MACHINE_IS_VM) | 681 | if (MACHINE_IS_VM) |
615 | cpcmd("IPL", NULL, 0, NULL); | 682 | __cpcmd("IPL", NULL, 0, NULL); |
616 | diag308(DIAG308_IPL, NULL); | 683 | diag308(DIAG308_IPL, NULL); |
617 | break; | 684 | break; |
618 | } | 685 | } |
619 | panic("reipl failed!\n"); | 686 | printk(KERN_EMERG "reboot failed!\n"); |
687 | signal_processor(smp_processor_id(), sigp_stop_and_store_status); | ||
620 | } | 688 | } |
621 | 689 | ||
622 | static void do_dump(void) | 690 | static void do_dump(void) |
@@ -639,17 +707,17 @@ static void do_dump(void) | |||
639 | 707 | ||
640 | switch (dump_method) { | 708 | switch (dump_method) { |
641 | case IPL_METHOD_CCW_CIO: | 709 | case IPL_METHOD_CCW_CIO: |
642 | dump_smp_stop_all(); | 710 | smp_send_stop(); |
643 | devid.devno = dump_block_ccw->ipl_info.ccw.devno; | 711 | devid.devno = dump_block_ccw->ipl_info.ccw.devno; |
644 | devid.ssid = 0; | 712 | devid.ssid = 0; |
645 | reipl_ccw_dev(&devid); | 713 | reipl_ccw_dev(&devid); |
646 | break; | 714 | break; |
647 | case IPL_METHOD_CCW_VM: | 715 | case IPL_METHOD_CCW_VM: |
648 | dump_smp_stop_all(); | 716 | smp_send_stop(); |
649 | sprintf(buf, "STORE STATUS"); | 717 | sprintf(buf, "STORE STATUS"); |
650 | cpcmd(buf, NULL, 0, NULL); | 718 | __cpcmd(buf, NULL, 0, NULL); |
651 | sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); | 719 | sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); |
652 | cpcmd(buf, NULL, 0, NULL); | 720 | __cpcmd(buf, NULL, 0, NULL); |
653 | break; | 721 | break; |
654 | case IPL_METHOD_CCW_DIAG: | 722 | case IPL_METHOD_CCW_DIAG: |
655 | diag308(DIAG308_SET, dump_block_ccw); | 723 | diag308(DIAG308_SET, dump_block_ccw); |
@@ -746,6 +814,17 @@ static int __init reipl_ccw_init(void) | |||
746 | reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; | 814 | reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; |
747 | reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw); | 815 | reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw); |
748 | reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; | 816 | reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; |
817 | /* check if read scp info worked and set loadparm */ | ||
818 | if (SCCB_VALID) | ||
819 | memcpy(reipl_block_ccw->ipl_info.ccw.load_param, | ||
820 | SCCB_LOADPARM, LOADPARM_LEN); | ||
821 | else | ||
822 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ | ||
823 | memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, | ||
824 | LOADPARM_LEN); | ||
825 | /* FIXME: check for diag308_set_works when enabling diag ccw reipl */ | ||
826 | if (!MACHINE_IS_VM) | ||
827 | sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO; | ||
749 | if (ipl_get_type() == IPL_TYPE_CCW) | 828 | if (ipl_get_type() == IPL_TYPE_CCW) |
750 | reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; | 829 | reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; |
751 | reipl_capabilities |= IPL_TYPE_CCW; | 830 | reipl_capabilities |= IPL_TYPE_CCW; |
@@ -827,13 +906,11 @@ static int __init dump_ccw_init(void) | |||
827 | return 0; | 906 | return 0; |
828 | } | 907 | } |
829 | 908 | ||
830 | extern char s390_readinfo_sccb[]; | ||
831 | |||
832 | static int __init dump_fcp_init(void) | 909 | static int __init dump_fcp_init(void) |
833 | { | 910 | { |
834 | int rc; | 911 | int rc; |
835 | 912 | ||
836 | if(!(s390_readinfo_sccb[91] & 0x2)) | 913 | if(!(SCCB_FLAG & 0x2) || !SCCB_VALID) |
837 | return 0; /* LDIPL DUMP is not installed */ | 914 | return 0; /* LDIPL DUMP is not installed */ |
838 | if (!diag308_set_works) | 915 | if (!diag308_set_works) |
839 | return 0; | 916 | return 0; |
@@ -931,3 +1008,53 @@ static int __init s390_ipl_init(void) | |||
931 | } | 1008 | } |
932 | 1009 | ||
933 | __initcall(s390_ipl_init); | 1010 | __initcall(s390_ipl_init); |
1011 | |||
1012 | static LIST_HEAD(rcall); | ||
1013 | static DEFINE_MUTEX(rcall_mutex); | ||
1014 | |||
1015 | void register_reset_call(struct reset_call *reset) | ||
1016 | { | ||
1017 | mutex_lock(&rcall_mutex); | ||
1018 | list_add(&reset->list, &rcall); | ||
1019 | mutex_unlock(&rcall_mutex); | ||
1020 | } | ||
1021 | EXPORT_SYMBOL_GPL(register_reset_call); | ||
1022 | |||
1023 | void unregister_reset_call(struct reset_call *reset) | ||
1024 | { | ||
1025 | mutex_lock(&rcall_mutex); | ||
1026 | list_del(&reset->list); | ||
1027 | mutex_unlock(&rcall_mutex); | ||
1028 | } | ||
1029 | EXPORT_SYMBOL_GPL(unregister_reset_call); | ||
1030 | |||
1031 | static void do_reset_calls(void) | ||
1032 | { | ||
1033 | struct reset_call *reset; | ||
1034 | |||
1035 | list_for_each_entry(reset, &rcall, list) | ||
1036 | reset->fn(); | ||
1037 | } | ||
1038 | |||
1039 | extern void reset_mcck_handler(void); | ||
1040 | |||
1041 | void s390_reset_system(void) | ||
1042 | { | ||
1043 | struct _lowcore *lc; | ||
1044 | |||
1045 | /* Stack for interrupt/machine check handler */ | ||
1046 | lc = (struct _lowcore *)(unsigned long) store_prefix(); | ||
1047 | lc->panic_stack = S390_lowcore.panic_stack; | ||
1048 | |||
1049 | /* Disable prefixing */ | ||
1050 | set_prefix(0); | ||
1051 | |||
1052 | /* Disable lowcore protection */ | ||
1053 | __ctl_clear_bit(0,28); | ||
1054 | |||
1055 | /* Set new machine check handler */ | ||
1056 | S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK; | ||
1057 | S390_lowcore.mcck_new_psw.addr = | ||
1058 | PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler; | ||
1059 | do_reset_calls(); | ||
1060 | } | ||
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 60b1ea9f946b..f6d9bcc0f75b 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c | |||
@@ -1,15 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/machine_kexec.c | 2 | * arch/s390/kernel/machine_kexec.c |
3 | * | 3 | * |
4 | * (C) Copyright IBM Corp. 2005 | 4 | * Copyright IBM Corp. 2005,2006 |
5 | * | 5 | * |
6 | * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com> | 6 | * Author(s): Rolf Adelsberger, |
7 | * | 7 | * Heiko Carstens <heiko.carstens@de.ibm.com> |
8 | */ | ||
9 | |||
10 | /* | ||
11 | * s390_machine_kexec.c - handle the transition of Linux booting another kernel | ||
12 | * on the S390 architecture. | ||
13 | */ | 8 | */ |
14 | 9 | ||
15 | #include <linux/device.h> | 10 | #include <linux/device.h> |
@@ -22,86 +17,49 @@ | |||
22 | #include <asm/pgalloc.h> | 17 | #include <asm/pgalloc.h> |
23 | #include <asm/system.h> | 18 | #include <asm/system.h> |
24 | #include <asm/smp.h> | 19 | #include <asm/smp.h> |
20 | #include <asm/reset.h> | ||
25 | 21 | ||
26 | static void kexec_halt_all_cpus(void *); | 22 | typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long); |
27 | |||
28 | typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long); | ||
29 | 23 | ||
30 | extern const unsigned char relocate_kernel[]; | 24 | extern const unsigned char relocate_kernel[]; |
31 | extern const unsigned long long relocate_kernel_len; | 25 | extern const unsigned long long relocate_kernel_len; |
32 | 26 | ||
33 | int | 27 | int machine_kexec_prepare(struct kimage *image) |
34 | machine_kexec_prepare(struct kimage *image) | ||
35 | { | 28 | { |
36 | unsigned long reboot_code_buffer; | 29 | void *reboot_code_buffer; |
37 | 30 | ||
38 | /* We don't support anything but the default image type for now. */ | 31 | /* We don't support anything but the default image type for now. */ |
39 | if (image->type != KEXEC_TYPE_DEFAULT) | 32 | if (image->type != KEXEC_TYPE_DEFAULT) |
40 | return -EINVAL; | 33 | return -EINVAL; |
41 | 34 | ||
42 | /* Get the destination where the assembler code should be copied to.*/ | 35 | /* Get the destination where the assembler code should be copied to.*/ |
43 | reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT; | 36 | reboot_code_buffer = (void *) page_to_phys(image->control_code_page); |
44 | 37 | ||
45 | /* Then copy it */ | 38 | /* Then copy it */ |
46 | memcpy((void *) reboot_code_buffer, relocate_kernel, | 39 | memcpy(reboot_code_buffer, relocate_kernel, relocate_kernel_len); |
47 | relocate_kernel_len); | ||
48 | return 0; | 40 | return 0; |
49 | } | 41 | } |
50 | 42 | ||
51 | void | 43 | void machine_kexec_cleanup(struct kimage *image) |
52 | machine_kexec_cleanup(struct kimage *image) | ||
53 | { | 44 | { |
54 | } | 45 | } |
55 | 46 | ||
56 | void | 47 | void machine_shutdown(void) |
57 | machine_shutdown(void) | ||
58 | { | 48 | { |
59 | printk(KERN_INFO "kexec: machine_shutdown called\n"); | 49 | printk(KERN_INFO "kexec: machine_shutdown called\n"); |
60 | } | 50 | } |
61 | 51 | ||
62 | NORET_TYPE void | 52 | void machine_kexec(struct kimage *image) |
63 | machine_kexec(struct kimage *image) | ||
64 | { | 53 | { |
65 | clear_all_subchannels(); | ||
66 | cio_reset_channel_paths(); | ||
67 | |||
68 | /* Disable lowcore protection */ | ||
69 | ctl_clear_bit(0,28); | ||
70 | |||
71 | on_each_cpu(kexec_halt_all_cpus, image, 0, 0); | ||
72 | for (;;); | ||
73 | } | ||
74 | |||
75 | extern void pfault_fini(void); | ||
76 | |||
77 | static void | ||
78 | kexec_halt_all_cpus(void *kernel_image) | ||
79 | { | ||
80 | static atomic_t cpuid = ATOMIC_INIT(-1); | ||
81 | int cpu; | ||
82 | struct kimage *image; | ||
83 | relocate_kernel_t data_mover; | 54 | relocate_kernel_t data_mover; |
84 | 55 | ||
85 | #ifdef CONFIG_PFAULT | 56 | smp_send_stop(); |
86 | if (MACHINE_IS_VM) | 57 | pfault_fini(); |
87 | pfault_fini(); | 58 | s390_reset_system(); |
88 | #endif | ||
89 | 59 | ||
90 | if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) | 60 | data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page); |
91 | signal_processor(smp_processor_id(), sigp_stop); | ||
92 | |||
93 | /* Wait for all other cpus to enter stopped state */ | ||
94 | for_each_online_cpu(cpu) { | ||
95 | if (cpu == smp_processor_id()) | ||
96 | continue; | ||
97 | while (!smp_cpu_not_running(cpu)) | ||
98 | cpu_relax(); | ||
99 | } | ||
100 | |||
101 | image = (struct kimage *) kernel_image; | ||
102 | data_mover = (relocate_kernel_t) | ||
103 | (page_to_pfn(image->control_code_page) << PAGE_SHIFT); | ||
104 | 61 | ||
105 | /* Call the moving routine */ | 62 | /* Call the moving routine */ |
106 | (*data_mover) (&image->head, image->start); | 63 | (*data_mover)(&image->head, image->start); |
64 | for (;;); | ||
107 | } | 65 | } |
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S index 0340477f3b08..f9434d42ce9f 100644 --- a/arch/s390/kernel/reipl.S +++ b/arch/s390/kernel/reipl.S | |||
@@ -11,19 +11,10 @@ | |||
11 | .globl do_reipl_asm | 11 | .globl do_reipl_asm |
12 | do_reipl_asm: basr %r13,0 | 12 | do_reipl_asm: basr %r13,0 |
13 | .Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) | 13 | .Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) |
14 | 14 | .Lpg1: # do store status of all registers | |
15 | # switch off lowcore protection | ||
16 | |||
17 | .Lpg1: stctl %c0,%c0,.Lctlsave1-.Lpg0(%r13) | ||
18 | stctl %c0,%c0,.Lctlsave2-.Lpg0(%r13) | ||
19 | ni .Lctlsave1-.Lpg0(%r13),0xef | ||
20 | lctl %c0,%c0,.Lctlsave1-.Lpg0(%r13) | ||
21 | |||
22 | # do store status of all registers | ||
23 | 15 | ||
24 | stm %r0,%r15,__LC_GPREGS_SAVE_AREA | 16 | stm %r0,%r15,__LC_GPREGS_SAVE_AREA |
25 | stctl %c0,%c15,__LC_CREGS_SAVE_AREA | 17 | stctl %c0,%c15,__LC_CREGS_SAVE_AREA |
26 | mvc __LC_CREGS_SAVE_AREA(4),.Lctlsave2-.Lpg0(%r13) | ||
27 | stam %a0,%a15,__LC_AREGS_SAVE_AREA | 18 | stam %a0,%a15,__LC_AREGS_SAVE_AREA |
28 | stpx __LC_PREFIX_SAVE_AREA | 19 | stpx __LC_PREFIX_SAVE_AREA |
29 | stckc .Lclkcmp-.Lpg0(%r13) | 20 | stckc .Lclkcmp-.Lpg0(%r13) |
@@ -56,8 +47,7 @@ do_reipl_asm: basr %r13,0 | |||
56 | .L002: tm .Liplirb+8-.Lpg0(%r13),0xf3 | 47 | .L002: tm .Liplirb+8-.Lpg0(%r13),0xf3 |
57 | jz .L003 | 48 | jz .L003 |
58 | bas %r14,.Ldisab-.Lpg0(%r13) | 49 | bas %r14,.Ldisab-.Lpg0(%r13) |
59 | .L003: spx .Lnull-.Lpg0(%r13) | 50 | .L003: st %r1,__LC_SUBCHANNEL_ID |
60 | st %r1,__LC_SUBCHANNEL_ID | ||
61 | lpsw 0 | 51 | lpsw 0 |
62 | sigp 0,0,0(6) | 52 | sigp 0,0,0(6) |
63 | .Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) | 53 | .Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) |
@@ -65,9 +55,6 @@ do_reipl_asm: basr %r13,0 | |||
65 | .align 8 | 55 | .align 8 |
66 | .Lclkcmp: .quad 0x0000000000000000 | 56 | .Lclkcmp: .quad 0x0000000000000000 |
67 | .Lall: .long 0xff000000 | 57 | .Lall: .long 0xff000000 |
68 | .Lnull: .long 0x00000000 | ||
69 | .Lctlsave1: .long 0x00000000 | ||
70 | .Lctlsave2: .long 0x00000000 | ||
71 | .align 8 | 58 | .align 8 |
72 | .Lnewpsw: .long 0x00080000,0x80000000+.Lpg1 | 59 | .Lnewpsw: .long 0x00080000,0x80000000+.Lpg1 |
73 | .Lpcnew: .long 0x00080000,0x80000000+.Lecs | 60 | .Lpcnew: .long 0x00080000,0x80000000+.Lecs |
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S index de7435054f7c..f18ef260ca23 100644 --- a/arch/s390/kernel/reipl64.S +++ b/arch/s390/kernel/reipl64.S | |||
@@ -10,10 +10,10 @@ | |||
10 | #include <asm/lowcore.h> | 10 | #include <asm/lowcore.h> |
11 | .globl do_reipl_asm | 11 | .globl do_reipl_asm |
12 | do_reipl_asm: basr %r13,0 | 12 | do_reipl_asm: basr %r13,0 |
13 | .Lpg0: lpswe .Lnewpsw-.Lpg0(%r13) | ||
14 | .Lpg1: # do store status of all registers | ||
13 | 15 | ||
14 | # do store status of all registers | 16 | stg %r1,.Lregsave-.Lpg0(%r13) |
15 | |||
16 | .Lpg0: stg %r1,.Lregsave-.Lpg0(%r13) | ||
17 | lghi %r1,0x1000 | 17 | lghi %r1,0x1000 |
18 | stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1) | 18 | stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1) |
19 | lg %r0,.Lregsave-.Lpg0(%r13) | 19 | lg %r0,.Lregsave-.Lpg0(%r13) |
@@ -27,11 +27,7 @@ do_reipl_asm: basr %r13,0 | |||
27 | stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) | 27 | stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) |
28 | stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) | 28 | stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) |
29 | 29 | ||
30 | lpswe .Lnewpsw-.Lpg0(%r13) | 30 | lctlg %c6,%c6,.Lall-.Lpg0(%r13) |
31 | .Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13) | ||
32 | stctg %c0,%c0,.Lregsave-.Lpg0(%r13) | ||
33 | ni .Lregsave+4-.Lpg0(%r13),0xef | ||
34 | lctlg %c0,%c0,.Lregsave-.Lpg0(%r13) | ||
35 | lgr %r1,%r2 | 31 | lgr %r1,%r2 |
36 | mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13) | 32 | mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13) |
37 | stsch .Lschib-.Lpg0(%r13) | 33 | stsch .Lschib-.Lpg0(%r13) |
@@ -56,8 +52,7 @@ do_reipl_asm: basr %r13,0 | |||
56 | .L002: tm .Liplirb+8-.Lpg0(%r13),0xf3 | 52 | .L002: tm .Liplirb+8-.Lpg0(%r13),0xf3 |
57 | jz .L003 | 53 | jz .L003 |
58 | bas %r14,.Ldisab-.Lpg0(%r13) | 54 | bas %r14,.Ldisab-.Lpg0(%r13) |
59 | .L003: spx .Lnull-.Lpg0(%r13) | 55 | .L003: st %r1,__LC_SUBCHANNEL_ID |
60 | st %r1,__LC_SUBCHANNEL_ID | ||
61 | lhi %r1,0 # mode 0 = esa | 56 | lhi %r1,0 # mode 0 = esa |
62 | slr %r0,%r0 # set cpuid to zero | 57 | slr %r0,%r0 # set cpuid to zero |
63 | sigp %r1,%r0,0x12 # switch to esa mode | 58 | sigp %r1,%r0,0x12 # switch to esa mode |
@@ -70,7 +65,6 @@ do_reipl_asm: basr %r13,0 | |||
70 | .Lclkcmp: .quad 0x0000000000000000 | 65 | .Lclkcmp: .quad 0x0000000000000000 |
71 | .Lall: .quad 0x00000000ff000000 | 66 | .Lall: .quad 0x00000000ff000000 |
72 | .Lregsave: .quad 0x0000000000000000 | 67 | .Lregsave: .quad 0x0000000000000000 |
73 | .Lnull: .long 0x0000000000000000 | ||
74 | .align 16 | 68 | .align 16 |
75 | /* | 69 | /* |
76 | * These addresses have to be 31 bit otherwise | 70 | * These addresses have to be 31 bit otherwise |
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S index f9899ff2e5b0..3b456b80bcee 100644 --- a/arch/s390/kernel/relocate_kernel.S +++ b/arch/s390/kernel/relocate_kernel.S | |||
@@ -26,8 +26,7 @@ | |||
26 | relocate_kernel: | 26 | relocate_kernel: |
27 | basr %r13,0 # base address | 27 | basr %r13,0 # base address |
28 | .base: | 28 | .base: |
29 | stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQ (external) | 29 | stnsm sys_msk-.base(%r13),0xfb # disable DAT |
30 | spx zero64-.base(%r13) # absolute addressing mode | ||
31 | stctl %c0,%c15,ctlregs-.base(%r13) | 30 | stctl %c0,%c15,ctlregs-.base(%r13) |
32 | stm %r0,%r15,gprregs-.base(%r13) | 31 | stm %r0,%r15,gprregs-.base(%r13) |
33 | la %r1,load_psw-.base(%r13) | 32 | la %r1,load_psw-.base(%r13) |
@@ -97,8 +96,6 @@ | |||
97 | lpsw 0 # hopefully start new kernel... | 96 | lpsw 0 # hopefully start new kernel... |
98 | 97 | ||
99 | .align 8 | 98 | .align 8 |
100 | zero64: | ||
101 | .quad 0 | ||
102 | load_psw: | 99 | load_psw: |
103 | .long 0x00080000,0x80000000 | 100 | .long 0x00080000,0x80000000 |
104 | sys_msk: | 101 | sys_msk: |
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S index 4fb443042d9c..1f9ea2067b59 100644 --- a/arch/s390/kernel/relocate_kernel64.S +++ b/arch/s390/kernel/relocate_kernel64.S | |||
@@ -27,8 +27,7 @@ | |||
27 | relocate_kernel: | 27 | relocate_kernel: |
28 | basr %r13,0 # base address | 28 | basr %r13,0 # base address |
29 | .base: | 29 | .base: |
30 | stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQs | 30 | stnsm sys_msk-.base(%r13),0xfb # disable DAT |
31 | spx zero64-.base(%r13) # absolute addressing mode | ||
32 | stctg %c0,%c15,ctlregs-.base(%r13) | 31 | stctg %c0,%c15,ctlregs-.base(%r13) |
33 | stmg %r0,%r15,gprregs-.base(%r13) | 32 | stmg %r0,%r15,gprregs-.base(%r13) |
34 | lghi %r0,3 | 33 | lghi %r0,3 |
@@ -100,8 +99,6 @@ | |||
100 | lpsw 0 # hopefully start new kernel... | 99 | lpsw 0 # hopefully start new kernel... |
101 | 100 | ||
102 | .align 8 | 101 | .align 8 |
103 | zero64: | ||
104 | .quad 0 | ||
105 | load_psw: | 102 | load_psw: |
106 | .long 0x00080000,0x80000000 | 103 | .long 0x00080000,0x80000000 |
107 | sys_msk: | 104 | sys_msk: |
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S new file mode 100644 index 000000000000..be8688c0665c --- /dev/null +++ b/arch/s390/kernel/reset.S | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * arch/s390/kernel/reset.S | ||
3 | * | ||
4 | * Copyright (C) IBM Corp. 2006 | ||
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <asm/ptrace.h> | ||
9 | #include <asm/lowcore.h> | ||
10 | |||
11 | #ifdef CONFIG_64BIT | ||
12 | |||
13 | .globl reset_mcck_handler | ||
14 | reset_mcck_handler: | ||
15 | basr %r13,0 | ||
16 | 0: lg %r15,__LC_PANIC_STACK # load panic stack | ||
17 | aghi %r15,-STACK_FRAME_OVERHEAD | ||
18 | lg %r1,s390_reset_mcck_handler-0b(%r13) | ||
19 | ltgr %r1,%r1 | ||
20 | jz 1f | ||
21 | basr %r14,%r1 | ||
22 | 1: la %r1,4095 | ||
23 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) | ||
24 | lpswe __LC_MCK_OLD_PSW | ||
25 | |||
26 | .globl s390_reset_mcck_handler | ||
27 | s390_reset_mcck_handler: | ||
28 | .quad 0 | ||
29 | |||
30 | #else /* CONFIG_64BIT */ | ||
31 | |||
32 | .globl reset_mcck_handler | ||
33 | reset_mcck_handler: | ||
34 | basr %r13,0 | ||
35 | 0: l %r15,__LC_PANIC_STACK # load panic stack | ||
36 | ahi %r15,-STACK_FRAME_OVERHEAD | ||
37 | l %r1,s390_reset_mcck_handler-0b(%r13) | ||
38 | ltr %r1,%r1 | ||
39 | jz 1f | ||
40 | basr %r14,%r1 | ||
41 | 1: lm %r0,%r15,__LC_GPREGS_SAVE_AREA | ||
42 | lpsw __LC_MCK_OLD_PSW | ||
43 | |||
44 | .globl s390_reset_mcck_handler | ||
45 | s390_reset_mcck_handler: | ||
46 | .long 0 | ||
47 | |||
48 | #endif /* CONFIG_64BIT */ | ||
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 2aa13e8e000a..b928fecdc743 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -62,13 +62,9 @@ EXPORT_SYMBOL_GPL(uaccess); | |||
62 | unsigned int console_mode = 0; | 62 | unsigned int console_mode = 0; |
63 | unsigned int console_devno = -1; | 63 | unsigned int console_devno = -1; |
64 | unsigned int console_irq = -1; | 64 | unsigned int console_irq = -1; |
65 | unsigned long memory_size = 0; | ||
66 | unsigned long machine_flags = 0; | 65 | unsigned long machine_flags = 0; |
67 | struct { | 66 | |
68 | unsigned long addr, size, type; | 67 | struct mem_chunk memory_chunk[MEMORY_CHUNKS]; |
69 | } memory_chunk[MEMORY_CHUNKS] = { { 0 } }; | ||
70 | #define CHUNK_READ_WRITE 0 | ||
71 | #define CHUNK_READ_ONLY 1 | ||
72 | volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ | 68 | volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ |
73 | unsigned long __initdata zholes_size[MAX_NR_ZONES]; | 69 | unsigned long __initdata zholes_size[MAX_NR_ZONES]; |
74 | static unsigned long __initdata memory_end; | 70 | static unsigned long __initdata memory_end; |
@@ -229,11 +225,11 @@ static void __init conmode_default(void) | |||
229 | char *ptr; | 225 | char *ptr; |
230 | 226 | ||
231 | if (MACHINE_IS_VM) { | 227 | if (MACHINE_IS_VM) { |
232 | __cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL); | 228 | cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL); |
233 | console_devno = simple_strtoul(query_buffer + 5, NULL, 16); | 229 | console_devno = simple_strtoul(query_buffer + 5, NULL, 16); |
234 | ptr = strstr(query_buffer, "SUBCHANNEL ="); | 230 | ptr = strstr(query_buffer, "SUBCHANNEL ="); |
235 | console_irq = simple_strtoul(ptr + 13, NULL, 16); | 231 | console_irq = simple_strtoul(ptr + 13, NULL, 16); |
236 | __cpcmd("QUERY TERM", query_buffer, 1024, NULL); | 232 | cpcmd("QUERY TERM", query_buffer, 1024, NULL); |
237 | ptr = strstr(query_buffer, "CONMODE"); | 233 | ptr = strstr(query_buffer, "CONMODE"); |
238 | /* | 234 | /* |
239 | * Set the conmode to 3215 so that the device recognition | 235 | * Set the conmode to 3215 so that the device recognition |
@@ -242,7 +238,7 @@ static void __init conmode_default(void) | |||
242 | * 3215 and the 3270 driver will try to access the console | 238 | * 3215 and the 3270 driver will try to access the console |
243 | * device (3215 as console and 3270 as normal tty). | 239 | * device (3215 as console and 3270 as normal tty). |
244 | */ | 240 | */ |
245 | __cpcmd("TERM CONMODE 3215", NULL, 0, NULL); | 241 | cpcmd("TERM CONMODE 3215", NULL, 0, NULL); |
246 | if (ptr == NULL) { | 242 | if (ptr == NULL) { |
247 | #if defined(CONFIG_SCLP_CONSOLE) | 243 | #if defined(CONFIG_SCLP_CONSOLE) |
248 | SET_CONSOLE_SCLP; | 244 | SET_CONSOLE_SCLP; |
@@ -299,14 +295,14 @@ static void do_machine_restart_nonsmp(char * __unused) | |||
299 | static void do_machine_halt_nonsmp(void) | 295 | static void do_machine_halt_nonsmp(void) |
300 | { | 296 | { |
301 | if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) | 297 | if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) |
302 | cpcmd(vmhalt_cmd, NULL, 0, NULL); | 298 | __cpcmd(vmhalt_cmd, NULL, 0, NULL); |
303 | signal_processor(smp_processor_id(), sigp_stop_and_store_status); | 299 | signal_processor(smp_processor_id(), sigp_stop_and_store_status); |
304 | } | 300 | } |
305 | 301 | ||
306 | static void do_machine_power_off_nonsmp(void) | 302 | static void do_machine_power_off_nonsmp(void) |
307 | { | 303 | { |
308 | if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) | 304 | if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) |
309 | cpcmd(vmpoff_cmd, NULL, 0, NULL); | 305 | __cpcmd(vmpoff_cmd, NULL, 0, NULL); |
310 | signal_processor(smp_processor_id(), sigp_stop_and_store_status); | 306 | signal_processor(smp_processor_id(), sigp_stop_and_store_status); |
311 | } | 307 | } |
312 | 308 | ||
@@ -489,6 +485,37 @@ setup_resources(void) | |||
489 | } | 485 | } |
490 | } | 486 | } |
491 | 487 | ||
488 | static void __init setup_memory_end(void) | ||
489 | { | ||
490 | unsigned long real_size, memory_size; | ||
491 | unsigned long max_mem, max_phys; | ||
492 | int i; | ||
493 | |||
494 | memory_size = real_size = 0; | ||
495 | max_phys = VMALLOC_END - VMALLOC_MIN_SIZE; | ||
496 | memory_end &= PAGE_MASK; | ||
497 | |||
498 | max_mem = memory_end ? min(max_phys, memory_end) : max_phys; | ||
499 | |||
500 | for (i = 0; i < MEMORY_CHUNKS; i++) { | ||
501 | struct mem_chunk *chunk = &memory_chunk[i]; | ||
502 | |||
503 | real_size = max(real_size, chunk->addr + chunk->size); | ||
504 | if (chunk->addr >= max_mem) { | ||
505 | memset(chunk, 0, sizeof(*chunk)); | ||
506 | continue; | ||
507 | } | ||
508 | if (chunk->addr + chunk->size > max_mem) | ||
509 | chunk->size = max_mem - chunk->addr; | ||
510 | memory_size = max(memory_size, chunk->addr + chunk->size); | ||
511 | } | ||
512 | if (!memory_end) | ||
513 | memory_end = memory_size; | ||
514 | if (real_size > memory_end) | ||
515 | printk("More memory detected than supported. Unused: %luk\n", | ||
516 | (real_size - memory_end) >> 10); | ||
517 | } | ||
518 | |||
492 | static void __init | 519 | static void __init |
493 | setup_memory(void) | 520 | setup_memory(void) |
494 | { | 521 | { |
@@ -645,8 +672,6 @@ setup_arch(char **cmdline_p) | |||
645 | init_mm.end_data = (unsigned long) &_edata; | 672 | init_mm.end_data = (unsigned long) &_edata; |
646 | init_mm.brk = (unsigned long) &_end; | 673 | init_mm.brk = (unsigned long) &_end; |
647 | 674 | ||
648 | memory_end = memory_size; | ||
649 | |||
650 | if (MACHINE_HAS_MVCOS) | 675 | if (MACHINE_HAS_MVCOS) |
651 | memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess)); | 676 | memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess)); |
652 | else | 677 | else |
@@ -654,20 +679,7 @@ setup_arch(char **cmdline_p) | |||
654 | 679 | ||
655 | parse_early_param(); | 680 | parse_early_param(); |
656 | 681 | ||
657 | #ifndef CONFIG_64BIT | 682 | setup_memory_end(); |
658 | memory_end &= ~0x400000UL; | ||
659 | |||
660 | /* | ||
661 | * We need some free virtual space to be able to do vmalloc. | ||
662 | * On a machine with 2GB memory we make sure that we have at | ||
663 | * least 128 MB free space for vmalloc. | ||
664 | */ | ||
665 | if (memory_end > 1920*1024*1024) | ||
666 | memory_end = 1920*1024*1024; | ||
667 | #else /* CONFIG_64BIT */ | ||
668 | memory_end &= ~0x200000UL; | ||
669 | #endif /* CONFIG_64BIT */ | ||
670 | |||
671 | setup_memory(); | 683 | setup_memory(); |
672 | setup_resources(); | 684 | setup_resources(); |
673 | setup_lowcore(); | 685 | setup_lowcore(); |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 62822245f9be..19090f7d4f51 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -230,18 +230,37 @@ static inline void do_store_status(void) | |||
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
233 | static inline void do_wait_for_stop(void) | ||
234 | { | ||
235 | int cpu; | ||
236 | |||
237 | /* Wait for all other cpus to enter stopped state */ | ||
238 | for_each_online_cpu(cpu) { | ||
239 | if (cpu == smp_processor_id()) | ||
240 | continue; | ||
241 | while(!smp_cpu_not_running(cpu)) | ||
242 | cpu_relax(); | ||
243 | } | ||
244 | } | ||
245 | |||
233 | /* | 246 | /* |
234 | * this function sends a 'stop' sigp to all other CPUs in the system. | 247 | * this function sends a 'stop' sigp to all other CPUs in the system. |
235 | * it goes straight through. | 248 | * it goes straight through. |
236 | */ | 249 | */ |
237 | void smp_send_stop(void) | 250 | void smp_send_stop(void) |
238 | { | 251 | { |
252 | /* Disable all interrupts/machine checks */ | ||
253 | __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK); | ||
254 | |||
239 | /* write magic number to zero page (absolute 0) */ | 255 | /* write magic number to zero page (absolute 0) */ |
240 | lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; | 256 | lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; |
241 | 257 | ||
242 | /* stop other processors. */ | 258 | /* stop other processors. */ |
243 | do_send_stop(); | 259 | do_send_stop(); |
244 | 260 | ||
261 | /* wait until other processors are stopped */ | ||
262 | do_wait_for_stop(); | ||
263 | |||
245 | /* store status of other processors. */ | 264 | /* store status of other processors. */ |
246 | do_store_status(); | 265 | do_store_status(); |
247 | } | 266 | } |
@@ -250,88 +269,28 @@ void smp_send_stop(void) | |||
250 | * Reboot, halt and power_off routines for SMP. | 269 | * Reboot, halt and power_off routines for SMP. |
251 | */ | 270 | */ |
252 | 271 | ||
253 | static void do_machine_restart(void * __unused) | ||
254 | { | ||
255 | int cpu; | ||
256 | static atomic_t cpuid = ATOMIC_INIT(-1); | ||
257 | |||
258 | if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) | ||
259 | signal_processor(smp_processor_id(), sigp_stop); | ||
260 | |||
261 | /* Wait for all other cpus to enter stopped state */ | ||
262 | for_each_online_cpu(cpu) { | ||
263 | if (cpu == smp_processor_id()) | ||
264 | continue; | ||
265 | while(!smp_cpu_not_running(cpu)) | ||
266 | cpu_relax(); | ||
267 | } | ||
268 | |||
269 | /* Store status of other cpus. */ | ||
270 | do_store_status(); | ||
271 | |||
272 | /* | ||
273 | * Finally call reipl. Because we waited for all other | ||
274 | * cpus to enter this function we know that they do | ||
275 | * not hold any s390irq-locks (the cpus have been | ||
276 | * interrupted by an external interrupt and s390irq | ||
277 | * locks are always held disabled). | ||
278 | */ | ||
279 | do_reipl(); | ||
280 | } | ||
281 | |||
282 | void machine_restart_smp(char * __unused) | 272 | void machine_restart_smp(char * __unused) |
283 | { | 273 | { |
284 | on_each_cpu(do_machine_restart, NULL, 0, 0); | 274 | smp_send_stop(); |
285 | } | 275 | do_reipl(); |
286 | |||
287 | static void do_wait_for_stop(void) | ||
288 | { | ||
289 | unsigned long cr[16]; | ||
290 | |||
291 | __ctl_store(cr, 0, 15); | ||
292 | cr[0] &= ~0xffff; | ||
293 | cr[6] = 0; | ||
294 | __ctl_load(cr, 0, 15); | ||
295 | for (;;) | ||
296 | enabled_wait(); | ||
297 | } | ||
298 | |||
299 | static void do_machine_halt(void * __unused) | ||
300 | { | ||
301 | static atomic_t cpuid = ATOMIC_INIT(-1); | ||
302 | |||
303 | if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) { | ||
304 | smp_send_stop(); | ||
305 | if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) | ||
306 | cpcmd(vmhalt_cmd, NULL, 0, NULL); | ||
307 | signal_processor(smp_processor_id(), | ||
308 | sigp_stop_and_store_status); | ||
309 | } | ||
310 | do_wait_for_stop(); | ||
311 | } | 276 | } |
312 | 277 | ||
313 | void machine_halt_smp(void) | 278 | void machine_halt_smp(void) |
314 | { | 279 | { |
315 | on_each_cpu(do_machine_halt, NULL, 0, 0); | 280 | smp_send_stop(); |
316 | } | 281 | if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) |
317 | 282 | __cpcmd(vmhalt_cmd, NULL, 0, NULL); | |
318 | static void do_machine_power_off(void * __unused) | 283 | signal_processor(smp_processor_id(), sigp_stop_and_store_status); |
319 | { | 284 | for (;;); |
320 | static atomic_t cpuid = ATOMIC_INIT(-1); | ||
321 | |||
322 | if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) { | ||
323 | smp_send_stop(); | ||
324 | if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) | ||
325 | cpcmd(vmpoff_cmd, NULL, 0, NULL); | ||
326 | signal_processor(smp_processor_id(), | ||
327 | sigp_stop_and_store_status); | ||
328 | } | ||
329 | do_wait_for_stop(); | ||
330 | } | 285 | } |
331 | 286 | ||
332 | void machine_power_off_smp(void) | 287 | void machine_power_off_smp(void) |
333 | { | 288 | { |
334 | on_each_cpu(do_machine_power_off, NULL, 0, 0); | 289 | smp_send_stop(); |
290 | if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) | ||
291 | __cpcmd(vmpoff_cmd, NULL, 0, NULL); | ||
292 | signal_processor(smp_processor_id(), sigp_stop_and_store_status); | ||
293 | for (;;); | ||
335 | } | 294 | } |
336 | 295 | ||
337 | /* | 296 | /* |
@@ -501,8 +460,6 @@ __init smp_count_cpus(void) | |||
501 | */ | 460 | */ |
502 | extern void init_cpu_timer(void); | 461 | extern void init_cpu_timer(void); |
503 | extern void init_cpu_vtimer(void); | 462 | extern void init_cpu_vtimer(void); |
504 | extern int pfault_init(void); | ||
505 | extern void pfault_fini(void); | ||
506 | 463 | ||
507 | int __devinit start_secondary(void *cpuvoid) | 464 | int __devinit start_secondary(void *cpuvoid) |
508 | { | 465 | { |
@@ -514,11 +471,9 @@ int __devinit start_secondary(void *cpuvoid) | |||
514 | #ifdef CONFIG_VIRT_TIMER | 471 | #ifdef CONFIG_VIRT_TIMER |
515 | init_cpu_vtimer(); | 472 | init_cpu_vtimer(); |
516 | #endif | 473 | #endif |
517 | #ifdef CONFIG_PFAULT | ||
518 | /* Enable pfault pseudo page faults on this cpu. */ | 474 | /* Enable pfault pseudo page faults on this cpu. */ |
519 | if (MACHINE_IS_VM) | 475 | pfault_init(); |
520 | pfault_init(); | 476 | |
521 | #endif | ||
522 | /* Mark this cpu as online */ | 477 | /* Mark this cpu as online */ |
523 | cpu_set(smp_processor_id(), cpu_online_map); | 478 | cpu_set(smp_processor_id(), cpu_online_map); |
524 | /* Switch on interrupts */ | 479 | /* Switch on interrupts */ |
@@ -708,11 +663,8 @@ __cpu_disable(void) | |||
708 | } | 663 | } |
709 | cpu_clear(cpu, cpu_online_map); | 664 | cpu_clear(cpu, cpu_online_map); |
710 | 665 | ||
711 | #ifdef CONFIG_PFAULT | ||
712 | /* Disable pfault pseudo page faults on this cpu. */ | 666 | /* Disable pfault pseudo page faults on this cpu. */ |
713 | if (MACHINE_IS_VM) | 667 | pfault_fini(); |
714 | pfault_fini(); | ||
715 | #endif | ||
716 | 668 | ||
717 | memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals)); | 669 | memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals)); |
718 | memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals)); | 670 | memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals)); |
@@ -860,4 +812,3 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); | |||
860 | EXPORT_SYMBOL(smp_call_function); | 812 | EXPORT_SYMBOL(smp_call_function); |
861 | EXPORT_SYMBOL(smp_get_cpu); | 813 | EXPORT_SYMBOL(smp_get_cpu); |
862 | EXPORT_SYMBOL(smp_put_cpu); | 814 | EXPORT_SYMBOL(smp_put_cpu); |
863 | |||
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 92ecffbc8d82..3cbb0dcf1f1d 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -58,12 +58,6 @@ int sysctl_userprocess_debug = 0; | |||
58 | 58 | ||
59 | extern pgm_check_handler_t do_protection_exception; | 59 | extern pgm_check_handler_t do_protection_exception; |
60 | extern pgm_check_handler_t do_dat_exception; | 60 | extern pgm_check_handler_t do_dat_exception; |
61 | #ifdef CONFIG_PFAULT | ||
62 | extern int pfault_init(void); | ||
63 | extern void pfault_fini(void); | ||
64 | extern void pfault_interrupt(__u16 error_code); | ||
65 | static ext_int_info_t ext_int_pfault; | ||
66 | #endif | ||
67 | extern pgm_check_handler_t do_monitor_call; | 61 | extern pgm_check_handler_t do_monitor_call; |
68 | 62 | ||
69 | #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) | 63 | #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) |
@@ -135,7 +129,7 @@ __show_trace(unsigned long sp, unsigned long low, unsigned long high) | |||
135 | } | 129 | } |
136 | } | 130 | } |
137 | 131 | ||
138 | void show_trace(struct task_struct *task, unsigned long * stack) | 132 | void show_trace(struct task_struct *task, unsigned long *stack) |
139 | { | 133 | { |
140 | register unsigned long __r15 asm ("15"); | 134 | register unsigned long __r15 asm ("15"); |
141 | unsigned long sp; | 135 | unsigned long sp; |
@@ -157,6 +151,9 @@ void show_trace(struct task_struct *task, unsigned long * stack) | |||
157 | __show_trace(sp, S390_lowcore.thread_info, | 151 | __show_trace(sp, S390_lowcore.thread_info, |
158 | S390_lowcore.thread_info + THREAD_SIZE); | 152 | S390_lowcore.thread_info + THREAD_SIZE); |
159 | printk("\n"); | 153 | printk("\n"); |
154 | if (!task) | ||
155 | task = current; | ||
156 | debug_show_held_locks(task); | ||
160 | } | 157 | } |
161 | 158 | ||
162 | void show_stack(struct task_struct *task, unsigned long *sp) | 159 | void show_stack(struct task_struct *task, unsigned long *sp) |
@@ -739,22 +736,5 @@ void __init trap_init(void) | |||
739 | pgm_check_table[0x1C] = &space_switch_exception; | 736 | pgm_check_table[0x1C] = &space_switch_exception; |
740 | pgm_check_table[0x1D] = &hfp_sqrt_exception; | 737 | pgm_check_table[0x1D] = &hfp_sqrt_exception; |
741 | pgm_check_table[0x40] = &do_monitor_call; | 738 | pgm_check_table[0x40] = &do_monitor_call; |
742 | 739 | pfault_irq_init(); | |
743 | if (MACHINE_IS_VM) { | ||
744 | #ifdef CONFIG_PFAULT | ||
745 | /* | ||
746 | * Try to get pfault pseudo page faults going. | ||
747 | */ | ||
748 | if (register_early_external_interrupt(0x2603, pfault_interrupt, | ||
749 | &ext_int_pfault) != 0) | ||
750 | panic("Couldn't request external interrupt 0x2603"); | ||
751 | |||
752 | if (pfault_init() == 0) | ||
753 | return; | ||
754 | |||
755 | /* Tough luck, no pfault. */ | ||
756 | unregister_early_external_interrupt(0x2603, pfault_interrupt, | ||
757 | &ext_int_pfault); | ||
758 | #endif | ||
759 | } | ||
760 | } | 740 | } |
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index b0cfa6c4883d..b5f94cf3bde8 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | EXTRA_AFLAGS := -traditional | 5 | EXTRA_AFLAGS := -traditional |
6 | 6 | ||
7 | lib-y += delay.o string.o uaccess_std.o | 7 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o |
8 | lib-$(CONFIG_32BIT) += div64.o | 8 | lib-$(CONFIG_32BIT) += div64.o |
9 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o | 9 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o |
10 | lib-$(CONFIG_SMP) += spinlock.o | 10 | lib-$(CONFIG_SMP) += spinlock.o |
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c index 121b2935a422..f9a23d57eb79 100644 --- a/arch/s390/lib/uaccess_mvcos.c +++ b/arch/s390/lib/uaccess_mvcos.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #define SLR "slgr" | 27 | #define SLR "slgr" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | extern size_t copy_from_user_std(size_t, const void __user *, void *); | ||
31 | extern size_t copy_to_user_std(size_t, void __user *, const void *); | ||
32 | |||
30 | size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) | 33 | size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) |
31 | { | 34 | { |
32 | register unsigned long reg0 asm("0") = 0x81UL; | 35 | register unsigned long reg0 asm("0") = 0x81UL; |
@@ -66,6 +69,13 @@ size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) | |||
66 | return size; | 69 | return size; |
67 | } | 70 | } |
68 | 71 | ||
72 | size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x) | ||
73 | { | ||
74 | if (size <= 256) | ||
75 | return copy_from_user_std(size, ptr, x); | ||
76 | return copy_from_user_mvcos(size, ptr, x); | ||
77 | } | ||
78 | |||
69 | size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) | 79 | size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) |
70 | { | 80 | { |
71 | register unsigned long reg0 asm("0") = 0x810000UL; | 81 | register unsigned long reg0 asm("0") = 0x810000UL; |
@@ -95,6 +105,13 @@ size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) | |||
95 | return size; | 105 | return size; |
96 | } | 106 | } |
97 | 107 | ||
108 | size_t copy_to_user_mvcos_check(size_t size, void __user *ptr, const void *x) | ||
109 | { | ||
110 | if (size <= 256) | ||
111 | return copy_to_user_std(size, ptr, x); | ||
112 | return copy_to_user_mvcos(size, ptr, x); | ||
113 | } | ||
114 | |||
98 | size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from) | 115 | size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from) |
99 | { | 116 | { |
100 | register unsigned long reg0 asm("0") = 0x810081UL; | 117 | register unsigned long reg0 asm("0") = 0x810081UL; |
@@ -145,18 +162,16 @@ size_t clear_user_mvcos(size_t size, void __user *to) | |||
145 | return size; | 162 | return size; |
146 | } | 163 | } |
147 | 164 | ||
148 | extern size_t copy_from_user_std_small(size_t, const void __user *, void *); | ||
149 | extern size_t copy_to_user_std_small(size_t, void __user *, const void *); | ||
150 | extern size_t strnlen_user_std(size_t, const char __user *); | 165 | extern size_t strnlen_user_std(size_t, const char __user *); |
151 | extern size_t strncpy_from_user_std(size_t, const char __user *, char *); | 166 | extern size_t strncpy_from_user_std(size_t, const char __user *, char *); |
152 | extern int futex_atomic_op(int, int __user *, int, int *); | 167 | extern int futex_atomic_op(int, int __user *, int, int *); |
153 | extern int futex_atomic_cmpxchg(int __user *, int, int); | 168 | extern int futex_atomic_cmpxchg(int __user *, int, int); |
154 | 169 | ||
155 | struct uaccess_ops uaccess_mvcos = { | 170 | struct uaccess_ops uaccess_mvcos = { |
156 | .copy_from_user = copy_from_user_mvcos, | 171 | .copy_from_user = copy_from_user_mvcos_check, |
157 | .copy_from_user_small = copy_from_user_std_small, | 172 | .copy_from_user_small = copy_from_user_std, |
158 | .copy_to_user = copy_to_user_mvcos, | 173 | .copy_to_user = copy_to_user_mvcos_check, |
159 | .copy_to_user_small = copy_to_user_std_small, | 174 | .copy_to_user_small = copy_to_user_std, |
160 | .copy_in_user = copy_in_user_mvcos, | 175 | .copy_in_user = copy_in_user_mvcos, |
161 | .clear_user = clear_user_mvcos, | 176 | .clear_user = clear_user_mvcos, |
162 | .strnlen_user = strnlen_user_std, | 177 | .strnlen_user = strnlen_user_std, |
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c new file mode 100644 index 000000000000..8741bdc09299 --- /dev/null +++ b/arch/s390/lib/uaccess_pt.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * arch/s390/lib/uaccess_pt.c | ||
3 | * | ||
4 | * User access functions based on page table walks. | ||
5 | * | ||
6 | * Copyright IBM Corp. 2006 | ||
7 | * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com) | ||
8 | */ | ||
9 | |||
10 | #include <linux/errno.h> | ||
11 | #include <asm/uaccess.h> | ||
12 | #include <linux/mm.h> | ||
13 | #include <asm/futex.h> | ||
14 | |||
15 | static inline int __handle_fault(struct mm_struct *mm, unsigned long address, | ||
16 | int write_access) | ||
17 | { | ||
18 | struct vm_area_struct *vma; | ||
19 | int ret = -EFAULT; | ||
20 | |||
21 | down_read(&mm->mmap_sem); | ||
22 | vma = find_vma(mm, address); | ||
23 | if (unlikely(!vma)) | ||
24 | goto out; | ||
25 | if (unlikely(vma->vm_start > address)) { | ||
26 | if (!(vma->vm_flags & VM_GROWSDOWN)) | ||
27 | goto out; | ||
28 | if (expand_stack(vma, address)) | ||
29 | goto out; | ||
30 | } | ||
31 | |||
32 | if (!write_access) { | ||
33 | /* page not present, check vm flags */ | ||
34 | if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) | ||
35 | goto out; | ||
36 | } else { | ||
37 | if (!(vma->vm_flags & VM_WRITE)) | ||
38 | goto out; | ||
39 | } | ||
40 | |||
41 | survive: | ||
42 | switch (handle_mm_fault(mm, vma, address, write_access)) { | ||
43 | case VM_FAULT_MINOR: | ||
44 | current->min_flt++; | ||
45 | break; | ||
46 | case VM_FAULT_MAJOR: | ||
47 | current->maj_flt++; | ||
48 | break; | ||
49 | case VM_FAULT_SIGBUS: | ||
50 | goto out_sigbus; | ||
51 | case VM_FAULT_OOM: | ||
52 | goto out_of_memory; | ||
53 | default: | ||
54 | BUG(); | ||
55 | } | ||
56 | ret = 0; | ||
57 | out: | ||
58 | up_read(&mm->mmap_sem); | ||
59 | return ret; | ||
60 | |||
61 | out_of_memory: | ||
62 | up_read(&mm->mmap_sem); | ||
63 | if (current->pid == 1) { | ||
64 | yield(); | ||
65 | goto survive; | ||
66 | } | ||
67 | printk("VM: killing process %s\n", current->comm); | ||
68 | return ret; | ||
69 | |||
70 | out_sigbus: | ||
71 | up_read(&mm->mmap_sem); | ||
72 | current->thread.prot_addr = address; | ||
73 | current->thread.trap_no = 0x11; | ||
74 | force_sig(SIGBUS, current); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | static inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, | ||
79 | size_t n, int write_user) | ||
80 | { | ||
81 | struct mm_struct *mm = current->mm; | ||
82 | unsigned long offset, pfn, done, size; | ||
83 | pgd_t *pgd; | ||
84 | pmd_t *pmd; | ||
85 | pte_t *pte; | ||
86 | void *from, *to; | ||
87 | |||
88 | done = 0; | ||
89 | retry: | ||
90 | spin_lock(&mm->page_table_lock); | ||
91 | do { | ||
92 | pgd = pgd_offset(mm, uaddr); | ||
93 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | ||
94 | goto fault; | ||
95 | |||
96 | pmd = pmd_offset(pgd, uaddr); | ||
97 | if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | ||
98 | goto fault; | ||
99 | |||
100 | pte = pte_offset_map(pmd, uaddr); | ||
101 | if (!pte || !pte_present(*pte) || | ||
102 | (write_user && !pte_write(*pte))) | ||
103 | goto fault; | ||
104 | |||
105 | pfn = pte_pfn(*pte); | ||
106 | if (!pfn_valid(pfn)) | ||
107 | goto out; | ||
108 | |||
109 | offset = uaddr & (PAGE_SIZE - 1); | ||
110 | size = min(n - done, PAGE_SIZE - offset); | ||
111 | if (write_user) { | ||
112 | to = (void *)((pfn << PAGE_SHIFT) + offset); | ||
113 | from = kptr + done; | ||
114 | } else { | ||
115 | from = (void *)((pfn << PAGE_SHIFT) + offset); | ||
116 | to = kptr + done; | ||
117 | } | ||
118 | memcpy(to, from, size); | ||
119 | done += size; | ||
120 | uaddr += size; | ||
121 | } while (done < n); | ||
122 | out: | ||
123 | spin_unlock(&mm->page_table_lock); | ||
124 | return n - done; | ||
125 | fault: | ||
126 | spin_unlock(&mm->page_table_lock); | ||
127 | if (__handle_fault(mm, uaddr, write_user)) | ||
128 | return n - done; | ||
129 | goto retry; | ||
130 | } | ||
131 | |||
132 | size_t copy_from_user_pt(size_t n, const void __user *from, void *to) | ||
133 | { | ||
134 | size_t rc; | ||
135 | |||
136 | if (segment_eq(get_fs(), KERNEL_DS)) { | ||
137 | memcpy(to, (void __kernel __force *) from, n); | ||
138 | return 0; | ||
139 | } | ||
140 | rc = __user_copy_pt((unsigned long) from, to, n, 0); | ||
141 | if (unlikely(rc)) | ||
142 | memset(to + n - rc, 0, rc); | ||
143 | return rc; | ||
144 | } | ||
145 | |||
146 | size_t copy_to_user_pt(size_t n, void __user *to, const void *from) | ||
147 | { | ||
148 | if (segment_eq(get_fs(), KERNEL_DS)) { | ||
149 | memcpy((void __kernel __force *) to, from, n); | ||
150 | return 0; | ||
151 | } | ||
152 | return __user_copy_pt((unsigned long) to, (void *) from, n, 1); | ||
153 | } | ||
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index f44f0078b354..2d549ed2e113 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #define SLR "slgr" | 28 | #define SLR "slgr" |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | extern size_t copy_from_user_pt(size_t n, const void __user *from, void *to); | ||
32 | extern size_t copy_to_user_pt(size_t n, void __user *to, const void *from); | ||
33 | |||
31 | size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) | 34 | size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) |
32 | { | 35 | { |
33 | unsigned long tmp1, tmp2; | 36 | unsigned long tmp1, tmp2; |
@@ -69,34 +72,11 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) | |||
69 | return size; | 72 | return size; |
70 | } | 73 | } |
71 | 74 | ||
72 | size_t copy_from_user_std_small(size_t size, const void __user *ptr, void *x) | 75 | size_t copy_from_user_std_check(size_t size, const void __user *ptr, void *x) |
73 | { | 76 | { |
74 | unsigned long tmp1, tmp2; | 77 | if (size <= 1024) |
75 | 78 | return copy_from_user_std(size, ptr, x); | |
76 | tmp1 = 0UL; | 79 | return copy_from_user_pt(size, ptr, x); |
77 | asm volatile( | ||
78 | "0: mvcp 0(%0,%2),0(%1),%3\n" | ||
79 | " "SLR" %0,%0\n" | ||
80 | " j 5f\n" | ||
81 | "1: la %4,255(%1)\n" /* %4 = ptr + 255 */ | ||
82 | " "LHI" %3,-4096\n" | ||
83 | " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */ | ||
84 | " "SLR" %4,%1\n" | ||
85 | " "CLR" %0,%4\n" /* copy crosses next page boundary? */ | ||
86 | " jnh 5f\n" | ||
87 | "2: mvcp 0(%4,%2),0(%1),%3\n" | ||
88 | " "SLR" %0,%4\n" | ||
89 | " "ALR" %2,%4\n" | ||
90 | "3:"LHI" %4,-1\n" | ||
91 | " "ALR" %4,%0\n" /* copy remaining size, subtract 1 */ | ||
92 | " bras %3,4f\n" | ||
93 | " xc 0(1,%2),0(%2)\n" | ||
94 | "4: ex %4,0(%3)\n" | ||
95 | "5:\n" | ||
96 | EX_TABLE(0b,1b) EX_TABLE(2b,3b) | ||
97 | : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) | ||
98 | : : "cc", "memory"); | ||
99 | return size; | ||
100 | } | 80 | } |
101 | 81 | ||
102 | size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) | 82 | size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) |
@@ -130,28 +110,11 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) | |||
130 | return size; | 110 | return size; |
131 | } | 111 | } |
132 | 112 | ||
133 | size_t copy_to_user_std_small(size_t size, void __user *ptr, const void *x) | 113 | size_t copy_to_user_std_check(size_t size, void __user *ptr, const void *x) |
134 | { | 114 | { |
135 | unsigned long tmp1, tmp2; | 115 | if (size <= 1024) |
136 | 116 | return copy_to_user_std(size, ptr, x); | |
137 | tmp1 = 0UL; | 117 | return copy_to_user_pt(size, ptr, x); |
138 | asm volatile( | ||
139 | "0: mvcs 0(%0,%1),0(%2),%3\n" | ||
140 | " "SLR" %0,%0\n" | ||
141 | " j 3f\n" | ||
142 | "1: la %4,255(%1)\n" /* ptr + 255 */ | ||
143 | " "LHI" %3,-4096\n" | ||
144 | " nr %4,%3\n" /* (ptr + 255) & -4096UL */ | ||
145 | " "SLR" %4,%1\n" | ||
146 | " "CLR" %0,%4\n" /* copy crosses next page boundary? */ | ||
147 | " jnh 3f\n" | ||
148 | "2: mvcs 0(%4,%1),0(%2),%3\n" | ||
149 | " "SLR" %0,%4\n" | ||
150 | "3:\n" | ||
151 | EX_TABLE(0b,1b) EX_TABLE(2b,3b) | ||
152 | : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) | ||
153 | : : "cc", "memory"); | ||
154 | return size; | ||
155 | } | 118 | } |
156 | 119 | ||
157 | size_t copy_in_user_std(size_t size, void __user *to, const void __user *from) | 120 | size_t copy_in_user_std(size_t size, void __user *to, const void __user *from) |
@@ -343,10 +306,10 @@ int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval) | |||
343 | } | 306 | } |
344 | 307 | ||
345 | struct uaccess_ops uaccess_std = { | 308 | struct uaccess_ops uaccess_std = { |
346 | .copy_from_user = copy_from_user_std, | 309 | .copy_from_user = copy_from_user_std_check, |
347 | .copy_from_user_small = copy_from_user_std_small, | 310 | .copy_from_user_small = copy_from_user_std, |
348 | .copy_to_user = copy_to_user_std, | 311 | .copy_to_user = copy_to_user_std_check, |
349 | .copy_to_user_small = copy_to_user_std_small, | 312 | .copy_to_user_small = copy_to_user_std, |
350 | .copy_in_user = copy_in_user_std, | 313 | .copy_in_user = copy_in_user_std, |
351 | .clear_user = clear_user_std, | 314 | .clear_user = clear_user_std, |
352 | .strnlen_user = strnlen_user_std, | 315 | .strnlen_user = strnlen_user_std, |
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 226275d5c4f6..9e9bc48463a5 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c | |||
@@ -14,12 +14,13 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
17 | #include <linux/ctype.h> | ||
17 | #include <asm/page.h> | 18 | #include <asm/page.h> |
18 | #include <asm/ebcdic.h> | 19 | #include <asm/ebcdic.h> |
19 | #include <asm/errno.h> | 20 | #include <asm/errno.h> |
20 | #include <asm/extmem.h> | 21 | #include <asm/extmem.h> |
21 | #include <asm/cpcmd.h> | 22 | #include <asm/cpcmd.h> |
22 | #include <linux/ctype.h> | 23 | #include <asm/setup.h> |
23 | 24 | ||
24 | #define DCSS_DEBUG /* Debug messages on/off */ | 25 | #define DCSS_DEBUG /* Debug messages on/off */ |
25 | 26 | ||
@@ -77,15 +78,11 @@ struct dcss_segment { | |||
77 | int segcnt; | 78 | int segcnt; |
78 | }; | 79 | }; |
79 | 80 | ||
80 | static DEFINE_SPINLOCK(dcss_lock); | 81 | static DEFINE_MUTEX(dcss_lock); |
81 | static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list); | 82 | static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list); |
82 | static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", | 83 | static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", |
83 | "EW/EN-MIXED" }; | 84 | "EW/EN-MIXED" }; |
84 | 85 | ||
85 | extern struct { | ||
86 | unsigned long addr, size, type; | ||
87 | } memory_chunk[MEMORY_CHUNKS]; | ||
88 | |||
89 | /* | 86 | /* |
90 | * Create the 8 bytes, ebcdic VM segment name from | 87 | * Create the 8 bytes, ebcdic VM segment name from |
91 | * an ascii name. | 88 | * an ascii name. |
@@ -117,7 +114,7 @@ segment_by_name (char *name) | |||
117 | struct list_head *l; | 114 | struct list_head *l; |
118 | struct dcss_segment *tmp, *retval = NULL; | 115 | struct dcss_segment *tmp, *retval = NULL; |
119 | 116 | ||
120 | assert_spin_locked(&dcss_lock); | 117 | BUG_ON(!mutex_is_locked(&dcss_lock)); |
121 | dcss_mkname (name, dcss_name); | 118 | dcss_mkname (name, dcss_name); |
122 | list_for_each (l, &dcss_list) { | 119 | list_for_each (l, &dcss_list) { |
123 | tmp = list_entry (l, struct dcss_segment, list); | 120 | tmp = list_entry (l, struct dcss_segment, list); |
@@ -249,8 +246,8 @@ segment_overlaps_storage(struct dcss_segment *seg) | |||
249 | { | 246 | { |
250 | int i; | 247 | int i; |
251 | 248 | ||
252 | for (i=0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { | 249 | for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { |
253 | if (memory_chunk[i].type != 0) | 250 | if (memory_chunk[i].type != CHUNK_READ_WRITE) |
254 | continue; | 251 | continue; |
255 | if ((memory_chunk[i].addr >> 20) > (seg->end >> 20)) | 252 | if ((memory_chunk[i].addr >> 20) > (seg->end >> 20)) |
256 | continue; | 253 | continue; |
@@ -272,7 +269,7 @@ segment_overlaps_others (struct dcss_segment *seg) | |||
272 | struct list_head *l; | 269 | struct list_head *l; |
273 | struct dcss_segment *tmp; | 270 | struct dcss_segment *tmp; |
274 | 271 | ||
275 | assert_spin_locked(&dcss_lock); | 272 | BUG_ON(!mutex_is_locked(&dcss_lock)); |
276 | list_for_each(l, &dcss_list) { | 273 | list_for_each(l, &dcss_list) { |
277 | tmp = list_entry(l, struct dcss_segment, list); | 274 | tmp = list_entry(l, struct dcss_segment, list); |
278 | if ((tmp->start_addr >> 20) > (seg->end >> 20)) | 275 | if ((tmp->start_addr >> 20) > (seg->end >> 20)) |
@@ -429,7 +426,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr, | |||
429 | if (!MACHINE_IS_VM) | 426 | if (!MACHINE_IS_VM) |
430 | return -ENOSYS; | 427 | return -ENOSYS; |
431 | 428 | ||
432 | spin_lock (&dcss_lock); | 429 | mutex_lock(&dcss_lock); |
433 | seg = segment_by_name (name); | 430 | seg = segment_by_name (name); |
434 | if (seg == NULL) | 431 | if (seg == NULL) |
435 | rc = __segment_load (name, do_nonshared, addr, end); | 432 | rc = __segment_load (name, do_nonshared, addr, end); |
@@ -444,7 +441,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr, | |||
444 | rc = -EPERM; | 441 | rc = -EPERM; |
445 | } | 442 | } |
446 | } | 443 | } |
447 | spin_unlock (&dcss_lock); | 444 | mutex_unlock(&dcss_lock); |
448 | return rc; | 445 | return rc; |
449 | } | 446 | } |
450 | 447 | ||
@@ -467,7 +464,7 @@ segment_modify_shared (char *name, int do_nonshared) | |||
467 | unsigned long dummy; | 464 | unsigned long dummy; |
468 | int dcss_command, rc, diag_cc; | 465 | int dcss_command, rc, diag_cc; |
469 | 466 | ||
470 | spin_lock (&dcss_lock); | 467 | mutex_lock(&dcss_lock); |
471 | seg = segment_by_name (name); | 468 | seg = segment_by_name (name); |
472 | if (seg == NULL) { | 469 | if (seg == NULL) { |
473 | rc = -EINVAL; | 470 | rc = -EINVAL; |
@@ -508,7 +505,7 @@ segment_modify_shared (char *name, int do_nonshared) | |||
508 | &dummy, &dummy); | 505 | &dummy, &dummy); |
509 | kfree(seg); | 506 | kfree(seg); |
510 | out_unlock: | 507 | out_unlock: |
511 | spin_unlock(&dcss_lock); | 508 | mutex_unlock(&dcss_lock); |
512 | return rc; | 509 | return rc; |
513 | } | 510 | } |
514 | 511 | ||
@@ -526,7 +523,7 @@ segment_unload(char *name) | |||
526 | if (!MACHINE_IS_VM) | 523 | if (!MACHINE_IS_VM) |
527 | return; | 524 | return; |
528 | 525 | ||
529 | spin_lock(&dcss_lock); | 526 | mutex_lock(&dcss_lock); |
530 | seg = segment_by_name (name); | 527 | seg = segment_by_name (name); |
531 | if (seg == NULL) { | 528 | if (seg == NULL) { |
532 | PRINT_ERR ("could not find segment %s in segment_unload, " | 529 | PRINT_ERR ("could not find segment %s in segment_unload, " |
@@ -540,7 +537,7 @@ segment_unload(char *name) | |||
540 | kfree(seg); | 537 | kfree(seg); |
541 | } | 538 | } |
542 | out_unlock: | 539 | out_unlock: |
543 | spin_unlock(&dcss_lock); | 540 | mutex_unlock(&dcss_lock); |
544 | } | 541 | } |
545 | 542 | ||
546 | /* | 543 | /* |
@@ -559,12 +556,13 @@ segment_save(char *name) | |||
559 | if (!MACHINE_IS_VM) | 556 | if (!MACHINE_IS_VM) |
560 | return; | 557 | return; |
561 | 558 | ||
562 | spin_lock(&dcss_lock); | 559 | mutex_lock(&dcss_lock); |
563 | seg = segment_by_name (name); | 560 | seg = segment_by_name (name); |
564 | 561 | ||
565 | if (seg == NULL) { | 562 | if (seg == NULL) { |
566 | PRINT_ERR ("could not find segment %s in segment_save, please report to linux390@de.ibm.com\n",name); | 563 | PRINT_ERR("could not find segment %s in segment_save, please " |
567 | return; | 564 | "report to linux390@de.ibm.com\n", name); |
565 | goto out; | ||
568 | } | 566 | } |
569 | 567 | ||
570 | startpfn = seg->start_addr >> PAGE_SHIFT; | 568 | startpfn = seg->start_addr >> PAGE_SHIFT; |
@@ -591,7 +589,7 @@ segment_save(char *name) | |||
591 | goto out; | 589 | goto out; |
592 | } | 590 | } |
593 | out: | 591 | out: |
594 | spin_unlock(&dcss_lock); | 592 | mutex_unlock(&dcss_lock); |
595 | } | 593 | } |
596 | 594 | ||
597 | EXPORT_SYMBOL(segment_load); | 595 | EXPORT_SYMBOL(segment_load); |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 1c323bbfda91..cd85e34d8703 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | #include <asm/pgtable.h> | 32 | #include <asm/pgtable.h> |
33 | #include <asm/kdebug.h> | 33 | #include <asm/kdebug.h> |
34 | #include <asm/s390_ext.h> | ||
34 | 35 | ||
35 | #ifndef CONFIG_64BIT | 36 | #ifndef CONFIG_64BIT |
36 | #define __FAIL_ADDR_MASK 0x7ffff000 | 37 | #define __FAIL_ADDR_MASK 0x7ffff000 |
@@ -394,6 +395,7 @@ void do_dat_exception(struct pt_regs *regs, unsigned long error_code) | |||
394 | /* | 395 | /* |
395 | * 'pfault' pseudo page faults routines. | 396 | * 'pfault' pseudo page faults routines. |
396 | */ | 397 | */ |
398 | static ext_int_info_t ext_int_pfault; | ||
397 | static int pfault_disable = 0; | 399 | static int pfault_disable = 0; |
398 | 400 | ||
399 | static int __init nopfault(char *str) | 401 | static int __init nopfault(char *str) |
@@ -422,7 +424,7 @@ int pfault_init(void) | |||
422 | __PF_RES_FIELD }; | 424 | __PF_RES_FIELD }; |
423 | int rc; | 425 | int rc; |
424 | 426 | ||
425 | if (pfault_disable) | 427 | if (!MACHINE_IS_VM || pfault_disable) |
426 | return -1; | 428 | return -1; |
427 | asm volatile( | 429 | asm volatile( |
428 | " diag %1,%0,0x258\n" | 430 | " diag %1,%0,0x258\n" |
@@ -440,7 +442,7 @@ void pfault_fini(void) | |||
440 | pfault_refbk_t refbk = | 442 | pfault_refbk_t refbk = |
441 | { 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL }; | 443 | { 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL }; |
442 | 444 | ||
443 | if (pfault_disable) | 445 | if (!MACHINE_IS_VM || pfault_disable) |
444 | return; | 446 | return; |
445 | __ctl_clear_bit(0,9); | 447 | __ctl_clear_bit(0,9); |
446 | asm volatile( | 448 | asm volatile( |
@@ -500,5 +502,25 @@ pfault_interrupt(__u16 error_code) | |||
500 | set_tsk_need_resched(tsk); | 502 | set_tsk_need_resched(tsk); |
501 | } | 503 | } |
502 | } | 504 | } |
503 | #endif | ||
504 | 505 | ||
506 | void __init pfault_irq_init(void) | ||
507 | { | ||
508 | if (!MACHINE_IS_VM) | ||
509 | return; | ||
510 | |||
511 | /* | ||
512 | * Try to get pfault pseudo page faults going. | ||
513 | */ | ||
514 | if (register_early_external_interrupt(0x2603, pfault_interrupt, | ||
515 | &ext_int_pfault) != 0) | ||
516 | panic("Couldn't request external interrupt 0x2603"); | ||
517 | |||
518 | if (pfault_init() == 0) | ||
519 | return; | ||
520 | |||
521 | /* Tough luck, no pfault. */ | ||
522 | pfault_disable = 1; | ||
523 | unregister_early_external_interrupt(0x2603, pfault_interrupt, | ||
524 | &ext_int_pfault); | ||
525 | } | ||
526 | #endif | ||
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 578b99b71d9c..bf5b79ed3613 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
30 | #include <linux/jiffies.h> | ||
30 | #include <acpi/acpi_bus.h> | 31 | #include <acpi/acpi_bus.h> |
31 | #include <acpi/acpi_drivers.h> | 32 | #include <acpi/acpi_drivers.h> |
32 | 33 | ||
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 03f6338acc8f..984ab284382a 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -328,6 +328,15 @@ config PATA_TRIFLEX | |||
328 | 328 | ||
329 | If unsure, say N. | 329 | If unsure, say N. |
330 | 330 | ||
331 | config PATA_MARVELL | ||
332 | tristate "Marvell PATA support via legacy mode" | ||
333 | depends on PCI | ||
334 | help | ||
335 | This option enables limited support for the Marvell 88SE6145 ATA | ||
336 | controller. | ||
337 | |||
338 | If unsure, say N. | ||
339 | |||
331 | config PATA_MPIIX | 340 | config PATA_MPIIX |
332 | tristate "Intel PATA MPIIX support" | 341 | tristate "Intel PATA MPIIX support" |
333 | depends on PCI | 342 | depends on PCI |
@@ -483,6 +492,32 @@ config PATA_WINBOND | |||
483 | 492 | ||
484 | If unsure, say N. | 493 | If unsure, say N. |
485 | 494 | ||
495 | config PATA_WINBOND_VLB | ||
496 | tristate "Winbond W83759A VLB PATA support (Experimental)" | ||
497 | depends on ISA && EXPERIMENTAL | ||
498 | help | ||
499 | Support for the Winbond W83759A controller on Vesa Local Bus | ||
500 | systems. | ||
501 | |||
502 | config PATA_PLATFORM | ||
503 | tristate "Generic platform device PATA support" | ||
504 | depends on EMBEDDED | ||
505 | help | ||
506 | This option enables support for generic directly connected ATA | ||
507 | devices commonly found on embedded systems. | ||
508 | |||
509 | If unsure, say N. | ||
510 | |||
511 | config PATA_IXP4XX_CF | ||
512 | tristate "IXP4XX Compact Flash support" | ||
513 | depends on ARCH_IXP4XX | ||
514 | help | ||
515 | This option enables support for a Compact Flash connected on | ||
516 | the ixp4xx expansion bus. This driver had been written for | ||
517 | Loft/Avila boards in mind but can work with others. | ||
518 | |||
519 | If unsure, say N. | ||
520 | |||
486 | endif | 521 | endif |
487 | endmenu | 522 | endmenu |
488 | 523 | ||
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 72243a677f9b..bc3d81ae757e 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
@@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o | |||
38 | obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o | 38 | obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o |
39 | obj-$(CONFIG_PATA_OPTI) += pata_opti.o | 39 | obj-$(CONFIG_PATA_OPTI) += pata_opti.o |
40 | obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o | 40 | obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o |
41 | obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o | ||
41 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o | 42 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o |
42 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o | 43 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o |
43 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o | 44 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o |
@@ -51,8 +52,11 @@ obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o | |||
51 | obj-$(CONFIG_PATA_SIL680) += pata_sil680.o | 52 | obj-$(CONFIG_PATA_SIL680) += pata_sil680.o |
52 | obj-$(CONFIG_PATA_VIA) += pata_via.o | 53 | obj-$(CONFIG_PATA_VIA) += pata_via.o |
53 | obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o | 54 | obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o |
55 | obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o | ||
54 | obj-$(CONFIG_PATA_SIS) += pata_sis.o | 56 | obj-$(CONFIG_PATA_SIS) += pata_sis.o |
55 | obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o | 57 | obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o |
58 | obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o | ||
59 | obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o | ||
56 | # Should be last but one libata driver | 60 | # Should be last but one libata driver |
57 | obj-$(CONFIG_ATA_GENERIC) += ata_generic.o | 61 | obj-$(CONFIG_ATA_GENERIC) += ata_generic.o |
58 | # Should be last libata driver | 62 | # Should be last libata driver |
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index bddb14e91d3c..f36da488a2c1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | enum { | 54 | enum { |
55 | AHCI_PCI_BAR = 5, | 55 | AHCI_PCI_BAR = 5, |
56 | AHCI_MAX_PORTS = 32, | ||
56 | AHCI_MAX_SG = 168, /* hardware max is 64K */ | 57 | AHCI_MAX_SG = 168, /* hardware max is 64K */ |
57 | AHCI_DMA_BOUNDARY = 0xffffffff, | 58 | AHCI_DMA_BOUNDARY = 0xffffffff, |
58 | AHCI_USE_CLUSTERING = 0, | 59 | AHCI_USE_CLUSTERING = 0, |
@@ -77,8 +78,9 @@ enum { | |||
77 | RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ | 78 | RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ |
78 | 79 | ||
79 | board_ahci = 0, | 80 | board_ahci = 0, |
80 | board_ahci_vt8251 = 1, | 81 | board_ahci_pi = 1, |
81 | board_ahci_ign_iferr = 2, | 82 | board_ahci_vt8251 = 2, |
83 | board_ahci_ign_iferr = 3, | ||
82 | 84 | ||
83 | /* global controller registers */ | 85 | /* global controller registers */ |
84 | HOST_CAP = 0x00, /* host capabilities */ | 86 | HOST_CAP = 0x00, /* host capabilities */ |
@@ -167,9 +169,9 @@ enum { | |||
167 | AHCI_FLAG_MSI = (1 << 0), | 169 | AHCI_FLAG_MSI = (1 << 0), |
168 | 170 | ||
169 | /* ap->flags bits */ | 171 | /* ap->flags bits */ |
170 | AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), | 172 | AHCI_FLAG_NO_NCQ = (1 << 24), |
171 | AHCI_FLAG_NO_NCQ = (1 << 25), | 173 | AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ |
172 | AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 26), /* ignore IRQ_IF_ERR */ | 174 | AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ |
173 | }; | 175 | }; |
174 | 176 | ||
175 | struct ahci_cmd_hdr { | 177 | struct ahci_cmd_hdr { |
@@ -216,6 +218,7 @@ static u8 ahci_check_status(struct ata_port *ap); | |||
216 | static void ahci_freeze(struct ata_port *ap); | 218 | static void ahci_freeze(struct ata_port *ap); |
217 | static void ahci_thaw(struct ata_port *ap); | 219 | static void ahci_thaw(struct ata_port *ap); |
218 | static void ahci_error_handler(struct ata_port *ap); | 220 | static void ahci_error_handler(struct ata_port *ap); |
221 | static void ahci_vt8251_error_handler(struct ata_port *ap); | ||
219 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); | 222 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); |
220 | static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); | 223 | static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); |
221 | static int ahci_port_resume(struct ata_port *ap); | 224 | static int ahci_port_resume(struct ata_port *ap); |
@@ -275,6 +278,37 @@ static const struct ata_port_operations ahci_ops = { | |||
275 | .port_stop = ahci_port_stop, | 278 | .port_stop = ahci_port_stop, |
276 | }; | 279 | }; |
277 | 280 | ||
281 | static const struct ata_port_operations ahci_vt8251_ops = { | ||
282 | .port_disable = ata_port_disable, | ||
283 | |||
284 | .check_status = ahci_check_status, | ||
285 | .check_altstatus = ahci_check_status, | ||
286 | .dev_select = ata_noop_dev_select, | ||
287 | |||
288 | .tf_read = ahci_tf_read, | ||
289 | |||
290 | .qc_prep = ahci_qc_prep, | ||
291 | .qc_issue = ahci_qc_issue, | ||
292 | |||
293 | .irq_handler = ahci_interrupt, | ||
294 | .irq_clear = ahci_irq_clear, | ||
295 | |||
296 | .scr_read = ahci_scr_read, | ||
297 | .scr_write = ahci_scr_write, | ||
298 | |||
299 | .freeze = ahci_freeze, | ||
300 | .thaw = ahci_thaw, | ||
301 | |||
302 | .error_handler = ahci_vt8251_error_handler, | ||
303 | .post_internal_cmd = ahci_post_internal_cmd, | ||
304 | |||
305 | .port_suspend = ahci_port_suspend, | ||
306 | .port_resume = ahci_port_resume, | ||
307 | |||
308 | .port_start = ahci_port_start, | ||
309 | .port_stop = ahci_port_stop, | ||
310 | }; | ||
311 | |||
278 | static const struct ata_port_info ahci_port_info[] = { | 312 | static const struct ata_port_info ahci_port_info[] = { |
279 | /* board_ahci */ | 313 | /* board_ahci */ |
280 | { | 314 | { |
@@ -286,16 +320,26 @@ static const struct ata_port_info ahci_port_info[] = { | |||
286 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 320 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
287 | .port_ops = &ahci_ops, | 321 | .port_ops = &ahci_ops, |
288 | }, | 322 | }, |
323 | /* board_ahci_pi */ | ||
324 | { | ||
325 | .sht = &ahci_sht, | ||
326 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | ||
327 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | ||
328 | ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI, | ||
329 | .pio_mask = 0x1f, /* pio0-4 */ | ||
330 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | ||
331 | .port_ops = &ahci_ops, | ||
332 | }, | ||
289 | /* board_ahci_vt8251 */ | 333 | /* board_ahci_vt8251 */ |
290 | { | 334 | { |
291 | .sht = &ahci_sht, | 335 | .sht = &ahci_sht, |
292 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 336 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
293 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | 337 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
294 | ATA_FLAG_SKIP_D2H_BSY | | 338 | ATA_FLAG_SKIP_D2H_BSY | |
295 | AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ, | 339 | ATA_FLAG_HRST_TO_RESUME | AHCI_FLAG_NO_NCQ, |
296 | .pio_mask = 0x1f, /* pio0-4 */ | 340 | .pio_mask = 0x1f, /* pio0-4 */ |
297 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 341 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
298 | .port_ops = &ahci_ops, | 342 | .port_ops = &ahci_vt8251_ops, |
299 | }, | 343 | }, |
300 | /* board_ahci_ign_iferr */ | 344 | /* board_ahci_ign_iferr */ |
301 | { | 345 | { |
@@ -322,22 +366,22 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
322 | { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ | 366 | { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ |
323 | { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ | 367 | { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ |
324 | { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ | 368 | { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ |
325 | { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ | 369 | { PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */ |
326 | { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */ | 370 | { PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */ |
327 | { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ | 371 | { PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */ |
328 | { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ | 372 | { PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */ |
329 | { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ | 373 | { PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */ |
330 | { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ | 374 | { PCI_VDEVICE(INTEL, 0x2922), board_ahci_pi }, /* ICH9 */ |
331 | { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ | 375 | { PCI_VDEVICE(INTEL, 0x2923), board_ahci_pi }, /* ICH9 */ |
332 | { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ | 376 | { PCI_VDEVICE(INTEL, 0x2924), board_ahci_pi }, /* ICH9 */ |
333 | { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ | 377 | { PCI_VDEVICE(INTEL, 0x2925), board_ahci_pi }, /* ICH9 */ |
334 | { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ | 378 | { PCI_VDEVICE(INTEL, 0x2927), board_ahci_pi }, /* ICH9 */ |
335 | { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ | 379 | { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */ |
336 | { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ | 380 | { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */ |
337 | { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ | 381 | { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */ |
338 | { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ | 382 | { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */ |
339 | { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ | 383 | { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */ |
340 | { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ | 384 | { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */ |
341 | 385 | ||
342 | /* JMicron */ | 386 | /* JMicron */ |
343 | { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ | 387 | { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ |
@@ -372,6 +416,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
372 | { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ | 416 | { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ |
373 | { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ | 417 | { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ |
374 | 418 | ||
419 | /* Generic, PCI class code for AHCI */ | ||
420 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | ||
421 | 0x010601, 0xffffff, board_ahci }, | ||
422 | |||
375 | { } /* terminate list */ | 423 | { } /* terminate list */ |
376 | }; | 424 | }; |
377 | 425 | ||
@@ -386,6 +434,11 @@ static struct pci_driver ahci_pci_driver = { | |||
386 | }; | 434 | }; |
387 | 435 | ||
388 | 436 | ||
437 | static inline int ahci_nr_ports(u32 cap) | ||
438 | { | ||
439 | return (cap & 0x1f) + 1; | ||
440 | } | ||
441 | |||
389 | static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port) | 442 | static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port) |
390 | { | 443 | { |
391 | return base + 0x100 + (port * 0x80); | 444 | return base + 0x100 + (port * 0x80); |
@@ -559,9 +612,6 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap) | |||
559 | static void ahci_init_port(void __iomem *port_mmio, u32 cap, | 612 | static void ahci_init_port(void __iomem *port_mmio, u32 cap, |
560 | dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) | 613 | dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) |
561 | { | 614 | { |
562 | /* power up */ | ||
563 | ahci_power_up(port_mmio, cap); | ||
564 | |||
565 | /* enable FIS reception */ | 615 | /* enable FIS reception */ |
566 | ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma); | 616 | ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma); |
567 | 617 | ||
@@ -587,19 +637,17 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg) | |||
587 | return rc; | 637 | return rc; |
588 | } | 638 | } |
589 | 639 | ||
590 | /* put device into slumber mode */ | ||
591 | ahci_power_down(port_mmio, cap); | ||
592 | |||
593 | return 0; | 640 | return 0; |
594 | } | 641 | } |
595 | 642 | ||
596 | static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) | 643 | static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) |
597 | { | 644 | { |
598 | u32 cap_save, tmp; | 645 | u32 cap_save, impl_save, tmp; |
599 | 646 | ||
600 | cap_save = readl(mmio + HOST_CAP); | 647 | cap_save = readl(mmio + HOST_CAP); |
601 | cap_save &= ( (1<<28) | (1<<17) ); | 648 | cap_save &= ( (1<<28) | (1<<17) ); |
602 | cap_save |= (1 << 27); | 649 | cap_save |= (1 << 27); |
650 | impl_save = readl(mmio + HOST_PORTS_IMPL); | ||
603 | 651 | ||
604 | /* global controller reset */ | 652 | /* global controller reset */ |
605 | tmp = readl(mmio + HOST_CTL); | 653 | tmp = readl(mmio + HOST_CTL); |
@@ -620,10 +668,21 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) | |||
620 | return -EIO; | 668 | return -EIO; |
621 | } | 669 | } |
622 | 670 | ||
671 | /* turn on AHCI mode */ | ||
623 | writel(HOST_AHCI_EN, mmio + HOST_CTL); | 672 | writel(HOST_AHCI_EN, mmio + HOST_CTL); |
624 | (void) readl(mmio + HOST_CTL); /* flush */ | 673 | (void) readl(mmio + HOST_CTL); /* flush */ |
674 | |||
675 | /* These write-once registers are normally cleared on reset. | ||
676 | * Restore BIOS values... which we HOPE were present before | ||
677 | * reset. | ||
678 | */ | ||
679 | if (!impl_save) { | ||
680 | impl_save = (1 << ahci_nr_ports(cap_save)) - 1; | ||
681 | dev_printk(KERN_WARNING, &pdev->dev, | ||
682 | "PORTS_IMPL is zero, forcing 0x%x\n", impl_save); | ||
683 | } | ||
625 | writel(cap_save, mmio + HOST_CAP); | 684 | writel(cap_save, mmio + HOST_CAP); |
626 | writel(0xf, mmio + HOST_PORTS_IMPL); | 685 | writel(impl_save, mmio + HOST_PORTS_IMPL); |
627 | (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ | 686 | (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ |
628 | 687 | ||
629 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) { | 688 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) { |
@@ -639,7 +698,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) | |||
639 | } | 698 | } |
640 | 699 | ||
641 | static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, | 700 | static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, |
642 | int n_ports, u32 cap) | 701 | int n_ports, unsigned int port_flags, |
702 | struct ahci_host_priv *hpriv) | ||
643 | { | 703 | { |
644 | int i, rc; | 704 | int i, rc; |
645 | u32 tmp; | 705 | u32 tmp; |
@@ -648,13 +708,12 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, | |||
648 | void __iomem *port_mmio = ahci_port_base(mmio, i); | 708 | void __iomem *port_mmio = ahci_port_base(mmio, i); |
649 | const char *emsg = NULL; | 709 | const char *emsg = NULL; |
650 | 710 | ||
651 | #if 0 /* BIOSen initialize this incorrectly */ | 711 | if ((port_flags & AHCI_FLAG_HONOR_PI) && |
652 | if (!(hpriv->port_map & (1 << i))) | 712 | !(hpriv->port_map & (1 << i))) |
653 | continue; | 713 | continue; |
654 | #endif | ||
655 | 714 | ||
656 | /* make sure port is not active */ | 715 | /* make sure port is not active */ |
657 | rc = ahci_deinit_port(port_mmio, cap, &emsg); | 716 | rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); |
658 | if (rc) | 717 | if (rc) |
659 | dev_printk(KERN_WARNING, &pdev->dev, | 718 | dev_printk(KERN_WARNING, &pdev->dev, |
660 | "%s (%d)\n", emsg, rc); | 719 | "%s (%d)\n", emsg, rc); |
@@ -729,17 +788,6 @@ static int ahci_clo(struct ata_port *ap) | |||
729 | return 0; | 788 | return 0; |
730 | } | 789 | } |
731 | 790 | ||
732 | static int ahci_prereset(struct ata_port *ap) | ||
733 | { | ||
734 | if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && | ||
735 | (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { | ||
736 | /* ATA_BUSY hasn't cleared, so send a CLO */ | ||
737 | ahci_clo(ap); | ||
738 | } | ||
739 | |||
740 | return ata_std_prereset(ap); | ||
741 | } | ||
742 | |||
743 | static int ahci_softreset(struct ata_port *ap, unsigned int *class) | 791 | static int ahci_softreset(struct ata_port *ap, unsigned int *class) |
744 | { | 792 | { |
745 | struct ahci_port_priv *pp = ap->private_data; | 793 | struct ahci_port_priv *pp = ap->private_data; |
@@ -877,6 +925,31 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) | |||
877 | return rc; | 925 | return rc; |
878 | } | 926 | } |
879 | 927 | ||
928 | static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class) | ||
929 | { | ||
930 | void __iomem *mmio = ap->host->mmio_base; | ||
931 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); | ||
932 | int rc; | ||
933 | |||
934 | DPRINTK("ENTER\n"); | ||
935 | |||
936 | ahci_stop_engine(port_mmio); | ||
937 | |||
938 | rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context)); | ||
939 | |||
940 | /* vt8251 needs SError cleared for the port to operate */ | ||
941 | ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR)); | ||
942 | |||
943 | ahci_start_engine(port_mmio); | ||
944 | |||
945 | DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); | ||
946 | |||
947 | /* vt8251 doesn't clear BSY on signature FIS reception, | ||
948 | * request follow-up softreset. | ||
949 | */ | ||
950 | return rc ?: -EAGAIN; | ||
951 | } | ||
952 | |||
880 | static void ahci_postreset(struct ata_port *ap, unsigned int *class) | 953 | static void ahci_postreset(struct ata_port *ap, unsigned int *class) |
881 | { | 954 | { |
882 | void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; | 955 | void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; |
@@ -1196,7 +1269,23 @@ static void ahci_error_handler(struct ata_port *ap) | |||
1196 | } | 1269 | } |
1197 | 1270 | ||
1198 | /* perform recovery */ | 1271 | /* perform recovery */ |
1199 | ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset, | 1272 | ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, |
1273 | ahci_postreset); | ||
1274 | } | ||
1275 | |||
1276 | static void ahci_vt8251_error_handler(struct ata_port *ap) | ||
1277 | { | ||
1278 | void __iomem *mmio = ap->host->mmio_base; | ||
1279 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); | ||
1280 | |||
1281 | if (!(ap->pflags & ATA_PFLAG_FROZEN)) { | ||
1282 | /* restart engine */ | ||
1283 | ahci_stop_engine(port_mmio); | ||
1284 | ahci_start_engine(port_mmio); | ||
1285 | } | ||
1286 | |||
1287 | /* perform recovery */ | ||
1288 | ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset, | ||
1200 | ahci_postreset); | 1289 | ahci_postreset); |
1201 | } | 1290 | } |
1202 | 1291 | ||
@@ -1226,7 +1315,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) | |||
1226 | int rc; | 1315 | int rc; |
1227 | 1316 | ||
1228 | rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); | 1317 | rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); |
1229 | if (rc) { | 1318 | if (rc == 0) |
1319 | ahci_power_down(port_mmio, hpriv->cap); | ||
1320 | else { | ||
1230 | ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); | 1321 | ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); |
1231 | ahci_init_port(port_mmio, hpriv->cap, | 1322 | ahci_init_port(port_mmio, hpriv->cap, |
1232 | pp->cmd_slot_dma, pp->rx_fis_dma); | 1323 | pp->cmd_slot_dma, pp->rx_fis_dma); |
@@ -1242,6 +1333,7 @@ static int ahci_port_resume(struct ata_port *ap) | |||
1242 | void __iomem *mmio = ap->host->mmio_base; | 1333 | void __iomem *mmio = ap->host->mmio_base; |
1243 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); | 1334 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); |
1244 | 1335 | ||
1336 | ahci_power_up(port_mmio, hpriv->cap); | ||
1245 | ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); | 1337 | ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); |
1246 | 1338 | ||
1247 | return 0; | 1339 | return 0; |
@@ -1281,7 +1373,8 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) | |||
1281 | if (rc) | 1373 | if (rc) |
1282 | return rc; | 1374 | return rc; |
1283 | 1375 | ||
1284 | ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap); | 1376 | ahci_init_controller(mmio, pdev, host->n_ports, |
1377 | host->ports[0]->flags, hpriv); | ||
1285 | } | 1378 | } |
1286 | 1379 | ||
1287 | ata_host_resume(host); | 1380 | ata_host_resume(host); |
@@ -1347,6 +1440,9 @@ static int ahci_port_start(struct ata_port *ap) | |||
1347 | 1440 | ||
1348 | ap->private_data = pp; | 1441 | ap->private_data = pp; |
1349 | 1442 | ||
1443 | /* power up port */ | ||
1444 | ahci_power_up(port_mmio, hpriv->cap); | ||
1445 | |||
1350 | /* initialize port */ | 1446 | /* initialize port */ |
1351 | ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); | 1447 | ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); |
1352 | 1448 | ||
@@ -1393,7 +1489,7 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
1393 | struct ahci_host_priv *hpriv = probe_ent->private_data; | 1489 | struct ahci_host_priv *hpriv = probe_ent->private_data; |
1394 | struct pci_dev *pdev = to_pci_dev(probe_ent->dev); | 1490 | struct pci_dev *pdev = to_pci_dev(probe_ent->dev); |
1395 | void __iomem *mmio = probe_ent->mmio_base; | 1491 | void __iomem *mmio = probe_ent->mmio_base; |
1396 | unsigned int i, using_dac; | 1492 | unsigned int i, cap_n_ports, using_dac; |
1397 | int rc; | 1493 | int rc; |
1398 | 1494 | ||
1399 | rc = ahci_reset_controller(mmio, pdev); | 1495 | rc = ahci_reset_controller(mmio, pdev); |
@@ -1402,10 +1498,34 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
1402 | 1498 | ||
1403 | hpriv->cap = readl(mmio + HOST_CAP); | 1499 | hpriv->cap = readl(mmio + HOST_CAP); |
1404 | hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); | 1500 | hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); |
1405 | probe_ent->n_ports = (hpriv->cap & 0x1f) + 1; | 1501 | cap_n_ports = ahci_nr_ports(hpriv->cap); |
1406 | 1502 | ||
1407 | VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", | 1503 | VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", |
1408 | hpriv->cap, hpriv->port_map, probe_ent->n_ports); | 1504 | hpriv->cap, hpriv->port_map, cap_n_ports); |
1505 | |||
1506 | if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) { | ||
1507 | unsigned int n_ports = cap_n_ports; | ||
1508 | u32 port_map = hpriv->port_map; | ||
1509 | int max_port = 0; | ||
1510 | |||
1511 | for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) { | ||
1512 | if (port_map & (1 << i)) { | ||
1513 | n_ports--; | ||
1514 | port_map &= ~(1 << i); | ||
1515 | max_port = i; | ||
1516 | } else | ||
1517 | probe_ent->dummy_port_mask |= 1 << i; | ||
1518 | } | ||
1519 | |||
1520 | if (n_ports || port_map) | ||
1521 | dev_printk(KERN_WARNING, &pdev->dev, | ||
1522 | "nr_ports (%u) and implemented port map " | ||
1523 | "(0x%x) don't match\n", | ||
1524 | cap_n_ports, hpriv->port_map); | ||
1525 | |||
1526 | probe_ent->n_ports = max_port + 1; | ||
1527 | } else | ||
1528 | probe_ent->n_ports = cap_n_ports; | ||
1409 | 1529 | ||
1410 | using_dac = hpriv->cap & HOST_CAP_64; | 1530 | using_dac = hpriv->cap & HOST_CAP_64; |
1411 | if (using_dac && | 1531 | if (using_dac && |
@@ -1437,7 +1557,8 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
1437 | for (i = 0; i < probe_ent->n_ports; i++) | 1557 | for (i = 0; i < probe_ent->n_ports; i++) |
1438 | ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i); | 1558 | ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i); |
1439 | 1559 | ||
1440 | ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap); | 1560 | ahci_init_controller(mmio, pdev, probe_ent->n_ports, |
1561 | probe_ent->port_flags, hpriv); | ||
1441 | 1562 | ||
1442 | pci_set_master(pdev); | 1563 | pci_set_master(pdev); |
1443 | 1564 | ||
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 4a80ff9312b8..908751d27e76 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/libata.h> | 26 | #include <linux/libata.h> |
27 | 27 | ||
28 | #define DRV_NAME "ata_generic" | 28 | #define DRV_NAME "ata_generic" |
29 | #define DRV_VERSION "0.2.6" | 29 | #define DRV_VERSION "0.2.10" |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * A generic parallel ATA driver using libata | 32 | * A generic parallel ATA driver using libata |
@@ -109,7 +109,6 @@ static struct scsi_host_template generic_sht = { | |||
109 | .can_queue = ATA_DEF_QUEUE, | 109 | .can_queue = ATA_DEF_QUEUE, |
110 | .this_id = ATA_SHT_THIS_ID, | 110 | .this_id = ATA_SHT_THIS_ID, |
111 | .sg_tablesize = LIBATA_MAX_PRD, | 111 | .sg_tablesize = LIBATA_MAX_PRD, |
112 | .max_sectors = ATA_MAX_SECTORS, | ||
113 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 112 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
114 | .emulated = ATA_SHT_EMULATED, | 113 | .emulated = ATA_SHT_EMULATED, |
115 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 114 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -118,6 +117,8 @@ static struct scsi_host_template generic_sht = { | |||
118 | .slave_configure = ata_scsi_slave_config, | 117 | .slave_configure = ata_scsi_slave_config, |
119 | .slave_destroy = ata_scsi_slave_destroy, | 118 | .slave_destroy = ata_scsi_slave_destroy, |
120 | .bios_param = ata_std_bios_param, | 119 | .bios_param = ata_std_bios_param, |
120 | .resume = ata_scsi_device_resume, | ||
121 | .suspend = ata_scsi_device_suspend, | ||
121 | }; | 122 | }; |
122 | 123 | ||
123 | static struct ata_port_operations generic_port_ops = { | 124 | static struct ata_port_operations generic_port_ops = { |
@@ -226,12 +227,14 @@ static struct pci_driver ata_generic_pci_driver = { | |||
226 | .name = DRV_NAME, | 227 | .name = DRV_NAME, |
227 | .id_table = ata_generic, | 228 | .id_table = ata_generic, |
228 | .probe = ata_generic_init_one, | 229 | .probe = ata_generic_init_one, |
229 | .remove = ata_pci_remove_one | 230 | .remove = ata_pci_remove_one, |
231 | .suspend = ata_pci_device_suspend, | ||
232 | .resume = ata_pci_device_resume, | ||
230 | }; | 233 | }; |
231 | 234 | ||
232 | static int __init ata_generic_init(void) | 235 | static int __init ata_generic_init(void) |
233 | { | 236 | { |
234 | return pci_module_init(&ata_generic_pci_driver); | 237 | return pci_register_driver(&ata_generic_pci_driver); |
235 | } | 238 | } |
236 | 239 | ||
237 | 240 | ||
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 720174d628fa..c7de0bb1591f 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -40,7 +40,7 @@ | |||
40 | * Documentation | 40 | * Documentation |
41 | * Publically available from Intel web site. Errata documentation | 41 | * Publically available from Intel web site. Errata documentation |
42 | * is also publically available. As an aide to anyone hacking on this | 42 | * is also publically available. As an aide to anyone hacking on this |
43 | * driver the list of errata that are relevant is below.going back to | 43 | * driver the list of errata that are relevant is below, going back to |
44 | * PIIX4. Older device documentation is now a bit tricky to find. | 44 | * PIIX4. Older device documentation is now a bit tricky to find. |
45 | * | 45 | * |
46 | * The chipsets all follow very much the same design. The orginal Triton | 46 | * The chipsets all follow very much the same design. The orginal Triton |
@@ -93,7 +93,7 @@ | |||
93 | #include <linux/libata.h> | 93 | #include <linux/libata.h> |
94 | 94 | ||
95 | #define DRV_NAME "ata_piix" | 95 | #define DRV_NAME "ata_piix" |
96 | #define DRV_VERSION "2.00ac6" | 96 | #define DRV_VERSION "2.00ac7" |
97 | 97 | ||
98 | enum { | 98 | enum { |
99 | PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ | 99 | PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ |
@@ -101,11 +101,13 @@ enum { | |||
101 | ICH5_PCS = 0x92, /* port control and status */ | 101 | ICH5_PCS = 0x92, /* port control and status */ |
102 | PIIX_SCC = 0x0A, /* sub-class code register */ | 102 | PIIX_SCC = 0x0A, /* sub-class code register */ |
103 | 103 | ||
104 | PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */ | ||
105 | PIIX_FLAG_SCR = (1 << 26), /* SCR available */ | 104 | PIIX_FLAG_SCR = (1 << 26), /* SCR available */ |
106 | PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ | 105 | PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ |
107 | PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ | 106 | PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ |
108 | 107 | ||
108 | PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS, | ||
109 | PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, | ||
110 | |||
109 | /* combined mode. if set, PATA is channel 0. | 111 | /* combined mode. if set, PATA is channel 0. |
110 | * if clear, PATA is channel 1. | 112 | * if clear, PATA is channel 1. |
111 | */ | 113 | */ |
@@ -122,11 +124,10 @@ enum { | |||
122 | ich_pata_100 = 3, /* ICH up to UDMA 100 */ | 124 | ich_pata_100 = 3, /* ICH up to UDMA 100 */ |
123 | ich_pata_133 = 4, /* ICH up to UDMA 133 */ | 125 | ich_pata_133 = 4, /* ICH up to UDMA 133 */ |
124 | ich5_sata = 5, | 126 | ich5_sata = 5, |
125 | esb_sata = 6, | 127 | ich6_sata = 6, |
126 | ich6_sata = 7, | 128 | ich6_sata_ahci = 7, |
127 | ich6_sata_ahci = 8, | 129 | ich6m_sata_ahci = 8, |
128 | ich6m_sata_ahci = 9, | 130 | ich8_sata_ahci = 9, |
129 | ich8_sata_ahci = 10, | ||
130 | 131 | ||
131 | /* constants for mapping table */ | 132 | /* constants for mapping table */ |
132 | P0 = 0, /* port 0 */ | 133 | P0 = 0, /* port 0 */ |
@@ -143,13 +144,11 @@ enum { | |||
143 | struct piix_map_db { | 144 | struct piix_map_db { |
144 | const u32 mask; | 145 | const u32 mask; |
145 | const u16 port_enable; | 146 | const u16 port_enable; |
146 | const int present_shift; | ||
147 | const int map[][4]; | 147 | const int map[][4]; |
148 | }; | 148 | }; |
149 | 149 | ||
150 | struct piix_host_priv { | 150 | struct piix_host_priv { |
151 | const int *map; | 151 | const int *map; |
152 | const struct piix_map_db *map_db; | ||
153 | }; | 152 | }; |
154 | 153 | ||
155 | static int piix_init_one (struct pci_dev *pdev, | 154 | static int piix_init_one (struct pci_dev *pdev, |
@@ -214,9 +213,9 @@ static const struct pci_device_id piix_pci_tbl[] = { | |||
214 | /* 82801EB (ICH5) */ | 213 | /* 82801EB (ICH5) */ |
215 | { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, | 214 | { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, |
216 | /* 6300ESB (ICH5 variant with broken PCS present bits) */ | 215 | /* 6300ESB (ICH5 variant with broken PCS present bits) */ |
217 | { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, | 216 | { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, |
218 | /* 6300ESB pretending RAID */ | 217 | /* 6300ESB pretending RAID */ |
219 | { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, | 218 | { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, |
220 | /* 82801FB/FW (ICH6/ICH6W) */ | 219 | /* 82801FB/FW (ICH6/ICH6W) */ |
221 | { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, | 220 | { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, |
222 | /* 82801FR/FRW (ICH6R/ICH6RW) */ | 221 | /* 82801FR/FRW (ICH6R/ICH6RW) */ |
@@ -367,7 +366,6 @@ static const struct ata_port_operations piix_sata_ops = { | |||
367 | static const struct piix_map_db ich5_map_db = { | 366 | static const struct piix_map_db ich5_map_db = { |
368 | .mask = 0x7, | 367 | .mask = 0x7, |
369 | .port_enable = 0x3, | 368 | .port_enable = 0x3, |
370 | .present_shift = 4, | ||
371 | .map = { | 369 | .map = { |
372 | /* PM PS SM SS MAP */ | 370 | /* PM PS SM SS MAP */ |
373 | { P0, NA, P1, NA }, /* 000b */ | 371 | { P0, NA, P1, NA }, /* 000b */ |
@@ -384,7 +382,6 @@ static const struct piix_map_db ich5_map_db = { | |||
384 | static const struct piix_map_db ich6_map_db = { | 382 | static const struct piix_map_db ich6_map_db = { |
385 | .mask = 0x3, | 383 | .mask = 0x3, |
386 | .port_enable = 0xf, | 384 | .port_enable = 0xf, |
387 | .present_shift = 4, | ||
388 | .map = { | 385 | .map = { |
389 | /* PM PS SM SS MAP */ | 386 | /* PM PS SM SS MAP */ |
390 | { P0, P2, P1, P3 }, /* 00b */ | 387 | { P0, P2, P1, P3 }, /* 00b */ |
@@ -397,7 +394,6 @@ static const struct piix_map_db ich6_map_db = { | |||
397 | static const struct piix_map_db ich6m_map_db = { | 394 | static const struct piix_map_db ich6m_map_db = { |
398 | .mask = 0x3, | 395 | .mask = 0x3, |
399 | .port_enable = 0x5, | 396 | .port_enable = 0x5, |
400 | .present_shift = 4, | ||
401 | 397 | ||
402 | /* Map 01b isn't specified in the doc but some notebooks use | 398 | /* Map 01b isn't specified in the doc but some notebooks use |
403 | * it anyway. MAP 01b have been spotted on both ICH6M and | 399 | * it anyway. MAP 01b have been spotted on both ICH6M and |
@@ -415,7 +411,6 @@ static const struct piix_map_db ich6m_map_db = { | |||
415 | static const struct piix_map_db ich8_map_db = { | 411 | static const struct piix_map_db ich8_map_db = { |
416 | .mask = 0x3, | 412 | .mask = 0x3, |
417 | .port_enable = 0x3, | 413 | .port_enable = 0x3, |
418 | .present_shift = 8, | ||
419 | .map = { | 414 | .map = { |
420 | /* PM PS SM SS MAP */ | 415 | /* PM PS SM SS MAP */ |
421 | { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ | 416 | { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ |
@@ -427,7 +422,6 @@ static const struct piix_map_db ich8_map_db = { | |||
427 | 422 | ||
428 | static const struct piix_map_db *piix_map_db_table[] = { | 423 | static const struct piix_map_db *piix_map_db_table[] = { |
429 | [ich5_sata] = &ich5_map_db, | 424 | [ich5_sata] = &ich5_map_db, |
430 | [esb_sata] = &ich5_map_db, | ||
431 | [ich6_sata] = &ich6_map_db, | 425 | [ich6_sata] = &ich6_map_db, |
432 | [ich6_sata_ahci] = &ich6_map_db, | 426 | [ich6_sata_ahci] = &ich6_map_db, |
433 | [ich6m_sata_ahci] = &ich6m_map_db, | 427 | [ich6m_sata_ahci] = &ich6m_map_db, |
@@ -438,7 +432,7 @@ static struct ata_port_info piix_port_info[] = { | |||
438 | /* piix_pata_33: 0: PIIX3 or 4 at 33MHz */ | 432 | /* piix_pata_33: 0: PIIX3 or 4 at 33MHz */ |
439 | { | 433 | { |
440 | .sht = &piix_sht, | 434 | .sht = &piix_sht, |
441 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 435 | .flags = PIIX_PATA_FLAGS, |
442 | .pio_mask = 0x1f, /* pio0-4 */ | 436 | .pio_mask = 0x1f, /* pio0-4 */ |
443 | .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ | 437 | .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ |
444 | .udma_mask = ATA_UDMA_MASK_40C, | 438 | .udma_mask = ATA_UDMA_MASK_40C, |
@@ -448,7 +442,7 @@ static struct ata_port_info piix_port_info[] = { | |||
448 | /* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/ | 442 | /* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/ |
449 | { | 443 | { |
450 | .sht = &piix_sht, | 444 | .sht = &piix_sht, |
451 | .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, | 445 | .flags = PIIX_PATA_FLAGS, |
452 | .pio_mask = 0x1f, /* pio 0-4 */ | 446 | .pio_mask = 0x1f, /* pio 0-4 */ |
453 | .mwdma_mask = 0x06, /* Check: maybe 0x07 */ | 447 | .mwdma_mask = 0x06, /* Check: maybe 0x07 */ |
454 | .udma_mask = ATA_UDMA2, /* UDMA33 */ | 448 | .udma_mask = ATA_UDMA2, /* UDMA33 */ |
@@ -457,7 +451,7 @@ static struct ata_port_info piix_port_info[] = { | |||
457 | /* ich_pata_66: 2 ICH controllers up to 66MHz */ | 451 | /* ich_pata_66: 2 ICH controllers up to 66MHz */ |
458 | { | 452 | { |
459 | .sht = &piix_sht, | 453 | .sht = &piix_sht, |
460 | .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, | 454 | .flags = PIIX_PATA_FLAGS, |
461 | .pio_mask = 0x1f, /* pio 0-4 */ | 455 | .pio_mask = 0x1f, /* pio 0-4 */ |
462 | .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ | 456 | .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ |
463 | .udma_mask = ATA_UDMA4, | 457 | .udma_mask = ATA_UDMA4, |
@@ -467,7 +461,7 @@ static struct ata_port_info piix_port_info[] = { | |||
467 | /* ich_pata_100: 3 */ | 461 | /* ich_pata_100: 3 */ |
468 | { | 462 | { |
469 | .sht = &piix_sht, | 463 | .sht = &piix_sht, |
470 | .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, | 464 | .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, |
471 | .pio_mask = 0x1f, /* pio0-4 */ | 465 | .pio_mask = 0x1f, /* pio0-4 */ |
472 | .mwdma_mask = 0x06, /* mwdma1-2 */ | 466 | .mwdma_mask = 0x06, /* mwdma1-2 */ |
473 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 467 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
@@ -477,7 +471,7 @@ static struct ata_port_info piix_port_info[] = { | |||
477 | /* ich_pata_133: 4 ICH with full UDMA6 */ | 471 | /* ich_pata_133: 4 ICH with full UDMA6 */ |
478 | { | 472 | { |
479 | .sht = &piix_sht, | 473 | .sht = &piix_sht, |
480 | .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, | 474 | .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, |
481 | .pio_mask = 0x1f, /* pio 0-4 */ | 475 | .pio_mask = 0x1f, /* pio 0-4 */ |
482 | .mwdma_mask = 0x06, /* Check: maybe 0x07 */ | 476 | .mwdma_mask = 0x06, /* Check: maybe 0x07 */ |
483 | .udma_mask = ATA_UDMA6, /* UDMA133 */ | 477 | .udma_mask = ATA_UDMA6, /* UDMA133 */ |
@@ -487,41 +481,27 @@ static struct ata_port_info piix_port_info[] = { | |||
487 | /* ich5_sata: 5 */ | 481 | /* ich5_sata: 5 */ |
488 | { | 482 | { |
489 | .sht = &piix_sht, | 483 | .sht = &piix_sht, |
490 | .flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR | | 484 | .flags = PIIX_SATA_FLAGS, |
491 | PIIX_FLAG_IGNORE_PCS, | ||
492 | .pio_mask = 0x1f, /* pio0-4 */ | ||
493 | .mwdma_mask = 0x07, /* mwdma0-2 */ | ||
494 | .udma_mask = 0x7f, /* udma0-6 */ | ||
495 | .port_ops = &piix_sata_ops, | ||
496 | }, | ||
497 | |||
498 | /* i6300esb_sata: 6 */ | ||
499 | { | ||
500 | .sht = &piix_sht, | ||
501 | .flags = ATA_FLAG_SATA | | ||
502 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS, | ||
503 | .pio_mask = 0x1f, /* pio0-4 */ | 485 | .pio_mask = 0x1f, /* pio0-4 */ |
504 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 486 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
505 | .udma_mask = 0x7f, /* udma0-6 */ | 487 | .udma_mask = 0x7f, /* udma0-6 */ |
506 | .port_ops = &piix_sata_ops, | 488 | .port_ops = &piix_sata_ops, |
507 | }, | 489 | }, |
508 | 490 | ||
509 | /* ich6_sata: 7 */ | 491 | /* ich6_sata: 6 */ |
510 | { | 492 | { |
511 | .sht = &piix_sht, | 493 | .sht = &piix_sht, |
512 | .flags = ATA_FLAG_SATA | | 494 | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR, |
513 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, | ||
514 | .pio_mask = 0x1f, /* pio0-4 */ | 495 | .pio_mask = 0x1f, /* pio0-4 */ |
515 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 496 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
516 | .udma_mask = 0x7f, /* udma0-6 */ | 497 | .udma_mask = 0x7f, /* udma0-6 */ |
517 | .port_ops = &piix_sata_ops, | 498 | .port_ops = &piix_sata_ops, |
518 | }, | 499 | }, |
519 | 500 | ||
520 | /* ich6_sata_ahci: 8 */ | 501 | /* ich6_sata_ahci: 7 */ |
521 | { | 502 | { |
522 | .sht = &piix_sht, | 503 | .sht = &piix_sht, |
523 | .flags = ATA_FLAG_SATA | | 504 | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | |
524 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | | ||
525 | PIIX_FLAG_AHCI, | 505 | PIIX_FLAG_AHCI, |
526 | .pio_mask = 0x1f, /* pio0-4 */ | 506 | .pio_mask = 0x1f, /* pio0-4 */ |
527 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 507 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
@@ -529,11 +509,10 @@ static struct ata_port_info piix_port_info[] = { | |||
529 | .port_ops = &piix_sata_ops, | 509 | .port_ops = &piix_sata_ops, |
530 | }, | 510 | }, |
531 | 511 | ||
532 | /* ich6m_sata_ahci: 9 */ | 512 | /* ich6m_sata_ahci: 8 */ |
533 | { | 513 | { |
534 | .sht = &piix_sht, | 514 | .sht = &piix_sht, |
535 | .flags = ATA_FLAG_SATA | | 515 | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | |
536 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | | ||
537 | PIIX_FLAG_AHCI, | 516 | PIIX_FLAG_AHCI, |
538 | .pio_mask = 0x1f, /* pio0-4 */ | 517 | .pio_mask = 0x1f, /* pio0-4 */ |
539 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 518 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
@@ -541,11 +520,10 @@ static struct ata_port_info piix_port_info[] = { | |||
541 | .port_ops = &piix_sata_ops, | 520 | .port_ops = &piix_sata_ops, |
542 | }, | 521 | }, |
543 | 522 | ||
544 | /* ich8_sata_ahci: 10 */ | 523 | /* ich8_sata_ahci: 9 */ |
545 | { | 524 | { |
546 | .sht = &piix_sht, | 525 | .sht = &piix_sht, |
547 | .flags = ATA_FLAG_SATA | | 526 | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | |
548 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | | ||
549 | PIIX_FLAG_AHCI, | 527 | PIIX_FLAG_AHCI, |
550 | .pio_mask = 0x1f, /* pio0-4 */ | 528 | .pio_mask = 0x1f, /* pio0-4 */ |
551 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 529 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
@@ -566,10 +544,22 @@ MODULE_LICENSE("GPL"); | |||
566 | MODULE_DEVICE_TABLE(pci, piix_pci_tbl); | 544 | MODULE_DEVICE_TABLE(pci, piix_pci_tbl); |
567 | MODULE_VERSION(DRV_VERSION); | 545 | MODULE_VERSION(DRV_VERSION); |
568 | 546 | ||
569 | static int force_pcs = 0; | 547 | struct ich_laptop { |
570 | module_param(force_pcs, int, 0444); | 548 | u16 device; |
571 | MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " | 549 | u16 subvendor; |
572 | "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)"); | 550 | u16 subdevice; |
551 | }; | ||
552 | |||
553 | /* | ||
554 | * List of laptops that use short cables rather than 80 wire | ||
555 | */ | ||
556 | |||
557 | static const struct ich_laptop ich_laptop[] = { | ||
558 | /* devid, subvendor, subdev */ | ||
559 | { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ | ||
560 | /* end marker */ | ||
561 | { 0, } | ||
562 | }; | ||
573 | 563 | ||
574 | /** | 564 | /** |
575 | * piix_pata_cbl_detect - Probe host controller cable detect info | 565 | * piix_pata_cbl_detect - Probe host controller cable detect info |
@@ -585,12 +575,24 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " | |||
585 | static void ich_pata_cbl_detect(struct ata_port *ap) | 575 | static void ich_pata_cbl_detect(struct ata_port *ap) |
586 | { | 576 | { |
587 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 577 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
578 | const struct ich_laptop *lap = &ich_laptop[0]; | ||
588 | u8 tmp, mask; | 579 | u8 tmp, mask; |
589 | 580 | ||
590 | /* no 80c support in host controller? */ | 581 | /* no 80c support in host controller? */ |
591 | if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) | 582 | if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) |
592 | goto cbl40; | 583 | goto cbl40; |
593 | 584 | ||
585 | /* Check for specials - Acer Aspire 5602WLMi */ | ||
586 | while (lap->device) { | ||
587 | if (lap->device == pdev->device && | ||
588 | lap->subvendor == pdev->subsystem_vendor && | ||
589 | lap->subdevice == pdev->subsystem_device) { | ||
590 | ap->cbl = ATA_CBL_PATA40_SHORT; | ||
591 | return; | ||
592 | } | ||
593 | lap++; | ||
594 | } | ||
595 | |||
594 | /* check BIOS cable detect results */ | 596 | /* check BIOS cable detect results */ |
595 | mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; | 597 | mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; |
596 | pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); | 598 | pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); |
@@ -659,84 +661,9 @@ static void ich_pata_error_handler(struct ata_port *ap) | |||
659 | ata_std_postreset); | 661 | ata_std_postreset); |
660 | } | 662 | } |
661 | 663 | ||
662 | /** | ||
663 | * piix_sata_present_mask - determine present mask for SATA host controller | ||
664 | * @ap: Target port | ||
665 | * | ||
666 | * Reads SATA PCI device's PCI config register Port Configuration | ||
667 | * and Status (PCS) to determine port and device availability. | ||
668 | * | ||
669 | * LOCKING: | ||
670 | * None (inherited from caller). | ||
671 | * | ||
672 | * RETURNS: | ||
673 | * determined present_mask | ||
674 | */ | ||
675 | static unsigned int piix_sata_present_mask(struct ata_port *ap) | ||
676 | { | ||
677 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
678 | struct piix_host_priv *hpriv = ap->host->private_data; | ||
679 | const unsigned int *map = hpriv->map; | ||
680 | int base = 2 * ap->port_no; | ||
681 | unsigned int present_mask = 0; | ||
682 | int port, i; | ||
683 | u16 pcs; | ||
684 | |||
685 | pci_read_config_word(pdev, ICH5_PCS, &pcs); | ||
686 | DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); | ||
687 | |||
688 | for (i = 0; i < 2; i++) { | ||
689 | port = map[base + i]; | ||
690 | if (port < 0) | ||
691 | continue; | ||
692 | if ((ap->flags & PIIX_FLAG_IGNORE_PCS) || | ||
693 | (pcs & 1 << (hpriv->map_db->present_shift + port))) | ||
694 | present_mask |= 1 << i; | ||
695 | } | ||
696 | |||
697 | DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", | ||
698 | ap->id, pcs, present_mask); | ||
699 | |||
700 | return present_mask; | ||
701 | } | ||
702 | |||
703 | /** | ||
704 | * piix_sata_softreset - reset SATA host port via ATA SRST | ||
705 | * @ap: port to reset | ||
706 | * @classes: resulting classes of attached devices | ||
707 | * | ||
708 | * Reset SATA host port via ATA SRST. On controllers with | ||
709 | * reliable PCS present bits, the bits are used to determine | ||
710 | * device presence. | ||
711 | * | ||
712 | * LOCKING: | ||
713 | * Kernel thread context (may sleep) | ||
714 | * | ||
715 | * RETURNS: | ||
716 | * 0 on success, -errno otherwise. | ||
717 | */ | ||
718 | static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes) | ||
719 | { | ||
720 | unsigned int present_mask; | ||
721 | int i, rc; | ||
722 | |||
723 | present_mask = piix_sata_present_mask(ap); | ||
724 | |||
725 | rc = ata_std_softreset(ap, classes); | ||
726 | if (rc) | ||
727 | return rc; | ||
728 | |||
729 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | ||
730 | if (!(present_mask & (1 << i))) | ||
731 | classes[i] = ATA_DEV_NONE; | ||
732 | } | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | static void piix_sata_error_handler(struct ata_port *ap) | 664 | static void piix_sata_error_handler(struct ata_port *ap) |
738 | { | 665 | { |
739 | ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL, | 666 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL, |
740 | ata_std_postreset); | 667 | ata_std_postreset); |
741 | } | 668 | } |
742 | 669 | ||
@@ -1051,18 +978,6 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev, | |||
1051 | pci_write_config_word(pdev, ICH5_PCS, new_pcs); | 978 | pci_write_config_word(pdev, ICH5_PCS, new_pcs); |
1052 | msleep(150); | 979 | msleep(150); |
1053 | } | 980 | } |
1054 | |||
1055 | if (force_pcs == 1) { | ||
1056 | dev_printk(KERN_INFO, &pdev->dev, | ||
1057 | "force ignoring PCS (0x%x)\n", new_pcs); | ||
1058 | pinfo[0].flags |= PIIX_FLAG_IGNORE_PCS; | ||
1059 | pinfo[1].flags |= PIIX_FLAG_IGNORE_PCS; | ||
1060 | } else if (force_pcs == 2) { | ||
1061 | dev_printk(KERN_INFO, &pdev->dev, | ||
1062 | "force honoring PCS (0x%x)\n", new_pcs); | ||
1063 | pinfo[0].flags &= ~PIIX_FLAG_IGNORE_PCS; | ||
1064 | pinfo[1].flags &= ~PIIX_FLAG_IGNORE_PCS; | ||
1065 | } | ||
1066 | } | 981 | } |
1067 | 982 | ||
1068 | static void __devinit piix_init_sata_map(struct pci_dev *pdev, | 983 | static void __devinit piix_init_sata_map(struct pci_dev *pdev, |
@@ -1112,7 +1027,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, | |||
1112 | "invalid MAP value %u\n", map_value); | 1027 | "invalid MAP value %u\n", map_value); |
1113 | 1028 | ||
1114 | hpriv->map = map; | 1029 | hpriv->map = map; |
1115 | hpriv->map_db = map_db; | ||
1116 | } | 1030 | } |
1117 | 1031 | ||
1118 | /** | 1032 | /** |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 915a55a6cc14..f8ec3896b793 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -199,7 +199,8 @@ static const u8 ata_rw_cmds[] = { | |||
199 | 199 | ||
200 | /** | 200 | /** |
201 | * ata_rwcmd_protocol - set taskfile r/w commands and protocol | 201 | * ata_rwcmd_protocol - set taskfile r/w commands and protocol |
202 | * @qc: command to examine and configure | 202 | * @tf: command to examine and configure |
203 | * @dev: device tf belongs to | ||
203 | * | 204 | * |
204 | * Examine the device configuration and tf->flags to calculate | 205 | * Examine the device configuration and tf->flags to calculate |
205 | * the proper read/write commands and protocol to use. | 206 | * the proper read/write commands and protocol to use. |
@@ -207,10 +208,8 @@ static const u8 ata_rw_cmds[] = { | |||
207 | * LOCKING: | 208 | * LOCKING: |
208 | * caller. | 209 | * caller. |
209 | */ | 210 | */ |
210 | int ata_rwcmd_protocol(struct ata_queued_cmd *qc) | 211 | static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev) |
211 | { | 212 | { |
212 | struct ata_taskfile *tf = &qc->tf; | ||
213 | struct ata_device *dev = qc->dev; | ||
214 | u8 cmd; | 213 | u8 cmd; |
215 | 214 | ||
216 | int index, fua, lba48, write; | 215 | int index, fua, lba48, write; |
@@ -222,7 +221,7 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) | |||
222 | if (dev->flags & ATA_DFLAG_PIO) { | 221 | if (dev->flags & ATA_DFLAG_PIO) { |
223 | tf->protocol = ATA_PROT_PIO; | 222 | tf->protocol = ATA_PROT_PIO; |
224 | index = dev->multi_count ? 0 : 8; | 223 | index = dev->multi_count ? 0 : 8; |
225 | } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) { | 224 | } else if (lba48 && (dev->ap->flags & ATA_FLAG_PIO_LBA48)) { |
226 | /* Unable to use DMA due to host limitation */ | 225 | /* Unable to use DMA due to host limitation */ |
227 | tf->protocol = ATA_PROT_PIO; | 226 | tf->protocol = ATA_PROT_PIO; |
228 | index = dev->multi_count ? 0 : 8; | 227 | index = dev->multi_count ? 0 : 8; |
@@ -240,6 +239,174 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) | |||
240 | } | 239 | } |
241 | 240 | ||
242 | /** | 241 | /** |
242 | * ata_tf_read_block - Read block address from ATA taskfile | ||
243 | * @tf: ATA taskfile of interest | ||
244 | * @dev: ATA device @tf belongs to | ||
245 | * | ||
246 | * LOCKING: | ||
247 | * None. | ||
248 | * | ||
249 | * Read block address from @tf. This function can handle all | ||
250 | * three address formats - LBA, LBA48 and CHS. tf->protocol and | ||
251 | * flags select the address format to use. | ||
252 | * | ||
253 | * RETURNS: | ||
254 | * Block address read from @tf. | ||
255 | */ | ||
256 | u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) | ||
257 | { | ||
258 | u64 block = 0; | ||
259 | |||
260 | if (tf->flags & ATA_TFLAG_LBA) { | ||
261 | if (tf->flags & ATA_TFLAG_LBA48) { | ||
262 | block |= (u64)tf->hob_lbah << 40; | ||
263 | block |= (u64)tf->hob_lbam << 32; | ||
264 | block |= tf->hob_lbal << 24; | ||
265 | } else | ||
266 | block |= (tf->device & 0xf) << 24; | ||
267 | |||
268 | block |= tf->lbah << 16; | ||
269 | block |= tf->lbam << 8; | ||
270 | block |= tf->lbal; | ||
271 | } else { | ||
272 | u32 cyl, head, sect; | ||
273 | |||
274 | cyl = tf->lbam | (tf->lbah << 8); | ||
275 | head = tf->device & 0xf; | ||
276 | sect = tf->lbal; | ||
277 | |||
278 | block = (cyl * dev->heads + head) * dev->sectors + sect; | ||
279 | } | ||
280 | |||
281 | return block; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * ata_build_rw_tf - Build ATA taskfile for given read/write request | ||
286 | * @tf: Target ATA taskfile | ||
287 | * @dev: ATA device @tf belongs to | ||
288 | * @block: Block address | ||
289 | * @n_block: Number of blocks | ||
290 | * @tf_flags: RW/FUA etc... | ||
291 | * @tag: tag | ||
292 | * | ||
293 | * LOCKING: | ||
294 | * None. | ||
295 | * | ||
296 | * Build ATA taskfile @tf for read/write request described by | ||
297 | * @block, @n_block, @tf_flags and @tag on @dev. | ||
298 | * | ||
299 | * RETURNS: | ||
300 | * | ||
301 | * 0 on success, -ERANGE if the request is too large for @dev, | ||
302 | * -EINVAL if the request is invalid. | ||
303 | */ | ||
304 | int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, | ||
305 | u64 block, u32 n_block, unsigned int tf_flags, | ||
306 | unsigned int tag) | ||
307 | { | ||
308 | tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | ||
309 | tf->flags |= tf_flags; | ||
310 | |||
311 | if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF | | ||
312 | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ && | ||
313 | likely(tag != ATA_TAG_INTERNAL)) { | ||
314 | /* yay, NCQ */ | ||
315 | if (!lba_48_ok(block, n_block)) | ||
316 | return -ERANGE; | ||
317 | |||
318 | tf->protocol = ATA_PROT_NCQ; | ||
319 | tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; | ||
320 | |||
321 | if (tf->flags & ATA_TFLAG_WRITE) | ||
322 | tf->command = ATA_CMD_FPDMA_WRITE; | ||
323 | else | ||
324 | tf->command = ATA_CMD_FPDMA_READ; | ||
325 | |||
326 | tf->nsect = tag << 3; | ||
327 | tf->hob_feature = (n_block >> 8) & 0xff; | ||
328 | tf->feature = n_block & 0xff; | ||
329 | |||
330 | tf->hob_lbah = (block >> 40) & 0xff; | ||
331 | tf->hob_lbam = (block >> 32) & 0xff; | ||
332 | tf->hob_lbal = (block >> 24) & 0xff; | ||
333 | tf->lbah = (block >> 16) & 0xff; | ||
334 | tf->lbam = (block >> 8) & 0xff; | ||
335 | tf->lbal = block & 0xff; | ||
336 | |||
337 | tf->device = 1 << 6; | ||
338 | if (tf->flags & ATA_TFLAG_FUA) | ||
339 | tf->device |= 1 << 7; | ||
340 | } else if (dev->flags & ATA_DFLAG_LBA) { | ||
341 | tf->flags |= ATA_TFLAG_LBA; | ||
342 | |||
343 | if (lba_28_ok(block, n_block)) { | ||
344 | /* use LBA28 */ | ||
345 | tf->device |= (block >> 24) & 0xf; | ||
346 | } else if (lba_48_ok(block, n_block)) { | ||
347 | if (!(dev->flags & ATA_DFLAG_LBA48)) | ||
348 | return -ERANGE; | ||
349 | |||
350 | /* use LBA48 */ | ||
351 | tf->flags |= ATA_TFLAG_LBA48; | ||
352 | |||
353 | tf->hob_nsect = (n_block >> 8) & 0xff; | ||
354 | |||
355 | tf->hob_lbah = (block >> 40) & 0xff; | ||
356 | tf->hob_lbam = (block >> 32) & 0xff; | ||
357 | tf->hob_lbal = (block >> 24) & 0xff; | ||
358 | } else | ||
359 | /* request too large even for LBA48 */ | ||
360 | return -ERANGE; | ||
361 | |||
362 | if (unlikely(ata_rwcmd_protocol(tf, dev) < 0)) | ||
363 | return -EINVAL; | ||
364 | |||
365 | tf->nsect = n_block & 0xff; | ||
366 | |||
367 | tf->lbah = (block >> 16) & 0xff; | ||
368 | tf->lbam = (block >> 8) & 0xff; | ||
369 | tf->lbal = block & 0xff; | ||
370 | |||
371 | tf->device |= ATA_LBA; | ||
372 | } else { | ||
373 | /* CHS */ | ||
374 | u32 sect, head, cyl, track; | ||
375 | |||
376 | /* The request -may- be too large for CHS addressing. */ | ||
377 | if (!lba_28_ok(block, n_block)) | ||
378 | return -ERANGE; | ||
379 | |||
380 | if (unlikely(ata_rwcmd_protocol(tf, dev) < 0)) | ||
381 | return -EINVAL; | ||
382 | |||
383 | /* Convert LBA to CHS */ | ||
384 | track = (u32)block / dev->sectors; | ||
385 | cyl = track / dev->heads; | ||
386 | head = track % dev->heads; | ||
387 | sect = (u32)block % dev->sectors + 1; | ||
388 | |||
389 | DPRINTK("block %u track %u cyl %u head %u sect %u\n", | ||
390 | (u32)block, track, cyl, head, sect); | ||
391 | |||
392 | /* Check whether the converted CHS can fit. | ||
393 | Cylinder: 0-65535 | ||
394 | Head: 0-15 | ||
395 | Sector: 1-255*/ | ||
396 | if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) | ||
397 | return -ERANGE; | ||
398 | |||
399 | tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ | ||
400 | tf->lbal = sect; | ||
401 | tf->lbam = cyl; | ||
402 | tf->lbah = cyl >> 8; | ||
403 | tf->device |= head; | ||
404 | } | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | /** | ||
243 | * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask | 410 | * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask |
244 | * @pio_mask: pio_mask | 411 | * @pio_mask: pio_mask |
245 | * @mwdma_mask: mwdma_mask | 412 | * @mwdma_mask: mwdma_mask |
@@ -999,13 +1166,13 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) | |||
999 | } | 1166 | } |
1000 | 1167 | ||
1001 | /** | 1168 | /** |
1002 | * ata_exec_internal - execute libata internal command | 1169 | * ata_exec_internal_sg - execute libata internal command |
1003 | * @dev: Device to which the command is sent | 1170 | * @dev: Device to which the command is sent |
1004 | * @tf: Taskfile registers for the command and the result | 1171 | * @tf: Taskfile registers for the command and the result |
1005 | * @cdb: CDB for packet command | 1172 | * @cdb: CDB for packet command |
1006 | * @dma_dir: Data tranfer direction of the command | 1173 | * @dma_dir: Data tranfer direction of the command |
1007 | * @buf: Data buffer of the command | 1174 | * @sg: sg list for the data buffer of the command |
1008 | * @buflen: Length of data buffer | 1175 | * @n_elem: Number of sg entries |
1009 | * | 1176 | * |
1010 | * Executes libata internal command with timeout. @tf contains | 1177 | * Executes libata internal command with timeout. @tf contains |
1011 | * command on entry and result on return. Timeout and error | 1178 | * command on entry and result on return. Timeout and error |
@@ -1019,9 +1186,10 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) | |||
1019 | * RETURNS: | 1186 | * RETURNS: |
1020 | * Zero on success, AC_ERR_* mask on failure | 1187 | * Zero on success, AC_ERR_* mask on failure |
1021 | */ | 1188 | */ |
1022 | unsigned ata_exec_internal(struct ata_device *dev, | 1189 | unsigned ata_exec_internal_sg(struct ata_device *dev, |
1023 | struct ata_taskfile *tf, const u8 *cdb, | 1190 | struct ata_taskfile *tf, const u8 *cdb, |
1024 | int dma_dir, void *buf, unsigned int buflen) | 1191 | int dma_dir, struct scatterlist *sg, |
1192 | unsigned int n_elem) | ||
1025 | { | 1193 | { |
1026 | struct ata_port *ap = dev->ap; | 1194 | struct ata_port *ap = dev->ap; |
1027 | u8 command = tf->command; | 1195 | u8 command = tf->command; |
@@ -1077,7 +1245,12 @@ unsigned ata_exec_internal(struct ata_device *dev, | |||
1077 | qc->flags |= ATA_QCFLAG_RESULT_TF; | 1245 | qc->flags |= ATA_QCFLAG_RESULT_TF; |
1078 | qc->dma_dir = dma_dir; | 1246 | qc->dma_dir = dma_dir; |
1079 | if (dma_dir != DMA_NONE) { | 1247 | if (dma_dir != DMA_NONE) { |
1080 | ata_sg_init_one(qc, buf, buflen); | 1248 | unsigned int i, buflen = 0; |
1249 | |||
1250 | for (i = 0; i < n_elem; i++) | ||
1251 | buflen += sg[i].length; | ||
1252 | |||
1253 | ata_sg_init(qc, sg, n_elem); | ||
1081 | qc->nsect = buflen / ATA_SECT_SIZE; | 1254 | qc->nsect = buflen / ATA_SECT_SIZE; |
1082 | } | 1255 | } |
1083 | 1256 | ||
@@ -1161,6 +1334,35 @@ unsigned ata_exec_internal(struct ata_device *dev, | |||
1161 | } | 1334 | } |
1162 | 1335 | ||
1163 | /** | 1336 | /** |
1337 | * ata_exec_internal_sg - execute libata internal command | ||
1338 | * @dev: Device to which the command is sent | ||
1339 | * @tf: Taskfile registers for the command and the result | ||
1340 | * @cdb: CDB for packet command | ||
1341 | * @dma_dir: Data tranfer direction of the command | ||
1342 | * @buf: Data buffer of the command | ||
1343 | * @buflen: Length of data buffer | ||
1344 | * | ||
1345 | * Wrapper around ata_exec_internal_sg() which takes simple | ||
1346 | * buffer instead of sg list. | ||
1347 | * | ||
1348 | * LOCKING: | ||
1349 | * None. Should be called with kernel context, might sleep. | ||
1350 | * | ||
1351 | * RETURNS: | ||
1352 | * Zero on success, AC_ERR_* mask on failure | ||
1353 | */ | ||
1354 | unsigned ata_exec_internal(struct ata_device *dev, | ||
1355 | struct ata_taskfile *tf, const u8 *cdb, | ||
1356 | int dma_dir, void *buf, unsigned int buflen) | ||
1357 | { | ||
1358 | struct scatterlist sg; | ||
1359 | |||
1360 | sg_init_one(&sg, buf, buflen); | ||
1361 | |||
1362 | return ata_exec_internal_sg(dev, tf, cdb, dma_dir, &sg, 1); | ||
1363 | } | ||
1364 | |||
1365 | /** | ||
1164 | * ata_do_simple_cmd - execute simple internal command | 1366 | * ata_do_simple_cmd - execute simple internal command |
1165 | * @dev: Device to which the command is sent | 1367 | * @dev: Device to which the command is sent |
1166 | * @cmd: Opcode to execute | 1368 | * @cmd: Opcode to execute |
@@ -1224,7 +1426,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) | |||
1224 | * ata_dev_read_id - Read ID data from the specified device | 1426 | * ata_dev_read_id - Read ID data from the specified device |
1225 | * @dev: target device | 1427 | * @dev: target device |
1226 | * @p_class: pointer to class of the target device (may be changed) | 1428 | * @p_class: pointer to class of the target device (may be changed) |
1227 | * @post_reset: is this read ID post-reset? | 1429 | * @flags: ATA_READID_* flags |
1228 | * @id: buffer to read IDENTIFY data into | 1430 | * @id: buffer to read IDENTIFY data into |
1229 | * | 1431 | * |
1230 | * Read ID data from the specified device. ATA_CMD_ID_ATA is | 1432 | * Read ID data from the specified device. ATA_CMD_ID_ATA is |
@@ -1239,7 +1441,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) | |||
1239 | * 0 on success, -errno otherwise. | 1441 | * 0 on success, -errno otherwise. |
1240 | */ | 1442 | */ |
1241 | int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | 1443 | int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, |
1242 | int post_reset, u16 *id) | 1444 | unsigned int flags, u16 *id) |
1243 | { | 1445 | { |
1244 | struct ata_port *ap = dev->ap; | 1446 | struct ata_port *ap = dev->ap; |
1245 | unsigned int class = *p_class; | 1447 | unsigned int class = *p_class; |
@@ -1271,10 +1473,17 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1271 | } | 1473 | } |
1272 | 1474 | ||
1273 | tf.protocol = ATA_PROT_PIO; | 1475 | tf.protocol = ATA_PROT_PIO; |
1476 | tf.flags |= ATA_TFLAG_POLLING; /* for polling presence detection */ | ||
1274 | 1477 | ||
1275 | err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, | 1478 | err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, |
1276 | id, sizeof(id[0]) * ATA_ID_WORDS); | 1479 | id, sizeof(id[0]) * ATA_ID_WORDS); |
1277 | if (err_mask) { | 1480 | if (err_mask) { |
1481 | if (err_mask & AC_ERR_NODEV_HINT) { | ||
1482 | DPRINTK("ata%u.%d: NODEV after polling detection\n", | ||
1483 | ap->id, dev->devno); | ||
1484 | return -ENOENT; | ||
1485 | } | ||
1486 | |||
1278 | rc = -EIO; | 1487 | rc = -EIO; |
1279 | reason = "I/O error"; | 1488 | reason = "I/O error"; |
1280 | goto err_out; | 1489 | goto err_out; |
@@ -1294,7 +1503,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1294 | goto err_out; | 1503 | goto err_out; |
1295 | } | 1504 | } |
1296 | 1505 | ||
1297 | if (post_reset && class == ATA_DEV_ATA) { | 1506 | if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { |
1298 | /* | 1507 | /* |
1299 | * The exact sequence expected by certain pre-ATA4 drives is: | 1508 | * The exact sequence expected by certain pre-ATA4 drives is: |
1300 | * SRST RESET | 1509 | * SRST RESET |
@@ -1314,7 +1523,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1314 | /* current CHS translation info (id[53-58]) might be | 1523 | /* current CHS translation info (id[53-58]) might be |
1315 | * changed. reread the identify device info. | 1524 | * changed. reread the identify device info. |
1316 | */ | 1525 | */ |
1317 | post_reset = 0; | 1526 | flags &= ~ATA_READID_POSTRESET; |
1318 | goto retry; | 1527 | goto retry; |
1319 | } | 1528 | } |
1320 | } | 1529 | } |
@@ -1345,7 +1554,10 @@ static void ata_dev_config_ncq(struct ata_device *dev, | |||
1345 | desc[0] = '\0'; | 1554 | desc[0] = '\0'; |
1346 | return; | 1555 | return; |
1347 | } | 1556 | } |
1348 | 1557 | if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) { | |
1558 | snprintf(desc, desc_sz, "NCQ (not used)"); | ||
1559 | return; | ||
1560 | } | ||
1349 | if (ap->flags & ATA_FLAG_NCQ) { | 1561 | if (ap->flags & ATA_FLAG_NCQ) { |
1350 | hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1); | 1562 | hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1); |
1351 | dev->flags |= ATA_DFLAG_NCQ; | 1563 | dev->flags |= ATA_DFLAG_NCQ; |
@@ -1374,7 +1586,6 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap) | |||
1374 | /** | 1586 | /** |
1375 | * ata_dev_configure - Configure the specified ATA/ATAPI device | 1587 | * ata_dev_configure - Configure the specified ATA/ATAPI device |
1376 | * @dev: Target device to configure | 1588 | * @dev: Target device to configure |
1377 | * @print_info: Enable device info printout | ||
1378 | * | 1589 | * |
1379 | * Configure @dev according to @dev->id. Generic and low-level | 1590 | * Configure @dev according to @dev->id. Generic and low-level |
1380 | * driver specific fixups are also applied. | 1591 | * driver specific fixups are also applied. |
@@ -1385,9 +1596,10 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap) | |||
1385 | * RETURNS: | 1596 | * RETURNS: |
1386 | * 0 on success, -errno otherwise | 1597 | * 0 on success, -errno otherwise |
1387 | */ | 1598 | */ |
1388 | int ata_dev_configure(struct ata_device *dev, int print_info) | 1599 | int ata_dev_configure(struct ata_device *dev) |
1389 | { | 1600 | { |
1390 | struct ata_port *ap = dev->ap; | 1601 | struct ata_port *ap = dev->ap; |
1602 | int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; | ||
1391 | const u16 *id = dev->id; | 1603 | const u16 *id = dev->id; |
1392 | unsigned int xfer_mask; | 1604 | unsigned int xfer_mask; |
1393 | char revbuf[7]; /* XYZ-99\0 */ | 1605 | char revbuf[7]; /* XYZ-99\0 */ |
@@ -1454,6 +1666,10 @@ int ata_dev_configure(struct ata_device *dev, int print_info) | |||
1454 | if (ata_id_has_lba48(id)) { | 1666 | if (ata_id_has_lba48(id)) { |
1455 | dev->flags |= ATA_DFLAG_LBA48; | 1667 | dev->flags |= ATA_DFLAG_LBA48; |
1456 | lba_desc = "LBA48"; | 1668 | lba_desc = "LBA48"; |
1669 | |||
1670 | if (dev->n_sectors >= (1UL << 28) && | ||
1671 | ata_id_has_flush_ext(id)) | ||
1672 | dev->flags |= ATA_DFLAG_FLUSH_EXT; | ||
1457 | } | 1673 | } |
1458 | 1674 | ||
1459 | /* config NCQ */ | 1675 | /* config NCQ */ |
@@ -1530,6 +1746,11 @@ int ata_dev_configure(struct ata_device *dev, int print_info) | |||
1530 | cdb_intr_string); | 1746 | cdb_intr_string); |
1531 | } | 1747 | } |
1532 | 1748 | ||
1749 | /* determine max_sectors */ | ||
1750 | dev->max_sectors = ATA_MAX_SECTORS; | ||
1751 | if (dev->flags & ATA_DFLAG_LBA48) | ||
1752 | dev->max_sectors = ATA_MAX_SECTORS_LBA48; | ||
1753 | |||
1533 | if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { | 1754 | if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { |
1534 | /* Let the user know. We don't want to disallow opens for | 1755 | /* Let the user know. We don't want to disallow opens for |
1535 | rescue purposes, or in case the vendor is just a blithering | 1756 | rescue purposes, or in case the vendor is just a blithering |
@@ -1631,11 +1852,14 @@ int ata_bus_probe(struct ata_port *ap) | |||
1631 | if (!ata_dev_enabled(dev)) | 1852 | if (!ata_dev_enabled(dev)) |
1632 | continue; | 1853 | continue; |
1633 | 1854 | ||
1634 | rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); | 1855 | rc = ata_dev_read_id(dev, &dev->class, ATA_READID_POSTRESET, |
1856 | dev->id); | ||
1635 | if (rc) | 1857 | if (rc) |
1636 | goto fail; | 1858 | goto fail; |
1637 | 1859 | ||
1638 | rc = ata_dev_configure(dev, 1); | 1860 | ap->eh_context.i.flags |= ATA_EHI_PRINTINFO; |
1861 | rc = ata_dev_configure(dev); | ||
1862 | ap->eh_context.i.flags &= ~ATA_EHI_PRINTINFO; | ||
1639 | if (rc) | 1863 | if (rc) |
1640 | goto fail; | 1864 | goto fail; |
1641 | } | 1865 | } |
@@ -2153,6 +2377,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) | |||
2153 | 2377 | ||
2154 | static int ata_dev_set_mode(struct ata_device *dev) | 2378 | static int ata_dev_set_mode(struct ata_device *dev) |
2155 | { | 2379 | { |
2380 | struct ata_eh_context *ehc = &dev->ap->eh_context; | ||
2156 | unsigned int err_mask; | 2381 | unsigned int err_mask; |
2157 | int rc; | 2382 | int rc; |
2158 | 2383 | ||
@@ -2167,7 +2392,9 @@ static int ata_dev_set_mode(struct ata_device *dev) | |||
2167 | return -EIO; | 2392 | return -EIO; |
2168 | } | 2393 | } |
2169 | 2394 | ||
2395 | ehc->i.flags |= ATA_EHI_POST_SETMODE; | ||
2170 | rc = ata_dev_revalidate(dev, 0); | 2396 | rc = ata_dev_revalidate(dev, 0); |
2397 | ehc->i.flags &= ~ATA_EHI_POST_SETMODE; | ||
2171 | if (rc) | 2398 | if (rc) |
2172 | return rc; | 2399 | return rc; |
2173 | 2400 | ||
@@ -2325,11 +2552,14 @@ static inline void ata_tf_to_host(struct ata_port *ap, | |||
2325 | * Sleep until ATA Status register bit BSY clears, | 2552 | * Sleep until ATA Status register bit BSY clears, |
2326 | * or a timeout occurs. | 2553 | * or a timeout occurs. |
2327 | * | 2554 | * |
2328 | * LOCKING: None. | 2555 | * LOCKING: |
2556 | * Kernel thread context (may sleep). | ||
2557 | * | ||
2558 | * RETURNS: | ||
2559 | * 0 on success, -errno otherwise. | ||
2329 | */ | 2560 | */ |
2330 | 2561 | int ata_busy_sleep(struct ata_port *ap, | |
2331 | unsigned int ata_busy_sleep (struct ata_port *ap, | 2562 | unsigned long tmout_pat, unsigned long tmout) |
2332 | unsigned long tmout_pat, unsigned long tmout) | ||
2333 | { | 2563 | { |
2334 | unsigned long timer_start, timeout; | 2564 | unsigned long timer_start, timeout; |
2335 | u8 status; | 2565 | u8 status; |
@@ -2337,27 +2567,32 @@ unsigned int ata_busy_sleep (struct ata_port *ap, | |||
2337 | status = ata_busy_wait(ap, ATA_BUSY, 300); | 2567 | status = ata_busy_wait(ap, ATA_BUSY, 300); |
2338 | timer_start = jiffies; | 2568 | timer_start = jiffies; |
2339 | timeout = timer_start + tmout_pat; | 2569 | timeout = timer_start + tmout_pat; |
2340 | while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { | 2570 | while (status != 0xff && (status & ATA_BUSY) && |
2571 | time_before(jiffies, timeout)) { | ||
2341 | msleep(50); | 2572 | msleep(50); |
2342 | status = ata_busy_wait(ap, ATA_BUSY, 3); | 2573 | status = ata_busy_wait(ap, ATA_BUSY, 3); |
2343 | } | 2574 | } |
2344 | 2575 | ||
2345 | if (status & ATA_BUSY) | 2576 | if (status != 0xff && (status & ATA_BUSY)) |
2346 | ata_port_printk(ap, KERN_WARNING, | 2577 | ata_port_printk(ap, KERN_WARNING, |
2347 | "port is slow to respond, please be patient " | 2578 | "port is slow to respond, please be patient " |
2348 | "(Status 0x%x)\n", status); | 2579 | "(Status 0x%x)\n", status); |
2349 | 2580 | ||
2350 | timeout = timer_start + tmout; | 2581 | timeout = timer_start + tmout; |
2351 | while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { | 2582 | while (status != 0xff && (status & ATA_BUSY) && |
2583 | time_before(jiffies, timeout)) { | ||
2352 | msleep(50); | 2584 | msleep(50); |
2353 | status = ata_chk_status(ap); | 2585 | status = ata_chk_status(ap); |
2354 | } | 2586 | } |
2355 | 2587 | ||
2588 | if (status == 0xff) | ||
2589 | return -ENODEV; | ||
2590 | |||
2356 | if (status & ATA_BUSY) { | 2591 | if (status & ATA_BUSY) { |
2357 | ata_port_printk(ap, KERN_ERR, "port failed to respond " | 2592 | ata_port_printk(ap, KERN_ERR, "port failed to respond " |
2358 | "(%lu secs, Status 0x%x)\n", | 2593 | "(%lu secs, Status 0x%x)\n", |
2359 | tmout / HZ, status); | 2594 | tmout / HZ, status); |
2360 | return 1; | 2595 | return -EBUSY; |
2361 | } | 2596 | } |
2362 | 2597 | ||
2363 | return 0; | 2598 | return 0; |
@@ -2448,10 +2683,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, | |||
2448 | * the bus shows 0xFF because the odd clown forgets the D7 | 2683 | * the bus shows 0xFF because the odd clown forgets the D7 |
2449 | * pulldown resistor. | 2684 | * pulldown resistor. |
2450 | */ | 2685 | */ |
2451 | if (ata_check_status(ap) == 0xFF) { | 2686 | if (ata_check_status(ap) == 0xFF) |
2452 | ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n"); | 2687 | return 0; |
2453 | return AC_ERR_OTHER; | ||
2454 | } | ||
2455 | 2688 | ||
2456 | ata_bus_post_reset(ap, devmask); | 2689 | ata_bus_post_reset(ap, devmask); |
2457 | 2690 | ||
@@ -2777,9 +3010,9 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) | |||
2777 | } | 3010 | } |
2778 | 3011 | ||
2779 | /** | 3012 | /** |
2780 | * sata_std_hardreset - reset host port via SATA phy reset | 3013 | * sata_port_hardreset - reset port via SATA phy reset |
2781 | * @ap: port to reset | 3014 | * @ap: port to reset |
2782 | * @class: resulting class of attached device | 3015 | * @timing: timing parameters { interval, duratinon, timeout } in msec |
2783 | * | 3016 | * |
2784 | * SATA phy-reset host port using DET bits of SControl register. | 3017 | * SATA phy-reset host port using DET bits of SControl register. |
2785 | * | 3018 | * |
@@ -2789,10 +3022,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes) | |||
2789 | * RETURNS: | 3022 | * RETURNS: |
2790 | * 0 on success, -errno otherwise. | 3023 | * 0 on success, -errno otherwise. |
2791 | */ | 3024 | */ |
2792 | int sata_std_hardreset(struct ata_port *ap, unsigned int *class) | 3025 | int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing) |
2793 | { | 3026 | { |
2794 | struct ata_eh_context *ehc = &ap->eh_context; | ||
2795 | const unsigned long *timing = sata_ehc_deb_timing(ehc); | ||
2796 | u32 scontrol; | 3027 | u32 scontrol; |
2797 | int rc; | 3028 | int rc; |
2798 | 3029 | ||
@@ -2805,24 +3036,24 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) | |||
2805 | * and Sil3124. | 3036 | * and Sil3124. |
2806 | */ | 3037 | */ |
2807 | if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) | 3038 | if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) |
2808 | return rc; | 3039 | goto out; |
2809 | 3040 | ||
2810 | scontrol = (scontrol & 0x0f0) | 0x304; | 3041 | scontrol = (scontrol & 0x0f0) | 0x304; |
2811 | 3042 | ||
2812 | if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) | 3043 | if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) |
2813 | return rc; | 3044 | goto out; |
2814 | 3045 | ||
2815 | sata_set_spd(ap); | 3046 | sata_set_spd(ap); |
2816 | } | 3047 | } |
2817 | 3048 | ||
2818 | /* issue phy wake/reset */ | 3049 | /* issue phy wake/reset */ |
2819 | if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) | 3050 | if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) |
2820 | return rc; | 3051 | goto out; |
2821 | 3052 | ||
2822 | scontrol = (scontrol & 0x0f0) | 0x301; | 3053 | scontrol = (scontrol & 0x0f0) | 0x301; |
2823 | 3054 | ||
2824 | if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol))) | 3055 | if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol))) |
2825 | return rc; | 3056 | goto out; |
2826 | 3057 | ||
2827 | /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 | 3058 | /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 |
2828 | * 10.4.2 says at least 1 ms. | 3059 | * 10.4.2 says at least 1 ms. |
@@ -2830,7 +3061,40 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) | |||
2830 | msleep(1); | 3061 | msleep(1); |
2831 | 3062 | ||
2832 | /* bring phy back */ | 3063 | /* bring phy back */ |
2833 | sata_phy_resume(ap, timing); | 3064 | rc = sata_phy_resume(ap, timing); |
3065 | out: | ||
3066 | DPRINTK("EXIT, rc=%d\n", rc); | ||
3067 | return rc; | ||
3068 | } | ||
3069 | |||
3070 | /** | ||
3071 | * sata_std_hardreset - reset host port via SATA phy reset | ||
3072 | * @ap: port to reset | ||
3073 | * @class: resulting class of attached device | ||
3074 | * | ||
3075 | * SATA phy-reset host port using DET bits of SControl register, | ||
3076 | * wait for !BSY and classify the attached device. | ||
3077 | * | ||
3078 | * LOCKING: | ||
3079 | * Kernel thread context (may sleep) | ||
3080 | * | ||
3081 | * RETURNS: | ||
3082 | * 0 on success, -errno otherwise. | ||
3083 | */ | ||
3084 | int sata_std_hardreset(struct ata_port *ap, unsigned int *class) | ||
3085 | { | ||
3086 | const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context); | ||
3087 | int rc; | ||
3088 | |||
3089 | DPRINTK("ENTER\n"); | ||
3090 | |||
3091 | /* do hardreset */ | ||
3092 | rc = sata_port_hardreset(ap, timing); | ||
3093 | if (rc) { | ||
3094 | ata_port_printk(ap, KERN_ERR, | ||
3095 | "COMRESET failed (errno=%d)\n", rc); | ||
3096 | return rc; | ||
3097 | } | ||
2834 | 3098 | ||
2835 | /* TODO: phy layer with polling, timeouts, etc. */ | 3099 | /* TODO: phy layer with polling, timeouts, etc. */ |
2836 | if (ata_port_offline(ap)) { | 3100 | if (ata_port_offline(ap)) { |
@@ -2969,7 +3233,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, | |||
2969 | /** | 3233 | /** |
2970 | * ata_dev_revalidate - Revalidate ATA device | 3234 | * ata_dev_revalidate - Revalidate ATA device |
2971 | * @dev: device to revalidate | 3235 | * @dev: device to revalidate |
2972 | * @post_reset: is this revalidation after reset? | 3236 | * @readid_flags: read ID flags |
2973 | * | 3237 | * |
2974 | * Re-read IDENTIFY page and make sure @dev is still attached to | 3238 | * Re-read IDENTIFY page and make sure @dev is still attached to |
2975 | * the port. | 3239 | * the port. |
@@ -2980,7 +3244,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, | |||
2980 | * RETURNS: | 3244 | * RETURNS: |
2981 | * 0 on success, negative errno otherwise | 3245 | * 0 on success, negative errno otherwise |
2982 | */ | 3246 | */ |
2983 | int ata_dev_revalidate(struct ata_device *dev, int post_reset) | 3247 | int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags) |
2984 | { | 3248 | { |
2985 | unsigned int class = dev->class; | 3249 | unsigned int class = dev->class; |
2986 | u16 *id = (void *)dev->ap->sector_buf; | 3250 | u16 *id = (void *)dev->ap->sector_buf; |
@@ -2992,7 +3256,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) | |||
2992 | } | 3256 | } |
2993 | 3257 | ||
2994 | /* read ID data */ | 3258 | /* read ID data */ |
2995 | rc = ata_dev_read_id(dev, &class, post_reset, id); | 3259 | rc = ata_dev_read_id(dev, &class, readid_flags, id); |
2996 | if (rc) | 3260 | if (rc) |
2997 | goto fail; | 3261 | goto fail; |
2998 | 3262 | ||
@@ -3005,7 +3269,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) | |||
3005 | memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); | 3269 | memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); |
3006 | 3270 | ||
3007 | /* configure device according to the new ID */ | 3271 | /* configure device according to the new ID */ |
3008 | rc = ata_dev_configure(dev, 0); | 3272 | rc = ata_dev_configure(dev); |
3009 | if (rc == 0) | 3273 | if (rc == 0) |
3010 | return 0; | 3274 | return 0; |
3011 | 3275 | ||
@@ -3014,37 +3278,55 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) | |||
3014 | return rc; | 3278 | return rc; |
3015 | } | 3279 | } |
3016 | 3280 | ||
3017 | static const char * const ata_dma_blacklist [] = { | 3281 | struct ata_blacklist_entry { |
3018 | "WDC AC11000H", NULL, | 3282 | const char *model_num; |
3019 | "WDC AC22100H", NULL, | 3283 | const char *model_rev; |
3020 | "WDC AC32500H", NULL, | 3284 | unsigned long horkage; |
3021 | "WDC AC33100H", NULL, | 3285 | }; |
3022 | "WDC AC31600H", NULL, | 3286 | |
3023 | "WDC AC32100H", "24.09P07", | 3287 | static const struct ata_blacklist_entry ata_device_blacklist [] = { |
3024 | "WDC AC23200L", "21.10N21", | 3288 | /* Devices with DMA related problems under Linux */ |
3025 | "Compaq CRD-8241B", NULL, | 3289 | { "WDC AC11000H", NULL, ATA_HORKAGE_NODMA }, |
3026 | "CRD-8400B", NULL, | 3290 | { "WDC AC22100H", NULL, ATA_HORKAGE_NODMA }, |
3027 | "CRD-8480B", NULL, | 3291 | { "WDC AC32500H", NULL, ATA_HORKAGE_NODMA }, |
3028 | "CRD-8482B", NULL, | 3292 | { "WDC AC33100H", NULL, ATA_HORKAGE_NODMA }, |
3029 | "CRD-84", NULL, | 3293 | { "WDC AC31600H", NULL, ATA_HORKAGE_NODMA }, |
3030 | "SanDisk SDP3B", NULL, | 3294 | { "WDC AC32100H", "24.09P07", ATA_HORKAGE_NODMA }, |
3031 | "SanDisk SDP3B-64", NULL, | 3295 | { "WDC AC23200L", "21.10N21", ATA_HORKAGE_NODMA }, |
3032 | "SANYO CD-ROM CRD", NULL, | 3296 | { "Compaq CRD-8241B", NULL, ATA_HORKAGE_NODMA }, |
3033 | "HITACHI CDR-8", NULL, | 3297 | { "CRD-8400B", NULL, ATA_HORKAGE_NODMA }, |
3034 | "HITACHI CDR-8335", NULL, | 3298 | { "CRD-8480B", NULL, ATA_HORKAGE_NODMA }, |
3035 | "HITACHI CDR-8435", NULL, | 3299 | { "CRD-8482B", NULL, ATA_HORKAGE_NODMA }, |
3036 | "Toshiba CD-ROM XM-6202B", NULL, | 3300 | { "CRD-84", NULL, ATA_HORKAGE_NODMA }, |
3037 | "TOSHIBA CD-ROM XM-1702BC", NULL, | 3301 | { "SanDisk SDP3B", NULL, ATA_HORKAGE_NODMA }, |
3038 | "CD-532E-A", NULL, | 3302 | { "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA }, |
3039 | "E-IDE CD-ROM CR-840", NULL, | 3303 | { "SANYO CD-ROM CRD", NULL, ATA_HORKAGE_NODMA }, |
3040 | "CD-ROM Drive/F5A", NULL, | 3304 | { "HITACHI CDR-8", NULL, ATA_HORKAGE_NODMA }, |
3041 | "WPI CDD-820", NULL, | 3305 | { "HITACHI CDR-8335", NULL, ATA_HORKAGE_NODMA }, |
3042 | "SAMSUNG CD-ROM SC-148C", NULL, | 3306 | { "HITACHI CDR-8435", NULL, ATA_HORKAGE_NODMA }, |
3043 | "SAMSUNG CD-ROM SC", NULL, | 3307 | { "Toshiba CD-ROM XM-6202B", NULL, ATA_HORKAGE_NODMA }, |
3044 | "SanDisk SDP3B-64", NULL, | 3308 | { "TOSHIBA CD-ROM XM-1702BC", NULL, ATA_HORKAGE_NODMA }, |
3045 | "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, | 3309 | { "CD-532E-A", NULL, ATA_HORKAGE_NODMA }, |
3046 | "_NEC DV5800A", NULL, | 3310 | { "E-IDE CD-ROM CR-840",NULL, ATA_HORKAGE_NODMA }, |
3047 | "SAMSUNG CD-ROM SN-124", "N001" | 3311 | { "CD-ROM Drive/F5A", NULL, ATA_HORKAGE_NODMA }, |
3312 | { "WPI CDD-820", NULL, ATA_HORKAGE_NODMA }, | ||
3313 | { "SAMSUNG CD-ROM SC-148C", NULL, ATA_HORKAGE_NODMA }, | ||
3314 | { "SAMSUNG CD-ROM SC", NULL, ATA_HORKAGE_NODMA }, | ||
3315 | { "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA }, | ||
3316 | { "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA }, | ||
3317 | { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, | ||
3318 | { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA }, | ||
3319 | |||
3320 | /* Devices we expect to fail diagnostics */ | ||
3321 | |||
3322 | /* Devices where NCQ should be avoided */ | ||
3323 | /* NCQ is slow */ | ||
3324 | { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, | ||
3325 | |||
3326 | /* Devices with NCQ limits */ | ||
3327 | |||
3328 | /* End Marker */ | ||
3329 | { } | ||
3048 | }; | 3330 | }; |
3049 | 3331 | ||
3050 | static int ata_strim(char *s, size_t len) | 3332 | static int ata_strim(char *s, size_t len) |
@@ -3059,20 +3341,12 @@ static int ata_strim(char *s, size_t len) | |||
3059 | return len; | 3341 | return len; |
3060 | } | 3342 | } |
3061 | 3343 | ||
3062 | static int ata_dma_blacklisted(const struct ata_device *dev) | 3344 | unsigned long ata_device_blacklisted(const struct ata_device *dev) |
3063 | { | 3345 | { |
3064 | unsigned char model_num[40]; | 3346 | unsigned char model_num[40]; |
3065 | unsigned char model_rev[16]; | 3347 | unsigned char model_rev[16]; |
3066 | unsigned int nlen, rlen; | 3348 | unsigned int nlen, rlen; |
3067 | int i; | 3349 | const struct ata_blacklist_entry *ad = ata_device_blacklist; |
3068 | |||
3069 | /* We don't support polling DMA. | ||
3070 | * DMA blacklist those ATAPI devices with CDB-intr (and use PIO) | ||
3071 | * if the LLDD handles only interrupts in the HSM_ST_LAST state. | ||
3072 | */ | ||
3073 | if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) && | ||
3074 | (dev->flags & ATA_DFLAG_CDB_INTR)) | ||
3075 | return 1; | ||
3076 | 3350 | ||
3077 | ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, | 3351 | ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, |
3078 | sizeof(model_num)); | 3352 | sizeof(model_num)); |
@@ -3081,17 +3355,30 @@ static int ata_dma_blacklisted(const struct ata_device *dev) | |||
3081 | nlen = ata_strim(model_num, sizeof(model_num)); | 3355 | nlen = ata_strim(model_num, sizeof(model_num)); |
3082 | rlen = ata_strim(model_rev, sizeof(model_rev)); | 3356 | rlen = ata_strim(model_rev, sizeof(model_rev)); |
3083 | 3357 | ||
3084 | for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) { | 3358 | while (ad->model_num) { |
3085 | if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) { | 3359 | if (!strncmp(ad->model_num, model_num, nlen)) { |
3086 | if (ata_dma_blacklist[i+1] == NULL) | 3360 | if (ad->model_rev == NULL) |
3087 | return 1; | 3361 | return ad->horkage; |
3088 | if (!strncmp(ata_dma_blacklist[i], model_rev, rlen)) | 3362 | if (!strncmp(ad->model_rev, model_rev, rlen)) |
3089 | return 1; | 3363 | return ad->horkage; |
3090 | } | 3364 | } |
3365 | ad++; | ||
3091 | } | 3366 | } |
3092 | return 0; | 3367 | return 0; |
3093 | } | 3368 | } |
3094 | 3369 | ||
3370 | static int ata_dma_blacklisted(const struct ata_device *dev) | ||
3371 | { | ||
3372 | /* We don't support polling DMA. | ||
3373 | * DMA blacklist those ATAPI devices with CDB-intr (and use PIO) | ||
3374 | * if the LLDD handles only interrupts in the HSM_ST_LAST state. | ||
3375 | */ | ||
3376 | if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) && | ||
3377 | (dev->flags & ATA_DFLAG_CDB_INTR)) | ||
3378 | return 1; | ||
3379 | return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0; | ||
3380 | } | ||
3381 | |||
3095 | /** | 3382 | /** |
3096 | * ata_dev_xfermask - Compute supported xfermask of the given device | 3383 | * ata_dev_xfermask - Compute supported xfermask of the given device |
3097 | * @dev: Device to compute xfermask for | 3384 | * @dev: Device to compute xfermask for |
@@ -3119,6 +3406,13 @@ static void ata_dev_xfermask(struct ata_device *dev) | |||
3119 | */ | 3406 | */ |
3120 | if (ap->cbl == ATA_CBL_PATA40) | 3407 | if (ap->cbl == ATA_CBL_PATA40) |
3121 | xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); | 3408 | xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); |
3409 | /* Apply drive side cable rule. Unknown or 80 pin cables reported | ||
3410 | * host side are checked drive side as well. Cases where we know a | ||
3411 | * 40wire cable is used safely for 80 are not checked here. | ||
3412 | */ | ||
3413 | if (ata_drive_40wire(dev->id) && (ap->cbl == ATA_CBL_PATA_UNK || ap->cbl == ATA_CBL_PATA80)) | ||
3414 | xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); | ||
3415 | |||
3122 | 3416 | ||
3123 | xfer_mask &= ata_pack_xfermask(dev->pio_mask, | 3417 | xfer_mask &= ata_pack_xfermask(dev->pio_mask, |
3124 | dev->mwdma_mask, dev->udma_mask); | 3418 | dev->mwdma_mask, dev->udma_mask); |
@@ -3236,8 +3530,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev, | |||
3236 | * LOCKING: | 3530 | * LOCKING: |
3237 | * spin_lock_irqsave(host lock) | 3531 | * spin_lock_irqsave(host lock) |
3238 | */ | 3532 | */ |
3239 | 3533 | void ata_sg_clean(struct ata_queued_cmd *qc) | |
3240 | static void ata_sg_clean(struct ata_queued_cmd *qc) | ||
3241 | { | 3534 | { |
3242 | struct ata_port *ap = qc->ap; | 3535 | struct ata_port *ap = qc->ap; |
3243 | struct scatterlist *sg = qc->__sg; | 3536 | struct scatterlist *sg = qc->__sg; |
@@ -3395,19 +3688,15 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } | |||
3395 | 3688 | ||
3396 | void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) | 3689 | void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) |
3397 | { | 3690 | { |
3398 | struct scatterlist *sg; | ||
3399 | |||
3400 | qc->flags |= ATA_QCFLAG_SINGLE; | 3691 | qc->flags |= ATA_QCFLAG_SINGLE; |
3401 | 3692 | ||
3402 | memset(&qc->sgent, 0, sizeof(qc->sgent)); | ||
3403 | qc->__sg = &qc->sgent; | 3693 | qc->__sg = &qc->sgent; |
3404 | qc->n_elem = 1; | 3694 | qc->n_elem = 1; |
3405 | qc->orig_n_elem = 1; | 3695 | qc->orig_n_elem = 1; |
3406 | qc->buf_virt = buf; | 3696 | qc->buf_virt = buf; |
3407 | qc->nbytes = buflen; | 3697 | qc->nbytes = buflen; |
3408 | 3698 | ||
3409 | sg = qc->__sg; | 3699 | sg_init_one(&qc->sgent, buf, buflen); |
3410 | sg_init_one(sg, buf, buflen); | ||
3411 | } | 3700 | } |
3412 | 3701 | ||
3413 | /** | 3702 | /** |
@@ -4200,8 +4489,12 @@ fsm_start: | |||
4200 | /* device stops HSM for abort/error */ | 4489 | /* device stops HSM for abort/error */ |
4201 | qc->err_mask |= AC_ERR_DEV; | 4490 | qc->err_mask |= AC_ERR_DEV; |
4202 | else | 4491 | else |
4203 | /* HSM violation. Let EH handle this */ | 4492 | /* HSM violation. Let EH handle this. |
4204 | qc->err_mask |= AC_ERR_HSM; | 4493 | * Phantom devices also trigger this |
4494 | * condition. Mark hint. | ||
4495 | */ | ||
4496 | qc->err_mask |= AC_ERR_HSM | | ||
4497 | AC_ERR_NODEV_HINT; | ||
4205 | 4498 | ||
4206 | ap->hsm_task_state = HSM_ST_ERR; | 4499 | ap->hsm_task_state = HSM_ST_ERR; |
4207 | goto fsm_start; | 4500 | goto fsm_start; |
@@ -4440,6 +4733,14 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) | |||
4440 | qc->complete_fn(qc); | 4733 | qc->complete_fn(qc); |
4441 | } | 4734 | } |
4442 | 4735 | ||
4736 | static void fill_result_tf(struct ata_queued_cmd *qc) | ||
4737 | { | ||
4738 | struct ata_port *ap = qc->ap; | ||
4739 | |||
4740 | ap->ops->tf_read(ap, &qc->result_tf); | ||
4741 | qc->result_tf.flags = qc->tf.flags; | ||
4742 | } | ||
4743 | |||
4443 | /** | 4744 | /** |
4444 | * ata_qc_complete - Complete an active ATA command | 4745 | * ata_qc_complete - Complete an active ATA command |
4445 | * @qc: Command to complete | 4746 | * @qc: Command to complete |
@@ -4477,7 +4778,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) | |||
4477 | if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { | 4778 | if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { |
4478 | if (!ata_tag_internal(qc->tag)) { | 4779 | if (!ata_tag_internal(qc->tag)) { |
4479 | /* always fill result TF for failed qc */ | 4780 | /* always fill result TF for failed qc */ |
4480 | ap->ops->tf_read(ap, &qc->result_tf); | 4781 | fill_result_tf(qc); |
4481 | ata_qc_schedule_eh(qc); | 4782 | ata_qc_schedule_eh(qc); |
4482 | return; | 4783 | return; |
4483 | } | 4784 | } |
@@ -4485,7 +4786,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) | |||
4485 | 4786 | ||
4486 | /* read result TF if requested */ | 4787 | /* read result TF if requested */ |
4487 | if (qc->flags & ATA_QCFLAG_RESULT_TF) | 4788 | if (qc->flags & ATA_QCFLAG_RESULT_TF) |
4488 | ap->ops->tf_read(ap, &qc->result_tf); | 4789 | fill_result_tf(qc); |
4489 | 4790 | ||
4490 | __ata_qc_complete(qc); | 4791 | __ata_qc_complete(qc); |
4491 | } else { | 4792 | } else { |
@@ -4494,7 +4795,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) | |||
4494 | 4795 | ||
4495 | /* read result TF if failed or requested */ | 4796 | /* read result TF if failed or requested */ |
4496 | if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) | 4797 | if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) |
4497 | ap->ops->tf_read(ap, &qc->result_tf); | 4798 | fill_result_tf(qc); |
4498 | 4799 | ||
4499 | __ata_qc_complete(qc); | 4800 | __ata_qc_complete(qc); |
4500 | } | 4801 | } |
@@ -4674,6 +4975,14 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) | |||
4674 | } | 4975 | } |
4675 | } | 4976 | } |
4676 | 4977 | ||
4978 | /* Some controllers show flaky interrupt behavior after | ||
4979 | * setting xfer mode. Use polling instead. | ||
4980 | */ | ||
4981 | if (unlikely(qc->tf.command == ATA_CMD_SET_FEATURES && | ||
4982 | qc->tf.feature == SETFEATURES_XFER) && | ||
4983 | (ap->flags & ATA_FLAG_SETXFER_POLLING)) | ||
4984 | qc->tf.flags |= ATA_TFLAG_POLLING; | ||
4985 | |||
4677 | /* select the device */ | 4986 | /* select the device */ |
4678 | ata_dev_select(ap, qc->dev->devno, 1, 0); | 4987 | ata_dev_select(ap, qc->dev->devno, 1, 0); |
4679 | 4988 | ||
@@ -4782,6 +5091,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) | |||
4782 | inline unsigned int ata_host_intr (struct ata_port *ap, | 5091 | inline unsigned int ata_host_intr (struct ata_port *ap, |
4783 | struct ata_queued_cmd *qc) | 5092 | struct ata_queued_cmd *qc) |
4784 | { | 5093 | { |
5094 | struct ata_eh_info *ehi = &ap->eh_info; | ||
4785 | u8 status, host_stat = 0; | 5095 | u8 status, host_stat = 0; |
4786 | 5096 | ||
4787 | VPRINTK("ata%u: protocol %d task_state %d\n", | 5097 | VPRINTK("ata%u: protocol %d task_state %d\n", |
@@ -4842,6 +5152,11 @@ inline unsigned int ata_host_intr (struct ata_port *ap, | |||
4842 | ap->ops->irq_clear(ap); | 5152 | ap->ops->irq_clear(ap); |
4843 | 5153 | ||
4844 | ata_hsm_move(ap, qc, status, 0); | 5154 | ata_hsm_move(ap, qc, status, 0); |
5155 | |||
5156 | if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || | ||
5157 | qc->tf.protocol == ATA_PROT_ATAPI_DMA)) | ||
5158 | ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); | ||
5159 | |||
4845 | return 1; /* irq handled */ | 5160 | return 1; /* irq handled */ |
4846 | 5161 | ||
4847 | idle_irq: | 5162 | idle_irq: |
@@ -5048,7 +5363,7 @@ int ata_flush_cache(struct ata_device *dev) | |||
5048 | if (!ata_try_flush_cache(dev)) | 5363 | if (!ata_try_flush_cache(dev)) |
5049 | return 0; | 5364 | return 0; |
5050 | 5365 | ||
5051 | if (ata_id_has_flush_ext(dev->id)) | 5366 | if (dev->flags & ATA_DFLAG_FLUSH_EXT) |
5052 | cmd = ATA_CMD_FLUSH_EXT; | 5367 | cmd = ATA_CMD_FLUSH_EXT; |
5053 | else | 5368 | else |
5054 | cmd = ATA_CMD_FLUSH; | 5369 | cmd = ATA_CMD_FLUSH; |
@@ -5520,9 +5835,8 @@ int ata_device_add(const struct ata_probe_ent *ent) | |||
5520 | ap->ioaddr.bmdma_addr, | 5835 | ap->ioaddr.bmdma_addr, |
5521 | irq_line); | 5836 | irq_line); |
5522 | 5837 | ||
5523 | ata_chk_status(ap); | 5838 | /* freeze port before requesting IRQ */ |
5524 | host->ops->irq_clear(ap); | 5839 | ata_eh_freeze_port(ap); |
5525 | ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */ | ||
5526 | } | 5840 | } |
5527 | 5841 | ||
5528 | /* obtain irq, that may be shared between channels */ | 5842 | /* obtain irq, that may be shared between channels */ |
@@ -6120,6 +6434,7 @@ EXPORT_SYMBOL_GPL(__sata_phy_reset); | |||
6120 | EXPORT_SYMBOL_GPL(ata_bus_reset); | 6434 | EXPORT_SYMBOL_GPL(ata_bus_reset); |
6121 | EXPORT_SYMBOL_GPL(ata_std_prereset); | 6435 | EXPORT_SYMBOL_GPL(ata_std_prereset); |
6122 | EXPORT_SYMBOL_GPL(ata_std_softreset); | 6436 | EXPORT_SYMBOL_GPL(ata_std_softreset); |
6437 | EXPORT_SYMBOL_GPL(sata_port_hardreset); | ||
6123 | EXPORT_SYMBOL_GPL(sata_std_hardreset); | 6438 | EXPORT_SYMBOL_GPL(sata_std_hardreset); |
6124 | EXPORT_SYMBOL_GPL(ata_std_postreset); | 6439 | EXPORT_SYMBOL_GPL(ata_std_postreset); |
6125 | EXPORT_SYMBOL_GPL(ata_dev_classify); | 6440 | EXPORT_SYMBOL_GPL(ata_dev_classify); |
@@ -6146,6 +6461,7 @@ EXPORT_SYMBOL_GPL(ata_host_suspend); | |||
6146 | EXPORT_SYMBOL_GPL(ata_host_resume); | 6461 | EXPORT_SYMBOL_GPL(ata_host_resume); |
6147 | EXPORT_SYMBOL_GPL(ata_id_string); | 6462 | EXPORT_SYMBOL_GPL(ata_id_string); |
6148 | EXPORT_SYMBOL_GPL(ata_id_c_string); | 6463 | EXPORT_SYMBOL_GPL(ata_id_c_string); |
6464 | EXPORT_SYMBOL_GPL(ata_device_blacklisted); | ||
6149 | EXPORT_SYMBOL_GPL(ata_scsi_simulate); | 6465 | EXPORT_SYMBOL_GPL(ata_scsi_simulate); |
6150 | 6466 | ||
6151 | EXPORT_SYMBOL_GPL(ata_pio_need_iordy); | 6467 | EXPORT_SYMBOL_GPL(ata_pio_need_iordy); |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 02b2b2787d9b..76a85dfb7307 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -1136,19 +1136,21 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, | |||
1136 | break; | 1136 | break; |
1137 | 1137 | ||
1138 | case ATA_DEV_ATAPI: | 1138 | case ATA_DEV_ATAPI: |
1139 | tmp = atapi_eh_request_sense(qc->dev, | 1139 | if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { |
1140 | qc->scsicmd->sense_buffer); | 1140 | tmp = atapi_eh_request_sense(qc->dev, |
1141 | if (!tmp) { | 1141 | qc->scsicmd->sense_buffer); |
1142 | /* ATA_QCFLAG_SENSE_VALID is used to tell | 1142 | if (!tmp) { |
1143 | * atapi_qc_complete() that sense data is | 1143 | /* ATA_QCFLAG_SENSE_VALID is used to |
1144 | * already valid. | 1144 | * tell atapi_qc_complete() that sense |
1145 | * | 1145 | * data is already valid. |
1146 | * TODO: interpret sense data and set | 1146 | * |
1147 | * appropriate err_mask. | 1147 | * TODO: interpret sense data and set |
1148 | */ | 1148 | * appropriate err_mask. |
1149 | qc->flags |= ATA_QCFLAG_SENSE_VALID; | 1149 | */ |
1150 | } else | 1150 | qc->flags |= ATA_QCFLAG_SENSE_VALID; |
1151 | qc->err_mask |= tmp; | 1151 | } else |
1152 | qc->err_mask |= tmp; | ||
1153 | } | ||
1152 | } | 1154 | } |
1153 | 1155 | ||
1154 | if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS)) | 1156 | if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS)) |
@@ -1433,16 +1435,39 @@ static void ata_eh_report(struct ata_port *ap) | |||
1433 | } | 1435 | } |
1434 | 1436 | ||
1435 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { | 1437 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { |
1438 | static const char *dma_str[] = { | ||
1439 | [DMA_BIDIRECTIONAL] = "bidi", | ||
1440 | [DMA_TO_DEVICE] = "out", | ||
1441 | [DMA_FROM_DEVICE] = "in", | ||
1442 | [DMA_NONE] = "", | ||
1443 | }; | ||
1436 | struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); | 1444 | struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); |
1445 | struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf; | ||
1446 | unsigned int nbytes; | ||
1437 | 1447 | ||
1438 | if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) | 1448 | if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) |
1439 | continue; | 1449 | continue; |
1440 | 1450 | ||
1441 | ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x " | 1451 | nbytes = qc->nbytes; |
1442 | "Emask 0x%x stat 0x%x err 0x%x (%s)\n", | 1452 | if (!nbytes) |
1443 | qc->tag, qc->tf.command, qc->err_mask, | 1453 | nbytes = qc->nsect << 9; |
1444 | qc->result_tf.command, qc->result_tf.feature, | 1454 | |
1445 | ata_err_string(qc->err_mask)); | 1455 | ata_dev_printk(qc->dev, KERN_ERR, |
1456 | "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " | ||
1457 | "tag %d cdb 0x%x data %u %s\n " | ||
1458 | "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " | ||
1459 | "Emask 0x%x (%s)\n", | ||
1460 | cmd->command, cmd->feature, cmd->nsect, | ||
1461 | cmd->lbal, cmd->lbam, cmd->lbah, | ||
1462 | cmd->hob_feature, cmd->hob_nsect, | ||
1463 | cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, | ||
1464 | cmd->device, qc->tag, qc->cdb[0], nbytes, | ||
1465 | dma_str[qc->dma_dir], | ||
1466 | res->command, res->feature, res->nsect, | ||
1467 | res->lbal, res->lbam, res->lbah, | ||
1468 | res->hob_feature, res->hob_nsect, | ||
1469 | res->hob_lbal, res->hob_lbam, res->hob_lbah, | ||
1470 | res->device, qc->err_mask, ata_err_string(qc->err_mask)); | ||
1446 | } | 1471 | } |
1447 | } | 1472 | } |
1448 | 1473 | ||
@@ -1634,11 +1659,14 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, | |||
1634 | DPRINTK("ENTER\n"); | 1659 | DPRINTK("ENTER\n"); |
1635 | 1660 | ||
1636 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 1661 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
1637 | unsigned int action; | 1662 | unsigned int action, readid_flags = 0; |
1638 | 1663 | ||
1639 | dev = &ap->device[i]; | 1664 | dev = &ap->device[i]; |
1640 | action = ata_eh_dev_action(dev); | 1665 | action = ata_eh_dev_action(dev); |
1641 | 1666 | ||
1667 | if (ehc->i.flags & ATA_EHI_DID_RESET) | ||
1668 | readid_flags |= ATA_READID_POSTRESET; | ||
1669 | |||
1642 | if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { | 1670 | if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { |
1643 | if (ata_port_offline(ap)) { | 1671 | if (ata_port_offline(ap)) { |
1644 | rc = -EIO; | 1672 | rc = -EIO; |
@@ -1646,13 +1674,17 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, | |||
1646 | } | 1674 | } |
1647 | 1675 | ||
1648 | ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); | 1676 | ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); |
1649 | rc = ata_dev_revalidate(dev, | 1677 | rc = ata_dev_revalidate(dev, readid_flags); |
1650 | ehc->i.flags & ATA_EHI_DID_RESET); | ||
1651 | if (rc) | 1678 | if (rc) |
1652 | break; | 1679 | break; |
1653 | 1680 | ||
1654 | ata_eh_done(ap, dev, ATA_EH_REVALIDATE); | 1681 | ata_eh_done(ap, dev, ATA_EH_REVALIDATE); |
1655 | 1682 | ||
1683 | /* Configuration may have changed, reconfigure | ||
1684 | * transfer mode. | ||
1685 | */ | ||
1686 | ehc->i.flags |= ATA_EHI_SETMODE; | ||
1687 | |||
1656 | /* schedule the scsi_rescan_device() here */ | 1688 | /* schedule the scsi_rescan_device() here */ |
1657 | queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); | 1689 | queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); |
1658 | } else if (dev->class == ATA_DEV_UNKNOWN && | 1690 | } else if (dev->class == ATA_DEV_UNKNOWN && |
@@ -1660,18 +1692,35 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, | |||
1660 | ata_class_enabled(ehc->classes[dev->devno])) { | 1692 | ata_class_enabled(ehc->classes[dev->devno])) { |
1661 | dev->class = ehc->classes[dev->devno]; | 1693 | dev->class = ehc->classes[dev->devno]; |
1662 | 1694 | ||
1663 | rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); | 1695 | rc = ata_dev_read_id(dev, &dev->class, readid_flags, |
1664 | if (rc == 0) | 1696 | dev->id); |
1665 | rc = ata_dev_configure(dev, 1); | 1697 | if (rc == 0) { |
1698 | ehc->i.flags |= ATA_EHI_PRINTINFO; | ||
1699 | rc = ata_dev_configure(dev); | ||
1700 | ehc->i.flags &= ~ATA_EHI_PRINTINFO; | ||
1701 | } else if (rc == -ENOENT) { | ||
1702 | /* IDENTIFY was issued to non-existent | ||
1703 | * device. No need to reset. Just | ||
1704 | * thaw and kill the device. | ||
1705 | */ | ||
1706 | ata_eh_thaw_port(ap); | ||
1707 | dev->class = ATA_DEV_UNKNOWN; | ||
1708 | rc = 0; | ||
1709 | } | ||
1666 | 1710 | ||
1667 | if (rc) { | 1711 | if (rc) { |
1668 | dev->class = ATA_DEV_UNKNOWN; | 1712 | dev->class = ATA_DEV_UNKNOWN; |
1669 | break; | 1713 | break; |
1670 | } | 1714 | } |
1671 | 1715 | ||
1672 | spin_lock_irqsave(ap->lock, flags); | 1716 | if (ata_dev_enabled(dev)) { |
1673 | ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; | 1717 | spin_lock_irqsave(ap->lock, flags); |
1674 | spin_unlock_irqrestore(ap->lock, flags); | 1718 | ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; |
1719 | spin_unlock_irqrestore(ap->lock, flags); | ||
1720 | |||
1721 | /* new device discovered, configure xfermode */ | ||
1722 | ehc->i.flags |= ATA_EHI_SETMODE; | ||
1723 | } | ||
1675 | } | 1724 | } |
1676 | } | 1725 | } |
1677 | 1726 | ||
@@ -1987,13 +2036,14 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1987 | if (rc) | 2036 | if (rc) |
1988 | goto dev_fail; | 2037 | goto dev_fail; |
1989 | 2038 | ||
1990 | /* configure transfer mode if the port has been reset */ | 2039 | /* configure transfer mode if necessary */ |
1991 | if (ehc->i.flags & ATA_EHI_DID_RESET) { | 2040 | if (ehc->i.flags & ATA_EHI_SETMODE) { |
1992 | rc = ata_set_mode(ap, &dev); | 2041 | rc = ata_set_mode(ap, &dev); |
1993 | if (rc) { | 2042 | if (rc) { |
1994 | down_xfermask = 1; | 2043 | down_xfermask = 1; |
1995 | goto dev_fail; | 2044 | goto dev_fail; |
1996 | } | 2045 | } |
2046 | ehc->i.flags &= ~ATA_EHI_SETMODE; | ||
1997 | } | 2047 | } |
1998 | 2048 | ||
1999 | /* suspend devices */ | 2049 | /* suspend devices */ |
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 47ea111d5ace..8eaace94d963 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -671,7 +671,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, | |||
671 | } | 671 | } |
672 | 672 | ||
673 | /* | 673 | /* |
674 | * ata_gen_ata_desc_sense - Generate check condition sense block. | 674 | * ata_gen_passthru_sense - Generate check condition sense block. |
675 | * @qc: Command that completed. | 675 | * @qc: Command that completed. |
676 | * | 676 | * |
677 | * This function is specific to the ATA descriptor format sense | 677 | * This function is specific to the ATA descriptor format sense |
@@ -681,9 +681,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, | |||
681 | * block. Clear sense key, ASC & ASCQ if there is no error. | 681 | * block. Clear sense key, ASC & ASCQ if there is no error. |
682 | * | 682 | * |
683 | * LOCKING: | 683 | * LOCKING: |
684 | * spin_lock_irqsave(host lock) | 684 | * None. |
685 | */ | 685 | */ |
686 | void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) | 686 | static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) |
687 | { | 687 | { |
688 | struct scsi_cmnd *cmd = qc->scsicmd; | 688 | struct scsi_cmnd *cmd = qc->scsicmd; |
689 | struct ata_taskfile *tf = &qc->result_tf; | 689 | struct ata_taskfile *tf = &qc->result_tf; |
@@ -713,12 +713,9 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) | |||
713 | 713 | ||
714 | desc[0] = 0x09; | 714 | desc[0] = 0x09; |
715 | 715 | ||
716 | /* | 716 | /* set length of additional sense data */ |
717 | * Set length of additional sense data. | 717 | sb[7] = 14; |
718 | * Since we only populate descriptor 0, the total | 718 | desc[1] = 12; |
719 | * length is the same (fixed) length as descriptor 0. | ||
720 | */ | ||
721 | desc[1] = sb[7] = 14; | ||
722 | 719 | ||
723 | /* | 720 | /* |
724 | * Copy registers into sense buffer. | 721 | * Copy registers into sense buffer. |
@@ -746,56 +743,56 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) | |||
746 | } | 743 | } |
747 | 744 | ||
748 | /** | 745 | /** |
749 | * ata_gen_fixed_sense - generate a SCSI fixed sense block | 746 | * ata_gen_ata_sense - generate a SCSI fixed sense block |
750 | * @qc: Command that we are erroring out | 747 | * @qc: Command that we are erroring out |
751 | * | 748 | * |
752 | * Leverage ata_to_sense_error() to give us the codes. Fit our | 749 | * Generate sense block for a failed ATA command @qc. Descriptor |
753 | * LBA in here if there's room. | 750 | * format is used to accomodate LBA48 block address. |
754 | * | 751 | * |
755 | * LOCKING: | 752 | * LOCKING: |
756 | * inherited from caller | 753 | * None. |
757 | */ | 754 | */ |
758 | void ata_gen_fixed_sense(struct ata_queued_cmd *qc) | 755 | static void ata_gen_ata_sense(struct ata_queued_cmd *qc) |
759 | { | 756 | { |
757 | struct ata_device *dev = qc->dev; | ||
760 | struct scsi_cmnd *cmd = qc->scsicmd; | 758 | struct scsi_cmnd *cmd = qc->scsicmd; |
761 | struct ata_taskfile *tf = &qc->result_tf; | 759 | struct ata_taskfile *tf = &qc->result_tf; |
762 | unsigned char *sb = cmd->sense_buffer; | 760 | unsigned char *sb = cmd->sense_buffer; |
761 | unsigned char *desc = sb + 8; | ||
763 | int verbose = qc->ap->ops->error_handler == NULL; | 762 | int verbose = qc->ap->ops->error_handler == NULL; |
763 | u64 block; | ||
764 | 764 | ||
765 | memset(sb, 0, SCSI_SENSE_BUFFERSIZE); | 765 | memset(sb, 0, SCSI_SENSE_BUFFERSIZE); |
766 | 766 | ||
767 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; | 767 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; |
768 | 768 | ||
769 | /* | 769 | /* sense data is current and format is descriptor */ |
770 | * Use ata_to_sense_error() to map status register bits | 770 | sb[0] = 0x72; |
771 | |||
772 | /* Use ata_to_sense_error() to map status register bits | ||
771 | * onto sense key, asc & ascq. | 773 | * onto sense key, asc & ascq. |
772 | */ | 774 | */ |
773 | if (qc->err_mask || | 775 | if (qc->err_mask || |
774 | tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { | 776 | tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { |
775 | ata_to_sense_error(qc->ap->id, tf->command, tf->feature, | 777 | ata_to_sense_error(qc->ap->id, tf->command, tf->feature, |
776 | &sb[2], &sb[12], &sb[13], verbose); | 778 | &sb[1], &sb[2], &sb[3], verbose); |
777 | sb[2] &= 0x0f; | 779 | sb[1] &= 0x0f; |
778 | } | 780 | } |
779 | 781 | ||
780 | sb[0] = 0x70; | 782 | block = ata_tf_read_block(&qc->result_tf, dev); |
781 | sb[7] = 0x0a; | ||
782 | |||
783 | if (tf->flags & ATA_TFLAG_LBA48) { | ||
784 | /* TODO: find solution for LBA48 descriptors */ | ||
785 | } | ||
786 | 783 | ||
787 | else if (tf->flags & ATA_TFLAG_LBA) { | 784 | /* information sense data descriptor */ |
788 | /* A small (28b) LBA will fit in the 32b info field */ | 785 | sb[7] = 12; |
789 | sb[0] |= 0x80; /* set valid bit */ | 786 | desc[0] = 0x00; |
790 | sb[3] = tf->device & 0x0f; | 787 | desc[1] = 10; |
791 | sb[4] = tf->lbah; | ||
792 | sb[5] = tf->lbam; | ||
793 | sb[6] = tf->lbal; | ||
794 | } | ||
795 | 788 | ||
796 | else { | 789 | desc[2] |= 0x80; /* valid */ |
797 | /* TODO: C/H/S */ | 790 | desc[6] = block >> 40; |
798 | } | 791 | desc[7] = block >> 32; |
792 | desc[8] = block >> 24; | ||
793 | desc[9] = block >> 16; | ||
794 | desc[10] = block >> 8; | ||
795 | desc[11] = block; | ||
799 | } | 796 | } |
800 | 797 | ||
801 | static void ata_scsi_sdev_config(struct scsi_device *sdev) | 798 | static void ata_scsi_sdev_config(struct scsi_device *sdev) |
@@ -807,23 +804,10 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) | |||
807 | static void ata_scsi_dev_config(struct scsi_device *sdev, | 804 | static void ata_scsi_dev_config(struct scsi_device *sdev, |
808 | struct ata_device *dev) | 805 | struct ata_device *dev) |
809 | { | 806 | { |
810 | unsigned int max_sectors; | 807 | /* configure max sectors */ |
811 | 808 | blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); | |
812 | /* TODO: 2048 is an arbitrary number, not the | ||
813 | * hardware maximum. This should be increased to | ||
814 | * 65534 when Jens Axboe's patch for dynamically | ||
815 | * determining max_sectors is merged. | ||
816 | */ | ||
817 | max_sectors = ATA_MAX_SECTORS; | ||
818 | if (dev->flags & ATA_DFLAG_LBA48) | ||
819 | max_sectors = ATA_MAX_SECTORS_LBA48; | ||
820 | if (dev->max_sectors) | ||
821 | max_sectors = dev->max_sectors; | ||
822 | 809 | ||
823 | blk_queue_max_sectors(sdev->request_queue, max_sectors); | 810 | /* SATA DMA transfers must be multiples of 4 byte, so |
824 | |||
825 | /* | ||
826 | * SATA DMA transfers must be multiples of 4 byte, so | ||
827 | * we need to pad ATAPI transfers using an extra sg. | 811 | * we need to pad ATAPI transfers using an extra sg. |
828 | * Decrement max hw segments accordingly. | 812 | * Decrement max hw segments accordingly. |
829 | */ | 813 | */ |
@@ -1040,8 +1024,7 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scs | |||
1040 | tf->flags |= ATA_TFLAG_DEVICE; | 1024 | tf->flags |= ATA_TFLAG_DEVICE; |
1041 | tf->protocol = ATA_PROT_NODATA; | 1025 | tf->protocol = ATA_PROT_NODATA; |
1042 | 1026 | ||
1043 | if ((qc->dev->flags & ATA_DFLAG_LBA48) && | 1027 | if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT) |
1044 | (ata_id_has_flush_ext(qc->dev->id))) | ||
1045 | tf->command = ATA_CMD_FLUSH_EXT; | 1028 | tf->command = ATA_CMD_FLUSH_EXT; |
1046 | else | 1029 | else |
1047 | tf->command = ATA_CMD_FLUSH; | 1030 | tf->command = ATA_CMD_FLUSH; |
@@ -1282,17 +1265,14 @@ nothing_to_do: | |||
1282 | 1265 | ||
1283 | static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) | 1266 | static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) |
1284 | { | 1267 | { |
1285 | struct ata_taskfile *tf = &qc->tf; | 1268 | unsigned int tf_flags = 0; |
1286 | struct ata_device *dev = qc->dev; | ||
1287 | u64 block; | 1269 | u64 block; |
1288 | u32 n_block; | 1270 | u32 n_block; |
1289 | 1271 | int rc; | |
1290 | qc->flags |= ATA_QCFLAG_IO; | ||
1291 | tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | ||
1292 | 1272 | ||
1293 | if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || | 1273 | if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || |
1294 | scsicmd[0] == WRITE_16) | 1274 | scsicmd[0] == WRITE_16) |
1295 | tf->flags |= ATA_TFLAG_WRITE; | 1275 | tf_flags |= ATA_TFLAG_WRITE; |
1296 | 1276 | ||
1297 | /* Calculate the SCSI LBA, transfer length and FUA. */ | 1277 | /* Calculate the SCSI LBA, transfer length and FUA. */ |
1298 | switch (scsicmd[0]) { | 1278 | switch (scsicmd[0]) { |
@@ -1300,7 +1280,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1300 | case WRITE_10: | 1280 | case WRITE_10: |
1301 | scsi_10_lba_len(scsicmd, &block, &n_block); | 1281 | scsi_10_lba_len(scsicmd, &block, &n_block); |
1302 | if (unlikely(scsicmd[1] & (1 << 3))) | 1282 | if (unlikely(scsicmd[1] & (1 << 3))) |
1303 | tf->flags |= ATA_TFLAG_FUA; | 1283 | tf_flags |= ATA_TFLAG_FUA; |
1304 | break; | 1284 | break; |
1305 | case READ_6: | 1285 | case READ_6: |
1306 | case WRITE_6: | 1286 | case WRITE_6: |
@@ -1316,7 +1296,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1316 | case WRITE_16: | 1296 | case WRITE_16: |
1317 | scsi_16_lba_len(scsicmd, &block, &n_block); | 1297 | scsi_16_lba_len(scsicmd, &block, &n_block); |
1318 | if (unlikely(scsicmd[1] & (1 << 3))) | 1298 | if (unlikely(scsicmd[1] & (1 << 3))) |
1319 | tf->flags |= ATA_TFLAG_FUA; | 1299 | tf_flags |= ATA_TFLAG_FUA; |
1320 | break; | 1300 | break; |
1321 | default: | 1301 | default: |
1322 | DPRINTK("no-byte command\n"); | 1302 | DPRINTK("no-byte command\n"); |
@@ -1334,106 +1314,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1334 | */ | 1314 | */ |
1335 | goto nothing_to_do; | 1315 | goto nothing_to_do; |
1336 | 1316 | ||
1337 | if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF | | 1317 | qc->flags |= ATA_QCFLAG_IO; |
1338 | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) { | 1318 | qc->nsect = n_block; |
1339 | /* yay, NCQ */ | ||
1340 | if (!lba_48_ok(block, n_block)) | ||
1341 | goto out_of_range; | ||
1342 | |||
1343 | tf->protocol = ATA_PROT_NCQ; | ||
1344 | tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; | ||
1345 | |||
1346 | if (tf->flags & ATA_TFLAG_WRITE) | ||
1347 | tf->command = ATA_CMD_FPDMA_WRITE; | ||
1348 | else | ||
1349 | tf->command = ATA_CMD_FPDMA_READ; | ||
1350 | |||
1351 | qc->nsect = n_block; | ||
1352 | |||
1353 | tf->nsect = qc->tag << 3; | ||
1354 | tf->hob_feature = (n_block >> 8) & 0xff; | ||
1355 | tf->feature = n_block & 0xff; | ||
1356 | |||
1357 | tf->hob_lbah = (block >> 40) & 0xff; | ||
1358 | tf->hob_lbam = (block >> 32) & 0xff; | ||
1359 | tf->hob_lbal = (block >> 24) & 0xff; | ||
1360 | tf->lbah = (block >> 16) & 0xff; | ||
1361 | tf->lbam = (block >> 8) & 0xff; | ||
1362 | tf->lbal = block & 0xff; | ||
1363 | |||
1364 | tf->device = 1 << 6; | ||
1365 | if (tf->flags & ATA_TFLAG_FUA) | ||
1366 | tf->device |= 1 << 7; | ||
1367 | } else if (dev->flags & ATA_DFLAG_LBA) { | ||
1368 | tf->flags |= ATA_TFLAG_LBA; | ||
1369 | |||
1370 | if (lba_28_ok(block, n_block)) { | ||
1371 | /* use LBA28 */ | ||
1372 | tf->device |= (block >> 24) & 0xf; | ||
1373 | } else if (lba_48_ok(block, n_block)) { | ||
1374 | if (!(dev->flags & ATA_DFLAG_LBA48)) | ||
1375 | goto out_of_range; | ||
1376 | |||
1377 | /* use LBA48 */ | ||
1378 | tf->flags |= ATA_TFLAG_LBA48; | ||
1379 | |||
1380 | tf->hob_nsect = (n_block >> 8) & 0xff; | ||
1381 | |||
1382 | tf->hob_lbah = (block >> 40) & 0xff; | ||
1383 | tf->hob_lbam = (block >> 32) & 0xff; | ||
1384 | tf->hob_lbal = (block >> 24) & 0xff; | ||
1385 | } else | ||
1386 | /* request too large even for LBA48 */ | ||
1387 | goto out_of_range; | ||
1388 | |||
1389 | if (unlikely(ata_rwcmd_protocol(qc) < 0)) | ||
1390 | goto invalid_fld; | ||
1391 | |||
1392 | qc->nsect = n_block; | ||
1393 | tf->nsect = n_block & 0xff; | ||
1394 | |||
1395 | tf->lbah = (block >> 16) & 0xff; | ||
1396 | tf->lbam = (block >> 8) & 0xff; | ||
1397 | tf->lbal = block & 0xff; | ||
1398 | |||
1399 | tf->device |= ATA_LBA; | ||
1400 | } else { | ||
1401 | /* CHS */ | ||
1402 | u32 sect, head, cyl, track; | ||
1403 | |||
1404 | /* The request -may- be too large for CHS addressing. */ | ||
1405 | if (!lba_28_ok(block, n_block)) | ||
1406 | goto out_of_range; | ||
1407 | |||
1408 | if (unlikely(ata_rwcmd_protocol(qc) < 0)) | ||
1409 | goto invalid_fld; | ||
1410 | |||
1411 | /* Convert LBA to CHS */ | ||
1412 | track = (u32)block / dev->sectors; | ||
1413 | cyl = track / dev->heads; | ||
1414 | head = track % dev->heads; | ||
1415 | sect = (u32)block % dev->sectors + 1; | ||
1416 | |||
1417 | DPRINTK("block %u track %u cyl %u head %u sect %u\n", | ||
1418 | (u32)block, track, cyl, head, sect); | ||
1419 | |||
1420 | /* Check whether the converted CHS can fit. | ||
1421 | Cylinder: 0-65535 | ||
1422 | Head: 0-15 | ||
1423 | Sector: 1-255*/ | ||
1424 | if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) | ||
1425 | goto out_of_range; | ||
1426 | |||
1427 | qc->nsect = n_block; | ||
1428 | tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ | ||
1429 | tf->lbal = sect; | ||
1430 | tf->lbam = cyl; | ||
1431 | tf->lbah = cyl >> 8; | ||
1432 | tf->device |= head; | ||
1433 | } | ||
1434 | 1319 | ||
1435 | return 0; | 1320 | rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, |
1321 | qc->tag); | ||
1322 | if (likely(rc == 0)) | ||
1323 | return 0; | ||
1436 | 1324 | ||
1325 | if (rc == -ERANGE) | ||
1326 | goto out_of_range; | ||
1327 | /* treat all other errors as -EINVAL, fall through */ | ||
1437 | invalid_fld: | 1328 | invalid_fld: |
1438 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0); | 1329 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0); |
1439 | /* "Invalid field in cbd" */ | 1330 | /* "Invalid field in cbd" */ |
@@ -1477,7 +1368,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
1477 | */ | 1368 | */ |
1478 | if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && | 1369 | if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && |
1479 | ((cdb[2] & 0x20) || need_sense)) { | 1370 | ((cdb[2] & 0x20) || need_sense)) { |
1480 | ata_gen_ata_desc_sense(qc); | 1371 | ata_gen_passthru_sense(qc); |
1481 | } else { | 1372 | } else { |
1482 | if (!need_sense) { | 1373 | if (!need_sense) { |
1483 | cmd->result = SAM_STAT_GOOD; | 1374 | cmd->result = SAM_STAT_GOOD; |
@@ -1488,7 +1379,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
1488 | * good for smaller LBA (and maybe CHS?) | 1379 | * good for smaller LBA (and maybe CHS?) |
1489 | * devices. | 1380 | * devices. |
1490 | */ | 1381 | */ |
1491 | ata_gen_fixed_sense(qc); | 1382 | ata_gen_ata_sense(qc); |
1492 | } | 1383 | } |
1493 | } | 1384 | } |
1494 | 1385 | ||
@@ -1715,6 +1606,22 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, | |||
1715 | } | 1606 | } |
1716 | 1607 | ||
1717 | /** | 1608 | /** |
1609 | * ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer | ||
1610 | * @idx: byte index into SCSI response buffer | ||
1611 | * @val: value to set | ||
1612 | * | ||
1613 | * To be used by SCSI command simulator functions. This macros | ||
1614 | * expects two local variables, u8 *rbuf and unsigned int buflen, | ||
1615 | * are in scope. | ||
1616 | * | ||
1617 | * LOCKING: | ||
1618 | * None. | ||
1619 | */ | ||
1620 | #define ATA_SCSI_RBUF_SET(idx, val) do { \ | ||
1621 | if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \ | ||
1622 | } while (0) | ||
1623 | |||
1624 | /** | ||
1718 | * ata_scsiop_inq_std - Simulate INQUIRY command | 1625 | * ata_scsiop_inq_std - Simulate INQUIRY command |
1719 | * @args: device IDENTIFY data / SCSI command of interest. | 1626 | * @args: device IDENTIFY data / SCSI command of interest. |
1720 | * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. | 1627 | * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. |
@@ -2173,67 +2080,42 @@ saving_not_supp: | |||
2173 | * Simulate READ CAPACITY commands. | 2080 | * Simulate READ CAPACITY commands. |
2174 | * | 2081 | * |
2175 | * LOCKING: | 2082 | * LOCKING: |
2176 | * spin_lock_irqsave(host lock) | 2083 | * None. |
2177 | */ | 2084 | */ |
2178 | |||
2179 | unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, | 2085 | unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, |
2180 | unsigned int buflen) | 2086 | unsigned int buflen) |
2181 | { | 2087 | { |
2182 | u64 n_sectors; | 2088 | u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */ |
2183 | u32 tmp; | ||
2184 | 2089 | ||
2185 | VPRINTK("ENTER\n"); | 2090 | VPRINTK("ENTER\n"); |
2186 | 2091 | ||
2187 | if (ata_id_has_lba(args->id)) { | ||
2188 | if (ata_id_has_lba48(args->id)) | ||
2189 | n_sectors = ata_id_u64(args->id, 100); | ||
2190 | else | ||
2191 | n_sectors = ata_id_u32(args->id, 60); | ||
2192 | } else { | ||
2193 | /* CHS default translation */ | ||
2194 | n_sectors = args->id[1] * args->id[3] * args->id[6]; | ||
2195 | |||
2196 | if (ata_id_current_chs_valid(args->id)) | ||
2197 | /* CHS current translation */ | ||
2198 | n_sectors = ata_id_u32(args->id, 57); | ||
2199 | } | ||
2200 | |||
2201 | n_sectors--; /* ATA TotalUserSectors - 1 */ | ||
2202 | |||
2203 | if (args->cmd->cmnd[0] == READ_CAPACITY) { | 2092 | if (args->cmd->cmnd[0] == READ_CAPACITY) { |
2204 | if( n_sectors >= 0xffffffffULL ) | 2093 | if (last_lba >= 0xffffffffULL) |
2205 | tmp = 0xffffffff ; /* Return max count on overflow */ | 2094 | last_lba = 0xffffffff; |
2206 | else | ||
2207 | tmp = n_sectors ; | ||
2208 | 2095 | ||
2209 | /* sector count, 32-bit */ | 2096 | /* sector count, 32-bit */ |
2210 | rbuf[0] = tmp >> (8 * 3); | 2097 | ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3)); |
2211 | rbuf[1] = tmp >> (8 * 2); | 2098 | ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2)); |
2212 | rbuf[2] = tmp >> (8 * 1); | 2099 | ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1)); |
2213 | rbuf[3] = tmp; | 2100 | ATA_SCSI_RBUF_SET(3, last_lba); |
2214 | 2101 | ||
2215 | /* sector size */ | 2102 | /* sector size */ |
2216 | tmp = ATA_SECT_SIZE; | 2103 | ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8); |
2217 | rbuf[6] = tmp >> 8; | 2104 | ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE); |
2218 | rbuf[7] = tmp; | ||
2219 | |||
2220 | } else { | 2105 | } else { |
2221 | /* sector count, 64-bit */ | 2106 | /* sector count, 64-bit */ |
2222 | tmp = n_sectors >> (8 * 4); | 2107 | ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7)); |
2223 | rbuf[2] = tmp >> (8 * 3); | 2108 | ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6)); |
2224 | rbuf[3] = tmp >> (8 * 2); | 2109 | ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5)); |
2225 | rbuf[4] = tmp >> (8 * 1); | 2110 | ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4)); |
2226 | rbuf[5] = tmp; | 2111 | ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3)); |
2227 | tmp = n_sectors; | 2112 | ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2)); |
2228 | rbuf[6] = tmp >> (8 * 3); | 2113 | ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1)); |
2229 | rbuf[7] = tmp >> (8 * 2); | 2114 | ATA_SCSI_RBUF_SET(7, last_lba); |
2230 | rbuf[8] = tmp >> (8 * 1); | ||
2231 | rbuf[9] = tmp; | ||
2232 | 2115 | ||
2233 | /* sector size */ | 2116 | /* sector size */ |
2234 | tmp = ATA_SECT_SIZE; | 2117 | ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8); |
2235 | rbuf[12] = tmp >> 8; | 2118 | ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE); |
2236 | rbuf[13] = tmp; | ||
2237 | } | 2119 | } |
2238 | 2120 | ||
2239 | return 0; | 2121 | return 0; |
@@ -2319,7 +2201,7 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc) | |||
2319 | * a sense descriptors, since that's only | 2201 | * a sense descriptors, since that's only |
2320 | * correct for ATA, not ATAPI | 2202 | * correct for ATA, not ATAPI |
2321 | */ | 2203 | */ |
2322 | ata_gen_ata_desc_sense(qc); | 2204 | ata_gen_passthru_sense(qc); |
2323 | } | 2205 | } |
2324 | 2206 | ||
2325 | qc->scsidone(qc->scsicmd); | 2207 | qc->scsidone(qc->scsicmd); |
@@ -2394,7 +2276,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) | |||
2394 | * sense descriptors, since that's only | 2276 | * sense descriptors, since that's only |
2395 | * correct for ATA, not ATAPI | 2277 | * correct for ATA, not ATAPI |
2396 | */ | 2278 | */ |
2397 | ata_gen_ata_desc_sense(qc); | 2279 | ata_gen_passthru_sense(qc); |
2398 | } | 2280 | } |
2399 | 2281 | ||
2400 | /* SCSI EH automatically locks door if sdev->locked is | 2282 | /* SCSI EH automatically locks door if sdev->locked is |
@@ -2427,7 +2309,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) | |||
2427 | * a sense descriptors, since that's only | 2309 | * a sense descriptors, since that's only |
2428 | * correct for ATA, not ATAPI | 2310 | * correct for ATA, not ATAPI |
2429 | */ | 2311 | */ |
2430 | ata_gen_ata_desc_sense(qc); | 2312 | ata_gen_passthru_sense(qc); |
2431 | } else { | 2313 | } else { |
2432 | u8 *scsicmd = cmd->cmnd; | 2314 | u8 *scsicmd = cmd->cmnd; |
2433 | 2315 | ||
@@ -3182,10 +3064,12 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, | |||
3182 | rc = -EINVAL; | 3064 | rc = -EINVAL; |
3183 | } | 3065 | } |
3184 | 3066 | ||
3185 | if (rc == 0) | 3067 | if (rc == 0) { |
3186 | ata_port_schedule_eh(ap); | 3068 | ata_port_schedule_eh(ap); |
3187 | 3069 | spin_unlock_irqrestore(ap->lock, flags); | |
3188 | spin_unlock_irqrestore(ap->lock, flags); | 3070 | ata_port_wait_eh(ap); |
3071 | } else | ||
3072 | spin_unlock_irqrestore(ap->lock, flags); | ||
3189 | 3073 | ||
3190 | return rc; | 3074 | return rc; |
3191 | } | 3075 | } |
@@ -3205,15 +3089,27 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, | |||
3205 | void ata_scsi_dev_rescan(void *data) | 3089 | void ata_scsi_dev_rescan(void *data) |
3206 | { | 3090 | { |
3207 | struct ata_port *ap = data; | 3091 | struct ata_port *ap = data; |
3208 | struct ata_device *dev; | 3092 | unsigned long flags; |
3209 | unsigned int i; | 3093 | unsigned int i; |
3210 | 3094 | ||
3095 | spin_lock_irqsave(ap->lock, flags); | ||
3096 | |||
3211 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 3097 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
3212 | dev = &ap->device[i]; | 3098 | struct ata_device *dev = &ap->device[i]; |
3099 | struct scsi_device *sdev = dev->sdev; | ||
3213 | 3100 | ||
3214 | if (ata_dev_enabled(dev) && dev->sdev) | 3101 | if (!ata_dev_enabled(dev) || !sdev) |
3215 | scsi_rescan_device(&(dev->sdev->sdev_gendev)); | 3102 | continue; |
3103 | if (scsi_device_get(sdev)) | ||
3104 | continue; | ||
3105 | |||
3106 | spin_unlock_irqrestore(ap->lock, flags); | ||
3107 | scsi_rescan_device(&(sdev->sdev_gendev)); | ||
3108 | scsi_device_put(sdev); | ||
3109 | spin_lock_irqsave(ap->lock, flags); | ||
3216 | } | 3110 | } |
3111 | |||
3112 | spin_unlock_irqrestore(ap->lock, flags); | ||
3217 | } | 3113 | } |
3218 | 3114 | ||
3219 | /** | 3115 | /** |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 7645f2b30ccf..10ee22ae5c15 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -39,6 +39,35 @@ | |||
39 | #include "libata.h" | 39 | #include "libata.h" |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * ata_irq_on - Enable interrupts on a port. | ||
43 | * @ap: Port on which interrupts are enabled. | ||
44 | * | ||
45 | * Enable interrupts on a legacy IDE device using MMIO or PIO, | ||
46 | * wait for idle, clear any pending interrupts. | ||
47 | * | ||
48 | * LOCKING: | ||
49 | * Inherited from caller. | ||
50 | */ | ||
51 | u8 ata_irq_on(struct ata_port *ap) | ||
52 | { | ||
53 | struct ata_ioports *ioaddr = &ap->ioaddr; | ||
54 | u8 tmp; | ||
55 | |||
56 | ap->ctl &= ~ATA_NIEN; | ||
57 | ap->last_ctl = ap->ctl; | ||
58 | |||
59 | if (ap->flags & ATA_FLAG_MMIO) | ||
60 | writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); | ||
61 | else | ||
62 | outb(ap->ctl, ioaddr->ctl_addr); | ||
63 | tmp = ata_wait_idle(ap); | ||
64 | |||
65 | ap->ops->irq_clear(ap); | ||
66 | |||
67 | return tmp; | ||
68 | } | ||
69 | |||
70 | /** | ||
42 | * ata_tf_load_pio - send taskfile registers to host controller | 71 | * ata_tf_load_pio - send taskfile registers to host controller |
43 | * @ap: Port to which output is sent | 72 | * @ap: Port to which output is sent |
44 | * @tf: ATA taskfile register set | 73 | * @tf: ATA taskfile register set |
@@ -671,6 +700,14 @@ void ata_bmdma_freeze(struct ata_port *ap) | |||
671 | writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr); | 700 | writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr); |
672 | else | 701 | else |
673 | outb(ap->ctl, ioaddr->ctl_addr); | 702 | outb(ap->ctl, ioaddr->ctl_addr); |
703 | |||
704 | /* Under certain circumstances, some controllers raise IRQ on | ||
705 | * ATA_NIEN manipulation. Also, many controllers fail to mask | ||
706 | * previously pending IRQ on ATA_NIEN assertion. Clear it. | ||
707 | */ | ||
708 | ata_chk_status(ap); | ||
709 | |||
710 | ap->ops->irq_clear(ap); | ||
674 | } | 711 | } |
675 | 712 | ||
676 | /** | 713 | /** |
@@ -714,7 +751,6 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
714 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, | 751 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, |
715 | ata_postreset_fn_t postreset) | 752 | ata_postreset_fn_t postreset) |
716 | { | 753 | { |
717 | struct ata_eh_context *ehc = &ap->eh_context; | ||
718 | struct ata_queued_cmd *qc; | 754 | struct ata_queued_cmd *qc; |
719 | unsigned long flags; | 755 | unsigned long flags; |
720 | int thaw = 0; | 756 | int thaw = 0; |
@@ -732,9 +768,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
732 | qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { | 768 | qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { |
733 | u8 host_stat; | 769 | u8 host_stat; |
734 | 770 | ||
735 | host_stat = ata_bmdma_status(ap); | 771 | host_stat = ap->ops->bmdma_status(ap); |
736 | |||
737 | ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat); | ||
738 | 772 | ||
739 | /* BMDMA controllers indicate host bus error by | 773 | /* BMDMA controllers indicate host bus error by |
740 | * setting DMA_ERR bit and timing out. As it wasn't | 774 | * setting DMA_ERR bit and timing out. As it wasn't |
@@ -877,6 +911,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, | |||
877 | return NULL; | 911 | return NULL; |
878 | 912 | ||
879 | probe_ent->n_ports = 2; | 913 | probe_ent->n_ports = 2; |
914 | probe_ent->irq_flags = IRQF_SHARED; | ||
880 | 915 | ||
881 | if (port_mask & ATA_PORT_PRIMARY) { | 916 | if (port_mask & ATA_PORT_PRIMARY) { |
882 | probe_ent->irq = ATA_PRIMARY_IRQ; | 917 | probe_ent->irq = ATA_PRIMARY_IRQ; |
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 0ed263be652a..107b2b565229 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -39,26 +39,39 @@ struct ata_scsi_args { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* libata-core.c */ | 41 | /* libata-core.c */ |
42 | enum { | ||
43 | /* flags for ata_dev_read_id() */ | ||
44 | ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ | ||
45 | }; | ||
46 | |||
42 | extern struct workqueue_struct *ata_aux_wq; | 47 | extern struct workqueue_struct *ata_aux_wq; |
43 | extern int atapi_enabled; | 48 | extern int atapi_enabled; |
44 | extern int atapi_dmadir; | 49 | extern int atapi_dmadir; |
45 | extern int libata_fua; | 50 | extern int libata_fua; |
46 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); | 51 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); |
47 | extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); | 52 | extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, |
53 | u64 block, u32 n_block, unsigned int tf_flags, | ||
54 | unsigned int tag); | ||
55 | extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); | ||
48 | extern void ata_dev_disable(struct ata_device *dev); | 56 | extern void ata_dev_disable(struct ata_device *dev); |
49 | extern void ata_port_flush_task(struct ata_port *ap); | 57 | extern void ata_port_flush_task(struct ata_port *ap); |
50 | extern unsigned ata_exec_internal(struct ata_device *dev, | 58 | extern unsigned ata_exec_internal(struct ata_device *dev, |
51 | struct ata_taskfile *tf, const u8 *cdb, | 59 | struct ata_taskfile *tf, const u8 *cdb, |
52 | int dma_dir, void *buf, unsigned int buflen); | 60 | int dma_dir, void *buf, unsigned int buflen); |
61 | extern unsigned ata_exec_internal_sg(struct ata_device *dev, | ||
62 | struct ata_taskfile *tf, const u8 *cdb, | ||
63 | int dma_dir, struct scatterlist *sg, | ||
64 | unsigned int n_elem); | ||
53 | extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd); | 65 | extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd); |
54 | extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | 66 | extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, |
55 | int post_reset, u16 *id); | 67 | unsigned int flags, u16 *id); |
56 | extern int ata_dev_revalidate(struct ata_device *dev, int post_reset); | 68 | extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags); |
57 | extern int ata_dev_configure(struct ata_device *dev, int print_info); | 69 | extern int ata_dev_configure(struct ata_device *dev); |
58 | extern int sata_down_spd_limit(struct ata_port *ap); | 70 | extern int sata_down_spd_limit(struct ata_port *ap); |
59 | extern int sata_set_spd_needed(struct ata_port *ap); | 71 | extern int sata_set_spd_needed(struct ata_port *ap); |
60 | extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); | 72 | extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); |
61 | extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); | 73 | extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); |
74 | extern void ata_sg_clean(struct ata_queued_cmd *qc); | ||
62 | extern void ata_qc_free(struct ata_queued_cmd *qc); | 75 | extern void ata_qc_free(struct ata_queued_cmd *qc); |
63 | extern void ata_qc_issue(struct ata_queued_cmd *qc); | 76 | extern void ata_qc_issue(struct ata_queued_cmd *qc); |
64 | extern void __ata_qc_complete(struct ata_queued_cmd *qc); | 77 | extern void __ata_qc_complete(struct ata_queued_cmd *qc); |
@@ -120,4 +133,7 @@ extern void ata_scsi_error(struct Scsi_Host *host); | |||
120 | extern void ata_port_wait_eh(struct ata_port *ap); | 133 | extern void ata_port_wait_eh(struct ata_port *ap); |
121 | extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); | 134 | extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); |
122 | 135 | ||
136 | /* libata-sff.c */ | ||
137 | extern u8 ata_irq_on(struct ata_port *ap); | ||
138 | |||
123 | #endif /* __LIBATA_H__ */ | 139 | #endif /* __LIBATA_H__ */ |
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 64eed99f6814..c5d61d1911a5 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/dmi.h> | 34 | #include <linux/dmi.h> |
35 | 35 | ||
36 | #define DRV_NAME "pata_ali" | 36 | #define DRV_NAME "pata_ali" |
37 | #define DRV_VERSION "0.6.6" | 37 | #define DRV_VERSION "0.7.2" |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Cable special cases | 40 | * Cable special cases |
@@ -78,7 +78,7 @@ static int ali_c2_cable_detect(struct ata_port *ap) | |||
78 | implement the detect logic */ | 78 | implement the detect logic */ |
79 | 79 | ||
80 | if (ali_cable_override(pdev)) | 80 | if (ali_cable_override(pdev)) |
81 | return ATA_CBL_PATA80; | 81 | return ATA_CBL_PATA40_SHORT; |
82 | 82 | ||
83 | /* Host view cable detect 0x4A bit 0 primary bit 1 secondary | 83 | /* Host view cable detect 0x4A bit 0 primary bit 1 secondary |
84 | Bit set for 40 pin */ | 84 | Bit set for 40 pin */ |
@@ -337,9 +337,6 @@ static struct scsi_host_template ali_sht = { | |||
337 | .can_queue = ATA_DEF_QUEUE, | 337 | .can_queue = ATA_DEF_QUEUE, |
338 | .this_id = ATA_SHT_THIS_ID, | 338 | .this_id = ATA_SHT_THIS_ID, |
339 | .sg_tablesize = LIBATA_MAX_PRD, | 339 | .sg_tablesize = LIBATA_MAX_PRD, |
340 | /* Keep LBA28 counts so large I/O's don't turn LBA48 and PIO | ||
341 | with older controllers. Not locked so will grow on C5 or later */ | ||
342 | .max_sectors = 255, | ||
343 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 340 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
344 | .emulated = ATA_SHT_EMULATED, | 341 | .emulated = ATA_SHT_EMULATED, |
345 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 342 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -348,6 +345,8 @@ static struct scsi_host_template ali_sht = { | |||
348 | .slave_configure = ata_scsi_slave_config, | 345 | .slave_configure = ata_scsi_slave_config, |
349 | .slave_destroy = ata_scsi_slave_destroy, | 346 | .slave_destroy = ata_scsi_slave_destroy, |
350 | .bios_param = ata_std_bios_param, | 347 | .bios_param = ata_std_bios_param, |
348 | .resume = ata_scsi_device_resume, | ||
349 | .suspend = ata_scsi_device_suspend, | ||
351 | }; | 350 | }; |
352 | 351 | ||
353 | /* | 352 | /* |
@@ -497,6 +496,69 @@ static struct ata_port_operations ali_c5_port_ops = { | |||
497 | .host_stop = ata_host_stop | 496 | .host_stop = ata_host_stop |
498 | }; | 497 | }; |
499 | 498 | ||
499 | |||
500 | /** | ||
501 | * ali_init_chipset - chip setup function | ||
502 | * @pdev: PCI device of ATA controller | ||
503 | * | ||
504 | * Perform the setup on the device that must be done both at boot | ||
505 | * and at resume time. | ||
506 | */ | ||
507 | |||
508 | static void ali_init_chipset(struct pci_dev *pdev) | ||
509 | { | ||
510 | u8 rev, tmp; | ||
511 | struct pci_dev *north, *isa_bridge; | ||
512 | |||
513 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); | ||
514 | |||
515 | /* | ||
516 | * The chipset revision selects the driver operations and | ||
517 | * mode data. | ||
518 | */ | ||
519 | |||
520 | if (rev >= 0x20 && rev < 0xC2) { | ||
521 | /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */ | ||
522 | pci_read_config_byte(pdev, 0x4B, &tmp); | ||
523 | /* Clear CD-ROM DMA write bit */ | ||
524 | tmp &= 0x7F; | ||
525 | pci_write_config_byte(pdev, 0x4B, tmp); | ||
526 | } else if (rev >= 0xC2) { | ||
527 | /* Enable cable detection logic */ | ||
528 | pci_read_config_byte(pdev, 0x4B, &tmp); | ||
529 | pci_write_config_byte(pdev, 0x4B, tmp | 0x08); | ||
530 | } | ||
531 | north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); | ||
532 | isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); | ||
533 | |||
534 | if (north && north->vendor == PCI_VENDOR_ID_AL && isa_bridge) { | ||
535 | /* Configure the ALi bridge logic. For non ALi rely on BIOS. | ||
536 | Set the south bridge enable bit */ | ||
537 | pci_read_config_byte(isa_bridge, 0x79, &tmp); | ||
538 | if (rev == 0xC2) | ||
539 | pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04); | ||
540 | else if (rev > 0xC2 && rev < 0xC5) | ||
541 | pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02); | ||
542 | } | ||
543 | if (rev >= 0x20) { | ||
544 | /* | ||
545 | * CD_ROM DMA on (0x53 bit 0). Enable this even if we want | ||
546 | * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control | ||
547 | * via 0x54/55. | ||
548 | */ | ||
549 | pci_read_config_byte(pdev, 0x53, &tmp); | ||
550 | if (rev <= 0x20) | ||
551 | tmp &= ~0x02; | ||
552 | if (rev >= 0xc7) | ||
553 | tmp |= 0x03; | ||
554 | else | ||
555 | tmp |= 0x01; /* CD_ROM enable for DMA */ | ||
556 | pci_write_config_byte(pdev, 0x53, tmp); | ||
557 | } | ||
558 | pci_dev_put(isa_bridge); | ||
559 | pci_dev_put(north); | ||
560 | ata_pci_clear_simplex(pdev); | ||
561 | } | ||
500 | /** | 562 | /** |
501 | * ali_init_one - discovery callback | 563 | * ali_init_one - discovery callback |
502 | * @pdev: PCI device ID | 564 | * @pdev: PCI device ID |
@@ -570,7 +632,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
570 | 632 | ||
571 | static struct ata_port_info *port_info[2]; | 633 | static struct ata_port_info *port_info[2]; |
572 | u8 rev, tmp; | 634 | u8 rev, tmp; |
573 | struct pci_dev *north, *isa_bridge; | 635 | struct pci_dev *isa_bridge; |
574 | 636 | ||
575 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); | 637 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); |
576 | 638 | ||
@@ -582,11 +644,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
582 | if (rev < 0x20) { | 644 | if (rev < 0x20) { |
583 | port_info[0] = port_info[1] = &info_early; | 645 | port_info[0] = port_info[1] = &info_early; |
584 | } else if (rev < 0xC2) { | 646 | } else if (rev < 0xC2) { |
585 | /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */ | ||
586 | pci_read_config_byte(pdev, 0x4B, &tmp); | ||
587 | /* Clear CD-ROM DMA write bit */ | ||
588 | tmp &= 0x7F; | ||
589 | pci_write_config_byte(pdev, 0x4B, tmp); | ||
590 | port_info[0] = port_info[1] = &info_20; | 647 | port_info[0] = port_info[1] = &info_20; |
591 | } else if (rev == 0xC2) { | 648 | } else if (rev == 0xC2) { |
592 | port_info[0] = port_info[1] = &info_c2; | 649 | port_info[0] = port_info[1] = &info_c2; |
@@ -597,54 +654,25 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
597 | } else | 654 | } else |
598 | port_info[0] = port_info[1] = &info_c5; | 655 | port_info[0] = port_info[1] = &info_c5; |
599 | 656 | ||
600 | if (rev >= 0xC2) { | 657 | ali_init_chipset(pdev); |
601 | /* Enable cable detection logic */ | 658 | |
602 | pci_read_config_byte(pdev, 0x4B, &tmp); | ||
603 | pci_write_config_byte(pdev, 0x4B, tmp | 0x08); | ||
604 | } | ||
605 | |||
606 | north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0)); | ||
607 | isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); | 659 | isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); |
608 | 660 | if (isa_bridge && rev >= 0x20 && rev < 0xC2) { | |
609 | if (north && north->vendor == PCI_VENDOR_ID_AL) { | 661 | /* Are we paired with a UDMA capable chip */ |
610 | /* Configure the ALi bridge logic. For non ALi rely on BIOS. | 662 | pci_read_config_byte(isa_bridge, 0x5E, &tmp); |
611 | Set the south bridge enable bit */ | 663 | if ((tmp & 0x1E) == 0x12) |
612 | pci_read_config_byte(isa_bridge, 0x79, &tmp); | 664 | port_info[0] = port_info[1] = &info_20_udma; |
613 | if (rev == 0xC2) | 665 | pci_dev_put(isa_bridge); |
614 | pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04); | ||
615 | else if (rev > 0xC2) | ||
616 | pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02); | ||
617 | } | ||
618 | |||
619 | if (rev >= 0x20) { | ||
620 | if (rev < 0xC2) { | ||
621 | /* Are we paired with a UDMA capable chip */ | ||
622 | pci_read_config_byte(isa_bridge, 0x5E, &tmp); | ||
623 | if ((tmp & 0x1E) == 0x12) | ||
624 | port_info[0] = port_info[1] = &info_20_udma; | ||
625 | } | ||
626 | /* | ||
627 | * CD_ROM DMA on (0x53 bit 0). Enable this even if we want | ||
628 | * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control | ||
629 | * via 0x54/55. | ||
630 | */ | ||
631 | pci_read_config_byte(pdev, 0x53, &tmp); | ||
632 | if (rev <= 0x20) | ||
633 | tmp &= ~0x02; | ||
634 | if (rev >= 0xc7) | ||
635 | tmp |= 0x03; | ||
636 | else | ||
637 | tmp |= 0x01; /* CD_ROM enable for DMA */ | ||
638 | pci_write_config_byte(pdev, 0x53, tmp); | ||
639 | } | 666 | } |
640 | |||
641 | pci_dev_put(isa_bridge); | ||
642 | pci_dev_put(north); | ||
643 | |||
644 | ata_pci_clear_simplex(pdev); | ||
645 | return ata_pci_init_one(pdev, port_info, 2); | 667 | return ata_pci_init_one(pdev, port_info, 2); |
646 | } | 668 | } |
647 | 669 | ||
670 | static int ali_reinit_one(struct pci_dev *pdev) | ||
671 | { | ||
672 | ali_init_chipset(pdev); | ||
673 | return ata_pci_device_resume(pdev); | ||
674 | } | ||
675 | |||
648 | static const struct pci_device_id ali[] = { | 676 | static const struct pci_device_id ali[] = { |
649 | { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), }, | 677 | { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), }, |
650 | { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), }, | 678 | { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), }, |
@@ -656,7 +684,9 @@ static struct pci_driver ali_pci_driver = { | |||
656 | .name = DRV_NAME, | 684 | .name = DRV_NAME, |
657 | .id_table = ali, | 685 | .id_table = ali, |
658 | .probe = ali_init_one, | 686 | .probe = ali_init_one, |
659 | .remove = ata_pci_remove_one | 687 | .remove = ata_pci_remove_one, |
688 | .suspend = ata_pci_device_suspend, | ||
689 | .resume = ali_reinit_one, | ||
660 | }; | 690 | }; |
661 | 691 | ||
662 | static int __init ali_init(void) | 692 | static int __init ali_init(void) |
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 8be46a63af74..a6b330089f22 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/libata.h> | 25 | #include <linux/libata.h> |
26 | 26 | ||
27 | #define DRV_NAME "pata_amd" | 27 | #define DRV_NAME "pata_amd" |
28 | #define DRV_VERSION "0.2.4" | 28 | #define DRV_VERSION "0.2.7" |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * timing_setup - shared timing computation and load | 31 | * timing_setup - shared timing computation and load |
@@ -326,7 +326,6 @@ static struct scsi_host_template amd_sht = { | |||
326 | .can_queue = ATA_DEF_QUEUE, | 326 | .can_queue = ATA_DEF_QUEUE, |
327 | .this_id = ATA_SHT_THIS_ID, | 327 | .this_id = ATA_SHT_THIS_ID, |
328 | .sg_tablesize = LIBATA_MAX_PRD, | 328 | .sg_tablesize = LIBATA_MAX_PRD, |
329 | .max_sectors = ATA_MAX_SECTORS, | ||
330 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 329 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
331 | .emulated = ATA_SHT_EMULATED, | 330 | .emulated = ATA_SHT_EMULATED, |
332 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 331 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -335,6 +334,8 @@ static struct scsi_host_template amd_sht = { | |||
335 | .slave_configure = ata_scsi_slave_config, | 334 | .slave_configure = ata_scsi_slave_config, |
336 | .slave_destroy = ata_scsi_slave_destroy, | 335 | .slave_destroy = ata_scsi_slave_destroy, |
337 | .bios_param = ata_std_bios_param, | 336 | .bios_param = ata_std_bios_param, |
337 | .resume = ata_scsi_device_resume, | ||
338 | .suspend = ata_scsi_device_suspend, | ||
338 | }; | 339 | }; |
339 | 340 | ||
340 | static struct ata_port_operations amd33_port_ops = { | 341 | static struct ata_port_operations amd33_port_ops = { |
@@ -662,6 +663,23 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
662 | return ata_pci_init_one(pdev, port_info, 2); | 663 | return ata_pci_init_one(pdev, port_info, 2); |
663 | } | 664 | } |
664 | 665 | ||
666 | static int amd_reinit_one(struct pci_dev *pdev) | ||
667 | { | ||
668 | if (pdev->vendor == PCI_VENDOR_ID_AMD) { | ||
669 | u8 fifo; | ||
670 | pci_read_config_byte(pdev, 0x41, &fifo); | ||
671 | if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) | ||
672 | /* FIFO is broken */ | ||
673 | pci_write_config_byte(pdev, 0x41, fifo & 0x0F); | ||
674 | else | ||
675 | pci_write_config_byte(pdev, 0x41, fifo | 0xF0); | ||
676 | if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 || | ||
677 | pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401) | ||
678 | ata_pci_clear_simplex(pdev); | ||
679 | } | ||
680 | return ata_pci_device_resume(pdev); | ||
681 | } | ||
682 | |||
665 | static const struct pci_device_id amd[] = { | 683 | static const struct pci_device_id amd[] = { |
666 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 }, | 684 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 }, |
667 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 }, | 685 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 }, |
@@ -689,7 +707,9 @@ static struct pci_driver amd_pci_driver = { | |||
689 | .name = DRV_NAME, | 707 | .name = DRV_NAME, |
690 | .id_table = amd, | 708 | .id_table = amd, |
691 | .probe = amd_init_one, | 709 | .probe = amd_init_one, |
692 | .remove = ata_pci_remove_one | 710 | .remove = ata_pci_remove_one, |
711 | .suspend = ata_pci_device_suspend, | ||
712 | .resume = amd_reinit_one, | ||
693 | }; | 713 | }; |
694 | 714 | ||
695 | static int __init amd_init(void) | 715 | static int __init amd_init(void) |
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 2cd30761ca1f..37bc1323bda7 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c | |||
@@ -307,7 +307,6 @@ static struct scsi_host_template artop_sht = { | |||
307 | .can_queue = ATA_DEF_QUEUE, | 307 | .can_queue = ATA_DEF_QUEUE, |
308 | .this_id = ATA_SHT_THIS_ID, | 308 | .this_id = ATA_SHT_THIS_ID, |
309 | .sg_tablesize = LIBATA_MAX_PRD, | 309 | .sg_tablesize = LIBATA_MAX_PRD, |
310 | .max_sectors = ATA_MAX_SECTORS, | ||
311 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 310 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
312 | .emulated = ATA_SHT_EMULATED, | 311 | .emulated = ATA_SHT_EMULATED, |
313 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 312 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 4e1d3b59adbb..6f6672c55131 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/libata.h> | 22 | #include <linux/libata.h> |
23 | 23 | ||
24 | #define DRV_NAME "pata_atiixp" | 24 | #define DRV_NAME "pata_atiixp" |
25 | #define DRV_VERSION "0.4.3" | 25 | #define DRV_VERSION "0.4.4" |
26 | 26 | ||
27 | enum { | 27 | enum { |
28 | ATIIXP_IDE_PIO_TIMING = 0x40, | 28 | ATIIXP_IDE_PIO_TIMING = 0x40, |
@@ -209,7 +209,6 @@ static struct scsi_host_template atiixp_sht = { | |||
209 | .can_queue = ATA_DEF_QUEUE, | 209 | .can_queue = ATA_DEF_QUEUE, |
210 | .this_id = ATA_SHT_THIS_ID, | 210 | .this_id = ATA_SHT_THIS_ID, |
211 | .sg_tablesize = LIBATA_MAX_PRD, | 211 | .sg_tablesize = LIBATA_MAX_PRD, |
212 | .max_sectors = ATA_MAX_SECTORS, | ||
213 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 212 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
214 | .emulated = ATA_SHT_EMULATED, | 213 | .emulated = ATA_SHT_EMULATED, |
215 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 214 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -218,6 +217,8 @@ static struct scsi_host_template atiixp_sht = { | |||
218 | .slave_configure = ata_scsi_slave_config, | 217 | .slave_configure = ata_scsi_slave_config, |
219 | .slave_destroy = ata_scsi_slave_destroy, | 218 | .slave_destroy = ata_scsi_slave_destroy, |
220 | .bios_param = ata_std_bios_param, | 219 | .bios_param = ata_std_bios_param, |
220 | .resume = ata_scsi_device_resume, | ||
221 | .suspend = ata_scsi_device_suspend, | ||
221 | }; | 222 | }; |
222 | 223 | ||
223 | static struct ata_port_operations atiixp_port_ops = { | 224 | static struct ata_port_operations atiixp_port_ops = { |
@@ -281,7 +282,9 @@ static struct pci_driver atiixp_pci_driver = { | |||
281 | .name = DRV_NAME, | 282 | .name = DRV_NAME, |
282 | .id_table = atiixp, | 283 | .id_table = atiixp, |
283 | .probe = atiixp_init_one, | 284 | .probe = atiixp_init_one, |
284 | .remove = ata_pci_remove_one | 285 | .remove = ata_pci_remove_one, |
286 | .resume = ata_pci_device_resume, | ||
287 | .suspend = ata_pci_device_suspend, | ||
285 | }; | 288 | }; |
286 | 289 | ||
287 | static int __init atiixp_init(void) | 290 | static int __init atiixp_init(void) |
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 29a60df465da..15841a563694 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/libata.h> | 31 | #include <linux/libata.h> |
32 | 32 | ||
33 | #define DRV_NAME "pata_cmd64x" | 33 | #define DRV_NAME "pata_cmd64x" |
34 | #define DRV_VERSION "0.2.1" | 34 | #define DRV_VERSION "0.2.2" |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * CMD64x specific registers definition. | 37 | * CMD64x specific registers definition. |
@@ -268,7 +268,6 @@ static struct scsi_host_template cmd64x_sht = { | |||
268 | .can_queue = ATA_DEF_QUEUE, | 268 | .can_queue = ATA_DEF_QUEUE, |
269 | .this_id = ATA_SHT_THIS_ID, | 269 | .this_id = ATA_SHT_THIS_ID, |
270 | .sg_tablesize = LIBATA_MAX_PRD, | 270 | .sg_tablesize = LIBATA_MAX_PRD, |
271 | .max_sectors = ATA_MAX_SECTORS, | ||
272 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 271 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
273 | .emulated = ATA_SHT_EMULATED, | 272 | .emulated = ATA_SHT_EMULATED, |
274 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 273 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -277,6 +276,8 @@ static struct scsi_host_template cmd64x_sht = { | |||
277 | .slave_configure = ata_scsi_slave_config, | 276 | .slave_configure = ata_scsi_slave_config, |
278 | .slave_destroy = ata_scsi_slave_destroy, | 277 | .slave_destroy = ata_scsi_slave_destroy, |
279 | .bios_param = ata_std_bios_param, | 278 | .bios_param = ata_std_bios_param, |
279 | .resume = ata_scsi_device_resume, | ||
280 | .suspend = ata_scsi_device_suspend, | ||
280 | }; | 281 | }; |
281 | 282 | ||
282 | static struct ata_port_operations cmd64x_port_ops = { | 283 | static struct ata_port_operations cmd64x_port_ops = { |
@@ -469,6 +470,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
469 | return ata_pci_init_one(pdev, port_info, 2); | 470 | return ata_pci_init_one(pdev, port_info, 2); |
470 | } | 471 | } |
471 | 472 | ||
473 | static int cmd64x_reinit_one(struct pci_dev *pdev) | ||
474 | { | ||
475 | u8 mrdmode; | ||
476 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); | ||
477 | pci_read_config_byte(pdev, MRDMODE, &mrdmode); | ||
478 | mrdmode &= ~ 0x30; /* IRQ set up */ | ||
479 | mrdmode |= 0x02; /* Memory read line enable */ | ||
480 | pci_write_config_byte(pdev, MRDMODE, mrdmode); | ||
481 | #ifdef CONFIG_PPC | ||
482 | pci_write_config_byte(pdev, UDIDETCR0, 0xF0); | ||
483 | #endif | ||
484 | return ata_pci_device_resume(pdev); | ||
485 | } | ||
486 | |||
472 | static const struct pci_device_id cmd64x[] = { | 487 | static const struct pci_device_id cmd64x[] = { |
473 | { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 }, | 488 | { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 }, |
474 | { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 }, | 489 | { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 }, |
@@ -482,7 +497,9 @@ static struct pci_driver cmd64x_pci_driver = { | |||
482 | .name = DRV_NAME, | 497 | .name = DRV_NAME, |
483 | .id_table = cmd64x, | 498 | .id_table = cmd64x, |
484 | .probe = cmd64x_init_one, | 499 | .probe = cmd64x_init_one, |
485 | .remove = ata_pci_remove_one | 500 | .remove = ata_pci_remove_one, |
501 | .suspend = ata_pci_device_suspend, | ||
502 | .resume = cmd64x_reinit_one, | ||
486 | }; | 503 | }; |
487 | 504 | ||
488 | static int __init cmd64x_init(void) | 505 | static int __init cmd64x_init(void) |
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 33d2b88f9c79..9f165a8e032d 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <linux/libata.h> | 41 | #include <linux/libata.h> |
42 | 42 | ||
43 | #define DRV_NAME "pata_cs5520" | 43 | #define DRV_NAME "pata_cs5520" |
44 | #define DRV_VERSION "0.6.2" | 44 | #define DRV_VERSION "0.6.3" |
45 | 45 | ||
46 | struct pio_clocks | 46 | struct pio_clocks |
47 | { | 47 | { |
@@ -159,7 +159,6 @@ static struct scsi_host_template cs5520_sht = { | |||
159 | .can_queue = ATA_DEF_QUEUE, | 159 | .can_queue = ATA_DEF_QUEUE, |
160 | .this_id = ATA_SHT_THIS_ID, | 160 | .this_id = ATA_SHT_THIS_ID, |
161 | .sg_tablesize = LIBATA_MAX_PRD, | 161 | .sg_tablesize = LIBATA_MAX_PRD, |
162 | .max_sectors = ATA_MAX_SECTORS, | ||
163 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 162 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
164 | .emulated = ATA_SHT_EMULATED, | 163 | .emulated = ATA_SHT_EMULATED, |
165 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 164 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -168,6 +167,8 @@ static struct scsi_host_template cs5520_sht = { | |||
168 | .slave_configure = ata_scsi_slave_config, | 167 | .slave_configure = ata_scsi_slave_config, |
169 | .slave_destroy = ata_scsi_slave_destroy, | 168 | .slave_destroy = ata_scsi_slave_destroy, |
170 | .bios_param = ata_std_bios_param, | 169 | .bios_param = ata_std_bios_param, |
170 | .resume = ata_scsi_device_resume, | ||
171 | .suspend = ata_scsi_device_suspend, | ||
171 | }; | 172 | }; |
172 | 173 | ||
173 | static struct ata_port_operations cs5520_port_ops = { | 174 | static struct ata_port_operations cs5520_port_ops = { |
@@ -297,6 +298,22 @@ static void __devexit cs5520_remove_one(struct pci_dev *pdev) | |||
297 | dev_set_drvdata(dev, NULL); | 298 | dev_set_drvdata(dev, NULL); |
298 | } | 299 | } |
299 | 300 | ||
301 | /** | ||
302 | * cs5520_reinit_one - device resume | ||
303 | * @pdev: PCI device | ||
304 | * | ||
305 | * Do any reconfiguration work needed by a resume from RAM. We need | ||
306 | * to restore DMA mode support on BIOSen which disabled it | ||
307 | */ | ||
308 | |||
309 | static int cs5520_reinit_one(struct pci_dev *pdev) | ||
310 | { | ||
311 | u8 pcicfg; | ||
312 | pci_read_config_byte(pdev, 0x60, &pcicfg); | ||
313 | if ((pcicfg & 0x40) == 0) | ||
314 | pci_write_config_byte(pdev, 0x60, pcicfg | 0x40); | ||
315 | return ata_pci_device_resume(pdev); | ||
316 | } | ||
300 | /* For now keep DMA off. We can set it for all but A rev CS5510 once the | 317 | /* For now keep DMA off. We can set it for all but A rev CS5510 once the |
301 | core ATA code can handle it */ | 318 | core ATA code can handle it */ |
302 | 319 | ||
@@ -311,7 +328,9 @@ static struct pci_driver cs5520_pci_driver = { | |||
311 | .name = DRV_NAME, | 328 | .name = DRV_NAME, |
312 | .id_table = pata_cs5520, | 329 | .id_table = pata_cs5520, |
313 | .probe = cs5520_init_one, | 330 | .probe = cs5520_init_one, |
314 | .remove = cs5520_remove_one | 331 | .remove = cs5520_remove_one, |
332 | .suspend = ata_pci_device_suspend, | ||
333 | .resume = cs5520_reinit_one, | ||
315 | }; | 334 | }; |
316 | 335 | ||
317 | static int __init cs5520_init(void) | 336 | static int __init cs5520_init(void) |
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index 981f49223469..1c628014dae6 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/dmi.h> | 35 | #include <linux/dmi.h> |
36 | 36 | ||
37 | #define DRV_NAME "pata_cs5530" | 37 | #define DRV_NAME "pata_cs5530" |
38 | #define DRV_VERSION "0.6" | 38 | #define DRV_VERSION "0.7.1" |
39 | 39 | ||
40 | /** | 40 | /** |
41 | * cs5530_set_piomode - PIO setup | 41 | * cs5530_set_piomode - PIO setup |
@@ -173,7 +173,6 @@ static struct scsi_host_template cs5530_sht = { | |||
173 | .can_queue = ATA_DEF_QUEUE, | 173 | .can_queue = ATA_DEF_QUEUE, |
174 | .this_id = ATA_SHT_THIS_ID, | 174 | .this_id = ATA_SHT_THIS_ID, |
175 | .sg_tablesize = LIBATA_MAX_PRD, | 175 | .sg_tablesize = LIBATA_MAX_PRD, |
176 | .max_sectors = ATA_MAX_SECTORS, | ||
177 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 176 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
178 | .emulated = ATA_SHT_EMULATED, | 177 | .emulated = ATA_SHT_EMULATED, |
179 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 178 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -182,6 +181,8 @@ static struct scsi_host_template cs5530_sht = { | |||
182 | .slave_configure = ata_scsi_slave_config, | 181 | .slave_configure = ata_scsi_slave_config, |
183 | .slave_destroy = ata_scsi_slave_destroy, | 182 | .slave_destroy = ata_scsi_slave_destroy, |
184 | .bios_param = ata_std_bios_param, | 183 | .bios_param = ata_std_bios_param, |
184 | .resume = ata_scsi_device_resume, | ||
185 | .suspend = ata_scsi_device_suspend, | ||
185 | }; | 186 | }; |
186 | 187 | ||
187 | static struct ata_port_operations cs5530_port_ops = { | 188 | static struct ata_port_operations cs5530_port_ops = { |
@@ -239,38 +240,18 @@ static int cs5530_is_palmax(void) | |||
239 | return 0; | 240 | return 0; |
240 | } | 241 | } |
241 | 242 | ||
243 | |||
242 | /** | 244 | /** |
243 | * cs5530_init_one - Initialise a CS5530 | 245 | * cs5530_init_chip - Chipset init |
244 | * @dev: PCI device | ||
245 | * @id: Entry in match table | ||
246 | * | 246 | * |
247 | * Install a driver for the newly found CS5530 companion chip. Most of | 247 | * Perform the chip initialisation work that is shared between both |
248 | * this is just housekeeping. We have to set the chip up correctly and | 248 | * setup and resume paths |
249 | * turn off various bits of emulation magic. | ||
250 | */ | 249 | */ |
251 | 250 | ||
252 | static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) | 251 | static int cs5530_init_chip(void) |
253 | { | 252 | { |
254 | int compiler_warning_pointless_fix; | 253 | struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL; |
255 | struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; | ||
256 | static struct ata_port_info info = { | ||
257 | .sht = &cs5530_sht, | ||
258 | .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, | ||
259 | .pio_mask = 0x1f, | ||
260 | .mwdma_mask = 0x07, | ||
261 | .udma_mask = 0x07, | ||
262 | .port_ops = &cs5530_port_ops | ||
263 | }; | ||
264 | /* The docking connector doesn't do UDMA, and it seems not MWDMA */ | ||
265 | static struct ata_port_info info_palmax_secondary = { | ||
266 | .sht = &cs5530_sht, | ||
267 | .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, | ||
268 | .pio_mask = 0x1f, | ||
269 | .port_ops = &cs5530_port_ops | ||
270 | }; | ||
271 | static struct ata_port_info *port_info[2] = { &info, &info }; | ||
272 | 254 | ||
273 | dev = NULL; | ||
274 | while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { | 255 | while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { |
275 | switch (dev->device) { | 256 | switch (dev->device) { |
276 | case PCI_DEVICE_ID_CYRIX_PCI_MASTER: | 257 | case PCI_DEVICE_ID_CYRIX_PCI_MASTER: |
@@ -291,7 +272,7 @@ static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
291 | } | 272 | } |
292 | 273 | ||
293 | pci_set_master(cs5530_0); | 274 | pci_set_master(cs5530_0); |
294 | compiler_warning_pointless_fix = pci_set_mwi(cs5530_0); | 275 | pci_set_mwi(cs5530_0); |
295 | 276 | ||
296 | /* | 277 | /* |
297 | * Set PCI CacheLineSize to 16-bytes: | 278 | * Set PCI CacheLineSize to 16-bytes: |
@@ -339,13 +320,7 @@ static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
339 | 320 | ||
340 | pci_dev_put(master_0); | 321 | pci_dev_put(master_0); |
341 | pci_dev_put(cs5530_0); | 322 | pci_dev_put(cs5530_0); |
342 | 323 | return 0; | |
343 | if (cs5530_is_palmax()) | ||
344 | port_info[1] = &info_palmax_secondary; | ||
345 | |||
346 | /* Now kick off ATA set up */ | ||
347 | return ata_pci_init_one(dev, port_info, 2); | ||
348 | |||
349 | fail_put: | 324 | fail_put: |
350 | if (master_0) | 325 | if (master_0) |
351 | pci_dev_put(master_0); | 326 | pci_dev_put(master_0); |
@@ -354,6 +329,53 @@ fail_put: | |||
354 | return -ENODEV; | 329 | return -ENODEV; |
355 | } | 330 | } |
356 | 331 | ||
332 | /** | ||
333 | * cs5530_init_one - Initialise a CS5530 | ||
334 | * @dev: PCI device | ||
335 | * @id: Entry in match table | ||
336 | * | ||
337 | * Install a driver for the newly found CS5530 companion chip. Most of | ||
338 | * this is just housekeeping. We have to set the chip up correctly and | ||
339 | * turn off various bits of emulation magic. | ||
340 | */ | ||
341 | |||
342 | static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | ||
343 | { | ||
344 | static struct ata_port_info info = { | ||
345 | .sht = &cs5530_sht, | ||
346 | .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, | ||
347 | .pio_mask = 0x1f, | ||
348 | .mwdma_mask = 0x07, | ||
349 | .udma_mask = 0x07, | ||
350 | .port_ops = &cs5530_port_ops | ||
351 | }; | ||
352 | /* The docking connector doesn't do UDMA, and it seems not MWDMA */ | ||
353 | static struct ata_port_info info_palmax_secondary = { | ||
354 | .sht = &cs5530_sht, | ||
355 | .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, | ||
356 | .pio_mask = 0x1f, | ||
357 | .port_ops = &cs5530_port_ops | ||
358 | }; | ||
359 | static struct ata_port_info *port_info[2] = { &info, &info }; | ||
360 | |||
361 | /* Chip initialisation */ | ||
362 | if (cs5530_init_chip()) | ||
363 | return -ENODEV; | ||
364 | |||
365 | if (cs5530_is_palmax()) | ||
366 | port_info[1] = &info_palmax_secondary; | ||
367 | |||
368 | /* Now kick off ATA set up */ | ||
369 | return ata_pci_init_one(pdev, port_info, 2); | ||
370 | } | ||
371 | |||
372 | static int cs5530_reinit_one(struct pci_dev *pdev) | ||
373 | { | ||
374 | /* If we fail on resume we are doomed */ | ||
375 | BUG_ON(cs5530_init_chip()); | ||
376 | return ata_pci_device_resume(pdev); | ||
377 | } | ||
378 | |||
357 | static const struct pci_device_id cs5530[] = { | 379 | static const struct pci_device_id cs5530[] = { |
358 | { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, | 380 | { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, |
359 | 381 | ||
@@ -364,7 +386,9 @@ static struct pci_driver cs5530_pci_driver = { | |||
364 | .name = DRV_NAME, | 386 | .name = DRV_NAME, |
365 | .id_table = cs5530, | 387 | .id_table = cs5530, |
366 | .probe = cs5530_init_one, | 388 | .probe = cs5530_init_one, |
367 | .remove = ata_pci_remove_one | 389 | .remove = ata_pci_remove_one, |
390 | .suspend = ata_pci_device_suspend, | ||
391 | .resume = cs5530_reinit_one, | ||
368 | }; | 392 | }; |
369 | 393 | ||
370 | static int __init cs5530_init(void) | 394 | static int __init cs5530_init(void) |
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 8dafa4a49fdc..e3efec4ffc79 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <asm/msr.h> | 39 | #include <asm/msr.h> |
40 | 40 | ||
41 | #define DRV_NAME "cs5535" | 41 | #define DRV_NAME "cs5535" |
42 | #define DRV_VERSION "0.2.10" | 42 | #define DRV_VERSION "0.2.11" |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * The Geode (Aka Athlon GX now) uses an internal MSR based | 45 | * The Geode (Aka Athlon GX now) uses an internal MSR based |
@@ -177,7 +177,6 @@ static struct scsi_host_template cs5535_sht = { | |||
177 | .can_queue = ATA_DEF_QUEUE, | 177 | .can_queue = ATA_DEF_QUEUE, |
178 | .this_id = ATA_SHT_THIS_ID, | 178 | .this_id = ATA_SHT_THIS_ID, |
179 | .sg_tablesize = LIBATA_MAX_PRD, | 179 | .sg_tablesize = LIBATA_MAX_PRD, |
180 | .max_sectors = ATA_MAX_SECTORS, | ||
181 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 180 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
182 | .emulated = ATA_SHT_EMULATED, | 181 | .emulated = ATA_SHT_EMULATED, |
183 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 182 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -186,6 +185,8 @@ static struct scsi_host_template cs5535_sht = { | |||
186 | .slave_configure = ata_scsi_slave_config, | 185 | .slave_configure = ata_scsi_slave_config, |
187 | .slave_destroy = ata_scsi_slave_destroy, | 186 | .slave_destroy = ata_scsi_slave_destroy, |
188 | .bios_param = ata_std_bios_param, | 187 | .bios_param = ata_std_bios_param, |
188 | .resume = ata_scsi_device_resume, | ||
189 | .suspend = ata_scsi_device_suspend, | ||
189 | }; | 190 | }; |
190 | 191 | ||
191 | static struct ata_port_operations cs5535_port_ops = { | 192 | static struct ata_port_operations cs5535_port_ops = { |
@@ -268,7 +269,9 @@ static struct pci_driver cs5535_pci_driver = { | |||
268 | .name = DRV_NAME, | 269 | .name = DRV_NAME, |
269 | .id_table = cs5535, | 270 | .id_table = cs5535, |
270 | .probe = cs5535_init_one, | 271 | .probe = cs5535_init_one, |
271 | .remove = ata_pci_remove_one | 272 | .remove = ata_pci_remove_one, |
273 | .suspend = ata_pci_device_suspend, | ||
274 | .resume = ata_pci_device_resume, | ||
272 | }; | 275 | }; |
273 | 276 | ||
274 | static int __init cs5535_init(void) | 277 | static int __init cs5535_init(void) |
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index 5a0b811907ee..e2a95699bae7 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/libata.h> | 18 | #include <linux/libata.h> |
19 | 19 | ||
20 | #define DRV_NAME "pata_cypress" | 20 | #define DRV_NAME "pata_cypress" |
21 | #define DRV_VERSION "0.1.2" | 21 | #define DRV_VERSION "0.1.4" |
22 | 22 | ||
23 | /* here are the offset definitions for the registers */ | 23 | /* here are the offset definitions for the registers */ |
24 | 24 | ||
@@ -128,7 +128,6 @@ static struct scsi_host_template cy82c693_sht = { | |||
128 | .can_queue = ATA_DEF_QUEUE, | 128 | .can_queue = ATA_DEF_QUEUE, |
129 | .this_id = ATA_SHT_THIS_ID, | 129 | .this_id = ATA_SHT_THIS_ID, |
130 | .sg_tablesize = LIBATA_MAX_PRD, | 130 | .sg_tablesize = LIBATA_MAX_PRD, |
131 | .max_sectors = ATA_MAX_SECTORS, | ||
132 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 131 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
133 | .emulated = ATA_SHT_EMULATED, | 132 | .emulated = ATA_SHT_EMULATED, |
134 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 133 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -137,6 +136,8 @@ static struct scsi_host_template cy82c693_sht = { | |||
137 | .slave_configure = ata_scsi_slave_config, | 136 | .slave_configure = ata_scsi_slave_config, |
138 | .slave_destroy = ata_scsi_slave_destroy, | 137 | .slave_destroy = ata_scsi_slave_destroy, |
139 | .bios_param = ata_std_bios_param, | 138 | .bios_param = ata_std_bios_param, |
139 | .resume = ata_scsi_device_resume, | ||
140 | .suspend = ata_scsi_device_suspend, | ||
140 | }; | 141 | }; |
141 | 142 | ||
142 | static struct ata_port_operations cy82c693_port_ops = { | 143 | static struct ata_port_operations cy82c693_port_ops = { |
@@ -204,7 +205,9 @@ static struct pci_driver cy82c693_pci_driver = { | |||
204 | .name = DRV_NAME, | 205 | .name = DRV_NAME, |
205 | .id_table = cy82c693, | 206 | .id_table = cy82c693, |
206 | .probe = cy82c693_init_one, | 207 | .probe = cy82c693_init_one, |
207 | .remove = ata_pci_remove_one | 208 | .remove = ata_pci_remove_one, |
209 | .suspend = ata_pci_device_suspend, | ||
210 | .resume = ata_pci_device_resume, | ||
208 | }; | 211 | }; |
209 | 212 | ||
210 | static int __init cy82c693_init(void) | 213 | static int __init cy82c693_init(void) |
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index 755f79279de3..edf8a63f50af 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/ata.h> | 22 | #include <linux/ata.h> |
23 | 23 | ||
24 | #define DRV_NAME "pata_efar" | 24 | #define DRV_NAME "pata_efar" |
25 | #define DRV_VERSION "0.4.2" | 25 | #define DRV_VERSION "0.4.3" |
26 | 26 | ||
27 | /** | 27 | /** |
28 | * efar_pre_reset - check for 40/80 pin | 28 | * efar_pre_reset - check for 40/80 pin |
@@ -226,7 +226,6 @@ static struct scsi_host_template efar_sht = { | |||
226 | .can_queue = ATA_DEF_QUEUE, | 226 | .can_queue = ATA_DEF_QUEUE, |
227 | .this_id = ATA_SHT_THIS_ID, | 227 | .this_id = ATA_SHT_THIS_ID, |
228 | .sg_tablesize = LIBATA_MAX_PRD, | 228 | .sg_tablesize = LIBATA_MAX_PRD, |
229 | .max_sectors = ATA_MAX_SECTORS, | ||
230 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 229 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
231 | .emulated = ATA_SHT_EMULATED, | 230 | .emulated = ATA_SHT_EMULATED, |
232 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 231 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -235,6 +234,8 @@ static struct scsi_host_template efar_sht = { | |||
235 | .slave_configure = ata_scsi_slave_config, | 234 | .slave_configure = ata_scsi_slave_config, |
236 | .slave_destroy = ata_scsi_slave_destroy, | 235 | .slave_destroy = ata_scsi_slave_destroy, |
237 | .bios_param = ata_std_bios_param, | 236 | .bios_param = ata_std_bios_param, |
237 | .resume = ata_scsi_device_resume, | ||
238 | .suspend = ata_scsi_device_suspend, | ||
238 | }; | 239 | }; |
239 | 240 | ||
240 | static const struct ata_port_operations efar_ops = { | 241 | static const struct ata_port_operations efar_ops = { |
@@ -316,6 +317,8 @@ static struct pci_driver efar_pci_driver = { | |||
316 | .id_table = efar_pci_tbl, | 317 | .id_table = efar_pci_tbl, |
317 | .probe = efar_init_one, | 318 | .probe = efar_init_one, |
318 | .remove = ata_pci_remove_one, | 319 | .remove = ata_pci_remove_one, |
320 | .suspend = ata_pci_device_suspend, | ||
321 | .resume = ata_pci_device_resume, | ||
319 | }; | 322 | }; |
320 | 323 | ||
321 | static int __init efar_init(void) | 324 | static int __init efar_init(void) |
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index c0e150a9586b..2663599a7c02 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/libata.h> | 27 | #include <linux/libata.h> |
28 | 28 | ||
29 | #define DRV_NAME "pata_hpt366" | 29 | #define DRV_NAME "pata_hpt366" |
30 | #define DRV_VERSION "0.5" | 30 | #define DRV_VERSION "0.5.3" |
31 | 31 | ||
32 | struct hpt_clock { | 32 | struct hpt_clock { |
33 | u8 xfer_speed; | 33 | u8 xfer_speed; |
@@ -222,9 +222,17 @@ static u32 hpt36x_find_mode(struct ata_port *ap, int speed) | |||
222 | 222 | ||
223 | static int hpt36x_pre_reset(struct ata_port *ap) | 223 | static int hpt36x_pre_reset(struct ata_port *ap) |
224 | { | 224 | { |
225 | static const struct pci_bits hpt36x_enable_bits[] = { | ||
226 | { 0x50, 1, 0x04, 0x04 }, | ||
227 | { 0x54, 1, 0x04, 0x04 } | ||
228 | }; | ||
229 | |||
225 | u8 ata66; | 230 | u8 ata66; |
226 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 231 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
227 | 232 | ||
233 | if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no])) | ||
234 | return -ENOENT; | ||
235 | |||
228 | pci_read_config_byte(pdev, 0x5A, &ata66); | 236 | pci_read_config_byte(pdev, 0x5A, &ata66); |
229 | if (ata66 & (1 << ap->port_no)) | 237 | if (ata66 & (1 << ap->port_no)) |
230 | ap->cbl = ATA_CBL_PATA40; | 238 | ap->cbl = ATA_CBL_PATA40; |
@@ -322,7 +330,6 @@ static struct scsi_host_template hpt36x_sht = { | |||
322 | .can_queue = ATA_DEF_QUEUE, | 330 | .can_queue = ATA_DEF_QUEUE, |
323 | .this_id = ATA_SHT_THIS_ID, | 331 | .this_id = ATA_SHT_THIS_ID, |
324 | .sg_tablesize = LIBATA_MAX_PRD, | 332 | .sg_tablesize = LIBATA_MAX_PRD, |
325 | .max_sectors = ATA_MAX_SECTORS, | ||
326 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 333 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
327 | .emulated = ATA_SHT_EMULATED, | 334 | .emulated = ATA_SHT_EMULATED, |
328 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 335 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -331,6 +338,8 @@ static struct scsi_host_template hpt36x_sht = { | |||
331 | .slave_configure = ata_scsi_slave_config, | 338 | .slave_configure = ata_scsi_slave_config, |
332 | .slave_destroy = ata_scsi_slave_destroy, | 339 | .slave_destroy = ata_scsi_slave_destroy, |
333 | .bios_param = ata_std_bios_param, | 340 | .bios_param = ata_std_bios_param, |
341 | .resume = ata_scsi_device_resume, | ||
342 | .suspend = ata_scsi_device_suspend, | ||
334 | }; | 343 | }; |
335 | 344 | ||
336 | /* | 345 | /* |
@@ -373,6 +382,27 @@ static struct ata_port_operations hpt366_port_ops = { | |||
373 | }; | 382 | }; |
374 | 383 | ||
375 | /** | 384 | /** |
385 | * hpt36x_init_chipset - common chip setup | ||
386 | * @dev: PCI device | ||
387 | * | ||
388 | * Perform the chip setup work that must be done at both init and | ||
389 | * resume time | ||
390 | */ | ||
391 | |||
392 | static void hpt36x_init_chipset(struct pci_dev *dev) | ||
393 | { | ||
394 | u8 drive_fast; | ||
395 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); | ||
396 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); | ||
397 | pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); | ||
398 | pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); | ||
399 | |||
400 | pci_read_config_byte(dev, 0x51, &drive_fast); | ||
401 | if (drive_fast & 0x80) | ||
402 | pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); | ||
403 | } | ||
404 | |||
405 | /** | ||
376 | * hpt36x_init_one - Initialise an HPT366/368 | 406 | * hpt36x_init_one - Initialise an HPT366/368 |
377 | * @dev: PCI device | 407 | * @dev: PCI device |
378 | * @id: Entry in match table | 408 | * @id: Entry in match table |
@@ -407,7 +437,6 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
407 | 437 | ||
408 | u32 class_rev; | 438 | u32 class_rev; |
409 | u32 reg1; | 439 | u32 reg1; |
410 | u8 drive_fast; | ||
411 | 440 | ||
412 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); | 441 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); |
413 | class_rev &= 0xFF; | 442 | class_rev &= 0xFF; |
@@ -417,14 +446,7 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
417 | if (class_rev > 2) | 446 | if (class_rev > 2) |
418 | return -ENODEV; | 447 | return -ENODEV; |
419 | 448 | ||
420 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); | 449 | hpt36x_init_chipset(dev); |
421 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); | ||
422 | pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); | ||
423 | pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); | ||
424 | |||
425 | pci_read_config_byte(dev, 0x51, &drive_fast); | ||
426 | if (drive_fast & 0x80) | ||
427 | pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); | ||
428 | 450 | ||
429 | pci_read_config_dword(dev, 0x40, ®1); | 451 | pci_read_config_dword(dev, 0x40, ®1); |
430 | 452 | ||
@@ -445,9 +467,15 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
445 | return ata_pci_init_one(dev, port_info, 2); | 467 | return ata_pci_init_one(dev, port_info, 2); |
446 | } | 468 | } |
447 | 469 | ||
470 | static int hpt36x_reinit_one(struct pci_dev *dev) | ||
471 | { | ||
472 | hpt36x_init_chipset(dev); | ||
473 | return ata_pci_device_resume(dev); | ||
474 | } | ||
475 | |||
476 | |||
448 | static const struct pci_device_id hpt36x[] = { | 477 | static const struct pci_device_id hpt36x[] = { |
449 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, | 478 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, |
450 | |||
451 | { }, | 479 | { }, |
452 | }; | 480 | }; |
453 | 481 | ||
@@ -455,7 +483,9 @@ static struct pci_driver hpt36x_pci_driver = { | |||
455 | .name = DRV_NAME, | 483 | .name = DRV_NAME, |
456 | .id_table = hpt36x, | 484 | .id_table = hpt36x, |
457 | .probe = hpt36x_init_one, | 485 | .probe = hpt36x_init_one, |
458 | .remove = ata_pci_remove_one | 486 | .remove = ata_pci_remove_one, |
487 | .suspend = ata_pci_device_suspend, | ||
488 | .resume = hpt36x_reinit_one, | ||
459 | }; | 489 | }; |
460 | 490 | ||
461 | static int __init hpt36x_init(void) | 491 | static int __init hpt36x_init(void) |
@@ -463,13 +493,11 @@ static int __init hpt36x_init(void) | |||
463 | return pci_register_driver(&hpt36x_pci_driver); | 493 | return pci_register_driver(&hpt36x_pci_driver); |
464 | } | 494 | } |
465 | 495 | ||
466 | |||
467 | static void __exit hpt36x_exit(void) | 496 | static void __exit hpt36x_exit(void) |
468 | { | 497 | { |
469 | pci_unregister_driver(&hpt36x_pci_driver); | 498 | pci_unregister_driver(&hpt36x_pci_driver); |
470 | } | 499 | } |
471 | 500 | ||
472 | |||
473 | MODULE_AUTHOR("Alan Cox"); | 501 | MODULE_AUTHOR("Alan Cox"); |
474 | MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368"); | 502 | MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368"); |
475 | MODULE_LICENSE("GPL"); | 503 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 1eeb16f0fb02..47082df7199e 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c | |||
@@ -768,7 +768,6 @@ static struct scsi_host_template hpt37x_sht = { | |||
768 | .can_queue = ATA_DEF_QUEUE, | 768 | .can_queue = ATA_DEF_QUEUE, |
769 | .this_id = ATA_SHT_THIS_ID, | 769 | .this_id = ATA_SHT_THIS_ID, |
770 | .sg_tablesize = LIBATA_MAX_PRD, | 770 | .sg_tablesize = LIBATA_MAX_PRD, |
771 | .max_sectors = ATA_MAX_SECTORS, | ||
772 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 771 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
773 | .emulated = ATA_SHT_EMULATED, | 772 | .emulated = ATA_SHT_EMULATED, |
774 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 773 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 47d7664e9eee..f6817b4093a4 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c | |||
@@ -334,7 +334,6 @@ static struct scsi_host_template hpt3x2n_sht = { | |||
334 | .can_queue = ATA_DEF_QUEUE, | 334 | .can_queue = ATA_DEF_QUEUE, |
335 | .this_id = ATA_SHT_THIS_ID, | 335 | .this_id = ATA_SHT_THIS_ID, |
336 | .sg_tablesize = LIBATA_MAX_PRD, | 336 | .sg_tablesize = LIBATA_MAX_PRD, |
337 | .max_sectors = ATA_MAX_SECTORS, | ||
338 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 337 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
339 | .emulated = ATA_SHT_EMULATED, | 338 | .emulated = ATA_SHT_EMULATED, |
340 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 339 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index d216cc564b56..5f1d385eb592 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/libata.h> | 23 | #include <linux/libata.h> |
24 | 24 | ||
25 | #define DRV_NAME "pata_hpt3x3" | 25 | #define DRV_NAME "pata_hpt3x3" |
26 | #define DRV_VERSION "0.4.1" | 26 | #define DRV_VERSION "0.4.2" |
27 | 27 | ||
28 | static int hpt3x3_probe_init(struct ata_port *ap) | 28 | static int hpt3x3_probe_init(struct ata_port *ap) |
29 | { | 29 | { |
@@ -111,7 +111,6 @@ static struct scsi_host_template hpt3x3_sht = { | |||
111 | .can_queue = ATA_DEF_QUEUE, | 111 | .can_queue = ATA_DEF_QUEUE, |
112 | .this_id = ATA_SHT_THIS_ID, | 112 | .this_id = ATA_SHT_THIS_ID, |
113 | .sg_tablesize = LIBATA_MAX_PRD, | 113 | .sg_tablesize = LIBATA_MAX_PRD, |
114 | .max_sectors = ATA_MAX_SECTORS, | ||
115 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 114 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
116 | .emulated = ATA_SHT_EMULATED, | 115 | .emulated = ATA_SHT_EMULATED, |
117 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 116 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -120,6 +119,8 @@ static struct scsi_host_template hpt3x3_sht = { | |||
120 | .slave_configure = ata_scsi_slave_config, | 119 | .slave_configure = ata_scsi_slave_config, |
121 | .slave_destroy = ata_scsi_slave_destroy, | 120 | .slave_destroy = ata_scsi_slave_destroy, |
122 | .bios_param = ata_std_bios_param, | 121 | .bios_param = ata_std_bios_param, |
122 | .resume = ata_scsi_device_resume, | ||
123 | .suspend = ata_scsi_device_suspend, | ||
123 | }; | 124 | }; |
124 | 125 | ||
125 | static struct ata_port_operations hpt3x3_port_ops = { | 126 | static struct ata_port_operations hpt3x3_port_ops = { |
@@ -158,6 +159,27 @@ static struct ata_port_operations hpt3x3_port_ops = { | |||
158 | }; | 159 | }; |
159 | 160 | ||
160 | /** | 161 | /** |
162 | * hpt3x3_init_chipset - chip setup | ||
163 | * @dev: PCI device | ||
164 | * | ||
165 | * Perform the setup required at boot and on resume. | ||
166 | */ | ||
167 | |||
168 | static void hpt3x3_init_chipset(struct pci_dev *dev) | ||
169 | { | ||
170 | u16 cmd; | ||
171 | /* Initialize the board */ | ||
172 | pci_write_config_word(dev, 0x80, 0x00); | ||
173 | /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */ | ||
174 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
175 | if (cmd & PCI_COMMAND_MEMORY) | ||
176 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); | ||
177 | else | ||
178 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); | ||
179 | } | ||
180 | |||
181 | |||
182 | /** | ||
161 | * hpt3x3_init_one - Initialise an HPT343/363 | 183 | * hpt3x3_init_one - Initialise an HPT343/363 |
162 | * @dev: PCI device | 184 | * @dev: PCI device |
163 | * @id: Entry in match table | 185 | * @id: Entry in match table |
@@ -178,21 +200,18 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
178 | .port_ops = &hpt3x3_port_ops | 200 | .port_ops = &hpt3x3_port_ops |
179 | }; | 201 | }; |
180 | static struct ata_port_info *port_info[2] = { &info, &info }; | 202 | static struct ata_port_info *port_info[2] = { &info, &info }; |
181 | u16 cmd; | ||
182 | |||
183 | /* Initialize the board */ | ||
184 | pci_write_config_word(dev, 0x80, 0x00); | ||
185 | /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */ | ||
186 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
187 | if (cmd & PCI_COMMAND_MEMORY) | ||
188 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); | ||
189 | else | ||
190 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); | ||
191 | 203 | ||
204 | hpt3x3_init_chipset(dev); | ||
192 | /* Now kick off ATA set up */ | 205 | /* Now kick off ATA set up */ |
193 | return ata_pci_init_one(dev, port_info, 2); | 206 | return ata_pci_init_one(dev, port_info, 2); |
194 | } | 207 | } |
195 | 208 | ||
209 | static int hpt3x3_reinit_one(struct pci_dev *dev) | ||
210 | { | ||
211 | hpt3x3_init_chipset(dev); | ||
212 | return ata_pci_device_resume(dev); | ||
213 | } | ||
214 | |||
196 | static const struct pci_device_id hpt3x3[] = { | 215 | static const struct pci_device_id hpt3x3[] = { |
197 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), }, | 216 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), }, |
198 | 217 | ||
@@ -203,7 +222,9 @@ static struct pci_driver hpt3x3_pci_driver = { | |||
203 | .name = DRV_NAME, | 222 | .name = DRV_NAME, |
204 | .id_table = hpt3x3, | 223 | .id_table = hpt3x3, |
205 | .probe = hpt3x3_init_one, | 224 | .probe = hpt3x3_init_one, |
206 | .remove = ata_pci_remove_one | 225 | .remove = ata_pci_remove_one, |
226 | .suspend = ata_pci_device_suspend, | ||
227 | .resume = hpt3x3_reinit_one, | ||
207 | }; | 228 | }; |
208 | 229 | ||
209 | static int __init hpt3x3_init(void) | 230 | static int __init hpt3x3_init(void) |
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 40ca2b82b7fc..a97d55ae95c9 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c | |||
@@ -27,7 +27,6 @@ static struct scsi_host_template isapnp_sht = { | |||
27 | .can_queue = ATA_DEF_QUEUE, | 27 | .can_queue = ATA_DEF_QUEUE, |
28 | .this_id = ATA_SHT_THIS_ID, | 28 | .this_id = ATA_SHT_THIS_ID, |
29 | .sg_tablesize = LIBATA_MAX_PRD, | 29 | .sg_tablesize = LIBATA_MAX_PRD, |
30 | .max_sectors = ATA_MAX_SECTORS, | ||
31 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 30 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
32 | .emulated = ATA_SHT_EMULATED, | 31 | .emulated = ATA_SHT_EMULATED, |
33 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 32 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 7f68f14be6fd..0b56ff3d1cfe 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c | |||
@@ -80,7 +80,7 @@ | |||
80 | 80 | ||
81 | 81 | ||
82 | #define DRV_NAME "pata_it821x" | 82 | #define DRV_NAME "pata_it821x" |
83 | #define DRV_VERSION "0.3.2" | 83 | #define DRV_VERSION "0.3.3" |
84 | 84 | ||
85 | struct it821x_dev | 85 | struct it821x_dev |
86 | { | 86 | { |
@@ -666,9 +666,6 @@ static struct scsi_host_template it821x_sht = { | |||
666 | .can_queue = ATA_DEF_QUEUE, | 666 | .can_queue = ATA_DEF_QUEUE, |
667 | .this_id = ATA_SHT_THIS_ID, | 667 | .this_id = ATA_SHT_THIS_ID, |
668 | .sg_tablesize = LIBATA_MAX_PRD, | 668 | .sg_tablesize = LIBATA_MAX_PRD, |
669 | /* 255 sectors to begin with. This is locked in smart mode but not | ||
670 | in pass through */ | ||
671 | .max_sectors = 255, | ||
672 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 669 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
673 | .emulated = ATA_SHT_EMULATED, | 670 | .emulated = ATA_SHT_EMULATED, |
674 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 671 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -677,6 +674,8 @@ static struct scsi_host_template it821x_sht = { | |||
677 | .slave_configure = ata_scsi_slave_config, | 674 | .slave_configure = ata_scsi_slave_config, |
678 | .slave_destroy = ata_scsi_slave_destroy, | 675 | .slave_destroy = ata_scsi_slave_destroy, |
679 | .bios_param = ata_std_bios_param, | 676 | .bios_param = ata_std_bios_param, |
677 | .resume = ata_scsi_device_resume, | ||
678 | .suspend = ata_scsi_device_suspend, | ||
680 | }; | 679 | }; |
681 | 680 | ||
682 | static struct ata_port_operations it821x_smart_port_ops = { | 681 | static struct ata_port_operations it821x_smart_port_ops = { |
@@ -809,6 +808,14 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
809 | return ata_pci_init_one(pdev, port_info, 2); | 808 | return ata_pci_init_one(pdev, port_info, 2); |
810 | } | 809 | } |
811 | 810 | ||
811 | static int it821x_reinit_one(struct pci_dev *pdev) | ||
812 | { | ||
813 | /* Resume - turn raid back off if need be */ | ||
814 | if (it8212_noraid) | ||
815 | it821x_disable_raid(pdev); | ||
816 | return ata_pci_device_resume(pdev); | ||
817 | } | ||
818 | |||
812 | static const struct pci_device_id it821x[] = { | 819 | static const struct pci_device_id it821x[] = { |
813 | { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), }, | 820 | { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), }, |
814 | { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), }, | 821 | { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), }, |
@@ -820,7 +827,9 @@ static struct pci_driver it821x_pci_driver = { | |||
820 | .name = DRV_NAME, | 827 | .name = DRV_NAME, |
821 | .id_table = it821x, | 828 | .id_table = it821x, |
822 | .probe = it821x_init_one, | 829 | .probe = it821x_init_one, |
823 | .remove = ata_pci_remove_one | 830 | .remove = ata_pci_remove_one, |
831 | .suspend = ata_pci_device_suspend, | ||
832 | .resume = it821x_reinit_one, | ||
824 | }; | 833 | }; |
825 | 834 | ||
826 | static int __init it821x_init(void) | 835 | static int __init it821x_init(void) |
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c new file mode 100644 index 000000000000..cb8924109f59 --- /dev/null +++ b/drivers/ata/pata_ixp4xx_cf.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * ixp4xx PATA/Compact Flash driver | ||
3 | * Copyright (c) 2006 Tower Technologies | ||
4 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
5 | * | ||
6 | * An ATA driver to handle a Compact Flash connected | ||
7 | * to the ixp4xx expansion bus in TrueIDE mode. The CF | ||
8 | * must have it chip selects connected to two CS lines | ||
9 | * on the ixp4xx. The interrupt line is optional, if not | ||
10 | * specified the driver will run in polling mode. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/libata.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <scsi/scsi_host.h> | ||
24 | |||
25 | #define DRV_NAME "pata_ixp4xx_cf" | ||
26 | #define DRV_VERSION "0.1.1" | ||
27 | |||
28 | static void ixp4xx_set_mode(struct ata_port *ap) | ||
29 | { | ||
30 | int i; | ||
31 | |||
32 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | ||
33 | struct ata_device *dev = &ap->device[i]; | ||
34 | if (ata_dev_enabled(dev)) { | ||
35 | dev->pio_mode = XFER_PIO_0; | ||
36 | dev->xfer_mode = XFER_PIO_0; | ||
37 | dev->xfer_shift = ATA_SHIFT_PIO; | ||
38 | dev->flags |= ATA_DFLAG_PIO; | ||
39 | } | ||
40 | } | ||
41 | } | ||
42 | |||
43 | static void ixp4xx_phy_reset(struct ata_port *ap) | ||
44 | { | ||
45 | ap->cbl = ATA_CBL_PATA40; | ||
46 | ata_port_probe(ap); | ||
47 | ata_bus_reset(ap); | ||
48 | } | ||
49 | |||
50 | static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, | ||
51 | unsigned int buflen, int write_data) | ||
52 | { | ||
53 | unsigned int i; | ||
54 | unsigned int words = buflen >> 1; | ||
55 | u16 *buf16 = (u16 *) buf; | ||
56 | struct ata_port *ap = adev->ap; | ||
57 | void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; | ||
58 | struct ixp4xx_pata_data *data = ap->host->dev->platform_data; | ||
59 | |||
60 | /* set the expansion bus in 16bit mode and restore | ||
61 | * 8 bit mode after the transaction. | ||
62 | */ | ||
63 | *data->cs0_cfg &= ~(0x01); | ||
64 | udelay(100); | ||
65 | |||
66 | /* Transfer multiple of 2 bytes */ | ||
67 | if (write_data) { | ||
68 | for (i = 0; i < words; i++) | ||
69 | writew(buf16[i], mmio); | ||
70 | } else { | ||
71 | for (i = 0; i < words; i++) | ||
72 | buf16[i] = readw(mmio); | ||
73 | } | ||
74 | |||
75 | /* Transfer trailing 1 byte, if any. */ | ||
76 | if (unlikely(buflen & 0x01)) { | ||
77 | u16 align_buf[1] = { 0 }; | ||
78 | unsigned char *trailing_buf = buf + buflen - 1; | ||
79 | |||
80 | if (write_data) { | ||
81 | memcpy(align_buf, trailing_buf, 1); | ||
82 | writew(align_buf[0], mmio); | ||
83 | } else { | ||
84 | align_buf[0] = readw(mmio); | ||
85 | memcpy(trailing_buf, align_buf, 1); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | udelay(100); | ||
90 | *data->cs0_cfg |= 0x01; | ||
91 | } | ||
92 | |||
93 | static void ixp4xx_irq_clear(struct ata_port *ap) | ||
94 | { | ||
95 | } | ||
96 | |||
97 | static void ixp4xx_host_stop (struct ata_host *host) | ||
98 | { | ||
99 | struct ixp4xx_pata_data *data = host->dev->platform_data; | ||
100 | |||
101 | iounmap(data->cs0); | ||
102 | iounmap(data->cs1); | ||
103 | } | ||
104 | |||
105 | static struct scsi_host_template ixp4xx_sht = { | ||
106 | .module = THIS_MODULE, | ||
107 | .name = DRV_NAME, | ||
108 | .ioctl = ata_scsi_ioctl, | ||
109 | .queuecommand = ata_scsi_queuecmd, | ||
110 | .can_queue = ATA_DEF_QUEUE, | ||
111 | .this_id = ATA_SHT_THIS_ID, | ||
112 | .sg_tablesize = LIBATA_MAX_PRD, | ||
113 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
114 | .emulated = ATA_SHT_EMULATED, | ||
115 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
116 | .proc_name = DRV_NAME, | ||
117 | .dma_boundary = ATA_DMA_BOUNDARY, | ||
118 | .slave_configure = ata_scsi_slave_config, | ||
119 | .slave_destroy = ata_scsi_slave_destroy, | ||
120 | .bios_param = ata_std_bios_param, | ||
121 | }; | ||
122 | |||
123 | static struct ata_port_operations ixp4xx_port_ops = { | ||
124 | .set_mode = ixp4xx_set_mode, | ||
125 | .mode_filter = ata_pci_default_filter, | ||
126 | |||
127 | .port_disable = ata_port_disable, | ||
128 | .tf_load = ata_tf_load, | ||
129 | .tf_read = ata_tf_read, | ||
130 | .check_status = ata_check_status, | ||
131 | .exec_command = ata_exec_command, | ||
132 | .dev_select = ata_std_dev_select, | ||
133 | |||
134 | .qc_prep = ata_qc_prep, | ||
135 | .qc_issue = ata_qc_issue_prot, | ||
136 | .eng_timeout = ata_eng_timeout, | ||
137 | .data_xfer = ixp4xx_mmio_data_xfer, | ||
138 | |||
139 | .irq_handler = ata_interrupt, | ||
140 | .irq_clear = ixp4xx_irq_clear, | ||
141 | |||
142 | .port_start = ata_port_start, | ||
143 | .port_stop = ata_port_stop, | ||
144 | .host_stop = ixp4xx_host_stop, | ||
145 | |||
146 | .phy_reset = ixp4xx_phy_reset, | ||
147 | }; | ||
148 | |||
149 | static void ixp4xx_setup_port(struct ata_ioports *ioaddr, | ||
150 | struct ixp4xx_pata_data *data) | ||
151 | { | ||
152 | ioaddr->cmd_addr = (unsigned long) data->cs0; | ||
153 | ioaddr->altstatus_addr = (unsigned long) data->cs1 + 0x06; | ||
154 | ioaddr->ctl_addr = (unsigned long) data->cs1 + 0x06; | ||
155 | |||
156 | ata_std_ports(ioaddr); | ||
157 | |||
158 | #ifndef __ARMEB__ | ||
159 | |||
160 | /* adjust the addresses to handle the address swizzling of the | ||
161 | * ixp4xx in little endian mode. | ||
162 | */ | ||
163 | |||
164 | ioaddr->data_addr ^= 0x02; | ||
165 | ioaddr->cmd_addr ^= 0x03; | ||
166 | ioaddr->altstatus_addr ^= 0x03; | ||
167 | ioaddr->ctl_addr ^= 0x03; | ||
168 | ioaddr->error_addr ^= 0x03; | ||
169 | ioaddr->feature_addr ^= 0x03; | ||
170 | ioaddr->nsect_addr ^= 0x03; | ||
171 | ioaddr->lbal_addr ^= 0x03; | ||
172 | ioaddr->lbam_addr ^= 0x03; | ||
173 | ioaddr->lbah_addr ^= 0x03; | ||
174 | ioaddr->device_addr ^= 0x03; | ||
175 | ioaddr->status_addr ^= 0x03; | ||
176 | ioaddr->command_addr ^= 0x03; | ||
177 | #endif | ||
178 | } | ||
179 | |||
180 | static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) | ||
181 | { | ||
182 | int ret; | ||
183 | unsigned int irq; | ||
184 | struct resource *cs0, *cs1; | ||
185 | struct ata_probe_ent ae; | ||
186 | |||
187 | struct ixp4xx_pata_data *data = pdev->dev.platform_data; | ||
188 | |||
189 | cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
190 | cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
191 | |||
192 | if (!cs0 || !cs1) | ||
193 | return -EINVAL; | ||
194 | |||
195 | pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; | ||
196 | |||
197 | data->cs0 = ioremap(cs0->start, 0x1000); | ||
198 | data->cs1 = ioremap(cs1->start, 0x1000); | ||
199 | |||
200 | irq = platform_get_irq(pdev, 0); | ||
201 | if (irq) | ||
202 | set_irq_type(irq, IRQT_HIGH); | ||
203 | |||
204 | /* Setup expansion bus chip selects */ | ||
205 | *data->cs0_cfg = data->cs0_bits; | ||
206 | *data->cs1_cfg = data->cs1_bits; | ||
207 | |||
208 | memset(&ae, 0, sizeof(struct ata_probe_ent)); | ||
209 | INIT_LIST_HEAD(&ae.node); | ||
210 | |||
211 | ae.dev = &pdev->dev; | ||
212 | ae.port_ops = &ixp4xx_port_ops; | ||
213 | ae.sht = &ixp4xx_sht; | ||
214 | ae.n_ports = 1; | ||
215 | ae.pio_mask = 0x1f; /* PIO4 */ | ||
216 | ae.irq = irq; | ||
217 | ae.irq_flags = 0; | ||
218 | ae.port_flags = ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ||
219 | | ATA_FLAG_NO_ATAPI | ATA_FLAG_SRST; | ||
220 | |||
221 | /* run in polling mode if no irq has been assigned */ | ||
222 | if (!irq) | ||
223 | ae.port_flags |= ATA_FLAG_PIO_POLLING; | ||
224 | |||
225 | ixp4xx_setup_port(&ae.port[0], data); | ||
226 | |||
227 | dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); | ||
228 | |||
229 | ret = ata_device_add(&ae); | ||
230 | if (ret == 0) | ||
231 | return -ENODEV; | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static __devexit int ixp4xx_pata_remove(struct platform_device *dev) | ||
237 | { | ||
238 | struct ata_host *host = platform_get_drvdata(dev); | ||
239 | |||
240 | ata_host_remove(host); | ||
241 | platform_set_drvdata(dev, NULL); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static struct platform_driver ixp4xx_pata_platform_driver = { | ||
247 | .driver = { | ||
248 | .name = DRV_NAME, | ||
249 | .owner = THIS_MODULE, | ||
250 | }, | ||
251 | .probe = ixp4xx_pata_probe, | ||
252 | .remove = __devexit_p(ixp4xx_pata_remove), | ||
253 | }; | ||
254 | |||
255 | static int __init ixp4xx_pata_init(void) | ||
256 | { | ||
257 | return platform_driver_register(&ixp4xx_pata_platform_driver); | ||
258 | } | ||
259 | |||
260 | static void __exit ixp4xx_pata_exit(void) | ||
261 | { | ||
262 | platform_driver_unregister(&ixp4xx_pata_platform_driver); | ||
263 | } | ||
264 | |||
265 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
266 | MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA"); | ||
267 | MODULE_LICENSE("GPL"); | ||
268 | MODULE_VERSION(DRV_VERSION); | ||
269 | |||
270 | module_init(ixp4xx_pata_init); | ||
271 | module_exit(ixp4xx_pata_exit); | ||
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 0210b10d49cd..2d661cb4df3c 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/ata.h> | 19 | #include <linux/ata.h> |
20 | 20 | ||
21 | #define DRV_NAME "pata_jmicron" | 21 | #define DRV_NAME "pata_jmicron" |
22 | #define DRV_VERSION "0.1.2" | 22 | #define DRV_VERSION "0.1.4" |
23 | 23 | ||
24 | typedef enum { | 24 | typedef enum { |
25 | PORT_PATA0 = 0, | 25 | PORT_PATA0 = 0, |
@@ -128,8 +128,6 @@ static struct scsi_host_template jmicron_sht = { | |||
128 | .can_queue = ATA_DEF_QUEUE, | 128 | .can_queue = ATA_DEF_QUEUE, |
129 | .this_id = ATA_SHT_THIS_ID, | 129 | .this_id = ATA_SHT_THIS_ID, |
130 | .sg_tablesize = LIBATA_MAX_PRD, | 130 | .sg_tablesize = LIBATA_MAX_PRD, |
131 | /* Special handling needed if you have sector or LBA48 limits */ | ||
132 | .max_sectors = ATA_MAX_SECTORS, | ||
133 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 131 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
134 | .emulated = ATA_SHT_EMULATED, | 132 | .emulated = ATA_SHT_EMULATED, |
135 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 133 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -213,12 +211,11 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i | |||
213 | 211 | ||
214 | /* FIXME: We may want a way to override this in future */ | 212 | /* FIXME: We may want a way to override this in future */ |
215 | pci_write_config_byte(pdev, 0x41, 0xa1); | 213 | pci_write_config_byte(pdev, 0x41, 0xa1); |
216 | } | ||
217 | |||
218 | /* PATA controller is fn 1, AHCI is fn 0 */ | ||
219 | if (PCI_FUNC(pdev->devfn) != 1) | ||
220 | return -ENODEV; | ||
221 | 214 | ||
215 | /* PATA controller is fn 1, AHCI is fn 0 */ | ||
216 | if (PCI_FUNC(pdev->devfn) != 1) | ||
217 | return -ENODEV; | ||
218 | } | ||
222 | if ( id->driver_data == 365 || id->driver_data == 366) { | 219 | if ( id->driver_data == 365 || id->driver_data == 366) { |
223 | /* The 365/66 have two PATA channels, redirect the second */ | 220 | /* The 365/66 have two PATA channels, redirect the second */ |
224 | pci_read_config_dword(pdev, 0x80, ®); | 221 | pci_read_config_dword(pdev, 0x80, ®); |
@@ -229,6 +226,27 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i | |||
229 | return ata_pci_init_one(pdev, port_info, 2); | 226 | return ata_pci_init_one(pdev, port_info, 2); |
230 | } | 227 | } |
231 | 228 | ||
229 | static int jmicron_reinit_one(struct pci_dev *pdev) | ||
230 | { | ||
231 | u32 reg; | ||
232 | |||
233 | switch(pdev->device) { | ||
234 | case PCI_DEVICE_ID_JMICRON_JMB368: | ||
235 | break; | ||
236 | case PCI_DEVICE_ID_JMICRON_JMB365: | ||
237 | case PCI_DEVICE_ID_JMICRON_JMB366: | ||
238 | /* Restore mapping or disks swap and boy does it get ugly */ | ||
239 | pci_read_config_dword(pdev, 0x80, ®); | ||
240 | reg |= (1 << 24); /* IDE1 to PATA IDE secondary */ | ||
241 | pci_write_config_dword(pdev, 0x80, reg); | ||
242 | /* Fall through */ | ||
243 | default: | ||
244 | /* Make sure AHCI is turned back on */ | ||
245 | pci_write_config_byte(pdev, 0x41, 0xa1); | ||
246 | } | ||
247 | return ata_pci_device_resume(pdev); | ||
248 | } | ||
249 | |||
232 | static const struct pci_device_id jmicron_pci_tbl[] = { | 250 | static const struct pci_device_id jmicron_pci_tbl[] = { |
233 | { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361}, | 251 | { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361}, |
234 | { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363}, | 252 | { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363}, |
@@ -244,6 +262,8 @@ static struct pci_driver jmicron_pci_driver = { | |||
244 | .id_table = jmicron_pci_tbl, | 262 | .id_table = jmicron_pci_tbl, |
245 | .probe = jmicron_init_one, | 263 | .probe = jmicron_init_one, |
246 | .remove = ata_pci_remove_one, | 264 | .remove = ata_pci_remove_one, |
265 | .suspend = ata_pci_device_suspend, | ||
266 | .resume = jmicron_reinit_one, | ||
247 | }; | 267 | }; |
248 | 268 | ||
249 | static int __init jmicron_init(void) | 269 | static int __init jmicron_init(void) |
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index b39078b2a47b..c7d1738e4e69 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c | |||
@@ -128,7 +128,6 @@ static struct scsi_host_template legacy_sht = { | |||
128 | .can_queue = ATA_DEF_QUEUE, | 128 | .can_queue = ATA_DEF_QUEUE, |
129 | .this_id = ATA_SHT_THIS_ID, | 129 | .this_id = ATA_SHT_THIS_ID, |
130 | .sg_tablesize = LIBATA_MAX_PRD, | 130 | .sg_tablesize = LIBATA_MAX_PRD, |
131 | .max_sectors = ATA_MAX_SECTORS, | ||
132 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 131 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
133 | .emulated = ATA_SHT_EMULATED, | 132 | .emulated = ATA_SHT_EMULATED, |
134 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 133 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c new file mode 100644 index 000000000000..1c810ea00253 --- /dev/null +++ b/drivers/ata/pata_marvell.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Marvell PATA driver. | ||
3 | * | ||
4 | * For the moment we drive the PATA port in legacy mode. That | ||
5 | * isn't making full use of the device functionality but it is | ||
6 | * easy to get working. | ||
7 | * | ||
8 | * (c) 2006 Red Hat <alan@redhat.com> | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/blkdev.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <scsi/scsi_host.h> | ||
19 | #include <linux/libata.h> | ||
20 | #include <linux/ata.h> | ||
21 | |||
22 | #define DRV_NAME "pata_marvell" | ||
23 | #define DRV_VERSION "0.1.1" | ||
24 | |||
25 | /** | ||
26 | * marvell_pre_reset - check for 40/80 pin | ||
27 | * @ap: Port | ||
28 | * | ||
29 | * Perform the PATA port setup we need. | ||
30 | */ | ||
31 | |||
32 | static int marvell_pre_reset(struct ata_port *ap) | ||
33 | { | ||
34 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
35 | u32 devices; | ||
36 | void __iomem *barp; | ||
37 | int i; | ||
38 | |||
39 | /* Check if our port is enabled */ | ||
40 | |||
41 | barp = pci_iomap(pdev, 5, 0x10); | ||
42 | if (barp == NULL) | ||
43 | return -ENOMEM; | ||
44 | printk("BAR5:"); | ||
45 | for(i = 0; i <= 0x0F; i++) | ||
46 | printk("%02X:%02X ", i, readb(barp + i)); | ||
47 | printk("\n"); | ||
48 | |||
49 | devices = readl(barp + 0x0C); | ||
50 | pci_iounmap(pdev, barp); | ||
51 | |||
52 | if ((pdev->device == 0x6145) && (ap->port_no == 0) && | ||
53 | (!(devices & 0x10))) /* PATA enable ? */ | ||
54 | return -ENOENT; | ||
55 | |||
56 | /* Cable type */ | ||
57 | switch(ap->port_no) | ||
58 | { | ||
59 | case 0: | ||
60 | if (inb(ap->ioaddr.bmdma_addr + 1) & 1) | ||
61 | ap->cbl = ATA_CBL_PATA40; | ||
62 | else | ||
63 | ap->cbl = ATA_CBL_PATA80; | ||
64 | break; | ||
65 | |||
66 | case 1: /* Legacy SATA port */ | ||
67 | ap->cbl = ATA_CBL_SATA; | ||
68 | break; | ||
69 | } | ||
70 | return ata_std_prereset(ap); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * marvell_error_handler - Setup and error handler | ||
75 | * @ap: Port to handle | ||
76 | * | ||
77 | * LOCKING: | ||
78 | * None (inherited from caller). | ||
79 | */ | ||
80 | |||
81 | static void marvell_error_handler(struct ata_port *ap) | ||
82 | { | ||
83 | return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, | ||
84 | NULL, ata_std_postreset); | ||
85 | } | ||
86 | |||
87 | /* No PIO or DMA methods needed for this device */ | ||
88 | |||
89 | static struct scsi_host_template marvell_sht = { | ||
90 | .module = THIS_MODULE, | ||
91 | .name = DRV_NAME, | ||
92 | .ioctl = ata_scsi_ioctl, | ||
93 | .queuecommand = ata_scsi_queuecmd, | ||
94 | .can_queue = ATA_DEF_QUEUE, | ||
95 | .this_id = ATA_SHT_THIS_ID, | ||
96 | .sg_tablesize = LIBATA_MAX_PRD, | ||
97 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
98 | .emulated = ATA_SHT_EMULATED, | ||
99 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
100 | .proc_name = DRV_NAME, | ||
101 | .dma_boundary = ATA_DMA_BOUNDARY, | ||
102 | .slave_configure = ata_scsi_slave_config, | ||
103 | .slave_destroy = ata_scsi_slave_destroy, | ||
104 | /* Use standard CHS mapping rules */ | ||
105 | .bios_param = ata_std_bios_param, | ||
106 | .resume = ata_scsi_device_resume, | ||
107 | .suspend = ata_scsi_device_suspend, | ||
108 | }; | ||
109 | |||
110 | static const struct ata_port_operations marvell_ops = { | ||
111 | .port_disable = ata_port_disable, | ||
112 | |||
113 | /* Task file is PCI ATA format, use helpers */ | ||
114 | .tf_load = ata_tf_load, | ||
115 | .tf_read = ata_tf_read, | ||
116 | .check_status = ata_check_status, | ||
117 | .exec_command = ata_exec_command, | ||
118 | .dev_select = ata_std_dev_select, | ||
119 | |||
120 | .freeze = ata_bmdma_freeze, | ||
121 | .thaw = ata_bmdma_thaw, | ||
122 | .error_handler = marvell_error_handler, | ||
123 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
124 | |||
125 | /* BMDMA handling is PCI ATA format, use helpers */ | ||
126 | .bmdma_setup = ata_bmdma_setup, | ||
127 | .bmdma_start = ata_bmdma_start, | ||
128 | .bmdma_stop = ata_bmdma_stop, | ||
129 | .bmdma_status = ata_bmdma_status, | ||
130 | .qc_prep = ata_qc_prep, | ||
131 | .qc_issue = ata_qc_issue_prot, | ||
132 | .data_xfer = ata_pio_data_xfer, | ||
133 | |||
134 | /* Timeout handling */ | ||
135 | .irq_handler = ata_interrupt, | ||
136 | .irq_clear = ata_bmdma_irq_clear, | ||
137 | |||
138 | /* Generic PATA PCI ATA helpers */ | ||
139 | .port_start = ata_port_start, | ||
140 | .port_stop = ata_port_stop, | ||
141 | .host_stop = ata_host_stop, | ||
142 | }; | ||
143 | |||
144 | |||
145 | /** | ||
146 | * marvell_init_one - Register Marvell ATA PCI device with kernel services | ||
147 | * @pdev: PCI device to register | ||
148 | * @ent: Entry in marvell_pci_tbl matching with @pdev | ||
149 | * | ||
150 | * Called from kernel PCI layer. | ||
151 | * | ||
152 | * LOCKING: | ||
153 | * Inherited from PCI layer (may sleep). | ||
154 | * | ||
155 | * RETURNS: | ||
156 | * Zero on success, or -ERRNO value. | ||
157 | */ | ||
158 | |||
159 | static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id) | ||
160 | { | ||
161 | static struct ata_port_info info = { | ||
162 | .sht = &marvell_sht, | ||
163 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | ||
164 | |||
165 | .pio_mask = 0x1f, | ||
166 | .mwdma_mask = 0x07, | ||
167 | .udma_mask = 0x3f, | ||
168 | |||
169 | .port_ops = &marvell_ops, | ||
170 | }; | ||
171 | static struct ata_port_info info_sata = { | ||
172 | .sht = &marvell_sht, | ||
173 | /* Slave possible as its magically mapped not real */ | ||
174 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | ||
175 | |||
176 | .pio_mask = 0x1f, | ||
177 | .mwdma_mask = 0x07, | ||
178 | .udma_mask = 0x7f, | ||
179 | |||
180 | .port_ops = &marvell_ops, | ||
181 | }; | ||
182 | struct ata_port_info *port_info[2] = { &info, &info_sata }; | ||
183 | int n_port = 2; | ||
184 | |||
185 | if (pdev->device == 0x6101) | ||
186 | n_port = 1; | ||
187 | |||
188 | return ata_pci_init_one(pdev, port_info, n_port); | ||
189 | } | ||
190 | |||
191 | static const struct pci_device_id marvell_pci_tbl[] = { | ||
192 | { PCI_DEVICE(0x11AB, 0x6101), }, | ||
193 | { PCI_DEVICE(0x11AB, 0x6145), }, | ||
194 | { } /* terminate list */ | ||
195 | }; | ||
196 | |||
197 | static struct pci_driver marvell_pci_driver = { | ||
198 | .name = DRV_NAME, | ||
199 | .id_table = marvell_pci_tbl, | ||
200 | .probe = marvell_init_one, | ||
201 | .remove = ata_pci_remove_one, | ||
202 | .suspend = ata_pci_device_suspend, | ||
203 | .resume = ata_pci_device_resume, | ||
204 | }; | ||
205 | |||
206 | static int __init marvell_init(void) | ||
207 | { | ||
208 | return pci_register_driver(&marvell_pci_driver); | ||
209 | } | ||
210 | |||
211 | static void __exit marvell_exit(void) | ||
212 | { | ||
213 | pci_unregister_driver(&marvell_pci_driver); | ||
214 | } | ||
215 | |||
216 | module_init(marvell_init); | ||
217 | module_exit(marvell_exit); | ||
218 | |||
219 | MODULE_AUTHOR("Alan Cox"); | ||
220 | MODULE_DESCRIPTION("SCSI low-level driver for Marvell ATA in legacy mode"); | ||
221 | MODULE_LICENSE("GPL"); | ||
222 | MODULE_DEVICE_TABLE(pci, marvell_pci_tbl); | ||
223 | MODULE_VERSION(DRV_VERSION); | ||
224 | |||
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index e00d406bfdf5..4ccca938675e 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/libata.h> | 35 | #include <linux/libata.h> |
36 | 36 | ||
37 | #define DRV_NAME "pata_mpiix" | 37 | #define DRV_NAME "pata_mpiix" |
38 | #define DRV_VERSION "0.7.2" | 38 | #define DRV_VERSION "0.7.3" |
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | IDETIM = 0x6C, /* IDE control register */ | 41 | IDETIM = 0x6C, /* IDE control register */ |
@@ -159,7 +159,6 @@ static struct scsi_host_template mpiix_sht = { | |||
159 | .can_queue = ATA_DEF_QUEUE, | 159 | .can_queue = ATA_DEF_QUEUE, |
160 | .this_id = ATA_SHT_THIS_ID, | 160 | .this_id = ATA_SHT_THIS_ID, |
161 | .sg_tablesize = LIBATA_MAX_PRD, | 161 | .sg_tablesize = LIBATA_MAX_PRD, |
162 | .max_sectors = ATA_MAX_SECTORS, | ||
163 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 162 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
164 | .emulated = ATA_SHT_EMULATED, | 163 | .emulated = ATA_SHT_EMULATED, |
165 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 164 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -168,6 +167,8 @@ static struct scsi_host_template mpiix_sht = { | |||
168 | .slave_configure = ata_scsi_slave_config, | 167 | .slave_configure = ata_scsi_slave_config, |
169 | .slave_destroy = ata_scsi_slave_destroy, | 168 | .slave_destroy = ata_scsi_slave_destroy, |
170 | .bios_param = ata_std_bios_param, | 169 | .bios_param = ata_std_bios_param, |
170 | .resume = ata_scsi_device_resume, | ||
171 | .suspend = ata_scsi_device_suspend, | ||
171 | }; | 172 | }; |
172 | 173 | ||
173 | static struct ata_port_operations mpiix_port_ops = { | 174 | static struct ata_port_operations mpiix_port_ops = { |
@@ -285,7 +286,9 @@ static struct pci_driver mpiix_pci_driver = { | |||
285 | .name = DRV_NAME, | 286 | .name = DRV_NAME, |
286 | .id_table = mpiix, | 287 | .id_table = mpiix, |
287 | .probe = mpiix_init_one, | 288 | .probe = mpiix_init_one, |
288 | .remove = mpiix_remove_one | 289 | .remove = mpiix_remove_one, |
290 | .suspend = ata_pci_device_suspend, | ||
291 | .resume = ata_pci_device_resume, | ||
289 | }; | 292 | }; |
290 | 293 | ||
291 | static int __init mpiix_init(void) | 294 | static int __init mpiix_init(void) |
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index 1963a4d35873..cf7fe037471c 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/ata.h> | 16 | #include <linux/ata.h> |
17 | 17 | ||
18 | #define DRV_NAME "pata_netcell" | 18 | #define DRV_NAME "pata_netcell" |
19 | #define DRV_VERSION "0.1.5" | 19 | #define DRV_VERSION "0.1.6" |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * netcell_probe_init - check for 40/80 pin | 22 | * netcell_probe_init - check for 40/80 pin |
@@ -54,8 +54,6 @@ static struct scsi_host_template netcell_sht = { | |||
54 | .can_queue = ATA_DEF_QUEUE, | 54 | .can_queue = ATA_DEF_QUEUE, |
55 | .this_id = ATA_SHT_THIS_ID, | 55 | .this_id = ATA_SHT_THIS_ID, |
56 | .sg_tablesize = LIBATA_MAX_PRD, | 56 | .sg_tablesize = LIBATA_MAX_PRD, |
57 | /* Special handling needed if you have sector or LBA48 limits */ | ||
58 | .max_sectors = ATA_MAX_SECTORS, | ||
59 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 57 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
60 | .emulated = ATA_SHT_EMULATED, | 58 | .emulated = ATA_SHT_EMULATED, |
61 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 59 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -65,6 +63,8 @@ static struct scsi_host_template netcell_sht = { | |||
65 | .slave_destroy = ata_scsi_slave_destroy, | 63 | .slave_destroy = ata_scsi_slave_destroy, |
66 | /* Use standard CHS mapping rules */ | 64 | /* Use standard CHS mapping rules */ |
67 | .bios_param = ata_std_bios_param, | 65 | .bios_param = ata_std_bios_param, |
66 | .resume = ata_scsi_device_resume, | ||
67 | .suspend = ata_scsi_device_suspend, | ||
68 | }; | 68 | }; |
69 | 69 | ||
70 | static const struct ata_port_operations netcell_ops = { | 70 | static const struct ata_port_operations netcell_ops = { |
@@ -153,6 +153,8 @@ static struct pci_driver netcell_pci_driver = { | |||
153 | .id_table = netcell_pci_tbl, | 153 | .id_table = netcell_pci_tbl, |
154 | .probe = netcell_init_one, | 154 | .probe = netcell_init_one, |
155 | .remove = ata_pci_remove_one, | 155 | .remove = ata_pci_remove_one, |
156 | .suspend = ata_pci_device_suspend, | ||
157 | .resume = ata_pci_device_resume, | ||
156 | }; | 158 | }; |
157 | 159 | ||
158 | static int __init netcell_init(void) | 160 | static int __init netcell_init(void) |
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index 7ec800f00ec8..c3032eb9010d 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/libata.h> | 28 | #include <linux/libata.h> |
29 | 29 | ||
30 | #define DRV_NAME "pata_ns87410" | 30 | #define DRV_NAME "pata_ns87410" |
31 | #define DRV_VERSION "0.4.2" | 31 | #define DRV_VERSION "0.4.3" |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * ns87410_pre_reset - probe begin | 34 | * ns87410_pre_reset - probe begin |
@@ -149,7 +149,6 @@ static struct scsi_host_template ns87410_sht = { | |||
149 | .can_queue = ATA_DEF_QUEUE, | 149 | .can_queue = ATA_DEF_QUEUE, |
150 | .this_id = ATA_SHT_THIS_ID, | 150 | .this_id = ATA_SHT_THIS_ID, |
151 | .sg_tablesize = LIBATA_MAX_PRD, | 151 | .sg_tablesize = LIBATA_MAX_PRD, |
152 | .max_sectors = ATA_MAX_SECTORS, | ||
153 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 152 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
154 | .emulated = ATA_SHT_EMULATED, | 153 | .emulated = ATA_SHT_EMULATED, |
155 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 154 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -158,6 +157,8 @@ static struct scsi_host_template ns87410_sht = { | |||
158 | .slave_configure = ata_scsi_slave_config, | 157 | .slave_configure = ata_scsi_slave_config, |
159 | .slave_destroy = ata_scsi_slave_destroy, | 158 | .slave_destroy = ata_scsi_slave_destroy, |
160 | .bios_param = ata_std_bios_param, | 159 | .bios_param = ata_std_bios_param, |
160 | .resume = ata_scsi_device_resume, | ||
161 | .suspend = ata_scsi_device_suspend, | ||
161 | }; | 162 | }; |
162 | 163 | ||
163 | static struct ata_port_operations ns87410_port_ops = { | 164 | static struct ata_port_operations ns87410_port_ops = { |
@@ -210,7 +211,9 @@ static struct pci_driver ns87410_pci_driver = { | |||
210 | .name = DRV_NAME, | 211 | .name = DRV_NAME, |
211 | .id_table = ns87410, | 212 | .id_table = ns87410, |
212 | .probe = ns87410_init_one, | 213 | .probe = ns87410_init_one, |
213 | .remove = ata_pci_remove_one | 214 | .remove = ata_pci_remove_one, |
215 | .suspend = ata_pci_device_suspend, | ||
216 | .resume = ata_pci_device_resume, | ||
214 | }; | 217 | }; |
215 | 218 | ||
216 | static int __init ns87410_init(void) | 219 | static int __init ns87410_init(void) |
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index 8837256632e9..10ac3cc10181 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c | |||
@@ -224,7 +224,6 @@ static struct scsi_host_template oldpiix_sht = { | |||
224 | .can_queue = ATA_DEF_QUEUE, | 224 | .can_queue = ATA_DEF_QUEUE, |
225 | .this_id = ATA_SHT_THIS_ID, | 225 | .this_id = ATA_SHT_THIS_ID, |
226 | .sg_tablesize = LIBATA_MAX_PRD, | 226 | .sg_tablesize = LIBATA_MAX_PRD, |
227 | .max_sectors = ATA_MAX_SECTORS, | ||
228 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 227 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
229 | .emulated = ATA_SHT_EMULATED, | 228 | .emulated = ATA_SHT_EMULATED, |
230 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 229 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -233,6 +232,8 @@ static struct scsi_host_template oldpiix_sht = { | |||
233 | .slave_configure = ata_scsi_slave_config, | 232 | .slave_configure = ata_scsi_slave_config, |
234 | .slave_destroy = ata_scsi_slave_destroy, | 233 | .slave_destroy = ata_scsi_slave_destroy, |
235 | .bios_param = ata_std_bios_param, | 234 | .bios_param = ata_std_bios_param, |
235 | .resume = ata_scsi_device_resume, | ||
236 | .suspend = ata_scsi_device_suspend, | ||
236 | }; | 237 | }; |
237 | 238 | ||
238 | static const struct ata_port_operations oldpiix_pata_ops = { | 239 | static const struct ata_port_operations oldpiix_pata_ops = { |
@@ -314,6 +315,8 @@ static struct pci_driver oldpiix_pci_driver = { | |||
314 | .id_table = oldpiix_pci_tbl, | 315 | .id_table = oldpiix_pci_tbl, |
315 | .probe = oldpiix_init_one, | 316 | .probe = oldpiix_init_one, |
316 | .remove = ata_pci_remove_one, | 317 | .remove = ata_pci_remove_one, |
318 | .suspend = ata_pci_device_suspend, | ||
319 | .resume = ata_pci_device_resume, | ||
317 | }; | 320 | }; |
318 | 321 | ||
319 | static int __init oldpiix_init(void) | 322 | static int __init oldpiix_init(void) |
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index c6319cf50de4..c2988b0aa8ea 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/libata.h> | 34 | #include <linux/libata.h> |
35 | 35 | ||
36 | #define DRV_NAME "pata_opti" | 36 | #define DRV_NAME "pata_opti" |
37 | #define DRV_VERSION "0.2.5" | 37 | #define DRV_VERSION "0.2.7" |
38 | 38 | ||
39 | enum { | 39 | enum { |
40 | READ_REG = 0, /* index of Read cycle timing register */ | 40 | READ_REG = 0, /* index of Read cycle timing register */ |
@@ -109,30 +109,6 @@ static void opti_write_reg(struct ata_port *ap, u8 val, int reg) | |||
109 | outb(0x83, regio + 2); | 109 | outb(0x83, regio + 2); |
110 | } | 110 | } |
111 | 111 | ||
112 | #if 0 | ||
113 | /** | ||
114 | * opti_read_reg - control register read | ||
115 | * @ap: ATA port | ||
116 | * @reg: control register number | ||
117 | * | ||
118 | * The Opti uses magic 'trapdoor' register accesses to do configuration | ||
119 | * rather than using PCI space as other controllers do. The double inw | ||
120 | * on the error register activates configuration mode. We can then read | ||
121 | * the control register | ||
122 | */ | ||
123 | |||
124 | static u8 opti_read_reg(struct ata_port *ap, int reg) | ||
125 | { | ||
126 | unsigned long regio = ap->ioaddr.cmd_addr; | ||
127 | u8 ret; | ||
128 | inw(regio + 1); | ||
129 | inw(regio + 1); | ||
130 | outb(3, regio + 2); | ||
131 | ret = inb(regio + reg); | ||
132 | outb(0x83, regio + 2); | ||
133 | } | ||
134 | #endif | ||
135 | |||
136 | /** | 112 | /** |
137 | * opti_set_piomode - set initial PIO mode data | 113 | * opti_set_piomode - set initial PIO mode data |
138 | * @ap: ATA interface | 114 | * @ap: ATA interface |
@@ -195,7 +171,6 @@ static struct scsi_host_template opti_sht = { | |||
195 | .can_queue = ATA_DEF_QUEUE, | 171 | .can_queue = ATA_DEF_QUEUE, |
196 | .this_id = ATA_SHT_THIS_ID, | 172 | .this_id = ATA_SHT_THIS_ID, |
197 | .sg_tablesize = LIBATA_MAX_PRD, | 173 | .sg_tablesize = LIBATA_MAX_PRD, |
198 | .max_sectors = ATA_MAX_SECTORS, | ||
199 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 174 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
200 | .emulated = ATA_SHT_EMULATED, | 175 | .emulated = ATA_SHT_EMULATED, |
201 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 176 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -204,12 +179,13 @@ static struct scsi_host_template opti_sht = { | |||
204 | .slave_configure = ata_scsi_slave_config, | 179 | .slave_configure = ata_scsi_slave_config, |
205 | .slave_destroy = ata_scsi_slave_destroy, | 180 | .slave_destroy = ata_scsi_slave_destroy, |
206 | .bios_param = ata_std_bios_param, | 181 | .bios_param = ata_std_bios_param, |
182 | .resume = ata_scsi_device_resume, | ||
183 | .suspend = ata_scsi_device_suspend, | ||
207 | }; | 184 | }; |
208 | 185 | ||
209 | static struct ata_port_operations opti_port_ops = { | 186 | static struct ata_port_operations opti_port_ops = { |
210 | .port_disable = ata_port_disable, | 187 | .port_disable = ata_port_disable, |
211 | .set_piomode = opti_set_piomode, | 188 | .set_piomode = opti_set_piomode, |
212 | /* .set_dmamode = opti_set_dmamode, */ | ||
213 | .tf_load = ata_tf_load, | 189 | .tf_load = ata_tf_load, |
214 | .tf_read = ata_tf_read, | 190 | .tf_read = ata_tf_read, |
215 | .check_status = ata_check_status, | 191 | .check_status = ata_check_status, |
@@ -267,7 +243,9 @@ static struct pci_driver opti_pci_driver = { | |||
267 | .name = DRV_NAME, | 243 | .name = DRV_NAME, |
268 | .id_table = opti, | 244 | .id_table = opti, |
269 | .probe = opti_init_one, | 245 | .probe = opti_init_one, |
270 | .remove = ata_pci_remove_one | 246 | .remove = ata_pci_remove_one, |
247 | .suspend = ata_pci_device_suspend, | ||
248 | .resume = ata_pci_device_resume, | ||
271 | }; | 249 | }; |
272 | 250 | ||
273 | static int __init opti_init(void) | 251 | static int __init opti_init(void) |
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 2f4770cce04e..80d111c569dc 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/libata.h> | 33 | #include <linux/libata.h> |
34 | 34 | ||
35 | #define DRV_NAME "pata_optidma" | 35 | #define DRV_NAME "pata_optidma" |
36 | #define DRV_VERSION "0.2.2" | 36 | #define DRV_VERSION "0.2.3" |
37 | 37 | ||
38 | enum { | 38 | enum { |
39 | READ_REG = 0, /* index of Read cycle timing register */ | 39 | READ_REG = 0, /* index of Read cycle timing register */ |
@@ -352,7 +352,6 @@ static struct scsi_host_template optidma_sht = { | |||
352 | .can_queue = ATA_DEF_QUEUE, | 352 | .can_queue = ATA_DEF_QUEUE, |
353 | .this_id = ATA_SHT_THIS_ID, | 353 | .this_id = ATA_SHT_THIS_ID, |
354 | .sg_tablesize = LIBATA_MAX_PRD, | 354 | .sg_tablesize = LIBATA_MAX_PRD, |
355 | .max_sectors = ATA_MAX_SECTORS, | ||
356 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 355 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
357 | .emulated = ATA_SHT_EMULATED, | 356 | .emulated = ATA_SHT_EMULATED, |
358 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 357 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -361,6 +360,8 @@ static struct scsi_host_template optidma_sht = { | |||
361 | .slave_configure = ata_scsi_slave_config, | 360 | .slave_configure = ata_scsi_slave_config, |
362 | .slave_destroy = ata_scsi_slave_destroy, | 361 | .slave_destroy = ata_scsi_slave_destroy, |
363 | .bios_param = ata_std_bios_param, | 362 | .bios_param = ata_std_bios_param, |
363 | .resume = ata_scsi_device_resume, | ||
364 | .suspend = ata_scsi_device_suspend, | ||
364 | }; | 365 | }; |
365 | 366 | ||
366 | static struct ata_port_operations optidma_port_ops = { | 367 | static struct ata_port_operations optidma_port_ops = { |
@@ -522,7 +523,9 @@ static struct pci_driver optidma_pci_driver = { | |||
522 | .name = DRV_NAME, | 523 | .name = DRV_NAME, |
523 | .id_table = optidma, | 524 | .id_table = optidma, |
524 | .probe = optidma_init_one, | 525 | .probe = optidma_init_one, |
525 | .remove = ata_pci_remove_one | 526 | .remove = ata_pci_remove_one, |
527 | .suspend = ata_pci_device_suspend, | ||
528 | .resume = ata_pci_device_resume, | ||
526 | }; | 529 | }; |
527 | 530 | ||
528 | static int __init optidma_init(void) | 531 | static int __init optidma_init(void) |
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 999922de476e..4ca6fa5dcb42 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
@@ -62,7 +62,6 @@ static struct scsi_host_template pcmcia_sht = { | |||
62 | .can_queue = ATA_DEF_QUEUE, | 62 | .can_queue = ATA_DEF_QUEUE, |
63 | .this_id = ATA_SHT_THIS_ID, | 63 | .this_id = ATA_SHT_THIS_ID, |
64 | .sg_tablesize = LIBATA_MAX_PRD, | 64 | .sg_tablesize = LIBATA_MAX_PRD, |
65 | .max_sectors = ATA_MAX_SECTORS, | ||
66 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 65 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
67 | .emulated = ATA_SHT_EMULATED, | 66 | .emulated = ATA_SHT_EMULATED, |
68 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 67 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index beb6d10a234b..76dd1c935dbd 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c | |||
@@ -134,7 +134,6 @@ static struct scsi_host_template pdc2027x_sht = { | |||
134 | .can_queue = ATA_DEF_QUEUE, | 134 | .can_queue = ATA_DEF_QUEUE, |
135 | .this_id = ATA_SHT_THIS_ID, | 135 | .this_id = ATA_SHT_THIS_ID, |
136 | .sg_tablesize = LIBATA_MAX_PRD, | 136 | .sg_tablesize = LIBATA_MAX_PRD, |
137 | .max_sectors = ATA_MAX_SECTORS, | ||
138 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 137 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
139 | .emulated = ATA_SHT_EMULATED, | 138 | .emulated = ATA_SHT_EMULATED, |
140 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 139 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -854,7 +853,7 @@ static void __devexit pdc2027x_remove_one(struct pci_dev *pdev) | |||
854 | */ | 853 | */ |
855 | static int __init pdc2027x_init(void) | 854 | static int __init pdc2027x_init(void) |
856 | { | 855 | { |
857 | return pci_module_init(&pdc2027x_pci_driver); | 856 | return pci_register_driver(&pdc2027x_pci_driver); |
858 | } | 857 | } |
859 | 858 | ||
860 | /** | 859 | /** |
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 6baf51b2fda1..ad691b9e7743 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/libata.h> | 21 | #include <linux/libata.h> |
22 | 22 | ||
23 | #define DRV_NAME "pata_pdc202xx_old" | 23 | #define DRV_NAME "pata_pdc202xx_old" |
24 | #define DRV_VERSION "0.2.1" | 24 | #define DRV_VERSION "0.2.3" |
25 | 25 | ||
26 | /** | 26 | /** |
27 | * pdc2024x_pre_reset - probe begin | 27 | * pdc2024x_pre_reset - probe begin |
@@ -63,7 +63,7 @@ static void pdc2026x_error_handler(struct ata_port *ap) | |||
63 | } | 63 | } |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * pdc_configure_piomode - set chip PIO timing | 66 | * pdc202xx_configure_piomode - set chip PIO timing |
67 | * @ap: ATA interface | 67 | * @ap: ATA interface |
68 | * @adev: ATA device | 68 | * @adev: ATA device |
69 | * @pio: PIO mode | 69 | * @pio: PIO mode |
@@ -73,7 +73,7 @@ static void pdc2026x_error_handler(struct ata_port *ap) | |||
73 | * versa | 73 | * versa |
74 | */ | 74 | */ |
75 | 75 | ||
76 | static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) | 76 | static void pdc202xx_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) |
77 | { | 77 | { |
78 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 78 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
79 | int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; | 79 | int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; |
@@ -98,7 +98,7 @@ static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, | |||
98 | } | 98 | } |
99 | 99 | ||
100 | /** | 100 | /** |
101 | * pdc_set_piomode - set initial PIO mode data | 101 | * pdc202xx_set_piomode - set initial PIO mode data |
102 | * @ap: ATA interface | 102 | * @ap: ATA interface |
103 | * @adev: ATA device | 103 | * @adev: ATA device |
104 | * | 104 | * |
@@ -106,13 +106,13 @@ static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, | |||
106 | * but we want to set the PIO timing by default. | 106 | * but we want to set the PIO timing by default. |
107 | */ | 107 | */ |
108 | 108 | ||
109 | static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev) | 109 | static void pdc202xx_set_piomode(struct ata_port *ap, struct ata_device *adev) |
110 | { | 110 | { |
111 | pdc_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); | 111 | pdc202xx_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); |
112 | } | 112 | } |
113 | 113 | ||
114 | /** | 114 | /** |
115 | * pdc_configure_dmamode - set DMA mode in chip | 115 | * pdc202xx_configure_dmamode - set DMA mode in chip |
116 | * @ap: ATA interface | 116 | * @ap: ATA interface |
117 | * @adev: ATA device | 117 | * @adev: ATA device |
118 | * | 118 | * |
@@ -120,7 +120,7 @@ static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
120 | * to occur. | 120 | * to occur. |
121 | */ | 121 | */ |
122 | 122 | ||
123 | static void pdc_set_dmamode(struct ata_port *ap, struct ata_device *adev) | 123 | static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev) |
124 | { | 124 | { |
125 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 125 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
126 | int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; | 126 | int port = 0x60 + 4 * ap->port_no + 2 * adev->devno; |
@@ -184,7 +184,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) | |||
184 | 184 | ||
185 | /* The DMA clocks may have been trashed by a reset. FIXME: make conditional | 185 | /* The DMA clocks may have been trashed by a reset. FIXME: make conditional |
186 | and move to qc_issue ? */ | 186 | and move to qc_issue ? */ |
187 | pdc_set_dmamode(ap, qc->dev); | 187 | pdc202xx_set_dmamode(ap, qc->dev); |
188 | 188 | ||
189 | /* Cases the state machine will not complete correctly without help */ | 189 | /* Cases the state machine will not complete correctly without help */ |
190 | if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) | 190 | if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) |
@@ -254,7 +254,7 @@ static void pdc2026x_dev_config(struct ata_port *ap, struct ata_device *adev) | |||
254 | adev->max_sectors = 256; | 254 | adev->max_sectors = 256; |
255 | } | 255 | } |
256 | 256 | ||
257 | static struct scsi_host_template pdc_sht = { | 257 | static struct scsi_host_template pdc202xx_sht = { |
258 | .module = THIS_MODULE, | 258 | .module = THIS_MODULE, |
259 | .name = DRV_NAME, | 259 | .name = DRV_NAME, |
260 | .ioctl = ata_scsi_ioctl, | 260 | .ioctl = ata_scsi_ioctl, |
@@ -262,7 +262,6 @@ static struct scsi_host_template pdc_sht = { | |||
262 | .can_queue = ATA_DEF_QUEUE, | 262 | .can_queue = ATA_DEF_QUEUE, |
263 | .this_id = ATA_SHT_THIS_ID, | 263 | .this_id = ATA_SHT_THIS_ID, |
264 | .sg_tablesize = LIBATA_MAX_PRD, | 264 | .sg_tablesize = LIBATA_MAX_PRD, |
265 | .max_sectors = ATA_MAX_SECTORS, | ||
266 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 265 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
267 | .emulated = ATA_SHT_EMULATED, | 266 | .emulated = ATA_SHT_EMULATED, |
268 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 267 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -271,12 +270,14 @@ static struct scsi_host_template pdc_sht = { | |||
271 | .slave_configure = ata_scsi_slave_config, | 270 | .slave_configure = ata_scsi_slave_config, |
272 | .slave_destroy = ata_scsi_slave_destroy, | 271 | .slave_destroy = ata_scsi_slave_destroy, |
273 | .bios_param = ata_std_bios_param, | 272 | .bios_param = ata_std_bios_param, |
273 | .resume = ata_scsi_device_resume, | ||
274 | .suspend = ata_scsi_device_suspend, | ||
274 | }; | 275 | }; |
275 | 276 | ||
276 | static struct ata_port_operations pdc2024x_port_ops = { | 277 | static struct ata_port_operations pdc2024x_port_ops = { |
277 | .port_disable = ata_port_disable, | 278 | .port_disable = ata_port_disable, |
278 | .set_piomode = pdc_set_piomode, | 279 | .set_piomode = pdc202xx_set_piomode, |
279 | .set_dmamode = pdc_set_dmamode, | 280 | .set_dmamode = pdc202xx_set_dmamode, |
280 | .mode_filter = ata_pci_default_filter, | 281 | .mode_filter = ata_pci_default_filter, |
281 | .tf_load = ata_tf_load, | 282 | .tf_load = ata_tf_load, |
282 | .tf_read = ata_tf_read, | 283 | .tf_read = ata_tf_read, |
@@ -308,8 +309,8 @@ static struct ata_port_operations pdc2024x_port_ops = { | |||
308 | 309 | ||
309 | static struct ata_port_operations pdc2026x_port_ops = { | 310 | static struct ata_port_operations pdc2026x_port_ops = { |
310 | .port_disable = ata_port_disable, | 311 | .port_disable = ata_port_disable, |
311 | .set_piomode = pdc_set_piomode, | 312 | .set_piomode = pdc202xx_set_piomode, |
312 | .set_dmamode = pdc_set_dmamode, | 313 | .set_dmamode = pdc202xx_set_dmamode, |
313 | .mode_filter = ata_pci_default_filter, | 314 | .mode_filter = ata_pci_default_filter, |
314 | .tf_load = ata_tf_load, | 315 | .tf_load = ata_tf_load, |
315 | .tf_read = ata_tf_read, | 316 | .tf_read = ata_tf_read, |
@@ -340,11 +341,11 @@ static struct ata_port_operations pdc2026x_port_ops = { | |||
340 | .host_stop = ata_host_stop | 341 | .host_stop = ata_host_stop |
341 | }; | 342 | }; |
342 | 343 | ||
343 | static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) | 344 | static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) |
344 | { | 345 | { |
345 | static struct ata_port_info info[3] = { | 346 | static struct ata_port_info info[3] = { |
346 | { | 347 | { |
347 | .sht = &pdc_sht, | 348 | .sht = &pdc202xx_sht, |
348 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 349 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, |
349 | .pio_mask = 0x1f, | 350 | .pio_mask = 0x1f, |
350 | .mwdma_mask = 0x07, | 351 | .mwdma_mask = 0x07, |
@@ -352,7 +353,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
352 | .port_ops = &pdc2024x_port_ops | 353 | .port_ops = &pdc2024x_port_ops |
353 | }, | 354 | }, |
354 | { | 355 | { |
355 | .sht = &pdc_sht, | 356 | .sht = &pdc202xx_sht, |
356 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 357 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, |
357 | .pio_mask = 0x1f, | 358 | .pio_mask = 0x1f, |
358 | .mwdma_mask = 0x07, | 359 | .mwdma_mask = 0x07, |
@@ -360,7 +361,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
360 | .port_ops = &pdc2026x_port_ops | 361 | .port_ops = &pdc2026x_port_ops |
361 | }, | 362 | }, |
362 | { | 363 | { |
363 | .sht = &pdc_sht, | 364 | .sht = &pdc202xx_sht, |
364 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 365 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, |
365 | .pio_mask = 0x1f, | 366 | .pio_mask = 0x1f, |
366 | .mwdma_mask = 0x07, | 367 | .mwdma_mask = 0x07, |
@@ -386,7 +387,7 @@ static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
386 | return ata_pci_init_one(dev, port_info, 2); | 387 | return ata_pci_init_one(dev, port_info, 2); |
387 | } | 388 | } |
388 | 389 | ||
389 | static const struct pci_device_id pdc[] = { | 390 | static const struct pci_device_id pdc202xx[] = { |
390 | { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, | 391 | { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, |
391 | { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, | 392 | { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, |
392 | { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 }, | 393 | { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 }, |
@@ -396,28 +397,30 @@ static const struct pci_device_id pdc[] = { | |||
396 | { }, | 397 | { }, |
397 | }; | 398 | }; |
398 | 399 | ||
399 | static struct pci_driver pdc_pci_driver = { | 400 | static struct pci_driver pdc202xx_pci_driver = { |
400 | .name = DRV_NAME, | 401 | .name = DRV_NAME, |
401 | .id_table = pdc, | 402 | .id_table = pdc202xx, |
402 | .probe = pdc_init_one, | 403 | .probe = pdc202xx_init_one, |
403 | .remove = ata_pci_remove_one | 404 | .remove = ata_pci_remove_one, |
405 | .suspend = ata_pci_device_suspend, | ||
406 | .resume = ata_pci_device_resume, | ||
404 | }; | 407 | }; |
405 | 408 | ||
406 | static int __init pdc_init(void) | 409 | static int __init pdc202xx_init(void) |
407 | { | 410 | { |
408 | return pci_register_driver(&pdc_pci_driver); | 411 | return pci_register_driver(&pdc202xx_pci_driver); |
409 | } | 412 | } |
410 | 413 | ||
411 | static void __exit pdc_exit(void) | 414 | static void __exit pdc202xx_exit(void) |
412 | { | 415 | { |
413 | pci_unregister_driver(&pdc_pci_driver); | 416 | pci_unregister_driver(&pdc202xx_pci_driver); |
414 | } | 417 | } |
415 | 418 | ||
416 | MODULE_AUTHOR("Alan Cox"); | 419 | MODULE_AUTHOR("Alan Cox"); |
417 | MODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267"); | 420 | MODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267"); |
418 | MODULE_LICENSE("GPL"); | 421 | MODULE_LICENSE("GPL"); |
419 | MODULE_DEVICE_TABLE(pci, pdc); | 422 | MODULE_DEVICE_TABLE(pci, pdc202xx); |
420 | MODULE_VERSION(DRV_VERSION); | 423 | MODULE_VERSION(DRV_VERSION); |
421 | 424 | ||
422 | module_init(pdc_init); | 425 | module_init(pdc202xx_init); |
423 | module_exit(pdc_exit); | 426 | module_exit(pdc202xx_exit); |
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c new file mode 100644 index 000000000000..443b1d85c6c4 --- /dev/null +++ b/drivers/ata/pata_platform.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | * Generic platform device PATA driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Paul Mundt | ||
5 | * | ||
6 | * Based on pata_pcmcia: | ||
7 | * | ||
8 | * Copyright 2005-2006 Red Hat Inc <alan@redhat.com>, all rights reserved. | ||
9 | * | ||
10 | * This file is subject to the terms and conditions of the GNU General Public | ||
11 | * License. See the file "COPYING" in the main directory of this archive | ||
12 | * for more details. | ||
13 | */ | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/blkdev.h> | ||
18 | #include <scsi/scsi_host.h> | ||
19 | #include <linux/ata.h> | ||
20 | #include <linux/libata.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/pata_platform.h> | ||
23 | |||
24 | #define DRV_NAME "pata_platform" | ||
25 | #define DRV_VERSION "0.1.2" | ||
26 | |||
27 | static int pio_mask = 1; | ||
28 | |||
29 | /* | ||
30 | * Provide our own set_mode() as we don't want to change anything that has | ||
31 | * already been configured.. | ||
32 | */ | ||
33 | static void pata_platform_set_mode(struct ata_port *ap) | ||
34 | { | ||
35 | int i; | ||
36 | |||
37 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | ||
38 | struct ata_device *dev = &ap->device[i]; | ||
39 | |||
40 | if (ata_dev_enabled(dev)) { | ||
41 | /* We don't really care */ | ||
42 | dev->pio_mode = dev->xfer_mode = XFER_PIO_0; | ||
43 | dev->xfer_shift = ATA_SHIFT_PIO; | ||
44 | dev->flags |= ATA_DFLAG_PIO; | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | static void pata_platform_host_stop(struct ata_host *host) | ||
50 | { | ||
51 | int i; | ||
52 | |||
53 | /* | ||
54 | * Unmap the bases for MMIO | ||
55 | */ | ||
56 | for (i = 0; i < host->n_ports; i++) { | ||
57 | struct ata_port *ap = host->ports[i]; | ||
58 | |||
59 | if (ap->flags & ATA_FLAG_MMIO) { | ||
60 | iounmap((void __iomem *)ap->ioaddr.ctl_addr); | ||
61 | iounmap((void __iomem *)ap->ioaddr.cmd_addr); | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | static struct scsi_host_template pata_platform_sht = { | ||
67 | .module = THIS_MODULE, | ||
68 | .name = DRV_NAME, | ||
69 | .ioctl = ata_scsi_ioctl, | ||
70 | .queuecommand = ata_scsi_queuecmd, | ||
71 | .can_queue = ATA_DEF_QUEUE, | ||
72 | .this_id = ATA_SHT_THIS_ID, | ||
73 | .sg_tablesize = LIBATA_MAX_PRD, | ||
74 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
75 | .emulated = ATA_SHT_EMULATED, | ||
76 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
77 | .proc_name = DRV_NAME, | ||
78 | .dma_boundary = ATA_DMA_BOUNDARY, | ||
79 | .slave_configure = ata_scsi_slave_config, | ||
80 | .slave_destroy = ata_scsi_slave_destroy, | ||
81 | .bios_param = ata_std_bios_param, | ||
82 | }; | ||
83 | |||
84 | static struct ata_port_operations pata_platform_port_ops = { | ||
85 | .set_mode = pata_platform_set_mode, | ||
86 | |||
87 | .port_disable = ata_port_disable, | ||
88 | .tf_load = ata_tf_load, | ||
89 | .tf_read = ata_tf_read, | ||
90 | .check_status = ata_check_status, | ||
91 | .exec_command = ata_exec_command, | ||
92 | .dev_select = ata_std_dev_select, | ||
93 | |||
94 | .freeze = ata_bmdma_freeze, | ||
95 | .thaw = ata_bmdma_thaw, | ||
96 | .error_handler = ata_bmdma_error_handler, | ||
97 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
98 | |||
99 | .qc_prep = ata_qc_prep, | ||
100 | .qc_issue = ata_qc_issue_prot, | ||
101 | |||
102 | .data_xfer = ata_pio_data_xfer_noirq, | ||
103 | |||
104 | .irq_handler = ata_interrupt, | ||
105 | .irq_clear = ata_bmdma_irq_clear, | ||
106 | |||
107 | .port_start = ata_port_start, | ||
108 | .port_stop = ata_port_stop, | ||
109 | .host_stop = pata_platform_host_stop | ||
110 | }; | ||
111 | |||
112 | static void pata_platform_setup_port(struct ata_ioports *ioaddr, | ||
113 | struct pata_platform_info *info) | ||
114 | { | ||
115 | unsigned int shift = 0; | ||
116 | |||
117 | /* Fixup the port shift for platforms that need it */ | ||
118 | if (info && info->ioport_shift) | ||
119 | shift = info->ioport_shift; | ||
120 | |||
121 | ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift); | ||
122 | ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift); | ||
123 | ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift); | ||
124 | ioaddr->nsect_addr = ioaddr->cmd_addr + (ATA_REG_NSECT << shift); | ||
125 | ioaddr->lbal_addr = ioaddr->cmd_addr + (ATA_REG_LBAL << shift); | ||
126 | ioaddr->lbam_addr = ioaddr->cmd_addr + (ATA_REG_LBAM << shift); | ||
127 | ioaddr->lbah_addr = ioaddr->cmd_addr + (ATA_REG_LBAH << shift); | ||
128 | ioaddr->device_addr = ioaddr->cmd_addr + (ATA_REG_DEVICE << shift); | ||
129 | ioaddr->status_addr = ioaddr->cmd_addr + (ATA_REG_STATUS << shift); | ||
130 | ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << shift); | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * pata_platform_probe - attach a platform interface | ||
135 | * @pdev: platform device | ||
136 | * | ||
137 | * Register a platform bus IDE interface. Such interfaces are PIO and we | ||
138 | * assume do not support IRQ sharing. | ||
139 | * | ||
140 | * Platform devices are expected to contain 3 resources per port: | ||
141 | * | ||
142 | * - I/O Base (IORESOURCE_IO or IORESOURCE_MEM) | ||
143 | * - CTL Base (IORESOURCE_IO or IORESOURCE_MEM) | ||
144 | * - IRQ (IORESOURCE_IRQ) | ||
145 | * | ||
146 | * If the base resources are both mem types, the ioremap() is handled | ||
147 | * here. For IORESOURCE_IO, it's assumed that there's no remapping | ||
148 | * necessary. | ||
149 | */ | ||
150 | static int __devinit pata_platform_probe(struct platform_device *pdev) | ||
151 | { | ||
152 | struct resource *io_res, *ctl_res; | ||
153 | struct ata_probe_ent ae; | ||
154 | unsigned int mmio; | ||
155 | int ret; | ||
156 | |||
157 | /* | ||
158 | * Simple resource validation .. | ||
159 | */ | ||
160 | if (unlikely(pdev->num_resources != 3)) { | ||
161 | dev_err(&pdev->dev, "invalid number of resources\n"); | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Get the I/O base first | ||
167 | */ | ||
168 | io_res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
169 | if (io_res == NULL) { | ||
170 | io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
171 | if (unlikely(io_res == NULL)) | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Then the CTL base | ||
177 | */ | ||
178 | ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1); | ||
179 | if (ctl_res == NULL) { | ||
180 | ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
181 | if (unlikely(ctl_res == NULL)) | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Check for MMIO | ||
187 | */ | ||
188 | mmio = (( io_res->flags == IORESOURCE_MEM) && | ||
189 | (ctl_res->flags == IORESOURCE_MEM)); | ||
190 | |||
191 | /* | ||
192 | * Now that that's out of the way, wire up the port.. | ||
193 | */ | ||
194 | memset(&ae, 0, sizeof(struct ata_probe_ent)); | ||
195 | INIT_LIST_HEAD(&ae.node); | ||
196 | ae.dev = &pdev->dev; | ||
197 | ae.port_ops = &pata_platform_port_ops; | ||
198 | ae.sht = &pata_platform_sht; | ||
199 | ae.n_ports = 1; | ||
200 | ae.pio_mask = pio_mask; | ||
201 | ae.irq = platform_get_irq(pdev, 0); | ||
202 | ae.irq_flags = 0; | ||
203 | ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; | ||
204 | |||
205 | /* | ||
206 | * Handle the MMIO case | ||
207 | */ | ||
208 | if (mmio) { | ||
209 | ae.port_flags |= ATA_FLAG_MMIO; | ||
210 | |||
211 | ae.port[0].cmd_addr = (unsigned long)ioremap(io_res->start, | ||
212 | io_res->end - io_res->start + 1); | ||
213 | if (unlikely(!ae.port[0].cmd_addr)) { | ||
214 | dev_err(&pdev->dev, "failed to remap IO base\n"); | ||
215 | return -ENXIO; | ||
216 | } | ||
217 | |||
218 | ae.port[0].ctl_addr = (unsigned long)ioremap(ctl_res->start, | ||
219 | ctl_res->end - ctl_res->start + 1); | ||
220 | if (unlikely(!ae.port[0].ctl_addr)) { | ||
221 | dev_err(&pdev->dev, "failed to remap CTL base\n"); | ||
222 | ret = -ENXIO; | ||
223 | goto bad_remap; | ||
224 | } | ||
225 | } else { | ||
226 | ae.port[0].cmd_addr = io_res->start; | ||
227 | ae.port[0].ctl_addr = ctl_res->start; | ||
228 | } | ||
229 | |||
230 | ae.port[0].altstatus_addr = ae.port[0].ctl_addr; | ||
231 | |||
232 | pata_platform_setup_port(&ae.port[0], pdev->dev.platform_data); | ||
233 | |||
234 | if (unlikely(ata_device_add(&ae) == 0)) { | ||
235 | ret = -ENODEV; | ||
236 | goto add_failed; | ||
237 | } | ||
238 | |||
239 | return 0; | ||
240 | |||
241 | add_failed: | ||
242 | if (ae.port[0].ctl_addr && mmio) | ||
243 | iounmap((void __iomem *)ae.port[0].ctl_addr); | ||
244 | bad_remap: | ||
245 | if (ae.port[0].cmd_addr && mmio) | ||
246 | iounmap((void __iomem *)ae.port[0].cmd_addr); | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * pata_platform_remove - unplug a platform interface | ||
253 | * @pdev: platform device | ||
254 | * | ||
255 | * A platform bus ATA device has been unplugged. Perform the needed | ||
256 | * cleanup. Also called on module unload for any active devices. | ||
257 | */ | ||
258 | static int __devexit pata_platform_remove(struct platform_device *pdev) | ||
259 | { | ||
260 | struct device *dev = &pdev->dev; | ||
261 | struct ata_host *host = dev_get_drvdata(dev); | ||
262 | |||
263 | ata_host_remove(host); | ||
264 | dev_set_drvdata(dev, NULL); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct platform_driver pata_platform_driver = { | ||
270 | .probe = pata_platform_probe, | ||
271 | .remove = __devexit_p(pata_platform_remove), | ||
272 | .driver = { | ||
273 | .name = DRV_NAME, | ||
274 | .owner = THIS_MODULE, | ||
275 | }, | ||
276 | }; | ||
277 | |||
278 | static int __init pata_platform_init(void) | ||
279 | { | ||
280 | return platform_driver_register(&pata_platform_driver); | ||
281 | } | ||
282 | |||
283 | static void __exit pata_platform_exit(void) | ||
284 | { | ||
285 | platform_driver_unregister(&pata_platform_driver); | ||
286 | } | ||
287 | module_init(pata_platform_init); | ||
288 | module_exit(pata_platform_exit); | ||
289 | |||
290 | module_param(pio_mask, int, 0); | ||
291 | |||
292 | MODULE_AUTHOR("Paul Mundt"); | ||
293 | MODULE_DESCRIPTION("low-level driver for platform device ATA"); | ||
294 | MODULE_LICENSE("GPL"); | ||
295 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index 314938dea1fc..36f621abc390 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c | |||
@@ -157,7 +157,6 @@ static struct scsi_host_template qdi_sht = { | |||
157 | .can_queue = ATA_DEF_QUEUE, | 157 | .can_queue = ATA_DEF_QUEUE, |
158 | .this_id = ATA_SHT_THIS_ID, | 158 | .this_id = ATA_SHT_THIS_ID, |
159 | .sg_tablesize = LIBATA_MAX_PRD, | 159 | .sg_tablesize = LIBATA_MAX_PRD, |
160 | .max_sectors = ATA_MAX_SECTORS, | ||
161 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 160 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
162 | .emulated = ATA_SHT_EMULATED, | 161 | .emulated = ATA_SHT_EMULATED, |
163 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 162 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 048c2bb21ef1..065541d034ad 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c | |||
@@ -220,7 +220,6 @@ static struct scsi_host_template radisys_sht = { | |||
220 | .can_queue = ATA_DEF_QUEUE, | 220 | .can_queue = ATA_DEF_QUEUE, |
221 | .this_id = ATA_SHT_THIS_ID, | 221 | .this_id = ATA_SHT_THIS_ID, |
222 | .sg_tablesize = LIBATA_MAX_PRD, | 222 | .sg_tablesize = LIBATA_MAX_PRD, |
223 | .max_sectors = ATA_MAX_SECTORS, | ||
224 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 223 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
225 | .emulated = ATA_SHT_EMULATED, | 224 | .emulated = ATA_SHT_EMULATED, |
226 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 225 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -229,6 +228,8 @@ static struct scsi_host_template radisys_sht = { | |||
229 | .slave_configure = ata_scsi_slave_config, | 228 | .slave_configure = ata_scsi_slave_config, |
230 | .slave_destroy = ata_scsi_slave_destroy, | 229 | .slave_destroy = ata_scsi_slave_destroy, |
231 | .bios_param = ata_std_bios_param, | 230 | .bios_param = ata_std_bios_param, |
231 | .resume = ata_scsi_device_resume, | ||
232 | .suspend = ata_scsi_device_suspend, | ||
232 | }; | 233 | }; |
233 | 234 | ||
234 | static const struct ata_port_operations radisys_pata_ops = { | 235 | static const struct ata_port_operations radisys_pata_ops = { |
@@ -311,6 +312,8 @@ static struct pci_driver radisys_pci_driver = { | |||
311 | .id_table = radisys_pci_tbl, | 312 | .id_table = radisys_pci_tbl, |
312 | .probe = radisys_init_one, | 313 | .probe = radisys_init_one, |
313 | .remove = ata_pci_remove_one, | 314 | .remove = ata_pci_remove_one, |
315 | .suspend = ata_pci_device_suspend, | ||
316 | .resume = ata_pci_device_resume, | ||
314 | }; | 317 | }; |
315 | 318 | ||
316 | static int __init radisys_init(void) | 319 | static int __init radisys_init(void) |
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index e4e5ea423fef..3677c642c9f9 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/libata.h> | 21 | #include <linux/libata.h> |
22 | 22 | ||
23 | #define DRV_NAME "pata_rz1000" | 23 | #define DRV_NAME "pata_rz1000" |
24 | #define DRV_VERSION "0.2.2" | 24 | #define DRV_VERSION "0.2.3" |
25 | 25 | ||
26 | 26 | ||
27 | /** | 27 | /** |
@@ -83,7 +83,6 @@ static struct scsi_host_template rz1000_sht = { | |||
83 | .can_queue = ATA_DEF_QUEUE, | 83 | .can_queue = ATA_DEF_QUEUE, |
84 | .this_id = ATA_SHT_THIS_ID, | 84 | .this_id = ATA_SHT_THIS_ID, |
85 | .sg_tablesize = LIBATA_MAX_PRD, | 85 | .sg_tablesize = LIBATA_MAX_PRD, |
86 | .max_sectors = ATA_MAX_SECTORS, | ||
87 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 86 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
88 | .emulated = ATA_SHT_EMULATED, | 87 | .emulated = ATA_SHT_EMULATED, |
89 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 88 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -92,6 +91,8 @@ static struct scsi_host_template rz1000_sht = { | |||
92 | .slave_configure = ata_scsi_slave_config, | 91 | .slave_configure = ata_scsi_slave_config, |
93 | .slave_destroy = ata_scsi_slave_destroy, | 92 | .slave_destroy = ata_scsi_slave_destroy, |
94 | .bios_param = ata_std_bios_param, | 93 | .bios_param = ata_std_bios_param, |
94 | .resume = ata_scsi_device_resume, | ||
95 | .suspend = ata_scsi_device_suspend, | ||
95 | }; | 96 | }; |
96 | 97 | ||
97 | static struct ata_port_operations rz1000_port_ops = { | 98 | static struct ata_port_operations rz1000_port_ops = { |
@@ -129,6 +130,19 @@ static struct ata_port_operations rz1000_port_ops = { | |||
129 | .host_stop = ata_host_stop | 130 | .host_stop = ata_host_stop |
130 | }; | 131 | }; |
131 | 132 | ||
133 | static int rz1000_fifo_disable(struct pci_dev *pdev) | ||
134 | { | ||
135 | u16 reg; | ||
136 | /* Be exceptionally paranoid as we must be sure to apply the fix */ | ||
137 | if (pci_read_config_word(pdev, 0x40, ®) != 0) | ||
138 | return -1; | ||
139 | reg &= 0xDFFF; | ||
140 | if (pci_write_config_word(pdev, 0x40, reg) != 0) | ||
141 | return -1; | ||
142 | printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
132 | /** | 146 | /** |
133 | * rz1000_init_one - Register RZ1000 ATA PCI device with kernel services | 147 | * rz1000_init_one - Register RZ1000 ATA PCI device with kernel services |
134 | * @pdev: PCI device to register | 148 | * @pdev: PCI device to register |
@@ -143,7 +157,6 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en | |||
143 | { | 157 | { |
144 | static int printed_version; | 158 | static int printed_version; |
145 | struct ata_port_info *port_info[2]; | 159 | struct ata_port_info *port_info[2]; |
146 | u16 reg; | ||
147 | static struct ata_port_info info = { | 160 | static struct ata_port_info info = { |
148 | .sht = &rz1000_sht, | 161 | .sht = &rz1000_sht, |
149 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 162 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, |
@@ -154,23 +167,25 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en | |||
154 | if (!printed_version++) | 167 | if (!printed_version++) |
155 | printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); | 168 | printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); |
156 | 169 | ||
157 | /* Be exceptionally paranoid as we must be sure to apply the fix */ | 170 | if (rz1000_fifo_disable(pdev) == 0) { |
158 | if (pci_read_config_word(pdev, 0x40, ®) != 0) | 171 | port_info[0] = &info; |
159 | goto fail; | 172 | port_info[1] = &info; |
160 | reg &= 0xDFFF; | 173 | return ata_pci_init_one(pdev, port_info, 2); |
161 | if (pci_write_config_word(pdev, 0x40, reg) != 0) | 174 | } |
162 | goto fail; | ||
163 | printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); | ||
164 | |||
165 | port_info[0] = &info; | ||
166 | port_info[1] = &info; | ||
167 | return ata_pci_init_one(pdev, port_info, 2); | ||
168 | fail: | ||
169 | printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); | 175 | printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); |
170 | /* Not safe to use so skip */ | 176 | /* Not safe to use so skip */ |
171 | return -ENODEV; | 177 | return -ENODEV; |
172 | } | 178 | } |
173 | 179 | ||
180 | static int rz1000_reinit_one(struct pci_dev *pdev) | ||
181 | { | ||
182 | /* If this fails on resume (which is a "cant happen" case), we | ||
183 | must stop as any progress risks data loss */ | ||
184 | if (rz1000_fifo_disable(pdev)) | ||
185 | panic("rz1000 fifo"); | ||
186 | return ata_pci_device_resume(pdev); | ||
187 | } | ||
188 | |||
174 | static const struct pci_device_id pata_rz1000[] = { | 189 | static const struct pci_device_id pata_rz1000[] = { |
175 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, | 190 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, |
176 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), }, | 191 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), }, |
@@ -182,7 +197,9 @@ static struct pci_driver rz1000_pci_driver = { | |||
182 | .name = DRV_NAME, | 197 | .name = DRV_NAME, |
183 | .id_table = pata_rz1000, | 198 | .id_table = pata_rz1000, |
184 | .probe = rz1000_init_one, | 199 | .probe = rz1000_init_one, |
185 | .remove = ata_pci_remove_one | 200 | .remove = ata_pci_remove_one, |
201 | .suspend = ata_pci_device_suspend, | ||
202 | .resume = rz1000_reinit_one, | ||
186 | }; | 203 | }; |
187 | 204 | ||
188 | static int __init rz1000_init(void) | 205 | static int __init rz1000_init(void) |
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 0c75dae74764..a3b35bc50394 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/libata.h> | 40 | #include <linux/libata.h> |
41 | 41 | ||
42 | #define DRV_NAME "sc1200" | 42 | #define DRV_NAME "sc1200" |
43 | #define DRV_VERSION "0.2.3" | 43 | #define DRV_VERSION "0.2.4" |
44 | 44 | ||
45 | #define SC1200_REV_A 0x00 | 45 | #define SC1200_REV_A 0x00 |
46 | #define SC1200_REV_B1 0x01 | 46 | #define SC1200_REV_B1 0x01 |
@@ -186,7 +186,6 @@ static struct scsi_host_template sc1200_sht = { | |||
186 | .can_queue = ATA_DEF_QUEUE, | 186 | .can_queue = ATA_DEF_QUEUE, |
187 | .this_id = ATA_SHT_THIS_ID, | 187 | .this_id = ATA_SHT_THIS_ID, |
188 | .sg_tablesize = LIBATA_MAX_PRD, | 188 | .sg_tablesize = LIBATA_MAX_PRD, |
189 | .max_sectors = ATA_MAX_SECTORS, | ||
190 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 189 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
191 | .emulated = ATA_SHT_EMULATED, | 190 | .emulated = ATA_SHT_EMULATED, |
192 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 191 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -195,6 +194,8 @@ static struct scsi_host_template sc1200_sht = { | |||
195 | .slave_configure = ata_scsi_slave_config, | 194 | .slave_configure = ata_scsi_slave_config, |
196 | .slave_destroy = ata_scsi_slave_destroy, | 195 | .slave_destroy = ata_scsi_slave_destroy, |
197 | .bios_param = ata_std_bios_param, | 196 | .bios_param = ata_std_bios_param, |
197 | .resume = ata_scsi_device_resume, | ||
198 | .suspend = ata_scsi_device_suspend, | ||
198 | }; | 199 | }; |
199 | 200 | ||
200 | static struct ata_port_operations sc1200_port_ops = { | 201 | static struct ata_port_operations sc1200_port_ops = { |
@@ -264,7 +265,9 @@ static struct pci_driver sc1200_pci_driver = { | |||
264 | .name = DRV_NAME, | 265 | .name = DRV_NAME, |
265 | .id_table = sc1200, | 266 | .id_table = sc1200, |
266 | .probe = sc1200_init_one, | 267 | .probe = sc1200_init_one, |
267 | .remove = ata_pci_remove_one | 268 | .remove = ata_pci_remove_one, |
269 | .suspend = ata_pci_device_suspend, | ||
270 | .resume = ata_pci_device_resume, | ||
268 | }; | 271 | }; |
269 | 272 | ||
270 | static int __init sc1200_init(void) | 273 | static int __init sc1200_init(void) |
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index be7f60efcb61..f02b6a3b0f10 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <linux/libata.h> | 41 | #include <linux/libata.h> |
42 | 42 | ||
43 | #define DRV_NAME "pata_serverworks" | 43 | #define DRV_NAME "pata_serverworks" |
44 | #define DRV_VERSION "0.3.7" | 44 | #define DRV_VERSION "0.3.9" |
45 | 45 | ||
46 | #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ | 46 | #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ |
47 | #define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ | 47 | #define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ |
@@ -318,7 +318,6 @@ static struct scsi_host_template serverworks_sht = { | |||
318 | .can_queue = ATA_DEF_QUEUE, | 318 | .can_queue = ATA_DEF_QUEUE, |
319 | .this_id = ATA_SHT_THIS_ID, | 319 | .this_id = ATA_SHT_THIS_ID, |
320 | .sg_tablesize = LIBATA_MAX_PRD, | 320 | .sg_tablesize = LIBATA_MAX_PRD, |
321 | .max_sectors = ATA_MAX_SECTORS, | ||
322 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 321 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
323 | .emulated = ATA_SHT_EMULATED, | 322 | .emulated = ATA_SHT_EMULATED, |
324 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 323 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -327,6 +326,8 @@ static struct scsi_host_template serverworks_sht = { | |||
327 | .slave_configure = ata_scsi_slave_config, | 326 | .slave_configure = ata_scsi_slave_config, |
328 | .slave_destroy = ata_scsi_slave_destroy, | 327 | .slave_destroy = ata_scsi_slave_destroy, |
329 | .bios_param = ata_std_bios_param, | 328 | .bios_param = ata_std_bios_param, |
329 | .resume = ata_scsi_device_resume, | ||
330 | .suspend = ata_scsi_device_suspend, | ||
330 | }; | 331 | }; |
331 | 332 | ||
332 | static struct ata_port_operations serverworks_osb4_port_ops = { | 333 | static struct ata_port_operations serverworks_osb4_port_ops = { |
@@ -554,6 +555,30 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id | |||
554 | return ata_pci_init_one(pdev, port_info, ports); | 555 | return ata_pci_init_one(pdev, port_info, ports); |
555 | } | 556 | } |
556 | 557 | ||
558 | static int serverworks_reinit_one(struct pci_dev *pdev) | ||
559 | { | ||
560 | /* Force master latency timer to 64 PCI clocks */ | ||
561 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); | ||
562 | |||
563 | switch (pdev->device) | ||
564 | { | ||
565 | case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: | ||
566 | serverworks_fixup_osb4(pdev); | ||
567 | break; | ||
568 | case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: | ||
569 | ata_pci_clear_simplex(pdev); | ||
570 | /* fall through */ | ||
571 | case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: | ||
572 | case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: | ||
573 | serverworks_fixup_csb(pdev); | ||
574 | break; | ||
575 | case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: | ||
576 | serverworks_fixup_ht1000(pdev); | ||
577 | break; | ||
578 | } | ||
579 | return ata_pci_device_resume(pdev); | ||
580 | } | ||
581 | |||
557 | static const struct pci_device_id serverworks[] = { | 582 | static const struct pci_device_id serverworks[] = { |
558 | { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0}, | 583 | { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0}, |
559 | { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 2}, | 584 | { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 2}, |
@@ -568,7 +593,9 @@ static struct pci_driver serverworks_pci_driver = { | |||
568 | .name = DRV_NAME, | 593 | .name = DRV_NAME, |
569 | .id_table = serverworks, | 594 | .id_table = serverworks, |
570 | .probe = serverworks_init_one, | 595 | .probe = serverworks_init_one, |
571 | .remove = ata_pci_remove_one | 596 | .remove = ata_pci_remove_one, |
597 | .suspend = ata_pci_device_suspend, | ||
598 | .resume = serverworks_reinit_one, | ||
572 | }; | 599 | }; |
573 | 600 | ||
574 | static int __init serverworks_init(void) | 601 | static int __init serverworks_init(void) |
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 11942fd03b55..32cf0bfa8921 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/libata.h> | 33 | #include <linux/libata.h> |
34 | 34 | ||
35 | #define DRV_NAME "pata_sil680" | 35 | #define DRV_NAME "pata_sil680" |
36 | #define DRV_VERSION "0.3.2" | 36 | #define DRV_VERSION "0.4.1" |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * sil680_selreg - return register base | 39 | * sil680_selreg - return register base |
@@ -218,7 +218,6 @@ static struct scsi_host_template sil680_sht = { | |||
218 | .can_queue = ATA_DEF_QUEUE, | 218 | .can_queue = ATA_DEF_QUEUE, |
219 | .this_id = ATA_SHT_THIS_ID, | 219 | .this_id = ATA_SHT_THIS_ID, |
220 | .sg_tablesize = LIBATA_MAX_PRD, | 220 | .sg_tablesize = LIBATA_MAX_PRD, |
221 | .max_sectors = ATA_MAX_SECTORS, | ||
222 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 221 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
223 | .emulated = ATA_SHT_EMULATED, | 222 | .emulated = ATA_SHT_EMULATED, |
224 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 223 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -263,32 +262,20 @@ static struct ata_port_operations sil680_port_ops = { | |||
263 | .host_stop = ata_host_stop | 262 | .host_stop = ata_host_stop |
264 | }; | 263 | }; |
265 | 264 | ||
266 | static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 265 | /** |
266 | * sil680_init_chip - chip setup | ||
267 | * @pdev: PCI device | ||
268 | * | ||
269 | * Perform all the chip setup which must be done both when the device | ||
270 | * is powered up on boot and when we resume in case we resumed from RAM. | ||
271 | * Returns the final clock settings. | ||
272 | */ | ||
273 | |||
274 | static u8 sil680_init_chip(struct pci_dev *pdev) | ||
267 | { | 275 | { |
268 | static struct ata_port_info info = { | ||
269 | .sht = &sil680_sht, | ||
270 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | ||
271 | .pio_mask = 0x1f, | ||
272 | .mwdma_mask = 0x07, | ||
273 | .udma_mask = 0x7f, | ||
274 | .port_ops = &sil680_port_ops | ||
275 | }; | ||
276 | static struct ata_port_info info_slow = { | ||
277 | .sht = &sil680_sht, | ||
278 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | ||
279 | .pio_mask = 0x1f, | ||
280 | .mwdma_mask = 0x07, | ||
281 | .udma_mask = 0x3f, | ||
282 | .port_ops = &sil680_port_ops | ||
283 | }; | ||
284 | static struct ata_port_info *port_info[2] = {&info, &info}; | ||
285 | static int printed_version; | ||
286 | u32 class_rev = 0; | 276 | u32 class_rev = 0; |
287 | u8 tmpbyte = 0; | 277 | u8 tmpbyte = 0; |
288 | 278 | ||
289 | if (!printed_version++) | ||
290 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | ||
291 | |||
292 | pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); | 279 | pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); |
293 | class_rev &= 0xff; | 280 | class_rev &= 0xff; |
294 | /* FIXME: double check */ | 281 | /* FIXME: double check */ |
@@ -323,8 +310,6 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
323 | pci_read_config_byte(pdev, 0x8A, &tmpbyte); | 310 | pci_read_config_byte(pdev, 0x8A, &tmpbyte); |
324 | printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", | 311 | printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", |
325 | tmpbyte & 1, tmpbyte & 0x30); | 312 | tmpbyte & 1, tmpbyte & 0x30); |
326 | if ((tmpbyte & 0x30) == 0) | ||
327 | port_info[0] = port_info[1] = &info_slow; | ||
328 | 313 | ||
329 | pci_write_config_byte(pdev, 0xA1, 0x72); | 314 | pci_write_config_byte(pdev, 0xA1, 0x72); |
330 | pci_write_config_word(pdev, 0xA2, 0x328A); | 315 | pci_write_config_word(pdev, 0xA2, 0x328A); |
@@ -343,11 +328,51 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
343 | case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break; | 328 | case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break; |
344 | /* This last case is _NOT_ ok */ | 329 | /* This last case is _NOT_ ok */ |
345 | case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n"); | 330 | case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n"); |
346 | return -EIO; | 331 | } |
332 | return tmpbyte & 0x30; | ||
333 | } | ||
334 | |||
335 | static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | ||
336 | { | ||
337 | static struct ata_port_info info = { | ||
338 | .sht = &sil680_sht, | ||
339 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | ||
340 | .pio_mask = 0x1f, | ||
341 | .mwdma_mask = 0x07, | ||
342 | .udma_mask = 0x7f, | ||
343 | .port_ops = &sil680_port_ops | ||
344 | }; | ||
345 | static struct ata_port_info info_slow = { | ||
346 | .sht = &sil680_sht, | ||
347 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | ||
348 | .pio_mask = 0x1f, | ||
349 | .mwdma_mask = 0x07, | ||
350 | .udma_mask = 0x3f, | ||
351 | .port_ops = &sil680_port_ops | ||
352 | }; | ||
353 | static struct ata_port_info *port_info[2] = {&info, &info}; | ||
354 | static int printed_version; | ||
355 | |||
356 | if (!printed_version++) | ||
357 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | ||
358 | |||
359 | switch(sil680_init_chip(pdev)) | ||
360 | { | ||
361 | case 0: | ||
362 | port_info[0] = port_info[1] = &info_slow; | ||
363 | break; | ||
364 | case 0x30: | ||
365 | return -ENODEV; | ||
347 | } | 366 | } |
348 | return ata_pci_init_one(pdev, port_info, 2); | 367 | return ata_pci_init_one(pdev, port_info, 2); |
349 | } | 368 | } |
350 | 369 | ||
370 | static int sil680_reinit_one(struct pci_dev *pdev) | ||
371 | { | ||
372 | sil680_init_chip(pdev); | ||
373 | return ata_pci_device_resume(pdev); | ||
374 | } | ||
375 | |||
351 | static const struct pci_device_id sil680[] = { | 376 | static const struct pci_device_id sil680[] = { |
352 | { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), }, | 377 | { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), }, |
353 | 378 | ||
@@ -358,7 +383,9 @@ static struct pci_driver sil680_pci_driver = { | |||
358 | .name = DRV_NAME, | 383 | .name = DRV_NAME, |
359 | .id_table = sil680, | 384 | .id_table = sil680, |
360 | .probe = sil680_init_one, | 385 | .probe = sil680_init_one, |
361 | .remove = ata_pci_remove_one | 386 | .remove = ata_pci_remove_one, |
387 | .suspend = ata_pci_device_suspend, | ||
388 | .resume = sil680_reinit_one, | ||
362 | }; | 389 | }; |
363 | 390 | ||
364 | static int __init sil680_init(void) | 391 | static int __init sil680_init(void) |
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 91e85f90941d..916cedb3d755 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/ata.h> | 34 | #include <linux/ata.h> |
35 | 35 | ||
36 | #define DRV_NAME "pata_sis" | 36 | #define DRV_NAME "pata_sis" |
37 | #define DRV_VERSION "0.4.4" | 37 | #define DRV_VERSION "0.4.5" |
38 | 38 | ||
39 | struct sis_chipset { | 39 | struct sis_chipset { |
40 | u16 device; /* PCI host ID */ | 40 | u16 device; /* PCI host ID */ |
@@ -538,7 +538,6 @@ static struct scsi_host_template sis_sht = { | |||
538 | .can_queue = ATA_DEF_QUEUE, | 538 | .can_queue = ATA_DEF_QUEUE, |
539 | .this_id = ATA_SHT_THIS_ID, | 539 | .this_id = ATA_SHT_THIS_ID, |
540 | .sg_tablesize = LIBATA_MAX_PRD, | 540 | .sg_tablesize = LIBATA_MAX_PRD, |
541 | .max_sectors = ATA_MAX_SECTORS, | ||
542 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 541 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
543 | .emulated = ATA_SHT_EMULATED, | 542 | .emulated = ATA_SHT_EMULATED, |
544 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 543 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -547,6 +546,8 @@ static struct scsi_host_template sis_sht = { | |||
547 | .slave_configure = ata_scsi_slave_config, | 546 | .slave_configure = ata_scsi_slave_config, |
548 | .slave_destroy = ata_scsi_slave_destroy, | 547 | .slave_destroy = ata_scsi_slave_destroy, |
549 | .bios_param = ata_std_bios_param, | 548 | .bios_param = ata_std_bios_param, |
549 | .resume = ata_scsi_device_resume, | ||
550 | .suspend = ata_scsi_device_suspend, | ||
550 | }; | 551 | }; |
551 | 552 | ||
552 | static const struct ata_port_operations sis_133_ops = { | 553 | static const struct ata_port_operations sis_133_ops = { |
@@ -1000,6 +1001,8 @@ static struct pci_driver sis_pci_driver = { | |||
1000 | .id_table = sis_pci_tbl, | 1001 | .id_table = sis_pci_tbl, |
1001 | .probe = sis_init_one, | 1002 | .probe = sis_init_one, |
1002 | .remove = ata_pci_remove_one, | 1003 | .remove = ata_pci_remove_one, |
1004 | .suspend = ata_pci_device_suspend, | ||
1005 | .resume = ata_pci_device_resume, | ||
1003 | }; | 1006 | }; |
1004 | 1007 | ||
1005 | static int __init sis_init(void) | 1008 | static int __init sis_init(void) |
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index dc1cfc6d805b..e94f515ef54b 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c | |||
@@ -230,7 +230,6 @@ static struct scsi_host_template sl82c105_sht = { | |||
230 | .can_queue = ATA_DEF_QUEUE, | 230 | .can_queue = ATA_DEF_QUEUE, |
231 | .this_id = ATA_SHT_THIS_ID, | 231 | .this_id = ATA_SHT_THIS_ID, |
232 | .sg_tablesize = LIBATA_MAX_PRD, | 232 | .sg_tablesize = LIBATA_MAX_PRD, |
233 | .max_sectors = ATA_MAX_SECTORS, | ||
234 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 233 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
235 | .emulated = ATA_SHT_EMULATED, | 234 | .emulated = ATA_SHT_EMULATED, |
236 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 235 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index bfda1f7e760a..a142971f1307 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #include <linux/libata.h> | 43 | #include <linux/libata.h> |
44 | 44 | ||
45 | #define DRV_NAME "pata_triflex" | 45 | #define DRV_NAME "pata_triflex" |
46 | #define DRV_VERSION "0.2.5" | 46 | #define DRV_VERSION "0.2.7" |
47 | 47 | ||
48 | /** | 48 | /** |
49 | * triflex_prereset - probe begin | 49 | * triflex_prereset - probe begin |
@@ -185,7 +185,6 @@ static struct scsi_host_template triflex_sht = { | |||
185 | .can_queue = ATA_DEF_QUEUE, | 185 | .can_queue = ATA_DEF_QUEUE, |
186 | .this_id = ATA_SHT_THIS_ID, | 186 | .this_id = ATA_SHT_THIS_ID, |
187 | .sg_tablesize = LIBATA_MAX_PRD, | 187 | .sg_tablesize = LIBATA_MAX_PRD, |
188 | .max_sectors = ATA_MAX_SECTORS, | ||
189 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 188 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
190 | .emulated = ATA_SHT_EMULATED, | 189 | .emulated = ATA_SHT_EMULATED, |
191 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 190 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -194,6 +193,8 @@ static struct scsi_host_template triflex_sht = { | |||
194 | .slave_configure = ata_scsi_slave_config, | 193 | .slave_configure = ata_scsi_slave_config, |
195 | .slave_destroy = ata_scsi_slave_destroy, | 194 | .slave_destroy = ata_scsi_slave_destroy, |
196 | .bios_param = ata_std_bios_param, | 195 | .bios_param = ata_std_bios_param, |
196 | .resume = ata_scsi_device_resume, | ||
197 | .suspend = ata_scsi_device_suspend, | ||
197 | }; | 198 | }; |
198 | 199 | ||
199 | static struct ata_port_operations triflex_port_ops = { | 200 | static struct ata_port_operations triflex_port_ops = { |
@@ -258,7 +259,9 @@ static struct pci_driver triflex_pci_driver = { | |||
258 | .name = DRV_NAME, | 259 | .name = DRV_NAME, |
259 | .id_table = triflex, | 260 | .id_table = triflex, |
260 | .probe = triflex_init_one, | 261 | .probe = triflex_init_one, |
261 | .remove = ata_pci_remove_one | 262 | .remove = ata_pci_remove_one, |
263 | .suspend = ata_pci_device_suspend, | ||
264 | .resume = ata_pci_device_resume, | ||
262 | }; | 265 | }; |
263 | 266 | ||
264 | static int __init triflex_init(void) | 267 | static int __init triflex_init(void) |
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index c5f1616d224d..cc09d47fb927 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * VIA VT8233c - UDMA100 | 23 | * VIA VT8233c - UDMA100 |
24 | * VIA VT8235 - UDMA133 | 24 | * VIA VT8235 - UDMA133 |
25 | * VIA VT8237 - UDMA133 | 25 | * VIA VT8237 - UDMA133 |
26 | * VIA VT8251 - UDMA133 | ||
26 | * | 27 | * |
27 | * Most registers remain compatible across chips. Others start reserved | 28 | * Most registers remain compatible across chips. Others start reserved |
28 | * and acquire sensible semantics if set to 1 (eg cable detect). A few | 29 | * and acquire sensible semantics if set to 1 (eg cable detect). A few |
@@ -60,7 +61,7 @@ | |||
60 | #include <linux/libata.h> | 61 | #include <linux/libata.h> |
61 | 62 | ||
62 | #define DRV_NAME "pata_via" | 63 | #define DRV_NAME "pata_via" |
63 | #define DRV_VERSION "0.1.14" | 64 | #define DRV_VERSION "0.2.0" |
64 | 65 | ||
65 | /* | 66 | /* |
66 | * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx | 67 | * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx |
@@ -94,6 +95,7 @@ static const struct via_isa_bridge { | |||
94 | u8 rev_max; | 95 | u8 rev_max; |
95 | u16 flags; | 96 | u16 flags; |
96 | } via_isa_bridges[] = { | 97 | } via_isa_bridges[] = { |
98 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | ||
97 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 99 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
98 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES}, | 100 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES}, |
99 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 101 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
@@ -288,7 +290,6 @@ static struct scsi_host_template via_sht = { | |||
288 | .can_queue = ATA_DEF_QUEUE, | 290 | .can_queue = ATA_DEF_QUEUE, |
289 | .this_id = ATA_SHT_THIS_ID, | 291 | .this_id = ATA_SHT_THIS_ID, |
290 | .sg_tablesize = LIBATA_MAX_PRD, | 292 | .sg_tablesize = LIBATA_MAX_PRD, |
291 | .max_sectors = ATA_MAX_SECTORS, | ||
292 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 293 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
293 | .emulated = ATA_SHT_EMULATED, | 294 | .emulated = ATA_SHT_EMULATED, |
294 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 295 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -297,6 +298,8 @@ static struct scsi_host_template via_sht = { | |||
297 | .slave_configure = ata_scsi_slave_config, | 298 | .slave_configure = ata_scsi_slave_config, |
298 | .slave_destroy = ata_scsi_slave_destroy, | 299 | .slave_destroy = ata_scsi_slave_destroy, |
299 | .bios_param = ata_std_bios_param, | 300 | .bios_param = ata_std_bios_param, |
301 | .resume = ata_scsi_device_resume, | ||
302 | .suspend = ata_scsi_device_suspend, | ||
300 | }; | 303 | }; |
301 | 304 | ||
302 | static struct ata_port_operations via_port_ops = { | 305 | static struct ata_port_operations via_port_ops = { |
@@ -370,8 +373,42 @@ static struct ata_port_operations via_port_ops_noirq = { | |||
370 | }; | 373 | }; |
371 | 374 | ||
372 | /** | 375 | /** |
376 | * via_config_fifo - set up the FIFO | ||
377 | * @pdev: PCI device | ||
378 | * @flags: configuration flags | ||
379 | * | ||
380 | * Set the FIFO properties for this device if neccessary. Used both on | ||
381 | * set up and on and the resume path | ||
382 | */ | ||
383 | |||
384 | static void via_config_fifo(struct pci_dev *pdev, unsigned int flags) | ||
385 | { | ||
386 | u8 enable; | ||
387 | |||
388 | /* 0x40 low bits indicate enabled channels */ | ||
389 | pci_read_config_byte(pdev, 0x40 , &enable); | ||
390 | enable &= 3; | ||
391 | |||
392 | if (flags & VIA_SET_FIFO) { | ||
393 | u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; | ||
394 | u8 fifo; | ||
395 | |||
396 | pci_read_config_byte(pdev, 0x43, &fifo); | ||
397 | |||
398 | /* Clear PREQ# until DDACK# for errata */ | ||
399 | if (flags & VIA_BAD_PREQ) | ||
400 | fifo &= 0x7F; | ||
401 | else | ||
402 | fifo &= 0x9f; | ||
403 | /* Turn on FIFO for enabled channels */ | ||
404 | fifo |= fifo_setting[enable]; | ||
405 | pci_write_config_byte(pdev, 0x43, fifo); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | /** | ||
373 | * via_init_one - discovery callback | 410 | * via_init_one - discovery callback |
374 | * @pdev: PCI device ID | 411 | * @pdev: PCI device |
375 | * @id: PCI table info | 412 | * @id: PCI table info |
376 | * | 413 | * |
377 | * A VIA IDE interface has been discovered. Figure out what revision | 414 | * A VIA IDE interface has been discovered. Figure out what revision |
@@ -383,7 +420,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
383 | /* Early VIA without UDMA support */ | 420 | /* Early VIA without UDMA support */ |
384 | static struct ata_port_info via_mwdma_info = { | 421 | static struct ata_port_info via_mwdma_info = { |
385 | .sht = &via_sht, | 422 | .sht = &via_sht, |
386 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 423 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
387 | .pio_mask = 0x1f, | 424 | .pio_mask = 0x1f, |
388 | .mwdma_mask = 0x07, | 425 | .mwdma_mask = 0x07, |
389 | .port_ops = &via_port_ops | 426 | .port_ops = &via_port_ops |
@@ -391,7 +428,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
391 | /* Ditto with IRQ masking required */ | 428 | /* Ditto with IRQ masking required */ |
392 | static struct ata_port_info via_mwdma_info_borked = { | 429 | static struct ata_port_info via_mwdma_info_borked = { |
393 | .sht = &via_sht, | 430 | .sht = &via_sht, |
394 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 431 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
395 | .pio_mask = 0x1f, | 432 | .pio_mask = 0x1f, |
396 | .mwdma_mask = 0x07, | 433 | .mwdma_mask = 0x07, |
397 | .port_ops = &via_port_ops_noirq, | 434 | .port_ops = &via_port_ops_noirq, |
@@ -399,7 +436,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
399 | /* VIA UDMA 33 devices (and borked 66) */ | 436 | /* VIA UDMA 33 devices (and borked 66) */ |
400 | static struct ata_port_info via_udma33_info = { | 437 | static struct ata_port_info via_udma33_info = { |
401 | .sht = &via_sht, | 438 | .sht = &via_sht, |
402 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 439 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
403 | .pio_mask = 0x1f, | 440 | .pio_mask = 0x1f, |
404 | .mwdma_mask = 0x07, | 441 | .mwdma_mask = 0x07, |
405 | .udma_mask = 0x7, | 442 | .udma_mask = 0x7, |
@@ -408,7 +445,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
408 | /* VIA UDMA 66 devices */ | 445 | /* VIA UDMA 66 devices */ |
409 | static struct ata_port_info via_udma66_info = { | 446 | static struct ata_port_info via_udma66_info = { |
410 | .sht = &via_sht, | 447 | .sht = &via_sht, |
411 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 448 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
412 | .pio_mask = 0x1f, | 449 | .pio_mask = 0x1f, |
413 | .mwdma_mask = 0x07, | 450 | .mwdma_mask = 0x07, |
414 | .udma_mask = 0x1f, | 451 | .udma_mask = 0x1f, |
@@ -417,7 +454,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
417 | /* VIA UDMA 100 devices */ | 454 | /* VIA UDMA 100 devices */ |
418 | static struct ata_port_info via_udma100_info = { | 455 | static struct ata_port_info via_udma100_info = { |
419 | .sht = &via_sht, | 456 | .sht = &via_sht, |
420 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 457 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
421 | .pio_mask = 0x1f, | 458 | .pio_mask = 0x1f, |
422 | .mwdma_mask = 0x07, | 459 | .mwdma_mask = 0x07, |
423 | .udma_mask = 0x3f, | 460 | .udma_mask = 0x3f, |
@@ -426,7 +463,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
426 | /* UDMA133 with bad AST (All current 133) */ | 463 | /* UDMA133 with bad AST (All current 133) */ |
427 | static struct ata_port_info via_udma133_info = { | 464 | static struct ata_port_info via_udma133_info = { |
428 | .sht = &via_sht, | 465 | .sht = &via_sht, |
429 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 466 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
430 | .pio_mask = 0x1f, | 467 | .pio_mask = 0x1f, |
431 | .mwdma_mask = 0x07, | 468 | .mwdma_mask = 0x07, |
432 | .udma_mask = 0x7f, /* FIXME: should check north bridge */ | 469 | .udma_mask = 0x7f, /* FIXME: should check north bridge */ |
@@ -471,21 +508,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
471 | } | 508 | } |
472 | 509 | ||
473 | /* Initialise the FIFO for the enabled channels. */ | 510 | /* Initialise the FIFO for the enabled channels. */ |
474 | if (config->flags & VIA_SET_FIFO) { | 511 | via_config_fifo(pdev, config->flags); |
475 | u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; | 512 | |
476 | u8 fifo; | ||
477 | |||
478 | pci_read_config_byte(pdev, 0x43, &fifo); | ||
479 | |||
480 | /* Clear PREQ# until DDACK# for errata */ | ||
481 | if (config->flags & VIA_BAD_PREQ) | ||
482 | fifo &= 0x7F; | ||
483 | else | ||
484 | fifo &= 0x9f; | ||
485 | /* Turn on FIFO for enabled channels */ | ||
486 | fifo |= fifo_setting[enable]; | ||
487 | pci_write_config_byte(pdev, 0x43, fifo); | ||
488 | } | ||
489 | /* Clock set up */ | 513 | /* Clock set up */ |
490 | switch(config->flags & VIA_UDMA) { | 514 | switch(config->flags & VIA_UDMA) { |
491 | case VIA_UDMA_NONE: | 515 | case VIA_UDMA_NONE: |
@@ -529,6 +553,39 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
529 | return ata_pci_init_one(pdev, port_info, 2); | 553 | return ata_pci_init_one(pdev, port_info, 2); |
530 | } | 554 | } |
531 | 555 | ||
556 | /** | ||
557 | * via_reinit_one - reinit after resume | ||
558 | * @pdev; PCI device | ||
559 | * | ||
560 | * Called when the VIA PATA device is resumed. We must then | ||
561 | * reconfigure the fifo and other setup we may have altered. In | ||
562 | * addition the kernel needs to have the resume methods on PCI | ||
563 | * quirk supported. | ||
564 | */ | ||
565 | |||
566 | static int via_reinit_one(struct pci_dev *pdev) | ||
567 | { | ||
568 | u32 timing; | ||
569 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
570 | const struct via_isa_bridge *config = host->private_data; | ||
571 | |||
572 | via_config_fifo(pdev, config->flags); | ||
573 | |||
574 | if ((config->flags & VIA_UDMA) == VIA_UDMA_66) { | ||
575 | /* The 66 MHz devices require we enable the clock */ | ||
576 | pci_read_config_dword(pdev, 0x50, &timing); | ||
577 | timing |= 0x80008; | ||
578 | pci_write_config_dword(pdev, 0x50, timing); | ||
579 | } | ||
580 | if (config->flags & VIA_BAD_CLK66) { | ||
581 | /* Disable the 66MHz clock on problem devices */ | ||
582 | pci_read_config_dword(pdev, 0x50, &timing); | ||
583 | timing &= ~0x80008; | ||
584 | pci_write_config_dword(pdev, 0x50, timing); | ||
585 | } | ||
586 | return ata_pci_device_resume(pdev); | ||
587 | } | ||
588 | |||
532 | static const struct pci_device_id via[] = { | 589 | static const struct pci_device_id via[] = { |
533 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), }, | 590 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), }, |
534 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), }, | 591 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), }, |
@@ -542,7 +599,9 @@ static struct pci_driver via_pci_driver = { | |||
542 | .name = DRV_NAME, | 599 | .name = DRV_NAME, |
543 | .id_table = via, | 600 | .id_table = via, |
544 | .probe = via_init_one, | 601 | .probe = via_init_one, |
545 | .remove = ata_pci_remove_one | 602 | .remove = ata_pci_remove_one, |
603 | .suspend = ata_pci_device_suspend, | ||
604 | .resume = via_reinit_one, | ||
546 | }; | 605 | }; |
547 | 606 | ||
548 | static int __init via_init(void) | 607 | static int __init via_init(void) |
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c new file mode 100644 index 000000000000..3ea345cde52e --- /dev/null +++ b/drivers/ata/pata_winbond.c | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * pata_winbond.c - Winbond VLB ATA controllers | ||
3 | * (C) 2006 Red Hat <alan@redhat.com> | ||
4 | * | ||
5 | * Support for the Winbond 83759A when operating in advanced mode. | ||
6 | * Multichip mode is not currently supported. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/blkdev.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <scsi/scsi_host.h> | ||
16 | #include <linux/libata.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #define DRV_NAME "pata_winbond" | ||
20 | #define DRV_VERSION "0.0.1" | ||
21 | |||
22 | #define NR_HOST 4 /* Two winbond controllers, two channels each */ | ||
23 | |||
24 | struct winbond_data { | ||
25 | unsigned long config; | ||
26 | struct platform_device *platform_dev; | ||
27 | }; | ||
28 | |||
29 | static struct ata_host *winbond_host[NR_HOST]; | ||
30 | static struct winbond_data winbond_data[NR_HOST]; | ||
31 | static int nr_winbond_host; | ||
32 | |||
33 | #ifdef MODULE | ||
34 | static int probe_winbond = 1; | ||
35 | #else | ||
36 | static int probe_winbond; | ||
37 | #endif | ||
38 | |||
39 | static spinlock_t winbond_lock = SPIN_LOCK_UNLOCKED; | ||
40 | |||
41 | static void winbond_writecfg(unsigned long port, u8 reg, u8 val) | ||
42 | { | ||
43 | unsigned long flags; | ||
44 | spin_lock_irqsave(&winbond_lock, flags); | ||
45 | outb(reg, port + 0x01); | ||
46 | outb(val, port + 0x02); | ||
47 | spin_unlock_irqrestore(&winbond_lock, flags); | ||
48 | } | ||
49 | |||
50 | static u8 winbond_readcfg(unsigned long port, u8 reg) | ||
51 | { | ||
52 | u8 val; | ||
53 | |||
54 | unsigned long flags; | ||
55 | spin_lock_irqsave(&winbond_lock, flags); | ||
56 | outb(reg, port + 0x01); | ||
57 | val = inb(port + 0x02); | ||
58 | spin_unlock_irqrestore(&winbond_lock, flags); | ||
59 | |||
60 | return val; | ||
61 | } | ||
62 | |||
63 | static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) | ||
64 | { | ||
65 | struct ata_timing t; | ||
66 | struct winbond_data *winbond = ap->host->private_data; | ||
67 | int active, recovery; | ||
68 | u8 reg; | ||
69 | int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2); | ||
70 | |||
71 | reg = winbond_readcfg(winbond->config, 0x81); | ||
72 | |||
73 | /* Get the timing data in cycles */ | ||
74 | if (reg & 0x40) /* Fast VLB bus, assume 50MHz */ | ||
75 | ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); | ||
76 | else | ||
77 | ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); | ||
78 | |||
79 | active = (FIT(t.active, 3, 17) - 1) & 0x0F; | ||
80 | recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F; | ||
81 | timing = (active << 4) | recovery; | ||
82 | winbond_writecfg(winbond->config, timing, reg); | ||
83 | |||
84 | /* Load the setup timing */ | ||
85 | |||
86 | reg = 0x35; | ||
87 | if (adev->class != ATA_DEV_ATA) | ||
88 | reg |= 0x08; /* FIFO off */ | ||
89 | if (!ata_pio_need_iordy(adev)) | ||
90 | reg |= 0x02; /* IORDY off */ | ||
91 | reg |= (FIT(t.setup, 0, 3) << 6); | ||
92 | winbond_writecfg(winbond->config, timing + 1, reg); | ||
93 | } | ||
94 | |||
95 | |||
96 | static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) | ||
97 | { | ||
98 | struct ata_port *ap = adev->ap; | ||
99 | int slop = buflen & 3; | ||
100 | |||
101 | if (ata_id_has_dword_io(adev->id)) { | ||
102 | if (write_data) | ||
103 | outsl(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
104 | else | ||
105 | insl(ap->ioaddr.data_addr, buf, buflen >> 2); | ||
106 | |||
107 | if (unlikely(slop)) { | ||
108 | u32 pad; | ||
109 | if (write_data) { | ||
110 | memcpy(&pad, buf + buflen - slop, slop); | ||
111 | outl(le32_to_cpu(pad), ap->ioaddr.data_addr); | ||
112 | } else { | ||
113 | pad = cpu_to_le16(inl(ap->ioaddr.data_addr)); | ||
114 | memcpy(buf + buflen - slop, &pad, slop); | ||
115 | } | ||
116 | } | ||
117 | } else | ||
118 | ata_pio_data_xfer(adev, buf, buflen, write_data); | ||
119 | } | ||
120 | |||
121 | static struct scsi_host_template winbond_sht = { | ||
122 | .module = THIS_MODULE, | ||
123 | .name = DRV_NAME, | ||
124 | .ioctl = ata_scsi_ioctl, | ||
125 | .queuecommand = ata_scsi_queuecmd, | ||
126 | .can_queue = ATA_DEF_QUEUE, | ||
127 | .this_id = ATA_SHT_THIS_ID, | ||
128 | .sg_tablesize = LIBATA_MAX_PRD, | ||
129 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
130 | .emulated = ATA_SHT_EMULATED, | ||
131 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
132 | .proc_name = DRV_NAME, | ||
133 | .dma_boundary = ATA_DMA_BOUNDARY, | ||
134 | .slave_configure = ata_scsi_slave_config, | ||
135 | .slave_destroy = ata_scsi_slave_destroy, | ||
136 | .bios_param = ata_std_bios_param, | ||
137 | }; | ||
138 | |||
139 | static struct ata_port_operations winbond_port_ops = { | ||
140 | .port_disable = ata_port_disable, | ||
141 | .set_piomode = winbond_set_piomode, | ||
142 | |||
143 | .tf_load = ata_tf_load, | ||
144 | .tf_read = ata_tf_read, | ||
145 | .check_status = ata_check_status, | ||
146 | .exec_command = ata_exec_command, | ||
147 | .dev_select = ata_std_dev_select, | ||
148 | |||
149 | .freeze = ata_bmdma_freeze, | ||
150 | .thaw = ata_bmdma_thaw, | ||
151 | .error_handler = ata_bmdma_error_handler, | ||
152 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
153 | |||
154 | .qc_prep = ata_qc_prep, | ||
155 | .qc_issue = ata_qc_issue_prot, | ||
156 | |||
157 | .data_xfer = winbond_data_xfer, | ||
158 | |||
159 | .irq_handler = ata_interrupt, | ||
160 | .irq_clear = ata_bmdma_irq_clear, | ||
161 | |||
162 | .port_start = ata_port_start, | ||
163 | .port_stop = ata_port_stop, | ||
164 | .host_stop = ata_host_stop | ||
165 | }; | ||
166 | |||
167 | /** | ||
168 | * winbond_init_one - attach a winbond interface | ||
169 | * @type: Type to display | ||
170 | * @io: I/O port start | ||
171 | * @irq: interrupt line | ||
172 | * @fast: True if on a > 33Mhz VLB | ||
173 | * | ||
174 | * Register a VLB bus IDE interface. Such interfaces are PIO and we | ||
175 | * assume do not support IRQ sharing. | ||
176 | */ | ||
177 | |||
178 | static __init int winbond_init_one(unsigned long port) | ||
179 | { | ||
180 | struct ata_probe_ent ae; | ||
181 | struct platform_device *pdev; | ||
182 | int ret; | ||
183 | u8 reg; | ||
184 | int i; | ||
185 | |||
186 | reg = winbond_readcfg(port, 0x81); | ||
187 | reg |= 0x80; /* jumpered mode off */ | ||
188 | winbond_writecfg(port, 0x81, reg); | ||
189 | reg = winbond_readcfg(port, 0x83); | ||
190 | reg |= 0xF0; /* local control */ | ||
191 | winbond_writecfg(port, 0x83, reg); | ||
192 | reg = winbond_readcfg(port, 0x85); | ||
193 | reg |= 0xF0; /* programmable timing */ | ||
194 | winbond_writecfg(port, 0x85, reg); | ||
195 | |||
196 | reg = winbond_readcfg(port, 0x81); | ||
197 | |||
198 | if (!(reg & 0x03)) /* Disabled */ | ||
199 | return 0; | ||
200 | |||
201 | for (i = 0; i < 2 ; i ++) { | ||
202 | |||
203 | if (reg & (1 << i)) { | ||
204 | /* | ||
205 | * Fill in a probe structure first of all | ||
206 | */ | ||
207 | |||
208 | pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0); | ||
209 | if (pdev == NULL) | ||
210 | return -ENOMEM; | ||
211 | |||
212 | memset(&ae, 0, sizeof(struct ata_probe_ent)); | ||
213 | INIT_LIST_HEAD(&ae.node); | ||
214 | ae.dev = &pdev->dev; | ||
215 | |||
216 | ae.port_ops = &winbond_port_ops; | ||
217 | ae.pio_mask = 0x1F; | ||
218 | |||
219 | ae.sht = &winbond_sht; | ||
220 | |||
221 | ae.n_ports = 1; | ||
222 | ae.irq = 14 + i; | ||
223 | ae.irq_flags = 0; | ||
224 | ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; | ||
225 | ae.port[0].cmd_addr = 0x1F0 - (0x80 * i); | ||
226 | ae.port[0].altstatus_addr = ae.port[0].cmd_addr + 0x0206; | ||
227 | ae.port[0].ctl_addr = ae.port[0].altstatus_addr; | ||
228 | ata_std_ports(&ae.port[0]); | ||
229 | /* | ||
230 | * Hook in a private data structure per channel | ||
231 | */ | ||
232 | ae.private_data = &winbond_data[nr_winbond_host]; | ||
233 | winbond_data[nr_winbond_host].config = port; | ||
234 | winbond_data[nr_winbond_host].platform_dev = pdev; | ||
235 | |||
236 | ret = ata_device_add(&ae); | ||
237 | if (ret == 0) { | ||
238 | platform_device_unregister(pdev); | ||
239 | return -ENODEV; | ||
240 | } | ||
241 | winbond_host[nr_winbond_host++] = dev_get_drvdata(&pdev->dev); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * winbond_init - attach winbond interfaces | ||
250 | * | ||
251 | * Attach winbond IDE interfaces by scanning the ports it may occupy. | ||
252 | */ | ||
253 | |||
254 | static __init int winbond_init(void) | ||
255 | { | ||
256 | static const unsigned long config[2] = { 0x130, 0x1B0 }; | ||
257 | |||
258 | int ct = 0; | ||
259 | int i; | ||
260 | |||
261 | if (probe_winbond == 0) | ||
262 | return -ENODEV; | ||
263 | |||
264 | /* | ||
265 | * Check both base addresses | ||
266 | */ | ||
267 | |||
268 | for (i = 0; i < 2; i++) { | ||
269 | if (probe_winbond & (1<<i)) { | ||
270 | int ret = 0; | ||
271 | unsigned long port = config[i]; | ||
272 | |||
273 | if (request_region(port, 2, "pata_winbond")) { | ||
274 | ret = winbond_init_one(port); | ||
275 | if(ret <= 0) | ||
276 | release_region(port, 2); | ||
277 | else ct+= ret; | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | if (ct != 0) | ||
282 | return 0; | ||
283 | return -ENODEV; | ||
284 | } | ||
285 | |||
286 | static __exit void winbond_exit(void) | ||
287 | { | ||
288 | int i; | ||
289 | |||
290 | for (i = 0; i < nr_winbond_host; i++) { | ||
291 | ata_host_remove(winbond_host[i]); | ||
292 | release_region(winbond_data[i].config, 2); | ||
293 | platform_device_unregister(winbond_data[i].platform_dev); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | MODULE_AUTHOR("Alan Cox"); | ||
298 | MODULE_DESCRIPTION("low-level driver for Winbond VL ATA"); | ||
299 | MODULE_LICENSE("GPL"); | ||
300 | MODULE_VERSION(DRV_VERSION); | ||
301 | |||
302 | module_init(winbond_init); | ||
303 | module_exit(winbond_exit); | ||
304 | |||
305 | module_param(probe_winbond, int, 0); | ||
306 | |||
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index d65ebfd7c7b2..0d316eb3c214 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -29,6 +29,11 @@ | |||
29 | * NV-specific details such as register offsets, SATA phy location, | 29 | * NV-specific details such as register offsets, SATA phy location, |
30 | * hotplug info, etc. | 30 | * hotplug info, etc. |
31 | * | 31 | * |
32 | * CK804/MCP04 controllers support an alternate programming interface | ||
33 | * similar to the ADMA specification (with some modifications). | ||
34 | * This allows the use of NCQ. Non-DMA-mapped ATA commands are still | ||
35 | * sent through the legacy interface. | ||
36 | * | ||
32 | */ | 37 | */ |
33 | 38 | ||
34 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
@@ -40,10 +45,13 @@ | |||
40 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
41 | #include <linux/device.h> | 46 | #include <linux/device.h> |
42 | #include <scsi/scsi_host.h> | 47 | #include <scsi/scsi_host.h> |
48 | #include <scsi/scsi_device.h> | ||
43 | #include <linux/libata.h> | 49 | #include <linux/libata.h> |
44 | 50 | ||
45 | #define DRV_NAME "sata_nv" | 51 | #define DRV_NAME "sata_nv" |
46 | #define DRV_VERSION "2.0" | 52 | #define DRV_VERSION "3.2" |
53 | |||
54 | #define NV_ADMA_DMA_BOUNDARY 0xffffffffUL | ||
47 | 55 | ||
48 | enum { | 56 | enum { |
49 | NV_PORTS = 2, | 57 | NV_PORTS = 2, |
@@ -78,8 +86,138 @@ enum { | |||
78 | // For PCI config register 20 | 86 | // For PCI config register 20 |
79 | NV_MCP_SATA_CFG_20 = 0x50, | 87 | NV_MCP_SATA_CFG_20 = 0x50, |
80 | NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04, | 88 | NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04, |
89 | NV_MCP_SATA_CFG_20_PORT0_EN = (1 << 17), | ||
90 | NV_MCP_SATA_CFG_20_PORT1_EN = (1 << 16), | ||
91 | NV_MCP_SATA_CFG_20_PORT0_PWB_EN = (1 << 14), | ||
92 | NV_MCP_SATA_CFG_20_PORT1_PWB_EN = (1 << 12), | ||
93 | |||
94 | NV_ADMA_MAX_CPBS = 32, | ||
95 | NV_ADMA_CPB_SZ = 128, | ||
96 | NV_ADMA_APRD_SZ = 16, | ||
97 | NV_ADMA_SGTBL_LEN = (1024 - NV_ADMA_CPB_SZ) / | ||
98 | NV_ADMA_APRD_SZ, | ||
99 | NV_ADMA_SGTBL_TOTAL_LEN = NV_ADMA_SGTBL_LEN + 5, | ||
100 | NV_ADMA_SGTBL_SZ = NV_ADMA_SGTBL_LEN * NV_ADMA_APRD_SZ, | ||
101 | NV_ADMA_PORT_PRIV_DMA_SZ = NV_ADMA_MAX_CPBS * | ||
102 | (NV_ADMA_CPB_SZ + NV_ADMA_SGTBL_SZ), | ||
103 | |||
104 | /* BAR5 offset to ADMA general registers */ | ||
105 | NV_ADMA_GEN = 0x400, | ||
106 | NV_ADMA_GEN_CTL = 0x00, | ||
107 | NV_ADMA_NOTIFIER_CLEAR = 0x30, | ||
108 | |||
109 | /* BAR5 offset to ADMA ports */ | ||
110 | NV_ADMA_PORT = 0x480, | ||
111 | |||
112 | /* size of ADMA port register space */ | ||
113 | NV_ADMA_PORT_SIZE = 0x100, | ||
114 | |||
115 | /* ADMA port registers */ | ||
116 | NV_ADMA_CTL = 0x40, | ||
117 | NV_ADMA_CPB_COUNT = 0x42, | ||
118 | NV_ADMA_NEXT_CPB_IDX = 0x43, | ||
119 | NV_ADMA_STAT = 0x44, | ||
120 | NV_ADMA_CPB_BASE_LOW = 0x48, | ||
121 | NV_ADMA_CPB_BASE_HIGH = 0x4C, | ||
122 | NV_ADMA_APPEND = 0x50, | ||
123 | NV_ADMA_NOTIFIER = 0x68, | ||
124 | NV_ADMA_NOTIFIER_ERROR = 0x6C, | ||
125 | |||
126 | /* NV_ADMA_CTL register bits */ | ||
127 | NV_ADMA_CTL_HOTPLUG_IEN = (1 << 0), | ||
128 | NV_ADMA_CTL_CHANNEL_RESET = (1 << 5), | ||
129 | NV_ADMA_CTL_GO = (1 << 7), | ||
130 | NV_ADMA_CTL_AIEN = (1 << 8), | ||
131 | NV_ADMA_CTL_READ_NON_COHERENT = (1 << 11), | ||
132 | NV_ADMA_CTL_WRITE_NON_COHERENT = (1 << 12), | ||
133 | |||
134 | /* CPB response flag bits */ | ||
135 | NV_CPB_RESP_DONE = (1 << 0), | ||
136 | NV_CPB_RESP_ATA_ERR = (1 << 3), | ||
137 | NV_CPB_RESP_CMD_ERR = (1 << 4), | ||
138 | NV_CPB_RESP_CPB_ERR = (1 << 7), | ||
139 | |||
140 | /* CPB control flag bits */ | ||
141 | NV_CPB_CTL_CPB_VALID = (1 << 0), | ||
142 | NV_CPB_CTL_QUEUE = (1 << 1), | ||
143 | NV_CPB_CTL_APRD_VALID = (1 << 2), | ||
144 | NV_CPB_CTL_IEN = (1 << 3), | ||
145 | NV_CPB_CTL_FPDMA = (1 << 4), | ||
146 | |||
147 | /* APRD flags */ | ||
148 | NV_APRD_WRITE = (1 << 1), | ||
149 | NV_APRD_END = (1 << 2), | ||
150 | NV_APRD_CONT = (1 << 3), | ||
151 | |||
152 | /* NV_ADMA_STAT flags */ | ||
153 | NV_ADMA_STAT_TIMEOUT = (1 << 0), | ||
154 | NV_ADMA_STAT_HOTUNPLUG = (1 << 1), | ||
155 | NV_ADMA_STAT_HOTPLUG = (1 << 2), | ||
156 | NV_ADMA_STAT_CPBERR = (1 << 4), | ||
157 | NV_ADMA_STAT_SERROR = (1 << 5), | ||
158 | NV_ADMA_STAT_CMD_COMPLETE = (1 << 6), | ||
159 | NV_ADMA_STAT_IDLE = (1 << 8), | ||
160 | NV_ADMA_STAT_LEGACY = (1 << 9), | ||
161 | NV_ADMA_STAT_STOPPED = (1 << 10), | ||
162 | NV_ADMA_STAT_DONE = (1 << 12), | ||
163 | NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR | | ||
164 | NV_ADMA_STAT_TIMEOUT, | ||
165 | |||
166 | /* port flags */ | ||
167 | NV_ADMA_PORT_REGISTER_MODE = (1 << 0), | ||
168 | NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1), | ||
169 | |||
170 | }; | ||
171 | |||
172 | /* ADMA Physical Region Descriptor - one SG segment */ | ||
173 | struct nv_adma_prd { | ||
174 | __le64 addr; | ||
175 | __le32 len; | ||
176 | u8 flags; | ||
177 | u8 packet_len; | ||
178 | __le16 reserved; | ||
179 | }; | ||
180 | |||
181 | enum nv_adma_regbits { | ||
182 | CMDEND = (1 << 15), /* end of command list */ | ||
183 | WNB = (1 << 14), /* wait-not-BSY */ | ||
184 | IGN = (1 << 13), /* ignore this entry */ | ||
185 | CS1n = (1 << (4 + 8)), /* std. PATA signals follow... */ | ||
186 | DA2 = (1 << (2 + 8)), | ||
187 | DA1 = (1 << (1 + 8)), | ||
188 | DA0 = (1 << (0 + 8)), | ||
189 | }; | ||
190 | |||
191 | /* ADMA Command Parameter Block | ||
192 | The first 5 SG segments are stored inside the Command Parameter Block itself. | ||
193 | If there are more than 5 segments the remainder are stored in a separate | ||
194 | memory area indicated by next_aprd. */ | ||
195 | struct nv_adma_cpb { | ||
196 | u8 resp_flags; /* 0 */ | ||
197 | u8 reserved1; /* 1 */ | ||
198 | u8 ctl_flags; /* 2 */ | ||
199 | /* len is length of taskfile in 64 bit words */ | ||
200 | u8 len; /* 3 */ | ||
201 | u8 tag; /* 4 */ | ||
202 | u8 next_cpb_idx; /* 5 */ | ||
203 | __le16 reserved2; /* 6-7 */ | ||
204 | __le16 tf[12]; /* 8-31 */ | ||
205 | struct nv_adma_prd aprd[5]; /* 32-111 */ | ||
206 | __le64 next_aprd; /* 112-119 */ | ||
207 | __le64 reserved3; /* 120-127 */ | ||
208 | }; | ||
209 | |||
210 | |||
211 | struct nv_adma_port_priv { | ||
212 | struct nv_adma_cpb *cpb; | ||
213 | dma_addr_t cpb_dma; | ||
214 | struct nv_adma_prd *aprd; | ||
215 | dma_addr_t aprd_dma; | ||
216 | u8 flags; | ||
81 | }; | 217 | }; |
82 | 218 | ||
219 | #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) | ||
220 | |||
83 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); | 221 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); |
84 | static void nv_ck804_host_stop(struct ata_host *host); | 222 | static void nv_ck804_host_stop(struct ata_host *host); |
85 | static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); | 223 | static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); |
@@ -93,13 +231,28 @@ static void nv_nf2_thaw(struct ata_port *ap); | |||
93 | static void nv_ck804_freeze(struct ata_port *ap); | 231 | static void nv_ck804_freeze(struct ata_port *ap); |
94 | static void nv_ck804_thaw(struct ata_port *ap); | 232 | static void nv_ck804_thaw(struct ata_port *ap); |
95 | static void nv_error_handler(struct ata_port *ap); | 233 | static void nv_error_handler(struct ata_port *ap); |
234 | static int nv_adma_slave_config(struct scsi_device *sdev); | ||
235 | static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); | ||
236 | static void nv_adma_qc_prep(struct ata_queued_cmd *qc); | ||
237 | static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc); | ||
238 | static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance); | ||
239 | static void nv_adma_irq_clear(struct ata_port *ap); | ||
240 | static int nv_adma_port_start(struct ata_port *ap); | ||
241 | static void nv_adma_port_stop(struct ata_port *ap); | ||
242 | static void nv_adma_error_handler(struct ata_port *ap); | ||
243 | static void nv_adma_host_stop(struct ata_host *host); | ||
244 | static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc); | ||
245 | static void nv_adma_bmdma_start(struct ata_queued_cmd *qc); | ||
246 | static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc); | ||
247 | static u8 nv_adma_bmdma_status(struct ata_port *ap); | ||
96 | 248 | ||
97 | enum nv_host_type | 249 | enum nv_host_type |
98 | { | 250 | { |
99 | GENERIC, | 251 | GENERIC, |
100 | NFORCE2, | 252 | NFORCE2, |
101 | NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ | 253 | NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ |
102 | CK804 | 254 | CK804, |
255 | ADMA | ||
103 | }; | 256 | }; |
104 | 257 | ||
105 | static const struct pci_device_id nv_pci_tbl[] = { | 258 | static const struct pci_device_id nv_pci_tbl[] = { |
@@ -160,6 +313,24 @@ static struct scsi_host_template nv_sht = { | |||
160 | .bios_param = ata_std_bios_param, | 313 | .bios_param = ata_std_bios_param, |
161 | }; | 314 | }; |
162 | 315 | ||
316 | static struct scsi_host_template nv_adma_sht = { | ||
317 | .module = THIS_MODULE, | ||
318 | .name = DRV_NAME, | ||
319 | .ioctl = ata_scsi_ioctl, | ||
320 | .queuecommand = ata_scsi_queuecmd, | ||
321 | .can_queue = NV_ADMA_MAX_CPBS, | ||
322 | .this_id = ATA_SHT_THIS_ID, | ||
323 | .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN, | ||
324 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
325 | .emulated = ATA_SHT_EMULATED, | ||
326 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
327 | .proc_name = DRV_NAME, | ||
328 | .dma_boundary = NV_ADMA_DMA_BOUNDARY, | ||
329 | .slave_configure = nv_adma_slave_config, | ||
330 | .slave_destroy = ata_scsi_slave_destroy, | ||
331 | .bios_param = ata_std_bios_param, | ||
332 | }; | ||
333 | |||
163 | static const struct ata_port_operations nv_generic_ops = { | 334 | static const struct ata_port_operations nv_generic_ops = { |
164 | .port_disable = ata_port_disable, | 335 | .port_disable = ata_port_disable, |
165 | .tf_load = ata_tf_load, | 336 | .tf_load = ata_tf_load, |
@@ -241,11 +412,40 @@ static const struct ata_port_operations nv_ck804_ops = { | |||
241 | .host_stop = nv_ck804_host_stop, | 412 | .host_stop = nv_ck804_host_stop, |
242 | }; | 413 | }; |
243 | 414 | ||
415 | static const struct ata_port_operations nv_adma_ops = { | ||
416 | .port_disable = ata_port_disable, | ||
417 | .tf_load = ata_tf_load, | ||
418 | .tf_read = ata_tf_read, | ||
419 | .check_atapi_dma = nv_adma_check_atapi_dma, | ||
420 | .exec_command = ata_exec_command, | ||
421 | .check_status = ata_check_status, | ||
422 | .dev_select = ata_std_dev_select, | ||
423 | .bmdma_setup = nv_adma_bmdma_setup, | ||
424 | .bmdma_start = nv_adma_bmdma_start, | ||
425 | .bmdma_stop = nv_adma_bmdma_stop, | ||
426 | .bmdma_status = nv_adma_bmdma_status, | ||
427 | .qc_prep = nv_adma_qc_prep, | ||
428 | .qc_issue = nv_adma_qc_issue, | ||
429 | .freeze = nv_ck804_freeze, | ||
430 | .thaw = nv_ck804_thaw, | ||
431 | .error_handler = nv_adma_error_handler, | ||
432 | .post_internal_cmd = nv_adma_bmdma_stop, | ||
433 | .data_xfer = ata_mmio_data_xfer, | ||
434 | .irq_handler = nv_adma_interrupt, | ||
435 | .irq_clear = nv_adma_irq_clear, | ||
436 | .scr_read = nv_scr_read, | ||
437 | .scr_write = nv_scr_write, | ||
438 | .port_start = nv_adma_port_start, | ||
439 | .port_stop = nv_adma_port_stop, | ||
440 | .host_stop = nv_adma_host_stop, | ||
441 | }; | ||
442 | |||
244 | static struct ata_port_info nv_port_info[] = { | 443 | static struct ata_port_info nv_port_info[] = { |
245 | /* generic */ | 444 | /* generic */ |
246 | { | 445 | { |
247 | .sht = &nv_sht, | 446 | .sht = &nv_sht, |
248 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | 447 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
448 | ATA_FLAG_HRST_TO_RESUME, | ||
249 | .pio_mask = NV_PIO_MASK, | 449 | .pio_mask = NV_PIO_MASK, |
250 | .mwdma_mask = NV_MWDMA_MASK, | 450 | .mwdma_mask = NV_MWDMA_MASK, |
251 | .udma_mask = NV_UDMA_MASK, | 451 | .udma_mask = NV_UDMA_MASK, |
@@ -254,7 +454,8 @@ static struct ata_port_info nv_port_info[] = { | |||
254 | /* nforce2/3 */ | 454 | /* nforce2/3 */ |
255 | { | 455 | { |
256 | .sht = &nv_sht, | 456 | .sht = &nv_sht, |
257 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | 457 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
458 | ATA_FLAG_HRST_TO_RESUME, | ||
258 | .pio_mask = NV_PIO_MASK, | 459 | .pio_mask = NV_PIO_MASK, |
259 | .mwdma_mask = NV_MWDMA_MASK, | 460 | .mwdma_mask = NV_MWDMA_MASK, |
260 | .udma_mask = NV_UDMA_MASK, | 461 | .udma_mask = NV_UDMA_MASK, |
@@ -263,12 +464,23 @@ static struct ata_port_info nv_port_info[] = { | |||
263 | /* ck804 */ | 464 | /* ck804 */ |
264 | { | 465 | { |
265 | .sht = &nv_sht, | 466 | .sht = &nv_sht, |
266 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | 467 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
468 | ATA_FLAG_HRST_TO_RESUME, | ||
267 | .pio_mask = NV_PIO_MASK, | 469 | .pio_mask = NV_PIO_MASK, |
268 | .mwdma_mask = NV_MWDMA_MASK, | 470 | .mwdma_mask = NV_MWDMA_MASK, |
269 | .udma_mask = NV_UDMA_MASK, | 471 | .udma_mask = NV_UDMA_MASK, |
270 | .port_ops = &nv_ck804_ops, | 472 | .port_ops = &nv_ck804_ops, |
271 | }, | 473 | }, |
474 | /* ADMA */ | ||
475 | { | ||
476 | .sht = &nv_adma_sht, | ||
477 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | ||
478 | ATA_FLAG_MMIO | ATA_FLAG_NCQ, | ||
479 | .pio_mask = NV_PIO_MASK, | ||
480 | .mwdma_mask = NV_MWDMA_MASK, | ||
481 | .udma_mask = NV_UDMA_MASK, | ||
482 | .port_ops = &nv_adma_ops, | ||
483 | }, | ||
272 | }; | 484 | }; |
273 | 485 | ||
274 | MODULE_AUTHOR("NVIDIA"); | 486 | MODULE_AUTHOR("NVIDIA"); |
@@ -277,37 +489,220 @@ MODULE_LICENSE("GPL"); | |||
277 | MODULE_DEVICE_TABLE(pci, nv_pci_tbl); | 489 | MODULE_DEVICE_TABLE(pci, nv_pci_tbl); |
278 | MODULE_VERSION(DRV_VERSION); | 490 | MODULE_VERSION(DRV_VERSION); |
279 | 491 | ||
280 | static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance) | 492 | static int adma_enabled = 1; |
493 | |||
494 | static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio, | ||
495 | unsigned int port_no) | ||
281 | { | 496 | { |
282 | struct ata_host *host = dev_instance; | 497 | mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE; |
283 | unsigned int i; | 498 | return mmio; |
284 | unsigned int handled = 0; | 499 | } |
285 | unsigned long flags; | ||
286 | 500 | ||
287 | spin_lock_irqsave(&host->lock, flags); | 501 | static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap) |
502 | { | ||
503 | return __nv_adma_ctl_block(ap->host->mmio_base, ap->port_no); | ||
504 | } | ||
288 | 505 | ||
289 | for (i = 0; i < host->n_ports; i++) { | 506 | static inline void __iomem *nv_adma_gen_block(struct ata_port *ap) |
290 | struct ata_port *ap; | 507 | { |
508 | return (ap->host->mmio_base + NV_ADMA_GEN); | ||
509 | } | ||
291 | 510 | ||
292 | ap = host->ports[i]; | 511 | static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap) |
293 | if (ap && | 512 | { |
294 | !(ap->flags & ATA_FLAG_DISABLED)) { | 513 | return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no)); |
295 | struct ata_queued_cmd *qc; | 514 | } |
296 | 515 | ||
297 | qc = ata_qc_from_tag(ap, ap->active_tag); | 516 | static void nv_adma_register_mode(struct ata_port *ap) |
298 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) | 517 | { |
299 | handled += ata_host_intr(ap, qc); | 518 | void __iomem *mmio = nv_adma_ctl_block(ap); |
300 | else | 519 | struct nv_adma_port_priv *pp = ap->private_data; |
301 | // No request pending? Clear interrupt status | 520 | u16 tmp; |
302 | // anyway, in case there's one pending. | 521 | |
303 | ap->ops->check_status(ap); | 522 | if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) |
304 | } | 523 | return; |
524 | |||
525 | tmp = readw(mmio + NV_ADMA_CTL); | ||
526 | writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); | ||
527 | |||
528 | pp->flags |= NV_ADMA_PORT_REGISTER_MODE; | ||
529 | } | ||
530 | |||
531 | static void nv_adma_mode(struct ata_port *ap) | ||
532 | { | ||
533 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
534 | struct nv_adma_port_priv *pp = ap->private_data; | ||
535 | u16 tmp; | ||
305 | 536 | ||
537 | if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) | ||
538 | return; | ||
539 | |||
540 | WARN_ON(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE); | ||
541 | |||
542 | tmp = readw(mmio + NV_ADMA_CTL); | ||
543 | writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); | ||
544 | |||
545 | pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE; | ||
546 | } | ||
547 | |||
548 | static int nv_adma_slave_config(struct scsi_device *sdev) | ||
549 | { | ||
550 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
551 | struct nv_adma_port_priv *pp = ap->private_data; | ||
552 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
553 | u64 bounce_limit; | ||
554 | unsigned long segment_boundary; | ||
555 | unsigned short sg_tablesize; | ||
556 | int rc; | ||
557 | int adma_enable; | ||
558 | u32 current_reg, new_reg, config_mask; | ||
559 | |||
560 | rc = ata_scsi_slave_config(sdev); | ||
561 | |||
562 | if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun) | ||
563 | /* Not a proper libata device, ignore */ | ||
564 | return rc; | ||
565 | |||
566 | if (ap->device[sdev->id].class == ATA_DEV_ATAPI) { | ||
567 | /* | ||
568 | * NVIDIA reports that ADMA mode does not support ATAPI commands. | ||
569 | * Therefore ATAPI commands are sent through the legacy interface. | ||
570 | * However, the legacy interface only supports 32-bit DMA. | ||
571 | * Restrict DMA parameters as required by the legacy interface | ||
572 | * when an ATAPI device is connected. | ||
573 | */ | ||
574 | bounce_limit = ATA_DMA_MASK; | ||
575 | segment_boundary = ATA_DMA_BOUNDARY; | ||
576 | /* Subtract 1 since an extra entry may be needed for padding, see | ||
577 | libata-scsi.c */ | ||
578 | sg_tablesize = LIBATA_MAX_PRD - 1; | ||
579 | |||
580 | /* Since the legacy DMA engine is in use, we need to disable ADMA | ||
581 | on the port. */ | ||
582 | adma_enable = 0; | ||
583 | nv_adma_register_mode(ap); | ||
584 | } | ||
585 | else { | ||
586 | bounce_limit = *ap->dev->dma_mask; | ||
587 | segment_boundary = NV_ADMA_DMA_BOUNDARY; | ||
588 | sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; | ||
589 | adma_enable = 1; | ||
590 | } | ||
591 | |||
592 | pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, ¤t_reg); | ||
593 | |||
594 | if(ap->port_no == 1) | ||
595 | config_mask = NV_MCP_SATA_CFG_20_PORT1_EN | | ||
596 | NV_MCP_SATA_CFG_20_PORT1_PWB_EN; | ||
597 | else | ||
598 | config_mask = NV_MCP_SATA_CFG_20_PORT0_EN | | ||
599 | NV_MCP_SATA_CFG_20_PORT0_PWB_EN; | ||
600 | |||
601 | if(adma_enable) { | ||
602 | new_reg = current_reg | config_mask; | ||
603 | pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE; | ||
604 | } | ||
605 | else { | ||
606 | new_reg = current_reg & ~config_mask; | ||
607 | pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE; | ||
306 | } | 608 | } |
609 | |||
610 | if(current_reg != new_reg) | ||
611 | pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg); | ||
612 | |||
613 | blk_queue_bounce_limit(sdev->request_queue, bounce_limit); | ||
614 | blk_queue_segment_boundary(sdev->request_queue, segment_boundary); | ||
615 | blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize); | ||
616 | ata_port_printk(ap, KERN_INFO, | ||
617 | "bounce limit 0x%llX, segment boundary 0x%lX, hw segs %hu\n", | ||
618 | (unsigned long long)bounce_limit, segment_boundary, sg_tablesize); | ||
619 | return rc; | ||
620 | } | ||
307 | 621 | ||
308 | spin_unlock_irqrestore(&host->lock, flags); | 622 | static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc) |
623 | { | ||
624 | struct nv_adma_port_priv *pp = qc->ap->private_data; | ||
625 | return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE); | ||
626 | } | ||
309 | 627 | ||
310 | return IRQ_RETVAL(handled); | 628 | static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb) |
629 | { | ||
630 | unsigned int idx = 0; | ||
631 | |||
632 | cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device | WNB); | ||
633 | |||
634 | if ((tf->flags & ATA_TFLAG_LBA48) == 0) { | ||
635 | cpb[idx++] = cpu_to_le16(IGN); | ||
636 | cpb[idx++] = cpu_to_le16(IGN); | ||
637 | cpb[idx++] = cpu_to_le16(IGN); | ||
638 | cpb[idx++] = cpu_to_le16(IGN); | ||
639 | cpb[idx++] = cpu_to_le16(IGN); | ||
640 | } | ||
641 | else { | ||
642 | cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature); | ||
643 | cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect); | ||
644 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->hob_lbal); | ||
645 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->hob_lbam); | ||
646 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->hob_lbah); | ||
647 | } | ||
648 | cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature); | ||
649 | cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->nsect); | ||
650 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->lbal); | ||
651 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->lbam); | ||
652 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah); | ||
653 | |||
654 | cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND); | ||
655 | |||
656 | return idx; | ||
657 | } | ||
658 | |||
659 | static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) | ||
660 | { | ||
661 | struct nv_adma_port_priv *pp = ap->private_data; | ||
662 | int complete = 0, have_err = 0; | ||
663 | u8 flags = pp->cpb[cpb_num].resp_flags; | ||
664 | |||
665 | VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags); | ||
666 | |||
667 | if (flags & NV_CPB_RESP_DONE) { | ||
668 | VPRINTK("CPB flags done, flags=0x%x\n", flags); | ||
669 | complete = 1; | ||
670 | } | ||
671 | if (flags & NV_CPB_RESP_ATA_ERR) { | ||
672 | ata_port_printk(ap, KERN_ERR, "CPB flags ATA err, flags=0x%x\n", flags); | ||
673 | have_err = 1; | ||
674 | complete = 1; | ||
675 | } | ||
676 | if (flags & NV_CPB_RESP_CMD_ERR) { | ||
677 | ata_port_printk(ap, KERN_ERR, "CPB flags CMD err, flags=0x%x\n", flags); | ||
678 | have_err = 1; | ||
679 | complete = 1; | ||
680 | } | ||
681 | if (flags & NV_CPB_RESP_CPB_ERR) { | ||
682 | ata_port_printk(ap, KERN_ERR, "CPB flags CPB err, flags=0x%x\n", flags); | ||
683 | have_err = 1; | ||
684 | complete = 1; | ||
685 | } | ||
686 | if(complete || force_err) | ||
687 | { | ||
688 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num); | ||
689 | if(likely(qc)) { | ||
690 | u8 ata_status = 0; | ||
691 | /* Only use the ATA port status for non-NCQ commands. | ||
692 | For NCQ commands the current status may have nothing to do with | ||
693 | the command just completed. */ | ||
694 | if(qc->tf.protocol != ATA_PROT_NCQ) | ||
695 | ata_status = readb(nv_adma_ctl_block(ap) + (ATA_REG_STATUS * 4)); | ||
696 | |||
697 | if(have_err || force_err) | ||
698 | ata_status |= ATA_ERR; | ||
699 | |||
700 | qc->err_mask |= ac_err_mask(ata_status); | ||
701 | DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num, | ||
702 | qc->err_mask); | ||
703 | ata_qc_complete(qc); | ||
704 | } | ||
705 | } | ||
311 | } | 706 | } |
312 | 707 | ||
313 | static int nv_host_intr(struct ata_port *ap, u8 irq_stat) | 708 | static int nv_host_intr(struct ata_port *ap, u8 irq_stat) |
@@ -341,6 +736,486 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat) | |||
341 | return 1; | 736 | return 1; |
342 | } | 737 | } |
343 | 738 | ||
739 | static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | ||
740 | { | ||
741 | struct ata_host *host = dev_instance; | ||
742 | int i, handled = 0; | ||
743 | u32 notifier_clears[2]; | ||
744 | |||
745 | spin_lock(&host->lock); | ||
746 | |||
747 | for (i = 0; i < host->n_ports; i++) { | ||
748 | struct ata_port *ap = host->ports[i]; | ||
749 | notifier_clears[i] = 0; | ||
750 | |||
751 | if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { | ||
752 | struct nv_adma_port_priv *pp = ap->private_data; | ||
753 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
754 | u16 status; | ||
755 | u32 gen_ctl; | ||
756 | int have_global_err = 0; | ||
757 | u32 notifier, notifier_error; | ||
758 | |||
759 | /* if in ATA register mode, use standard ata interrupt handler */ | ||
760 | if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { | ||
761 | u8 irq_stat = readb(host->mmio_base + NV_INT_STATUS_CK804) | ||
762 | >> (NV_INT_PORT_SHIFT * i); | ||
763 | handled += nv_host_intr(ap, irq_stat); | ||
764 | continue; | ||
765 | } | ||
766 | |||
767 | notifier = readl(mmio + NV_ADMA_NOTIFIER); | ||
768 | notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); | ||
769 | notifier_clears[i] = notifier | notifier_error; | ||
770 | |||
771 | gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); | ||
772 | |||
773 | if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && | ||
774 | !notifier_error) | ||
775 | /* Nothing to do */ | ||
776 | continue; | ||
777 | |||
778 | status = readw(mmio + NV_ADMA_STAT); | ||
779 | |||
780 | /* Clear status. Ensure the controller sees the clearing before we start | ||
781 | looking at any of the CPB statuses, so that any CPB completions after | ||
782 | this point in the handler will raise another interrupt. */ | ||
783 | writew(status, mmio + NV_ADMA_STAT); | ||
784 | readw(mmio + NV_ADMA_STAT); /* flush posted write */ | ||
785 | rmb(); | ||
786 | |||
787 | /* freeze if hotplugged */ | ||
788 | if (unlikely(status & (NV_ADMA_STAT_HOTPLUG | NV_ADMA_STAT_HOTUNPLUG))) { | ||
789 | ata_port_printk(ap, KERN_NOTICE, "Hotplug event, freezing\n"); | ||
790 | ata_port_freeze(ap); | ||
791 | handled++; | ||
792 | continue; | ||
793 | } | ||
794 | |||
795 | if (status & NV_ADMA_STAT_TIMEOUT) { | ||
796 | ata_port_printk(ap, KERN_ERR, "timeout, stat=0x%x\n", status); | ||
797 | have_global_err = 1; | ||
798 | } | ||
799 | if (status & NV_ADMA_STAT_CPBERR) { | ||
800 | ata_port_printk(ap, KERN_ERR, "CPB error, stat=0x%x\n", status); | ||
801 | have_global_err = 1; | ||
802 | } | ||
803 | if ((status & NV_ADMA_STAT_DONE) || have_global_err) { | ||
804 | /** Check CPBs for completed commands */ | ||
805 | |||
806 | if(ata_tag_valid(ap->active_tag)) | ||
807 | /* Non-NCQ command */ | ||
808 | nv_adma_check_cpb(ap, ap->active_tag, have_global_err || | ||
809 | (notifier_error & (1 << ap->active_tag))); | ||
810 | else { | ||
811 | int pos; | ||
812 | u32 active = ap->sactive; | ||
813 | while( (pos = ffs(active)) ) { | ||
814 | pos--; | ||
815 | nv_adma_check_cpb(ap, pos, have_global_err || | ||
816 | (notifier_error & (1 << pos)) ); | ||
817 | active &= ~(1 << pos ); | ||
818 | } | ||
819 | } | ||
820 | } | ||
821 | |||
822 | handled++; /* irq handled if we got here */ | ||
823 | } | ||
824 | } | ||
825 | |||
826 | if(notifier_clears[0] || notifier_clears[1]) { | ||
827 | /* Note: Both notifier clear registers must be written | ||
828 | if either is set, even if one is zero, according to NVIDIA. */ | ||
829 | writel(notifier_clears[0], | ||
830 | nv_adma_notifier_clear_block(host->ports[0])); | ||
831 | writel(notifier_clears[1], | ||
832 | nv_adma_notifier_clear_block(host->ports[1])); | ||
833 | } | ||
834 | |||
835 | spin_unlock(&host->lock); | ||
836 | |||
837 | return IRQ_RETVAL(handled); | ||
838 | } | ||
839 | |||
840 | static void nv_adma_irq_clear(struct ata_port *ap) | ||
841 | { | ||
842 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
843 | u16 status = readw(mmio + NV_ADMA_STAT); | ||
844 | u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); | ||
845 | u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); | ||
846 | unsigned long dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; | ||
847 | |||
848 | /* clear ADMA status */ | ||
849 | writew(status, mmio + NV_ADMA_STAT); | ||
850 | writel(notifier | notifier_error, | ||
851 | nv_adma_notifier_clear_block(ap)); | ||
852 | |||
853 | /** clear legacy status */ | ||
854 | outb(inb(dma_stat_addr), dma_stat_addr); | ||
855 | } | ||
856 | |||
857 | static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc) | ||
858 | { | ||
859 | struct ata_port *ap = qc->ap; | ||
860 | unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); | ||
861 | struct nv_adma_port_priv *pp = ap->private_data; | ||
862 | u8 dmactl; | ||
863 | |||
864 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { | ||
865 | WARN_ON(1); | ||
866 | return; | ||
867 | } | ||
868 | |||
869 | /* load PRD table addr. */ | ||
870 | outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); | ||
871 | |||
872 | /* specify data direction, triple-check start bit is clear */ | ||
873 | dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
874 | dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); | ||
875 | if (!rw) | ||
876 | dmactl |= ATA_DMA_WR; | ||
877 | |||
878 | outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
879 | |||
880 | /* issue r/w command */ | ||
881 | ata_exec_command(ap, &qc->tf); | ||
882 | } | ||
883 | |||
884 | static void nv_adma_bmdma_start(struct ata_queued_cmd *qc) | ||
885 | { | ||
886 | struct ata_port *ap = qc->ap; | ||
887 | struct nv_adma_port_priv *pp = ap->private_data; | ||
888 | u8 dmactl; | ||
889 | |||
890 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { | ||
891 | WARN_ON(1); | ||
892 | return; | ||
893 | } | ||
894 | |||
895 | /* start host DMA transaction */ | ||
896 | dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
897 | outb(dmactl | ATA_DMA_START, | ||
898 | ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
899 | } | ||
900 | |||
901 | static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc) | ||
902 | { | ||
903 | struct ata_port *ap = qc->ap; | ||
904 | struct nv_adma_port_priv *pp = ap->private_data; | ||
905 | |||
906 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) | ||
907 | return; | ||
908 | |||
909 | /* clear start/stop bit */ | ||
910 | outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, | ||
911 | ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
912 | |||
913 | /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ | ||
914 | ata_altstatus(ap); /* dummy read */ | ||
915 | } | ||
916 | |||
917 | static u8 nv_adma_bmdma_status(struct ata_port *ap) | ||
918 | { | ||
919 | struct nv_adma_port_priv *pp = ap->private_data; | ||
920 | |||
921 | WARN_ON(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)); | ||
922 | |||
923 | return inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
924 | } | ||
925 | |||
926 | static int nv_adma_port_start(struct ata_port *ap) | ||
927 | { | ||
928 | struct device *dev = ap->host->dev; | ||
929 | struct nv_adma_port_priv *pp; | ||
930 | int rc; | ||
931 | void *mem; | ||
932 | dma_addr_t mem_dma; | ||
933 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
934 | u16 tmp; | ||
935 | |||
936 | VPRINTK("ENTER\n"); | ||
937 | |||
938 | rc = ata_port_start(ap); | ||
939 | if (rc) | ||
940 | return rc; | ||
941 | |||
942 | pp = kzalloc(sizeof(*pp), GFP_KERNEL); | ||
943 | if (!pp) { | ||
944 | rc = -ENOMEM; | ||
945 | goto err_out; | ||
946 | } | ||
947 | |||
948 | mem = dma_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, | ||
949 | &mem_dma, GFP_KERNEL); | ||
950 | |||
951 | if (!mem) { | ||
952 | rc = -ENOMEM; | ||
953 | goto err_out_kfree; | ||
954 | } | ||
955 | memset(mem, 0, NV_ADMA_PORT_PRIV_DMA_SZ); | ||
956 | |||
957 | /* | ||
958 | * First item in chunk of DMA memory: | ||
959 | * 128-byte command parameter block (CPB) | ||
960 | * one for each command tag | ||
961 | */ | ||
962 | pp->cpb = mem; | ||
963 | pp->cpb_dma = mem_dma; | ||
964 | |||
965 | writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); | ||
966 | writel((mem_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); | ||
967 | |||
968 | mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; | ||
969 | mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ; | ||
970 | |||
971 | /* | ||
972 | * Second item: block of ADMA_SGTBL_LEN s/g entries | ||
973 | */ | ||
974 | pp->aprd = mem; | ||
975 | pp->aprd_dma = mem_dma; | ||
976 | |||
977 | ap->private_data = pp; | ||
978 | |||
979 | /* clear any outstanding interrupt conditions */ | ||
980 | writew(0xffff, mmio + NV_ADMA_STAT); | ||
981 | |||
982 | /* initialize port variables */ | ||
983 | pp->flags = NV_ADMA_PORT_REGISTER_MODE; | ||
984 | |||
985 | /* clear CPB fetch count */ | ||
986 | writew(0, mmio + NV_ADMA_CPB_COUNT); | ||
987 | |||
988 | /* clear GO for register mode */ | ||
989 | tmp = readw(mmio + NV_ADMA_CTL); | ||
990 | writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); | ||
991 | |||
992 | tmp = readw(mmio + NV_ADMA_CTL); | ||
993 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | ||
994 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | ||
995 | udelay(1); | ||
996 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | ||
997 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | ||
998 | |||
999 | return 0; | ||
1000 | |||
1001 | err_out_kfree: | ||
1002 | kfree(pp); | ||
1003 | err_out: | ||
1004 | ata_port_stop(ap); | ||
1005 | return rc; | ||
1006 | } | ||
1007 | |||
1008 | static void nv_adma_port_stop(struct ata_port *ap) | ||
1009 | { | ||
1010 | struct device *dev = ap->host->dev; | ||
1011 | struct nv_adma_port_priv *pp = ap->private_data; | ||
1012 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
1013 | |||
1014 | VPRINTK("ENTER\n"); | ||
1015 | |||
1016 | writew(0, mmio + NV_ADMA_CTL); | ||
1017 | |||
1018 | ap->private_data = NULL; | ||
1019 | dma_free_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, pp->cpb, pp->cpb_dma); | ||
1020 | kfree(pp); | ||
1021 | ata_port_stop(ap); | ||
1022 | } | ||
1023 | |||
1024 | |||
1025 | static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port) | ||
1026 | { | ||
1027 | void __iomem *mmio = probe_ent->mmio_base; | ||
1028 | struct ata_ioports *ioport = &probe_ent->port[port]; | ||
1029 | |||
1030 | VPRINTK("ENTER\n"); | ||
1031 | |||
1032 | mmio += NV_ADMA_PORT + port * NV_ADMA_PORT_SIZE; | ||
1033 | |||
1034 | ioport->cmd_addr = (unsigned long) mmio; | ||
1035 | ioport->data_addr = (unsigned long) mmio + (ATA_REG_DATA * 4); | ||
1036 | ioport->error_addr = | ||
1037 | ioport->feature_addr = (unsigned long) mmio + (ATA_REG_ERR * 4); | ||
1038 | ioport->nsect_addr = (unsigned long) mmio + (ATA_REG_NSECT * 4); | ||
1039 | ioport->lbal_addr = (unsigned long) mmio + (ATA_REG_LBAL * 4); | ||
1040 | ioport->lbam_addr = (unsigned long) mmio + (ATA_REG_LBAM * 4); | ||
1041 | ioport->lbah_addr = (unsigned long) mmio + (ATA_REG_LBAH * 4); | ||
1042 | ioport->device_addr = (unsigned long) mmio + (ATA_REG_DEVICE * 4); | ||
1043 | ioport->status_addr = | ||
1044 | ioport->command_addr = (unsigned long) mmio + (ATA_REG_STATUS * 4); | ||
1045 | ioport->altstatus_addr = | ||
1046 | ioport->ctl_addr = (unsigned long) mmio + 0x20; | ||
1047 | } | ||
1048 | |||
1049 | static int nv_adma_host_init(struct ata_probe_ent *probe_ent) | ||
1050 | { | ||
1051 | struct pci_dev *pdev = to_pci_dev(probe_ent->dev); | ||
1052 | unsigned int i; | ||
1053 | u32 tmp32; | ||
1054 | |||
1055 | VPRINTK("ENTER\n"); | ||
1056 | |||
1057 | /* enable ADMA on the ports */ | ||
1058 | pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); | ||
1059 | tmp32 |= NV_MCP_SATA_CFG_20_PORT0_EN | | ||
1060 | NV_MCP_SATA_CFG_20_PORT0_PWB_EN | | ||
1061 | NV_MCP_SATA_CFG_20_PORT1_EN | | ||
1062 | NV_MCP_SATA_CFG_20_PORT1_PWB_EN; | ||
1063 | |||
1064 | pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); | ||
1065 | |||
1066 | for (i = 0; i < probe_ent->n_ports; i++) | ||
1067 | nv_adma_setup_port(probe_ent, i); | ||
1068 | |||
1069 | for (i = 0; i < probe_ent->n_ports; i++) { | ||
1070 | void __iomem *mmio = __nv_adma_ctl_block(probe_ent->mmio_base, i); | ||
1071 | u16 tmp; | ||
1072 | |||
1073 | /* enable interrupt, clear reset if not already clear */ | ||
1074 | tmp = readw(mmio + NV_ADMA_CTL); | ||
1075 | writew(tmp | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); | ||
1076 | } | ||
1077 | |||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
1081 | static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, | ||
1082 | struct scatterlist *sg, | ||
1083 | int idx, | ||
1084 | struct nv_adma_prd *aprd) | ||
1085 | { | ||
1086 | u8 flags; | ||
1087 | |||
1088 | memset(aprd, 0, sizeof(struct nv_adma_prd)); | ||
1089 | |||
1090 | flags = 0; | ||
1091 | if (qc->tf.flags & ATA_TFLAG_WRITE) | ||
1092 | flags |= NV_APRD_WRITE; | ||
1093 | if (idx == qc->n_elem - 1) | ||
1094 | flags |= NV_APRD_END; | ||
1095 | else if (idx != 4) | ||
1096 | flags |= NV_APRD_CONT; | ||
1097 | |||
1098 | aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg))); | ||
1099 | aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */ | ||
1100 | aprd->flags = flags; | ||
1101 | } | ||
1102 | |||
1103 | static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) | ||
1104 | { | ||
1105 | struct nv_adma_port_priv *pp = qc->ap->private_data; | ||
1106 | unsigned int idx; | ||
1107 | struct nv_adma_prd *aprd; | ||
1108 | struct scatterlist *sg; | ||
1109 | |||
1110 | VPRINTK("ENTER\n"); | ||
1111 | |||
1112 | idx = 0; | ||
1113 | |||
1114 | ata_for_each_sg(sg, qc) { | ||
1115 | aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; | ||
1116 | nv_adma_fill_aprd(qc, sg, idx, aprd); | ||
1117 | idx++; | ||
1118 | } | ||
1119 | if (idx > 5) | ||
1120 | cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag))); | ||
1121 | } | ||
1122 | |||
1123 | static void nv_adma_qc_prep(struct ata_queued_cmd *qc) | ||
1124 | { | ||
1125 | struct nv_adma_port_priv *pp = qc->ap->private_data; | ||
1126 | struct nv_adma_cpb *cpb = &pp->cpb[qc->tag]; | ||
1127 | u8 ctl_flags = NV_CPB_CTL_CPB_VALID | | ||
1128 | NV_CPB_CTL_APRD_VALID | | ||
1129 | NV_CPB_CTL_IEN; | ||
1130 | |||
1131 | VPRINTK("qc->flags = 0x%lx\n", qc->flags); | ||
1132 | |||
1133 | if (!(qc->flags & ATA_QCFLAG_DMAMAP) || | ||
1134 | (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { | ||
1135 | nv_adma_register_mode(qc->ap); | ||
1136 | ata_qc_prep(qc); | ||
1137 | return; | ||
1138 | } | ||
1139 | |||
1140 | memset(cpb, 0, sizeof(struct nv_adma_cpb)); | ||
1141 | |||
1142 | cpb->len = 3; | ||
1143 | cpb->tag = qc->tag; | ||
1144 | cpb->next_cpb_idx = 0; | ||
1145 | |||
1146 | /* turn on NCQ flags for NCQ commands */ | ||
1147 | if (qc->tf.protocol == ATA_PROT_NCQ) | ||
1148 | ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA; | ||
1149 | |||
1150 | nv_adma_tf_to_cpb(&qc->tf, cpb->tf); | ||
1151 | |||
1152 | nv_adma_fill_sg(qc, cpb); | ||
1153 | |||
1154 | /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are | ||
1155 | finished filling in all of the contents */ | ||
1156 | wmb(); | ||
1157 | cpb->ctl_flags = ctl_flags; | ||
1158 | } | ||
1159 | |||
1160 | static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) | ||
1161 | { | ||
1162 | struct nv_adma_port_priv *pp = qc->ap->private_data; | ||
1163 | void __iomem *mmio = nv_adma_ctl_block(qc->ap); | ||
1164 | |||
1165 | VPRINTK("ENTER\n"); | ||
1166 | |||
1167 | if (!(qc->flags & ATA_QCFLAG_DMAMAP) || | ||
1168 | (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { | ||
1169 | /* use ATA register mode */ | ||
1170 | VPRINTK("no dmamap or ATAPI, using ATA register mode: 0x%lx\n", qc->flags); | ||
1171 | nv_adma_register_mode(qc->ap); | ||
1172 | return ata_qc_issue_prot(qc); | ||
1173 | } else | ||
1174 | nv_adma_mode(qc->ap); | ||
1175 | |||
1176 | /* write append register, command tag in lower 8 bits | ||
1177 | and (number of cpbs to append -1) in top 8 bits */ | ||
1178 | wmb(); | ||
1179 | writew(qc->tag, mmio + NV_ADMA_APPEND); | ||
1180 | |||
1181 | DPRINTK("Issued tag %u\n",qc->tag); | ||
1182 | |||
1183 | return 0; | ||
1184 | } | ||
1185 | |||
1186 | static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance) | ||
1187 | { | ||
1188 | struct ata_host *host = dev_instance; | ||
1189 | unsigned int i; | ||
1190 | unsigned int handled = 0; | ||
1191 | unsigned long flags; | ||
1192 | |||
1193 | spin_lock_irqsave(&host->lock, flags); | ||
1194 | |||
1195 | for (i = 0; i < host->n_ports; i++) { | ||
1196 | struct ata_port *ap; | ||
1197 | |||
1198 | ap = host->ports[i]; | ||
1199 | if (ap && | ||
1200 | !(ap->flags & ATA_FLAG_DISABLED)) { | ||
1201 | struct ata_queued_cmd *qc; | ||
1202 | |||
1203 | qc = ata_qc_from_tag(ap, ap->active_tag); | ||
1204 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) | ||
1205 | handled += ata_host_intr(ap, qc); | ||
1206 | else | ||
1207 | // No request pending? Clear interrupt status | ||
1208 | // anyway, in case there's one pending. | ||
1209 | ap->ops->check_status(ap); | ||
1210 | } | ||
1211 | |||
1212 | } | ||
1213 | |||
1214 | spin_unlock_irqrestore(&host->lock, flags); | ||
1215 | |||
1216 | return IRQ_RETVAL(handled); | ||
1217 | } | ||
1218 | |||
344 | static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat) | 1219 | static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat) |
345 | { | 1220 | { |
346 | int i, handled = 0; | 1221 | int i, handled = 0; |
@@ -466,6 +1341,56 @@ static void nv_error_handler(struct ata_port *ap) | |||
466 | nv_hardreset, ata_std_postreset); | 1341 | nv_hardreset, ata_std_postreset); |
467 | } | 1342 | } |
468 | 1343 | ||
1344 | static void nv_adma_error_handler(struct ata_port *ap) | ||
1345 | { | ||
1346 | struct nv_adma_port_priv *pp = ap->private_data; | ||
1347 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { | ||
1348 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
1349 | int i; | ||
1350 | u16 tmp; | ||
1351 | |||
1352 | u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); | ||
1353 | u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); | ||
1354 | u32 gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); | ||
1355 | u32 status = readw(mmio + NV_ADMA_STAT); | ||
1356 | |||
1357 | ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " | ||
1358 | "notifier_error 0x%X gen_ctl 0x%X status 0x%X\n", | ||
1359 | notifier, notifier_error, gen_ctl, status); | ||
1360 | |||
1361 | for( i=0;i<NV_ADMA_MAX_CPBS;i++) { | ||
1362 | struct nv_adma_cpb *cpb = &pp->cpb[i]; | ||
1363 | if( cpb->ctl_flags || cpb->resp_flags ) | ||
1364 | ata_port_printk(ap, KERN_ERR, | ||
1365 | "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n", | ||
1366 | i, cpb->ctl_flags, cpb->resp_flags); | ||
1367 | } | ||
1368 | |||
1369 | /* Push us back into port register mode for error handling. */ | ||
1370 | nv_adma_register_mode(ap); | ||
1371 | |||
1372 | ata_port_printk(ap, KERN_ERR, "Resetting port\n"); | ||
1373 | |||
1374 | /* Mark all of the CPBs as invalid to prevent them from being executed */ | ||
1375 | for( i=0;i<NV_ADMA_MAX_CPBS;i++) | ||
1376 | pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID; | ||
1377 | |||
1378 | /* clear CPB fetch count */ | ||
1379 | writew(0, mmio + NV_ADMA_CPB_COUNT); | ||
1380 | |||
1381 | /* Reset channel */ | ||
1382 | tmp = readw(mmio + NV_ADMA_CTL); | ||
1383 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | ||
1384 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | ||
1385 | udelay(1); | ||
1386 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | ||
1387 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | ||
1388 | } | ||
1389 | |||
1390 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, | ||
1391 | nv_hardreset, ata_std_postreset); | ||
1392 | } | ||
1393 | |||
469 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 1394 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
470 | { | 1395 | { |
471 | static int printed_version = 0; | 1396 | static int printed_version = 0; |
@@ -475,6 +1400,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
475 | int rc; | 1400 | int rc; |
476 | u32 bar; | 1401 | u32 bar; |
477 | unsigned long base; | 1402 | unsigned long base; |
1403 | unsigned long type = ent->driver_data; | ||
1404 | int mask_set = 0; | ||
478 | 1405 | ||
479 | // Make sure this is a SATA controller by counting the number of bars | 1406 | // Make sure this is a SATA controller by counting the number of bars |
480 | // (NVIDIA SATA controllers will always have six bars). Otherwise, | 1407 | // (NVIDIA SATA controllers will always have six bars). Otherwise, |
@@ -483,7 +1410,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
483 | if (pci_resource_start(pdev, bar) == 0) | 1410 | if (pci_resource_start(pdev, bar) == 0) |
484 | return -ENODEV; | 1411 | return -ENODEV; |
485 | 1412 | ||
486 | if (!printed_version++) | 1413 | if ( !printed_version++) |
487 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | 1414 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); |
488 | 1415 | ||
489 | rc = pci_enable_device(pdev); | 1416 | rc = pci_enable_device(pdev); |
@@ -496,16 +1423,26 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
496 | goto err_out_disable; | 1423 | goto err_out_disable; |
497 | } | 1424 | } |
498 | 1425 | ||
499 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | 1426 | if(type >= CK804 && adma_enabled) { |
500 | if (rc) | 1427 | dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); |
501 | goto err_out_regions; | 1428 | type = ADMA; |
502 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | 1429 | if(!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && |
503 | if (rc) | 1430 | !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) |
504 | goto err_out_regions; | 1431 | mask_set = 1; |
1432 | } | ||
1433 | |||
1434 | if(!mask_set) { | ||
1435 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
1436 | if (rc) | ||
1437 | goto err_out_regions; | ||
1438 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
1439 | if (rc) | ||
1440 | goto err_out_regions; | ||
1441 | } | ||
505 | 1442 | ||
506 | rc = -ENOMEM; | 1443 | rc = -ENOMEM; |
507 | 1444 | ||
508 | ppi[0] = ppi[1] = &nv_port_info[ent->driver_data]; | 1445 | ppi[0] = ppi[1] = &nv_port_info[type]; |
509 | probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); | 1446 | probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); |
510 | if (!probe_ent) | 1447 | if (!probe_ent) |
511 | goto err_out_regions; | 1448 | goto err_out_regions; |
@@ -522,7 +1459,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
522 | probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; | 1459 | probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; |
523 | 1460 | ||
524 | /* enable SATA space for CK804 */ | 1461 | /* enable SATA space for CK804 */ |
525 | if (ent->driver_data == CK804) { | 1462 | if (type >= CK804) { |
526 | u8 regval; | 1463 | u8 regval; |
527 | 1464 | ||
528 | pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); | 1465 | pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); |
@@ -532,6 +1469,12 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
532 | 1469 | ||
533 | pci_set_master(pdev); | 1470 | pci_set_master(pdev); |
534 | 1471 | ||
1472 | if (type == ADMA) { | ||
1473 | rc = nv_adma_host_init(probe_ent); | ||
1474 | if (rc) | ||
1475 | goto err_out_iounmap; | ||
1476 | } | ||
1477 | |||
535 | rc = ata_device_add(probe_ent); | 1478 | rc = ata_device_add(probe_ent); |
536 | if (rc != NV_PORTS) | 1479 | if (rc != NV_PORTS) |
537 | goto err_out_iounmap; | 1480 | goto err_out_iounmap; |
@@ -566,6 +1509,33 @@ static void nv_ck804_host_stop(struct ata_host *host) | |||
566 | ata_pci_host_stop(host); | 1509 | ata_pci_host_stop(host); |
567 | } | 1510 | } |
568 | 1511 | ||
1512 | static void nv_adma_host_stop(struct ata_host *host) | ||
1513 | { | ||
1514 | struct pci_dev *pdev = to_pci_dev(host->dev); | ||
1515 | int i; | ||
1516 | u32 tmp32; | ||
1517 | |||
1518 | for (i = 0; i < host->n_ports; i++) { | ||
1519 | void __iomem *mmio = __nv_adma_ctl_block(host->mmio_base, i); | ||
1520 | u16 tmp; | ||
1521 | |||
1522 | /* disable interrupt */ | ||
1523 | tmp = readw(mmio + NV_ADMA_CTL); | ||
1524 | writew(tmp & ~NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); | ||
1525 | } | ||
1526 | |||
1527 | /* disable ADMA on the ports */ | ||
1528 | pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); | ||
1529 | tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | | ||
1530 | NV_MCP_SATA_CFG_20_PORT0_PWB_EN | | ||
1531 | NV_MCP_SATA_CFG_20_PORT1_EN | | ||
1532 | NV_MCP_SATA_CFG_20_PORT1_PWB_EN); | ||
1533 | |||
1534 | pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); | ||
1535 | |||
1536 | nv_ck804_host_stop(host); | ||
1537 | } | ||
1538 | |||
569 | static int __init nv_init(void) | 1539 | static int __init nv_init(void) |
570 | { | 1540 | { |
571 | return pci_register_driver(&nv_pci_driver); | 1541 | return pci_register_driver(&nv_pci_driver); |
@@ -578,3 +1548,5 @@ static void __exit nv_exit(void) | |||
578 | 1548 | ||
579 | module_init(nv_init); | 1549 | module_init(nv_init); |
580 | module_exit(nv_exit); | 1550 | module_exit(nv_exit); |
1551 | module_param_named(adma, adma_enabled, bool, 0444); | ||
1552 | MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); | ||
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 72eda5160fad..a2778cf016bc 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c | |||
@@ -46,20 +46,19 @@ | |||
46 | #include "sata_promise.h" | 46 | #include "sata_promise.h" |
47 | 47 | ||
48 | #define DRV_NAME "sata_promise" | 48 | #define DRV_NAME "sata_promise" |
49 | #define DRV_VERSION "1.04" | 49 | #define DRV_VERSION "1.05" |
50 | 50 | ||
51 | 51 | ||
52 | enum { | 52 | enum { |
53 | PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ | 53 | PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ |
54 | PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ | 54 | PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ |
55 | PDC_TBG_MODE = 0x41, /* TBG mode */ | ||
56 | PDC_FLASH_CTL = 0x44, /* Flash control register */ | 55 | PDC_FLASH_CTL = 0x44, /* Flash control register */ |
57 | PDC_PCI_CTL = 0x48, /* PCI control and status register */ | ||
58 | PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ | 56 | PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ |
59 | PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ | 57 | PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ |
60 | PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ | 58 | PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ |
61 | PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ | 59 | PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ |
62 | PDC_SLEW_CTL = 0x470, /* slew rate control reg */ | 60 | PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ |
61 | PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */ | ||
63 | 62 | ||
64 | PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | | 63 | PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | |
65 | (1<<8) | (1<<9) | (1<<10), | 64 | (1<<8) | (1<<9) | (1<<10), |
@@ -78,6 +77,9 @@ enum { | |||
78 | PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | | 77 | PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | |
79 | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | | 78 | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | |
80 | ATA_FLAG_PIO_POLLING, | 79 | ATA_FLAG_PIO_POLLING, |
80 | |||
81 | /* hp->flags bits */ | ||
82 | PDC_FLAG_GEN_II = (1 << 0), | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | 85 | ||
@@ -87,6 +89,7 @@ struct pdc_port_priv { | |||
87 | }; | 89 | }; |
88 | 90 | ||
89 | struct pdc_host_priv { | 91 | struct pdc_host_priv { |
92 | unsigned long flags; | ||
90 | int hotplug_offset; | 93 | int hotplug_offset; |
91 | }; | 94 | }; |
92 | 95 | ||
@@ -235,20 +238,20 @@ static const struct ata_port_info pdc_port_info[] = { | |||
235 | 238 | ||
236 | static const struct pci_device_id pdc_ata_pci_tbl[] = { | 239 | static const struct pci_device_id pdc_ata_pci_tbl[] = { |
237 | { PCI_VDEVICE(PROMISE, 0x3371), board_2037x }, | 240 | { PCI_VDEVICE(PROMISE, 0x3371), board_2037x }, |
238 | { PCI_VDEVICE(PROMISE, 0x3570), board_2037x }, | ||
239 | { PCI_VDEVICE(PROMISE, 0x3571), board_2037x }, | ||
240 | { PCI_VDEVICE(PROMISE, 0x3373), board_2037x }, | 241 | { PCI_VDEVICE(PROMISE, 0x3373), board_2037x }, |
241 | { PCI_VDEVICE(PROMISE, 0x3375), board_2037x }, | 242 | { PCI_VDEVICE(PROMISE, 0x3375), board_2037x }, |
242 | { PCI_VDEVICE(PROMISE, 0x3376), board_2037x }, | 243 | { PCI_VDEVICE(PROMISE, 0x3376), board_2037x }, |
244 | { PCI_VDEVICE(PROMISE, 0x3570), board_2057x }, | ||
245 | { PCI_VDEVICE(PROMISE, 0x3571), board_2057x }, | ||
243 | { PCI_VDEVICE(PROMISE, 0x3574), board_2057x }, | 246 | { PCI_VDEVICE(PROMISE, 0x3574), board_2057x }, |
247 | { PCI_VDEVICE(PROMISE, 0x3d73), board_2057x }, | ||
244 | { PCI_VDEVICE(PROMISE, 0x3d75), board_2057x }, | 248 | { PCI_VDEVICE(PROMISE, 0x3d75), board_2057x }, |
245 | { PCI_VDEVICE(PROMISE, 0x3d73), board_2037x }, | ||
246 | 249 | ||
247 | { PCI_VDEVICE(PROMISE, 0x3318), board_20319 }, | 250 | { PCI_VDEVICE(PROMISE, 0x3318), board_20319 }, |
248 | { PCI_VDEVICE(PROMISE, 0x3319), board_20319 }, | 251 | { PCI_VDEVICE(PROMISE, 0x3319), board_20319 }, |
249 | { PCI_VDEVICE(PROMISE, 0x3515), board_20319 }, | 252 | { PCI_VDEVICE(PROMISE, 0x3515), board_20319 }, |
250 | { PCI_VDEVICE(PROMISE, 0x3519), board_20319 }, | 253 | { PCI_VDEVICE(PROMISE, 0x3519), board_20319 }, |
251 | { PCI_VDEVICE(PROMISE, 0x3d17), board_20319 }, | 254 | { PCI_VDEVICE(PROMISE, 0x3d17), board_40518 }, |
252 | { PCI_VDEVICE(PROMISE, 0x3d18), board_40518 }, | 255 | { PCI_VDEVICE(PROMISE, 0x3d18), board_40518 }, |
253 | 256 | ||
254 | { PCI_VDEVICE(PROMISE, 0x6629), board_20619 }, | 257 | { PCI_VDEVICE(PROMISE, 0x6629), board_20619 }, |
@@ -277,6 +280,7 @@ static struct pci_driver pdc_ata_pci_driver = { | |||
277 | static int pdc_port_start(struct ata_port *ap) | 280 | static int pdc_port_start(struct ata_port *ap) |
278 | { | 281 | { |
279 | struct device *dev = ap->host->dev; | 282 | struct device *dev = ap->host->dev; |
283 | struct pdc_host_priv *hp = ap->host->private_data; | ||
280 | struct pdc_port_priv *pp; | 284 | struct pdc_port_priv *pp; |
281 | int rc; | 285 | int rc; |
282 | 286 | ||
@@ -298,6 +302,16 @@ static int pdc_port_start(struct ata_port *ap) | |||
298 | 302 | ||
299 | ap->private_data = pp; | 303 | ap->private_data = pp; |
300 | 304 | ||
305 | /* fix up PHYMODE4 align timing */ | ||
306 | if ((hp->flags & PDC_FLAG_GEN_II) && sata_scr_valid(ap)) { | ||
307 | void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr; | ||
308 | unsigned int tmp; | ||
309 | |||
310 | tmp = readl(mmio + 0x014); | ||
311 | tmp = (tmp & ~3) | 1; /* set bits 1:0 = 0:1 */ | ||
312 | writel(tmp, mmio + 0x014); | ||
313 | } | ||
314 | |||
301 | return 0; | 315 | return 0; |
302 | 316 | ||
303 | err_out_kfree: | 317 | err_out_kfree: |
@@ -640,9 +654,11 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) | |||
640 | * "TODO: figure out why we do this" | 654 | * "TODO: figure out why we do this" |
641 | */ | 655 | */ |
642 | 656 | ||
643 | /* change FIFO_SHD to 8 dwords, enable BMR_BURST */ | 657 | /* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */ |
644 | tmp = readl(mmio + PDC_FLASH_CTL); | 658 | tmp = readl(mmio + PDC_FLASH_CTL); |
645 | tmp |= 0x12000; /* bit 16 (fifo 8 dw) and 13 (bmr burst?) */ | 659 | tmp |= 0x02000; /* bit 13 (enable bmr burst) */ |
660 | if (!(hp->flags & PDC_FLAG_GEN_II)) | ||
661 | tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */ | ||
646 | writel(tmp, mmio + PDC_FLASH_CTL); | 662 | writel(tmp, mmio + PDC_FLASH_CTL); |
647 | 663 | ||
648 | /* clear plug/unplug flags for all ports */ | 664 | /* clear plug/unplug flags for all ports */ |
@@ -653,6 +669,10 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) | |||
653 | tmp = readl(mmio + hotplug_offset); | 669 | tmp = readl(mmio + hotplug_offset); |
654 | writel(tmp | 0xff0000, mmio + hotplug_offset); | 670 | writel(tmp | 0xff0000, mmio + hotplug_offset); |
655 | 671 | ||
672 | /* don't initialise TBG or SLEW on 2nd generation chips */ | ||
673 | if (hp->flags & PDC_FLAG_GEN_II) | ||
674 | return; | ||
675 | |||
656 | /* reduce TBG clock to 133 Mhz. */ | 676 | /* reduce TBG clock to 133 Mhz. */ |
657 | tmp = readl(mmio + PDC_TBG_MODE); | 677 | tmp = readl(mmio + PDC_TBG_MODE); |
658 | tmp &= ~0x30000; /* clear bit 17, 16*/ | 678 | tmp &= ~0x30000; /* clear bit 17, 16*/ |
@@ -746,6 +766,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
746 | /* notice 4-port boards */ | 766 | /* notice 4-port boards */ |
747 | switch (board_idx) { | 767 | switch (board_idx) { |
748 | case board_40518: | 768 | case board_40518: |
769 | hp->flags |= PDC_FLAG_GEN_II; | ||
749 | /* Override hotplug offset for SATAII150 */ | 770 | /* Override hotplug offset for SATAII150 */ |
750 | hp->hotplug_offset = PDC2_SATA_PLUG_CSR; | 771 | hp->hotplug_offset = PDC2_SATA_PLUG_CSR; |
751 | /* Fall through */ | 772 | /* Fall through */ |
@@ -759,15 +780,14 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
759 | probe_ent->port[3].scr_addr = base + 0x700; | 780 | probe_ent->port[3].scr_addr = base + 0x700; |
760 | break; | 781 | break; |
761 | case board_2057x: | 782 | case board_2057x: |
783 | case board_20771: | ||
784 | hp->flags |= PDC_FLAG_GEN_II; | ||
762 | /* Override hotplug offset for SATAII150 */ | 785 | /* Override hotplug offset for SATAII150 */ |
763 | hp->hotplug_offset = PDC2_SATA_PLUG_CSR; | 786 | hp->hotplug_offset = PDC2_SATA_PLUG_CSR; |
764 | /* Fall through */ | 787 | /* Fall through */ |
765 | case board_2037x: | 788 | case board_2037x: |
766 | probe_ent->n_ports = 2; | 789 | probe_ent->n_ports = 2; |
767 | break; | 790 | break; |
768 | case board_20771: | ||
769 | probe_ent->n_ports = 2; | ||
770 | break; | ||
771 | case board_20619: | 791 | case board_20619: |
772 | probe_ent->n_ports = 4; | 792 | probe_ent->n_ports = 4; |
773 | 793 | ||
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index ca8d99312472..7808d0369d91 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c | |||
@@ -356,6 +356,7 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | |||
356 | 356 | ||
357 | static void sil_host_intr(struct ata_port *ap, u32 bmdma2) | 357 | static void sil_host_intr(struct ata_port *ap, u32 bmdma2) |
358 | { | 358 | { |
359 | struct ata_eh_info *ehi = &ap->eh_info; | ||
359 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); | 360 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); |
360 | u8 status; | 361 | u8 status; |
361 | 362 | ||
@@ -428,6 +429,10 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) | |||
428 | /* kick HSM in the ass */ | 429 | /* kick HSM in the ass */ |
429 | ata_hsm_move(ap, qc, status, 0); | 430 | ata_hsm_move(ap, qc, status, 0); |
430 | 431 | ||
432 | if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || | ||
433 | qc->tf.protocol == ATA_PROT_ATAPI_DMA)) | ||
434 | ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); | ||
435 | |||
431 | return; | 436 | return; |
432 | 437 | ||
433 | err_hsm: | 438 | err_hsm: |
@@ -534,6 +539,7 @@ static void sil_thaw(struct ata_port *ap) | |||
534 | */ | 539 | */ |
535 | static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) | 540 | static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) |
536 | { | 541 | { |
542 | int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; | ||
537 | unsigned int n, quirks = 0; | 543 | unsigned int n, quirks = 0; |
538 | unsigned char model_num[41]; | 544 | unsigned char model_num[41]; |
539 | 545 | ||
@@ -549,16 +555,18 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) | |||
549 | if (slow_down || | 555 | if (slow_down || |
550 | ((ap->flags & SIL_FLAG_MOD15WRITE) && | 556 | ((ap->flags & SIL_FLAG_MOD15WRITE) && |
551 | (quirks & SIL_QUIRK_MOD15WRITE))) { | 557 | (quirks & SIL_QUIRK_MOD15WRITE))) { |
552 | ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix " | 558 | if (print_info) |
553 | "(mod15write workaround)\n"); | 559 | ata_dev_printk(dev, KERN_INFO, "applying Seagate " |
560 | "errata fix (mod15write workaround)\n"); | ||
554 | dev->max_sectors = 15; | 561 | dev->max_sectors = 15; |
555 | return; | 562 | return; |
556 | } | 563 | } |
557 | 564 | ||
558 | /* limit to udma5 */ | 565 | /* limit to udma5 */ |
559 | if (quirks & SIL_QUIRK_UDMA5MAX) { | 566 | if (quirks & SIL_QUIRK_UDMA5MAX) { |
560 | ata_dev_printk(dev, KERN_INFO, | 567 | if (print_info) |
561 | "applying Maxtor errata fix %s\n", model_num); | 568 | ata_dev_printk(dev, KERN_INFO, "applying Maxtor " |
569 | "errata fix %s\n", model_num); | ||
562 | dev->udma_mask &= ATA_UDMA5; | 570 | dev->udma_mask &= ATA_UDMA5; |
563 | return; | 571 | return; |
564 | } | 572 | } |
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 169e200a6a71..5aa288d2fb86 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -100,10 +100,14 @@ enum { | |||
100 | */ | 100 | */ |
101 | PORT_REGS_SIZE = 0x2000, | 101 | PORT_REGS_SIZE = 0x2000, |
102 | 102 | ||
103 | PORT_LRAM = 0x0000, /* 31 LRAM slots and PM regs */ | 103 | PORT_LRAM = 0x0000, /* 31 LRAM slots and PMP regs */ |
104 | PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */ | 104 | PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */ |
105 | 105 | ||
106 | PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */ | 106 | PORT_PMP = 0x0f80, /* 8 bytes PMP * 16 (128 bytes) */ |
107 | PORT_PMP_STATUS = 0x0000, /* port device status offset */ | ||
108 | PORT_PMP_QACTIVE = 0x0004, /* port device QActive offset */ | ||
109 | PORT_PMP_SIZE = 0x0008, /* 8 bytes per PMP */ | ||
110 | |||
107 | /* 32 bit regs */ | 111 | /* 32 bit regs */ |
108 | PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */ | 112 | PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */ |
109 | PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */ | 113 | PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */ |
@@ -126,6 +130,7 @@ enum { | |||
126 | PORT_PHY_CFG = 0x1050, | 130 | PORT_PHY_CFG = 0x1050, |
127 | PORT_SLOT_STAT = 0x1800, | 131 | PORT_SLOT_STAT = 0x1800, |
128 | PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */ | 132 | PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */ |
133 | PORT_CONTEXT = 0x1e04, | ||
129 | PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */ | 134 | PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */ |
130 | PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */ | 135 | PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */ |
131 | PORT_SCONTROL = 0x1f00, | 136 | PORT_SCONTROL = 0x1f00, |
@@ -139,9 +144,9 @@ enum { | |||
139 | PORT_CS_INIT = (1 << 2), /* port initialize */ | 144 | PORT_CS_INIT = (1 << 2), /* port initialize */ |
140 | PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */ | 145 | PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */ |
141 | PORT_CS_CDB16 = (1 << 5), /* 0=12b cdb, 1=16b cdb */ | 146 | PORT_CS_CDB16 = (1 << 5), /* 0=12b cdb, 1=16b cdb */ |
142 | PORT_CS_RESUME = (1 << 6), /* port resume */ | 147 | PORT_CS_PMP_RESUME = (1 << 6), /* PMP resume */ |
143 | PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */ | 148 | PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */ |
144 | PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */ | 149 | PORT_CS_PMP_EN = (1 << 13), /* port multiplier enable */ |
145 | PORT_CS_RDY = (1 << 31), /* port ready to accept commands */ | 150 | PORT_CS_RDY = (1 << 31), /* port ready to accept commands */ |
146 | 151 | ||
147 | /* PORT_IRQ_STAT/ENABLE_SET/CLR */ | 152 | /* PORT_IRQ_STAT/ENABLE_SET/CLR */ |
@@ -562,7 +567,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class) | |||
562 | 567 | ||
563 | /* do SRST */ | 568 | /* do SRST */ |
564 | prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); | 569 | prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); |
565 | prb->fis[1] = 0; /* no PM yet */ | 570 | prb->fis[1] = 0; /* no PMP yet */ |
566 | 571 | ||
567 | writel((u32)paddr, port + PORT_CMD_ACTIVATE); | 572 | writel((u32)paddr, port + PORT_CMD_ACTIVATE); |
568 | writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); | 573 | writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); |
@@ -1050,7 +1055,8 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports, | |||
1050 | writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); | 1055 | writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); |
1051 | 1056 | ||
1052 | /* Clear port multiplier enable and resume bits */ | 1057 | /* Clear port multiplier enable and resume bits */ |
1053 | writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR); | 1058 | writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME, |
1059 | port + PORT_CTRL_CLR); | ||
1054 | } | 1060 | } |
1055 | 1061 | ||
1056 | /* Turn on interrupts */ | 1062 | /* Turn on interrupts */ |
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 9d1235ba06b1..9c25a1e91730 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c | |||
@@ -173,7 +173,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) | |||
173 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) | 173 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) |
174 | pci_read_config_dword(pdev, cfg_addr+0x10, &val2); | 174 | pci_read_config_dword(pdev, cfg_addr+0x10, &val2); |
175 | 175 | ||
176 | return val|val2; | 176 | return (val|val2) & 0xfffffffb; /* avoid problems with powerdowned ports */ |
177 | } | 177 | } |
178 | 178 | ||
179 | static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) | 179 | static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) |
@@ -212,7 +212,7 @@ static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg) | |||
212 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) | 212 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) |
213 | val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10); | 213 | val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10); |
214 | 214 | ||
215 | return val | val2; | 215 | return (val | val2) & 0xfffffffb; |
216 | } | 216 | } |
217 | 217 | ||
218 | static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | 218 | static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) |
@@ -239,7 +239,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
239 | static int printed_version; | 239 | static int printed_version; |
240 | struct ata_probe_ent *probe_ent = NULL; | 240 | struct ata_probe_ent *probe_ent = NULL; |
241 | int rc; | 241 | int rc; |
242 | u32 genctl; | 242 | u32 genctl, val; |
243 | struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi }; | 243 | struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi }; |
244 | int pci_dev_busy = 0; | 244 | int pci_dev_busy = 0; |
245 | u8 pmr; | 245 | u8 pmr; |
@@ -285,17 +285,24 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
285 | if (ent->device != 0x182) { | 285 | if (ent->device != 0x182) { |
286 | if ((pmr & SIS_PMR_COMBINED) == 0) { | 286 | if ((pmr & SIS_PMR_COMBINED) == 0) { |
287 | dev_printk(KERN_INFO, &pdev->dev, | 287 | dev_printk(KERN_INFO, &pdev->dev, |
288 | "Detected SiS 180/181 chipset in SATA mode\n"); | 288 | "Detected SiS 180/181/964 chipset in SATA mode\n"); |
289 | port2_start = 64; | 289 | port2_start = 64; |
290 | } | 290 | } |
291 | else { | 291 | else { |
292 | dev_printk(KERN_INFO, &pdev->dev, | 292 | dev_printk(KERN_INFO, &pdev->dev, |
293 | "Detected SiS 180/181 chipset in combined mode\n"); | 293 | "Detected SiS 180/181 chipset in combined mode\n"); |
294 | port2_start=0; | 294 | port2_start=0; |
295 | pi.flags |= ATA_FLAG_SLAVE_POSS; | ||
295 | } | 296 | } |
296 | } | 297 | } |
297 | else { | 298 | else { |
298 | dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n"); | 299 | pci_read_config_dword ( pdev, 0x6C, &val); |
300 | if (val & (1L << 31)) { | ||
301 | dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n"); | ||
302 | pi.flags |= ATA_FLAG_SLAVE_POSS; | ||
303 | } | ||
304 | else | ||
305 | dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n"); | ||
299 | port2_start = 0x20; | 306 | port2_start = 0x20; |
300 | } | 307 | } |
301 | 308 | ||
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 4bef76a2f3f2..1f745f12f94e 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/sysdev.h> | 5 | #include <linux/sysdev.h> |
6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/sched.h> | ||
8 | #include <linux/cpu.h> | 9 | #include <linux/cpu.h> |
9 | #include <linux/topology.h> | 10 | #include <linux/topology.h> |
10 | #include <linux/device.h> | 11 | #include <linux/device.h> |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index ad8b537ad47b..24f922f12783 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -855,39 +855,6 @@ config TANBAC_TB0219 | |||
855 | depends TANBAC_TB022X | 855 | depends TANBAC_TB022X |
856 | select GPIO_VR41XX | 856 | select GPIO_VR41XX |
857 | 857 | ||
858 | menu "Ftape, the floppy tape device driver" | ||
859 | |||
860 | config FTAPE | ||
861 | tristate "Ftape (QIC-80/Travan) support" | ||
862 | depends on BROKEN_ON_SMP && (ALPHA || X86) | ||
863 | ---help--- | ||
864 | If you have a tape drive that is connected to your floppy | ||
865 | controller, say Y here. | ||
866 | |||
867 | Some tape drives (like the Seagate "Tape Store 3200" or the Iomega | ||
868 | "Ditto 3200" or the Exabyte "Eagle TR-3") come with a "high speed" | ||
869 | controller of their own. These drives (and their companion | ||
870 | controllers) are also supported if you say Y here. | ||
871 | |||
872 | If you have a special controller (such as the CMS FC-10, FC-20, | ||
873 | Mountain Mach-II, or any controller that is based on the Intel 82078 | ||
874 | FDC like the high speed controllers by Seagate and Exabyte and | ||
875 | Iomega's "Ditto Dash") you must configure it by selecting the | ||
876 | appropriate entries from the "Floppy tape controllers" sub-menu | ||
877 | below and possibly modify the default values for the IRQ and DMA | ||
878 | channel and the IO base in ftape's configuration menu. | ||
879 | |||
880 | If you want to use your floppy tape drive on a PCI-bus based system, | ||
881 | please read the file <file:drivers/char/ftape/README.PCI>. | ||
882 | |||
883 | The ftape kernel driver is also available as a runtime loadable | ||
884 | module. To compile this driver as a module, choose M here: the | ||
885 | module will be called ftape. | ||
886 | |||
887 | source "drivers/char/ftape/Kconfig" | ||
888 | |||
889 | endmenu | ||
890 | |||
891 | source "drivers/char/agp/Kconfig" | 858 | source "drivers/char/agp/Kconfig" |
892 | 859 | ||
893 | source "drivers/char/drm/Kconfig" | 860 | source "drivers/char/drm/Kconfig" |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 777cad045094..b1fcdab90947 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -78,7 +78,6 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o | |||
78 | obj-$(CONFIG_I8K) += i8k.o | 78 | obj-$(CONFIG_I8K) += i8k.o |
79 | obj-$(CONFIG_DS1620) += ds1620.o | 79 | obj-$(CONFIG_DS1620) += ds1620.o |
80 | obj-$(CONFIG_HW_RANDOM) += hw_random/ | 80 | obj-$(CONFIG_HW_RANDOM) += hw_random/ |
81 | obj-$(CONFIG_FTAPE) += ftape/ | ||
82 | obj-$(CONFIG_COBALT_LCD) += lcd.o | 81 | obj-$(CONFIG_COBALT_LCD) += lcd.o |
83 | obj-$(CONFIG_PPDEV) += ppdev.o | 82 | obj-$(CONFIG_PPDEV) += ppdev.o |
84 | obj-$(CONFIG_NWBUTTON) += nwbutton.o | 83 | obj-$(CONFIG_NWBUTTON) += nwbutton.o |
diff --git a/drivers/char/ftape/Kconfig b/drivers/char/ftape/Kconfig deleted file mode 100644 index 0d65189a7ae8..000000000000 --- a/drivers/char/ftape/Kconfig +++ /dev/null | |||
@@ -1,330 +0,0 @@ | |||
1 | # | ||
2 | # Ftape configuration | ||
3 | # | ||
4 | config ZFTAPE | ||
5 | tristate "Zftape, the VFS interface" | ||
6 | depends on FTAPE | ||
7 | ---help--- | ||
8 | Normally, you want to say Y or M. DON'T say N here or you | ||
9 | WON'T BE ABLE TO USE YOUR FLOPPY TAPE DRIVE. | ||
10 | |||
11 | The ftape module itself no longer contains the routines necessary | ||
12 | to interface with the kernel VFS layer (i.e. to actually write data | ||
13 | to and read data from the tape drive). Instead the file system | ||
14 | interface (i.e. the hardware independent part of the driver) has | ||
15 | been moved to a separate module. | ||
16 | |||
17 | To compile this driver as a module, choose M here: the | ||
18 | module will be called zftape. | ||
19 | |||
20 | Regardless of whether you say Y or M here, an additional runtime | ||
21 | loadable module called `zft-compressor' which contains code to | ||
22 | support user transparent on-the-fly compression based on Ross | ||
23 | William's lzrw3 algorithm will be produced. If you have enabled the | ||
24 | kernel module loader (i.e. have said Y to "Kernel module loader | ||
25 | support", above) then `zft-compressor' will be loaded | ||
26 | automatically by zftape when needed. | ||
27 | |||
28 | Despite its name, zftape does NOT use compression by default. | ||
29 | |||
30 | config ZFT_DFLT_BLK_SZ | ||
31 | int "Default block size" | ||
32 | depends on ZFTAPE | ||
33 | default "10240" | ||
34 | ---help--- | ||
35 | If unsure leave this at its default value, i.e. 10240. Note that | ||
36 | you specify only the default block size here. The block size can be | ||
37 | changed at run time using the MTSETBLK tape operation with the | ||
38 | MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the | ||
39 | shell command line). | ||
40 | |||
41 | The probably most striking difference between zftape and previous | ||
42 | versions of ftape is the fact that all data must be written or read | ||
43 | in multiples of a fixed block size. The block size defaults to | ||
44 | 10240 which is what GNU tar uses. The values for the block size | ||
45 | should be either 1 or multiples of 1024 up to a maximum value of | ||
46 | 63488 (i.e. 62 K). If you specify `1' then zftape's builtin | ||
47 | compression will be disabled. | ||
48 | |||
49 | Reasonable values are `10240' (GNU tar's default block size), | ||
50 | `5120' (afio's default block size), `32768' (default block size some | ||
51 | backup programs assume for SCSI tape drives) or `1' (no restriction | ||
52 | on block size, but disables builtin compression). | ||
53 | |||
54 | comment "The compressor will be built as a module only!" | ||
55 | depends on FTAPE && ZFTAPE | ||
56 | |||
57 | config ZFT_COMPRESSOR | ||
58 | tristate | ||
59 | depends on FTAPE!=n && ZFTAPE!=n | ||
60 | default m | ||
61 | |||
62 | config FT_NR_BUFFERS | ||
63 | int "Number of ftape buffers (EXPERIMENTAL)" | ||
64 | depends on FTAPE && EXPERIMENTAL | ||
65 | default "3" | ||
66 | help | ||
67 | Please leave this at `3' unless you REALLY know what you are doing. | ||
68 | It is not necessary to change this value. Values below 3 make the | ||
69 | proper use of ftape impossible, values greater than 3 are a waste of | ||
70 | memory. You can change the amount of DMA memory used by ftape at | ||
71 | runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer | ||
72 | wastes 32 KB of memory. Please note that this memory cannot be | ||
73 | swapped out. | ||
74 | |||
75 | config FT_PROC_FS | ||
76 | bool "Enable procfs status report (+2kb)" | ||
77 | depends on FTAPE && PROC_FS | ||
78 | ---help--- | ||
79 | Optional. Saying Y will result in creation of a directory | ||
80 | `/proc/ftape' under the /proc file system. The files can be viewed | ||
81 | with your favorite pager (i.e. use "more /proc/ftape/history" or | ||
82 | "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The | ||
83 | file will contain some status information about the inserted | ||
84 | cartridge, the kernel driver, your tape drive, the floppy disk | ||
85 | controller and the error history for the most recent use of the | ||
86 | kernel driver. Saying Y will enlarge the size of the ftape driver | ||
87 | by approximately 2 KB. | ||
88 | |||
89 | WARNING: When compiling ftape as a module (i.e. saying M to "Floppy | ||
90 | tape drive") it is dangerous to use ftape's /proc file system | ||
91 | interface. Accessing `/proc/ftape' while the module is unloaded will | ||
92 | result in a kernel Oops. This cannot be fixed from inside ftape. | ||
93 | |||
94 | choice | ||
95 | prompt "Debugging output" | ||
96 | depends on FTAPE | ||
97 | default FT_NORMAL_DEBUG | ||
98 | |||
99 | config FT_NORMAL_DEBUG | ||
100 | bool "Normal" | ||
101 | ---help--- | ||
102 | This option controls the amount of debugging output the ftape driver | ||
103 | is ABLE to produce; it does not increase or diminish the debugging | ||
104 | level itself. If unsure, leave this at its default setting, | ||
105 | i.e. choose "Normal". | ||
106 | |||
107 | Ftape can print lots of debugging messages to the system console | ||
108 | resp. kernel log files. Reducing the amount of possible debugging | ||
109 | output reduces the size of the kernel module by some KB, so it might | ||
110 | be a good idea to use "None" for emergency boot floppies. | ||
111 | |||
112 | If you want to save memory then the following strategy is | ||
113 | recommended: leave this option at its default setting "Normal" until | ||
114 | you know that the driver works as expected, afterwards reconfigure | ||
115 | the kernel, this time specifying "Reduced" or "None" and recompile | ||
116 | and install the kernel as usual. Note that choosing "Excessive" | ||
117 | debugging output does not increase the amount of debugging output | ||
118 | printed to the console but only makes it possible to produce | ||
119 | "Excessive" debugging output. | ||
120 | |||
121 | Please read <file:Documentation/ftape.txt> for a short description | ||
122 | how to control the amount of debugging output. | ||
123 | |||
124 | config FT_FULL_DEBUG | ||
125 | bool "Excessive" | ||
126 | help | ||
127 | Extremely verbose output for driver debugging purposes. | ||
128 | |||
129 | config FT_NO_TRACE | ||
130 | bool "Reduced" | ||
131 | help | ||
132 | Reduced tape driver debugging output. | ||
133 | |||
134 | config FT_NO_TRACE_AT_ALL | ||
135 | bool "None" | ||
136 | help | ||
137 | Suppress all debugging output from the tape drive. | ||
138 | |||
139 | endchoice | ||
140 | |||
141 | comment "Hardware configuration" | ||
142 | depends on FTAPE | ||
143 | |||
144 | choice | ||
145 | prompt "Floppy tape controllers" | ||
146 | depends on FTAPE | ||
147 | default FT_STD_FDC | ||
148 | |||
149 | config FT_STD_FDC | ||
150 | bool "Standard" | ||
151 | ---help--- | ||
152 | Only change this setting if you have a special controller. If you | ||
153 | didn't plug any add-on card into your computer system but just | ||
154 | plugged the floppy tape cable into the already existing floppy drive | ||
155 | controller then you don't want to change the default setting, | ||
156 | i.e. choose "Standard". | ||
157 | |||
158 | Choose "MACH-2" if you have a Mountain Mach-2 controller. | ||
159 | Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20 | ||
160 | controller. | ||
161 | Choose "Alt/82078" if you have another controller that is located at | ||
162 | an IO base address different from the standard floppy drive | ||
163 | controller's base address of `0x3f0', or uses an IRQ (interrupt) | ||
164 | channel different from `6', or a DMA channel different from | ||
165 | `2'. This is necessary for any controller card that is based on | ||
166 | Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high | ||
167 | speed" controllers. | ||
168 | |||
169 | If you choose something other than "Standard" then please make | ||
170 | sure that the settings for the IO base address and the IRQ and DMA | ||
171 | channel in the configuration menus below are correct. Use the manual | ||
172 | of your tape drive to determine the correct settings! | ||
173 | |||
174 | If you are already successfully using your tape drive with another | ||
175 | operating system then you definitely should use the same settings | ||
176 | for the IO base, the IRQ and DMA channel that have proven to work | ||
177 | with that other OS. | ||
178 | |||
179 | Note that this menu lets you specify only the default setting for | ||
180 | the hardware setup. The hardware configuration can be changed at | ||
181 | boot time (when ftape is compiled into the kernel, i.e. if you | ||
182 | have said Y to "Floppy tape drive") or module load time (i.e. if you | ||
183 | have said M to "Floppy tape drive"). | ||
184 | |||
185 | Please read also the file <file:Documentation/ftape.txt> which | ||
186 | contains a short description of the parameters that can be set at | ||
187 | boot or load time. If you want to use your floppy tape drive on a | ||
188 | PCI-bus based system, please read the file | ||
189 | <file:drivers/char/ftape/README.PCI>. | ||
190 | |||
191 | config FT_MACH2 | ||
192 | bool "MACH-2" | ||
193 | |||
194 | config FT_PROBE_FC10 | ||
195 | bool "FC-10/FC-20" | ||
196 | |||
197 | config FT_ALT_FDC | ||
198 | bool "Alt/82078" | ||
199 | |||
200 | endchoice | ||
201 | |||
202 | comment "Consult the manuals of your tape drive for the correct settings!" | ||
203 | depends on FTAPE && !FT_STD_FDC | ||
204 | |||
205 | config FT_FDC_BASE | ||
206 | hex "IO base of the floppy disk controller" | ||
207 | depends on FTAPE && !FT_STD_FDC | ||
208 | default "0" | ||
209 | ---help--- | ||
210 | You don't need to specify a value if the following default | ||
211 | settings for the base IO address are correct: | ||
212 | <<< MACH-2 : 0x1E0 >>> | ||
213 | <<< FC-10/FC-20: 0x180 >>> | ||
214 | <<< Secondary : 0x370 >>> | ||
215 | Secondary refers to a secondary FDC controller like the "high speed" | ||
216 | controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash. | ||
217 | Please make sure that the setting for the IO base address | ||
218 | specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR | ||
219 | CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already | ||
220 | successfully using the tape drive with another operating system then | ||
221 | you definitely should use the same settings for the IO base that has | ||
222 | proven to work with that other OS. | ||
223 | |||
224 | Note that this menu lets you specify only the default setting for | ||
225 | the IO base. The hardware configuration can be changed at boot time | ||
226 | (when ftape is compiled into the kernel, i.e. if you specified Y to | ||
227 | "Floppy tape drive") or module load time (i.e. if you have said M to | ||
228 | "Floppy tape drive"). | ||
229 | |||
230 | Please read also the file <file:Documentation/ftape.txt> which | ||
231 | contains a short description of the parameters that can be set at | ||
232 | boot or load time. | ||
233 | |||
234 | config FT_FDC_IRQ | ||
235 | int "IRQ channel of the floppy disk controller" | ||
236 | depends on FTAPE && !FT_STD_FDC | ||
237 | default "0" | ||
238 | ---help--- | ||
239 | You don't need to specify a value if the following default | ||
240 | settings for the interrupt channel are correct: | ||
241 | <<< MACH-2 : 6 >>> | ||
242 | <<< FC-10/FC-20: 9 >>> | ||
243 | <<< Secondary : 6 >>> | ||
244 | Secondary refers to secondary a FDC controller like the "high speed" | ||
245 | controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash. | ||
246 | Please make sure that the setting for the IO base address | ||
247 | specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR | ||
248 | CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already | ||
249 | successfully using the tape drive with another operating system then | ||
250 | you definitely should use the same settings for the IO base that has | ||
251 | proven to work with that other OS. | ||
252 | |||
253 | Note that this menu lets you specify only the default setting for | ||
254 | the IRQ channel. The hardware configuration can be changed at boot | ||
255 | time (when ftape is compiled into the kernel, i.e. if you said Y to | ||
256 | "Floppy tape drive") or module load time (i.e. if you said M to | ||
257 | "Floppy tape drive"). | ||
258 | |||
259 | Please read also the file <file:Documentation/ftape.txt> which | ||
260 | contains a short description of the parameters that can be set at | ||
261 | boot or load time. | ||
262 | |||
263 | config FT_FDC_DMA | ||
264 | int "DMA channel of the floppy disk controller" | ||
265 | depends on FTAPE && !FT_STD_FDC | ||
266 | default "0" | ||
267 | ---help--- | ||
268 | You don't need to specify a value if the following default | ||
269 | settings for the DMA channel are correct: | ||
270 | <<< MACH-2 : 2 >>> | ||
271 | <<< FC-10/FC-20: 3 >>> | ||
272 | <<< Secondary : 2 >>> | ||
273 | Secondary refers to a secondary FDC controller like the "high speed" | ||
274 | controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash. | ||
275 | Please make sure that the setting for the IO base address | ||
276 | specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR | ||
277 | CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already | ||
278 | successfully using the tape drive with another operating system then | ||
279 | you definitely should use the same settings for the IO base that has | ||
280 | proven to work with that other OS. | ||
281 | |||
282 | Note that this menu lets you specify only the default setting for | ||
283 | the DMA channel. The hardware configuration can be changed at boot | ||
284 | time (when ftape is compiled into the kernel, i.e. if you said Y to | ||
285 | "Floppy tape drive") or module load time (i.e. if you said M to | ||
286 | "Floppy tape drive"). | ||
287 | |||
288 | Please read also the file <file:Documentation/ftape.txt> which | ||
289 | contains a short description of the parameters that can be set at | ||
290 | boot or load time. | ||
291 | |||
292 | config FT_FDC_THR | ||
293 | int "Default FIFO threshold (EXPERIMENTAL)" | ||
294 | depends on FTAPE && EXPERIMENTAL | ||
295 | default "8" | ||
296 | help | ||
297 | Set the FIFO threshold of the FDC. If this is higher the DMA | ||
298 | controller may serve the FDC after a higher latency time. If this is | ||
299 | lower, fewer DMA transfers occur leading to less bus contention. | ||
300 | You may try to tune this if ftape annoys you with "reduced data | ||
301 | rate because of excessive overrun errors" messages. However, this | ||
302 | doesn't seem to have too much effect. | ||
303 | |||
304 | If unsure, don't touch the initial value, i.e. leave it at "8". | ||
305 | |||
306 | config FT_FDC_MAX_RATE | ||
307 | int "Maximal data rate to use (EXPERIMENTAL)" | ||
308 | depends on FTAPE && EXPERIMENTAL | ||
309 | default "2000" | ||
310 | ---help--- | ||
311 | With some motherboard/FDC combinations ftape will not be able to | ||
312 | run your FDC/tape drive combination at the highest available | ||
313 | speed. If this is the case you'll encounter "reduced data rate | ||
314 | because of excessive overrun errors" messages and lots of retries | ||
315 | before ftape finally decides to reduce the data rate. | ||
316 | |||
317 | In this case it might be desirable to tell ftape beforehand that | ||
318 | it need not try to run the tape drive at the highest available | ||
319 | speed. If unsure, leave this disabled, i.e. leave it at 2000 | ||
320 | bits/sec. | ||
321 | |||
322 | config FT_ALPHA_CLOCK | ||
323 | int "CPU clock frequency of your DEC Alpha" if ALPHA | ||
324 | depends on FTAPE | ||
325 | default "0" | ||
326 | help | ||
327 | On some DEC Alpha machines the CPU clock frequency cannot be | ||
328 | determined automatically, so you need to specify it here ONLY if | ||
329 | running a DEC Alpha, otherwise this setting has no effect. | ||
330 | |||
diff --git a/drivers/char/ftape/Makefile b/drivers/char/ftape/Makefile deleted file mode 100644 index 0e67d2f8b7ec..000000000000 --- a/drivers/char/ftape/Makefile +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 1997 Claus Heine. | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 2, or (at your option) | ||
7 | # any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program; see the file COPYING. If not, write to | ||
16 | # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | # | ||
18 | # $Source: /homes/cvs/ftape-stacked/ftape/Makefile,v $ | ||
19 | # $Revision: 1.4 $ | ||
20 | # $Date: 1997/10/05 19:17:56 $ | ||
21 | # | ||
22 | # Makefile for the QIC-40/80/3010/3020 floppy-tape driver for | ||
23 | # Linux. | ||
24 | # | ||
25 | |||
26 | obj-$(CONFIG_FTAPE) += lowlevel/ | ||
27 | obj-$(CONFIG_ZFTAPE) += zftape/ | ||
28 | obj-$(CONFIG_ZFT_COMPRESSOR) += compressor/ | ||
diff --git a/drivers/char/ftape/README.PCI b/drivers/char/ftape/README.PCI deleted file mode 100644 index 18de159d36e0..000000000000 --- a/drivers/char/ftape/README.PCI +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | Some notes for ftape users with PCI motherboards: | ||
2 | ================================================= | ||
3 | |||
4 | The problem: | ||
5 | ------------ | ||
6 | |||
7 | There have been some problem reports from people using PCI-bus based | ||
8 | systems getting overrun errors. | ||
9 | I wasn't able to reproduce these until I ran ftape on a Intel Plato | ||
10 | (Premiere PCI II) motherboard with bios version 1.00.08AX1. | ||
11 | It turned out that if GAT (Guaranteed Access Timing) is enabled (?) | ||
12 | ftape gets a lot of overrun errors. | ||
13 | The problem disappears when disabling GAT in the bios. | ||
14 | Note that Intel removed this setting (permanently disabled) from the | ||
15 | 1.00.10AX1 bios ! | ||
16 | |||
17 | It looks like that if GAT is enabled there are often large periods | ||
18 | (greater than 120 us !??) on the ISA bus that the DMA controller cannot | ||
19 | service the floppy disk controller. | ||
20 | I cannot imagine this being acceptable in a decent PCI implementation. | ||
21 | Maybe this is a `feature' of the chipset. I can only speculate why | ||
22 | Intel choose to remove the option from the latest Bios... | ||
23 | |||
24 | The lesson of this all is that there may be other motherboard | ||
25 | implementations having the same of similar problems. | ||
26 | If you experience a lot of overrun errors during a backup to tape, | ||
27 | see if there is some setting in the Bios that may influence the | ||
28 | bus timing. | ||
29 | |||
30 | I judge this a hardware problem and not a limitation of ftape ;-) | ||
31 | My DOS backup software seems to be suffering from the same problems | ||
32 | and even refuses to run at 1 Mbps ! | ||
33 | Ftape will reduce the data-rate from 1 Mbps to 500 Kbps if the number | ||
34 | of overrun errors on a track exceeds a threshold. | ||
35 | |||
36 | |||
37 | Possible solutions: | ||
38 | ------------------- | ||
39 | |||
40 | Some of the problems were solved by upgrading the (flash) bios. | ||
41 | Other suggest that it has to do with the FDC being on the PCI | ||
42 | bus, but that is not the case with the Intel Premiere II boards. | ||
43 | [If upgrading the bios doesn't solve the problem you could try | ||
44 | a floppy disk controller on the isa-bus]. | ||
45 | |||
46 | Here is a list of systems and recommended BIOS settings: | ||
47 | |||
48 | |||
49 | Intel Premiere PCI (Revenge): | ||
50 | |||
51 | Bios version 1.00.09.AF2 is reported to work. | ||
52 | |||
53 | |||
54 | |||
55 | Intel Premiere PCI II (Plato): | ||
56 | |||
57 | Bios version 1.00.10.AX1 and version 11 beta are ok. | ||
58 | If using version 1.00.08.AX1, GAT must be disabled ! | ||
59 | |||
60 | |||
61 | |||
62 | ASUS PCI/I-SP3G: | ||
63 | |||
64 | Preferred settings: ISA-GAT-mode : disabled | ||
65 | DMA-linebuffer-mode : standard | ||
66 | ISA-masterbuffer-mode : standard | ||
67 | |||
68 | |||
69 | DELL Dimension XPS P90 | ||
70 | |||
71 | Bios version A2 is reported to be broken, while bios version A5 works. | ||
72 | You can get a flash bios upgrade from http://www.dell.com | ||
73 | |||
74 | |||
75 | To see if you're having the GAT problem, try making a backup | ||
76 | under DOS. If it's very slow and often repositions you're | ||
77 | probably having this problem. | ||
78 | |||
79 | --//-- | ||
80 | LocalWords: ftape PCI bios GAT ISA DMA chipset Mbps Kbps FDC isa AF ok ASUS | ||
81 | LocalWords: SP linebuffer masterbuffer XPS http www com | ||
diff --git a/drivers/char/ftape/RELEASE-NOTES b/drivers/char/ftape/RELEASE-NOTES deleted file mode 100644 index 03799dbc05a4..000000000000 --- a/drivers/char/ftape/RELEASE-NOTES +++ /dev/null | |||
@@ -1,966 +0,0 @@ | |||
1 | Hey, Emacs, we're -*-Text-*- mode! | ||
2 | |||
3 | ===== Release notes for ftape-3.04d 25/11/97 ===== | ||
4 | - The correct pre-processor statement for "else if" is "#elif" not | ||
5 | "elsif". | ||
6 | - Need to call zft_reset_position() when overwriting cartridges | ||
7 | previously written with ftape-2.x, sftape, or ancient | ||
8 | (pre-ftape-3.x) versions of zftape. | ||
9 | |||
10 | ===== Release notes for ftape-3.04c 16/11/97 ===== | ||
11 | - fdc_probe() was calling DUMPREGS with a result length of "1" which | ||
12 | was just fine. Undo previous change. | ||
13 | |||
14 | ===== Release notes for ftape-3.04b 14/11/97 ===== | ||
15 | |||
16 | - patches/2.x.x/floppy.c.diff was somewhat broken, releasing i/o | ||
17 | regions it never had allocated. | ||
18 | - fdc_probe() was calling DUMPREGS with a result length of "1" instead | ||
19 | of "10" | ||
20 | - Writing deleted data marks if the first segents on track zero are | ||
21 | should work now. | ||
22 | - ftformat should now be able to handle those cases where the tape | ||
23 | drive sets the read only status bit (QIC-40/80 cartridges with | ||
24 | QIC-3010/3020 tape drives) because the header segment is damaged. | ||
25 | - the MTIOCFTCMD ioctl may now be issued by the superuser ONLY. | ||
26 | |||
27 | ===== Release notes for ftape-3.04a 12/11/97 ===== | ||
28 | - Fix an "infinite loop can't be killed by signal" bug in | ||
29 | ftape_get_drive_status(). Only relevant when trying to access | ||
30 | buggy/misconfigured hardware | ||
31 | - Try to compensate a bug in the HP Colorado T3000's firmware: it | ||
32 | doesn't set the write protect bit for QIC80/QIC40 cartridges. | ||
33 | |||
34 | ===== Release notes for ftape-3.04 06/11/97 ===== | ||
35 | - If positioning with fast seeking fails fall back to a slow seek | ||
36 | before giving up. | ||
37 | - (nearly) no retries on "no data errors" when verifying after | ||
38 | formatting. Improved tuning of the bad sector map after formatting. | ||
39 | - the directory layout has changed again to allow for easier kernel | ||
40 | integration | ||
41 | - Module parameter "ftape_tracing" now is called "ft_tracing" because | ||
42 | the "ftape_tracing" variable has the version checksum attached to it. | ||
43 | - `/proc/ftape' interface for 2.0.* kernels. `/proc/ftape' no longer | ||
44 | is a directory but a file that contains all the information formerly | ||
45 | provided in separate files under the `/proc/ftape/' directory. | ||
46 | - Most of the configuration options have been prefixed by "CONFIG_FT_" | ||
47 | in preparation of the kernel inclusion. The Makefiles under | ||
48 | "./ftape/" should be directly usable by the kernel. | ||
49 | - The MODVERSIONS stuff is now auto-detected. | ||
50 | - Broke backslashed multi line options in MCONFIG into separate lines | ||
51 | using GNU-make's "+=" feature. | ||
52 | - The html and dvi version of the manual is now installed under | ||
53 | '/usr/doc/ftape` with 'make install` | ||
54 | - New SMP define in MCONFIG. ftape works with SMP if this is defined. | ||
55 | - attempt to cope with "excessive overrun errors" by gradually | ||
56 | increasing FDC FIFO threshold. But this doesn't seem to have too | ||
57 | much an effect. | ||
58 | - New load time configuration parameter "ft_fdc_rate_limit". If you | ||
59 | encounter too many overrun errors with a 2Mb controller then you | ||
60 | might want to set this to 1000. | ||
61 | - overrun errors on the last sector in a segment sometimes result in | ||
62 | a zero DMA residue. Dunno why, but compensate for it. | ||
63 | - there were still fdc_read() timeout errors. I think I have fixed it | ||
64 | now, please FIXME. | ||
65 | - Sometimes ftape_write() failed to re-start the tape drive when a | ||
66 | segment without a good sector was reached ("wait for empty segment | ||
67 | failed"). This is fixed. Especially important for > QIC-3010. | ||
68 | - sftape (aka ftape-2.x) has vanished. I didn't work on it for | ||
69 | ages. It is probably still possible to use the old code with | ||
70 | ftape-3.04, if one really needs it (BUT RECOMPILE IT) | ||
71 | - zftape no longer alters the contents of already existing volume | ||
72 | table entries, which makes it possible to fill in missing fields, | ||
73 | like time stamps using some user space program. | ||
74 | - ./contrib/vtblc/ contains such a program. | ||
75 | - new perl script ./contrib/scripts/listtape that list the contents of a | ||
76 | floppy tape cartridge parsing the output of "mt volinfo" + "mt fsf" | ||
77 | - the MTWEOF implementation has changed a little bit (after I had a | ||
78 | look at amanda). Calling MTWEOF while the tape is still held open | ||
79 | after writing something to the tape now will terminate the current | ||
80 | volume, and start a new one at the current position. | ||
81 | - the volume table maintained by zftape now is a doubly linked list | ||
82 | that grows dynamically as needed. | ||
83 | |||
84 | formatting floppy tape cartridges | ||
85 | --------------------------------- | ||
86 | * there is a new user space formatting program that does most of the | ||
87 | dirty work in user space (auto-detect, computing the sector | ||
88 | coordinates, adjusting time stamps and statistics). It has a | ||
89 | simple command line interface. | ||
90 | * ftape-format.o has vanished, it has been folded into the low level | ||
91 | ftape.o module, and the ioctl interface into zftape.o. Most of the | ||
92 | complicated stuff has been moved to user space, so there was no | ||
93 | need for a separate module anymore. | ||
94 | * there is a new ioctl MTIOCFTCMD that sends a bare QIC-117 command | ||
95 | to the tape drive. | ||
96 | * there is a new mmap() feature to map the dma buffers into user | ||
97 | space to be used by the user level formatting program. | ||
98 | * Formatting of yet unformatted or totally degaussed cartridges | ||
99 | should be possible now. FIXME. | ||
100 | |||
101 | ===== Release notes for ftape-3.03b, <forgot the exact date> ==== | ||
102 | |||
103 | ftape-3.03b was released as a beta release only. Its main new feature | ||
104 | was support of the DITTO-2GB drive. This was made possible by reverse | ||
105 | engineering done by <fill in his name> after Iomega failed to support | ||
106 | ftape. Although they had promised to do so (this makes me feel a bit | ||
107 | sad and uncomfortable about Iomega). | ||
108 | |||
109 | ===== Release notes for ftape-3.03a, 22/05/97 ==== | ||
110 | |||
111 | - Finally fixed auto-un-loading of modules for kernels > 2.1.18 | ||
112 | - Add an "uninstall" target to the Makefile | ||
113 | - removed the kdtime hack | ||
114 | - texi2www didn't properly set the back-reference from a footnote back | ||
115 | to the regular text. | ||
116 | |||
117 | zftape specific | ||
118 | --------------- | ||
119 | * hide the old compression map volume. Taper doesn't accept the | ||
120 | presence of non-Taper volumes and Taper-written volume on the same | ||
121 | tape. | ||
122 | * EOD (End Of Data) handling was still broken: the expected behavior | ||
123 | is to return a zero byte count at the first attempt to read past | ||
124 | EOD, return a zero byte count at the second attempt to read past | ||
125 | EOD and THEN return -EIO. | ||
126 | |||
127 | ftape-format specific | ||
128 | --------------------- | ||
129 | * Detection of QIC-40 cartridges in select_tape_format() was broken | ||
130 | and made it impossible to format QIC-3010/3020 cartridges. | ||
131 | * There are strange "TR-1 Extra" cartridges out there which weren't | ||
132 | detected properly because the don't strictly conform to the | ||
133 | QIC-80, Rev. N, spec. | ||
134 | |||
135 | ===== Release notes for ftape-3.03, 30/04/97 ===== | ||
136 | |||
137 | - Removed kernel integration code from the package. I plan to provide | ||
138 | a package that can be integrated into the stock kernel separately | ||
139 | (hopefully soon). | ||
140 | As a result, a simple `make' command now will build everything. | ||
141 | - ALL compile time configuration options have been moved to the file | ||
142 | `MCONFIG'. | ||
143 | - Quite a few `low level' changes to allow formatting of cartridges. | ||
144 | - formatting is implemented as a separate module `ftape-format.o'. The | ||
145 | modified `mt' program contains sample code that shows how to use it. | ||
146 | - The VFS interface has been moved from the `ftape.o' module to the | ||
147 | high level modules `zftape.o' resp. `sftape.o'. `ftape.o' contains | ||
148 | the hardware support only. | ||
149 | - A bit of /proc support for kernels > 2.1.28 | ||
150 | - Moved documentation to Doc subdir. INSTALL now contains some real | ||
151 | installation notes. | ||
152 | - `install' target in Makefile. | ||
153 | |||
154 | zftape specific: | ||
155 | ---------------- | ||
156 | |||
157 | - zftape works for large cartridges now ( > 2^31 bytes) | ||
158 | - MTIOCVOLINFO and MTIOCGETSIZE now return the size in KILOBYTES, | ||
159 | NO LONGER in bytes. | ||
160 | |||
161 | - permissions for write access to a cartridge have changed: | ||
162 | * zftape now also takes the file access mode into account | ||
163 | * zftape no longer allows writing in the middle of the recorded | ||
164 | media. The tape has to be positioned at BOT or EOD for write | ||
165 | access. | ||
166 | |||
167 | - MTBSF has changed. It used to position at the beginning of the | ||
168 | previous file when called with count 1. This was different from the | ||
169 | expected behavior for other Un*x tape drivers (i.e. SCSI). MTBSF | ||
170 | with count 1 should merely position at the beginning of the current | ||
171 | volume. Fixed. As a result, `tar --verify' now produces the desired | ||
172 | result: it verifies the last written volume, not the pre-last | ||
173 | written volume. | ||
174 | |||
175 | - The compression map has vanished --> no need for `mt erase' any | ||
176 | more. Fast seeking in a compressed volume is still be possible, but | ||
177 | takes slightly longer. As a side effect, you may experience an | ||
178 | additional volume showing up in front of all others for old | ||
179 | cartridges. This is the tape volume that holds the compression map. | ||
180 | |||
181 | - The compression support for zftape has been moved to a separate | ||
182 | module `zft-compressor'. DON'T forget to load it before trying to | ||
183 | read back compressed volumes. The stock `zftape.o' module probes for | ||
184 | the module `zft-compressor' using the kerneld message channel; you | ||
185 | have to install `zft-compressor.o' in a place where modprobe can | ||
186 | find it if you want to use this. | ||
187 | |||
188 | - New experimental feature that tries to get the broken down GMT time | ||
189 | from user space via a kernel daemon message channel. You need to | ||
190 | compile and start the `kdtime' daemon contained in the contrib | ||
191 | directory to use it. Needed (?) for time stamps in the header | ||
192 | segments and the volume table. | ||
193 | |||
194 | - variable block size mode via MTSETBLK 0 | ||
195 | |||
196 | - keep modules locked in memory after the block size has been changed | ||
197 | |||
198 | sftape specific: | ||
199 | ---------------- | ||
200 | |||
201 | - end of tape handling should be fixed, i.e. multi volume archives | ||
202 | written with `afio' can be read back now. | ||
203 | |||
204 | |||
205 | ===== Release notes for ftape-3.02a, 09/01/97 ===== | ||
206 | |||
207 | No big news: | ||
208 | - call zft_init() resp. sft_init() when compiling the entire stuff | ||
209 | into the kernel image. | ||
210 | - fix bug in ftape-setup.c when NO_TRACE_AT_ALL was defined. | ||
211 | - fix bug in sftape-eof.c/zftape-eof.c for old kernels (1.2.*) | ||
212 | - add support for new module interface for recent kernels | ||
213 | |||
214 | ===== Release notes for ftape-3.02, 16/12/96 ===== | ||
215 | - Fixed the `FDC unlock command failed' bug in fdc-io.c. When the FIFO | ||
216 | was already locked when ftape was loaded, ftape failed to unlock it. | ||
217 | - Fixed compilation of `contrib/gnumt'. It now finds `mtio.h' even if | ||
218 | ftape is NOT included into the kernel source tree. | ||
219 | - fc-10.c: include <asm/io.h> for inb() and outb(). | ||
220 | - ftape/sftape/zftape: all global variable now have either a `ftape_', | ||
221 | a `ft_', `sft_', `zft_' or `qic_' prefix to prevent name clashes | ||
222 | with other parts of the kernel when including ftape into the kernel | ||
223 | source tree. | ||
224 | - Kerneld support has changed. `ftape' now searches for a module | ||
225 | `ftape-frontend' when none of the frontend (`sftape' or `zftape') is | ||
226 | loaded. Please refer to the `Installation/Loading ftape' section of | ||
227 | the TeXinfo manual. | ||
228 | - Add load resp. boot-time configuration of ftape. There are now | ||
229 | variables ft_fdc_base, ft_fdc_dma and ft_fdc_irq corresponding to | ||
230 | the former FDC_BASE etc. compile time definitions. One can also use | ||
231 | the kernel command line parameters to configure the driver if it is | ||
232 | compiled into the kernel. Also, the FC-10/FC-20 support is load-time | ||
233 | configurable now as well as the MACH-II hack (ft_probe_fc10, | ||
234 | resp. ft_mach2). Please refer to the section `Installation/Configure | ||
235 | ftape' of the TeXinfo manual. | ||
236 | - I removed the MODVERSIONS option from `Makefile.module'. Let me alone | ||
237 | with ftape and MODVERSIONS unless you include the ftape sources into | ||
238 | the kernel source tree. | ||
239 | - new vendors in `vendors.h': | ||
240 | * HP Colorado T3000 | ||
241 | * ComByte DoublePlay (including a bug fix for their broken | ||
242 | formatting software, thanks to whraven@njackn.com) | ||
243 | * Iomega DITTO 2GIG. NOTE: this drive cannot work with ftape because | ||
244 | the logical data layout of the cartridges used by this drive does | ||
245 | NOT conform to the QIC standards, it is a special Iomega specific | ||
246 | format. I've sent mail to Iomega but didn't receive an answer | ||
247 | yet. If you want this drive to be supported by ftape, ask Iomega | ||
248 | to give me information about it. | ||
249 | - zftape: | ||
250 | * re-introduced the MTIOC_ZFTAPE_GETBLKSZ ioctl for compatibility | ||
251 | with zftape 1.06a and earlier. Please don't use it when writing | ||
252 | new software, use the MTIOCVOLINFO ioctl instead. | ||
253 | * Major overhaul of the code that updates the header segments. Never | ||
254 | change the tape label unless erasing the tape. Thus we almost | ||
255 | never need to write the header segments, unless we would modify | ||
256 | the bad sector map which isn't done yet. Updating of volume table | ||
257 | and compression map more secure now although it takes a bit | ||
258 | longer. | ||
259 | * Fixed bug when aborting a write operation with a signal: zftape | ||
260 | now finishes the current volume (i.e. writes an eof marker) at the | ||
261 | current position. It didn't before which led to somehow *strange* | ||
262 | behavior in this cases. | ||
263 | * Keep module locked in memory when using it with the non-rewinding | ||
264 | devices and the tape is not logical at BOT. Needed for kerneld | ||
265 | support. | ||
266 | - sftape: | ||
267 | * Keep module locked in memory when using it with the non-rewinding | ||
268 | devices and the tape is not logical at BOT. Needed for kerneld | ||
269 | support. | ||
270 | |||
271 | ===== Release notes for ftape-3.01, 14/11/96 ===== | ||
272 | |||
273 | - Fixed silly bugs in ftape-3.00: | ||
274 | * MAKEDEV.ftape: major device number must be 27, not 23 | ||
275 | * sftape/sftape-read.c: sftape_read_header_segments() called | ||
276 | itself recursively instead of calling ftape_read_header_segment() | ||
277 | * zftape/qic-vtbl.h: conversion of ftape's file marks to zftape's | ||
278 | internal volume table was broken. | ||
279 | * patches/2.x.x/linux-2.0.21.dif: my RCS (resp. CVS) system replaced | ||
280 | the `$Revison:' etc. macros in the `ftape.h' concerning part of the | ||
281 | patch :-( Fixed. | ||
282 | * info/ftape.info: Fixed misspellings (`cp' <-> `cp -r' etc.) | ||
283 | * when ftape/sftape or ftape/zftape was compiled into the kernel the | ||
284 | variable ftape_status was declared twice. Fixed. | ||
285 | * removed reference to undeclared variable kernel_version when not | ||
286 | compiling as module | ||
287 | * fixed a bug introduced by the use of bit-fields for some flags | ||
288 | (i.e. write_protected, no_cartridge, formatted) | ||
289 | * flag `header_read' is now reset correctly to zero when tape is | ||
290 | removed. | ||
291 | - fixed a bug in sftape/sftape-eof.c that was already in the original | ||
292 | ftape code. MTFSF/BSF was not handled correctly when positioned | ||
293 | right before the file mark (think of tar) | ||
294 | - Changed TRACE macros (following a suggestion of Marcin Dalecki) to use | ||
295 | the predefined __FUNCTION__ macro of GCC. Spares about 4k of code. | ||
296 | - added new vendor id for Iomega DITTO 2GIG | ||
297 | - fixed a bug already present in zftape-1.06 when aborting a write | ||
298 | with a signal: we now finish the current volume at that | ||
299 | position. Header segments remain NOT up to date until an explicit call | ||
300 | to MTREW or MTOFFL is done. | ||
301 | |||
302 | ===== Release notes for ftape-3.00, 14/10/96 ===== | ||
303 | |||
304 | - Merged ftape with zftape. There are three modules now: | ||
305 | ftape for the hardware support, sftape for the implementation of the | ||
306 | original ftape eof mark stuff and zftape that implements zftape's way | ||
307 | of handling things (compression, volume table, tape blocks of | ||
308 | constant length) | ||
309 | - Documentation in TeXinfo format in the `info' subdirectory. | ||
310 | - New ioctls for zftape. See zftape/zftape.h | ||
311 | - Dummy formatting ioctl for ftape. See ftape.h | ||
312 | - Kernel patch files for the 2.*.* series to include ftape-3.00 in the | ||
313 | kernel source tree. These includes a kernel compatible Config.in | ||
314 | script and fairly large online information for the kernel configure | ||
315 | script. | ||
316 | - Support for compiling with Linux-1.2.13. | ||
317 | - Modified GNU mt from their cpio package that can handle the new | ||
318 | ioctls. | ||
319 | - ftape/sftape/zftape is kerneld save now! | ||
320 | |||
321 | Notes on sftape: | ||
322 | - sftape implements the eof handling code of the original ftape. If | ||
323 | you like to stick with the original ftape stuff, you have to use | ||
324 | this module, not zftape. | ||
325 | - sftape is kerneld save, unlike the original ftape. | ||
326 | - we keep the entire header segment now in memory, so no need to read | ||
327 | it before updating the header segments. Additional memory | ||
328 | consumption: 256 bytes. | ||
329 | |||
330 | Notes for zftape: | ||
331 | - zftape has support for tapes with format code 6 now, which use a | ||
332 | slightly different volume table format compared with other floppy | ||
333 | tapes. | ||
334 | - new ioctls for zftape. Have a look at zftape/zftape.h | ||
335 | - The internal volume table representation has changed for zftape. Old | ||
336 | cartridges are converted automatically. | ||
337 | - zftape no longer uses compression map segments, which have vanished | ||
338 | from the QIC specs, but creates volume table entry that reserves | ||
339 | enough space for the compression map. | ||
340 | - zftape is kerneld save now. | ||
341 | - we keep the entire header segment now in memory, so no need to read | ||
342 | it before updating the header segments. Additional memory | ||
343 | consumption: 256 bytes. | ||
344 | |||
345 | Notes for contrib/gnumt: | ||
346 | - modified mt from the GNU cpio package that supports all the new | ||
347 | ioctls of zftape. | ||
348 | Notes for contrib/swapout: | ||
349 | - This contains the swapout.c program that was written by Kai | ||
350 | Harrekilde-Pederson. I simply added a Makefile. | ||
351 | |||
352 | ===== Release notes for ftape-2.10, 14/10/96 ===== | ||
353 | |||
354 | The ftape maintainer has changed. | ||
355 | Kai Harrekilde-Petersen <khp@dolphinics.no> | ||
356 | has resigned from maintaining ftape, and I, | ||
357 | Claus-Justus Heine <claus@momo.math.rwth-aachen.de>, | ||
358 | have taken over. | ||
359 | |||
360 | - Added support for tapes with `format code 6', i.e. QIC-3020 tapes | ||
361 | with more than 2^16 segments. | ||
362 | - merged changes made by Bas Laarhoven with ftape-2.09. Refer | ||
363 | to his release notes below. I've included them into this | ||
364 | file unchanged for your reference. | ||
365 | - disabled call stack back trace for now. This new feature | ||
366 | introduced by the interim release 2.0.x still seems to | ||
367 | be buggy. | ||
368 | - Tried to minimize differences between the ftape version | ||
369 | to be included into the kernel source tree and the standalone | ||
370 | module version. | ||
371 | - Reintroduced support for Linux-1.2.13. Please refer to the | ||
372 | Install-guide. | ||
373 | |||
374 | ===== Release notes for ftape-2.09, 16/06/96 ===== | ||
375 | |||
376 | There aren't any really big news in this release, mostly just that I | ||
377 | (the maintainer) have changed my email address (due to a new job). My | ||
378 | new address is <khp@dolphinics.no> | ||
379 | |||
380 | - The CLK_48MHZ and FDC_82078SL options has gone (all 2Mbps cards seem | ||
381 | to use a 48MHz oscillator anyway and I haven't heard of an 'SL | ||
382 | chip out there). | ||
383 | - The S82078B has been `downgraded' to i82077AA compability. | ||
384 | - TESTING option revived. Right now, it'll enable the (seriously broken) | ||
385 | 2Mbps code. If you enable it, you'll experience a tape drive that's | ||
386 | *really* out to lunch! | ||
387 | - Some (bold) changes in the init code. Please notify me if they | ||
388 | break things for you. | ||
389 | |||
390 | ===== Release notes for ftape-2.08, 14/03/96 ===== | ||
391 | |||
392 | If you correct a problem with ftape, please send your patch to | ||
393 | khp@dolphinics.no too. | ||
394 | |||
395 | - Updated to reflect that NR_MEM_LISTS is gone in 1.3.74 | ||
396 | - Teac 700 added to list of known drives. | ||
397 | - The registered device name is now "ft" rather than "ftape". | ||
398 | |||
399 | ===== Release notes for ftape-2.07a, 14/03/96 ===== | ||
400 | |||
401 | Bugfixes by Marcin Dalecki <dalecki@namu03.gwdg.de>: | ||
402 | - In the last release it just compiled against 1.3.70; | ||
403 | now the params to request_irq() and free_irq are() are fixed, so it also | ||
404 | works in 1.3.73 :-) | ||
405 | - Support for modules is now correct for newer kernels. | ||
406 | |||
407 | ===== Release notes for ftape-2.07, 04/03/96 ===== | ||
408 | |||
409 | |||
410 | - ftape updated to compile against 1.3.70. | ||
411 | - Iomega 700 and Wangtek 3200 recognised. | ||
412 | |||
413 | |||
414 | ===== Release notes for ftape-2.06b, 13/02/96 ===== | ||
415 | |||
416 | Another simple bugfix version. | ||
417 | |||
418 | - Jumbo 700 recognised. | ||
419 | - Typo in vendors.h fixed. | ||
420 | |||
421 | |||
422 | ===== Release notes for ftape-2.06a, 10/02/96 ===== | ||
423 | |||
424 | This release is a simple bugfix version. | ||
425 | |||
426 | - Linux/SMP: ftape *should* work. | ||
427 | - FC-10/20: Only accepts IRQs 3-7, or 9. If IRQ 9, properly tell the card | ||
428 | to use IRQ 2. Thanks to Greg Crider (gcrider@iclnet.org) for finding and | ||
429 | locating this bug and testing the patch. | ||
430 | - Insight drive recognised correctly again. | ||
431 | - Motor-on wakeup version of the Iomega 250 drive added | ||
432 | |||
433 | |||
434 | ===== Release notes for ftape-2.06, 28/01/96 ===== | ||
435 | |||
436 | Special thanks go to Neal Friedman and Steven Sorbom for their | ||
437 | help in producing and testing this release. | ||
438 | |||
439 | I have continued to clean up the code, with an eye towards inclusion | ||
440 | of ftape in Linus' official kernel (In fact, as I type this, I am | ||
441 | running on a kernel with ftape support statically linked). I have | ||
442 | test-compiled ftape against my 1.2.13 tree without problems. | ||
443 | Hopefully, everything should be OK for the v1.2.x people. | ||
444 | |||
445 | WARNING! Alan Cox has mailed me that ftape does *NOT* work with | ||
446 | Linux/SMP. If you try to run ftape under Linux/SMP, it will cause a | ||
447 | kernel deadlock (which is worse than a panic). | ||
448 | |||
449 | - QIC-3020/TR-3: 1Mbps support works. Neal is capable of reading and | ||
450 | writing data to a tape. ftape will automatically detect the type of | ||
451 | tape (e.g. TR-3 vs QIC-80) and move the fdc in and out of | ||
452 | "perpendicular mode" as necessary. | ||
453 | - 2Mbps support is disabled by default, since it is not fully | ||
454 | debugged. If you are adventurous, remove -DFDC_82078SL in the | ||
455 | Makefile and see what happens :-) | ||
456 | - fdc detection: silly bugs removed (Only 2Mbps fdcs were affected) | ||
457 | and added detection of the National Semiconductors PC8744 fdc chip | ||
458 | (used in the PC873xx "super-IO" chips). | ||
459 | - Removed warning about incompatible types when compiling with Linux | ||
460 | 1.2.x. | ||
461 | - README.PCI updated with info about the DELL Dimension XPS P90. | ||
462 | - Connor TST3200R added to detected drives. | ||
463 | - `swapout' utility added to distribution. It will dirty 5Meg of | ||
464 | memory, trying to swap out other programs. Just say `make swapout' | ||
465 | to build it. ftape will do this automatically Real Soon Now (ie: | ||
466 | when I have found out which kernel memory alloc function to call). | ||
467 | |||
468 | |||
469 | ===== Release notes for ftape-2.05, 08/01/96 ===== | ||
470 | |||
471 | - For v1.2.x Kernels, you must apply the patch linux-1.2/ksyms.patch to | ||
472 | the kernel and rebuild it (it adds the __get_dma_pages symbol to | ||
473 | ksyms.c). | ||
474 | - Included new asm-i386/io.h file from v1.3.x kernel series, to enable | ||
475 | gcc v.2.7.[12] to compile v1.2.x kernels (linux-1.2/io.h). | ||
476 | - Module versions: If you wish to compile ftape as a versioned module, | ||
477 | you must first compile your kernel with CONFIG_MODVERSIONS=y. | ||
478 | Otherwise, you will get complaints that <linux/modversions.h> does not | ||
479 | exist (if that happens, a `touch modversions.h' will help you out). | ||
480 | - CLK_48MHZ: new define in the Makefile (default: non-zero). If you have | ||
481 | a tape controller card that uses the i82078(-1) chip, but cannot get | ||
482 | it to work with ftape, try set it to 0 (and please report this). | ||
483 | - QIC-3010/3020: Complete support is still missing, but will hopefully | ||
484 | come soon. Steven Sorbom has kindly provided me with hints about | ||
485 | this. Writing of QIC-3020 tapes definitely does NOT work (do not try | ||
486 | it! - the drive will not be in "perpendicular mode" and this will ruin | ||
487 | the formatting info on the tape). | ||
488 | - ftape_num_buffers is out of fashion: use NR_BUFFERS instead (and | ||
489 | recompile if you want to change it :-). | ||
490 | |||
491 | |||
492 | ===== Release notes for ftape-2.04, 01/01/96 ===== | ||
493 | |||
494 | This version by Kai Harrekilde-Petersen <khp@dolphinics.no> | ||
495 | |||
496 | - ALERT! Support for Kernels earlier then v1.1.85 is about to go away. | ||
497 | I intend to clean up some of the code (getting rid of an annoyingly | ||
498 | large numbers of #ifdef mostly), which means that support for | ||
499 | pre-1.1.85 kernels must go as well. | ||
500 | - NR_FTAPE_BUFFERS is gone; You can instead select the number of dma | ||
501 | buffers by saying `insmod ftape.o ftape_num_buffer=<n>' instead. | ||
502 | - Configure script gone. ftape will now automagically determine your | ||
503 | kernel version by /usr/include/linux/version.h instead. | ||
504 | - CONFIG_MODVERSIONS now work. All combinations of versioned / | ||
505 | unversioned kernel and ftape module works (at least with my 1.3.52 | ||
506 | kernel). | ||
507 | - If you have problems with inserting ftape into an old (1.2.x) | ||
508 | kernel (e.g. insmod says "1.2.8 does not match 1.2.8), recompile | ||
509 | your modules utilities with your new compiler. | ||
510 | - Reveal TB1400 drive added to vendors.h | ||
511 | - Support for the i82078-1 (2Mbps) chip is coming along. The | ||
512 | biggest problem is that I don't have such a card, which makes | ||
513 | testing / debugging somewhat problematic. The second biggest | ||
514 | problem is that I do not have the QIC-3010/3020 standards either. | ||
515 | Status right now is that the chip is detected, and it should be | ||
516 | possible to put it into 2Mbps mode. However, I do not know what | ||
517 | "extras" are needed to complete the support. Although putting the | ||
518 | i82078 into 1Mbps mode ought to work out of the box, it doesn't | ||
519 | (right now, ftape complains about id am errors). | ||
520 | |||
521 | |||
522 | ===== Release notes for ftape-2.04beta5, 29/12/95 ===== | ||
523 | |||
524 | Bas offline linux-tape | ||
525 | ---------------------- | ||
526 | For reasons only known to the majordomo mail list processor, Bas was | ||
527 | kicked off the linux-tape list sometime during the summer. Being | ||
528 | overworked at his for-pay job, he didn't notice it much. Instead I | ||
529 | (Kai, khp@dolphinics.no) has worked on ftape to produce the 2.04(beta) | ||
530 | version. | ||
531 | |||
532 | zftape | ||
533 | ------ | ||
534 | Note that there exists a much improved version of ftape, written by | ||
535 | Claus-Justus Heine <claus@willi.math.rwth-aachen.de> which is named | ||
536 | zftape, which conforms to the QIC-80 specs on how to mark backups, and | ||
537 | is capable of doing automatic compression. However, zftape makes | ||
538 | substantial changes to ftape, and I (Kai) have therefore declined to | ||
539 | integrate zftape into ftape. Hopefully, this will happen soon. | ||
540 | |||
541 | CONFIG_QIC117 removed from the kernel | ||
542 | ------------------------------------- | ||
543 | The biggest change of all is that ftape now will allocate its dma | ||
544 | buffers when it is inserted. The means that the CONFIG_QIC117 option | ||
545 | has disappeared from the Linux kernel as of v1.3.34. If you have an | ||
546 | earlier kernel, simply answer 'no' to the question will do the trick | ||
547 | (if you get complains about __get_free_pages() missing, contact the | ||
548 | linux-tape mailing list). | ||
549 | |||
550 | Note that ftape-2.04beta will work equally well on kernels with and | ||
551 | without `ftape support'. The only catch is, that you will waste | ||
552 | around 96-128Kb of precious DMA'able memory on a box that has ftape | ||
553 | support compiled in. | ||
554 | |||
555 | Now for the real changes: | ||
556 | |||
557 | - FC-20 can now use DMA channels 1, 2, and 3. Thanks to Daniel | ||
558 | Cohen, catman@wpi.edu. | ||
559 | - ftape no longer requires a (gigantic) 96Kb buffer to be statically | ||
560 | allocated by the kernel. | ||
561 | - Added new Iomega drive (8882) to vendors.h | ||
562 | - -fno-strength-reduce added to Makefile, since GCC is broken. | ||
563 | - i82078-1 (2Mbps) FDC support started. | ||
564 | |||
565 | |||
566 | ===== Release notes for ftape-2.03b, 27/05/95 ===== | ||
567 | |||
568 | - Prevented verify_area to return error if called with zero length. | ||
569 | - Fixed a bug in flush_buffers that caused too much padding to be | ||
570 | written when a final segment had bad sectors. | ||
571 | - Increased maximum fast-seek overshoot value from 5 to 10 segments. | ||
572 | - Breaking loop after 5 retries when positioning fails. | ||
573 | - Fixed wrong calculation of tape length for QIC-3010 and QIC-3020 | ||
574 | tapes (densities were swapped). | ||
575 | - Fixed wrong calculation of overshoot on seek_forward: Wrong sign | ||
576 | of error. | ||
577 | - Suppress (false) error message due to new tape loaded. | ||
578 | - Added two new CMS drives (11c3 and 11c5) to vendors.h. | ||
579 | |||
580 | |||
581 | ===== Release notes for ftape-2.03a, 09/05/95 ===== | ||
582 | |||
583 | - Fixed display of old error (even if already cleared) in ftape_open. | ||
584 | - Improved tape length detection, ioctls would fail for 425 ft tapes. | ||
585 | Until the tape length is calculated with data from the header | ||
586 | segment, we'll use worst-case values. | ||
587 | - Clear eof_mark after rewinding ioctls. | ||
588 | - Fixed wrong version message (2.03 had 2.02g id). | ||
589 | - Fixed bug that caused the fdc to be reset very frequently. | ||
590 | This shouldn't affect normal operation but the timing of the | ||
591 | report routines has changed again and that may cause problems. | ||
592 | We'll just have to find out.... | ||
593 | - Implemented correct write precompensation setting for QIC-3010/3020. | ||
594 | - Cleaned up fdc_interrupt_wait routine. Hope it still works :-) | ||
595 | - Finally removed (already disabled) special eof mark handling for | ||
596 | gnu tar. | ||
597 | - Changed order of get_dma_residue and disable_dma in fdc-isr.c | ||
598 | because the current order would fail on at least one system. | ||
599 | We're back to the original order again, hope (and expect) this | ||
600 | doesn't break any other system. | ||
601 | |||
602 | |||
603 | ===== Release notes for ftape-2.03, 07/05/95 ===== | ||
604 | |||
605 | (Changes refer to the first ftape-2.02 release) | ||
606 | |||
607 | Support for wide and extended length tapes | ||
608 | ------------------------------------------ | ||
609 | The Conner TSM 420 and 850 drives are reported to be working. | ||
610 | I haven't received any reports about other brands; the TSM 420 | ||
611 | and 850 seem to be the most widely used wide drives. | ||
612 | Extended length tapes (425 ft) with normal QIC-80 drives | ||
613 | are operating too (At least I've had no reports stating otherwise). | ||
614 | _Not_ yet completely supported (although they may work) are | ||
615 | QIC-3020 drives and 2 Mbps floppy disk controllers won't work at | ||
616 | the highest speed. | ||
617 | If someone is kind enough to send me one of these, I'll include | ||
618 | support for it too ;-) | ||
619 | |||
620 | Easier configuration | ||
621 | -------------------- | ||
622 | Problems due to wrong settings in the Makefile are prevented | ||
623 | by using a configuration script that sets the necessary (kernel | ||
624 | version dependent) compile time options. | ||
625 | This kernel version is now determined from the sources found | ||
626 | at /usr/src/linux, or if not found, the old way using | ||
627 | /proc/version. | ||
628 | Versioned modules will be used automatically when supported | ||
629 | by- and configured in- the kernel. | ||
630 | Note that the current modules code (1.1.87) is still broken | ||
631 | and _needs_ the fix included in the insmod directory. | ||
632 | Please don't send me any more Oops reports caused by insmod :-( | ||
633 | |||
634 | Reduced module size | ||
635 | ------------------- | ||
636 | The standard module size is much reduced and some compile time | ||
637 | options can even reduce it further. (I don't recommend this | ||
638 | for normal use but it can be handy for rescue diskettes) | ||
639 | |||
640 | Option: Approx. module size: | ||
641 | |||
642 | <standard> 150 Kb | ||
643 | NO_TRACE 125 Kb | ||
644 | NO_TRACE_AT_ALL 67 Kb | ||
645 | |||
646 | |||
647 | Much improved driver interruption | ||
648 | --------------------------------- | ||
649 | Most possible loops have been broken and signal detection | ||
650 | has been improved. | ||
651 | In most cases the driver can be aborted by ^C (SIGINT) and | ||
652 | SIGKILL (kill -9) will generate be a sure kill. | ||
653 | (Note that aborting a tape operation may damage the last | ||
654 | data written to tape) | ||
655 | |||
656 | Improved error recovery | ||
657 | ----------------------- | ||
658 | Ftape now returns an error (ENODATA) to the application if | ||
659 | a segment proves to be unrecoverable and then skips the | ||
660 | bad segment. | ||
661 | This causes most applications to continue to work (tar | ||
662 | and afio) loosing only a small amount (up to 29 Kb) of data. | ||
663 | Retried read operations will now be done slightly off-track | ||
664 | to improve the chance of success. Serious head off-track | ||
665 | errors will be detected. | ||
666 | |||
667 | FC-10 and FC-20 controllers | ||
668 | --------------------------- | ||
669 | Ftape now supports both the old CMS FC-10 and the newer FC-20 | ||
670 | controllers. | ||
671 | Because the operation of these cards is still undocumented, | ||
672 | thus far they will only work with the default settings (See | ||
673 | Makefile). Any feed-back on how to use them with other settings | ||
674 | will be welcome ! | ||
675 | Compilation will fail if one changes the settings to illegal | ||
676 | values. | ||
677 | |||
678 | Kernels and compilers | ||
679 | --------------------- | ||
680 | Ftape is currently being developed using the 2.5.8 compiler. | ||
681 | The older 2.4.5 probably works too (Set option in Makefile!). | ||
682 | I have no experience with any later compilers nor Elf support. | ||
683 | Any information on this is welcome. | ||
684 | The latest kernel I have tested ftape with is 1.2.6. | ||
685 | |||
686 | Compression | ||
687 | ----------- | ||
688 | An impressive collection of changes for ftape including | ||
689 | on-the-fly compression is still lying on my desk. | ||
690 | If 2.03 proves to be reliable I might start integrating these | ||
691 | but as usual, I'm short in time :-( | ||
692 | |||
693 | Formatting | ||
694 | ---------- | ||
695 | There is still no way to format tapes under Linux. As far as | ||
696 | I know all attempts to write such a program have died now. | ||
697 | Since formatted tapes are rather common now, I think all we | ||
698 | need is a utility that writes a worst case pattern and verifies | ||
699 | that with the drive put in verify mode, reducing margins. | ||
700 | Any takers ? | ||
701 | |||
702 | Furthermore | ||
703 | ----------- | ||
704 | Cleaned up messages. | ||
705 | Prepared to support multiple tape drives on one fdc. | ||
706 | Thanks to all the people who sent bug reports and helped me | ||
707 | improve the driver. Without trying to be complete I'll mention | ||
708 | Gary Anderson (without his accurate reports and unreliable | ||
709 | hardware there wouldn't be a 2.03), Stefan Kneifel (FC-20), | ||
710 | Robert Broughton (FC-20, you were almost there ;-), Bjorn | ||
711 | Ekwall (for the versioned modules and buggy insmod ;-), Peter | ||
712 | Fox, Christopher Oliver, Ralph Whittaker and not the least | ||
713 | Linus Torvalds (for Linux and keeping me busy because of | ||
714 | changes to the kernel ;-) | ||
715 | Thanks to anyone I forgot, for the bug reports, the ftape | ||
716 | bashing and the mental support... | ||
717 | |||
718 | |||
719 | That's it for now. Have Fun, | ||
720 | |||
721 | Bas. | ||
722 | |||
723 | |||
724 | ===== Release notes for ftape-2.02g, 06/05/95 ===== | ||
725 | |||
726 | - Added extra test to break read-id loop with signal. | ||
727 | - Changed rewind code to handle negative overshoot for drives | ||
728 | that take very long to start or stop. | ||
729 | - Let use of get/set i/o-regions depend on kernel version. | ||
730 | - Changed code to use a more general test for conditional | ||
731 | compilations depending on kernel version. | ||
732 | - Improved micro-step functionality to go off-track only | ||
733 | while reading (id & data). | ||
734 | - Added failure on tape-not-referenced bit in ftape_command. | ||
735 | - Added FOREVER option to read-wait routine. | ||
736 | - Changed read-id to use shorter timeout causing smaller | ||
737 | rewinds on timeout. | ||
738 | - Made kernel-interface functions static. | ||
739 | |||
740 | |||
741 | ===== Release notes for ftape-2.02f, 03/05/95 ===== | ||
742 | |||
743 | - Added support for dual tape drives on my system, extended Configure | ||
744 | script to detect host 'dodo'. | ||
745 | - Log media defect in history if ecc failed and no data was returned. | ||
746 | - Fixed Configure script that was failing for kernel versions with | ||
747 | double digit version or revision numbers. | ||
748 | |||
749 | |||
750 | ===== Release notes for ftape-2.02e, 01/05/95 ===== | ||
751 | |||
752 | - Fixed reposition loop at logical eot (failing read_id). | ||
753 | - Fixed 34 segment offset when rewinding. | ||
754 | - Added fast seek capability for more than 255 segments. | ||
755 | - Fixed wrong busy result from ftape_command causing reverse | ||
756 | seek to fail. | ||
757 | - Added breakout from infinite rewind loop (if something fails). | ||
758 | |||
759 | |||
760 | ===== Release notes for ftape-2.02d, 30/04/95 ===== | ||
761 | |||
762 | - Improved abortion on signals: Interrupt will make a graceful | ||
763 | exit, Kill will be less nice and should be used if everything | ||
764 | else fails. | ||
765 | - Included check for tape-head off track. | ||
766 | - Implemented exit from tape-start loop. | ||
767 | - Added kernel io-port registration. | ||
768 | - Implemented skip of failing segment (ENODATA) on ecc failure. | ||
769 | This allows afio and tar to continue when the tape is damaged. | ||
770 | - Made distinction between drive names with different codes. | ||
771 | |||
772 | |||
773 | ===== Release notes for ftape-2.02c, 22/04/95 ===== | ||
774 | |||
775 | - Fixed too tight command queueing after tape stop/pause command | ||
776 | issued from within interrupt service routine (Showed as timeout | ||
777 | on Acknowledge errors during retries on some systems) | ||
778 | - Tried to fix timeouts when using 425 ft tape because the extended | ||
779 | length doesn't seem to be detected by the hardware. | ||
780 | We now use the format code from the header segment so adjust the | ||
781 | timing after reading the header segment. | ||
782 | - Fixed some messages stating 'unexpected something...' being not | ||
783 | unexpected anymore. | ||
784 | - Started preparations for merge of dynamic buffer allocation and | ||
785 | compression code. | ||
786 | - Changed some debug messages to include relevant segment information | ||
787 | at level 4. | ||
788 | - Included early bail-out when drive offline, preventing a lot of | ||
789 | false messages. | ||
790 | - Moved ftape_parameter_xxx() offsets into function instead of in calls. | ||
791 | - Removed 'weird, drive busy but no data' error when caused by | ||
792 | an error during a read-id. | ||
793 | - Improved 'timeout on acknowledge' diagnostics. | ||
794 | - Moved MODULE option into Configure. | ||
795 | - Reduced code size when no tracing at all was set (Claus Heine). | ||
796 | - No longer log error code 0 (no error) as an error. | ||
797 | |||
798 | |||
799 | ===== Release notes for ftape-2.02b, 09/04/95 ===== | ||
800 | |||
801 | - Relaxed timing for status operation and displaying | ||
802 | abnormal results. Hopefully this shows what's going | ||
803 | wrong with the Conner TSM850R drives. | ||
804 | - Created script for configuration, using version number | ||
805 | of kernel source if available, otherwise /proc/version. | ||
806 | - Fixed conditionals in kernel-interface.c. | ||
807 | - Removed unavoidable TRACE output. | ||
808 | |||
809 | |||
810 | ===== Release notes for ftape-2.02a, 01/04/95 ===== | ||
811 | |||
812 | - Implemented `new-style' (versioned) modules support for new | ||
813 | kernels. | ||
814 | - Reduced size of module by moving static data to bss. | ||
815 | - Now using version number of kernel source instead of running | ||
816 | kernel for kernel versions >= 1.1.82 | ||
817 | - Added feedback on drive speeds to vendor information. | ||
818 | - Included fixed insmod sources to distribution (Let's hope | ||
819 | the modules distribution get fixed soon :-/). | ||
820 | |||
821 | Note that I haven't yet implemented any of the code extension I | ||
822 | received. I hope to find some time to do this soon. | ||
823 | |||
824 | |||
825 | ===== Release notes for ftape-2.02, 15/01/95 ===== | ||
826 | |||
827 | |||
828 | - Fixed failing repositioning when overshoot was incremented. | ||
829 | - Fixed rate selection: Because of a deficiency in the QIC-117 | ||
830 | specification one cannot distinguish between a not implemented | ||
831 | and a failing command. Therefor we now try to find out if the | ||
832 | drive does support this command before usage. | ||
833 | - Fixed error retry using wrong offset in fdc-isr. | ||
834 | - Improved retry code to retry only once on a single no-data | ||
835 | error in a segment. | ||
836 | - Validate sector number extracted from eof mark because an | ||
837 | invalid file mark (due to ???) could cause kernel panic. | ||
838 | - Split ftape-io.c into ftape-io.c and ftape-ctl.c files. | ||
839 | - Corrected too high media error count after writing to | ||
840 | a bad tape. | ||
841 | - Added #include <asm/segment.h> again because old kernel versions | ||
842 | need it. | ||
843 | - Fixed fdc not being disabled when open failed because no tape | ||
844 | drive was found. | ||
845 | - Fixed problem with soft error in sector 32 (shift operator with | ||
846 | shiftcount 32 is not defined). | ||
847 | |||
848 | |||
849 | ===== Release notes for ftape-2.01, 08/01/95 ===== | ||
850 | |||
851 | |||
852 | - Removed TESTING setting from distributed Makefile. | ||
853 | - Fixed `mt asf' failure: Rewind was deferred to close which | ||
854 | overruled the fsf ioctl. | ||
855 | - Prevented non-interruptible commands being interrupted. | ||
856 | - Added missing timeout.pause setting. | ||
857 | - Maximum tape speed read from drive type information table. | ||
858 | If the information is not in the table (0) the drive will | ||
859 | determine the speed itself and put a message in the logfile. | ||
860 | This information should then be added to the table in the | ||
861 | vendors.h file (and reported to me). | ||
862 | - Added call to ftape_init_drive after soft reset for those | ||
863 | (antique) drives that don't do an implicit seek_load_point | ||
864 | after a reset or power up. | ||
865 | - Don't try to set data rate if reset failed. | ||
866 | - Prevent update of seek variables when starting from the | ||
867 | beginning or the end of the tape. | ||
868 | - Fixed wrong adjustment of overshoot in seek_forward(). | ||
869 | - Added sync to Makefile (again). | ||
870 | - Added code to diagnose timer problems (calibr.c). | ||
871 | - Replaced time differences by timediff calls. | ||
872 | - Removed reference to do_floppy from object for recent kernels. | ||
873 | - Fixed wrong display of 'failing dma controller' message. | ||
874 | - Removed various no longer used #include statements. | ||
875 | - Added max. tape speed value to vendor-struct. | ||
876 | - Changed ftape-command to check pre-conditions and wait | ||
877 | if needed. | ||
878 | - Further updated qic117.h to rev G. | ||
879 | - Combined command name table and restrictions table to one. | ||
880 | Extended this table with some new fields. | ||
881 | - Increased timeout on Ack timer value and included code to | ||
882 | report out of spec behaviour. | ||
883 | - Increased rewind timeout margin to calculated + 20%. | ||
884 | - Improved data rate selection so it won't fail on some | ||
885 | older (pre standard) drives. | ||
886 | - Changed initialisation code so drive will be rewound if the | ||
887 | driver is reloaded and the tape is not at bot. | ||
888 | - Moved some of the flush operations from close to the ioctls. | ||
889 | - Added exit code value to failing verify area message. | ||
890 | - Loop until tape halted in smart-stop. | ||
891 | - Fast seek handled specially if located at bot or eot. | ||
892 | - Being more conservative on overshoot value. | ||
893 | |||
894 | |||
895 | ===== Release notes for ftape-2.00, 31/12/94 ===== | ||
896 | |||
897 | The Install-guide is completely rewritten and now also includes | ||
898 | some information on how to use the driver. If you're either new | ||
899 | to ftape or new to Unix tape devices make sure to read it ! | ||
900 | |||
901 | If you own a pci system and experience problems with the | ||
902 | ftape driver make sure to read the README.PCI file. It contains | ||
903 | some hints on how to fix your hardware. | ||
904 | |||
905 | For anybody who hasn't noticed: The version number of the | ||
906 | driver has been incremented (The latest released version has | ||
907 | been version 1.14d). | ||
908 | This has been done for two major reasons: | ||
909 | |||
910 | o A new (better) error recovery scheme is implemented. | ||
911 | o Support for new drive types has been added. | ||
912 | |||
913 | All these improvements/changes will probably include a couple | ||
914 | of new (and old?) bugs. If you encounter any problems that you think | ||
915 | I'm not yet aware of, feel free to send a report to <bas@vimec.nl>. | ||
916 | I recommend keeping a version of ftape-1.14d available, just | ||
917 | in case ;-) | ||
918 | |||
919 | This version should work with all kernel versions from 1.0.9 up | ||
920 | to 1.1.72 (and probably earlier and later versions too). | ||
921 | |||
922 | |||
923 | Major new features: | ||
924 | |||
925 | - Better handling of tapes with defects: When a sector repeatedly | ||
926 | (SOFT_RETRIES in ftape.h) cannot be written to or read from it is | ||
927 | marked as an hard error and gets skipped. | ||
928 | The error correction code can handle up to three of these hard | ||
929 | errors provided there are no other errors in that segment (32 Kb). | ||
930 | |||
931 | - Allows writing to tapes with defects (although the risk of loosing | ||
932 | data increases !) | ||
933 | Look for the media-defects entry printed with the statistics when | ||
934 | the tape is closed. A non-zero value here shows a bad tape. | ||
935 | [the actual count is wrong (too high), this is a known bug]. | ||
936 | |||
937 | - Use of backup header segment if first one is failing. | ||
938 | |||
939 | - Support for extended length tapes with QIC-80: both 425 and 1100 ft. | ||
940 | 0.25 inch tapes are now recognized and handled. | ||
941 | |||
942 | - Support for new QIC-80 drives with 8 mm `wide' tapes (e.g. Conner | ||
943 | TSM 420). | ||
944 | |||
945 | - Support for new QIC-3010 and QIC-3020 drives (experimental) with | ||
946 | both 0.25 inch and 8 mm tapes. | ||
947 | |||
948 | Some minor features were added, a couple of small bugs were fixed and | ||
949 | probably some new ones introduced ;-). | ||
950 | |||
951 | [lseek() didn't make it into this version] | ||
952 | |||
953 | Have fun, | ||
954 | |||
955 | Bas. | ||
956 | ---- | ||
957 | LocalWords: ftape MCONFIG mt VFS zftape resp sftape proc subdir MTIOCVOLINFO | ||
958 | LocalWords: MTIOCGETSIZE BOT EOD MTBSF zft kerneld modprobe kdtime contrib TR | ||
959 | LocalWords: MTSETBLK afio uninstall texi www EIO QIC init sft eof aka dma GB | ||
960 | LocalWords: SIGKILL MTIOCFTCMD mmap Iomega FDC fdc io gnumt mtio fc asm inb | ||
961 | LocalWords: outb ft qic frontend TeXinfo irq mach MODVERSIONS CONFIG html dvi | ||
962 | LocalWords: usr doc SMP Mb Dunno FIXME vtblc perl listtape volinfo fsf MTWEOF | ||
963 | LocalWords: amanda degaussed ComByte DoublePlay whraven njackn com MTIOC vtbl | ||
964 | LocalWords: GETBLKSZ MAKEDEV zftape's linux dif CVS Revison cp MTREW MTOFFL | ||
965 | LocalWords: MTFSF BSF Marcin Dalecki GCC Config cpio swapout Kai Harrekilde | ||
966 | LocalWords: Pederson khp dolphinics Justus claus momo rwth aachen Laarhoven | ||
diff --git a/drivers/char/ftape/compressor/Makefile b/drivers/char/ftape/compressor/Makefile deleted file mode 100644 index 1fbd6c4019db..000000000000 --- a/drivers/char/ftape/compressor/Makefile +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 1997 Claus-Justus Heine. | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 2, or (at your option) | ||
7 | # any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program; see the file COPYING. If not, write to | ||
16 | # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | # | ||
18 | # $Source: /homes/cvs/ftape-stacked/ftape/compressor/Makefile,v $ | ||
19 | # $Revision: 1.1 $ | ||
20 | # $Date: 1997/10/05 19:12:28 $ | ||
21 | # | ||
22 | # Makefile for the optional compressor for th zftape VFS | ||
23 | # interface to the QIC-40/80/3010/3020 floppy-tape driver for | ||
24 | # Linux. | ||
25 | # | ||
26 | |||
27 | obj-$(CONFIG_ZFT_COMPRESSOR) += zft-compressor.o | ||
28 | |||
29 | zft-compressor-objs := zftape-compress.o lzrw3.o | ||
30 | |||
31 | CFLAGS_lzrw3.o := -O6 -funroll-all-loops | ||
diff --git a/drivers/char/ftape/compressor/lzrw3.c b/drivers/char/ftape/compressor/lzrw3.c deleted file mode 100644 index a032a0ee2a99..000000000000 --- a/drivers/char/ftape/compressor/lzrw3.c +++ /dev/null | |||
@@ -1,743 +0,0 @@ | |||
1 | /* | ||
2 | * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.c,v $ | ||
3 | * $Revision: 1.1 $ | ||
4 | * $Date: 1997/10/05 19:12:29 $ | ||
5 | * | ||
6 | * Implementation of Ross Williams lzrw3 algorithm. Adaption for zftape. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include "../compressor/lzrw3.h" /* Defines single exported function "compress". */ | ||
11 | |||
12 | /******************************************************************************/ | ||
13 | /* */ | ||
14 | /* LZRW3.C */ | ||
15 | /* */ | ||
16 | /******************************************************************************/ | ||
17 | /* */ | ||
18 | /* Author : Ross Williams. */ | ||
19 | /* Date : 30-Jun-1991. */ | ||
20 | /* Release : 1. */ | ||
21 | /* */ | ||
22 | /******************************************************************************/ | ||
23 | /* */ | ||
24 | /* This file contains an implementation of the LZRW3 data compression */ | ||
25 | /* algorithm in C. */ | ||
26 | /* */ | ||
27 | /* The algorithm is a general purpose compression algorithm that runs fast */ | ||
28 | /* and gives reasonable compression. The algorithm is a member of the Lempel */ | ||
29 | /* Ziv family of algorithms and bases its compression on the presence in the */ | ||
30 | /* data of repeated substrings. */ | ||
31 | /* */ | ||
32 | /* This algorithm is unpatented and the code is public domain. As the */ | ||
33 | /* algorithm is based on the LZ77 class of algorithms, it is unlikely to be */ | ||
34 | /* the subject of a patent challenge. */ | ||
35 | /* */ | ||
36 | /* Unlike the LZRW1 and LZRW1-A algorithms, the LZRW3 algorithm is */ | ||
37 | /* deterministic and is guaranteed to yield the same compressed */ | ||
38 | /* representation for a given file each time it is run. */ | ||
39 | /* */ | ||
40 | /* The LZRW3 algorithm was originally designed and implemented */ | ||
41 | /* by Ross Williams on 31-Dec-1990. */ | ||
42 | /* */ | ||
43 | /* Here are the results of applying this code, compiled under THINK C 4.0 */ | ||
44 | /* and running on a Mac-SE (8MHz 68000), to the standard calgary corpus. */ | ||
45 | /* */ | ||
46 | /* +----------------------------------------------------------------+ */ | ||
47 | /* | DATA COMPRESSION TEST | */ | ||
48 | /* | ===================== | */ | ||
49 | /* | Time of run : Sun 30-Jun-1991 09:31PM | */ | ||
50 | /* | Timing accuracy : One part in 100 | */ | ||
51 | /* | Context length : 262144 bytes (= 256.0000K) | */ | ||
52 | /* | Test suite : Calgary Corpus Suite | */ | ||
53 | /* | Files in suite : 14 | */ | ||
54 | /* | Algorithm : LZRW3 | */ | ||
55 | /* | Note: All averages are calculated from the un-rounded values. | */ | ||
56 | /* +----------------------------------------------------------------+ */ | ||
57 | /* | File Name Length CxB ComLen %Remn Bits Com K/s Dec K/s | */ | ||
58 | /* | ---------- ------ --- ------ ----- ---- ------- ------- | */ | ||
59 | /* | rpus:Bib.D 111261 1 55033 49.5 3.96 19.46 32.27 | */ | ||
60 | /* | us:Book1.D 768771 3 467962 60.9 4.87 17.03 31.07 | */ | ||
61 | /* | us:Book2.D 610856 3 317102 51.9 4.15 19.39 34.15 | */ | ||
62 | /* | rpus:Geo.D 102400 1 82424 80.5 6.44 11.65 18.18 | */ | ||
63 | /* | pus:News.D 377109 2 205670 54.5 4.36 17.14 27.47 | */ | ||
64 | /* | pus:Obj1.D 21504 1 13027 60.6 4.85 13.40 18.95 | */ | ||
65 | /* | pus:Obj2.D 246814 1 116286 47.1 3.77 19.31 30.10 | */ | ||
66 | /* | s:Paper1.D 53161 1 27522 51.8 4.14 18.60 31.15 | */ | ||
67 | /* | s:Paper2.D 82199 1 45160 54.9 4.40 18.45 32.84 | */ | ||
68 | /* | rpus:Pic.D 513216 2 122388 23.8 1.91 35.29 51.05 | */ | ||
69 | /* | us:Progc.D 39611 1 19669 49.7 3.97 18.87 30.64 | */ | ||
70 | /* | us:Progl.D 71646 1 28247 39.4 3.15 24.34 40.66 | */ | ||
71 | /* | us:Progp.D 49379 1 19377 39.2 3.14 23.91 39.23 | */ | ||
72 | /* | us:Trans.D 93695 1 33481 35.7 2.86 25.48 40.37 | */ | ||
73 | /* +----------------------------------------------------------------+ */ | ||
74 | /* | Average 224401 1 110953 50.0 4.00 20.17 32.72 | */ | ||
75 | /* +----------------------------------------------------------------+ */ | ||
76 | /* */ | ||
77 | /******************************************************************************/ | ||
78 | |||
79 | /******************************************************************************/ | ||
80 | |||
81 | /* The following structure is returned by the "compress" function below when */ | ||
82 | /* the user asks the function to return identifying information. */ | ||
83 | /* The most important field in the record is the working memory field which */ | ||
84 | /* tells the calling program how much working memory should be passed to */ | ||
85 | /* "compress" when it is called to perform a compression or decompression. */ | ||
86 | /* LZRW3 uses the same amount of memory during compression and decompression. */ | ||
87 | /* For more information on this structure see "compress.h". */ | ||
88 | |||
89 | #define U(X) ((ULONG) X) | ||
90 | #define SIZE_P_BYTE (U(sizeof(UBYTE *))) | ||
91 | #define SIZE_WORD (U(sizeof(UWORD ))) | ||
92 | #define ALIGNMENT_FUDGE (U(16)) | ||
93 | #define MEM_REQ ( U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE ) | ||
94 | |||
95 | static struct compress_identity identity = | ||
96 | { | ||
97 | U(0x032DDEA8), /* Algorithm identification number. */ | ||
98 | MEM_REQ, /* Working memory (bytes) required. */ | ||
99 | "LZRW3", /* Name of algorithm. */ | ||
100 | "1.0", /* Version number of algorithm. */ | ||
101 | "31-Dec-1990", /* Date of algorithm. */ | ||
102 | "Public Domain", /* Copyright notice. */ | ||
103 | "Ross N. Williams", /* Author of algorithm. */ | ||
104 | "Renaissance Software", /* Affiliation of author. */ | ||
105 | "Public Domain" /* Vendor of algorithm. */ | ||
106 | }; | ||
107 | |||
108 | LOCAL void compress_compress (UBYTE *,UBYTE *,ULONG,UBYTE *, LONG *); | ||
109 | LOCAL void compress_decompress(UBYTE *,UBYTE *,LONG, UBYTE *, ULONG *); | ||
110 | |||
111 | /******************************************************************************/ | ||
112 | |||
113 | /* This function is the only function exported by this module. */ | ||
114 | /* Depending on its first parameter, the function can be requested to */ | ||
115 | /* compress a block of memory, decompress a block of memory, or to identify */ | ||
116 | /* itself. For more information, see the specification file "compress.h". */ | ||
117 | |||
118 | EXPORT void lzrw3_compress( | ||
119 | UWORD action, /* Action to be performed. */ | ||
120 | UBYTE *wrk_mem, /* Address of working memory we can use.*/ | ||
121 | UBYTE *src_adr, /* Address of input data. */ | ||
122 | LONG src_len, /* Length of input data. */ | ||
123 | UBYTE *dst_adr, /* Address to put output data. */ | ||
124 | void *p_dst_len /* Address of longword for length of output data.*/ | ||
125 | ) | ||
126 | { | ||
127 | switch (action) | ||
128 | { | ||
129 | case COMPRESS_ACTION_IDENTITY: | ||
130 | *((struct compress_identity **)p_dst_len)= &identity; | ||
131 | break; | ||
132 | case COMPRESS_ACTION_COMPRESS: | ||
133 | compress_compress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len); | ||
134 | break; | ||
135 | case COMPRESS_ACTION_DECOMPRESS: | ||
136 | compress_decompress(wrk_mem,src_adr,src_len,dst_adr,(LONG *)p_dst_len); | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /******************************************************************************/ | ||
142 | /* */ | ||
143 | /* BRIEF DESCRIPTION OF THE LZRW3 ALGORITHM */ | ||
144 | /* ======================================== */ | ||
145 | /* The LZRW3 algorithm is identical to the LZRW1-A algorithm except that */ | ||
146 | /* instead of transmitting history offsets, it transmits hash table indexes. */ | ||
147 | /* In order to decode the indexes, the decompressor must maintain an */ | ||
148 | /* identical hash table. Copy items are straightforward:when the decompressor */ | ||
149 | /* receives a copy item, it simply looks up the hash table to translate the */ | ||
150 | /* index into a pointer into the data already decompressed. To update the */ | ||
151 | /* hash table, it replaces the same table entry with a pointer to the start */ | ||
152 | /* of the newly decoded phrase. The tricky part is with literal items, for at */ | ||
153 | /* the time that the decompressor receives a literal item the decompressor */ | ||
154 | /* does not have the three bytes in the Ziv (that the compressor has) to */ | ||
155 | /* perform the three-byte hash. To solve this problem, in LZRW3, both the */ | ||
156 | /* compressor and decompressor are wired up so that they "buffer" these */ | ||
157 | /* literals and update their hash tables only when three bytes are available. */ | ||
158 | /* This makes the maximum buffering 2 bytes. */ | ||
159 | /* */ | ||
160 | /* Replacement of offsets by hash table indexes yields a few percent extra */ | ||
161 | /* compression at the cost of some speed. LZRW3 is slower than LZRW1, LZRW1-A */ | ||
162 | /* and LZRW2, but yields better compression. */ | ||
163 | /* */ | ||
164 | /* Extra compression could be obtained by using a hash table of depth two. */ | ||
165 | /* However, increasing the depth above one incurs a significant decrease in */ | ||
166 | /* compression speed which was not considered worthwhile. Another reason for */ | ||
167 | /* keeping the depth down to one was to allow easy comparison with the */ | ||
168 | /* LZRW1-A and LZRW2 algorithms so as to demonstrate the exact effect of the */ | ||
169 | /* use of direct hash indexes. */ | ||
170 | /* */ | ||
171 | /* +---+ */ | ||
172 | /* |___|4095 */ | ||
173 | /* |___| */ | ||
174 | /* +---------------------*_|<---+ /----+---\ */ | ||
175 | /* | |___| +---|Hash | */ | ||
176 | /* | |___| |Function| */ | ||
177 | /* | |___| \--------/ */ | ||
178 | /* | |___|0 ^ */ | ||
179 | /* | +---+ | */ | ||
180 | /* | Hash +-----+ */ | ||
181 | /* | Table | */ | ||
182 | /* | --- */ | ||
183 | /* v ^^^ */ | ||
184 | /* +-------------------------------------|----------------+ */ | ||
185 | /* |||||||||||||||||||||||||||||||||||||||||||||||||||||||| */ | ||
186 | /* +-------------------------------------|----------------+ */ | ||
187 | /* | |1......18| | */ | ||
188 | /* |<------- Lempel=History ------------>|<--Ziv-->| | */ | ||
189 | /* | (=bytes already processed) |<-Still to go-->| */ | ||
190 | /* |<-------------------- INPUT BLOCK ------------------->| */ | ||
191 | /* */ | ||
192 | /* The diagram above for LZRW3 looks almost identical to the diagram for */ | ||
193 | /* LZRW1. The difference is that in LZRW3, the compressor transmits hash */ | ||
194 | /* table indices instead of Lempel offsets. For this to work, the */ | ||
195 | /* decompressor must maintain a hash table as well as the compressor and both */ | ||
196 | /* compressor and decompressor must "buffer" literals, as the decompressor */ | ||
197 | /* cannot hash phrases commencing with a literal until another two bytes have */ | ||
198 | /* arrived. */ | ||
199 | /* */ | ||
200 | /* LZRW3 Algorithm Execution Summary */ | ||
201 | /* --------------------------------- */ | ||
202 | /* 1. Hash the first three bytes of the Ziv to yield a hash table index h. */ | ||
203 | /* 2. Look up the hash table yielding history pointer p. */ | ||
204 | /* 3. Match where p points with the Ziv. If there is a match of three or */ | ||
205 | /* more bytes, code those bytes (in the Ziv) as a copy item, otherwise */ | ||
206 | /* code the next byte in the Ziv as a literal item. */ | ||
207 | /* 4. Update the hash table as possible subject to the constraint that only */ | ||
208 | /* phrases commencing three bytes back from the Ziv can be hashed and */ | ||
209 | /* entered into the hash table. (This enables the decompressor to keep */ | ||
210 | /* pace). See the description and code for more details. */ | ||
211 | /* */ | ||
212 | /******************************************************************************/ | ||
213 | /* */ | ||
214 | /* DEFINITION OF COMPRESSED FILE FORMAT */ | ||
215 | /* ==================================== */ | ||
216 | /* * A compressed file consists of a COPY FLAG followed by a REMAINDER. */ | ||
217 | /* * The copy flag CF uses up four bytes with the first byte being the */ | ||
218 | /* least significant. */ | ||
219 | /* * If CF=1, then the compressed file represents the remainder of the file */ | ||
220 | /* exactly. Otherwise CF=0 and the remainder of the file consists of zero */ | ||
221 | /* or more GROUPS, each of which represents one or more bytes. */ | ||
222 | /* * Each group consists of two bytes of CONTROL information followed by */ | ||
223 | /* sixteen ITEMs except for the last group which can contain from one */ | ||
224 | /* to sixteen items. */ | ||
225 | /* * An item can be either a LITERAL item or a COPY item. */ | ||
226 | /* * Each item corresponds to a bit in the control bytes. */ | ||
227 | /* * The first control byte corresponds to the first 8 items in the group */ | ||
228 | /* with bit 0 corresponding to the first item in the group and bit 7 to */ | ||
229 | /* the eighth item in the group. */ | ||
230 | /* * The second control byte corresponds to the second 8 items in the group */ | ||
231 | /* with bit 0 corresponding to the ninth item in the group and bit 7 to */ | ||
232 | /* the sixteenth item in the group. */ | ||
233 | /* * A zero bit in a control word means that the corresponding item is a */ | ||
234 | /* literal item. A one bit corresponds to a copy item. */ | ||
235 | /* * A literal item consists of a single byte which represents itself. */ | ||
236 | /* * A copy item consists of two bytes that represent from 3 to 18 bytes. */ | ||
237 | /* * The first byte in a copy item will be denoted C1. */ | ||
238 | /* * The second byte in a copy item will be denoted C2. */ | ||
239 | /* * Bits will be selected using square brackets. */ | ||
240 | /* For example: C1[0..3] is the low nibble of the first control byte. */ | ||
241 | /* of copy item C1. */ | ||
242 | /* * The LENGTH of a copy item is defined to be C1[0..3]+3 which is a number */ | ||
243 | /* in the range [3,18]. */ | ||
244 | /* * The INDEX of a copy item is defined to be C1[4..7]*256+C2[0..8] which */ | ||
245 | /* is a number in the range [0,4095]. */ | ||
246 | /* * A copy item represents the sequence of bytes */ | ||
247 | /* text[POS-OFFSET..POS-OFFSET+LENGTH-1] where */ | ||
248 | /* text is the entire text of the uncompressed string. */ | ||
249 | /* POS is the index in the text of the character following the */ | ||
250 | /* string represented by all the items preceeding the item */ | ||
251 | /* being defined. */ | ||
252 | /* OFFSET is obtained from INDEX by looking up the hash table. */ | ||
253 | /* */ | ||
254 | /******************************************************************************/ | ||
255 | |||
256 | /* The following #define defines the length of the copy flag that appears at */ | ||
257 | /* the start of the compressed file. The value of four bytes was chosen */ | ||
258 | /* because the fast_copy routine on my Macintosh runs faster if the source */ | ||
259 | /* and destination blocks are relatively longword aligned. */ | ||
260 | /* The actual flag data appears in the first byte. The rest are zeroed so as */ | ||
261 | /* to normalize the compressed representation (i.e. not non-deterministic). */ | ||
262 | #define FLAG_BYTES 4 | ||
263 | |||
264 | /* The following #defines define the meaning of the values of the copy */ | ||
265 | /* flag at the start of the compressed file. */ | ||
266 | #define FLAG_COMPRESS 0 /* Signals that output was result of compression. */ | ||
267 | #define FLAG_COPY 1 /* Signals that output was simply copied over. */ | ||
268 | |||
269 | /* The 68000 microprocessor (on which this algorithm was originally developed */ | ||
270 | /* is fussy about non-aligned arrays of words. To avoid these problems the */ | ||
271 | /* following macro can be used to "waste" from 0 to 3 bytes so as to align */ | ||
272 | /* the argument pointer. */ | ||
273 | #define ULONG_ALIGN_UP(X) ((((ULONG)X)+sizeof(ULONG)-1)&~(sizeof(ULONG)-1)) | ||
274 | |||
275 | |||
276 | /* The following constant defines the maximum length of an uncompressed item. */ | ||
277 | /* This definition must not be changed; its value is hardwired into the code. */ | ||
278 | /* The longest number of bytes that can be spanned by a single item is 18 */ | ||
279 | /* for the longest copy item. */ | ||
280 | #define MAX_RAW_ITEM (18) | ||
281 | |||
282 | /* The following constant defines the maximum length of an uncompressed group.*/ | ||
283 | /* This definition must not be changed; its value is hardwired into the code. */ | ||
284 | /* A group contains at most 16 items which explains this definition. */ | ||
285 | #define MAX_RAW_GROUP (16*MAX_RAW_ITEM) | ||
286 | |||
287 | /* The following constant defines the maximum length of a compressed group. */ | ||
288 | /* This definition must not be changed; its value is hardwired into the code. */ | ||
289 | /* A compressed group consists of two control bytes followed by up to 16 */ | ||
290 | /* compressed items each of which can have a maximum length of two bytes. */ | ||
291 | #define MAX_CMP_GROUP (2+16*2) | ||
292 | |||
293 | /* The following constant defines the number of entries in the hash table. */ | ||
294 | /* This definition must not be changed; its value is hardwired into the code. */ | ||
295 | #define HASH_TABLE_LENGTH (4096) | ||
296 | |||
297 | /* LZRW3, unlike LZRW1(-A), must initialize its hash table so as to enable */ | ||
298 | /* the compressor and decompressor to stay in step maintaining identical hash */ | ||
299 | /* tables. In an early version of the algorithm, the tables were simply */ | ||
300 | /* initialized to zero and a check for zero was included just before the */ | ||
301 | /* matching code. However, this test costs time. A better solution is to */ | ||
302 | /* initialize all the entries in the hash table to point to a constant */ | ||
303 | /* string. The decompressor does the same. This solution requires no extra */ | ||
304 | /* test. The contents of the string do not matter so long as the string is */ | ||
305 | /* the same for the compressor and decompressor and contains at least */ | ||
306 | /* MAX_RAW_ITEM bytes. I chose consecutive decimal digits because they do not */ | ||
307 | /* have white space problems (e.g. there is no chance that the compiler will */ | ||
308 | /* replace more than one space by a TAB) and because they make the length of */ | ||
309 | /* the string obvious by inspection. */ | ||
310 | #define START_STRING_18 ((UBYTE *) "123456789012345678") | ||
311 | |||
312 | /* In this algorithm, hash values have to be calculated at more than one */ | ||
313 | /* point. The following macro neatens the code up for this. */ | ||
314 | #define HASH(PTR) \ | ||
315 | (((40543*(((*(PTR))<<8)^((*((PTR)+1))<<4)^(*((PTR)+2))))>>4) & 0xFFF) | ||
316 | |||
317 | /******************************************************************************/ | ||
318 | |||
319 | /* Input : Hand over the required amount of working memory in p_wrk_mem. */ | ||
320 | /* Input : Specify input block using p_src_first and src_len. */ | ||
321 | /* Input : Point p_dst_first to the start of the output zone (OZ). */ | ||
322 | /* Input : Point p_dst_len to a ULONG to receive the output length. */ | ||
323 | /* Input : Input block and output zone must not overlap. */ | ||
324 | /* Output : Length of output block written to *p_dst_len. */ | ||
325 | /* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. May */ | ||
326 | /* Output : write in OZ=Mem[p_dst_first..p_dst_first+src_len+MAX_CMP_GROUP-1].*/ | ||
327 | /* Output : Upon completion guaranteed *p_dst_len<=src_len+FLAG_BYTES. */ | ||
328 | LOCAL void compress_compress(UBYTE *p_wrk_mem, | ||
329 | UBYTE *p_src_first, ULONG src_len, | ||
330 | UBYTE *p_dst_first, LONG *p_dst_len) | ||
331 | { | ||
332 | /* p_src and p_dst step through the source and destination blocks. */ | ||
333 | register UBYTE *p_src = p_src_first; | ||
334 | register UBYTE *p_dst = p_dst_first; | ||
335 | |||
336 | /* The following variables are never modified and are used in the */ | ||
337 | /* calculations that determine when the main loop terminates. */ | ||
338 | UBYTE *p_src_post = p_src_first+src_len; | ||
339 | UBYTE *p_dst_post = p_dst_first+src_len; | ||
340 | UBYTE *p_src_max1 = p_src_first+src_len-MAX_RAW_ITEM; | ||
341 | UBYTE *p_src_max16 = p_src_first+src_len-MAX_RAW_ITEM*16; | ||
342 | |||
343 | /* The variables 'p_control' and 'control' are used to buffer control bits. */ | ||
344 | /* Before each group is processed, the next two bytes of the output block */ | ||
345 | /* are set aside for the control word for the group about to be processed. */ | ||
346 | /* 'p_control' is set to point to the first byte of that word. Meanwhile, */ | ||
347 | /* 'control' buffers the control bits being generated during the processing */ | ||
348 | /* of the group. Instead of having a counter to keep track of how many items */ | ||
349 | /* have been processed (=the number of bits in the control word), at the */ | ||
350 | /* start of each group, the top word of 'control' is filled with 1 bits. */ | ||
351 | /* As 'control' is shifted for each item, the 1 bits in the top word are */ | ||
352 | /* absorbed or destroyed. When they all run out (i.e. when the top word is */ | ||
353 | /* all zero bits, we know that we are at the end of a group. */ | ||
354 | # define TOPWORD 0xFFFF0000 | ||
355 | UBYTE *p_control; | ||
356 | register ULONG control=TOPWORD; | ||
357 | |||
358 | /* THe variable 'hash' always points to the first element of the hash table. */ | ||
359 | UBYTE **hash= (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem); | ||
360 | |||
361 | /* The following two variables represent the literal buffer. p_h1 points to */ | ||
362 | /* the hash table entry corresponding to the youngest literal. p_h2 points */ | ||
363 | /* to the hash table entry corresponding to the second youngest literal. */ | ||
364 | /* Note: p_h1=0=>p_h2=0 because zero values denote absence of a pending */ | ||
365 | /* literal. The variables are initialized to zero meaning an empty "buffer". */ | ||
366 | UBYTE **p_h1=NULL; | ||
367 | UBYTE **p_h2=NULL; | ||
368 | |||
369 | /* To start, we write the flag bytes. Being optimistic, we set the flag to */ | ||
370 | /* FLAG_COMPRESS. The remaining flag bytes are zeroed so as to keep the */ | ||
371 | /* algorithm deterministic. */ | ||
372 | *p_dst++=FLAG_COMPRESS; | ||
373 | {UWORD i; for (i=2;i<=FLAG_BYTES;i++) *p_dst++=0;} | ||
374 | |||
375 | /* Reserve the first word of output as the control word for the first group. */ | ||
376 | /* Note: This is undone at the end if the input block is empty. */ | ||
377 | p_control=p_dst; p_dst+=2; | ||
378 | |||
379 | /* Initialize all elements of the hash table to point to a constant string. */ | ||
380 | /* Use of an unrolled loop speeds this up considerably. */ | ||
381 | {UWORD i; UBYTE **p_h=hash; | ||
382 | # define ZH *p_h++=START_STRING_18 | ||
383 | for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */ | ||
384 | {ZH;ZH;ZH;ZH; | ||
385 | ZH;ZH;ZH;ZH; | ||
386 | ZH;ZH;ZH;ZH; | ||
387 | ZH;ZH;ZH;ZH;} | ||
388 | } | ||
389 | |||
390 | /* The main loop processes either 1 or 16 items per iteration. As its */ | ||
391 | /* termination logic is complicated, I have opted for an infinite loop */ | ||
392 | /* structure containing 'break' and 'goto' statements. */ | ||
393 | while (TRUE) | ||
394 | {/* Begin main processing loop. */ | ||
395 | |||
396 | /* Note: All the variables here except unroll should be defined within */ | ||
397 | /* the inner loop. Unfortunately the loop hasn't got a block. */ | ||
398 | register UBYTE *p; /* Scans through targ phrase during matching. */ | ||
399 | register UBYTE *p_ziv= NULL ; /* Points to first byte of current Ziv. */ | ||
400 | register UWORD unroll; /* Loop counter for unrolled inner loop. */ | ||
401 | register UWORD index; /* Index of current hash table entry. */ | ||
402 | register UBYTE **p_h0 = NULL ; /* Pointer to current hash table entry. */ | ||
403 | |||
404 | /* Test for overrun and jump to overrun code if necessary. */ | ||
405 | if (p_dst>p_dst_post) | ||
406 | goto overrun; | ||
407 | |||
408 | /* The following cascade of if statements efficiently catches and deals */ | ||
409 | /* with varying degrees of closeness to the end of the input block. */ | ||
410 | /* When we get very close to the end, we stop updating the table and */ | ||
411 | /* code the remaining bytes as literals. This makes the code simpler. */ | ||
412 | unroll=16; | ||
413 | if (p_src>p_src_max16) | ||
414 | { | ||
415 | unroll=1; | ||
416 | if (p_src>p_src_max1) | ||
417 | { | ||
418 | if (p_src==p_src_post) | ||
419 | break; | ||
420 | else | ||
421 | goto literal; | ||
422 | } | ||
423 | } | ||
424 | |||
425 | /* This inner unrolled loop processes 'unroll' (whose value is either 1 */ | ||
426 | /* or 16) items. I have chosen to implement this loop with labels and */ | ||
427 | /* gotos to heighten the ease with which the loop may be implemented with */ | ||
428 | /* a single decrement and branch instruction in assembly language and */ | ||
429 | /* also because the labels act as highly readable place markers. */ | ||
430 | /* (Also because we jump into the loop for endgame literals (see above)). */ | ||
431 | |||
432 | begin_unrolled_loop: | ||
433 | |||
434 | /* To process the next phrase, we hash the next three bytes and use */ | ||
435 | /* the resultant hash table index to look up the hash table. A pointer */ | ||
436 | /* to the entry is stored in p_h0 so as to avoid an array lookup. The */ | ||
437 | /* hash table entry *p_h0 is looked up yielding a pointer p to a */ | ||
438 | /* potential match of the Ziv in the history. */ | ||
439 | index=HASH(p_src); | ||
440 | p_h0=&hash[index]; | ||
441 | p=*p_h0; | ||
442 | |||
443 | /* Having looked up the candidate position, we are in a position to */ | ||
444 | /* attempt a match. The match loop has been unrolled using the PS */ | ||
445 | /* macro so that failure within the first three bytes automatically */ | ||
446 | /* results in the literal branch being taken. The coding is simple. */ | ||
447 | /* p_ziv saves p_src so we can let p_src wander. */ | ||
448 | # define PS *p++!=*p_src++ | ||
449 | p_ziv=p_src; | ||
450 | if (PS || PS || PS) | ||
451 | { | ||
452 | /* Literal. */ | ||
453 | |||
454 | /* Code the literal byte as itself and a zero control bit. */ | ||
455 | p_src=p_ziv; literal: *p_dst++=*p_src++; control&=0xFFFEFFFF; | ||
456 | |||
457 | /* We have just coded a literal. If we had two pending ones, that */ | ||
458 | /* makes three and we can update the hash table. */ | ||
459 | if (p_h2!=0) | ||
460 | {*p_h2=p_ziv-2;} | ||
461 | |||
462 | /* In any case, rotate the hash table pointers for next time. */ | ||
463 | p_h2=p_h1; p_h1=p_h0; | ||
464 | |||
465 | } | ||
466 | else | ||
467 | { | ||
468 | /* Copy */ | ||
469 | |||
470 | /* Match up to 15 remaining bytes using an unrolled loop and code. */ | ||
471 | #if 0 | ||
472 | PS || PS || PS || PS || PS || PS || PS || PS || | ||
473 | PS || PS || PS || PS || PS || PS || PS || p_src++; | ||
474 | #else | ||
475 | if ( | ||
476 | !( PS || PS || PS || PS || PS || PS || PS || PS || | ||
477 | PS || PS || PS || PS || PS || PS || PS ) | ||
478 | ) p_src++; | ||
479 | #endif | ||
480 | *p_dst++=((index&0xF00)>>4)|(--p_src-p_ziv-3); | ||
481 | *p_dst++=index&0xFF; | ||
482 | |||
483 | /* As we have just coded three bytes, we are now in a position to */ | ||
484 | /* update the hash table with the literal bytes that were pending */ | ||
485 | /* upon the arrival of extra context bytes. */ | ||
486 | if (p_h1!=0) | ||
487 | { | ||
488 | if (p_h2) | ||
489 | {*p_h2=p_ziv-2; p_h2=NULL;} | ||
490 | *p_h1=p_ziv-1; p_h1=NULL; | ||
491 | } | ||
492 | |||
493 | /* In any case, we can update the hash table based on the current */ | ||
494 | /* position as we just coded at least three bytes in a copy items. */ | ||
495 | *p_h0=p_ziv; | ||
496 | |||
497 | } | ||
498 | control>>=1; | ||
499 | |||
500 | /* This loop is all set up for a decrement and jump instruction! */ | ||
501 | #ifndef linux | ||
502 | ` end_unrolled_loop: if (--unroll) goto begin_unrolled_loop; | ||
503 | #else | ||
504 | /* end_unrolled_loop: */ if (--unroll) goto begin_unrolled_loop; | ||
505 | #endif | ||
506 | |||
507 | /* At this point it will nearly always be the end of a group in which */ | ||
508 | /* case, we have to do some control-word processing. However, near the */ | ||
509 | /* end of the input block, the inner unrolled loop is only executed once. */ | ||
510 | /* This necessitates the 'if' test. */ | ||
511 | if ((control&TOPWORD)==0) | ||
512 | { | ||
513 | /* Write the control word to the place we saved for it in the output. */ | ||
514 | *p_control++= control &0xFF; | ||
515 | *p_control = (control>>8) &0xFF; | ||
516 | |||
517 | /* Reserve the next word in the output block for the control word */ | ||
518 | /* for the group about to be processed. */ | ||
519 | p_control=p_dst; p_dst+=2; | ||
520 | |||
521 | /* Reset the control bits buffer. */ | ||
522 | control=TOPWORD; | ||
523 | } | ||
524 | |||
525 | } /* End main processing loop. */ | ||
526 | |||
527 | /* After the main processing loop has executed, all the input bytes have */ | ||
528 | /* been processed. However, the control word has still to be written to the */ | ||
529 | /* word reserved for it in the output at the start of the most recent group. */ | ||
530 | /* Before writing, the control word has to be shifted so that all the bits */ | ||
531 | /* are in the right place. The "empty" bit positions are filled with 1s */ | ||
532 | /* which partially fill the top word. */ | ||
533 | while(control&TOPWORD) control>>=1; | ||
534 | *p_control++= control &0xFF; | ||
535 | *p_control++=(control>>8) &0xFF; | ||
536 | |||
537 | /* If the last group contained no items, delete the control word too. */ | ||
538 | if (p_control==p_dst) p_dst-=2; | ||
539 | |||
540 | /* Write the length of the output block to the dst_len parameter and return. */ | ||
541 | *p_dst_len=p_dst-p_dst_first; | ||
542 | return; | ||
543 | |||
544 | /* Jump here as soon as an overrun is detected. An overrun is defined to */ | ||
545 | /* have occurred if p_dst>p_dst_first+src_len. That is, the moment the */ | ||
546 | /* length of the output written so far exceeds the length of the input block.*/ | ||
547 | /* The algorithm checks for overruns at least at the end of each group */ | ||
548 | /* which means that the maximum overrun is MAX_CMP_GROUP bytes. */ | ||
549 | /* Once an overrun occurs, the only thing to do is to set the copy flag and */ | ||
550 | /* copy the input over. */ | ||
551 | overrun: | ||
552 | #if 0 | ||
553 | *p_dst_first=FLAG_COPY; | ||
554 | fast_copy(p_src_first,p_dst_first+FLAG_BYTES,src_len); | ||
555 | *p_dst_len=src_len+FLAG_BYTES; | ||
556 | #else | ||
557 | fast_copy(p_src_first,p_dst_first,src_len); | ||
558 | *p_dst_len= -src_len; /* return a negative number to indicate uncompressed data */ | ||
559 | #endif | ||
560 | } | ||
561 | |||
562 | /******************************************************************************/ | ||
563 | |||
564 | /* Input : Hand over the required amount of working memory in p_wrk_mem. */ | ||
565 | /* Input : Specify input block using p_src_first and src_len. */ | ||
566 | /* Input : Point p_dst_first to the start of the output zone. */ | ||
567 | /* Input : Point p_dst_len to a ULONG to receive the output length. */ | ||
568 | /* Input : Input block and output zone must not overlap. User knows */ | ||
569 | /* Input : upperbound on output block length from earlier compression. */ | ||
570 | /* Input : In any case, maximum expansion possible is nine times. */ | ||
571 | /* Output : Length of output block written to *p_dst_len. */ | ||
572 | /* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */ | ||
573 | /* Output : Writes only in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */ | ||
574 | LOCAL void compress_decompress( UBYTE *p_wrk_mem, | ||
575 | UBYTE *p_src_first, LONG src_len, | ||
576 | UBYTE *p_dst_first, ULONG *p_dst_len) | ||
577 | { | ||
578 | /* Byte pointers p_src and p_dst scan through the input and output blocks. */ | ||
579 | register UBYTE *p_src = p_src_first+FLAG_BYTES; | ||
580 | register UBYTE *p_dst = p_dst_first; | ||
581 | /* we need to avoid a SEGV when trying to uncompress corrupt data */ | ||
582 | register UBYTE *p_dst_post = p_dst_first + *p_dst_len; | ||
583 | |||
584 | /* The following two variables are never modified and are used to control */ | ||
585 | /* the main loop. */ | ||
586 | UBYTE *p_src_post = p_src_first+src_len; | ||
587 | UBYTE *p_src_max16 = p_src_first+src_len-(MAX_CMP_GROUP-2); | ||
588 | |||
589 | /* The hash table is the only resident of the working memory. The hash table */ | ||
590 | /* contains HASH_TABLE_LENGTH=4096 pointers to positions in the history. To */ | ||
591 | /* keep Macintoshes happy, it is longword aligned. */ | ||
592 | UBYTE **hash = (UBYTE **) ULONG_ALIGN_UP(p_wrk_mem); | ||
593 | |||
594 | /* The variable 'control' is used to buffer the control bits which appear in */ | ||
595 | /* groups of 16 bits (control words) at the start of each compressed group. */ | ||
596 | /* When each group is read, bit 16 of the register is set to one. Whenever */ | ||
597 | /* a new bit is needed, the register is shifted right. When the value of the */ | ||
598 | /* register becomes 1, we know that we have reached the end of a group. */ | ||
599 | /* Initializing the register to 1 thus instructs the code to follow that it */ | ||
600 | /* should read a new control word immediately. */ | ||
601 | register ULONG control=1; | ||
602 | |||
603 | /* The value of 'literals' is always in the range 0..3. It is the number of */ | ||
604 | /* consecutive literal items just seen. We have to record this number so as */ | ||
605 | /* to know when to update the hash table. When literals gets to 3, there */ | ||
606 | /* have been three consecutive literals and we can update at the position of */ | ||
607 | /* the oldest of the three. */ | ||
608 | register UWORD literals=0; | ||
609 | |||
610 | /* Check the leading copy flag to see if the compressor chose to use a copy */ | ||
611 | /* operation instead of a compression operation. If a copy operation was */ | ||
612 | /* used, then all we need to do is copy the data over, set the output length */ | ||
613 | /* and return. */ | ||
614 | #if 0 | ||
615 | if (*p_src_first==FLAG_COPY) | ||
616 | { | ||
617 | fast_copy(p_src_first+FLAG_BYTES,p_dst_first,src_len-FLAG_BYTES); | ||
618 | *p_dst_len=src_len-FLAG_BYTES; | ||
619 | return; | ||
620 | } | ||
621 | #else | ||
622 | if ( src_len < 0 ) | ||
623 | { | ||
624 | fast_copy(p_src_first,p_dst_first,-src_len ); | ||
625 | *p_dst_len = (ULONG)-src_len; | ||
626 | return; | ||
627 | } | ||
628 | #endif | ||
629 | |||
630 | /* Initialize all elements of the hash table to point to a constant string. */ | ||
631 | /* Use of an unrolled loop speeds this up considerably. */ | ||
632 | {UWORD i; UBYTE **p_h=hash; | ||
633 | # define ZJ *p_h++=START_STRING_18 | ||
634 | for (i=0;i<256;i++) /* 256=HASH_TABLE_LENGTH/16. */ | ||
635 | {ZJ;ZJ;ZJ;ZJ; | ||
636 | ZJ;ZJ;ZJ;ZJ; | ||
637 | ZJ;ZJ;ZJ;ZJ; | ||
638 | ZJ;ZJ;ZJ;ZJ;} | ||
639 | } | ||
640 | |||
641 | /* The outer loop processes either 1 or 16 items per iteration depending on */ | ||
642 | /* how close p_src is to the end of the input block. */ | ||
643 | while (p_src!=p_src_post) | ||
644 | {/* Start of outer loop */ | ||
645 | |||
646 | register UWORD unroll; /* Counts unrolled loop executions. */ | ||
647 | |||
648 | /* When 'control' has the value 1, it means that the 16 buffered control */ | ||
649 | /* bits that were read in at the start of the current group have all been */ | ||
650 | /* shifted out and that all that is left is the 1 bit that was injected */ | ||
651 | /* into bit 16 at the start of the current group. When we reach the end */ | ||
652 | /* of a group, we have to load a new control word and inject a new 1 bit. */ | ||
653 | if (control==1) | ||
654 | { | ||
655 | control=0x10000|*p_src++; | ||
656 | control|=(*p_src++)<<8; | ||
657 | } | ||
658 | |||
659 | /* If it is possible that we are within 16 groups from the end of the */ | ||
660 | /* input, execute the unrolled loop only once, else process a whole group */ | ||
661 | /* of 16 items by looping 16 times. */ | ||
662 | unroll= p_src<=p_src_max16 ? 16 : 1; | ||
663 | |||
664 | /* This inner loop processes one phrase (item) per iteration. */ | ||
665 | while (unroll--) | ||
666 | { /* Begin unrolled inner loop. */ | ||
667 | |||
668 | /* Process a literal or copy item depending on the next control bit. */ | ||
669 | if (control&1) | ||
670 | { | ||
671 | /* Copy item. */ | ||
672 | |||
673 | register UBYTE *p; /* Points to place from which to copy. */ | ||
674 | register UWORD lenmt; /* Length of copy item minus three. */ | ||
675 | register UBYTE **p_hte; /* Pointer to current hash table entry.*/ | ||
676 | register UBYTE *p_ziv=p_dst; /* Pointer to start of current Ziv. */ | ||
677 | |||
678 | /* Read and dismantle the copy word. Work out from where to copy. */ | ||
679 | lenmt=*p_src++; | ||
680 | p_hte=&hash[((lenmt&0xF0)<<4)|*p_src++]; | ||
681 | p=*p_hte; | ||
682 | lenmt&=0xF; | ||
683 | |||
684 | /* Now perform the copy using a half unrolled loop. */ | ||
685 | *p_dst++=*p++; | ||
686 | *p_dst++=*p++; | ||
687 | *p_dst++=*p++; | ||
688 | while (lenmt--) | ||
689 | *p_dst++=*p++; | ||
690 | |||
691 | /* Because we have just received 3 or more bytes in a copy item */ | ||
692 | /* (whose bytes we have just installed in the output), we are now */ | ||
693 | /* in a position to flush all the pending literal hashings that had */ | ||
694 | /* been postponed for lack of bytes. */ | ||
695 | if (literals>0) | ||
696 | { | ||
697 | register UBYTE *r=p_ziv-literals; | ||
698 | hash[HASH(r)]=r; | ||
699 | if (literals==2) | ||
700 | {r++; hash[HASH(r)]=r;} | ||
701 | literals=0; | ||
702 | } | ||
703 | |||
704 | /* In any case, we can immediately update the hash table with the */ | ||
705 | /* current position. We don't need to do a HASH(...) to work out */ | ||
706 | /* where to put the pointer, as the compressor just told us!!! */ | ||
707 | *p_hte=p_ziv; | ||
708 | |||
709 | } | ||
710 | else | ||
711 | { | ||
712 | /* Literal item. */ | ||
713 | |||
714 | /* Copy over the literal byte. */ | ||
715 | *p_dst++=*p_src++; | ||
716 | |||
717 | /* If we now have three literals waiting to be hashed into the hash */ | ||
718 | /* table, we can do one of them now (because there are three). */ | ||
719 | if (++literals == 3) | ||
720 | {register UBYTE *p=p_dst-3; hash[HASH(p)]=p; literals=2;} | ||
721 | } | ||
722 | |||
723 | /* Shift the control buffer so the next control bit is in bit 0. */ | ||
724 | control>>=1; | ||
725 | #if 1 | ||
726 | if (p_dst > p_dst_post) | ||
727 | { | ||
728 | /* Shit: we tried to decompress corrupt data */ | ||
729 | *p_dst_len = 0; | ||
730 | return; | ||
731 | } | ||
732 | #endif | ||
733 | } /* End unrolled inner loop. */ | ||
734 | |||
735 | } /* End of outer loop */ | ||
736 | |||
737 | /* Write the length of the decompressed data before returning. */ | ||
738 | *p_dst_len=p_dst-p_dst_first; | ||
739 | } | ||
740 | |||
741 | /******************************************************************************/ | ||
742 | /* End of LZRW3.C */ | ||
743 | /******************************************************************************/ | ||
diff --git a/drivers/char/ftape/compressor/lzrw3.h b/drivers/char/ftape/compressor/lzrw3.h deleted file mode 100644 index 533feba47526..000000000000 --- a/drivers/char/ftape/compressor/lzrw3.h +++ /dev/null | |||
@@ -1,253 +0,0 @@ | |||
1 | #ifndef _LZRW3_H | ||
2 | #define _LZRW3_H | ||
3 | /* | ||
4 | * $Source: /homes/cvs/ftape-stacked/ftape/compressor/lzrw3.h,v $ | ||
5 | * $Revision: 1.1 $ | ||
6 | * $Date: 1997/10/05 19:12:30 $ | ||
7 | * | ||
8 | * include files for lzrw3. Only slighty modified from the original | ||
9 | * version. Assembles the three include files compress.h, port.h and | ||
10 | * fastcopy.h from the original lzrw3 package. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | #include <linux/string.h> | ||
16 | |||
17 | /******************************************************************************/ | ||
18 | /* */ | ||
19 | /* COMPRESS.H */ | ||
20 | /* */ | ||
21 | /******************************************************************************/ | ||
22 | /* */ | ||
23 | /* Author : Ross Williams. */ | ||
24 | /* Date : December 1989. */ | ||
25 | /* */ | ||
26 | /* This header file defines the interface to a set of functions called */ | ||
27 | /* 'compress', each member of which implements a particular data compression */ | ||
28 | /* algorithm. */ | ||
29 | /* */ | ||
30 | /* Normally in C programming, for each .H file, there is a corresponding .C */ | ||
31 | /* file that implements the functions promised in the .H file. */ | ||
32 | /* Here, there are many .C files corresponding to this header file. */ | ||
33 | /* Each comforming implementation file contains a single function */ | ||
34 | /* called 'compress' that implements a single data compression */ | ||
35 | /* algorithm that conforms with the interface specified in this header file. */ | ||
36 | /* Only one algorithm can be linked in at a time in this organization. */ | ||
37 | /* */ | ||
38 | /******************************************************************************/ | ||
39 | /* */ | ||
40 | /* DEFINITION OF FUNCTION COMPRESS */ | ||
41 | /* =============================== */ | ||
42 | /* */ | ||
43 | /* Summary of Function Compress */ | ||
44 | /* ---------------------------- */ | ||
45 | /* The action that 'compress' takes depends on its first argument called */ | ||
46 | /* 'action'. The function provides three actions: */ | ||
47 | /* */ | ||
48 | /* - Return information about the algorithm. */ | ||
49 | /* - Compress a block of memory. */ | ||
50 | /* - Decompress a block of memory. */ | ||
51 | /* */ | ||
52 | /* Parameters */ | ||
53 | /* ---------- */ | ||
54 | /* See the formal C definition later for a description of the parameters. */ | ||
55 | /* */ | ||
56 | /* Constants */ | ||
57 | /* --------- */ | ||
58 | /* COMPRESS_OVERRUN: The constant COMPRESS_OVERRUN defines by how many bytes */ | ||
59 | /* an algorithm is allowed to expand a block during a compression operation. */ | ||
60 | /* */ | ||
61 | /* Although compression algorithms usually compress data, there will always */ | ||
62 | /* be data that a given compressor will expand (this can be proven). */ | ||
63 | /* Fortunately, the degree of expansion can be limited to a single bit, by */ | ||
64 | /* copying over the input data if the data gets bigger during compression. */ | ||
65 | /* To allow for this possibility, the first bit of a compressed */ | ||
66 | /* representation can be used as a flag indicating whether the */ | ||
67 | /* input data was copied over, or truly compressed. In practice, the first */ | ||
68 | /* byte would be used to store this bit so as to maintain byte alignment. */ | ||
69 | /* */ | ||
70 | /* Unfortunately, in general, the only way to tell if an algorithm will */ | ||
71 | /* expand a particular block of data is to run the algorithm on the data. */ | ||
72 | /* If the algorithm does not continuously monitor how many output bytes it */ | ||
73 | /* has written, it might write an output block far larger than the input */ | ||
74 | /* block before realizing that it has done so. */ | ||
75 | /* On the other hand, continuous checks on output length are inefficient. */ | ||
76 | /* */ | ||
77 | /* To cater for all these problems, this interface definition: */ | ||
78 | /* > Allows a compression algorithm to return an output block that is up to */ | ||
79 | /* COMPRESS_OVERRUN bytes longer than the input block. */ | ||
80 | /* > Allows a compression algorithm to write up to COMPRESS_OVERRUN bytes */ | ||
81 | /* more than the length of the input block to the memory of the output */ | ||
82 | /* block regardless of the length of the output block eventually returned. */ | ||
83 | /* This allows an algorithm to overrun the length of the input block in the */ | ||
84 | /* output block by up to COMPRESS_OVERRUN bytes between expansion checks. */ | ||
85 | /* */ | ||
86 | /* The problem does not arise for decompression. */ | ||
87 | /* */ | ||
88 | /* Identity Action */ | ||
89 | /* --------------- */ | ||
90 | /* > action must be COMPRESS_ACTION_IDENTITY. */ | ||
91 | /* > p_dst_len must point to a longword to receive a longword address. */ | ||
92 | /* > The value of the other parameters does not matter. */ | ||
93 | /* > After execution, the longword that p_dst_len points to will be a pointer */ | ||
94 | /* to a structure of type compress_identity. */ | ||
95 | /* Thus, for example, after the call, (*p_dst_len)->memory will return the */ | ||
96 | /* number of bytes of working memory that the algorithm requires to run. */ | ||
97 | /* > The values of the identity structure returned are fixed constant */ | ||
98 | /* attributes of the algorithm and must not vary from call to call. */ | ||
99 | /* */ | ||
100 | /* Common Requirements for Compression and Decompression Actions */ | ||
101 | /* ------------------------------------------------------------- */ | ||
102 | /* > wrk_mem must point to an unused block of memory of a length specified in */ | ||
103 | /* the algorithm's identity block. The identity block can be obtained by */ | ||
104 | /* making a separate call to compress, specifying the identity action. */ | ||
105 | /* > The INPUT BLOCK is defined to be Memory[src_addr,src_addr+src_len-1]. */ | ||
106 | /* > dst_len will be used to denote *p_dst_len. */ | ||
107 | /* > dst_len is not read by compress, only written. */ | ||
108 | /* > The value of dst_len is defined only upon termination. */ | ||
109 | /* > The OUTPUT BLOCK is defined to be Memory[dst_addr,dst_addr+dst_len-1]. */ | ||
110 | /* */ | ||
111 | /* Compression Action */ | ||
112 | /* ------------------ */ | ||
113 | /* > action must be COMPRESS_ACTION_COMPRESS. */ | ||
114 | /* > src_len must be in the range [0,COMPRESS_MAX_ORG]. */ | ||
115 | /* > The OUTPUT ZONE is defined to be */ | ||
116 | /* Memory[dst_addr,dst_addr+src_len-1+COMPRESS_OVERRUN]. */ | ||
117 | /* > The function can modify any part of the output zone regardless of the */ | ||
118 | /* final length of the output block. */ | ||
119 | /* > The input block and the output zone must not overlap. */ | ||
120 | /* > dst_len will be in the range [0,src_len+COMPRESS_OVERRUN]. */ | ||
121 | /* > dst_len will be in the range [0,COMPRESS_MAX_COM] (from prev fact). */ | ||
122 | /* > The output block will consist of a representation of the input block. */ | ||
123 | /* */ | ||
124 | /* Decompression Action */ | ||
125 | /* -------------------- */ | ||
126 | /* > action must be COMPRESS_ACTION_DECOMPRESS. */ | ||
127 | /* > The input block must be the result of an earlier compression operation. */ | ||
128 | /* > If the previous fact is true, the following facts must also be true: */ | ||
129 | /* > src_len will be in the range [0,COMPRESS_MAX_COM]. */ | ||
130 | /* > dst_len will be in the range [0,COMPRESS_MAX_ORG]. */ | ||
131 | /* > The input and output blocks must not overlap. */ | ||
132 | /* > Only the output block is modified. */ | ||
133 | /* > Upon termination, the output block will consist of the bytes contained */ | ||
134 | /* in the input block passed to the earlier compression operation. */ | ||
135 | /* */ | ||
136 | /******************************************************************************/ | ||
137 | |||
138 | /******************************************************************************/ | ||
139 | /* */ | ||
140 | /* PORT.H */ | ||
141 | /* */ | ||
142 | /******************************************************************************/ | ||
143 | /* */ | ||
144 | /* This module contains macro definitions and types that are likely to */ | ||
145 | /* change between computers. */ | ||
146 | /* */ | ||
147 | /******************************************************************************/ | ||
148 | |||
149 | #ifndef DONE_PORT /* Only do this if not previously done. */ | ||
150 | |||
151 | #ifdef THINK_C | ||
152 | #define UBYTE unsigned char /* Unsigned byte */ | ||
153 | #define UWORD unsigned int /* Unsigned word (2 bytes) */ | ||
154 | #define ULONG unsigned long /* Unsigned word (4 bytes) */ | ||
155 | #define BOOL unsigned char /* Boolean */ | ||
156 | #define FOPEN_BINARY_READ "rb" /* Mode string for binary reading. */ | ||
157 | #define FOPEN_BINARY_WRITE "wb" /* Mode string for binary writing. */ | ||
158 | #define FOPEN_TEXT_APPEND "a" /* Mode string for text appending. */ | ||
159 | #define REAL double /* USed for floating point stuff. */ | ||
160 | #endif | ||
161 | #if defined(LINUX) || defined(linux) | ||
162 | #define UBYTE __u8 /* Unsigned byte */ | ||
163 | #define UWORD __u16 /* Unsigned word (2 bytes) */ | ||
164 | #define ULONG __u32 /* Unsigned word (4 bytes) */ | ||
165 | #define LONG __s32 /* Signed word (4 bytes) */ | ||
166 | #define BOOL is not used here /* Boolean */ | ||
167 | #define FOPEN_BINARY_READ not used /* Mode string for binary reading. */ | ||
168 | #define FOPEN_BINARY_WRITE not used /* Mode string for binary writing. */ | ||
169 | #define FOPEN_TEXT_APPEND not used /* Mode string for text appending. */ | ||
170 | #define REAL not used /* USed for floating point stuff. */ | ||
171 | #ifndef TRUE | ||
172 | #define TRUE 1 | ||
173 | #endif | ||
174 | #endif | ||
175 | |||
176 | #define DONE_PORT /* Don't do all this again. */ | ||
177 | #define MALLOC_FAIL NULL /* Failure status from malloc() */ | ||
178 | #define LOCAL static /* For non-exported routines. */ | ||
179 | #define EXPORT /* Signals exported function. */ | ||
180 | #define then /* Useful for aligning ifs. */ | ||
181 | |||
182 | #endif | ||
183 | |||
184 | /******************************************************************************/ | ||
185 | /* End of PORT.H */ | ||
186 | /******************************************************************************/ | ||
187 | |||
188 | #define COMPRESS_ACTION_IDENTITY 0 | ||
189 | #define COMPRESS_ACTION_COMPRESS 1 | ||
190 | #define COMPRESS_ACTION_DECOMPRESS 2 | ||
191 | |||
192 | #define COMPRESS_OVERRUN 1024 | ||
193 | #define COMPRESS_MAX_COM 0x70000000 | ||
194 | #define COMPRESS_MAX_ORG (COMPRESS_MAX_COM-COMPRESS_OVERRUN) | ||
195 | |||
196 | #define COMPRESS_MAX_STRLEN 255 | ||
197 | |||
198 | /* The following structure provides information about the algorithm. */ | ||
199 | /* > The top bit of id must be zero. The remaining bits must be chosen by */ | ||
200 | /* the author of the algorithm by tossing a coin 31 times. */ | ||
201 | /* > The amount of memory requested by the algorithm is specified in bytes */ | ||
202 | /* and must be in the range [0,0x70000000]. */ | ||
203 | /* > All strings s must be such that strlen(s)<=COMPRESS_MAX_STRLEN. */ | ||
204 | struct compress_identity | ||
205 | { | ||
206 | ULONG id; /* Identifying number of algorithm. */ | ||
207 | ULONG memory; /* Number of bytes of working memory required. */ | ||
208 | |||
209 | char *name; /* Name of algorithm. */ | ||
210 | char *version; /* Version number. */ | ||
211 | char *date; /* Date of release of this version. */ | ||
212 | char *copyright; /* Copyright message. */ | ||
213 | |||
214 | char *author; /* Author of algorithm. */ | ||
215 | char *affiliation; /* Affiliation of author. */ | ||
216 | char *vendor; /* Where the algorithm can be obtained. */ | ||
217 | }; | ||
218 | |||
219 | void lzrw3_compress( /* Single function interface to compression algorithm. */ | ||
220 | UWORD action, /* Action to be performed. */ | ||
221 | UBYTE *wrk_mem, /* Working memory temporarily given to routine to use. */ | ||
222 | UBYTE *src_adr, /* Address of input data. */ | ||
223 | LONG src_len, /* Length of input data. */ | ||
224 | UBYTE *dst_adr, /* Address of output data. */ | ||
225 | void *p_dst_len /* Pointer to a longword where routine will write: */ | ||
226 | /* If action=..IDENTITY => Adr of id structure. */ | ||
227 | /* If action=..COMPRESS => Length of output data. */ | ||
228 | /* If action=..DECOMPRESS => Length of output data. */ | ||
229 | ); | ||
230 | |||
231 | /******************************************************************************/ | ||
232 | /* End of COMPRESS.H */ | ||
233 | /******************************************************************************/ | ||
234 | |||
235 | |||
236 | /******************************************************************************/ | ||
237 | /* fast_copy.h */ | ||
238 | /******************************************************************************/ | ||
239 | |||
240 | /* This function copies a block of memory very quickly. */ | ||
241 | /* The exact speed depends on the relative alignment of the blocks of memory. */ | ||
242 | /* PRE : 0<=src_len<=(2^32)-1 . */ | ||
243 | /* PRE : Source and destination blocks must not overlap. */ | ||
244 | /* POST : MEM[dst_adr,dst_adr+src_len-1]=MEM[src_adr,src_adr+src_len-1]. */ | ||
245 | /* POST : MEM[dst_adr,dst_adr+src_len-1] is the only memory changed. */ | ||
246 | |||
247 | #define fast_copy(src,dst,len) memcpy(dst,src,len) | ||
248 | |||
249 | /******************************************************************************/ | ||
250 | /* End of fast_copy.h */ | ||
251 | /******************************************************************************/ | ||
252 | |||
253 | #endif | ||
diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c deleted file mode 100644 index 65ffc0be3df9..000000000000 --- a/drivers/char/ftape/compressor/zftape-compress.c +++ /dev/null | |||
@@ -1,1203 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1994-1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 2, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
17 | USA. | ||
18 | |||
19 | * | ||
20 | * This file implements a "generic" interface between the * | ||
21 | * zftape-driver and a compression-algorithm. The * | ||
22 | * compression-algorithm currently used is a LZ77. I use the * | ||
23 | * implementation lzrw3 by Ross N. Williams (Renaissance * | ||
24 | * Software). The compression program itself is in the file | ||
25 | * lzrw3.c * and lzrw3.h. To adopt another compression algorithm | ||
26 | * the functions * zft_compress() and zft_uncompress() must be | ||
27 | * changed * appropriately. See below. | ||
28 | */ | ||
29 | |||
30 | #include <linux/errno.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/module.h> | ||
33 | |||
34 | #include <linux/zftape.h> | ||
35 | |||
36 | #include <asm/uaccess.h> | ||
37 | |||
38 | #include "../zftape/zftape-init.h" | ||
39 | #include "../zftape/zftape-eof.h" | ||
40 | #include "../zftape/zftape-ctl.h" | ||
41 | #include "../zftape/zftape-write.h" | ||
42 | #include "../zftape/zftape-read.h" | ||
43 | #include "../zftape/zftape-rw.h" | ||
44 | #include "../compressor/zftape-compress.h" | ||
45 | #include "../zftape/zftape-vtbl.h" | ||
46 | #include "../compressor/lzrw3.h" | ||
47 | |||
48 | /* | ||
49 | * global variables | ||
50 | */ | ||
51 | |||
52 | /* I handle the allocation of this buffer as a special case, because | ||
53 | * it's size varies depending on the tape length inserted. | ||
54 | */ | ||
55 | |||
56 | /* local variables | ||
57 | */ | ||
58 | static void *zftc_wrk_mem = NULL; | ||
59 | static __u8 *zftc_buf = NULL; | ||
60 | static void *zftc_scratch_buf = NULL; | ||
61 | |||
62 | /* compression statistics | ||
63 | */ | ||
64 | static unsigned int zftc_wr_uncompressed = 0; | ||
65 | static unsigned int zftc_wr_compressed = 0; | ||
66 | static unsigned int zftc_rd_uncompressed = 0; | ||
67 | static unsigned int zftc_rd_compressed = 0; | ||
68 | |||
69 | /* forward */ | ||
70 | static int zftc_write(int *write_cnt, | ||
71 | __u8 *dst_buf, const int seg_sz, | ||
72 | const __u8 __user *src_buf, const int req_len, | ||
73 | const zft_position *pos, const zft_volinfo *volume); | ||
74 | static int zftc_read(int *read_cnt, | ||
75 | __u8 __user *dst_buf, const int to_do, | ||
76 | const __u8 *src_buf, const int seg_sz, | ||
77 | const zft_position *pos, const zft_volinfo *volume); | ||
78 | static int zftc_seek(unsigned int new_block_pos, | ||
79 | zft_position *pos, const zft_volinfo *volume, | ||
80 | __u8 *buffer); | ||
81 | static void zftc_lock (void); | ||
82 | static void zftc_reset (void); | ||
83 | static void zftc_cleanup(void); | ||
84 | static void zftc_stats (void); | ||
85 | |||
86 | /* compressed segment. This conforms to QIC-80-MC, Revision K. | ||
87 | * | ||
88 | * Rev. K applies to tapes with `fixed length format' which is | ||
89 | * indicated by format code 2,3 and 5. See below for format code 4 and 6 | ||
90 | * | ||
91 | * 2 bytes: offset of compression segment structure | ||
92 | * 29k > offset >= 29k-18: data from previous segment ens in this | ||
93 | * segment and no compressed block starts | ||
94 | * in this segment | ||
95 | * offset == 0: data from previous segment occupies entire | ||
96 | * segment and continues in next segment | ||
97 | * n bytes: remainder from previous segment | ||
98 | * | ||
99 | * Rev. K: | ||
100 | * 4 bytes: 4 bytes: files set byte offset | ||
101 | * Post Rev. K and QIC-3020/3020: | ||
102 | * 8 bytes: 8 bytes: files set byte offset | ||
103 | * 2 bytes: byte count N (amount of data following) | ||
104 | * bit 15 is set if data is compressed, bit 15 is not | ||
105 | * set if data is uncompressed | ||
106 | * N bytes: data (as much as specified in the byte count) | ||
107 | * 2 bytes: byte count N_1 of next cluster | ||
108 | * N_1 bytes: data of next cluset | ||
109 | * 2 bytes: byte count N_2 of next cluster | ||
110 | * N_2 bytes: ... | ||
111 | * | ||
112 | * Note that the `N' byte count accounts only for the bytes that in the | ||
113 | * current segment if the cluster spans to the next segment. | ||
114 | */ | ||
115 | |||
116 | typedef struct | ||
117 | { | ||
118 | int cmpr_pos; /* actual position in compression buffer */ | ||
119 | int cmpr_sz; /* what is left in the compression buffer | ||
120 | * when copying the compressed data to the | ||
121 | * deblock buffer | ||
122 | */ | ||
123 | unsigned int first_block; /* location of header information in | ||
124 | * this segment | ||
125 | */ | ||
126 | unsigned int count; /* amount of data of current block | ||
127 | * contained in current segment | ||
128 | */ | ||
129 | unsigned int offset; /* offset in current segment */ | ||
130 | unsigned int spans:1; /* might continue in next segment */ | ||
131 | unsigned int uncmpr; /* 0x8000 if this block contains | ||
132 | * uncompressed data | ||
133 | */ | ||
134 | __s64 foffs; /* file set byte offset, same as in | ||
135 | * compression map segment | ||
136 | */ | ||
137 | } cmpr_info; | ||
138 | |||
139 | static cmpr_info cseg; /* static data. Must be kept uptodate and shared by | ||
140 | * read, write and seek functions | ||
141 | */ | ||
142 | |||
143 | #define DUMP_CMPR_INFO(level, msg, info) \ | ||
144 | TRACE(level, msg "\n" \ | ||
145 | KERN_INFO "cmpr_pos : %d\n" \ | ||
146 | KERN_INFO "cmpr_sz : %d\n" \ | ||
147 | KERN_INFO "first_block: %d\n" \ | ||
148 | KERN_INFO "count : %d\n" \ | ||
149 | KERN_INFO "offset : %d\n" \ | ||
150 | KERN_INFO "spans : %d\n" \ | ||
151 | KERN_INFO "uncmpr : 0x%04x\n" \ | ||
152 | KERN_INFO "foffs : " LL_X, \ | ||
153 | (info)->cmpr_pos, (info)->cmpr_sz, (info)->first_block, \ | ||
154 | (info)->count, (info)->offset, (info)->spans == 1, \ | ||
155 | (info)->uncmpr, LL((info)->foffs)) | ||
156 | |||
157 | /* dispatch compression segment info, return error code | ||
158 | * | ||
159 | * afterwards, cseg->offset points to start of data of the NEXT | ||
160 | * compressed block, and cseg->count contains the amount of data | ||
161 | * left in the actual compressed block. cseg->spans is set to 1 if | ||
162 | * the block is continued in the following segment. Otherwise it is | ||
163 | * set to 0. | ||
164 | */ | ||
165 | static int get_cseg (cmpr_info *cinfo, const __u8 *buff, | ||
166 | const unsigned int seg_sz, | ||
167 | const zft_volinfo *volume) | ||
168 | { | ||
169 | TRACE_FUN(ft_t_flow); | ||
170 | |||
171 | cinfo->first_block = GET2(buff, 0); | ||
172 | if (cinfo->first_block == 0) { /* data spans to next segment */ | ||
173 | cinfo->count = seg_sz - sizeof(__u16); | ||
174 | cinfo->offset = seg_sz; | ||
175 | cinfo->spans = 1; | ||
176 | } else { /* cluster definetely ends in this segment */ | ||
177 | if (cinfo->first_block > seg_sz) { | ||
178 | /* data corrupted */ | ||
179 | TRACE_ABORT(-EIO, ft_t_err, "corrupted data:\n" | ||
180 | KERN_INFO "segment size: %d\n" | ||
181 | KERN_INFO "first block : %d", | ||
182 | seg_sz, cinfo->first_block); | ||
183 | } | ||
184 | cinfo->count = cinfo->first_block - sizeof(__u16); | ||
185 | cinfo->offset = cinfo->first_block; | ||
186 | cinfo->spans = 0; | ||
187 | } | ||
188 | /* now get the offset the first block should have in the | ||
189 | * uncompressed data stream. | ||
190 | * | ||
191 | * For this magic `18' refer to CRF-3 standard or QIC-80MC, | ||
192 | * Rev. K. | ||
193 | */ | ||
194 | if ((seg_sz - cinfo->offset) > 18) { | ||
195 | if (volume->qic113) { /* > revision K */ | ||
196 | TRACE(ft_t_data_flow, "New QIC-113 compliance"); | ||
197 | cinfo->foffs = GET8(buff, cinfo->offset); | ||
198 | cinfo->offset += sizeof(__s64); | ||
199 | } else { | ||
200 | TRACE(/* ft_t_data_flow */ ft_t_noise, "pre QIC-113 version"); | ||
201 | cinfo->foffs = (__s64)GET4(buff, cinfo->offset); | ||
202 | cinfo->offset += sizeof(__u32); | ||
203 | } | ||
204 | } | ||
205 | if (cinfo->foffs > volume->size) { | ||
206 | TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n" | ||
207 | KERN_INFO "offset in current volume: %d\n" | ||
208 | KERN_INFO "size of current volume : %d", | ||
209 | (int)(cinfo->foffs>>10), (int)(volume->size>>10)); | ||
210 | } | ||
211 | if (cinfo->cmpr_pos + cinfo->count > volume->blk_sz) { | ||
212 | TRACE_ABORT(-EIO, ft_t_err, "Inconsistency:\n" | ||
213 | KERN_INFO "block size : %d\n" | ||
214 | KERN_INFO "data record: %d", | ||
215 | volume->blk_sz, cinfo->cmpr_pos + cinfo->count); | ||
216 | } | ||
217 | DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", cinfo); | ||
218 | TRACE_EXIT 0; | ||
219 | } | ||
220 | |||
221 | /* This one is called, when a new cluster starts in same segment. | ||
222 | * | ||
223 | * Note: if this is the first cluster in the current segment, we must | ||
224 | * not check whether there are more than 18 bytes available because | ||
225 | * this have already been done in get_cseg() and there may be less | ||
226 | * than 18 bytes available due to header information. | ||
227 | * | ||
228 | */ | ||
229 | static void get_next_cluster(cmpr_info *cluster, const __u8 *buff, | ||
230 | const int seg_sz, const int finish) | ||
231 | { | ||
232 | TRACE_FUN(ft_t_flow); | ||
233 | |||
234 | if (seg_sz - cluster->offset > 18 || cluster->foffs != 0) { | ||
235 | cluster->count = GET2(buff, cluster->offset); | ||
236 | cluster->uncmpr = cluster->count & 0x8000; | ||
237 | cluster->count -= cluster->uncmpr; | ||
238 | cluster->offset += sizeof(__u16); | ||
239 | cluster->foffs = 0; | ||
240 | if ((cluster->offset + cluster->count) < seg_sz) { | ||
241 | cluster->spans = 0; | ||
242 | } else if (cluster->offset + cluster->count == seg_sz) { | ||
243 | cluster->spans = !finish; | ||
244 | } else { | ||
245 | /* either an error or a volume written by an | ||
246 | * old version. If this is a data error, then we'll | ||
247 | * catch it later. | ||
248 | */ | ||
249 | TRACE(ft_t_data_flow, "Either error or old volume"); | ||
250 | cluster->spans = 1; | ||
251 | cluster->count = seg_sz - cluster->offset; | ||
252 | } | ||
253 | } else { | ||
254 | cluster->count = 0; | ||
255 | cluster->spans = 0; | ||
256 | cluster->foffs = 0; | ||
257 | } | ||
258 | DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */ , "", cluster); | ||
259 | TRACE_EXIT; | ||
260 | } | ||
261 | |||
262 | static void zftc_lock(void) | ||
263 | { | ||
264 | } | ||
265 | |||
266 | /* this function is needed for zftape_reset_position in zftape-io.c | ||
267 | */ | ||
268 | static void zftc_reset(void) | ||
269 | { | ||
270 | TRACE_FUN(ft_t_flow); | ||
271 | |||
272 | memset((void *)&cseg, '\0', sizeof(cseg)); | ||
273 | zftc_stats(); | ||
274 | TRACE_EXIT; | ||
275 | } | ||
276 | |||
277 | static int cmpr_mem_initialized = 0; | ||
278 | static unsigned int alloc_blksz = 0; | ||
279 | |||
280 | static int zft_allocate_cmpr_mem(unsigned int blksz) | ||
281 | { | ||
282 | TRACE_FUN(ft_t_flow); | ||
283 | |||
284 | if (cmpr_mem_initialized && blksz == alloc_blksz) { | ||
285 | TRACE_EXIT 0; | ||
286 | } | ||
287 | TRACE_CATCH(zft_vmalloc_once(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE), | ||
288 | zftc_cleanup()); | ||
289 | TRACE_CATCH(zft_vmalloc_always(&zftc_buf, blksz + CMPR_OVERRUN), | ||
290 | zftc_cleanup()); | ||
291 | alloc_blksz = blksz; | ||
292 | TRACE_CATCH(zft_vmalloc_always(&zftc_scratch_buf, blksz+CMPR_OVERRUN), | ||
293 | zftc_cleanup()); | ||
294 | cmpr_mem_initialized = 1; | ||
295 | TRACE_EXIT 0; | ||
296 | } | ||
297 | |||
298 | static void zftc_cleanup(void) | ||
299 | { | ||
300 | TRACE_FUN(ft_t_flow); | ||
301 | |||
302 | zft_vfree(&zftc_wrk_mem, CMPR_WRK_MEM_SIZE); | ||
303 | zft_vfree(&zftc_buf, alloc_blksz + CMPR_OVERRUN); | ||
304 | zft_vfree(&zftc_scratch_buf, alloc_blksz + CMPR_OVERRUN); | ||
305 | cmpr_mem_initialized = alloc_blksz = 0; | ||
306 | TRACE_EXIT; | ||
307 | } | ||
308 | |||
309 | /***************************************************************************** | ||
310 | * * | ||
311 | * The following two functions "ftape_compress()" and * | ||
312 | * "ftape_uncompress()" are the interface to the actual compression * | ||
313 | * algorithm (i.e. they are calling the "compress()" function from * | ||
314 | * the lzrw3 package for now). These routines could quite easily be * | ||
315 | * changed to adopt another compression algorithm instead of lzrw3, * | ||
316 | * which currently is used. * | ||
317 | * * | ||
318 | *****************************************************************************/ | ||
319 | |||
320 | /* called by zft_compress_write() to perform the compression. Must | ||
321 | * return the size of the compressed data. | ||
322 | * | ||
323 | * NOTE: The size of the compressed data should not exceed the size of | ||
324 | * the uncompressed data. Most compression algorithms have means | ||
325 | * to store data unchanged if the "compressed" data amount would | ||
326 | * exceed the original one. Mostly this is done by storing some | ||
327 | * flag-bytes in front of the compressed data to indicate if it | ||
328 | * is compressed or not. Thus the worst compression result | ||
329 | * length is the original length plus those flag-bytes. | ||
330 | * | ||
331 | * We don't want that, as the QIC-80 standard provides a means | ||
332 | * of marking uncompressed blocks by simply setting bit 15 of | ||
333 | * the compressed block's length. Thus a compessed block can | ||
334 | * have at most a length of 2^15-1 bytes. The QIC-80 standard | ||
335 | * restricts the block-length even further, allowing only 29k - | ||
336 | * 6 bytes. | ||
337 | * | ||
338 | * Currently, the maximum blocksize used by zftape is 28k. | ||
339 | * | ||
340 | * In short: don't exceed the length of the input-package, set | ||
341 | * bit 15 of the compressed size to 1 if you have copied data | ||
342 | * instead of compressing it. | ||
343 | */ | ||
344 | static int zft_compress(__u8 *in_buffer, unsigned int in_sz, __u8 *out_buffer) | ||
345 | { | ||
346 | __s32 compressed_sz; | ||
347 | TRACE_FUN(ft_t_flow); | ||
348 | |||
349 | |||
350 | lzrw3_compress(COMPRESS_ACTION_COMPRESS, zftc_wrk_mem, | ||
351 | in_buffer, in_sz, out_buffer, &compressed_sz); | ||
352 | if (TRACE_LEVEL >= ft_t_info) { | ||
353 | /* the compiler will optimize this away when | ||
354 | * compiled with NO_TRACE_AT_ALL option | ||
355 | */ | ||
356 | TRACE(ft_t_data_flow, "\n" | ||
357 | KERN_INFO "before compression: %d bytes\n" | ||
358 | KERN_INFO "after compresison : %d bytes", | ||
359 | in_sz, | ||
360 | (int)(compressed_sz < 0 | ||
361 | ? -compressed_sz : compressed_sz)); | ||
362 | /* for statistical purposes | ||
363 | */ | ||
364 | zftc_wr_compressed += (compressed_sz < 0 | ||
365 | ? -compressed_sz : compressed_sz); | ||
366 | zftc_wr_uncompressed += in_sz; | ||
367 | } | ||
368 | TRACE_EXIT (int)compressed_sz; | ||
369 | } | ||
370 | |||
371 | /* called by zft_compress_read() to decompress the data. Must | ||
372 | * return the size of the decompressed data for sanity checks | ||
373 | * (compared with zft_blk_sz) | ||
374 | * | ||
375 | * NOTE: Read the note for zft_compress() above! If bit 15 of the | ||
376 | * parameter in_sz is set, then the data in in_buffer isn't | ||
377 | * compressed, which must be handled by the un-compression | ||
378 | * algorithm. (I changed lzrw3 to handle this.) | ||
379 | * | ||
380 | * The parameter max_out_sz is needed to prevent buffer overruns when | ||
381 | * uncompressing corrupt data. | ||
382 | */ | ||
383 | static unsigned int zft_uncompress(__u8 *in_buffer, | ||
384 | int in_sz, | ||
385 | __u8 *out_buffer, | ||
386 | unsigned int max_out_sz) | ||
387 | { | ||
388 | TRACE_FUN(ft_t_flow); | ||
389 | |||
390 | lzrw3_compress(COMPRESS_ACTION_DECOMPRESS, zftc_wrk_mem, | ||
391 | in_buffer, (__s32)in_sz, | ||
392 | out_buffer, (__u32 *)&max_out_sz); | ||
393 | |||
394 | if (TRACE_LEVEL >= ft_t_info) { | ||
395 | TRACE(ft_t_data_flow, "\n" | ||
396 | KERN_INFO "before decompression: %d bytes\n" | ||
397 | KERN_INFO "after decompression : %d bytes", | ||
398 | in_sz < 0 ? -in_sz : in_sz,(int)max_out_sz); | ||
399 | /* for statistical purposes | ||
400 | */ | ||
401 | zftc_rd_compressed += in_sz < 0 ? -in_sz : in_sz; | ||
402 | zftc_rd_uncompressed += max_out_sz; | ||
403 | } | ||
404 | TRACE_EXIT (unsigned int)max_out_sz; | ||
405 | } | ||
406 | |||
407 | /* print some statistics about the efficiency of the compression to | ||
408 | * the kernel log | ||
409 | */ | ||
410 | static void zftc_stats(void) | ||
411 | { | ||
412 | TRACE_FUN(ft_t_flow); | ||
413 | |||
414 | if (TRACE_LEVEL < ft_t_info) { | ||
415 | TRACE_EXIT; | ||
416 | } | ||
417 | if (zftc_wr_uncompressed != 0) { | ||
418 | if (zftc_wr_compressed > (1<<14)) { | ||
419 | TRACE(ft_t_info, "compression statistics (writing):\n" | ||
420 | KERN_INFO " compr./uncmpr. : %3d %%", | ||
421 | (((zftc_wr_compressed>>10) * 100) | ||
422 | / (zftc_wr_uncompressed>>10))); | ||
423 | } else { | ||
424 | TRACE(ft_t_info, "compression statistics (writing):\n" | ||
425 | KERN_INFO " compr./uncmpr. : %3d %%", | ||
426 | ((zftc_wr_compressed * 100) | ||
427 | / zftc_wr_uncompressed)); | ||
428 | } | ||
429 | } | ||
430 | if (zftc_rd_uncompressed != 0) { | ||
431 | if (zftc_rd_compressed > (1<<14)) { | ||
432 | TRACE(ft_t_info, "compression statistics (reading):\n" | ||
433 | KERN_INFO " compr./uncmpr. : %3d %%", | ||
434 | (((zftc_rd_compressed>>10) * 100) | ||
435 | / (zftc_rd_uncompressed>>10))); | ||
436 | } else { | ||
437 | TRACE(ft_t_info, "compression statistics (reading):\n" | ||
438 | KERN_INFO " compr./uncmpr. : %3d %%", | ||
439 | ((zftc_rd_compressed * 100) | ||
440 | / zftc_rd_uncompressed)); | ||
441 | } | ||
442 | } | ||
443 | /* only print it once: */ | ||
444 | zftc_wr_uncompressed = | ||
445 | zftc_wr_compressed = | ||
446 | zftc_rd_uncompressed = | ||
447 | zftc_rd_compressed = 0; | ||
448 | TRACE_EXIT; | ||
449 | } | ||
450 | |||
451 | /* start new compressed block | ||
452 | */ | ||
453 | static int start_new_cseg(cmpr_info *cluster, | ||
454 | char *dst_buf, | ||
455 | const zft_position *pos, | ||
456 | const unsigned int blk_sz, | ||
457 | const char *src_buf, | ||
458 | const int this_segs_sz, | ||
459 | const int qic113) | ||
460 | { | ||
461 | int size_left; | ||
462 | int cp_cnt; | ||
463 | int buf_pos; | ||
464 | TRACE_FUN(ft_t_flow); | ||
465 | |||
466 | size_left = this_segs_sz - sizeof(__u16) - cluster->cmpr_sz; | ||
467 | TRACE(ft_t_data_flow,"\n" | ||
468 | KERN_INFO "segment size : %d\n" | ||
469 | KERN_INFO "compressed_sz: %d\n" | ||
470 | KERN_INFO "size_left : %d", | ||
471 | this_segs_sz, cluster->cmpr_sz, size_left); | ||
472 | if (size_left > 18) { /* start a new cluseter */ | ||
473 | cp_cnt = cluster->cmpr_sz; | ||
474 | cluster->cmpr_sz = 0; | ||
475 | buf_pos = cp_cnt + sizeof(__u16); | ||
476 | PUT2(dst_buf, 0, buf_pos); | ||
477 | |||
478 | if (qic113) { | ||
479 | __s64 foffs = pos->volume_pos; | ||
480 | if (cp_cnt) foffs += (__s64)blk_sz; | ||
481 | |||
482 | TRACE(ft_t_data_flow, "new style QIC-113 header"); | ||
483 | PUT8(dst_buf, buf_pos, foffs); | ||
484 | buf_pos += sizeof(__s64); | ||
485 | } else { | ||
486 | __u32 foffs = (__u32)pos->volume_pos; | ||
487 | if (cp_cnt) foffs += (__u32)blk_sz; | ||
488 | |||
489 | TRACE(ft_t_data_flow, "old style QIC-80MC header"); | ||
490 | PUT4(dst_buf, buf_pos, foffs); | ||
491 | buf_pos += sizeof(__u32); | ||
492 | } | ||
493 | } else if (size_left >= 0) { | ||
494 | cp_cnt = cluster->cmpr_sz; | ||
495 | cluster->cmpr_sz = 0; | ||
496 | buf_pos = cp_cnt + sizeof(__u16); | ||
497 | PUT2(dst_buf, 0, buf_pos); | ||
498 | /* zero unused part of segment. */ | ||
499 | memset(dst_buf + buf_pos, '\0', size_left); | ||
500 | buf_pos = this_segs_sz; | ||
501 | } else { /* need entire segment and more space */ | ||
502 | PUT2(dst_buf, 0, 0); | ||
503 | cp_cnt = this_segs_sz - sizeof(__u16); | ||
504 | cluster->cmpr_sz -= cp_cnt; | ||
505 | buf_pos = this_segs_sz; | ||
506 | } | ||
507 | memcpy(dst_buf + sizeof(__u16), src_buf + cluster->cmpr_pos, cp_cnt); | ||
508 | cluster->cmpr_pos += cp_cnt; | ||
509 | TRACE_EXIT buf_pos; | ||
510 | } | ||
511 | |||
512 | /* return-value: the number of bytes removed from the user-buffer | ||
513 | * `src_buf' or error code | ||
514 | * | ||
515 | * int *write_cnt : how much actually has been moved to the | ||
516 | * dst_buf. Need not be initialized when | ||
517 | * function returns with an error code | ||
518 | * (negativ return value) | ||
519 | * __u8 *dst_buf : kernel space buffer where the has to be | ||
520 | * copied to. The contents of this buffers | ||
521 | * goes to a specific segment. | ||
522 | * const int seg_sz : the size of the segment dst_buf will be | ||
523 | * copied to. | ||
524 | * const zft_position *pos : struct containing the coordinates in | ||
525 | * the current volume (byte position, | ||
526 | * segment id of current segment etc) | ||
527 | * const zft_volinfo *volume: information about the current volume, | ||
528 | * size etc. | ||
529 | * const __u8 *src_buf : user space buffer that contains the | ||
530 | * data the user wants to be written to | ||
531 | * tape. | ||
532 | * const int req_len : the amount of data the user wants to be | ||
533 | * written to tape. | ||
534 | */ | ||
535 | static int zftc_write(int *write_cnt, | ||
536 | __u8 *dst_buf, const int seg_sz, | ||
537 | const __u8 __user *src_buf, const int req_len, | ||
538 | const zft_position *pos, const zft_volinfo *volume) | ||
539 | { | ||
540 | int req_len_left = req_len; | ||
541 | int result; | ||
542 | int len_left; | ||
543 | int buf_pos_write = pos->seg_byte_pos; | ||
544 | TRACE_FUN(ft_t_flow); | ||
545 | |||
546 | /* Note: we do not unlock the module because | ||
547 | * there are some values cached in that `cseg' variable. We | ||
548 | * don't don't want to use this information when being | ||
549 | * unloaded by kerneld even when the tape is full or when we | ||
550 | * cannot allocate enough memory. | ||
551 | */ | ||
552 | if (pos->tape_pos > (volume->size-volume->blk_sz-ZFT_CMPR_OVERHEAD)) { | ||
553 | TRACE_EXIT -ENOSPC; | ||
554 | } | ||
555 | if (zft_allocate_cmpr_mem(volume->blk_sz) < 0) { | ||
556 | /* should we unlock the module? But it shouldn't | ||
557 | * be locked anyway ... | ||
558 | */ | ||
559 | TRACE_EXIT -ENOMEM; | ||
560 | } | ||
561 | if (buf_pos_write == 0) { /* fill a new segment */ | ||
562 | *write_cnt = buf_pos_write = start_new_cseg(&cseg, | ||
563 | dst_buf, | ||
564 | pos, | ||
565 | volume->blk_sz, | ||
566 | zftc_buf, | ||
567 | seg_sz, | ||
568 | volume->qic113); | ||
569 | if (cseg.cmpr_sz == 0 && cseg.cmpr_pos != 0) { | ||
570 | req_len_left -= result = volume->blk_sz; | ||
571 | cseg.cmpr_pos = 0; | ||
572 | } else { | ||
573 | result = 0; | ||
574 | } | ||
575 | } else { | ||
576 | *write_cnt = result = 0; | ||
577 | } | ||
578 | |||
579 | len_left = seg_sz - buf_pos_write; | ||
580 | while ((req_len_left > 0) && (len_left > 18)) { | ||
581 | /* now we have some size left for a new compressed | ||
582 | * block. We know, that the compression buffer is | ||
583 | * empty (else there wouldn't be any space left). | ||
584 | */ | ||
585 | if (copy_from_user(zftc_scratch_buf, src_buf + result, | ||
586 | volume->blk_sz) != 0) { | ||
587 | TRACE_EXIT -EFAULT; | ||
588 | } | ||
589 | req_len_left -= volume->blk_sz; | ||
590 | cseg.cmpr_sz = zft_compress(zftc_scratch_buf, volume->blk_sz, | ||
591 | zftc_buf); | ||
592 | if (cseg.cmpr_sz < 0) { | ||
593 | cseg.uncmpr = 0x8000; | ||
594 | cseg.cmpr_sz = -cseg.cmpr_sz; | ||
595 | } else { | ||
596 | cseg.uncmpr = 0; | ||
597 | } | ||
598 | /* increment "result" iff we copied the entire | ||
599 | * compressed block to the zft_deblock_buf | ||
600 | */ | ||
601 | len_left -= sizeof(__u16); | ||
602 | if (len_left >= cseg.cmpr_sz) { | ||
603 | len_left -= cseg.count = cseg.cmpr_sz; | ||
604 | cseg.cmpr_pos = cseg.cmpr_sz = 0; | ||
605 | result += volume->blk_sz; | ||
606 | } else { | ||
607 | cseg.cmpr_sz -= | ||
608 | cseg.cmpr_pos = | ||
609 | cseg.count = len_left; | ||
610 | len_left = 0; | ||
611 | } | ||
612 | PUT2(dst_buf, buf_pos_write, cseg.uncmpr | cseg.count); | ||
613 | buf_pos_write += sizeof(__u16); | ||
614 | memcpy(dst_buf + buf_pos_write, zftc_buf, cseg.count); | ||
615 | buf_pos_write += cseg.count; | ||
616 | *write_cnt += cseg.count + sizeof(__u16); | ||
617 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
618 | } | ||
619 | /* erase the remainder of the segment if less than 18 bytes | ||
620 | * left (18 bytes is due to the QIC-80 standard) | ||
621 | */ | ||
622 | if (len_left <= 18) { | ||
623 | memset(dst_buf + buf_pos_write, '\0', len_left); | ||
624 | (*write_cnt) += len_left; | ||
625 | } | ||
626 | TRACE(ft_t_data_flow, "returning %d", result); | ||
627 | TRACE_EXIT result; | ||
628 | } | ||
629 | |||
630 | /* out: | ||
631 | * | ||
632 | * int *read_cnt: the number of bytes we removed from the zft_deblock_buf | ||
633 | * (result) | ||
634 | * int *to_do : the remaining size of the read-request. | ||
635 | * | ||
636 | * in: | ||
637 | * | ||
638 | * char *buff : buff is the address of the upper part of the user | ||
639 | * buffer, that hasn't been filled with data yet. | ||
640 | |||
641 | * int buf_pos_read : copy of from _ftape_read() | ||
642 | * int buf_len_read : copy of buf_len_rd from _ftape_read() | ||
643 | * char *zft_deblock_buf: zft_deblock_buf | ||
644 | * unsigned short blk_sz: the block size valid for this volume, may differ | ||
645 | * from zft_blk_sz. | ||
646 | * int finish: if != 0 means that this is the last segment belonging | ||
647 | * to this volume | ||
648 | * returns the amount of data actually copied to the user-buffer | ||
649 | * | ||
650 | * to_do MUST NOT SHRINK except to indicate an EOF. In this case *to_do has to | ||
651 | * be set to 0 | ||
652 | */ | ||
653 | static int zftc_read (int *read_cnt, | ||
654 | __u8 __user *dst_buf, const int to_do, | ||
655 | const __u8 *src_buf, const int seg_sz, | ||
656 | const zft_position *pos, const zft_volinfo *volume) | ||
657 | { | ||
658 | int uncompressed_sz; | ||
659 | int result = 0; | ||
660 | int remaining = to_do; | ||
661 | TRACE_FUN(ft_t_flow); | ||
662 | |||
663 | TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),); | ||
664 | if (pos->seg_byte_pos == 0) { | ||
665 | /* new segment just read | ||
666 | */ | ||
667 | TRACE_CATCH(get_cseg(&cseg, src_buf, seg_sz, volume), | ||
668 | *read_cnt = 0); | ||
669 | memcpy(zftc_buf + cseg.cmpr_pos, src_buf + sizeof(__u16), | ||
670 | cseg.count); | ||
671 | cseg.cmpr_pos += cseg.count; | ||
672 | *read_cnt = cseg.offset; | ||
673 | DUMP_CMPR_INFO(ft_t_noise /* ft_t_any */, "", &cseg); | ||
674 | } else { | ||
675 | *read_cnt = 0; | ||
676 | } | ||
677 | /* loop and uncompress until user buffer full or | ||
678 | * deblock-buffer empty | ||
679 | */ | ||
680 | TRACE(ft_t_data_flow, "compressed_sz: %d, compos : %d, *read_cnt: %d", | ||
681 | cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt); | ||
682 | while ((cseg.spans == 0) && (remaining > 0)) { | ||
683 | if (cseg.cmpr_pos != 0) { /* cmpr buf is not empty */ | ||
684 | uncompressed_sz = | ||
685 | zft_uncompress(zftc_buf, | ||
686 | cseg.uncmpr == 0x8000 ? | ||
687 | -cseg.cmpr_pos : cseg.cmpr_pos, | ||
688 | zftc_scratch_buf, | ||
689 | volume->blk_sz); | ||
690 | if (uncompressed_sz != volume->blk_sz) { | ||
691 | *read_cnt = 0; | ||
692 | TRACE_ABORT(-EIO, ft_t_warn, | ||
693 | "Uncompressed blk (%d) != blk size (%d)", | ||
694 | uncompressed_sz, volume->blk_sz); | ||
695 | } | ||
696 | if (copy_to_user(dst_buf + result, | ||
697 | zftc_scratch_buf, | ||
698 | uncompressed_sz) != 0 ) { | ||
699 | TRACE_EXIT -EFAULT; | ||
700 | } | ||
701 | remaining -= uncompressed_sz; | ||
702 | result += uncompressed_sz; | ||
703 | cseg.cmpr_pos = 0; | ||
704 | } | ||
705 | if (remaining > 0) { | ||
706 | get_next_cluster(&cseg, src_buf, seg_sz, | ||
707 | volume->end_seg == pos->seg_pos); | ||
708 | if (cseg.count != 0) { | ||
709 | memcpy(zftc_buf, src_buf + cseg.offset, | ||
710 | cseg.count); | ||
711 | cseg.cmpr_pos = cseg.count; | ||
712 | cseg.offset += cseg.count; | ||
713 | *read_cnt += cseg.count + sizeof(__u16); | ||
714 | } else { | ||
715 | remaining = 0; | ||
716 | } | ||
717 | } | ||
718 | TRACE(ft_t_data_flow, "\n" | ||
719 | KERN_INFO "compressed_sz: %d\n" | ||
720 | KERN_INFO "compos : %d\n" | ||
721 | KERN_INFO "*read_cnt : %d", | ||
722 | cseg.cmpr_sz, cseg.cmpr_pos, *read_cnt); | ||
723 | } | ||
724 | if (seg_sz - cseg.offset <= 18) { | ||
725 | *read_cnt += seg_sz - cseg.offset; | ||
726 | TRACE(ft_t_data_flow, "expanding read cnt to: %d", *read_cnt); | ||
727 | } | ||
728 | TRACE(ft_t_data_flow, "\n" | ||
729 | KERN_INFO "segment size : %d\n" | ||
730 | KERN_INFO "read count : %d\n" | ||
731 | KERN_INFO "buf_pos_read : %d\n" | ||
732 | KERN_INFO "remaining : %d", | ||
733 | seg_sz, *read_cnt, pos->seg_byte_pos, | ||
734 | seg_sz - *read_cnt - pos->seg_byte_pos); | ||
735 | TRACE(ft_t_data_flow, "returning: %d", result); | ||
736 | TRACE_EXIT result; | ||
737 | } | ||
738 | |||
739 | /* seeks to the new data-position. Reads sometimes a segment. | ||
740 | * | ||
741 | * start_seg and end_seg give the boundaries of the current volume | ||
742 | * blk_sz is the blk_sz of the current volume as stored in the | ||
743 | * volume label | ||
744 | * | ||
745 | * We don't allow blocksizes less than 1024 bytes, therefore we don't need | ||
746 | * a 64 bit argument for new_block_pos. | ||
747 | */ | ||
748 | |||
749 | static int seek_in_segment(const unsigned int to_do, cmpr_info *c_info, | ||
750 | const char *src_buf, const int seg_sz, | ||
751 | const int seg_pos, const zft_volinfo *volume); | ||
752 | static int slow_seek_forward_until_error(const unsigned int distance, | ||
753 | cmpr_info *c_info, zft_position *pos, | ||
754 | const zft_volinfo *volume, __u8 *buf); | ||
755 | static int search_valid_segment(unsigned int segment, | ||
756 | const unsigned int end_seg, | ||
757 | const unsigned int max_foffs, | ||
758 | zft_position *pos, cmpr_info *c_info, | ||
759 | const zft_volinfo *volume, __u8 *buf); | ||
760 | static int slow_seek_forward(unsigned int dest, cmpr_info *c_info, | ||
761 | zft_position *pos, const zft_volinfo *volume, | ||
762 | __u8 *buf); | ||
763 | static int compute_seg_pos(unsigned int dest, zft_position *pos, | ||
764 | const zft_volinfo *volume); | ||
765 | |||
766 | #define ZFT_SLOW_SEEK_THRESHOLD 10 /* segments */ | ||
767 | #define ZFT_FAST_SEEK_MAX_TRIALS 10 /* times */ | ||
768 | #define ZFT_FAST_SEEK_BACKUP 10 /* segments */ | ||
769 | |||
770 | static int zftc_seek(unsigned int new_block_pos, | ||
771 | zft_position *pos, const zft_volinfo *volume, __u8 *buf) | ||
772 | { | ||
773 | unsigned int dest; | ||
774 | int limit; | ||
775 | int distance; | ||
776 | int result = 0; | ||
777 | int seg_dist; | ||
778 | int new_seg; | ||
779 | int old_seg = 0; | ||
780 | int fast_seek_trials = 0; | ||
781 | TRACE_FUN(ft_t_flow); | ||
782 | |||
783 | if (new_block_pos == 0) { | ||
784 | pos->seg_pos = volume->start_seg; | ||
785 | pos->seg_byte_pos = 0; | ||
786 | pos->volume_pos = 0; | ||
787 | zftc_reset(); | ||
788 | TRACE_EXIT 0; | ||
789 | } | ||
790 | dest = new_block_pos * (volume->blk_sz >> 10); | ||
791 | distance = dest - (pos->volume_pos >> 10); | ||
792 | while (distance != 0) { | ||
793 | seg_dist = compute_seg_pos(dest, pos, volume); | ||
794 | TRACE(ft_t_noise, "\n" | ||
795 | KERN_INFO "seg_dist: %d\n" | ||
796 | KERN_INFO "distance: %d\n" | ||
797 | KERN_INFO "dest : %d\n" | ||
798 | KERN_INFO "vpos : %d\n" | ||
799 | KERN_INFO "seg_pos : %d\n" | ||
800 | KERN_INFO "trials : %d", | ||
801 | seg_dist, distance, dest, | ||
802 | (unsigned int)(pos->volume_pos>>10), pos->seg_pos, | ||
803 | fast_seek_trials); | ||
804 | if (distance > 0) { | ||
805 | if (seg_dist < 0) { | ||
806 | TRACE(ft_t_bug, "BUG: distance %d > 0, " | ||
807 | "segment difference %d < 0", | ||
808 | distance, seg_dist); | ||
809 | result = -EIO; | ||
810 | break; | ||
811 | } | ||
812 | new_seg = pos->seg_pos + seg_dist; | ||
813 | if (new_seg > volume->end_seg) { | ||
814 | new_seg = volume->end_seg; | ||
815 | } | ||
816 | if (old_seg == new_seg || /* loop */ | ||
817 | seg_dist <= ZFT_SLOW_SEEK_THRESHOLD || | ||
818 | fast_seek_trials >= ZFT_FAST_SEEK_MAX_TRIALS) { | ||
819 | TRACE(ft_t_noise, "starting slow seek:\n" | ||
820 | KERN_INFO "fast seek failed too often: %s\n" | ||
821 | KERN_INFO "near target position : %s\n" | ||
822 | KERN_INFO "looping between two segs : %s", | ||
823 | (fast_seek_trials >= | ||
824 | ZFT_FAST_SEEK_MAX_TRIALS) | ||
825 | ? "yes" : "no", | ||
826 | (seg_dist <= ZFT_SLOW_SEEK_THRESHOLD) | ||
827 | ? "yes" : "no", | ||
828 | (old_seg == new_seg) | ||
829 | ? "yes" : "no"); | ||
830 | result = slow_seek_forward(dest, &cseg, | ||
831 | pos, volume, buf); | ||
832 | break; | ||
833 | } | ||
834 | old_seg = new_seg; | ||
835 | limit = volume->end_seg; | ||
836 | fast_seek_trials ++; | ||
837 | for (;;) { | ||
838 | result = search_valid_segment(new_seg, limit, | ||
839 | volume->size, | ||
840 | pos, &cseg, | ||
841 | volume, buf); | ||
842 | if (result == 0 || result == -EINTR) { | ||
843 | break; | ||
844 | } | ||
845 | if (new_seg == volume->start_seg) { | ||
846 | result = -EIO; /* set errror | ||
847 | * condition | ||
848 | */ | ||
849 | break; | ||
850 | } | ||
851 | limit = new_seg; | ||
852 | new_seg -= ZFT_FAST_SEEK_BACKUP; | ||
853 | if (new_seg < volume->start_seg) { | ||
854 | new_seg = volume->start_seg; | ||
855 | } | ||
856 | } | ||
857 | if (result < 0) { | ||
858 | TRACE(ft_t_warn, | ||
859 | "Couldn't find a readable segment"); | ||
860 | break; | ||
861 | } | ||
862 | } else /* if (distance < 0) */ { | ||
863 | if (seg_dist > 0) { | ||
864 | TRACE(ft_t_bug, "BUG: distance %d < 0, " | ||
865 | "segment difference %d >0", | ||
866 | distance, seg_dist); | ||
867 | result = -EIO; | ||
868 | break; | ||
869 | } | ||
870 | new_seg = pos->seg_pos + seg_dist; | ||
871 | if (fast_seek_trials > 0 && seg_dist == 0) { | ||
872 | /* this avoids sticking to the same | ||
873 | * segment all the time. On the other hand: | ||
874 | * if we got here for the first time, and the | ||
875 | * deblock_buffer still contains a valid | ||
876 | * segment, then there is no need to skip to | ||
877 | * the previous segment if the desired position | ||
878 | * is inside this segment. | ||
879 | */ | ||
880 | new_seg --; | ||
881 | } | ||
882 | if (new_seg < volume->start_seg) { | ||
883 | new_seg = volume->start_seg; | ||
884 | } | ||
885 | limit = pos->seg_pos; | ||
886 | fast_seek_trials ++; | ||
887 | for (;;) { | ||
888 | result = search_valid_segment(new_seg, limit, | ||
889 | pos->volume_pos, | ||
890 | pos, &cseg, | ||
891 | volume, buf); | ||
892 | if (result == 0 || result == -EINTR) { | ||
893 | break; | ||
894 | } | ||
895 | if (new_seg == volume->start_seg) { | ||
896 | result = -EIO; /* set errror | ||
897 | * condition | ||
898 | */ | ||
899 | break; | ||
900 | } | ||
901 | limit = new_seg; | ||
902 | new_seg -= ZFT_FAST_SEEK_BACKUP; | ||
903 | if (new_seg < volume->start_seg) { | ||
904 | new_seg = volume->start_seg; | ||
905 | } | ||
906 | } | ||
907 | if (result < 0) { | ||
908 | TRACE(ft_t_warn, | ||
909 | "Couldn't find a readable segment"); | ||
910 | break; | ||
911 | } | ||
912 | } | ||
913 | distance = dest - (pos->volume_pos >> 10); | ||
914 | } | ||
915 | TRACE_EXIT result; | ||
916 | } | ||
917 | |||
918 | |||
919 | /* advance inside the given segment at most to_do bytes. | ||
920 | * of kilobytes moved | ||
921 | */ | ||
922 | |||
923 | static int seek_in_segment(const unsigned int to_do, | ||
924 | cmpr_info *c_info, | ||
925 | const char *src_buf, | ||
926 | const int seg_sz, | ||
927 | const int seg_pos, | ||
928 | const zft_volinfo *volume) | ||
929 | { | ||
930 | int result = 0; | ||
931 | int blk_sz = volume->blk_sz >> 10; | ||
932 | int remaining = to_do; | ||
933 | TRACE_FUN(ft_t_flow); | ||
934 | |||
935 | if (c_info->offset == 0) { | ||
936 | /* new segment just read | ||
937 | */ | ||
938 | TRACE_CATCH(get_cseg(c_info, src_buf, seg_sz, volume),); | ||
939 | c_info->cmpr_pos += c_info->count; | ||
940 | DUMP_CMPR_INFO(ft_t_noise, "", c_info); | ||
941 | } | ||
942 | /* loop and uncompress until user buffer full or | ||
943 | * deblock-buffer empty | ||
944 | */ | ||
945 | TRACE(ft_t_noise, "compressed_sz: %d, compos : %d", | ||
946 | c_info->cmpr_sz, c_info->cmpr_pos); | ||
947 | while (c_info->spans == 0 && remaining > 0) { | ||
948 | if (c_info->cmpr_pos != 0) { /* cmpr buf is not empty */ | ||
949 | result += blk_sz; | ||
950 | remaining -= blk_sz; | ||
951 | c_info->cmpr_pos = 0; | ||
952 | } | ||
953 | if (remaining > 0) { | ||
954 | get_next_cluster(c_info, src_buf, seg_sz, | ||
955 | volume->end_seg == seg_pos); | ||
956 | if (c_info->count != 0) { | ||
957 | c_info->cmpr_pos = c_info->count; | ||
958 | c_info->offset += c_info->count; | ||
959 | } else { | ||
960 | break; | ||
961 | } | ||
962 | } | ||
963 | /* Allow escape from this loop on signal! | ||
964 | */ | ||
965 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
966 | DUMP_CMPR_INFO(ft_t_noise, "", c_info); | ||
967 | TRACE(ft_t_noise, "to_do: %d", remaining); | ||
968 | } | ||
969 | if (seg_sz - c_info->offset <= 18) { | ||
970 | c_info->offset = seg_sz; | ||
971 | } | ||
972 | TRACE(ft_t_noise, "\n" | ||
973 | KERN_INFO "segment size : %d\n" | ||
974 | KERN_INFO "buf_pos_read : %d\n" | ||
975 | KERN_INFO "remaining : %d", | ||
976 | seg_sz, c_info->offset, | ||
977 | seg_sz - c_info->offset); | ||
978 | TRACE_EXIT result; | ||
979 | } | ||
980 | |||
981 | static int slow_seek_forward_until_error(const unsigned int distance, | ||
982 | cmpr_info *c_info, | ||
983 | zft_position *pos, | ||
984 | const zft_volinfo *volume, | ||
985 | __u8 *buf) | ||
986 | { | ||
987 | unsigned int remaining = distance; | ||
988 | int seg_sz; | ||
989 | int seg_pos; | ||
990 | int result; | ||
991 | TRACE_FUN(ft_t_flow); | ||
992 | |||
993 | seg_pos = pos->seg_pos; | ||
994 | do { | ||
995 | TRACE_CATCH(seg_sz = zft_fetch_segment(seg_pos, buf, | ||
996 | FT_RD_AHEAD),); | ||
997 | /* now we have the contents of the actual segment in | ||
998 | * the deblock buffer | ||
999 | */ | ||
1000 | TRACE_CATCH(result = seek_in_segment(remaining, c_info, buf, | ||
1001 | seg_sz, seg_pos,volume),); | ||
1002 | remaining -= result; | ||
1003 | pos->volume_pos += result<<10; | ||
1004 | pos->seg_pos = seg_pos; | ||
1005 | pos->seg_byte_pos = c_info->offset; | ||
1006 | seg_pos ++; | ||
1007 | if (seg_pos <= volume->end_seg && c_info->offset == seg_sz) { | ||
1008 | pos->seg_pos ++; | ||
1009 | pos->seg_byte_pos = 0; | ||
1010 | c_info->offset = 0; | ||
1011 | } | ||
1012 | /* Allow escape from this loop on signal! | ||
1013 | */ | ||
1014 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
1015 | TRACE(ft_t_noise, "\n" | ||
1016 | KERN_INFO "remaining: %d\n" | ||
1017 | KERN_INFO "seg_pos: %d\n" | ||
1018 | KERN_INFO "end_seg: %d\n" | ||
1019 | KERN_INFO "result: %d", | ||
1020 | remaining, seg_pos, volume->end_seg, result); | ||
1021 | } while (remaining > 0 && seg_pos <= volume->end_seg); | ||
1022 | TRACE_EXIT 0; | ||
1023 | } | ||
1024 | |||
1025 | /* return segment id of next segment containing valid data, -EIO otherwise | ||
1026 | */ | ||
1027 | static int search_valid_segment(unsigned int segment, | ||
1028 | const unsigned int end_seg, | ||
1029 | const unsigned int max_foffs, | ||
1030 | zft_position *pos, | ||
1031 | cmpr_info *c_info, | ||
1032 | const zft_volinfo *volume, | ||
1033 | __u8 *buf) | ||
1034 | { | ||
1035 | cmpr_info tmp_info; | ||
1036 | int seg_sz; | ||
1037 | TRACE_FUN(ft_t_flow); | ||
1038 | |||
1039 | memset(&tmp_info, 0, sizeof(cmpr_info)); | ||
1040 | while (segment <= end_seg) { | ||
1041 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
1042 | TRACE(ft_t_noise, | ||
1043 | "Searching readable segment between %d and %d", | ||
1044 | segment, end_seg); | ||
1045 | seg_sz = zft_fetch_segment(segment, buf, FT_RD_AHEAD); | ||
1046 | if ((seg_sz > 0) && | ||
1047 | (get_cseg (&tmp_info, buf, seg_sz, volume) >= 0) && | ||
1048 | (tmp_info.foffs != 0 || segment == volume->start_seg)) { | ||
1049 | if ((tmp_info.foffs>>10) > max_foffs) { | ||
1050 | TRACE_ABORT(-EIO, ft_t_noise, "\n" | ||
1051 | KERN_INFO "cseg.foff: %d\n" | ||
1052 | KERN_INFO "dest : %d", | ||
1053 | (int)(tmp_info.foffs >> 10), | ||
1054 | max_foffs); | ||
1055 | } | ||
1056 | DUMP_CMPR_INFO(ft_t_noise, "", &tmp_info); | ||
1057 | *c_info = tmp_info; | ||
1058 | pos->seg_pos = segment; | ||
1059 | pos->volume_pos = c_info->foffs; | ||
1060 | pos->seg_byte_pos = c_info->offset; | ||
1061 | TRACE(ft_t_noise, "found segment at %d", segment); | ||
1062 | TRACE_EXIT 0; | ||
1063 | } | ||
1064 | segment++; | ||
1065 | } | ||
1066 | TRACE_EXIT -EIO; | ||
1067 | } | ||
1068 | |||
1069 | static int slow_seek_forward(unsigned int dest, | ||
1070 | cmpr_info *c_info, | ||
1071 | zft_position *pos, | ||
1072 | const zft_volinfo *volume, | ||
1073 | __u8 *buf) | ||
1074 | { | ||
1075 | unsigned int distance; | ||
1076 | int result = 0; | ||
1077 | TRACE_FUN(ft_t_flow); | ||
1078 | |||
1079 | distance = dest - (pos->volume_pos >> 10); | ||
1080 | while ((distance > 0) && | ||
1081 | (result = slow_seek_forward_until_error(distance, | ||
1082 | c_info, | ||
1083 | pos, | ||
1084 | volume, | ||
1085 | buf)) < 0) { | ||
1086 | if (result == -EINTR) { | ||
1087 | break; | ||
1088 | } | ||
1089 | TRACE(ft_t_noise, "seg_pos: %d", pos->seg_pos); | ||
1090 | /* the failing segment is either pos->seg_pos or | ||
1091 | * pos->seg_pos + 1. There is no need to further try | ||
1092 | * that segment, because ftape_read_segment() already | ||
1093 | * has tried very much to read it. So we start with | ||
1094 | * following segment, which is pos->seg_pos + 1 | ||
1095 | */ | ||
1096 | if(search_valid_segment(pos->seg_pos+1, volume->end_seg, dest, | ||
1097 | pos, c_info, | ||
1098 | volume, buf) < 0) { | ||
1099 | TRACE(ft_t_noise, "search_valid_segment() failed"); | ||
1100 | result = -EIO; | ||
1101 | break; | ||
1102 | } | ||
1103 | distance = dest - (pos->volume_pos >> 10); | ||
1104 | result = 0; | ||
1105 | TRACE(ft_t_noise, "segment: %d", pos->seg_pos); | ||
1106 | /* found valid segment, retry the seek */ | ||
1107 | } | ||
1108 | TRACE_EXIT result; | ||
1109 | } | ||
1110 | |||
1111 | static int compute_seg_pos(const unsigned int dest, | ||
1112 | zft_position *pos, | ||
1113 | const zft_volinfo *volume) | ||
1114 | { | ||
1115 | int segment; | ||
1116 | int distance = dest - (pos->volume_pos >> 10); | ||
1117 | unsigned int raw_size; | ||
1118 | unsigned int virt_size; | ||
1119 | unsigned int factor; | ||
1120 | TRACE_FUN(ft_t_flow); | ||
1121 | |||
1122 | if (distance >= 0) { | ||
1123 | raw_size = volume->end_seg - pos->seg_pos + 1; | ||
1124 | virt_size = ((unsigned int)(volume->size>>10) | ||
1125 | - (unsigned int)(pos->volume_pos>>10) | ||
1126 | + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1); | ||
1127 | virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS; | ||
1128 | if (virt_size == 0 || raw_size == 0) { | ||
1129 | TRACE_EXIT 0; | ||
1130 | } | ||
1131 | if (raw_size >= (1<<25)) { | ||
1132 | factor = raw_size/(virt_size>>7); | ||
1133 | } else { | ||
1134 | factor = (raw_size<<7)/virt_size; | ||
1135 | } | ||
1136 | segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS); | ||
1137 | segment = (segment * factor)>>7; | ||
1138 | } else { | ||
1139 | raw_size = pos->seg_pos - volume->start_seg + 1; | ||
1140 | virt_size = ((unsigned int)(pos->volume_pos>>10) | ||
1141 | + FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS - 1); | ||
1142 | virt_size /= FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS; | ||
1143 | if (virt_size == 0 || raw_size == 0) { | ||
1144 | TRACE_EXIT 0; | ||
1145 | } | ||
1146 | if (raw_size >= (1<<25)) { | ||
1147 | factor = raw_size/(virt_size>>7); | ||
1148 | } else { | ||
1149 | factor = (raw_size<<7)/virt_size; | ||
1150 | } | ||
1151 | segment = distance/(FT_SECTORS_PER_SEGMENT-FT_ECC_SECTORS); | ||
1152 | } | ||
1153 | TRACE(ft_t_noise, "factor: %d/%d", factor, 1<<7); | ||
1154 | TRACE_EXIT segment; | ||
1155 | } | ||
1156 | |||
1157 | static struct zft_cmpr_ops cmpr_ops = { | ||
1158 | zftc_write, | ||
1159 | zftc_read, | ||
1160 | zftc_seek, | ||
1161 | zftc_lock, | ||
1162 | zftc_reset, | ||
1163 | zftc_cleanup | ||
1164 | }; | ||
1165 | |||
1166 | int zft_compressor_init(void) | ||
1167 | { | ||
1168 | TRACE_FUN(ft_t_flow); | ||
1169 | |||
1170 | #ifdef MODULE | ||
1171 | printk(KERN_INFO "zftape compressor v1.00a 970514 for " FTAPE_VERSION "\n"); | ||
1172 | if (TRACE_LEVEL >= ft_t_info) { | ||
1173 | printk( | ||
1174 | KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n" | ||
1175 | KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n"); | ||
1176 | } | ||
1177 | #else /* !MODULE */ | ||
1178 | /* print a short no-nonsense boot message */ | ||
1179 | printk(KERN_INFO "zftape compressor v1.00a 970514\n"); | ||
1180 | printk(KERN_INFO "For use with " FTAPE_VERSION "\n"); | ||
1181 | #endif /* MODULE */ | ||
1182 | TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init); | ||
1183 | TRACE(ft_t_info, "installing compressor for zftape ..."); | ||
1184 | TRACE_CATCH(zft_cmpr_register(&cmpr_ops),); | ||
1185 | TRACE_EXIT 0; | ||
1186 | } | ||
1187 | |||
1188 | #ifdef MODULE | ||
1189 | |||
1190 | MODULE_AUTHOR( | ||
1191 | "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de"); | ||
1192 | MODULE_DESCRIPTION( | ||
1193 | "Compression routines for zftape. Uses the lzrw3 algorithm by Ross Williams"); | ||
1194 | MODULE_LICENSE("GPL"); | ||
1195 | |||
1196 | /* Called by modules package when installing the driver | ||
1197 | */ | ||
1198 | int init_module(void) | ||
1199 | { | ||
1200 | return zft_compressor_init(); | ||
1201 | } | ||
1202 | |||
1203 | #endif /* MODULE */ | ||
diff --git a/drivers/char/ftape/compressor/zftape-compress.h b/drivers/char/ftape/compressor/zftape-compress.h deleted file mode 100644 index f200741e33bf..000000000000 --- a/drivers/char/ftape/compressor/zftape-compress.h +++ /dev/null | |||
@@ -1,83 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_COMPRESS_H | ||
2 | #define _ZFTAPE_COMPRESS_H | ||
3 | /* | ||
4 | * Copyright (c) 1994-1997 Claus-Justus Heine | ||
5 | |||
6 | This program is free software; you can redistribute it and/or | ||
7 | modify it under the terms of the GNU General Public License as | ||
8 | published by the Free Software Foundation; either version 2, or (at | ||
9 | your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; see the file COPYING. If not, write to | ||
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
19 | USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/compressor/zftape-compress.h,v $ | ||
23 | * $Revision: 1.1 $ | ||
24 | * $Date: 1997/10/05 19:12:32 $ | ||
25 | * | ||
26 | * This file contains macros and definitions for zftape's | ||
27 | * builtin compression code. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include "../zftape/zftape-buffers.h" | ||
32 | #include "../zftape/zftape-vtbl.h" | ||
33 | #include "../compressor/lzrw3.h" | ||
34 | |||
35 | /* CMPR_WRK_MEM_SIZE gives the size of the compression wrk_mem */ | ||
36 | /* I got these out of lzrw3.c */ | ||
37 | #define U(X) ((__u32) X) | ||
38 | #define SIZE_P_BYTE (U(sizeof(__u8 *))) | ||
39 | #define ALIGNMENT_FUDGE (U(16)) | ||
40 | |||
41 | #define CMPR_WRK_MEM_SIZE (U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE) | ||
42 | |||
43 | /* the maximum number of bytes the size of the "compressed" data can | ||
44 | * exceed the uncompressed data. As it is quite useless to compress | ||
45 | * data twice it is sometimes the case that it is more efficient to | ||
46 | * copy a block of data but to feed it to the "compression" | ||
47 | * algorithm. In this case there are some flag bytes or the like | ||
48 | * proceding the "compressed" data. THAT MUST NOT BE THE CASE for the | ||
49 | * algorithm we use for this driver. Instead, the high bit 15 of | ||
50 | * compressed_size: | ||
51 | * | ||
52 | * compressed_size = ftape_compress() | ||
53 | * | ||
54 | * must be set in such a case. | ||
55 | * | ||
56 | * Nevertheless, it might also be as for lzrw3 that there is an | ||
57 | * "intermediate" overrun that exceeds the amount of the compressed | ||
58 | * data that is actually produced. During the algorithm we need in the | ||
59 | * worst case MAX_CMP_GROUP bytes more than the input-size. | ||
60 | */ | ||
61 | #define MAX_CMP_GROUP (2+16*2) /* from lzrw3.c */ | ||
62 | |||
63 | #define CMPR_OVERRUN MAX_CMP_GROUP /* during compression */ | ||
64 | |||
65 | /****************************************************/ | ||
66 | |||
67 | #define CMPR_BUFFER_SIZE (MAX_BLOCK_SIZE + CMPR_OVERRUN) | ||
68 | |||
69 | /* the compression map stores the byte offset compressed blocks within | ||
70 | * the current volume for catridges with format code 2,3 and 5 | ||
71 | * (and old versions of zftape) and the offset measured in kilobytes for | ||
72 | * format code 4 and 6. This gives us a possible max. size of a | ||
73 | * compressed volume of 1024*4GIG which should be enough. | ||
74 | */ | ||
75 | typedef __u32 CmprMap; | ||
76 | |||
77 | /* globals | ||
78 | */ | ||
79 | |||
80 | /* exported functions | ||
81 | */ | ||
82 | |||
83 | #endif /* _ZFTAPE_COMPRESS_H */ | ||
diff --git a/drivers/char/ftape/lowlevel/Makefile b/drivers/char/ftape/lowlevel/Makefile deleted file mode 100644 index febab07ba427..000000000000 --- a/drivers/char/ftape/lowlevel/Makefile +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 1996, 1997 Clau-Justus Heine. | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 2, or (at your option) | ||
7 | # any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program; see the file COPYING. If not, write to | ||
16 | # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | # | ||
18 | # $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/Makefile,v $ | ||
19 | # $Revision: 1.4 $ | ||
20 | # $Date: 1997/10/07 09:26:02 $ | ||
21 | # | ||
22 | # Makefile for the lowlevel part QIC-40/80/3010/3020 floppy-tape | ||
23 | # driver for Linux. | ||
24 | # | ||
25 | |||
26 | obj-$(CONFIG_FTAPE) += ftape.o | ||
27 | |||
28 | ftape-objs := ftape-init.o fdc-io.o fdc-isr.o \ | ||
29 | ftape-bsm.o ftape-ctl.o ftape-read.o ftape-rw.o \ | ||
30 | ftape-write.o ftape-io.o ftape-calibr.o ftape-ecc.o fc-10.o \ | ||
31 | ftape-buffer.o ftape-format.o ftape_syms.o | ||
32 | |||
33 | ifeq ($(CONFIG_FTAPE),y) | ||
34 | ftape-objs += ftape-setup.o | ||
35 | endif | ||
36 | |||
37 | ifndef CONFIG_FT_NO_TRACE_AT_ALL | ||
38 | ftape-objs += ftape-tracing.o | ||
39 | endif | ||
40 | |||
41 | ifeq ($(CONFIG_FT_PROC_FS),y) | ||
42 | ftape-objs += ftape-proc.o | ||
43 | endif | ||
diff --git a/drivers/char/ftape/lowlevel/fc-10.c b/drivers/char/ftape/lowlevel/fc-10.c deleted file mode 100644 index 9bc1cddade76..000000000000 --- a/drivers/char/ftape/lowlevel/fc-10.c +++ /dev/null | |||
@@ -1,175 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | |||
4 | Copyright (C) 1993,1994 Jon Tombs. | ||
5 | |||
6 | This program is distributed in the hope that it will be useful, | ||
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
9 | GNU General Public License for more details. | ||
10 | |||
11 | The entire guts of this program was written by dosemu, modified to | ||
12 | record reads and writes to the ports in the 0x180-0x188 address space, | ||
13 | while running the CMS program TAPE.EXE V2.0.5 supplied with the drive. | ||
14 | |||
15 | Modified to use an array of addresses and generally cleaned up (made | ||
16 | much shorter) 4 June 94, dosemu isn't that good at writing short code it | ||
17 | would seem :-). Made independent of 0x180, but I doubt it will work | ||
18 | at any other address. | ||
19 | |||
20 | Modified for distribution with ftape source. 21 June 94, SJL. | ||
21 | |||
22 | Modifications on 20 October 95, by Daniel Cohen (catman@wpi.edu): | ||
23 | Modified to support different DMA, IRQ, and IO Ports. Borland's | ||
24 | Turbo Debugger in virtual 8086 mode (TD386.EXE with hardware breakpoints | ||
25 | provided by the TDH386.SYS Device Driver) was used on the CMS program | ||
26 | TAPE V4.0.5. I set breakpoints on I/O to ports 0x180-0x187. Note that | ||
27 | CMS's program will not successfully configure the tape drive if you set | ||
28 | breakpoints on IO Reads, but you can set them on IO Writes without problems. | ||
29 | Known problems: | ||
30 | - You can not use DMA Channels 5 or 7. | ||
31 | |||
32 | Modification on 29 January 96, by Daniel Cohen (catman@wpi.edu): | ||
33 | Modified to only accept IRQs 3 - 7, or 9. Since we can only send a 3 bit | ||
34 | number representing the IRQ to the card, special handling is required when | ||
35 | IRQ 9 is selected. IRQ 2 and 9 are the same, and we should request IRQ 9 | ||
36 | from the kernel while telling the card to use IRQ 2. Thanks to Greg | ||
37 | Crider (gcrider@iclnet.org) for finding and locating this bug, as well as | ||
38 | testing the patch. | ||
39 | |||
40 | Modification on 11 December 96, by Claus Heine (claus@momo.math.rwth-aachen.de): | ||
41 | Modified a little to use variahle ft_fdc_base, ft_fdc_irq, ft_fdc_dma | ||
42 | instead of preprocessor symbols. Thus we can compile this into the module | ||
43 | or kernel and let the user specify the options as command line arguments. | ||
44 | |||
45 | * | ||
46 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.c,v $ | ||
47 | * $Revision: 1.2 $ | ||
48 | * $Date: 1997/10/05 19:18:04 $ | ||
49 | * | ||
50 | * This file contains code for the CMS FC-10/FC-20 card. | ||
51 | */ | ||
52 | |||
53 | #include <asm/io.h> | ||
54 | #include <linux/ftape.h> | ||
55 | #include "../lowlevel/ftape-tracing.h" | ||
56 | #include "../lowlevel/fdc-io.h" | ||
57 | #include "../lowlevel/fc-10.h" | ||
58 | |||
59 | static __u16 inbs_magic[] = { | ||
60 | 0x3, 0x3, 0x0, 0x4, 0x7, 0x2, 0x5, 0x3, 0x1, 0x4, | ||
61 | 0x3, 0x5, 0x2, 0x0, 0x3, 0x7, 0x4, 0x2, | ||
62 | 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 | ||
63 | }; | ||
64 | |||
65 | static __u16 fc10_ports[] = { | ||
66 | 0x180, 0x210, 0x2A0, 0x300, 0x330, 0x340, 0x370 | ||
67 | }; | ||
68 | |||
69 | int fc10_enable(void) | ||
70 | { | ||
71 | int i; | ||
72 | __u8 cardConfig = 0x00; | ||
73 | __u8 x; | ||
74 | TRACE_FUN(ft_t_flow); | ||
75 | |||
76 | /* This code will only work if the FC-10 (or FC-20) is set to | ||
77 | * use DMA channels 1, 2, or 3. DMA channels 5 and 7 seem to be | ||
78 | * initialized by the same command as channels 1 and 3, respectively. | ||
79 | */ | ||
80 | if (ft_fdc_dma > 3) { | ||
81 | TRACE_ABORT(0, ft_t_err, | ||
82 | "Error: The FC-10/20 must be set to use DMA channels 1, 2, or 3!"); | ||
83 | } | ||
84 | /* Only allow the FC-10/20 to use IRQ 3-7, or 9. Note that CMS's program | ||
85 | * only accepts IRQ's 2-7, but in linux, IRQ 2 is the same as IRQ 9. | ||
86 | */ | ||
87 | if (ft_fdc_irq < 3 || ft_fdc_irq == 8 || ft_fdc_irq > 9) { | ||
88 | TRACE_ABORT(0, ft_t_err, | ||
89 | "Error: The FC-10/20 must be set to use IRQ levels 3 - 7, or 9!\n" | ||
90 | KERN_INFO "Note: IRQ 9 is the same as IRQ 2"); | ||
91 | } | ||
92 | /* Clear state machine ??? | ||
93 | */ | ||
94 | for (i = 0; i < NR_ITEMS(inbs_magic); i++) { | ||
95 | inb(ft_fdc_base + inbs_magic[i]); | ||
96 | } | ||
97 | outb(0x0, ft_fdc_base); | ||
98 | |||
99 | x = inb(ft_fdc_base); | ||
100 | if (x == 0x13 || x == 0x93) { | ||
101 | for (i = 1; i < 8; i++) { | ||
102 | if (inb(ft_fdc_base + i) != x) { | ||
103 | TRACE_EXIT 0; | ||
104 | } | ||
105 | } | ||
106 | } else { | ||
107 | TRACE_EXIT 0; | ||
108 | } | ||
109 | |||
110 | outb(0x8, ft_fdc_base); | ||
111 | |||
112 | for (i = 0; i < 8; i++) { | ||
113 | if (inb(ft_fdc_base + i) != 0x0) { | ||
114 | TRACE_EXIT 0; | ||
115 | } | ||
116 | } | ||
117 | outb(0x10, ft_fdc_base); | ||
118 | |||
119 | for (i = 0; i < 8; i++) { | ||
120 | if (inb(ft_fdc_base + i) != 0xff) { | ||
121 | TRACE_EXIT 0; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* Okay, we found a FC-10 card ! ??? | ||
126 | */ | ||
127 | outb(0x0, fdc.ccr); | ||
128 | |||
129 | /* Clear state machine again ??? | ||
130 | */ | ||
131 | for (i = 0; i < NR_ITEMS(inbs_magic); i++) { | ||
132 | inb(ft_fdc_base + inbs_magic[i]); | ||
133 | } | ||
134 | /* Send io port */ | ||
135 | for (i = 0; i < NR_ITEMS(fc10_ports); i++) | ||
136 | if (ft_fdc_base == fc10_ports[i]) | ||
137 | cardConfig = i + 1; | ||
138 | if (cardConfig == 0) { | ||
139 | TRACE_EXIT 0; /* Invalid I/O Port */ | ||
140 | } | ||
141 | /* and IRQ - If using IRQ 9, tell the FC card it is actually IRQ 2 */ | ||
142 | if (ft_fdc_irq != 9) | ||
143 | cardConfig |= ft_fdc_irq << 3; | ||
144 | else | ||
145 | cardConfig |= 2 << 3; | ||
146 | |||
147 | /* and finally DMA Channel */ | ||
148 | cardConfig |= ft_fdc_dma << 6; | ||
149 | outb(cardConfig, ft_fdc_base); /* DMA [2 bits]/IRQ [3 bits]/BASE [3 bits] */ | ||
150 | |||
151 | /* Enable FC-10 ??? | ||
152 | */ | ||
153 | outb(0, fdc.ccr); | ||
154 | outb(0, fdc.dor2); | ||
155 | outb(FDC_DMA_MODE /* 8 */, fdc.dor); | ||
156 | outb(FDC_DMA_MODE /* 8 */, fdc.dor); | ||
157 | outb(1, fdc.dor2); | ||
158 | |||
159 | /************************************* | ||
160 | * | ||
161 | * cH: why the hell should this be necessary? This is done | ||
162 | * by fdc_reset()!!! | ||
163 | * | ||
164 | *************************************/ | ||
165 | /* Initialize fdc, select drive B: | ||
166 | */ | ||
167 | outb(FDC_DMA_MODE, fdc.dor); /* assert reset, dma & irq enabled */ | ||
168 | /* 0x08 */ | ||
169 | outb(FDC_DMA_MODE|FDC_RESET_NOT, fdc.dor); /* release reset */ | ||
170 | /* 0x08 | 0x04 = 0x0c */ | ||
171 | outb(FDC_DMA_MODE|FDC_RESET_NOT|FDC_MOTOR_1|FTAPE_SEL_B, fdc.dor); | ||
172 | /* 0x08 | 0x04 | 0x20 | 0x01 = 0x2d */ | ||
173 | /* select drive 1 */ /* why not drive 0 ???? */ | ||
174 | TRACE_EXIT (x == 0x93) ? 2 : 1; | ||
175 | } | ||
diff --git a/drivers/char/ftape/lowlevel/fc-10.h b/drivers/char/ftape/lowlevel/fc-10.h deleted file mode 100644 index da7b88bca889..000000000000 --- a/drivers/char/ftape/lowlevel/fc-10.h +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | #ifndef _FC_10_H | ||
2 | #define _FC_10_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1994-1996 Bas Laarhoven. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.h,v $ | ||
23 | * $Revision: 1.1 $ | ||
24 | * $Date: 1997/09/19 09:05:22 $ | ||
25 | * | ||
26 | * This file contains definitions for the FC-10 code | ||
27 | * of the QIC-40/80 floppy-tape driver for Linux. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * fc-10.c defined global vars. | ||
32 | */ | ||
33 | |||
34 | /* | ||
35 | * fc-10.c defined global functions. | ||
36 | */ | ||
37 | extern int fc10_enable(void); | ||
38 | |||
39 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c deleted file mode 100644 index bbcf918f056f..000000000000 --- a/drivers/char/ftape/lowlevel/fdc-io.c +++ /dev/null | |||
@@ -1,1349 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-io.c,v $ | ||
21 | * $Revision: 1.7.4.2 $ | ||
22 | * $Date: 1997/11/16 14:48:17 $ | ||
23 | * | ||
24 | * This file contains the low-level floppy disk interface code | ||
25 | * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for | ||
26 | * Linux. | ||
27 | */ | ||
28 | |||
29 | #include <linux/errno.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <asm/system.h> | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/dma.h> | ||
37 | #include <asm/irq.h> | ||
38 | |||
39 | #include <linux/ftape.h> | ||
40 | #include <linux/qic117.h> | ||
41 | #include "../lowlevel/ftape-tracing.h" | ||
42 | #include "../lowlevel/fdc-io.h" | ||
43 | #include "../lowlevel/fdc-isr.h" | ||
44 | #include "../lowlevel/ftape-io.h" | ||
45 | #include "../lowlevel/ftape-rw.h" | ||
46 | #include "../lowlevel/ftape-ctl.h" | ||
47 | #include "../lowlevel/ftape-calibr.h" | ||
48 | #include "../lowlevel/fc-10.h" | ||
49 | |||
50 | /* Global vars. | ||
51 | */ | ||
52 | static int ftape_motor; | ||
53 | volatile int ftape_current_cylinder = -1; | ||
54 | volatile fdc_mode_enum fdc_mode = fdc_idle; | ||
55 | fdc_config_info fdc; | ||
56 | DECLARE_WAIT_QUEUE_HEAD(ftape_wait_intr); | ||
57 | |||
58 | unsigned int ft_fdc_base = CONFIG_FT_FDC_BASE; | ||
59 | unsigned int ft_fdc_irq = CONFIG_FT_FDC_IRQ; | ||
60 | unsigned int ft_fdc_dma = CONFIG_FT_FDC_DMA; | ||
61 | unsigned int ft_fdc_threshold = CONFIG_FT_FDC_THR; /* bytes */ | ||
62 | unsigned int ft_fdc_rate_limit = CONFIG_FT_FDC_MAX_RATE; /* bits/sec */ | ||
63 | int ft_probe_fc10 = CONFIG_FT_PROBE_FC10; | ||
64 | int ft_mach2 = CONFIG_FT_MACH2; | ||
65 | |||
66 | /* Local vars. | ||
67 | */ | ||
68 | static spinlock_t fdc_io_lock; | ||
69 | static unsigned int fdc_calibr_count; | ||
70 | static unsigned int fdc_calibr_time; | ||
71 | static int fdc_status; | ||
72 | volatile __u8 fdc_head; /* FDC head from sector id */ | ||
73 | volatile __u8 fdc_cyl; /* FDC track from sector id */ | ||
74 | volatile __u8 fdc_sect; /* FDC sector from sector id */ | ||
75 | static int fdc_data_rate = 500; /* data rate (Kbps) */ | ||
76 | static int fdc_rate_code; /* data rate code (0 == 500 Kbps) */ | ||
77 | static int fdc_seek_rate = 2; /* step rate (msec) */ | ||
78 | static void (*do_ftape) (void); | ||
79 | static int fdc_fifo_state; /* original fifo setting - fifo enabled */ | ||
80 | static int fdc_fifo_thr; /* original fifo setting - threshold */ | ||
81 | static int fdc_lock_state; /* original lock setting - locked */ | ||
82 | static int fdc_fifo_locked; /* has fifo && lock set ? */ | ||
83 | static __u8 fdc_precomp; /* default precomp. value (nsec) */ | ||
84 | static __u8 fdc_prec_code; /* fdc precomp. select code */ | ||
85 | |||
86 | static char ftape_id[] = "ftape"; /* used by request irq and free irq */ | ||
87 | |||
88 | static int fdc_set_seek_rate(int seek_rate); | ||
89 | |||
90 | void fdc_catch_stray_interrupts(int count) | ||
91 | { | ||
92 | unsigned long flags; | ||
93 | |||
94 | spin_lock_irqsave(&fdc_io_lock, flags); | ||
95 | if (count == 0) { | ||
96 | ft_expected_stray_interrupts = 0; | ||
97 | } else { | ||
98 | ft_expected_stray_interrupts += count; | ||
99 | } | ||
100 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
101 | } | ||
102 | |||
103 | /* Wait during a timeout period for a given FDC status. | ||
104 | * If usecs == 0 then just test status, else wait at least for usecs. | ||
105 | * Returns -ETIME on timeout. Function must be calibrated first ! | ||
106 | */ | ||
107 | static int fdc_wait(unsigned int usecs, __u8 mask, __u8 state) | ||
108 | { | ||
109 | int count_1 = (fdc_calibr_count * usecs + | ||
110 | fdc_calibr_count - 1) / fdc_calibr_time; | ||
111 | |||
112 | do { | ||
113 | fdc_status = inb_p(fdc.msr); | ||
114 | if ((fdc_status & mask) == state) { | ||
115 | return 0; | ||
116 | } | ||
117 | } while (count_1-- >= 0); | ||
118 | return -ETIME; | ||
119 | } | ||
120 | |||
121 | int fdc_ready_wait(unsigned int usecs) | ||
122 | { | ||
123 | return fdc_wait(usecs, FDC_DATA_READY | FDC_BUSY, FDC_DATA_READY); | ||
124 | } | ||
125 | |||
126 | /* Why can't we just use udelay()? | ||
127 | */ | ||
128 | static void fdc_usec_wait(unsigned int usecs) | ||
129 | { | ||
130 | fdc_wait(usecs, 0, 1); /* will always timeout ! */ | ||
131 | } | ||
132 | |||
133 | static int fdc_ready_out_wait(unsigned int usecs) | ||
134 | { | ||
135 | fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ | ||
136 | return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY); | ||
137 | } | ||
138 | |||
139 | void fdc_wait_calibrate(void) | ||
140 | { | ||
141 | ftape_calibrate("fdc_wait", | ||
142 | fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time); | ||
143 | } | ||
144 | |||
145 | /* Wait for a (short) while for the FDC to become ready | ||
146 | * and transfer the next command byte. | ||
147 | * Return -ETIME on timeout on getting ready (depends on hardware!). | ||
148 | */ | ||
149 | static int fdc_write(const __u8 data) | ||
150 | { | ||
151 | fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ | ||
152 | if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) { | ||
153 | return -ETIME; | ||
154 | } else { | ||
155 | outb(data, fdc.fifo); | ||
156 | return 0; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /* Wait for a (short) while for the FDC to become ready | ||
161 | * and transfer the next result byte. | ||
162 | * Return -ETIME if timeout on getting ready (depends on hardware!). | ||
163 | */ | ||
164 | static int fdc_read(__u8 * data) | ||
165 | { | ||
166 | fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ | ||
167 | if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) { | ||
168 | return -ETIME; | ||
169 | } else { | ||
170 | *data = inb(fdc.fifo); | ||
171 | return 0; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | /* Output a cmd_len long command string to the FDC. | ||
176 | * The FDC should be ready to receive a new command or | ||
177 | * an error (EBUSY or ETIME) will occur. | ||
178 | */ | ||
179 | int fdc_command(const __u8 * cmd_data, int cmd_len) | ||
180 | { | ||
181 | int result = 0; | ||
182 | unsigned long flags; | ||
183 | int count = cmd_len; | ||
184 | int retry = 0; | ||
185 | #ifdef TESTING | ||
186 | static unsigned int last_time; | ||
187 | unsigned int time; | ||
188 | #endif | ||
189 | TRACE_FUN(ft_t_any); | ||
190 | |||
191 | fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ | ||
192 | spin_lock_irqsave(&fdc_io_lock, flags); | ||
193 | if (!in_interrupt()) | ||
194 | /* Yes, I know, too much comments inside this function | ||
195 | * ... | ||
196 | * | ||
197 | * Yet another bug in the original driver. All that | ||
198 | * havoc is caused by the fact that the isr() sends | ||
199 | * itself a command to the floppy tape driver (pause, | ||
200 | * micro step pause). Now, the problem is that | ||
201 | * commands are transmitted via the fdc_seek | ||
202 | * command. But: the fdc performs seeks in the | ||
203 | * background i.e. it doesn't signal busy while | ||
204 | * sending the step pulses to the drive. Therefore the | ||
205 | * non-interrupt level driver has no chance to tell | ||
206 | * whether the isr() just has issued a seek. Therefore | ||
207 | * we HAVE TO have a look at the ft_hide_interrupt | ||
208 | * flag: it signals the non-interrupt level part of | ||
209 | * the driver that it has to wait for the fdc until it | ||
210 | * has completet seeking. | ||
211 | * | ||
212 | * THIS WAS PRESUMABLY THE REASON FOR ALL THAT | ||
213 | * "fdc_read timeout" errors, I HOPE :-) | ||
214 | */ | ||
215 | if (ft_hide_interrupt) { | ||
216 | restore_flags(flags); | ||
217 | TRACE(ft_t_info, | ||
218 | "Waiting for the isr() completing fdc_seek()"); | ||
219 | if (fdc_interrupt_wait(2 * FT_SECOND) < 0) { | ||
220 | TRACE(ft_t_warn, | ||
221 | "Warning: timeout waiting for isr() seek to complete"); | ||
222 | } | ||
223 | if (ft_hide_interrupt || !ft_seek_completed) { | ||
224 | /* There cannot be another | ||
225 | * interrupt. The isr() only stops | ||
226 | * the tape and the next interrupt | ||
227 | * won't come until we have send our | ||
228 | * command to the drive. | ||
229 | */ | ||
230 | TRACE_ABORT(-EIO, ft_t_bug, | ||
231 | "BUG? isr() is still seeking?\n" | ||
232 | KERN_INFO "hide: %d\n" | ||
233 | KERN_INFO "seek: %d", | ||
234 | ft_hide_interrupt, | ||
235 | ft_seek_completed); | ||
236 | |||
237 | } | ||
238 | fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ | ||
239 | spin_lock_irqsave(&fdc_io_lock, flags); | ||
240 | } | ||
241 | fdc_status = inb(fdc.msr); | ||
242 | if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) { | ||
243 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
244 | TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready"); | ||
245 | } | ||
246 | fdc_mode = *cmd_data; /* used by isr */ | ||
247 | #ifdef TESTING | ||
248 | if (fdc_mode == FDC_SEEK) { | ||
249 | time = ftape_timediff(last_time, ftape_timestamp()); | ||
250 | if (time < 6000) { | ||
251 | TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d", | ||
252 | time); | ||
253 | } | ||
254 | } | ||
255 | #endif | ||
256 | if (!in_interrupt()) { | ||
257 | /* shouldn't be cleared if called from isr | ||
258 | */ | ||
259 | ft_interrupt_seen = 0; | ||
260 | } | ||
261 | while (count) { | ||
262 | result = fdc_write(*cmd_data); | ||
263 | if (result < 0) { | ||
264 | TRACE(ft_t_fdc_dma, | ||
265 | "fdc_mode = %02x, status = %02x at index %d", | ||
266 | (int) fdc_mode, (int) fdc_status, | ||
267 | cmd_len - count); | ||
268 | if (++retry <= 3) { | ||
269 | TRACE(ft_t_warn, "fdc_write timeout, retry"); | ||
270 | } else { | ||
271 | TRACE(ft_t_err, "fdc_write timeout, fatal"); | ||
272 | /* recover ??? */ | ||
273 | break; | ||
274 | } | ||
275 | } else { | ||
276 | --count; | ||
277 | ++cmd_data; | ||
278 | } | ||
279 | } | ||
280 | #ifdef TESTING | ||
281 | if (fdc_mode == FDC_SEEK) { | ||
282 | last_time = ftape_timestamp(); | ||
283 | } | ||
284 | #endif | ||
285 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
286 | TRACE_EXIT result; | ||
287 | } | ||
288 | |||
289 | /* Input a res_len long result string from the FDC. | ||
290 | * The FDC should be ready to send the result or an error | ||
291 | * (EBUSY or ETIME) will occur. | ||
292 | */ | ||
293 | int fdc_result(__u8 * res_data, int res_len) | ||
294 | { | ||
295 | int result = 0; | ||
296 | unsigned long flags; | ||
297 | int count = res_len; | ||
298 | int retry = 0; | ||
299 | TRACE_FUN(ft_t_any); | ||
300 | |||
301 | spin_lock_irqsave(&fdc_io_lock, flags); | ||
302 | fdc_status = inb(fdc.msr); | ||
303 | if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) { | ||
304 | TRACE(ft_t_err, "fdc not ready"); | ||
305 | result = -EBUSY; | ||
306 | } else while (count) { | ||
307 | if (!(fdc_status & FDC_BUSY)) { | ||
308 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
309 | TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase"); | ||
310 | } | ||
311 | result = fdc_read(res_data); | ||
312 | if (result < 0) { | ||
313 | TRACE(ft_t_fdc_dma, | ||
314 | "fdc_mode = %02x, status = %02x at index %d", | ||
315 | (int) fdc_mode, | ||
316 | (int) fdc_status, | ||
317 | res_len - count); | ||
318 | if (++retry <= 3) { | ||
319 | TRACE(ft_t_warn, "fdc_read timeout, retry"); | ||
320 | } else { | ||
321 | TRACE(ft_t_err, "fdc_read timeout, fatal"); | ||
322 | /* recover ??? */ | ||
323 | break; | ||
324 | ++retry; | ||
325 | } | ||
326 | } else { | ||
327 | --count; | ||
328 | ++res_data; | ||
329 | } | ||
330 | } | ||
331 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
332 | fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */ | ||
333 | TRACE_EXIT result; | ||
334 | } | ||
335 | |||
336 | /* Handle command and result phases for | ||
337 | * commands without data phase. | ||
338 | */ | ||
339 | static int fdc_issue_command(const __u8 * out_data, int out_count, | ||
340 | __u8 * in_data, int in_count) | ||
341 | { | ||
342 | TRACE_FUN(ft_t_any); | ||
343 | |||
344 | if (out_count > 0) { | ||
345 | TRACE_CATCH(fdc_command(out_data, out_count),); | ||
346 | } | ||
347 | /* will take 24 - 30 usec for fdc_sense_drive_status and | ||
348 | * fdc_sense_interrupt_status commands. | ||
349 | * 35 fails sometimes (5/9/93 SJL) | ||
350 | * On a loaded system it incidentally takes longer than | ||
351 | * this for the fdc to get ready ! ?????? WHY ?????? | ||
352 | * So until we know what's going on use a very long timeout. | ||
353 | */ | ||
354 | TRACE_CATCH(fdc_ready_out_wait(500 /* usec */),); | ||
355 | if (in_count > 0) { | ||
356 | TRACE_CATCH(fdc_result(in_data, in_count), | ||
357 | TRACE(ft_t_err, "result phase aborted")); | ||
358 | } | ||
359 | TRACE_EXIT 0; | ||
360 | } | ||
361 | |||
362 | /* Wait for FDC interrupt with timeout (in milliseconds). | ||
363 | * Signals are blocked so the wait will not be aborted. | ||
364 | * Note: interrupts must be enabled ! (23/05/93 SJL) | ||
365 | */ | ||
366 | int fdc_interrupt_wait(unsigned int time) | ||
367 | { | ||
368 | DECLARE_WAITQUEUE(wait,current); | ||
369 | sigset_t old_sigmask; | ||
370 | static int resetting; | ||
371 | long timeout; | ||
372 | |||
373 | TRACE_FUN(ft_t_fdc_dma); | ||
374 | |||
375 | if (waitqueue_active(&ftape_wait_intr)) { | ||
376 | TRACE_ABORT(-EIO, ft_t_err, "error: nested call"); | ||
377 | } | ||
378 | /* timeout time will be up to USPT microseconds too long ! */ | ||
379 | timeout = (1000 * time + FT_USPT - 1) / FT_USPT; | ||
380 | |||
381 | spin_lock_irq(¤t->sighand->siglock); | ||
382 | old_sigmask = current->blocked; | ||
383 | sigfillset(¤t->blocked); | ||
384 | recalc_sigpending(); | ||
385 | spin_unlock_irq(¤t->sighand->siglock); | ||
386 | |||
387 | set_current_state(TASK_INTERRUPTIBLE); | ||
388 | add_wait_queue(&ftape_wait_intr, &wait); | ||
389 | while (!ft_interrupt_seen && timeout) | ||
390 | timeout = schedule_timeout_interruptible(timeout); | ||
391 | |||
392 | spin_lock_irq(¤t->sighand->siglock); | ||
393 | current->blocked = old_sigmask; | ||
394 | recalc_sigpending(); | ||
395 | spin_unlock_irq(¤t->sighand->siglock); | ||
396 | |||
397 | remove_wait_queue(&ftape_wait_intr, &wait); | ||
398 | /* the following IS necessary. True: as well | ||
399 | * wake_up_interruptible() as the schedule() set TASK_RUNNING | ||
400 | * when they wakeup a task, BUT: it may very well be that | ||
401 | * ft_interrupt_seen is already set to 1 when we enter here | ||
402 | * in which case schedule() gets never called, and | ||
403 | * TASK_RUNNING never set. This has the funny effect that we | ||
404 | * execute all the code until we leave kernel space, but then | ||
405 | * the task is stopped (a task CANNOT be preempted while in | ||
406 | * kernel mode. Sending a pair of SIGSTOP/SIGCONT to the | ||
407 | * tasks wakes it up again. Funny! :-) | ||
408 | */ | ||
409 | current->state = TASK_RUNNING; | ||
410 | if (ft_interrupt_seen) { /* woken up by interrupt */ | ||
411 | ft_interrupt_seen = 0; | ||
412 | TRACE_EXIT 0; | ||
413 | } | ||
414 | /* Original comment: | ||
415 | * In first instance, next statement seems unnecessary since | ||
416 | * it will be cleared in fdc_command. However, a small part of | ||
417 | * the software seems to rely on this being cleared here | ||
418 | * (ftape_close might fail) so stick to it until things get fixed ! | ||
419 | */ | ||
420 | /* My deeply sought of knowledge: | ||
421 | * Behold NO! It is obvious. fdc_reset() doesn't call fdc_command() | ||
422 | * but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to | ||
423 | * be reset here. | ||
424 | */ | ||
425 | ft_interrupt_seen = 0; /* clear for next call */ | ||
426 | if (!resetting) { | ||
427 | resetting = 1; /* break infinite recursion if reset fails */ | ||
428 | TRACE(ft_t_any, "cleanup reset"); | ||
429 | fdc_reset(); | ||
430 | resetting = 0; | ||
431 | } | ||
432 | TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME; | ||
433 | } | ||
434 | |||
435 | /* Start/stop drive motor. Enable DMA mode. | ||
436 | */ | ||
437 | void fdc_motor(int motor) | ||
438 | { | ||
439 | int unit = ft_drive_sel; | ||
440 | int data = unit | FDC_RESET_NOT | FDC_DMA_MODE; | ||
441 | TRACE_FUN(ft_t_any); | ||
442 | |||
443 | ftape_motor = motor; | ||
444 | if (ftape_motor) { | ||
445 | data |= FDC_MOTOR_0 << unit; | ||
446 | TRACE(ft_t_noise, "turning motor %d on", unit); | ||
447 | } else { | ||
448 | TRACE(ft_t_noise, "turning motor %d off", unit); | ||
449 | } | ||
450 | if (ft_mach2) { | ||
451 | outb_p(data, fdc.dor2); | ||
452 | } else { | ||
453 | outb_p(data, fdc.dor); | ||
454 | } | ||
455 | ftape_sleep(10 * FT_MILLISECOND); | ||
456 | TRACE_EXIT; | ||
457 | } | ||
458 | |||
459 | static void fdc_update_dsr(void) | ||
460 | { | ||
461 | TRACE_FUN(ft_t_any); | ||
462 | |||
463 | TRACE(ft_t_flow, "rate = %d Kbps, precomp = %d ns", | ||
464 | fdc_data_rate, fdc_precomp); | ||
465 | if (fdc.type >= i82077) { | ||
466 | outb_p((fdc_rate_code & 0x03) | fdc_prec_code, fdc.dsr); | ||
467 | } else { | ||
468 | outb_p(fdc_rate_code & 0x03, fdc.ccr); | ||
469 | } | ||
470 | TRACE_EXIT; | ||
471 | } | ||
472 | |||
473 | void fdc_set_write_precomp(int precomp) | ||
474 | { | ||
475 | TRACE_FUN(ft_t_any); | ||
476 | |||
477 | TRACE(ft_t_noise, "New precomp: %d nsec", precomp); | ||
478 | fdc_precomp = precomp; | ||
479 | /* write precompensation can be set in multiples of 41.67 nsec. | ||
480 | * round the parameter to the nearest multiple and convert it | ||
481 | * into a fdc setting. Note that 0 means default to the fdc, | ||
482 | * 7 is used instead of that. | ||
483 | */ | ||
484 | fdc_prec_code = ((fdc_precomp + 21) / 42) << 2; | ||
485 | if (fdc_prec_code == 0 || fdc_prec_code > (6 << 2)) { | ||
486 | fdc_prec_code = 7 << 2; | ||
487 | } | ||
488 | fdc_update_dsr(); | ||
489 | TRACE_EXIT; | ||
490 | } | ||
491 | |||
492 | /* Reprogram the 82078 registers to use Data Rate Table 1 on all drives. | ||
493 | */ | ||
494 | static void fdc_set_drive_specs(void) | ||
495 | { | ||
496 | __u8 cmd[] = { FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0}; | ||
497 | int result; | ||
498 | TRACE_FUN(ft_t_any); | ||
499 | |||
500 | TRACE(ft_t_flow, "Setting of drive specs called"); | ||
501 | if (fdc.type >= i82078_1) { | ||
502 | cmd[1] = (0 << 5) | (2 << 2); | ||
503 | cmd[2] = (1 << 5) | (2 << 2); | ||
504 | cmd[3] = (2 << 5) | (2 << 2); | ||
505 | cmd[4] = (3 << 5) | (2 << 2); | ||
506 | result = fdc_command(cmd, NR_ITEMS(cmd)); | ||
507 | if (result < 0) { | ||
508 | TRACE(ft_t_err, "Setting of drive specs failed"); | ||
509 | } | ||
510 | } | ||
511 | TRACE_EXIT; | ||
512 | } | ||
513 | |||
514 | /* Select clock for fdc, must correspond with tape drive setting ! | ||
515 | * This also influences the fdc timing so we must adjust some values. | ||
516 | */ | ||
517 | int fdc_set_data_rate(int rate) | ||
518 | { | ||
519 | int bad_rate = 0; | ||
520 | TRACE_FUN(ft_t_any); | ||
521 | |||
522 | /* Select clock for fdc, must correspond with tape drive setting ! | ||
523 | * This also influences the fdc timing so we must adjust some values. | ||
524 | */ | ||
525 | TRACE(ft_t_fdc_dma, "new rate = %d", rate); | ||
526 | switch (rate) { | ||
527 | case 250: | ||
528 | fdc_rate_code = fdc_data_rate_250; | ||
529 | break; | ||
530 | case 500: | ||
531 | fdc_rate_code = fdc_data_rate_500; | ||
532 | break; | ||
533 | case 1000: | ||
534 | if (fdc.type < i82077) { | ||
535 | bad_rate = 1; | ||
536 | } else { | ||
537 | fdc_rate_code = fdc_data_rate_1000; | ||
538 | } | ||
539 | break; | ||
540 | case 2000: | ||
541 | if (fdc.type < i82078_1) { | ||
542 | bad_rate = 1; | ||
543 | } else { | ||
544 | fdc_rate_code = fdc_data_rate_2000; | ||
545 | } | ||
546 | break; | ||
547 | default: | ||
548 | bad_rate = 1; | ||
549 | } | ||
550 | if (bad_rate) { | ||
551 | TRACE_ABORT(-EIO, | ||
552 | ft_t_fdc_dma, "%d is not a valid data rate", rate); | ||
553 | } | ||
554 | fdc_data_rate = rate; | ||
555 | fdc_update_dsr(); | ||
556 | fdc_set_seek_rate(fdc_seek_rate); /* clock changed! */ | ||
557 | ftape_udelay(1000); | ||
558 | TRACE_EXIT 0; | ||
559 | } | ||
560 | |||
561 | /* keep the unit select if keep_select is != 0, | ||
562 | */ | ||
563 | static void fdc_dor_reset(int keep_select) | ||
564 | { | ||
565 | __u8 fdc_ctl = ft_drive_sel; | ||
566 | |||
567 | if (keep_select != 0) { | ||
568 | fdc_ctl |= FDC_DMA_MODE; | ||
569 | if (ftape_motor) { | ||
570 | fdc_ctl |= FDC_MOTOR_0 << ft_drive_sel; | ||
571 | } | ||
572 | } | ||
573 | ftape_udelay(10); /* ??? but seems to be necessary */ | ||
574 | if (ft_mach2) { | ||
575 | outb_p(fdc_ctl & 0x0f, fdc.dor); | ||
576 | outb_p(fdc_ctl, fdc.dor2); | ||
577 | } else { | ||
578 | outb_p(fdc_ctl, fdc.dor); | ||
579 | } | ||
580 | fdc_usec_wait(10); /* delay >= 14 fdc clocks */ | ||
581 | if (keep_select == 0) { | ||
582 | fdc_ctl = 0; | ||
583 | } | ||
584 | fdc_ctl |= FDC_RESET_NOT; | ||
585 | if (ft_mach2) { | ||
586 | outb_p(fdc_ctl & 0x0f, fdc.dor); | ||
587 | outb_p(fdc_ctl, fdc.dor2); | ||
588 | } else { | ||
589 | outb_p(fdc_ctl, fdc.dor); | ||
590 | } | ||
591 | } | ||
592 | |||
593 | /* Reset the floppy disk controller. Leave the ftape_unit selected. | ||
594 | */ | ||
595 | void fdc_reset(void) | ||
596 | { | ||
597 | int st0; | ||
598 | int i; | ||
599 | int dummy; | ||
600 | unsigned long flags; | ||
601 | TRACE_FUN(ft_t_any); | ||
602 | |||
603 | spin_lock_irqsave(&fdc_io_lock, flags); | ||
604 | |||
605 | fdc_dor_reset(1); /* keep unit selected */ | ||
606 | |||
607 | fdc_mode = fdc_idle; | ||
608 | |||
609 | /* maybe the spin_lock_irq* pair is not necessary, BUT: | ||
610 | * the following line MUST be here. Otherwise fdc_interrupt_wait() | ||
611 | * won't wait. Note that fdc_reset() is called from | ||
612 | * ftape_dumb_stop() when the fdc is busy transferring data. In this | ||
613 | * case fdc_isr() MOST PROBABLY sets ft_interrupt_seen, and tries | ||
614 | * to get the result bytes from the fdc etc. CLASH. | ||
615 | */ | ||
616 | ft_interrupt_seen = 0; | ||
617 | |||
618 | /* Program data rate | ||
619 | */ | ||
620 | fdc_update_dsr(); /* restore data rate and precomp */ | ||
621 | |||
622 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
623 | |||
624 | /* | ||
625 | * Wait for first polling cycle to complete | ||
626 | */ | ||
627 | if (fdc_interrupt_wait(1 * FT_SECOND) < 0) { | ||
628 | TRACE(ft_t_err, "no drive polling interrupt!"); | ||
629 | } else { /* clear all disk-changed statuses */ | ||
630 | for (i = 0; i < 4; ++i) { | ||
631 | if(fdc_sense_interrupt_status(&st0, &dummy) != 0) { | ||
632 | TRACE(ft_t_err, "sense failed for %d", i); | ||
633 | } | ||
634 | if (i == ft_drive_sel) { | ||
635 | ftape_current_cylinder = dummy; | ||
636 | } | ||
637 | } | ||
638 | TRACE(ft_t_noise, "drive polling completed"); | ||
639 | } | ||
640 | /* | ||
641 | * SPECIFY COMMAND | ||
642 | */ | ||
643 | fdc_set_seek_rate(fdc_seek_rate); | ||
644 | /* | ||
645 | * DRIVE SPECIFICATION COMMAND (if fdc type known) | ||
646 | */ | ||
647 | if (fdc.type >= i82078_1) { | ||
648 | fdc_set_drive_specs(); | ||
649 | } | ||
650 | TRACE_EXIT; | ||
651 | } | ||
652 | |||
653 | #if !defined(CLK_48MHZ) | ||
654 | # define CLK_48MHZ 1 | ||
655 | #endif | ||
656 | |||
657 | /* When we're done, put the fdc into reset mode so that the regular | ||
658 | * floppy disk driver will figure out that something is wrong and | ||
659 | * initialize the controller the way it wants. | ||
660 | */ | ||
661 | void fdc_disable(void) | ||
662 | { | ||
663 | __u8 cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00}; | ||
664 | __u8 cmd2[] = {FDC_LOCK}; | ||
665 | __u8 cmd3[] = {FDC_UNLOCK}; | ||
666 | __u8 stat[1]; | ||
667 | TRACE_FUN(ft_t_flow); | ||
668 | |||
669 | if (!fdc_fifo_locked) { | ||
670 | fdc_reset(); | ||
671 | TRACE_EXIT; | ||
672 | } | ||
673 | if (fdc_issue_command(cmd3, 1, stat, 1) < 0 || stat[0] != 0x00) { | ||
674 | fdc_dor_reset(0); | ||
675 | TRACE_ABORT(/**/, ft_t_bug, | ||
676 | "couldn't unlock fifo, configuration remains changed"); | ||
677 | } | ||
678 | fdc_fifo_locked = 0; | ||
679 | if (CLK_48MHZ && fdc.type >= i82078) { | ||
680 | cmd1[0] |= FDC_CLK48_BIT; | ||
681 | } | ||
682 | cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1); | ||
683 | if (fdc_command(cmd1, NR_ITEMS(cmd1)) < 0) { | ||
684 | fdc_dor_reset(0); | ||
685 | TRACE_ABORT(/**/, ft_t_bug, | ||
686 | "couldn't reconfigure fifo to old state"); | ||
687 | } | ||
688 | if (fdc_lock_state && | ||
689 | fdc_issue_command(cmd2, 1, stat, 1) < 0) { | ||
690 | fdc_dor_reset(0); | ||
691 | TRACE_ABORT(/**/, ft_t_bug, "couldn't lock old state again"); | ||
692 | } | ||
693 | TRACE(ft_t_noise, "fifo restored: %sabled, thr. %d, %slocked", | ||
694 | fdc_fifo_state ? "en" : "dis", | ||
695 | fdc_fifo_thr, (fdc_lock_state) ? "" : "not "); | ||
696 | fdc_dor_reset(0); | ||
697 | TRACE_EXIT; | ||
698 | } | ||
699 | |||
700 | /* Specify FDC seek-rate (milliseconds) | ||
701 | */ | ||
702 | static int fdc_set_seek_rate(int seek_rate) | ||
703 | { | ||
704 | /* set step rate, dma mode, and minimal head load and unload times | ||
705 | */ | ||
706 | __u8 in[3] = { FDC_SPECIFY, 1, (1 << 1)}; | ||
707 | |||
708 | fdc_seek_rate = seek_rate; | ||
709 | in[1] |= (16 - (fdc_data_rate * fdc_seek_rate) / 500) << 4; | ||
710 | |||
711 | return fdc_command(in, 3); | ||
712 | } | ||
713 | |||
714 | /* Sense drive status: get unit's drive status (ST3) | ||
715 | */ | ||
716 | int fdc_sense_drive_status(int *st3) | ||
717 | { | ||
718 | __u8 out[2]; | ||
719 | __u8 in[1]; | ||
720 | TRACE_FUN(ft_t_any); | ||
721 | |||
722 | out[0] = FDC_SENSED; | ||
723 | out[1] = ft_drive_sel; | ||
724 | TRACE_CATCH(fdc_issue_command(out, 2, in, 1),); | ||
725 | *st3 = in[0]; | ||
726 | TRACE_EXIT 0; | ||
727 | } | ||
728 | |||
729 | /* Sense Interrupt Status command: | ||
730 | * should be issued at the end of each seek. | ||
731 | * get ST0 and current cylinder. | ||
732 | */ | ||
733 | int fdc_sense_interrupt_status(int *st0, int *current_cylinder) | ||
734 | { | ||
735 | __u8 out[1]; | ||
736 | __u8 in[2]; | ||
737 | TRACE_FUN(ft_t_any); | ||
738 | |||
739 | out[0] = FDC_SENSEI; | ||
740 | TRACE_CATCH(fdc_issue_command(out, 1, in, 2),); | ||
741 | *st0 = in[0]; | ||
742 | *current_cylinder = in[1]; | ||
743 | TRACE_EXIT 0; | ||
744 | } | ||
745 | |||
746 | /* step to track | ||
747 | */ | ||
748 | int fdc_seek(int track) | ||
749 | { | ||
750 | __u8 out[3]; | ||
751 | int st0, pcn; | ||
752 | #ifdef TESTING | ||
753 | unsigned int time; | ||
754 | #endif | ||
755 | TRACE_FUN(ft_t_any); | ||
756 | |||
757 | out[0] = FDC_SEEK; | ||
758 | out[1] = ft_drive_sel; | ||
759 | out[2] = track; | ||
760 | #ifdef TESTING | ||
761 | time = ftape_timestamp(); | ||
762 | #endif | ||
763 | /* We really need this command to work ! | ||
764 | */ | ||
765 | ft_seek_completed = 0; | ||
766 | TRACE_CATCH(fdc_command(out, 3), | ||
767 | fdc_reset(); | ||
768 | TRACE(ft_t_noise, "destination was: %d, resetting FDC...", | ||
769 | track)); | ||
770 | /* Handle interrupts until ft_seek_completed or timeout. | ||
771 | */ | ||
772 | for (;;) { | ||
773 | TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),); | ||
774 | if (ft_seek_completed) { | ||
775 | TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),); | ||
776 | if ((st0 & ST0_SEEK_END) == 0) { | ||
777 | TRACE_ABORT(-EIO, ft_t_err, | ||
778 | "no seek-end after seek completion !??"); | ||
779 | } | ||
780 | break; | ||
781 | } | ||
782 | } | ||
783 | #ifdef TESTING | ||
784 | time = ftape_timediff(time, ftape_timestamp()) / abs(track - ftape_current_cylinder); | ||
785 | if ((time < 900 || time > 3100) && abs(track - ftape_current_cylinder) > 5) { | ||
786 | TRACE(ft_t_warn, "Wrong FDC STEP interval: %d usecs (%d)", | ||
787 | time, track - ftape_current_cylinder); | ||
788 | } | ||
789 | #endif | ||
790 | /* Verify whether we issued the right tape command. | ||
791 | */ | ||
792 | /* Verify that we seek to the proper track. */ | ||
793 | if (pcn != track) { | ||
794 | TRACE_ABORT(-EIO, ft_t_err, "bad seek.."); | ||
795 | } | ||
796 | ftape_current_cylinder = track; | ||
797 | TRACE_EXIT 0; | ||
798 | } | ||
799 | |||
800 | static int perpend_mode; /* set if fdc is in perpendicular mode */ | ||
801 | |||
802 | static int perpend_off(void) | ||
803 | { | ||
804 | __u8 perpend[] = {FDC_PERPEND, 0x00}; | ||
805 | TRACE_FUN(ft_t_any); | ||
806 | |||
807 | if (perpend_mode) { | ||
808 | /* Turn off perpendicular mode */ | ||
809 | perpend[1] = 0x80; | ||
810 | TRACE_CATCH(fdc_command(perpend, 2), | ||
811 | TRACE(ft_t_err,"Perpendicular mode exit failed!")); | ||
812 | perpend_mode = 0; | ||
813 | } | ||
814 | TRACE_EXIT 0; | ||
815 | } | ||
816 | |||
817 | static int handle_perpend(int segment_id) | ||
818 | { | ||
819 | __u8 perpend[] = {FDC_PERPEND, 0x00}; | ||
820 | TRACE_FUN(ft_t_any); | ||
821 | |||
822 | /* When writing QIC-3020 tapes, turn on perpendicular mode | ||
823 | * if tape is moving in forward direction (even tracks). | ||
824 | */ | ||
825 | if (ft_qic_std == QIC_TAPE_QIC3020 && | ||
826 | ((segment_id / ft_segments_per_track) & 1) == 0) { | ||
827 | /* FIXME: some i82077 seem to support perpendicular mode as | ||
828 | * well. | ||
829 | */ | ||
830 | #if 0 | ||
831 | if (fdc.type < i82077AA) {} | ||
832 | #else | ||
833 | if (fdc.type < i82077 && ft_data_rate < 1000) { | ||
834 | #endif | ||
835 | /* fdc does not support perpendicular mode: complain | ||
836 | */ | ||
837 | TRACE_ABORT(-EIO, ft_t_err, | ||
838 | "Your FDC does not support QIC-3020."); | ||
839 | } | ||
840 | perpend[1] = 0x03 /* 0x83 + (0x4 << ft_drive_sel) */ ; | ||
841 | TRACE_CATCH(fdc_command(perpend, 2), | ||
842 | TRACE(ft_t_err,"Perpendicular mode entry failed!")); | ||
843 | TRACE(ft_t_flow, "Perpendicular mode set"); | ||
844 | perpend_mode = 1; | ||
845 | TRACE_EXIT 0; | ||
846 | } | ||
847 | TRACE_EXIT perpend_off(); | ||
848 | } | ||
849 | |||
850 | static inline void fdc_setup_dma(char mode, | ||
851 | volatile void *addr, unsigned int count) | ||
852 | { | ||
853 | /* Program the DMA controller. | ||
854 | */ | ||
855 | disable_dma(fdc.dma); | ||
856 | clear_dma_ff(fdc.dma); | ||
857 | set_dma_mode(fdc.dma, mode); | ||
858 | set_dma_addr(fdc.dma, virt_to_bus((void*)addr)); | ||
859 | set_dma_count(fdc.dma, count); | ||
860 | enable_dma(fdc.dma); | ||
861 | } | ||
862 | |||
863 | /* Setup fdc and dma for formatting the next segment | ||
864 | */ | ||
865 | int fdc_setup_formatting(buffer_struct * buff) | ||
866 | { | ||
867 | unsigned long flags; | ||
868 | __u8 out[6] = { | ||
869 | FDC_FORMAT, 0x00, 3, 4 * FT_SECTORS_PER_SEGMENT, 0x00, 0x6b | ||
870 | }; | ||
871 | TRACE_FUN(ft_t_any); | ||
872 | |||
873 | TRACE_CATCH(handle_perpend(buff->segment_id),); | ||
874 | /* Program the DMA controller. | ||
875 | */ | ||
876 | TRACE(ft_t_fdc_dma, | ||
877 | "phys. addr. = %lx", virt_to_bus((void*) buff->ptr)); | ||
878 | spin_lock_irqsave(&fdc_io_lock, flags); | ||
879 | fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4); | ||
880 | /* Issue FDC command to start reading/writing. | ||
881 | */ | ||
882 | out[1] = ft_drive_sel; | ||
883 | out[4] = buff->gap3; | ||
884 | TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)), | ||
885 | restore_flags(flags); fdc_mode = fdc_idle); | ||
886 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
887 | TRACE_EXIT 0; | ||
888 | } | ||
889 | |||
890 | |||
891 | /* Setup Floppy Disk Controller and DMA to read or write the next cluster | ||
892 | * of good sectors from or to the current segment. | ||
893 | */ | ||
894 | int fdc_setup_read_write(buffer_struct * buff, __u8 operation) | ||
895 | { | ||
896 | unsigned long flags; | ||
897 | __u8 out[9]; | ||
898 | int dma_mode; | ||
899 | TRACE_FUN(ft_t_any); | ||
900 | |||
901 | switch(operation) { | ||
902 | case FDC_VERIFY: | ||
903 | if (fdc.type < i82077) { | ||
904 | operation = FDC_READ; | ||
905 | } | ||
906 | case FDC_READ: | ||
907 | case FDC_READ_DELETED: | ||
908 | dma_mode = DMA_MODE_READ; | ||
909 | TRACE(ft_t_fdc_dma, "xfer %d sectors to 0x%p", | ||
910 | buff->sector_count, buff->ptr); | ||
911 | TRACE_CATCH(perpend_off(),); | ||
912 | break; | ||
913 | case FDC_WRITE_DELETED: | ||
914 | TRACE(ft_t_noise, "deleting segment %d", buff->segment_id); | ||
915 | case FDC_WRITE: | ||
916 | dma_mode = DMA_MODE_WRITE; | ||
917 | /* When writing QIC-3020 tapes, turn on perpendicular mode | ||
918 | * if tape is moving in forward direction (even tracks). | ||
919 | */ | ||
920 | TRACE_CATCH(handle_perpend(buff->segment_id),); | ||
921 | TRACE(ft_t_fdc_dma, "xfer %d sectors from 0x%p", | ||
922 | buff->sector_count, buff->ptr); | ||
923 | break; | ||
924 | default: | ||
925 | TRACE_ABORT(-EIO, | ||
926 | ft_t_bug, "bug: invalid operation parameter"); | ||
927 | } | ||
928 | TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr)); | ||
929 | spin_lock_irqsave(&fdc_io_lock, flags); | ||
930 | if (operation != FDC_VERIFY) { | ||
931 | fdc_setup_dma(dma_mode, buff->ptr, | ||
932 | FT_SECTOR_SIZE * buff->sector_count); | ||
933 | } | ||
934 | /* Issue FDC command to start reading/writing. | ||
935 | */ | ||
936 | out[0] = operation; | ||
937 | out[1] = ft_drive_sel; | ||
938 | out[2] = buff->cyl; | ||
939 | out[3] = buff->head; | ||
940 | out[4] = buff->sect + buff->sector_offset; | ||
941 | out[5] = 3; /* Sector size of 1K. */ | ||
942 | out[6] = out[4] + buff->sector_count - 1; /* last sector */ | ||
943 | out[7] = 109; /* Gap length. */ | ||
944 | out[8] = 0xff; /* No limit to transfer size. */ | ||
945 | TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x", | ||
946 | out[2], out[3], out[4], out[6] - out[4] + 1); | ||
947 | spin_unlock_irqrestore(&fdc_io_lock, flags); | ||
948 | TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle); | ||
949 | TRACE_EXIT 0; | ||
950 | } | ||
951 | |||
952 | int fdc_fifo_threshold(__u8 threshold, | ||
953 | int *fifo_state, int *lock_state, int *fifo_thr) | ||
954 | { | ||
955 | const __u8 cmd0[] = {FDC_DUMPREGS}; | ||
956 | __u8 cmd1[] = {FDC_CONFIGURE, 0, (0x0f & (threshold - 1)), 0}; | ||
957 | const __u8 cmd2[] = {FDC_LOCK}; | ||
958 | const __u8 cmd3[] = {FDC_UNLOCK}; | ||
959 | __u8 reg[10]; | ||
960 | __u8 stat; | ||
961 | int i; | ||
962 | int result; | ||
963 | TRACE_FUN(ft_t_any); | ||
964 | |||
965 | if (CLK_48MHZ && fdc.type >= i82078) { | ||
966 | cmd1[0] |= FDC_CLK48_BIT; | ||
967 | } | ||
968 | /* Dump fdc internal registers for examination | ||
969 | */ | ||
970 | TRACE_CATCH(fdc_command(cmd0, NR_ITEMS(cmd0)), | ||
971 | TRACE(ft_t_warn, "dumpreg cmd failed, fifo unchanged")); | ||
972 | /* Now read fdc internal registers from fifo | ||
973 | */ | ||
974 | for (i = 0; i < (int)NR_ITEMS(reg); ++i) { | ||
975 | fdc_read(®[i]); | ||
976 | TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]); | ||
977 | } | ||
978 | if (fifo_state && lock_state && fifo_thr) { | ||
979 | *fifo_state = (reg[8] & 0x20) == 0; | ||
980 | *lock_state = reg[7] & 0x80; | ||
981 | *fifo_thr = 1 + (reg[8] & 0x0f); | ||
982 | } | ||
983 | TRACE(ft_t_noise, | ||
984 | "original fifo state: %sabled, threshold %d, %slocked", | ||
985 | ((reg[8] & 0x20) == 0) ? "en" : "dis", | ||
986 | 1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not "); | ||
987 | /* If fdc is already locked, unlock it first ! */ | ||
988 | if (reg[7] & 0x80) { | ||
989 | fdc_ready_wait(100); | ||
990 | TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1), | ||
991 | TRACE(ft_t_bug, "FDC unlock command failed, " | ||
992 | "configuration unchanged")); | ||
993 | } | ||
994 | fdc_fifo_locked = 0; | ||
995 | /* Enable fifo and set threshold at xx bytes to allow a | ||
996 | * reasonably large latency and reduce number of dma bursts. | ||
997 | */ | ||
998 | fdc_ready_wait(100); | ||
999 | if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) { | ||
1000 | TRACE(ft_t_bug, "configure cmd failed, fifo unchanged"); | ||
1001 | } | ||
1002 | /* Now lock configuration so reset will not change it | ||
1003 | */ | ||
1004 | if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 || | ||
1005 | stat != 0x10) { | ||
1006 | TRACE_ABORT(-EIO, ft_t_bug, | ||
1007 | "FDC lock command failed, stat = 0x%02x", stat); | ||
1008 | } | ||
1009 | fdc_fifo_locked = 1; | ||
1010 | TRACE_EXIT result; | ||
1011 | } | ||
1012 | |||
1013 | static int fdc_fifo_enable(void) | ||
1014 | { | ||
1015 | TRACE_FUN(ft_t_any); | ||
1016 | |||
1017 | if (fdc_fifo_locked) { | ||
1018 | TRACE_ABORT(0, ft_t_warn, "Fifo not enabled because locked"); | ||
1019 | } | ||
1020 | TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */, | ||
1021 | &fdc_fifo_state, | ||
1022 | &fdc_lock_state, | ||
1023 | &fdc_fifo_thr),); | ||
1024 | TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */, | ||
1025 | NULL, NULL, NULL),); | ||
1026 | TRACE_EXIT 0; | ||
1027 | } | ||
1028 | |||
1029 | /* Determine fd controller type | ||
1030 | */ | ||
1031 | static __u8 fdc_save_state[2]; | ||
1032 | |||
1033 | static int fdc_probe(void) | ||
1034 | { | ||
1035 | __u8 cmd[1]; | ||
1036 | __u8 stat[16]; /* must be able to hold dumpregs & save results */ | ||
1037 | int i; | ||
1038 | TRACE_FUN(ft_t_any); | ||
1039 | |||
1040 | /* Try to find out what kind of fd controller we have to deal with | ||
1041 | * Scheme borrowed from floppy driver: | ||
1042 | * first try if FDC_DUMPREGS command works | ||
1043 | * (this indicates that we have a 82072 or better) | ||
1044 | * then try the FDC_VERSION command (82072 doesn't support this) | ||
1045 | * then try the FDC_UNLOCK command (some older 82077's don't support this) | ||
1046 | * then try the FDC_PARTID command (82078's support this) | ||
1047 | */ | ||
1048 | cmd[0] = FDC_DUMPREGS; | ||
1049 | if (fdc_issue_command(cmd, 1, stat, 1) != 0) { | ||
1050 | TRACE_ABORT(no_fdc, ft_t_bug, "No FDC found"); | ||
1051 | } | ||
1052 | if (stat[0] == 0x80) { | ||
1053 | /* invalid command: must be pre 82072 */ | ||
1054 | TRACE_ABORT(i8272, | ||
1055 | ft_t_warn, "Type 8272A/765A compatible FDC found"); | ||
1056 | } | ||
1057 | fdc_result(&stat[1], 9); | ||
1058 | fdc_save_state[0] = stat[7]; | ||
1059 | fdc_save_state[1] = stat[8]; | ||
1060 | cmd[0] = FDC_VERSION; | ||
1061 | if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) { | ||
1062 | TRACE_ABORT(i8272, ft_t_warn, "Type 82072 FDC found"); | ||
1063 | } | ||
1064 | if (*stat != 0x90) { | ||
1065 | TRACE_ABORT(i8272, ft_t_warn, "Unknown FDC found"); | ||
1066 | } | ||
1067 | cmd[0] = FDC_UNLOCK; | ||
1068 | if(fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] != 0x00) { | ||
1069 | TRACE_ABORT(i8272, ft_t_warn, | ||
1070 | "Type pre-1991 82077 FDC found, " | ||
1071 | "treating it like a 82072"); | ||
1072 | } | ||
1073 | if (fdc_save_state[0] & 0x80) { /* was locked */ | ||
1074 | cmd[0] = FDC_LOCK; /* restore lock */ | ||
1075 | (void)fdc_issue_command(cmd, 1, stat, 1); | ||
1076 | TRACE(ft_t_warn, "FDC is already locked"); | ||
1077 | } | ||
1078 | /* Test for a i82078 FDC */ | ||
1079 | cmd[0] = FDC_PARTID; | ||
1080 | if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) { | ||
1081 | /* invalid command: not a i82078xx type FDC */ | ||
1082 | for (i = 0; i < 4; ++i) { | ||
1083 | outb_p(i, fdc.tdr); | ||
1084 | if ((inb_p(fdc.tdr) & 0x03) != i) { | ||
1085 | TRACE_ABORT(i82077, | ||
1086 | ft_t_warn, "Type 82077 FDC found"); | ||
1087 | } | ||
1088 | } | ||
1089 | TRACE_ABORT(i82077AA, ft_t_warn, "Type 82077AA FDC found"); | ||
1090 | } | ||
1091 | /* FDC_PARTID cmd succeeded */ | ||
1092 | switch (stat[0] >> 5) { | ||
1093 | case 0x0: | ||
1094 | /* i82078SL or i82078-1. The SL part cannot run at | ||
1095 | * 2Mbps (the SL and -1 dies are identical; they are | ||
1096 | * speed graded after production, according to Intel). | ||
1097 | * Some SL's can be detected by doing a SAVE cmd and | ||
1098 | * look at bit 7 of the first byte (the SEL3V# bit). | ||
1099 | * If it is 0, the part runs off 3Volts, and hence it | ||
1100 | * is a SL. | ||
1101 | */ | ||
1102 | cmd[0] = FDC_SAVE; | ||
1103 | if(fdc_issue_command(cmd, 1, stat, 16) < 0) { | ||
1104 | TRACE(ft_t_err, "FDC_SAVE failed. Dunno why"); | ||
1105 | /* guess we better claim the fdc to be a i82078 */ | ||
1106 | TRACE_ABORT(i82078, | ||
1107 | ft_t_warn, | ||
1108 | "Type i82078 FDC (i suppose) found"); | ||
1109 | } | ||
1110 | if ((stat[0] & FDC_SEL3V_BIT)) { | ||
1111 | /* fdc running off 5Volts; Pray that it's a i82078-1 | ||
1112 | */ | ||
1113 | TRACE_ABORT(i82078_1, ft_t_warn, | ||
1114 | "Type i82078-1 or 5Volt i82078SL FDC found"); | ||
1115 | } | ||
1116 | TRACE_ABORT(i82078, ft_t_warn, | ||
1117 | "Type 3Volt i82078SL FDC (1Mbps) found"); | ||
1118 | case 0x1: | ||
1119 | case 0x2: /* S82078B */ | ||
1120 | /* The '78B isn't '78 compatible. Detect it as a '77AA */ | ||
1121 | TRACE_ABORT(i82077AA, ft_t_warn, "Type i82077AA FDC found"); | ||
1122 | case 0x3: /* NSC PC8744 core; used in several super-IO chips */ | ||
1123 | TRACE_ABORT(i82077AA, | ||
1124 | ft_t_warn, "Type 82077AA compatible FDC found"); | ||
1125 | default: | ||
1126 | TRACE(ft_t_warn, "A previously undetected FDC found"); | ||
1127 | TRACE_ABORT(i82077AA, ft_t_warn, | ||
1128 | "Treating it as a 82077AA. Please report partid= %d", | ||
1129 | stat[0]); | ||
1130 | } /* switch(stat[ 0] >> 5) */ | ||
1131 | TRACE_EXIT no_fdc; | ||
1132 | } | ||
1133 | |||
1134 | static int fdc_request_regions(void) | ||
1135 | { | ||
1136 | TRACE_FUN(ft_t_flow); | ||
1137 | |||
1138 | if (ft_mach2 || ft_probe_fc10) { | ||
1139 | if (!request_region(fdc.sra, 8, "fdc (ft)")) { | ||
1140 | #ifndef BROKEN_FLOPPY_DRIVER | ||
1141 | TRACE_EXIT -EBUSY; | ||
1142 | #else | ||
1143 | TRACE(ft_t_warn, | ||
1144 | "address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra); | ||
1145 | #endif | ||
1146 | } | ||
1147 | } else { | ||
1148 | if (!request_region(fdc.sra, 6, "fdc (ft)")) { | ||
1149 | #ifndef BROKEN_FLOPPY_DRIVER | ||
1150 | TRACE_EXIT -EBUSY; | ||
1151 | #else | ||
1152 | TRACE(ft_t_warn, | ||
1153 | "address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra); | ||
1154 | #endif | ||
1155 | } | ||
1156 | if (!request_region(fdc.sra + 7, 1, "fdc (ft)")) { | ||
1157 | #ifndef BROKEN_FLOPPY_DRIVER | ||
1158 | release_region(fdc.sra, 6); | ||
1159 | TRACE_EXIT -EBUSY; | ||
1160 | #else | ||
1161 | TRACE(ft_t_warn, | ||
1162 | "address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra + 7); | ||
1163 | #endif | ||
1164 | } | ||
1165 | } | ||
1166 | TRACE_EXIT 0; | ||
1167 | } | ||
1168 | |||
1169 | void fdc_release_regions(void) | ||
1170 | { | ||
1171 | TRACE_FUN(ft_t_flow); | ||
1172 | |||
1173 | if (fdc.sra != 0) { | ||
1174 | if (fdc.dor2 != 0) { | ||
1175 | release_region(fdc.sra, 8); | ||
1176 | } else { | ||
1177 | release_region(fdc.sra, 6); | ||
1178 | release_region(fdc.dir, 1); | ||
1179 | } | ||
1180 | } | ||
1181 | TRACE_EXIT; | ||
1182 | } | ||
1183 | |||
1184 | static int fdc_config_regs(unsigned int fdc_base, | ||
1185 | unsigned int fdc_irq, | ||
1186 | unsigned int fdc_dma) | ||
1187 | { | ||
1188 | TRACE_FUN(ft_t_flow); | ||
1189 | |||
1190 | fdc.irq = fdc_irq; | ||
1191 | fdc.dma = fdc_dma; | ||
1192 | fdc.sra = fdc_base; | ||
1193 | fdc.srb = fdc_base + 1; | ||
1194 | fdc.dor = fdc_base + 2; | ||
1195 | fdc.tdr = fdc_base + 3; | ||
1196 | fdc.msr = fdc.dsr = fdc_base + 4; | ||
1197 | fdc.fifo = fdc_base + 5; | ||
1198 | fdc.dir = fdc.ccr = fdc_base + 7; | ||
1199 | fdc.dor2 = (ft_mach2 || ft_probe_fc10) ? fdc_base + 6 : 0; | ||
1200 | TRACE_CATCH(fdc_request_regions(), fdc.sra = 0); | ||
1201 | TRACE_EXIT 0; | ||
1202 | } | ||
1203 | |||
1204 | static int fdc_config(void) | ||
1205 | { | ||
1206 | static int already_done; | ||
1207 | TRACE_FUN(ft_t_any); | ||
1208 | |||
1209 | if (already_done) { | ||
1210 | TRACE_CATCH(fdc_request_regions(),); | ||
1211 | *(fdc.hook) = fdc_isr; /* hook our handler in */ | ||
1212 | TRACE_EXIT 0; | ||
1213 | } | ||
1214 | if (ft_probe_fc10) { | ||
1215 | int fc_type; | ||
1216 | |||
1217 | TRACE_CATCH(fdc_config_regs(ft_fdc_base, | ||
1218 | ft_fdc_irq, ft_fdc_dma),); | ||
1219 | fc_type = fc10_enable(); | ||
1220 | if (fc_type != 0) { | ||
1221 | TRACE(ft_t_warn, "FC-%c0 controller found", '0' + fc_type); | ||
1222 | fdc.type = fc10; | ||
1223 | fdc.hook = &do_ftape; | ||
1224 | *(fdc.hook) = fdc_isr; /* hook our handler in */ | ||
1225 | already_done = 1; | ||
1226 | TRACE_EXIT 0; | ||
1227 | } else { | ||
1228 | TRACE(ft_t_warn, "FC-10/20 controller not found"); | ||
1229 | fdc_release_regions(); | ||
1230 | fdc.type = no_fdc; | ||
1231 | ft_probe_fc10 = 0; | ||
1232 | ft_fdc_base = 0x3f0; | ||
1233 | ft_fdc_irq = 6; | ||
1234 | ft_fdc_dma = 2; | ||
1235 | } | ||
1236 | } | ||
1237 | TRACE(ft_t_warn, "fdc base: 0x%x, irq: %d, dma: %d", | ||
1238 | ft_fdc_base, ft_fdc_irq, ft_fdc_dma); | ||
1239 | TRACE_CATCH(fdc_config_regs(ft_fdc_base, ft_fdc_irq, ft_fdc_dma),); | ||
1240 | fdc.hook = &do_ftape; | ||
1241 | *(fdc.hook) = fdc_isr; /* hook our handler in */ | ||
1242 | already_done = 1; | ||
1243 | TRACE_EXIT 0; | ||
1244 | } | ||
1245 | |||
1246 | static irqreturn_t ftape_interrupt(int irq, void *dev_id) | ||
1247 | { | ||
1248 | void (*handler) (void) = *fdc.hook; | ||
1249 | int handled = 0; | ||
1250 | TRACE_FUN(ft_t_any); | ||
1251 | |||
1252 | *fdc.hook = NULL; | ||
1253 | if (handler) { | ||
1254 | handled = 1; | ||
1255 | handler(); | ||
1256 | } else { | ||
1257 | TRACE(ft_t_bug, "Unexpected ftape interrupt"); | ||
1258 | } | ||
1259 | TRACE_EXIT IRQ_RETVAL(handled); | ||
1260 | } | ||
1261 | |||
1262 | static int fdc_grab_irq_and_dma(void) | ||
1263 | { | ||
1264 | TRACE_FUN(ft_t_any); | ||
1265 | |||
1266 | if (fdc.hook == &do_ftape) { | ||
1267 | /* Get fast interrupt handler. | ||
1268 | */ | ||
1269 | if (request_irq(fdc.irq, ftape_interrupt, | ||
1270 | IRQF_DISABLED, "ft", ftape_id)) { | ||
1271 | TRACE_ABORT(-EIO, ft_t_bug, | ||
1272 | "Unable to grab IRQ%d for ftape driver", | ||
1273 | fdc.irq); | ||
1274 | } | ||
1275 | if (request_dma(fdc.dma, ftape_id)) { | ||
1276 | free_irq(fdc.irq, ftape_id); | ||
1277 | TRACE_ABORT(-EIO, ft_t_bug, | ||
1278 | "Unable to grab DMA%d for ftape driver", | ||
1279 | fdc.dma); | ||
1280 | } | ||
1281 | } | ||
1282 | if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) { | ||
1283 | /* Using same dma channel or irq as standard fdc, need | ||
1284 | * to disable the dma-gate on the std fdc. This | ||
1285 | * couldn't be done in the floppy driver as some | ||
1286 | * laptops are using the dma-gate to enter a low power | ||
1287 | * or even suspended state :-( | ||
1288 | */ | ||
1289 | outb_p(FDC_RESET_NOT, 0x3f2); | ||
1290 | TRACE(ft_t_noise, "DMA-gate on standard fdc disabled"); | ||
1291 | } | ||
1292 | TRACE_EXIT 0; | ||
1293 | } | ||
1294 | |||
1295 | int fdc_release_irq_and_dma(void) | ||
1296 | { | ||
1297 | TRACE_FUN(ft_t_any); | ||
1298 | |||
1299 | if (fdc.hook == &do_ftape) { | ||
1300 | disable_dma(fdc.dma); /* just in case... */ | ||
1301 | free_dma(fdc.dma); | ||
1302 | free_irq(fdc.irq, ftape_id); | ||
1303 | } | ||
1304 | if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) { | ||
1305 | /* Using same dma channel as standard fdc, need to | ||
1306 | * disable the dma-gate on the std fdc. This couldn't | ||
1307 | * be done in the floppy driver as some laptops are | ||
1308 | * using the dma-gate to enter a low power or even | ||
1309 | * suspended state :-( | ||
1310 | */ | ||
1311 | outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2); | ||
1312 | TRACE(ft_t_noise, "DMA-gate on standard fdc enabled again"); | ||
1313 | } | ||
1314 | TRACE_EXIT 0; | ||
1315 | } | ||
1316 | |||
1317 | int fdc_init(void) | ||
1318 | { | ||
1319 | TRACE_FUN(ft_t_any); | ||
1320 | |||
1321 | /* find a FDC to use */ | ||
1322 | TRACE_CATCH(fdc_config(),); | ||
1323 | TRACE_CATCH(fdc_grab_irq_and_dma(), fdc_release_regions()); | ||
1324 | ftape_motor = 0; | ||
1325 | fdc_catch_stray_interrupts(0); /* clear number of awainted | ||
1326 | * stray interrupte | ||
1327 | */ | ||
1328 | fdc_catch_stray_interrupts(1); /* one always comes (?) */ | ||
1329 | TRACE(ft_t_flow, "resetting fdc"); | ||
1330 | fdc_set_seek_rate(2); /* use nominal QIC step rate */ | ||
1331 | fdc_reset(); /* init fdc & clear track counters */ | ||
1332 | if (fdc.type == no_fdc) { /* no FC-10 or FC-20 found */ | ||
1333 | fdc.type = fdc_probe(); | ||
1334 | fdc_reset(); /* update with new knowledge */ | ||
1335 | } | ||
1336 | if (fdc.type == no_fdc) { | ||
1337 | fdc_release_irq_and_dma(); | ||
1338 | fdc_release_regions(); | ||
1339 | TRACE_EXIT -ENXIO; | ||
1340 | } | ||
1341 | if (fdc.type >= i82077) { | ||
1342 | if (fdc_fifo_enable() < 0) { | ||
1343 | TRACE(ft_t_warn, "couldn't enable fdc fifo !"); | ||
1344 | } else { | ||
1345 | TRACE(ft_t_flow, "fdc fifo enabled and locked"); | ||
1346 | } | ||
1347 | } | ||
1348 | TRACE_EXIT 0; | ||
1349 | } | ||
diff --git a/drivers/char/ftape/lowlevel/fdc-io.h b/drivers/char/ftape/lowlevel/fdc-io.h deleted file mode 100644 index 7ec3c72178bb..000000000000 --- a/drivers/char/ftape/lowlevel/fdc-io.h +++ /dev/null | |||
@@ -1,252 +0,0 @@ | |||
1 | #ifndef _FDC_IO_H | ||
2 | #define _FDC_IO_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-io.h,v $ | ||
24 | * $Revision: 1.3 $ | ||
25 | * $Date: 1997/10/05 19:18:06 $ | ||
26 | * | ||
27 | * This file contains the declarations for the low level | ||
28 | * functions that communicate with the floppy disk controller, | ||
29 | * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for | ||
30 | * Linux. | ||
31 | */ | ||
32 | |||
33 | #include <linux/fdreg.h> | ||
34 | |||
35 | #include "../lowlevel/ftape-bsm.h" | ||
36 | |||
37 | #define FDC_SK_BIT (0x20) | ||
38 | #define FDC_MT_BIT (0x80) | ||
39 | |||
40 | #define FDC_READ (FD_READ & ~(FDC_SK_BIT | FDC_MT_BIT)) | ||
41 | #define FDC_WRITE (FD_WRITE & ~FDC_MT_BIT) | ||
42 | #define FDC_READ_DELETED (0x4c) | ||
43 | #define FDC_WRITE_DELETED (0x49) | ||
44 | #define FDC_VERIFY (0x56) | ||
45 | #define FDC_READID (0x4a) | ||
46 | #define FDC_SENSED (0x04) | ||
47 | #define FDC_SENSEI (FD_SENSEI) | ||
48 | #define FDC_FORMAT (FD_FORMAT) | ||
49 | #define FDC_RECAL (FD_RECALIBRATE) | ||
50 | #define FDC_SEEK (FD_SEEK) | ||
51 | #define FDC_SPECIFY (FD_SPECIFY) | ||
52 | #define FDC_RECALIBR (FD_RECALIBRATE) | ||
53 | #define FDC_VERSION (FD_VERSION) | ||
54 | #define FDC_PERPEND (FD_PERPENDICULAR) | ||
55 | #define FDC_DUMPREGS (FD_DUMPREGS) | ||
56 | #define FDC_LOCK (FD_LOCK) | ||
57 | #define FDC_UNLOCK (FD_UNLOCK) | ||
58 | #define FDC_CONFIGURE (FD_CONFIGURE) | ||
59 | #define FDC_DRIVE_SPEC (0x8e) /* i82078 has this (any others?) */ | ||
60 | #define FDC_PARTID (0x18) /* i82078 has this */ | ||
61 | #define FDC_SAVE (0x2e) /* i82078 has this (any others?) */ | ||
62 | #define FDC_RESTORE (0x4e) /* i82078 has this (any others?) */ | ||
63 | |||
64 | #define FDC_STATUS_MASK (STATUS_BUSY | STATUS_DMA | STATUS_DIR | STATUS_READY) | ||
65 | #define FDC_DATA_READY (STATUS_READY) | ||
66 | #define FDC_DATA_OUTPUT (STATUS_DIR) | ||
67 | #define FDC_DATA_READY_MASK (STATUS_READY | STATUS_DIR) | ||
68 | #define FDC_DATA_OUT_READY (STATUS_READY | STATUS_DIR) | ||
69 | #define FDC_DATA_IN_READY (STATUS_READY) | ||
70 | #define FDC_BUSY (STATUS_BUSY) | ||
71 | #define FDC_CLK48_BIT (0x80) | ||
72 | #define FDC_SEL3V_BIT (0x40) | ||
73 | |||
74 | #define ST0_INT_MASK (ST0_INTR) | ||
75 | #define FDC_INT_NORMAL (ST0_INTR & 0x00) | ||
76 | #define FDC_INT_ABNORMAL (ST0_INTR & 0x40) | ||
77 | #define FDC_INT_INVALID (ST0_INTR & 0x80) | ||
78 | #define FDC_INT_READYCH (ST0_INTR & 0xC0) | ||
79 | #define ST0_SEEK_END (ST0_SE) | ||
80 | #define ST3_TRACK_0 (ST3_TZ) | ||
81 | |||
82 | #define FDC_RESET_NOT (0x04) | ||
83 | #define FDC_DMA_MODE (0x08) | ||
84 | #define FDC_MOTOR_0 (0x10) | ||
85 | #define FDC_MOTOR_1 (0x20) | ||
86 | |||
87 | typedef struct { | ||
88 | void (**hook) (void); /* our wedge into the isr */ | ||
89 | enum { | ||
90 | no_fdc, i8272, i82077, i82077AA, fc10, | ||
91 | i82078, i82078_1 | ||
92 | } type; /* FDC type */ | ||
93 | unsigned int irq; /* FDC irq nr */ | ||
94 | unsigned int dma; /* FDC dma channel nr */ | ||
95 | __u16 sra; /* Status register A (PS/2 only) */ | ||
96 | __u16 srb; /* Status register B (PS/2 only) */ | ||
97 | __u16 dor; /* Digital output register */ | ||
98 | __u16 tdr; /* Tape Drive Register (82077SL-1 & | ||
99 | 82078 only) */ | ||
100 | __u16 msr; /* Main Status Register */ | ||
101 | __u16 dsr; /* Datarate Select Register (8207x only) */ | ||
102 | __u16 fifo; /* Data register / Fifo on 8207x */ | ||
103 | __u16 dir; /* Digital Input Register */ | ||
104 | __u16 ccr; /* Configuration Control Register */ | ||
105 | __u16 dor2; /* Alternate dor on MACH-2 controller, | ||
106 | also used with FC-10, meaning unknown */ | ||
107 | } fdc_config_info; | ||
108 | |||
109 | typedef enum { | ||
110 | fdc_data_rate_250 = 2, | ||
111 | fdc_data_rate_300 = 1, /* any fdc in default configuration */ | ||
112 | fdc_data_rate_500 = 0, | ||
113 | fdc_data_rate_1000 = 3, | ||
114 | fdc_data_rate_2000 = 1, /* i82078-1: when using Data Rate Table #2 */ | ||
115 | } fdc_data_rate_type; | ||
116 | |||
117 | typedef enum { | ||
118 | fdc_idle = 0, | ||
119 | fdc_reading_data = FDC_READ, | ||
120 | fdc_seeking = FDC_SEEK, | ||
121 | fdc_writing_data = FDC_WRITE, | ||
122 | fdc_deleting = FDC_WRITE_DELETED, | ||
123 | fdc_reading_id = FDC_READID, | ||
124 | fdc_recalibrating = FDC_RECAL, | ||
125 | fdc_formatting = FDC_FORMAT, | ||
126 | fdc_verifying = FDC_VERIFY | ||
127 | } fdc_mode_enum; | ||
128 | |||
129 | typedef enum { | ||
130 | waiting = 0, | ||
131 | reading, | ||
132 | writing, | ||
133 | formatting, | ||
134 | verifying, | ||
135 | deleting, | ||
136 | done, | ||
137 | error, | ||
138 | mmapped, | ||
139 | } buffer_state_enum; | ||
140 | |||
141 | typedef struct { | ||
142 | __u8 *address; | ||
143 | volatile buffer_state_enum status; | ||
144 | volatile __u8 *ptr; | ||
145 | volatile unsigned int bytes; | ||
146 | volatile unsigned int segment_id; | ||
147 | |||
148 | /* bitmap for remainder of segment not yet handled. | ||
149 | * one bit set for each bad sector that must be skipped. | ||
150 | */ | ||
151 | volatile SectorMap bad_sector_map; | ||
152 | |||
153 | /* bitmap with bad data blocks in data buffer. | ||
154 | * the errors in this map may be retried. | ||
155 | */ | ||
156 | volatile SectorMap soft_error_map; | ||
157 | |||
158 | /* bitmap with bad data blocks in data buffer | ||
159 | * the errors in this map may not be retried. | ||
160 | */ | ||
161 | volatile SectorMap hard_error_map; | ||
162 | |||
163 | /* retry counter for soft errors. | ||
164 | */ | ||
165 | volatile int retry; | ||
166 | |||
167 | /* sectors to skip on retry ??? | ||
168 | */ | ||
169 | volatile unsigned int skip; | ||
170 | |||
171 | /* nr of data blocks in data buffer | ||
172 | */ | ||
173 | volatile unsigned int data_offset; | ||
174 | |||
175 | /* offset in segment for first sector to be handled. | ||
176 | */ | ||
177 | volatile unsigned int sector_offset; | ||
178 | |||
179 | /* size of cluster of good sectors to be handled. | ||
180 | */ | ||
181 | volatile unsigned int sector_count; | ||
182 | |||
183 | /* size of remaining part of segment to be handled. | ||
184 | */ | ||
185 | volatile unsigned int remaining; | ||
186 | |||
187 | /* points to next segment (contiguous) to be handled, | ||
188 | * or is zero if no read-ahead is allowed. | ||
189 | */ | ||
190 | volatile unsigned int next_segment; | ||
191 | |||
192 | /* flag being set if deleted data was read. | ||
193 | */ | ||
194 | volatile int deleted; | ||
195 | |||
196 | /* floppy coordinates of first sector in segment */ | ||
197 | volatile __u8 head; | ||
198 | volatile __u8 cyl; | ||
199 | volatile __u8 sect; | ||
200 | |||
201 | /* gap to use when formatting */ | ||
202 | __u8 gap3; | ||
203 | /* flag set when buffer is mmaped */ | ||
204 | int mmapped; | ||
205 | } buffer_struct; | ||
206 | |||
207 | /* | ||
208 | * fdc-io.c defined public variables | ||
209 | */ | ||
210 | extern volatile fdc_mode_enum fdc_mode; | ||
211 | extern int fdc_setup_error; /* outdated ??? */ | ||
212 | extern wait_queue_head_t ftape_wait_intr; | ||
213 | extern volatile int ftape_current_cylinder; /* track nr FDC thinks we're on */ | ||
214 | extern volatile __u8 fdc_head; /* FDC head */ | ||
215 | extern volatile __u8 fdc_cyl; /* FDC track */ | ||
216 | extern volatile __u8 fdc_sect; /* FDC sector */ | ||
217 | extern fdc_config_info fdc; /* FDC hardware configuration */ | ||
218 | |||
219 | extern unsigned int ft_fdc_base; | ||
220 | extern unsigned int ft_fdc_irq; | ||
221 | extern unsigned int ft_fdc_dma; | ||
222 | extern unsigned int ft_fdc_threshold; | ||
223 | extern unsigned int ft_fdc_rate_limit; | ||
224 | extern int ft_probe_fc10; | ||
225 | extern int ft_mach2; | ||
226 | /* | ||
227 | * fdc-io.c defined public functions | ||
228 | */ | ||
229 | extern void fdc_catch_stray_interrupts(int count); | ||
230 | extern int fdc_ready_wait(unsigned int timeout); | ||
231 | extern int fdc_command(const __u8 * cmd_data, int cmd_len); | ||
232 | extern int fdc_result(__u8 * res_data, int res_len); | ||
233 | extern int fdc_interrupt_wait(unsigned int time); | ||
234 | extern int fdc_seek(int track); | ||
235 | extern int fdc_sense_drive_status(int *st3); | ||
236 | extern void fdc_motor(int motor); | ||
237 | extern void fdc_reset(void); | ||
238 | extern void fdc_disable(void); | ||
239 | extern int fdc_fifo_threshold(__u8 threshold, | ||
240 | int *fifo_state, int *lock_state, int *fifo_thr); | ||
241 | extern void fdc_wait_calibrate(void); | ||
242 | extern int fdc_sense_interrupt_status(int *st0, int *current_cylinder); | ||
243 | extern void fdc_save_drive_specs(void); | ||
244 | extern void fdc_restore_drive_specs(void); | ||
245 | extern int fdc_set_data_rate(int rate); | ||
246 | extern void fdc_set_write_precomp(int precomp); | ||
247 | extern int fdc_release_irq_and_dma(void); | ||
248 | extern void fdc_release_regions(void); | ||
249 | extern int fdc_init(void); | ||
250 | extern int fdc_setup_read_write(buffer_struct * buff, __u8 operation); | ||
251 | extern int fdc_setup_formatting(buffer_struct * buff); | ||
252 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/fdc-isr.c b/drivers/char/ftape/lowlevel/fdc-isr.c deleted file mode 100644 index ad2bc733ae1b..000000000000 --- a/drivers/char/ftape/lowlevel/fdc-isr.c +++ /dev/null | |||
@@ -1,1170 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1994-1996 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.c,v $ | ||
21 | * $Revision: 1.9 $ | ||
22 | * $Date: 1997/10/17 23:01:53 $ | ||
23 | * | ||
24 | * This file contains the interrupt service routine and | ||
25 | * associated code for the QIC-40/80/3010/3020 floppy-tape driver | ||
26 | * "ftape" for Linux. | ||
27 | */ | ||
28 | |||
29 | #include <asm/io.h> | ||
30 | #include <asm/dma.h> | ||
31 | |||
32 | #define volatile /* */ | ||
33 | |||
34 | #include <linux/ftape.h> | ||
35 | #include <linux/qic117.h> | ||
36 | #include "../lowlevel/ftape-tracing.h" | ||
37 | #include "../lowlevel/fdc-isr.h" | ||
38 | #include "../lowlevel/fdc-io.h" | ||
39 | #include "../lowlevel/ftape-ctl.h" | ||
40 | #include "../lowlevel/ftape-rw.h" | ||
41 | #include "../lowlevel/ftape-io.h" | ||
42 | #include "../lowlevel/ftape-calibr.h" | ||
43 | #include "../lowlevel/ftape-bsm.h" | ||
44 | |||
45 | /* Global vars. | ||
46 | */ | ||
47 | volatile int ft_expected_stray_interrupts; | ||
48 | volatile int ft_interrupt_seen; | ||
49 | volatile int ft_seek_completed; | ||
50 | volatile int ft_hide_interrupt; | ||
51 | /* Local vars. | ||
52 | */ | ||
53 | typedef enum { | ||
54 | no_error = 0, id_am_error = 0x01, id_crc_error = 0x02, | ||
55 | data_am_error = 0x04, data_crc_error = 0x08, | ||
56 | no_data_error = 0x10, overrun_error = 0x20, | ||
57 | } error_cause; | ||
58 | static int stop_read_ahead; | ||
59 | |||
60 | |||
61 | static void print_error_cause(int cause) | ||
62 | { | ||
63 | TRACE_FUN(ft_t_any); | ||
64 | |||
65 | switch (cause) { | ||
66 | case no_data_error: | ||
67 | TRACE(ft_t_noise, "no data error"); | ||
68 | break; | ||
69 | case id_am_error: | ||
70 | TRACE(ft_t_noise, "id am error"); | ||
71 | break; | ||
72 | case id_crc_error: | ||
73 | TRACE(ft_t_noise, "id crc error"); | ||
74 | break; | ||
75 | case data_am_error: | ||
76 | TRACE(ft_t_noise, "data am error"); | ||
77 | break; | ||
78 | case data_crc_error: | ||
79 | TRACE(ft_t_noise, "data crc error"); | ||
80 | break; | ||
81 | case overrun_error: | ||
82 | TRACE(ft_t_noise, "overrun error"); | ||
83 | break; | ||
84 | default:; | ||
85 | } | ||
86 | TRACE_EXIT; | ||
87 | } | ||
88 | |||
89 | static char *fdc_mode_txt(fdc_mode_enum mode) | ||
90 | { | ||
91 | switch (mode) { | ||
92 | case fdc_idle: | ||
93 | return "fdc_idle"; | ||
94 | case fdc_reading_data: | ||
95 | return "fdc_reading_data"; | ||
96 | case fdc_seeking: | ||
97 | return "fdc_seeking"; | ||
98 | case fdc_writing_data: | ||
99 | return "fdc_writing_data"; | ||
100 | case fdc_reading_id: | ||
101 | return "fdc_reading_id"; | ||
102 | case fdc_recalibrating: | ||
103 | return "fdc_recalibrating"; | ||
104 | case fdc_formatting: | ||
105 | return "fdc_formatting"; | ||
106 | case fdc_verifying: | ||
107 | return "fdc_verifying"; | ||
108 | default: | ||
109 | return "unknown"; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | static inline error_cause decode_irq_cause(fdc_mode_enum mode, __u8 st[]) | ||
114 | { | ||
115 | error_cause cause = no_error; | ||
116 | TRACE_FUN(ft_t_any); | ||
117 | |||
118 | /* Valid st[], decode cause of interrupt. | ||
119 | */ | ||
120 | switch (st[0] & ST0_INT_MASK) { | ||
121 | case FDC_INT_NORMAL: | ||
122 | TRACE(ft_t_fdc_dma,"normal completion: %s",fdc_mode_txt(mode)); | ||
123 | break; | ||
124 | case FDC_INT_ABNORMAL: | ||
125 | TRACE(ft_t_flow, "abnormal completion %s", fdc_mode_txt(mode)); | ||
126 | TRACE(ft_t_fdc_dma, "ST0: 0x%02x, ST1: 0x%02x, ST2: 0x%02x", | ||
127 | st[0], st[1], st[2]); | ||
128 | TRACE(ft_t_fdc_dma, | ||
129 | "C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x", | ||
130 | st[3], st[4], st[5], st[6]); | ||
131 | if (st[1] & 0x01) { | ||
132 | if (st[2] & 0x01) { | ||
133 | cause = data_am_error; | ||
134 | } else { | ||
135 | cause = id_am_error; | ||
136 | } | ||
137 | } else if (st[1] & 0x20) { | ||
138 | if (st[2] & 0x20) { | ||
139 | cause = data_crc_error; | ||
140 | } else { | ||
141 | cause = id_crc_error; | ||
142 | } | ||
143 | } else if (st[1] & 0x04) { | ||
144 | cause = no_data_error; | ||
145 | } else if (st[1] & 0x10) { | ||
146 | cause = overrun_error; | ||
147 | } | ||
148 | print_error_cause(cause); | ||
149 | break; | ||
150 | case FDC_INT_INVALID: | ||
151 | TRACE(ft_t_flow, "invalid completion %s", fdc_mode_txt(mode)); | ||
152 | break; | ||
153 | case FDC_INT_READYCH: | ||
154 | if (st[0] & ST0_SEEK_END) { | ||
155 | TRACE(ft_t_flow, "drive poll completed"); | ||
156 | } else { | ||
157 | TRACE(ft_t_flow, "ready change %s",fdc_mode_txt(mode)); | ||
158 | } | ||
159 | break; | ||
160 | default: | ||
161 | break; | ||
162 | } | ||
163 | TRACE_EXIT cause; | ||
164 | } | ||
165 | |||
166 | static void update_history(error_cause cause) | ||
167 | { | ||
168 | switch (cause) { | ||
169 | case id_am_error: | ||
170 | ft_history.id_am_errors++; | ||
171 | break; | ||
172 | case id_crc_error: | ||
173 | ft_history.id_crc_errors++; | ||
174 | break; | ||
175 | case data_am_error: | ||
176 | ft_history.data_am_errors++; | ||
177 | break; | ||
178 | case data_crc_error: | ||
179 | ft_history.data_crc_errors++; | ||
180 | break; | ||
181 | case overrun_error: | ||
182 | ft_history.overrun_errors++; | ||
183 | break; | ||
184 | case no_data_error: | ||
185 | ft_history.no_data_errors++; | ||
186 | break; | ||
187 | default:; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | static void skip_bad_sector(buffer_struct * buff) | ||
192 | { | ||
193 | TRACE_FUN(ft_t_any); | ||
194 | |||
195 | /* Mark sector as soft error and skip it | ||
196 | */ | ||
197 | if (buff->remaining > 0) { | ||
198 | ++buff->sector_offset; | ||
199 | ++buff->data_offset; | ||
200 | --buff->remaining; | ||
201 | buff->ptr += FT_SECTOR_SIZE; | ||
202 | buff->bad_sector_map >>= 1; | ||
203 | } else { | ||
204 | /* Hey, what is this????????????? C code: if we shift | ||
205 | * more than 31 bits, we get no shift. That's bad!!!!!! | ||
206 | */ | ||
207 | ++buff->sector_offset; /* hack for error maps */ | ||
208 | TRACE(ft_t_warn, "skipping last sector in segment"); | ||
209 | } | ||
210 | TRACE_EXIT; | ||
211 | } | ||
212 | |||
213 | static void update_error_maps(buffer_struct * buff, unsigned int error_offset) | ||
214 | { | ||
215 | int hard = 0; | ||
216 | TRACE_FUN(ft_t_any); | ||
217 | |||
218 | if (buff->retry < FT_SOFT_RETRIES) { | ||
219 | buff->soft_error_map |= (1 << error_offset); | ||
220 | } else { | ||
221 | buff->hard_error_map |= (1 << error_offset); | ||
222 | buff->soft_error_map &= ~buff->hard_error_map; | ||
223 | buff->retry = -1; /* will be set to 0 in setup_segment */ | ||
224 | hard = 1; | ||
225 | } | ||
226 | TRACE(ft_t_noise, "sector %d : %s error\n" | ||
227 | KERN_INFO "hard map: 0x%08lx\n" | ||
228 | KERN_INFO "soft map: 0x%08lx", | ||
229 | FT_SECTOR(error_offset), hard ? "hard" : "soft", | ||
230 | (long) buff->hard_error_map, (long) buff->soft_error_map); | ||
231 | TRACE_EXIT; | ||
232 | } | ||
233 | |||
234 | static void print_progress(buffer_struct *buff, error_cause cause) | ||
235 | { | ||
236 | TRACE_FUN(ft_t_any); | ||
237 | |||
238 | switch (cause) { | ||
239 | case no_error: | ||
240 | TRACE(ft_t_flow,"%d Sector(s) transferred", buff->sector_count); | ||
241 | break; | ||
242 | case no_data_error: | ||
243 | TRACE(ft_t_flow, "Sector %d not found", | ||
244 | FT_SECTOR(buff->sector_offset)); | ||
245 | break; | ||
246 | case overrun_error: | ||
247 | /* got an overrun error on the first byte, must be a | ||
248 | * hardware problem | ||
249 | */ | ||
250 | TRACE(ft_t_bug, | ||
251 | "Unexpected error: failing DMA or FDC controller ?"); | ||
252 | break; | ||
253 | case data_crc_error: | ||
254 | TRACE(ft_t_flow, "Error in sector %d", | ||
255 | FT_SECTOR(buff->sector_offset - 1)); | ||
256 | break; | ||
257 | case id_crc_error: | ||
258 | case id_am_error: | ||
259 | case data_am_error: | ||
260 | TRACE(ft_t_flow, "Error in sector %d", | ||
261 | FT_SECTOR(buff->sector_offset)); | ||
262 | break; | ||
263 | default: | ||
264 | TRACE(ft_t_flow, "Unexpected error at sector %d", | ||
265 | FT_SECTOR(buff->sector_offset)); | ||
266 | break; | ||
267 | } | ||
268 | TRACE_EXIT; | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * Error cause: Amount xferred: Action: | ||
273 | * | ||
274 | * id_am_error 0 mark bad and skip | ||
275 | * id_crc_error 0 mark bad and skip | ||
276 | * data_am_error 0 mark bad and skip | ||
277 | * data_crc_error % 1024 mark bad and skip | ||
278 | * no_data_error 0 retry on write | ||
279 | * mark bad and skip on read | ||
280 | * overrun_error [ 0..all-1 ] mark bad and skip | ||
281 | * no_error all continue | ||
282 | */ | ||
283 | |||
284 | /* the arg `sector' is returned by the fdc and tells us at which sector we | ||
285 | * are positioned at (relative to starting sector of segment) | ||
286 | */ | ||
287 | static void determine_verify_progress(buffer_struct *buff, | ||
288 | error_cause cause, | ||
289 | __u8 sector) | ||
290 | { | ||
291 | TRACE_FUN(ft_t_any); | ||
292 | |||
293 | if (cause == no_error && sector == 1) { | ||
294 | buff->sector_offset = FT_SECTORS_PER_SEGMENT; | ||
295 | buff->remaining = 0; | ||
296 | if (TRACE_LEVEL >= ft_t_flow) { | ||
297 | print_progress(buff, cause); | ||
298 | } | ||
299 | } else { | ||
300 | buff->sector_offset = sector - buff->sect; | ||
301 | buff->remaining = FT_SECTORS_PER_SEGMENT - buff->sector_offset; | ||
302 | TRACE(ft_t_noise, "%ssector offset: 0x%04x", | ||
303 | (cause == no_error) ? "unexpected " : "", | ||
304 | buff->sector_offset); | ||
305 | switch (cause) { | ||
306 | case overrun_error: | ||
307 | break; | ||
308 | #if 0 | ||
309 | case no_data_error: | ||
310 | buff->retry = FT_SOFT_RETRIES; | ||
311 | if (buff->hard_error_map && | ||
312 | buff->sector_offset > 1 && | ||
313 | (buff->hard_error_map & | ||
314 | (1 << (buff->sector_offset-2)))) { | ||
315 | buff->retry --; | ||
316 | } | ||
317 | break; | ||
318 | #endif | ||
319 | default: | ||
320 | buff->retry = FT_SOFT_RETRIES; | ||
321 | break; | ||
322 | } | ||
323 | if (TRACE_LEVEL >= ft_t_flow) { | ||
324 | print_progress(buff, cause); | ||
325 | } | ||
326 | /* Sector_offset points to the problem area Now adjust | ||
327 | * sector_offset so it always points one past he failing | ||
328 | * sector. I.e. skip the bad sector. | ||
329 | */ | ||
330 | ++buff->sector_offset; | ||
331 | --buff->remaining; | ||
332 | update_error_maps(buff, buff->sector_offset - 1); | ||
333 | } | ||
334 | TRACE_EXIT; | ||
335 | } | ||
336 | |||
337 | static void determine_progress(buffer_struct *buff, | ||
338 | error_cause cause, | ||
339 | __u8 sector) | ||
340 | { | ||
341 | unsigned int dma_residue; | ||
342 | TRACE_FUN(ft_t_any); | ||
343 | |||
344 | /* Using less preferred order of disable_dma and | ||
345 | * get_dma_residue because this seems to fail on at least one | ||
346 | * system if reversed! | ||
347 | */ | ||
348 | dma_residue = get_dma_residue(fdc.dma); | ||
349 | disable_dma(fdc.dma); | ||
350 | if (cause != no_error || dma_residue != 0) { | ||
351 | TRACE(ft_t_noise, "%sDMA residue: 0x%04x", | ||
352 | (cause == no_error) ? "unexpected " : "", | ||
353 | dma_residue); | ||
354 | /* adjust to actual value: */ | ||
355 | if (dma_residue == 0) { | ||
356 | /* this happens sometimes with overrun errors. | ||
357 | * I don't know whether we could ignore the | ||
358 | * overrun error. Play save. | ||
359 | */ | ||
360 | buff->sector_count --; | ||
361 | } else { | ||
362 | buff->sector_count -= ((dma_residue + | ||
363 | (FT_SECTOR_SIZE - 1)) / | ||
364 | FT_SECTOR_SIZE); | ||
365 | } | ||
366 | } | ||
367 | /* Update var's influenced by the DMA operation. | ||
368 | */ | ||
369 | if (buff->sector_count > 0) { | ||
370 | buff->sector_offset += buff->sector_count; | ||
371 | buff->data_offset += buff->sector_count; | ||
372 | buff->ptr += (buff->sector_count * | ||
373 | FT_SECTOR_SIZE); | ||
374 | buff->remaining -= buff->sector_count; | ||
375 | buff->bad_sector_map >>= buff->sector_count; | ||
376 | } | ||
377 | if (TRACE_LEVEL >= ft_t_flow) { | ||
378 | print_progress(buff, cause); | ||
379 | } | ||
380 | if (cause != no_error) { | ||
381 | if (buff->remaining == 0) { | ||
382 | TRACE(ft_t_warn, "foo?\n" | ||
383 | KERN_INFO "count : %d\n" | ||
384 | KERN_INFO "offset: %d\n" | ||
385 | KERN_INFO "soft : %08x\n" | ||
386 | KERN_INFO "hard : %08x", | ||
387 | buff->sector_count, | ||
388 | buff->sector_offset, | ||
389 | buff->soft_error_map, | ||
390 | buff->hard_error_map); | ||
391 | } | ||
392 | /* Sector_offset points to the problem area, except if we got | ||
393 | * a data_crc_error. In that case it points one past the | ||
394 | * failing sector. | ||
395 | * | ||
396 | * Now adjust sector_offset so it always points one past he | ||
397 | * failing sector. I.e. skip the bad sector. | ||
398 | */ | ||
399 | if (cause != data_crc_error) { | ||
400 | skip_bad_sector(buff); | ||
401 | } | ||
402 | update_error_maps(buff, buff->sector_offset - 1); | ||
403 | } | ||
404 | TRACE_EXIT; | ||
405 | } | ||
406 | |||
407 | static int calc_steps(int cmd) | ||
408 | { | ||
409 | if (ftape_current_cylinder > cmd) { | ||
410 | return ftape_current_cylinder - cmd; | ||
411 | } else { | ||
412 | return ftape_current_cylinder + cmd; | ||
413 | } | ||
414 | } | ||
415 | |||
416 | static void pause_tape(int retry, int mode) | ||
417 | { | ||
418 | int result; | ||
419 | __u8 out[3] = {FDC_SEEK, ft_drive_sel, 0}; | ||
420 | TRACE_FUN(ft_t_any); | ||
421 | |||
422 | /* We'll use a raw seek command to get the tape to rewind and | ||
423 | * stop for a retry. | ||
424 | */ | ||
425 | ++ft_history.rewinds; | ||
426 | if (qic117_cmds[ftape_current_command].non_intr) { | ||
427 | TRACE(ft_t_warn, "motion command may be issued too soon"); | ||
428 | } | ||
429 | if (retry && (mode == fdc_reading_data || | ||
430 | mode == fdc_reading_id || | ||
431 | mode == fdc_verifying)) { | ||
432 | ftape_current_command = QIC_MICRO_STEP_PAUSE; | ||
433 | ftape_might_be_off_track = 1; | ||
434 | } else { | ||
435 | ftape_current_command = QIC_PAUSE; | ||
436 | } | ||
437 | out[2] = calc_steps(ftape_current_command); | ||
438 | result = fdc_command(out, 3); /* issue QIC_117 command */ | ||
439 | ftape_current_cylinder = out[ 2]; | ||
440 | if (result < 0) { | ||
441 | TRACE(ft_t_noise, "qic-pause failed, status = %d", result); | ||
442 | } else { | ||
443 | ft_location.known = 0; | ||
444 | ft_runner_status = idle; | ||
445 | ft_hide_interrupt = 1; | ||
446 | ftape_tape_running = 0; | ||
447 | } | ||
448 | TRACE_EXIT; | ||
449 | } | ||
450 | |||
451 | static void continue_xfer(buffer_struct *buff, | ||
452 | fdc_mode_enum mode, | ||
453 | unsigned int skip) | ||
454 | { | ||
455 | int write = 0; | ||
456 | TRACE_FUN(ft_t_any); | ||
457 | |||
458 | if (mode == fdc_writing_data || mode == fdc_deleting) { | ||
459 | write = 1; | ||
460 | } | ||
461 | /* This part can be removed if it never happens | ||
462 | */ | ||
463 | if (skip > 0 && | ||
464 | (ft_runner_status != running || | ||
465 | (write && (buff->status != writing)) || | ||
466 | (!write && (buff->status != reading && | ||
467 | buff->status != verifying)))) { | ||
468 | TRACE(ft_t_err, "unexpected runner/buffer state %d/%d", | ||
469 | ft_runner_status, buff->status); | ||
470 | buff->status = error; | ||
471 | /* finish this buffer: */ | ||
472 | (void)ftape_next_buffer(ft_queue_head); | ||
473 | ft_runner_status = aborting; | ||
474 | fdc_mode = fdc_idle; | ||
475 | } else if (buff->remaining > 0 && ftape_calc_next_cluster(buff) > 0) { | ||
476 | /* still sectors left in current segment, continue | ||
477 | * with this segment | ||
478 | */ | ||
479 | if (fdc_setup_read_write(buff, mode) < 0) { | ||
480 | /* failed, abort operation | ||
481 | */ | ||
482 | buff->bytes = buff->ptr - buff->address; | ||
483 | buff->status = error; | ||
484 | /* finish this buffer: */ | ||
485 | (void)ftape_next_buffer(ft_queue_head); | ||
486 | ft_runner_status = aborting; | ||
487 | fdc_mode = fdc_idle; | ||
488 | } | ||
489 | } else { | ||
490 | /* current segment completed | ||
491 | */ | ||
492 | unsigned int last_segment = buff->segment_id; | ||
493 | int eot = ((last_segment + 1) % ft_segments_per_track) == 0; | ||
494 | unsigned int next = buff->next_segment; /* 0 means stop ! */ | ||
495 | |||
496 | buff->bytes = buff->ptr - buff->address; | ||
497 | buff->status = done; | ||
498 | buff = ftape_next_buffer(ft_queue_head); | ||
499 | if (eot) { | ||
500 | /* finished last segment on current track, | ||
501 | * can't continue | ||
502 | */ | ||
503 | ft_runner_status = logical_eot; | ||
504 | fdc_mode = fdc_idle; | ||
505 | TRACE_EXIT; | ||
506 | } | ||
507 | if (next <= 0) { | ||
508 | /* don't continue with next segment | ||
509 | */ | ||
510 | TRACE(ft_t_noise, "no %s allowed, stopping tape", | ||
511 | (write) ? "write next" : "read ahead"); | ||
512 | pause_tape(0, mode); | ||
513 | ft_runner_status = idle; /* not quite true until | ||
514 | * next irq | ||
515 | */ | ||
516 | TRACE_EXIT; | ||
517 | } | ||
518 | /* continue with next segment | ||
519 | */ | ||
520 | if (buff->status != waiting) { | ||
521 | TRACE(ft_t_noise, "all input buffers %s, pausing tape", | ||
522 | (write) ? "empty" : "full"); | ||
523 | pause_tape(0, mode); | ||
524 | ft_runner_status = idle; /* not quite true until | ||
525 | * next irq | ||
526 | */ | ||
527 | TRACE_EXIT; | ||
528 | } | ||
529 | if (write && next != buff->segment_id) { | ||
530 | TRACE(ft_t_noise, | ||
531 | "segments out of order, aborting write"); | ||
532 | ft_runner_status = do_abort; | ||
533 | fdc_mode = fdc_idle; | ||
534 | TRACE_EXIT; | ||
535 | } | ||
536 | ftape_setup_new_segment(buff, next, 0); | ||
537 | if (stop_read_ahead) { | ||
538 | buff->next_segment = 0; | ||
539 | stop_read_ahead = 0; | ||
540 | } | ||
541 | if (ftape_calc_next_cluster(buff) == 0 || | ||
542 | fdc_setup_read_write(buff, mode) != 0) { | ||
543 | TRACE(ft_t_err, "couldn't start %s-ahead", | ||
544 | write ? "write" : "read"); | ||
545 | ft_runner_status = do_abort; | ||
546 | fdc_mode = fdc_idle; | ||
547 | } else { | ||
548 | /* keep on going */ | ||
549 | switch (ft_driver_state) { | ||
550 | case reading: buff->status = reading; break; | ||
551 | case verifying: buff->status = verifying; break; | ||
552 | case writing: buff->status = writing; break; | ||
553 | case deleting: buff->status = deleting; break; | ||
554 | default: | ||
555 | TRACE(ft_t_err, | ||
556 | "BUG: ft_driver_state %d should be one out of " | ||
557 | "{reading, writing, verifying, deleting}", | ||
558 | ft_driver_state); | ||
559 | buff->status = write ? writing : reading; | ||
560 | break; | ||
561 | } | ||
562 | } | ||
563 | } | ||
564 | TRACE_EXIT; | ||
565 | } | ||
566 | |||
567 | static void retry_sector(buffer_struct *buff, | ||
568 | int mode, | ||
569 | unsigned int skip) | ||
570 | { | ||
571 | TRACE_FUN(ft_t_any); | ||
572 | |||
573 | TRACE(ft_t_noise, "%s error, will retry", | ||
574 | (mode == fdc_writing_data || mode == fdc_deleting) ? "write" : "read"); | ||
575 | pause_tape(1, mode); | ||
576 | ft_runner_status = aborting; | ||
577 | buff->status = error; | ||
578 | buff->skip = skip; | ||
579 | TRACE_EXIT; | ||
580 | } | ||
581 | |||
582 | static unsigned int find_resume_point(buffer_struct *buff) | ||
583 | { | ||
584 | int i = 0; | ||
585 | SectorMap mask; | ||
586 | SectorMap map; | ||
587 | TRACE_FUN(ft_t_any); | ||
588 | |||
589 | /* This function is to be called after all variables have been | ||
590 | * updated to point past the failing sector. | ||
591 | * If there are any soft errors before the failing sector, | ||
592 | * find the first soft error and return the sector offset. | ||
593 | * Otherwise find the last hard error. | ||
594 | * Note: there should always be at least one hard or soft error ! | ||
595 | */ | ||
596 | if (buff->sector_offset < 1 || buff->sector_offset > 32) { | ||
597 | TRACE(ft_t_bug, "BUG: sector_offset = %d", | ||
598 | buff->sector_offset); | ||
599 | TRACE_EXIT 0; | ||
600 | } | ||
601 | if (buff->sector_offset >= 32) { /* C-limitation on shift ! */ | ||
602 | mask = 0xffffffff; | ||
603 | } else { | ||
604 | mask = (1 << buff->sector_offset) - 1; | ||
605 | } | ||
606 | map = buff->soft_error_map & mask; | ||
607 | if (map) { | ||
608 | while ((map & (1 << i)) == 0) { | ||
609 | ++i; | ||
610 | } | ||
611 | TRACE(ft_t_noise, "at sector %d", FT_SECTOR(i)); | ||
612 | } else { | ||
613 | map = buff->hard_error_map & mask; | ||
614 | i = buff->sector_offset - 1; | ||
615 | if (map) { | ||
616 | while ((map & (1 << i)) == 0) { | ||
617 | --i; | ||
618 | } | ||
619 | TRACE(ft_t_noise, "after sector %d", FT_SECTOR(i)); | ||
620 | ++i; /* first sector after last hard error */ | ||
621 | } else { | ||
622 | TRACE(ft_t_bug, "BUG: no soft or hard errors"); | ||
623 | } | ||
624 | } | ||
625 | TRACE_EXIT i; | ||
626 | } | ||
627 | |||
628 | /* check possible dma residue when formatting, update position record in | ||
629 | * buffer struct. This is, of course, modelled after determine_progress(), but | ||
630 | * we don't need to set up for retries because the format process cannot be | ||
631 | * interrupted (except at the end of the tape track). | ||
632 | */ | ||
633 | static int determine_fmt_progress(buffer_struct *buff, error_cause cause) | ||
634 | { | ||
635 | unsigned int dma_residue; | ||
636 | TRACE_FUN(ft_t_any); | ||
637 | |||
638 | /* Using less preferred order of disable_dma and | ||
639 | * get_dma_residue because this seems to fail on at least one | ||
640 | * system if reversed! | ||
641 | */ | ||
642 | dma_residue = get_dma_residue(fdc.dma); | ||
643 | disable_dma(fdc.dma); | ||
644 | if (cause != no_error || dma_residue != 0) { | ||
645 | TRACE(ft_t_info, "DMA residue = 0x%04x", dma_residue); | ||
646 | fdc_mode = fdc_idle; | ||
647 | switch(cause) { | ||
648 | case no_error: | ||
649 | ft_runner_status = aborting; | ||
650 | buff->status = idle; | ||
651 | break; | ||
652 | case overrun_error: | ||
653 | /* got an overrun error on the first byte, must be a | ||
654 | * hardware problem | ||
655 | */ | ||
656 | TRACE(ft_t_bug, | ||
657 | "Unexpected error: failing DMA controller ?"); | ||
658 | ft_runner_status = do_abort; | ||
659 | buff->status = error; | ||
660 | break; | ||
661 | default: | ||
662 | TRACE(ft_t_noise, "Unexpected error at segment %d", | ||
663 | buff->segment_id); | ||
664 | ft_runner_status = do_abort; | ||
665 | buff->status = error; | ||
666 | break; | ||
667 | } | ||
668 | TRACE_EXIT -EIO; /* can only retry entire track in format mode | ||
669 | */ | ||
670 | } | ||
671 | /* Update var's influenced by the DMA operation. | ||
672 | */ | ||
673 | buff->ptr += FT_SECTORS_PER_SEGMENT * 4; | ||
674 | buff->bytes -= FT_SECTORS_PER_SEGMENT * 4; | ||
675 | buff->remaining -= FT_SECTORS_PER_SEGMENT; | ||
676 | buff->segment_id ++; /* done with segment */ | ||
677 | TRACE_EXIT 0; | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * Continue formatting, switch buffers if there is no data left in | ||
682 | * current buffer. This is, of course, modelled after | ||
683 | * continue_xfer(), but we don't need to set up for retries because | ||
684 | * the format process cannot be interrupted (except at the end of the | ||
685 | * tape track). | ||
686 | */ | ||
687 | static void continue_formatting(buffer_struct *buff) | ||
688 | { | ||
689 | TRACE_FUN(ft_t_any); | ||
690 | |||
691 | if (buff->remaining <= 0) { /* no space left in dma buffer */ | ||
692 | unsigned int next = buff->next_segment; | ||
693 | |||
694 | if (next == 0) { /* end of tape track */ | ||
695 | buff->status = done; | ||
696 | ft_runner_status = logical_eot; | ||
697 | fdc_mode = fdc_idle; | ||
698 | TRACE(ft_t_noise, "Done formatting track %d", | ||
699 | ft_location.track); | ||
700 | TRACE_EXIT; | ||
701 | } | ||
702 | /* | ||
703 | * switch to next buffer! | ||
704 | */ | ||
705 | buff->status = done; | ||
706 | buff = ftape_next_buffer(ft_queue_head); | ||
707 | |||
708 | if (buff->status != waiting || next != buff->segment_id) { | ||
709 | goto format_setup_error; | ||
710 | } | ||
711 | } | ||
712 | if (fdc_setup_formatting(buff) < 0) { | ||
713 | goto format_setup_error; | ||
714 | } | ||
715 | buff->status = formatting; | ||
716 | TRACE(ft_t_fdc_dma, "Formatting segment %d on track %d", | ||
717 | buff->segment_id, ft_location.track); | ||
718 | TRACE_EXIT; | ||
719 | format_setup_error: | ||
720 | ft_runner_status = do_abort; | ||
721 | fdc_mode = fdc_idle; | ||
722 | buff->status = error; | ||
723 | TRACE(ft_t_err, "Error setting up for segment %d on track %d", | ||
724 | buff->segment_id, ft_location.track); | ||
725 | TRACE_EXIT; | ||
726 | |||
727 | } | ||
728 | |||
729 | /* this handles writing, read id, reading and formatting | ||
730 | */ | ||
731 | static void handle_fdc_busy(buffer_struct *buff) | ||
732 | { | ||
733 | static int no_data_error_count; | ||
734 | int retry = 0; | ||
735 | error_cause cause; | ||
736 | __u8 in[7]; | ||
737 | int skip; | ||
738 | fdc_mode_enum fmode = fdc_mode; | ||
739 | TRACE_FUN(ft_t_any); | ||
740 | |||
741 | if (fdc_result(in, 7) < 0) { /* better get it fast ! */ | ||
742 | TRACE(ft_t_err, | ||
743 | "Probably fatal error during FDC Result Phase\n" | ||
744 | KERN_INFO | ||
745 | "drive may hang until (power on) reset :-("); | ||
746 | /* what to do next ???? | ||
747 | */ | ||
748 | TRACE_EXIT; | ||
749 | } | ||
750 | cause = decode_irq_cause(fdc_mode, in); | ||
751 | #ifdef TESTING | ||
752 | { int i; | ||
753 | for (i = 0; i < (int)ft_nr_buffers; ++i) | ||
754 | TRACE(ft_t_any, "buffer[%d] status: %d, segment_id: %d", | ||
755 | i, ft_buffer[i]->status, ft_buffer[i]->segment_id); | ||
756 | } | ||
757 | #endif | ||
758 | if (fmode == fdc_reading_data && ft_driver_state == verifying) { | ||
759 | fmode = fdc_verifying; | ||
760 | } | ||
761 | switch (fmode) { | ||
762 | case fdc_verifying: | ||
763 | if (ft_runner_status == aborting || | ||
764 | ft_runner_status == do_abort) { | ||
765 | TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode)); | ||
766 | break; | ||
767 | } | ||
768 | if (buff->retry > 0) { | ||
769 | TRACE(ft_t_flow, "this is retry nr %d", buff->retry); | ||
770 | } | ||
771 | switch (cause) { | ||
772 | case no_error: | ||
773 | no_data_error_count = 0; | ||
774 | determine_verify_progress(buff, cause, in[5]); | ||
775 | if (in[2] & 0x40) { | ||
776 | /* This should not happen when verifying | ||
777 | */ | ||
778 | TRACE(ft_t_warn, | ||
779 | "deleted data in segment %d/%d", | ||
780 | buff->segment_id, | ||
781 | FT_SECTOR(buff->sector_offset - 1)); | ||
782 | buff->remaining = 0; /* abort transfer */ | ||
783 | buff->hard_error_map = EMPTY_SEGMENT; | ||
784 | skip = 1; | ||
785 | } else { | ||
786 | skip = 0; | ||
787 | } | ||
788 | continue_xfer(buff, fdc_mode, skip); | ||
789 | break; | ||
790 | case no_data_error: | ||
791 | no_data_error_count ++; | ||
792 | case overrun_error: | ||
793 | retry ++; | ||
794 | case id_am_error: | ||
795 | case id_crc_error: | ||
796 | case data_am_error: | ||
797 | case data_crc_error: | ||
798 | determine_verify_progress(buff, cause, in[5]); | ||
799 | if (cause == no_data_error) { | ||
800 | if (no_data_error_count >= 2) { | ||
801 | TRACE(ft_t_warn, | ||
802 | "retrying because of successive " | ||
803 | "no data errors"); | ||
804 | no_data_error_count = 0; | ||
805 | } else { | ||
806 | retry --; | ||
807 | } | ||
808 | } else { | ||
809 | no_data_error_count = 0; | ||
810 | } | ||
811 | if (retry) { | ||
812 | skip = find_resume_point(buff); | ||
813 | } else { | ||
814 | skip = buff->sector_offset; | ||
815 | } | ||
816 | if (retry && skip < 32) { | ||
817 | retry_sector(buff, fdc_mode, skip); | ||
818 | } else { | ||
819 | continue_xfer(buff, fdc_mode, skip); | ||
820 | } | ||
821 | update_history(cause); | ||
822 | break; | ||
823 | default: | ||
824 | /* Don't know why this could happen | ||
825 | * but find out. | ||
826 | */ | ||
827 | determine_verify_progress(buff, cause, in[5]); | ||
828 | retry_sector(buff, fdc_mode, 0); | ||
829 | TRACE(ft_t_err, "Error: unexpected error"); | ||
830 | break; | ||
831 | } | ||
832 | break; | ||
833 | case fdc_reading_data: | ||
834 | #ifdef TESTING | ||
835 | /* I'm sorry, but: NOBODY ever used this trace | ||
836 | * messages for ages. I guess that Bas was the last person | ||
837 | * that ever really used this (thank you, between the lines) | ||
838 | */ | ||
839 | if (cause == no_error) { | ||
840 | TRACE(ft_t_flow,"reading segment %d",buff->segment_id); | ||
841 | } else { | ||
842 | TRACE(ft_t_noise, "error reading segment %d", | ||
843 | buff->segment_id); | ||
844 | TRACE(ft_t_noise, "\n" | ||
845 | KERN_INFO | ||
846 | "IRQ:C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x\n" | ||
847 | KERN_INFO | ||
848 | "BUF:C: 0x%02x, H: 0x%02x, R: 0x%02x", | ||
849 | in[3], in[4], in[5], in[6], | ||
850 | buff->cyl, buff->head, buff->sect); | ||
851 | } | ||
852 | #endif | ||
853 | if (ft_runner_status == aborting || | ||
854 | ft_runner_status == do_abort) { | ||
855 | TRACE(ft_t_noise,"aborting %s",fdc_mode_txt(fdc_mode)); | ||
856 | break; | ||
857 | } | ||
858 | if (buff->bad_sector_map == FAKE_SEGMENT) { | ||
859 | /* This condition occurs when reading a `fake' | ||
860 | * sector that's not accessible. Doesn't | ||
861 | * really matter as we would have ignored it | ||
862 | * anyway ! | ||
863 | * | ||
864 | * Chance is that we're past the next segment | ||
865 | * now, so the next operation may fail and | ||
866 | * result in a retry. | ||
867 | */ | ||
868 | buff->remaining = 0; /* skip failing sector */ | ||
869 | /* buff->ptr = buff->address; */ | ||
870 | /* fake success: */ | ||
871 | continue_xfer(buff, fdc_mode, 1); | ||
872 | /* trace calls are expensive: place them AFTER | ||
873 | * the real stuff has been done. | ||
874 | * | ||
875 | */ | ||
876 | TRACE(ft_t_noise, "skipping empty segment %d (read), size? %d", | ||
877 | buff->segment_id, buff->ptr - buff->address); | ||
878 | TRACE_EXIT; | ||
879 | } | ||
880 | if (buff->retry > 0) { | ||
881 | TRACE(ft_t_flow, "this is retry nr %d", buff->retry); | ||
882 | } | ||
883 | switch (cause) { | ||
884 | case no_error: | ||
885 | determine_progress(buff, cause, in[5]); | ||
886 | if (in[2] & 0x40) { | ||
887 | /* Handle deleted data in header segments. | ||
888 | * Skip segment and force read-ahead. | ||
889 | */ | ||
890 | TRACE(ft_t_warn, | ||
891 | "deleted data in segment %d/%d", | ||
892 | buff->segment_id, | ||
893 | FT_SECTOR(buff->sector_offset - 1)); | ||
894 | buff->deleted = 1; | ||
895 | buff->remaining = 0;/*abort transfer */ | ||
896 | buff->soft_error_map |= | ||
897 | (-1L << buff->sector_offset); | ||
898 | if (buff->segment_id == 0) { | ||
899 | /* stop on next segment */ | ||
900 | stop_read_ahead = 1; | ||
901 | } | ||
902 | /* force read-ahead: */ | ||
903 | buff->next_segment = | ||
904 | buff->segment_id + 1; | ||
905 | skip = (FT_SECTORS_PER_SEGMENT - | ||
906 | buff->sector_offset); | ||
907 | } else { | ||
908 | skip = 0; | ||
909 | } | ||
910 | continue_xfer(buff, fdc_mode, skip); | ||
911 | break; | ||
912 | case no_data_error: | ||
913 | /* Tape started too far ahead of or behind the | ||
914 | * right sector. This may also happen in the | ||
915 | * middle of a segment ! | ||
916 | * | ||
917 | * Handle no-data as soft error. If next | ||
918 | * sector fails too, a retry (with needed | ||
919 | * reposition) will follow. | ||
920 | */ | ||
921 | retry ++; | ||
922 | case id_am_error: | ||
923 | case id_crc_error: | ||
924 | case data_am_error: | ||
925 | case data_crc_error: | ||
926 | case overrun_error: | ||
927 | retry += (buff->soft_error_map != 0 || | ||
928 | buff->hard_error_map != 0); | ||
929 | determine_progress(buff, cause, in[5]); | ||
930 | #if 1 || defined(TESTING) | ||
931 | if (cause == overrun_error) retry ++; | ||
932 | #endif | ||
933 | if (retry) { | ||
934 | skip = find_resume_point(buff); | ||
935 | } else { | ||
936 | skip = buff->sector_offset; | ||
937 | } | ||
938 | /* Try to resume with next sector on single | ||
939 | * errors (let ecc correct it), but retry on | ||
940 | * no_data (we'll be past the target when we | ||
941 | * get here so we cannot retry) or on | ||
942 | * multiple errors (reduce chance on ecc | ||
943 | * failure). | ||
944 | */ | ||
945 | /* cH: 23/02/97: if the last sector in the | ||
946 | * segment was a hard error, then there is | ||
947 | * no sense in a retry. This occasion seldom | ||
948 | * occurs but ... @:³²¸`@%&§$ | ||
949 | */ | ||
950 | if (retry && skip < 32) { | ||
951 | retry_sector(buff, fdc_mode, skip); | ||
952 | } else { | ||
953 | continue_xfer(buff, fdc_mode, skip); | ||
954 | } | ||
955 | update_history(cause); | ||
956 | break; | ||
957 | default: | ||
958 | /* Don't know why this could happen | ||
959 | * but find out. | ||
960 | */ | ||
961 | determine_progress(buff, cause, in[5]); | ||
962 | retry_sector(buff, fdc_mode, 0); | ||
963 | TRACE(ft_t_err, "Error: unexpected error"); | ||
964 | break; | ||
965 | } | ||
966 | break; | ||
967 | case fdc_reading_id: | ||
968 | if (cause == no_error) { | ||
969 | fdc_cyl = in[3]; | ||
970 | fdc_head = in[4]; | ||
971 | fdc_sect = in[5]; | ||
972 | TRACE(ft_t_fdc_dma, | ||
973 | "id read: C: 0x%02x, H: 0x%02x, R: 0x%02x", | ||
974 | fdc_cyl, fdc_head, fdc_sect); | ||
975 | } else { /* no valid information, use invalid sector */ | ||
976 | fdc_cyl = fdc_head = fdc_sect = 0; | ||
977 | TRACE(ft_t_flow, "Didn't find valid sector Id"); | ||
978 | } | ||
979 | fdc_mode = fdc_idle; | ||
980 | break; | ||
981 | case fdc_deleting: | ||
982 | case fdc_writing_data: | ||
983 | #ifdef TESTING | ||
984 | if (cause == no_error) { | ||
985 | TRACE(ft_t_flow, "writing segment %d", buff->segment_id); | ||
986 | } else { | ||
987 | TRACE(ft_t_noise, "error writing segment %d", | ||
988 | buff->segment_id); | ||
989 | } | ||
990 | #endif | ||
991 | if (ft_runner_status == aborting || | ||
992 | ft_runner_status == do_abort) { | ||
993 | TRACE(ft_t_flow, "aborting %s",fdc_mode_txt(fdc_mode)); | ||
994 | break; | ||
995 | } | ||
996 | if (buff->retry > 0) { | ||
997 | TRACE(ft_t_flow, "this is retry nr %d", buff->retry); | ||
998 | } | ||
999 | if (buff->bad_sector_map == FAKE_SEGMENT) { | ||
1000 | /* This condition occurs when trying to write to a | ||
1001 | * `fake' sector that's not accessible. Doesn't really | ||
1002 | * matter as it isn't used anyway ! Might be located | ||
1003 | * at wrong segment, then we'll fail on the next | ||
1004 | * segment. | ||
1005 | */ | ||
1006 | TRACE(ft_t_noise, "skipping empty segment (write)"); | ||
1007 | buff->remaining = 0; /* skip failing sector */ | ||
1008 | /* fake success: */ | ||
1009 | continue_xfer(buff, fdc_mode, 1); | ||
1010 | break; | ||
1011 | } | ||
1012 | switch (cause) { | ||
1013 | case no_error: | ||
1014 | determine_progress(buff, cause, in[5]); | ||
1015 | continue_xfer(buff, fdc_mode, 0); | ||
1016 | break; | ||
1017 | case no_data_error: | ||
1018 | case id_am_error: | ||
1019 | case id_crc_error: | ||
1020 | case data_am_error: | ||
1021 | case overrun_error: | ||
1022 | update_history(cause); | ||
1023 | determine_progress(buff, cause, in[5]); | ||
1024 | skip = find_resume_point(buff); | ||
1025 | retry_sector(buff, fdc_mode, skip); | ||
1026 | break; | ||
1027 | default: | ||
1028 | if (in[1] & 0x02) { | ||
1029 | TRACE(ft_t_err, "media not writable"); | ||
1030 | } else { | ||
1031 | TRACE(ft_t_bug, "unforeseen write error"); | ||
1032 | } | ||
1033 | fdc_mode = fdc_idle; | ||
1034 | break; | ||
1035 | } | ||
1036 | break; /* fdc_deleting || fdc_writing_data */ | ||
1037 | case fdc_formatting: | ||
1038 | /* The interrupt comes after formatting a segment. We then | ||
1039 | * have to set up QUICKLY for the next segment. But | ||
1040 | * afterwards, there is plenty of time. | ||
1041 | */ | ||
1042 | switch (cause) { | ||
1043 | case no_error: | ||
1044 | /* would like to keep most of the formatting stuff | ||
1045 | * outside the isr code, but timing is too critical | ||
1046 | */ | ||
1047 | if (determine_fmt_progress(buff, cause) >= 0) { | ||
1048 | continue_formatting(buff); | ||
1049 | } | ||
1050 | break; | ||
1051 | case no_data_error: | ||
1052 | case id_am_error: | ||
1053 | case id_crc_error: | ||
1054 | case data_am_error: | ||
1055 | case overrun_error: | ||
1056 | default: | ||
1057 | determine_fmt_progress(buff, cause); | ||
1058 | update_history(cause); | ||
1059 | if (in[1] & 0x02) { | ||
1060 | TRACE(ft_t_err, "media not writable"); | ||
1061 | } else { | ||
1062 | TRACE(ft_t_bug, "unforeseen write error"); | ||
1063 | } | ||
1064 | break; | ||
1065 | } /* cause */ | ||
1066 | break; | ||
1067 | default: | ||
1068 | TRACE(ft_t_warn, "Warning: unexpected irq during: %s", | ||
1069 | fdc_mode_txt(fdc_mode)); | ||
1070 | fdc_mode = fdc_idle; | ||
1071 | break; | ||
1072 | } | ||
1073 | TRACE_EXIT; | ||
1074 | } | ||
1075 | |||
1076 | /* FDC interrupt service routine. | ||
1077 | */ | ||
1078 | void fdc_isr(void) | ||
1079 | { | ||
1080 | static int isr_active; | ||
1081 | #ifdef TESTING | ||
1082 | unsigned int t0 = ftape_timestamp(); | ||
1083 | #endif | ||
1084 | TRACE_FUN(ft_t_any); | ||
1085 | |||
1086 | if (isr_active++) { | ||
1087 | --isr_active; | ||
1088 | TRACE(ft_t_bug, "BUG: nested interrupt, not good !"); | ||
1089 | *fdc.hook = fdc_isr; /* hook our handler into the fdc | ||
1090 | * code again | ||
1091 | */ | ||
1092 | TRACE_EXIT; | ||
1093 | } | ||
1094 | sti(); | ||
1095 | if (inb_p(fdc.msr) & FDC_BUSY) { /* Entering Result Phase */ | ||
1096 | ft_hide_interrupt = 0; | ||
1097 | handle_fdc_busy(ftape_get_buffer(ft_queue_head)); | ||
1098 | if (ft_runner_status == do_abort) { | ||
1099 | /* cease operation, remember tape position | ||
1100 | */ | ||
1101 | TRACE(ft_t_flow, "runner aborting"); | ||
1102 | ft_runner_status = aborting; | ||
1103 | ++ft_expected_stray_interrupts; | ||
1104 | } | ||
1105 | } else { /* !FDC_BUSY */ | ||
1106 | /* clear interrupt, cause should be gotten by issuing | ||
1107 | * a Sense Interrupt Status command. | ||
1108 | */ | ||
1109 | if (fdc_mode == fdc_recalibrating || fdc_mode == fdc_seeking) { | ||
1110 | if (ft_hide_interrupt) { | ||
1111 | int st0; | ||
1112 | int pcn; | ||
1113 | |||
1114 | if (fdc_sense_interrupt_status(&st0, &pcn) < 0) | ||
1115 | TRACE(ft_t_err, | ||
1116 | "sense interrupt status failed"); | ||
1117 | ftape_current_cylinder = pcn; | ||
1118 | TRACE(ft_t_flow, "handled hidden interrupt"); | ||
1119 | } | ||
1120 | ft_seek_completed = 1; | ||
1121 | fdc_mode = fdc_idle; | ||
1122 | } else if (!waitqueue_active(&ftape_wait_intr)) { | ||
1123 | if (ft_expected_stray_interrupts == 0) { | ||
1124 | TRACE(ft_t_warn, "unexpected stray interrupt"); | ||
1125 | } else { | ||
1126 | TRACE(ft_t_flow, "expected stray interrupt"); | ||
1127 | --ft_expected_stray_interrupts; | ||
1128 | } | ||
1129 | } else { | ||
1130 | if (fdc_mode == fdc_reading_data || | ||
1131 | fdc_mode == fdc_verifying || | ||
1132 | fdc_mode == fdc_writing_data || | ||
1133 | fdc_mode == fdc_deleting || | ||
1134 | fdc_mode == fdc_formatting || | ||
1135 | fdc_mode == fdc_reading_id) { | ||
1136 | if (inb_p(fdc.msr) & FDC_BUSY) { | ||
1137 | TRACE(ft_t_bug, | ||
1138 | "***** FDC failure, busy too late"); | ||
1139 | } else { | ||
1140 | TRACE(ft_t_bug, | ||
1141 | "***** FDC failure, no busy"); | ||
1142 | } | ||
1143 | } else { | ||
1144 | TRACE(ft_t_fdc_dma, "awaited stray interrupt"); | ||
1145 | } | ||
1146 | } | ||
1147 | ft_hide_interrupt = 0; | ||
1148 | } | ||
1149 | /* Handle sleep code. | ||
1150 | */ | ||
1151 | if (!ft_hide_interrupt) { | ||
1152 | ft_interrupt_seen ++; | ||
1153 | if (waitqueue_active(&ftape_wait_intr)) { | ||
1154 | wake_up_interruptible(&ftape_wait_intr); | ||
1155 | } | ||
1156 | } else { | ||
1157 | TRACE(ft_t_flow, "hiding interrupt while %s", | ||
1158 | waitqueue_active(&ftape_wait_intr) ? "waiting":"active"); | ||
1159 | } | ||
1160 | #ifdef TESTING | ||
1161 | t0 = ftape_timediff(t0, ftape_timestamp()); | ||
1162 | if (t0 >= 1000) { | ||
1163 | /* only tell us about long calls */ | ||
1164 | TRACE(ft_t_noise, "isr() duration: %5d usec", t0); | ||
1165 | } | ||
1166 | #endif | ||
1167 | *fdc.hook = fdc_isr; /* hook our handler into the fdc code again */ | ||
1168 | --isr_active; | ||
1169 | TRACE_EXIT; | ||
1170 | } | ||
diff --git a/drivers/char/ftape/lowlevel/fdc-isr.h b/drivers/char/ftape/lowlevel/fdc-isr.h deleted file mode 100644 index 065aa978942d..000000000000 --- a/drivers/char/ftape/lowlevel/fdc-isr.h +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | #ifndef _FDC_ISR_H | ||
2 | #define _FDC_ISR_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fdc-isr.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:07 $ | ||
26 | * | ||
27 | * This file declares the global variables necessary to | ||
28 | * synchronize the interrupt service routine (isr) with the | ||
29 | * remainder of the QIC-40/80/3010/3020 floppy-tape driver | ||
30 | * "ftape" for Linux. | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * fdc-isr.c defined public variables | ||
35 | */ | ||
36 | extern volatile int ft_expected_stray_interrupts; /* masks stray interrupts */ | ||
37 | extern volatile int ft_seek_completed; /* flag set by isr */ | ||
38 | extern volatile int ft_interrupt_seen; /* flag set by isr */ | ||
39 | extern volatile int ft_hide_interrupt; /* flag set by isr */ | ||
40 | |||
41 | /* | ||
42 | * fdc-io.c defined public functions | ||
43 | */ | ||
44 | extern void fdc_isr(void); | ||
45 | |||
46 | /* | ||
47 | * A kernel hook that steals one interrupt from the floppy | ||
48 | * driver (Should be fixed when the new fdc driver gets ready) | ||
49 | * See the linux kernel source files: | ||
50 | * drivers/block/floppy.c & drivers/block/blk.h | ||
51 | * for the details. | ||
52 | */ | ||
53 | extern void (*do_floppy) (void); | ||
54 | |||
55 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-bsm.c b/drivers/char/ftape/lowlevel/ftape-bsm.c deleted file mode 100644 index d1a301cc344f..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-bsm.c +++ /dev/null | |||
@@ -1,491 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1994-1996 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-bsm.c,v $ | ||
21 | * $Revision: 1.3 $ | ||
22 | * $Date: 1997/10/05 19:15:15 $ | ||
23 | * | ||
24 | * This file contains the bad-sector map handling code for | ||
25 | * the QIC-117 floppy tape driver for Linux. | ||
26 | * QIC-40, QIC-80, QIC-3010 and QIC-3020 maps are implemented. | ||
27 | */ | ||
28 | |||
29 | #include <linux/string.h> | ||
30 | |||
31 | #include <linux/ftape.h> | ||
32 | #include "../lowlevel/ftape-tracing.h" | ||
33 | #include "../lowlevel/ftape-bsm.h" | ||
34 | #include "../lowlevel/ftape-ctl.h" | ||
35 | #include "../lowlevel/ftape-rw.h" | ||
36 | |||
37 | /* Global vars. | ||
38 | */ | ||
39 | |||
40 | /* Local vars. | ||
41 | */ | ||
42 | static __u8 *bad_sector_map; | ||
43 | static SectorCount *bsm_hash_ptr; | ||
44 | |||
45 | typedef enum { | ||
46 | forward, backward | ||
47 | } mode_type; | ||
48 | |||
49 | #if 0 | ||
50 | static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map); | ||
51 | #endif | ||
52 | |||
53 | #if 0 | ||
54 | /* fix_tape converts a normal QIC-80 tape into a 'wide' tape. | ||
55 | * For testing purposes only ! | ||
56 | */ | ||
57 | void fix_tape(__u8 * buffer, ft_format_type new_code) | ||
58 | { | ||
59 | static __u8 list[BAD_SECTOR_MAP_SIZE]; | ||
60 | SectorMap *src_ptr = (SectorMap *) list; | ||
61 | __u8 *dst_ptr = bad_sector_map; | ||
62 | SectorMap map; | ||
63 | unsigned int sector = 1; | ||
64 | int i; | ||
65 | |||
66 | if (format_code != fmt_var && format_code != fmt_big) { | ||
67 | memcpy(list, bad_sector_map, sizeof(list)); | ||
68 | memset(bad_sector_map, 0, sizeof(bad_sector_map)); | ||
69 | while ((__u8 *) src_ptr - list < sizeof(list)) { | ||
70 | map = *src_ptr++; | ||
71 | if (map == EMPTY_SEGMENT) { | ||
72 | *(SectorMap *) dst_ptr = 0x800000 + sector; | ||
73 | dst_ptr += 3; | ||
74 | sector += SECTORS_PER_SEGMENT; | ||
75 | } else { | ||
76 | for (i = 0; i < SECTORS_PER_SEGMENT; ++i) { | ||
77 | if (map & 1) { | ||
78 | *(SewctorMap *) dst_ptr = sector; | ||
79 | dst_ptr += 3; | ||
80 | } | ||
81 | map >>= 1; | ||
82 | ++sector; | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | bad_sector_map_changed = 1; | ||
88 | *(buffer + 4) = new_code; /* put new format code */ | ||
89 | if (format_code != fmt_var && new_code == fmt_big) { | ||
90 | PUT4(buffer, FT_6_HSEG_1, (__u32)GET2(buffer, 6)); | ||
91 | PUT4(buffer, FT_6_HSEG_2, (__u32)GET2(buffer, 8)); | ||
92 | PUT4(buffer, FT_6_FRST_SEG, (__u32)GET2(buffer, 10)); | ||
93 | PUT4(buffer, FT_6_LAST_SEG, (__u32)GET2(buffer, 12)); | ||
94 | memset(buffer+6, '\0', 8); | ||
95 | } | ||
96 | format_code = new_code; | ||
97 | } | ||
98 | |||
99 | #endif | ||
100 | |||
101 | /* given buffer that contains a header segment, find the end of | ||
102 | * of the bsm list | ||
103 | */ | ||
104 | __u8 * ftape_find_end_of_bsm_list(__u8 * address) | ||
105 | { | ||
106 | __u8 *ptr = address + FT_HEADER_END; /* start of bsm list */ | ||
107 | __u8 *limit = address + FT_SEGMENT_SIZE; | ||
108 | while (ptr + 2 < limit) { | ||
109 | if (ptr[0] || ptr[1] || ptr[2]) { | ||
110 | ptr += 3; | ||
111 | } else { | ||
112 | return ptr; | ||
113 | } | ||
114 | } | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | static inline void put_sector(SectorCount *ptr, unsigned int sector) | ||
119 | { | ||
120 | ptr->bytes[0] = sector & 0xff; | ||
121 | sector >>= 8; | ||
122 | ptr->bytes[1] = sector & 0xff; | ||
123 | sector >>= 8; | ||
124 | ptr->bytes[2] = sector & 0xff; | ||
125 | } | ||
126 | |||
127 | static inline unsigned int get_sector(SectorCount *ptr) | ||
128 | { | ||
129 | #if 1 | ||
130 | unsigned int sector; | ||
131 | |||
132 | sector = ptr->bytes[0]; | ||
133 | sector += ptr->bytes[1] << 8; | ||
134 | sector += ptr->bytes[2] << 16; | ||
135 | |||
136 | return sector; | ||
137 | #else | ||
138 | /* GET4 gets the next four bytes in Intel little endian order | ||
139 | * and converts them to host byte order and handles unaligned | ||
140 | * access. | ||
141 | */ | ||
142 | return (GET4(ptr, 0) & 0x00ffffff); /* back to host byte order */ | ||
143 | #endif | ||
144 | } | ||
145 | |||
146 | static void bsm_debug_fake(void) | ||
147 | { | ||
148 | /* for testing of bad sector handling at end of tape | ||
149 | */ | ||
150 | #if 0 | ||
151 | ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 3, | ||
152 | 0x000003e0; | ||
153 | ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 2, | ||
154 | 0xff3fffff; | ||
155 | ftape_put_bad_sector_entry(segments_per_track * tracks_per_tape - 1, | ||
156 | 0xffffe000; | ||
157 | #endif | ||
158 | /* Enable to test bad sector handling | ||
159 | */ | ||
160 | #if 0 | ||
161 | ftape_put_bad_sector_entry(30, 0xfffffffe) | ||
162 | ftape_put_bad_sector_entry(32, 0x7fffffff); | ||
163 | ftape_put_bad_sector_entry(34, 0xfffeffff); | ||
164 | ftape_put_bad_sector_entry(36, 0x55555555); | ||
165 | ftape_put_bad_sector_entry(38, 0xffffffff); | ||
166 | ftape_put_bad_sector_entry(50, 0xffff0000); | ||
167 | ftape_put_bad_sector_entry(51, 0xffffffff); | ||
168 | ftape_put_bad_sector_entry(52, 0xffffffff); | ||
169 | ftape_put_bad_sector_entry(53, 0x0000ffff); | ||
170 | #endif | ||
171 | /* Enable when testing multiple volume tar dumps. | ||
172 | */ | ||
173 | #if 0 | ||
174 | { | ||
175 | int i; | ||
176 | |||
177 | for (i = ft_first_data_segment; | ||
178 | i <= ft_last_data_segment - 7; ++i) { | ||
179 | ftape_put_bad_sector_entry(i, EMPTY_SEGMENT); | ||
180 | } | ||
181 | } | ||
182 | #endif | ||
183 | /* Enable when testing bit positions in *_error_map | ||
184 | */ | ||
185 | #if 0 | ||
186 | { | ||
187 | int i; | ||
188 | |||
189 | for (i = first_data_segment; i <= last_data_segment; ++i) { | ||
190 | ftape_put_bad_sector_entry(i, | ||
191 | ftape_get_bad_sector_entry(i) | ||
192 | | 0x00ff00ff); | ||
193 | } | ||
194 | } | ||
195 | #endif | ||
196 | } | ||
197 | |||
198 | static void print_bad_sector_map(void) | ||
199 | { | ||
200 | unsigned int good_sectors; | ||
201 | unsigned int total_bad = 0; | ||
202 | int i; | ||
203 | TRACE_FUN(ft_t_flow); | ||
204 | |||
205 | if (ft_format_code == fmt_big || | ||
206 | ft_format_code == fmt_var || | ||
207 | ft_format_code == fmt_1100ft) { | ||
208 | SectorCount *ptr = (SectorCount *)bad_sector_map; | ||
209 | unsigned int sector; | ||
210 | __u16 *ptr16; | ||
211 | |||
212 | while((sector = get_sector(ptr++)) != 0) { | ||
213 | if ((ft_format_code == fmt_big || | ||
214 | ft_format_code == fmt_var) && | ||
215 | sector & 0x800000) { | ||
216 | total_bad += FT_SECTORS_PER_SEGMENT - 3; | ||
217 | TRACE(ft_t_noise, "bad segment at sector: %6d", | ||
218 | sector & 0x7fffff); | ||
219 | } else { | ||
220 | ++total_bad; | ||
221 | TRACE(ft_t_noise, "bad sector: %6d", sector); | ||
222 | } | ||
223 | } | ||
224 | /* Display old ftape's end-of-file marks | ||
225 | */ | ||
226 | ptr16 = (__u16*)ptr; | ||
227 | while ((sector = get_unaligned(ptr16++)) != 0) { | ||
228 | TRACE(ft_t_noise, "Old ftape eof mark: %4d/%2d", | ||
229 | sector, get_unaligned(ptr16++)); | ||
230 | } | ||
231 | } else { /* fixed size format */ | ||
232 | for (i = ft_first_data_segment; | ||
233 | i < (int)(ft_segments_per_track * ft_tracks_per_tape); ++i) { | ||
234 | SectorMap map = ((SectorMap *) bad_sector_map)[i]; | ||
235 | |||
236 | if (map) { | ||
237 | TRACE(ft_t_noise, | ||
238 | "bsm for segment %4d: 0x%08x", i, (unsigned int)map); | ||
239 | total_bad += ((map == EMPTY_SEGMENT) | ||
240 | ? FT_SECTORS_PER_SEGMENT - 3 | ||
241 | : count_ones(map)); | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | good_sectors = | ||
246 | ((ft_segments_per_track * ft_tracks_per_tape - ft_first_data_segment) | ||
247 | * (FT_SECTORS_PER_SEGMENT - 3)) - total_bad; | ||
248 | TRACE(ft_t_info, "%d Kb usable on this tape", good_sectors); | ||
249 | if (total_bad == 0) { | ||
250 | TRACE(ft_t_info, | ||
251 | "WARNING: this tape has no bad blocks registered !"); | ||
252 | } else { | ||
253 | TRACE(ft_t_info, "%d bad sectors", total_bad); | ||
254 | } | ||
255 | TRACE_EXIT; | ||
256 | } | ||
257 | |||
258 | |||
259 | void ftape_extract_bad_sector_map(__u8 * buffer) | ||
260 | { | ||
261 | TRACE_FUN(ft_t_any); | ||
262 | |||
263 | /* Fill the bad sector map with the contents of buffer. | ||
264 | */ | ||
265 | if (ft_format_code == fmt_var || ft_format_code == fmt_big) { | ||
266 | /* QIC-3010/3020 and wide QIC-80 tapes no longer have a failed | ||
267 | * sector log but use this area to extend the bad sector map. | ||
268 | */ | ||
269 | bad_sector_map = &buffer[FT_HEADER_END]; | ||
270 | } else { | ||
271 | /* non-wide QIC-80 tapes have a failed sector log area that | ||
272 | * mustn't be included in the bad sector map. | ||
273 | */ | ||
274 | bad_sector_map = &buffer[FT_FSL + FT_FSL_SIZE]; | ||
275 | } | ||
276 | if (ft_format_code == fmt_1100ft || | ||
277 | ft_format_code == fmt_var || | ||
278 | ft_format_code == fmt_big) { | ||
279 | bsm_hash_ptr = (SectorCount *)bad_sector_map; | ||
280 | } else { | ||
281 | bsm_hash_ptr = NULL; | ||
282 | } | ||
283 | bsm_debug_fake(); | ||
284 | if (TRACE_LEVEL >= ft_t_info) { | ||
285 | print_bad_sector_map(); | ||
286 | } | ||
287 | TRACE_EXIT; | ||
288 | } | ||
289 | |||
290 | static inline SectorMap cvt2map(unsigned int sector) | ||
291 | { | ||
292 | return 1 << (((sector & 0x7fffff) - 1) % FT_SECTORS_PER_SEGMENT); | ||
293 | } | ||
294 | |||
295 | static inline int cvt2segment(unsigned int sector) | ||
296 | { | ||
297 | return ((sector & 0x7fffff) - 1) / FT_SECTORS_PER_SEGMENT; | ||
298 | } | ||
299 | |||
300 | static int forward_seek_entry(int segment_id, | ||
301 | SectorCount **ptr, | ||
302 | SectorMap *map) | ||
303 | { | ||
304 | unsigned int sector; | ||
305 | int segment; | ||
306 | |||
307 | do { | ||
308 | sector = get_sector((*ptr)++); | ||
309 | segment = cvt2segment(sector); | ||
310 | } while (sector != 0 && segment < segment_id); | ||
311 | (*ptr) --; /* point to first sector >= segment_id */ | ||
312 | /* Get all sectors in segment_id | ||
313 | */ | ||
314 | if (sector == 0 || segment != segment_id) { | ||
315 | *map = 0; | ||
316 | return 0; | ||
317 | } else if ((sector & 0x800000) && | ||
318 | (ft_format_code == fmt_var || ft_format_code == fmt_big)) { | ||
319 | *map = EMPTY_SEGMENT; | ||
320 | return FT_SECTORS_PER_SEGMENT; | ||
321 | } else { | ||
322 | int count = 1; | ||
323 | SectorCount *tmp_ptr = (*ptr) + 1; | ||
324 | |||
325 | *map = cvt2map(sector); | ||
326 | while ((sector = get_sector(tmp_ptr++)) != 0 && | ||
327 | (segment = cvt2segment(sector)) == segment_id) { | ||
328 | *map |= cvt2map(sector); | ||
329 | ++count; | ||
330 | } | ||
331 | return count; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | static int backwards_seek_entry(int segment_id, | ||
336 | SectorCount **ptr, | ||
337 | SectorMap *map) | ||
338 | { | ||
339 | unsigned int sector; | ||
340 | int segment; /* max unsigned int */ | ||
341 | |||
342 | if (*ptr <= (SectorCount *)bad_sector_map) { | ||
343 | *map = 0; | ||
344 | return 0; | ||
345 | } | ||
346 | do { | ||
347 | sector = get_sector(--(*ptr)); | ||
348 | segment = cvt2segment(sector); | ||
349 | } while (*ptr > (SectorCount *)bad_sector_map && segment > segment_id); | ||
350 | if (segment > segment_id) { /* at start of list, no entry found */ | ||
351 | *map = 0; | ||
352 | return 0; | ||
353 | } else if (segment < segment_id) { | ||
354 | /* before smaller entry, adjust for overshoot */ | ||
355 | (*ptr) ++; | ||
356 | *map = 0; | ||
357 | return 0; | ||
358 | } else if ((sector & 0x800000) && | ||
359 | (ft_format_code == fmt_big || ft_format_code == fmt_var)) { | ||
360 | *map = EMPTY_SEGMENT; | ||
361 | return FT_SECTORS_PER_SEGMENT; | ||
362 | } else { /* get all sectors in segment_id */ | ||
363 | int count = 1; | ||
364 | |||
365 | *map = cvt2map(sector); | ||
366 | while(*ptr > (SectorCount *)bad_sector_map) { | ||
367 | sector = get_sector(--(*ptr)); | ||
368 | segment = cvt2segment(sector); | ||
369 | if (segment != segment_id) { | ||
370 | break; | ||
371 | } | ||
372 | *map |= cvt2map(sector); | ||
373 | ++count; | ||
374 | } | ||
375 | if (segment < segment_id) { | ||
376 | (*ptr) ++; | ||
377 | } | ||
378 | return count; | ||
379 | } | ||
380 | } | ||
381 | |||
382 | #if 0 | ||
383 | static void ftape_put_bad_sector_entry(int segment_id, SectorMap new_map) | ||
384 | { | ||
385 | SectorCount *ptr = (SectorCount *)bad_sector_map; | ||
386 | int count; | ||
387 | int new_count; | ||
388 | SectorMap map; | ||
389 | TRACE_FUN(ft_t_any); | ||
390 | |||
391 | if (ft_format_code == fmt_1100ft || | ||
392 | ft_format_code == fmt_var || | ||
393 | ft_format_code == fmt_big) { | ||
394 | count = forward_seek_entry(segment_id, &ptr, &map); | ||
395 | new_count = count_ones(new_map); | ||
396 | /* If format code == 4 put empty segment instead of 32 | ||
397 | * bad sectors. | ||
398 | */ | ||
399 | if (ft_format_code == fmt_var || ft_format_code == fmt_big) { | ||
400 | if (new_count == FT_SECTORS_PER_SEGMENT) { | ||
401 | new_count = 1; | ||
402 | } | ||
403 | if (count == FT_SECTORS_PER_SEGMENT) { | ||
404 | count = 1; | ||
405 | } | ||
406 | } | ||
407 | if (count != new_count) { | ||
408 | /* insert (or delete if < 0) new_count - count | ||
409 | * entries. Move trailing part of list | ||
410 | * including terminating 0. | ||
411 | */ | ||
412 | SectorCount *hi_ptr = ptr; | ||
413 | |||
414 | do { | ||
415 | } while (get_sector(hi_ptr++) != 0); | ||
416 | /* Note: ptr is of type byte *, and each bad sector | ||
417 | * consumes 3 bytes. | ||
418 | */ | ||
419 | memmove(ptr + new_count, ptr + count, | ||
420 | (size_t)(hi_ptr - (ptr + count))*sizeof(SectorCount)); | ||
421 | } | ||
422 | TRACE(ft_t_noise, "putting map 0x%08x at %p, segment %d", | ||
423 | (unsigned int)new_map, ptr, segment_id); | ||
424 | if (new_count == 1 && new_map == EMPTY_SEGMENT) { | ||
425 | put_sector(ptr++, (0x800001 + | ||
426 | segment_id * | ||
427 | FT_SECTORS_PER_SEGMENT)); | ||
428 | } else { | ||
429 | int i = 0; | ||
430 | |||
431 | while (new_map) { | ||
432 | if (new_map & 1) { | ||
433 | put_sector(ptr++, | ||
434 | 1 + segment_id * | ||
435 | FT_SECTORS_PER_SEGMENT + i); | ||
436 | } | ||
437 | ++i; | ||
438 | new_map >>= 1; | ||
439 | } | ||
440 | } | ||
441 | } else { | ||
442 | ((SectorMap *) bad_sector_map)[segment_id] = new_map; | ||
443 | } | ||
444 | TRACE_EXIT; | ||
445 | } | ||
446 | #endif /* 0 */ | ||
447 | |||
448 | SectorMap ftape_get_bad_sector_entry(int segment_id) | ||
449 | { | ||
450 | if (ft_used_header_segment == -1) { | ||
451 | /* When reading header segment we'll need a blank map. | ||
452 | */ | ||
453 | return 0; | ||
454 | } else if (bsm_hash_ptr != NULL) { | ||
455 | /* Invariants: | ||
456 | * map - mask value returned on last call. | ||
457 | * bsm_hash_ptr - points to first sector greater or equal to | ||
458 | * first sector in last_referenced segment. | ||
459 | * last_referenced - segment id used in the last call, | ||
460 | * sector and map belong to this id. | ||
461 | * This code is designed for sequential access and retries. | ||
462 | * For true random access it may have to be redesigned. | ||
463 | */ | ||
464 | static int last_reference = -1; | ||
465 | static SectorMap map; | ||
466 | |||
467 | if (segment_id > last_reference) { | ||
468 | /* Skip all sectors before segment_id | ||
469 | */ | ||
470 | forward_seek_entry(segment_id, &bsm_hash_ptr, &map); | ||
471 | } else if (segment_id < last_reference) { | ||
472 | /* Skip backwards until begin of buffer or | ||
473 | * first sector in segment_id | ||
474 | */ | ||
475 | backwards_seek_entry(segment_id, &bsm_hash_ptr, &map); | ||
476 | } /* segment_id == last_reference : keep map */ | ||
477 | last_reference = segment_id; | ||
478 | return map; | ||
479 | } else { | ||
480 | return ((SectorMap *) bad_sector_map)[segment_id]; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | /* This is simply here to prevent us from overwriting other kernel | ||
485 | * data. Writes will result in NULL Pointer dereference. | ||
486 | */ | ||
487 | void ftape_init_bsm(void) | ||
488 | { | ||
489 | bad_sector_map = NULL; | ||
490 | bsm_hash_ptr = NULL; | ||
491 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-bsm.h b/drivers/char/ftape/lowlevel/ftape-bsm.h deleted file mode 100644 index ed45465af4d4..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-bsm.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | #ifndef _FTAPE_BSM_H | ||
2 | #define _FTAPE_BSM_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1994-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-bsm.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:07 $ | ||
26 | * | ||
27 | * This file contains definitions for the bad sector map handling | ||
28 | * routines for the QIC-117 floppy-tape driver for Linux. | ||
29 | */ | ||
30 | |||
31 | #include <linux/ftape.h> | ||
32 | #include <linux/ftape-header-segment.h> | ||
33 | |||
34 | #define EMPTY_SEGMENT (0xffffffff) | ||
35 | #define FAKE_SEGMENT (0xfffffffe) | ||
36 | |||
37 | /* maximum (format code 4) bad sector map size (bytes). | ||
38 | */ | ||
39 | #define BAD_SECTOR_MAP_SIZE (29 * SECTOR_SIZE - 256) | ||
40 | |||
41 | /* format code 4 bad sector entry, ftape uses this | ||
42 | * internally for all format codes | ||
43 | */ | ||
44 | typedef __u32 SectorMap; | ||
45 | /* variable and 1100 ft bad sector map entry. These three bytes represent | ||
46 | * a single sector address measured from BOT. | ||
47 | */ | ||
48 | typedef struct NewSectorMap { | ||
49 | __u8 bytes[3]; | ||
50 | } SectorCount; | ||
51 | |||
52 | |||
53 | /* | ||
54 | * ftape-bsm.c defined global vars. | ||
55 | */ | ||
56 | |||
57 | /* | ||
58 | * ftape-bsm.c defined global functions. | ||
59 | */ | ||
60 | extern void update_bad_sector_map(__u8 * buffer); | ||
61 | extern void ftape_extract_bad_sector_map(__u8 * buffer); | ||
62 | extern SectorMap ftape_get_bad_sector_entry(int segment_id); | ||
63 | extern __u8 *ftape_find_end_of_bsm_list(__u8 * address); | ||
64 | extern void ftape_init_bsm(void); | ||
65 | |||
66 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.c b/drivers/char/ftape/lowlevel/ftape-buffer.c deleted file mode 100644 index c706ff162771..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-buffer.c +++ /dev/null | |||
@@ -1,130 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $ | ||
20 | * $Revision: 1.3 $ | ||
21 | * $Date: 1997/10/16 23:33:11 $ | ||
22 | * | ||
23 | * This file contains the allocator/dealloctor for ftape's dynamic dma | ||
24 | * buffer. | ||
25 | */ | ||
26 | |||
27 | #include <linux/slab.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/mman.h> | ||
30 | #include <asm/dma.h> | ||
31 | |||
32 | #include <linux/ftape.h> | ||
33 | #include "../lowlevel/ftape-rw.h" | ||
34 | #include "../lowlevel/ftape-read.h" | ||
35 | #include "../lowlevel/ftape-tracing.h" | ||
36 | #include "../lowlevel/ftape-buffer.h" | ||
37 | |||
38 | /* DMA'able memory allocation stuff. | ||
39 | */ | ||
40 | |||
41 | static inline void *dmaalloc(size_t size) | ||
42 | { | ||
43 | unsigned long addr; | ||
44 | |||
45 | if (size == 0) { | ||
46 | return NULL; | ||
47 | } | ||
48 | addr = __get_dma_pages(GFP_KERNEL, get_order(size)); | ||
49 | if (addr) { | ||
50 | struct page *page; | ||
51 | |||
52 | for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++) | ||
53 | SetPageReserved(page); | ||
54 | } | ||
55 | return (void *)addr; | ||
56 | } | ||
57 | |||
58 | static inline void dmafree(void *addr, size_t size) | ||
59 | { | ||
60 | if (size > 0) { | ||
61 | struct page *page; | ||
62 | |||
63 | for (page = virt_to_page((unsigned long)addr); | ||
64 | page < virt_to_page((unsigned long)addr+size); page++) | ||
65 | ClearPageReserved(page); | ||
66 | free_pages((unsigned long) addr, get_order(size)); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | static int add_one_buffer(void) | ||
71 | { | ||
72 | TRACE_FUN(ft_t_flow); | ||
73 | |||
74 | if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) { | ||
75 | TRACE_EXIT -ENOMEM; | ||
76 | } | ||
77 | ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL); | ||
78 | if (ft_buffer[ft_nr_buffers] == NULL) { | ||
79 | TRACE_EXIT -ENOMEM; | ||
80 | } | ||
81 | memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct)); | ||
82 | ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE); | ||
83 | if (ft_buffer[ft_nr_buffers]->address == NULL) { | ||
84 | kfree(ft_buffer[ft_nr_buffers]); | ||
85 | ft_buffer[ft_nr_buffers] = NULL; | ||
86 | TRACE_EXIT -ENOMEM; | ||
87 | } | ||
88 | ft_nr_buffers ++; | ||
89 | TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p", | ||
90 | ft_nr_buffers, | ||
91 | ft_buffer[ft_nr_buffers-1], | ||
92 | ft_buffer[ft_nr_buffers-1]->address); | ||
93 | TRACE_EXIT 0; | ||
94 | } | ||
95 | |||
96 | static void del_one_buffer(void) | ||
97 | { | ||
98 | TRACE_FUN(ft_t_flow); | ||
99 | if (ft_nr_buffers > 0) { | ||
100 | TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p", | ||
101 | ft_nr_buffers, | ||
102 | ft_buffer[ft_nr_buffers-1], | ||
103 | ft_buffer[ft_nr_buffers-1]->address); | ||
104 | ft_nr_buffers --; | ||
105 | dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE); | ||
106 | kfree(ft_buffer[ft_nr_buffers]); | ||
107 | ft_buffer[ft_nr_buffers] = NULL; | ||
108 | } | ||
109 | TRACE_EXIT; | ||
110 | } | ||
111 | |||
112 | int ftape_set_nr_buffers(int cnt) | ||
113 | { | ||
114 | int delta = cnt - ft_nr_buffers; | ||
115 | TRACE_FUN(ft_t_flow); | ||
116 | |||
117 | if (delta > 0) { | ||
118 | while (delta--) { | ||
119 | if (add_one_buffer() < 0) { | ||
120 | TRACE_EXIT -ENOMEM; | ||
121 | } | ||
122 | } | ||
123 | } else if (delta < 0) { | ||
124 | while (delta++) { | ||
125 | del_one_buffer(); | ||
126 | } | ||
127 | } | ||
128 | ftape_zap_read_buffers(); | ||
129 | TRACE_EXIT 0; | ||
130 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.h b/drivers/char/ftape/lowlevel/ftape-buffer.h deleted file mode 100644 index eec99cee8f82..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-buffer.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | #ifndef _FTAPE_BUFFER_H | ||
2 | #define _FTAPE_BUFFER_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1997 Claus-Justus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:18:08 $ | ||
25 | * | ||
26 | * This file contains the allocator/dealloctor for ftape's dynamic dma | ||
27 | * buffer. | ||
28 | */ | ||
29 | |||
30 | extern int ftape_set_nr_buffers(int cnt); | ||
31 | |||
32 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c deleted file mode 100644 index 8e50bfd35a52..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-calibr.c +++ /dev/null | |||
@@ -1,275 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.c,v $ | ||
20 | * $Revision: 1.2 $ | ||
21 | * $Date: 1997/10/05 19:18:08 $ | ||
22 | * | ||
23 | * GP calibration routine for processor speed dependent | ||
24 | * functions. | ||
25 | */ | ||
26 | |||
27 | #include <linux/errno.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | #include <asm/system.h> | ||
30 | #include <asm/io.h> | ||
31 | #if defined(__alpha__) | ||
32 | # include <asm/hwrpb.h> | ||
33 | #elif defined(__x86_64__) | ||
34 | # include <asm/msr.h> | ||
35 | # include <asm/timex.h> | ||
36 | #elif defined(__i386__) | ||
37 | # include <linux/timex.h> | ||
38 | #endif | ||
39 | #include <linux/ftape.h> | ||
40 | #include "../lowlevel/ftape-tracing.h" | ||
41 | #include "../lowlevel/ftape-calibr.h" | ||
42 | #include "../lowlevel/fdc-io.h" | ||
43 | |||
44 | #undef DEBUG | ||
45 | |||
46 | #if !defined(__alpha__) && !defined(__i386__) && !defined(__x86_64__) | ||
47 | # error Ftape is not implemented for this architecture! | ||
48 | #endif | ||
49 | |||
50 | #if defined(__alpha__) || defined(__x86_64__) | ||
51 | static unsigned long ps_per_cycle = 0; | ||
52 | #endif | ||
53 | |||
54 | static spinlock_t calibr_lock; | ||
55 | |||
56 | /* | ||
57 | * Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is | ||
58 | * too slow for certain timeouts (and that clock doesn't even tick | ||
59 | * when interrupts are disabled). For that reason, the 8254 timer is | ||
60 | * used directly to implement fine-grained timeouts. However, on | ||
61 | * Alpha PCs, the 8254 is *not* used to implement the clock tick | ||
62 | * (which is 1024 Hz, normally) and the 8254 timer runs at some | ||
63 | * "random" frequency (it seems to run at 18Hz, but it's not safe to | ||
64 | * rely on this value). Instead, we use the Alpha's "rpcc" | ||
65 | * instruction to read cycle counts. As this is a 32 bit counter, | ||
66 | * it will overflow only once per 30 seconds (on a 200MHz machine), | ||
67 | * which is plenty. | ||
68 | */ | ||
69 | |||
70 | unsigned int ftape_timestamp(void) | ||
71 | { | ||
72 | #if defined(__alpha__) | ||
73 | unsigned long r; | ||
74 | |||
75 | asm volatile ("rpcc %0" : "=r" (r)); | ||
76 | return r; | ||
77 | #elif defined(__x86_64__) | ||
78 | unsigned long r; | ||
79 | rdtscl(r); | ||
80 | return r; | ||
81 | #elif defined(__i386__) | ||
82 | |||
83 | /* | ||
84 | * Note that there is some time between counter underflowing and jiffies | ||
85 | * increasing, so the code below won't always give correct output. | ||
86 | * -Vojtech | ||
87 | */ | ||
88 | |||
89 | unsigned long flags; | ||
90 | __u16 lo; | ||
91 | __u16 hi; | ||
92 | |||
93 | spin_lock_irqsave(&calibr_lock, flags); | ||
94 | outb_p(0x00, 0x43); /* latch the count ASAP */ | ||
95 | lo = inb_p(0x40); /* read the latched count */ | ||
96 | lo |= inb(0x40) << 8; | ||
97 | hi = jiffies; | ||
98 | spin_unlock_irqrestore(&calibr_lock, flags); | ||
99 | return ((hi + 1) * (unsigned int) LATCH) - lo; /* downcounter ! */ | ||
100 | #endif | ||
101 | } | ||
102 | |||
103 | static unsigned int short_ftape_timestamp(void) | ||
104 | { | ||
105 | #if defined(__alpha__) || defined(__x86_64__) | ||
106 | return ftape_timestamp(); | ||
107 | #elif defined(__i386__) | ||
108 | unsigned int count; | ||
109 | unsigned long flags; | ||
110 | |||
111 | spin_lock_irqsave(&calibr_lock, flags); | ||
112 | outb_p(0x00, 0x43); /* latch the count ASAP */ | ||
113 | count = inb_p(0x40); /* read the latched count */ | ||
114 | count |= inb(0x40) << 8; | ||
115 | spin_unlock_irqrestore(&calibr_lock, flags); | ||
116 | return (LATCH - count); /* normal: downcounter */ | ||
117 | #endif | ||
118 | } | ||
119 | |||
120 | static unsigned int diff(unsigned int t0, unsigned int t1) | ||
121 | { | ||
122 | #if defined(__alpha__) || defined(__x86_64__) | ||
123 | return (t1 - t0); | ||
124 | #elif defined(__i386__) | ||
125 | /* | ||
126 | * This is tricky: to work for both short and full ftape_timestamps | ||
127 | * we'll have to discriminate between these. | ||
128 | * If it _looks_ like short stamps with wrapping around we'll | ||
129 | * asume it are. This will generate a small error if it really | ||
130 | * was a (very large) delta from full ftape_timestamps. | ||
131 | */ | ||
132 | return (t1 <= t0 && t0 <= LATCH) ? t1 + LATCH - t0 : t1 - t0; | ||
133 | #endif | ||
134 | } | ||
135 | |||
136 | static unsigned int usecs(unsigned int count) | ||
137 | { | ||
138 | #if defined(__alpha__) || defined(__x86_64__) | ||
139 | return (ps_per_cycle * count) / 1000000UL; | ||
140 | #elif defined(__i386__) | ||
141 | return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100); | ||
142 | #endif | ||
143 | } | ||
144 | |||
145 | unsigned int ftape_timediff(unsigned int t0, unsigned int t1) | ||
146 | { | ||
147 | /* | ||
148 | * Calculate difference in usec for ftape_timestamp results t0 & t1. | ||
149 | * Note that on the i386 platform with short time-stamps, the | ||
150 | * maximum allowed timespan is 1/HZ or we'll lose ticks! | ||
151 | */ | ||
152 | return usecs(diff(t0, t1)); | ||
153 | } | ||
154 | |||
155 | /* To get an indication of the I/O performance, | ||
156 | * measure the duration of the inb() function. | ||
157 | */ | ||
158 | static void time_inb(void) | ||
159 | { | ||
160 | int i; | ||
161 | int t0, t1; | ||
162 | unsigned long flags; | ||
163 | int status; | ||
164 | TRACE_FUN(ft_t_any); | ||
165 | |||
166 | spin_lock_irqsave(&calibr_lock, flags); | ||
167 | t0 = short_ftape_timestamp(); | ||
168 | for (i = 0; i < 1000; ++i) { | ||
169 | status = inb(fdc.msr); | ||
170 | } | ||
171 | t1 = short_ftape_timestamp(); | ||
172 | spin_unlock_irqrestore(&calibr_lock, flags); | ||
173 | TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1)); | ||
174 | TRACE_EXIT; | ||
175 | } | ||
176 | |||
177 | static void init_clock(void) | ||
178 | { | ||
179 | TRACE_FUN(ft_t_any); | ||
180 | |||
181 | #if defined(__x86_64__) | ||
182 | ps_per_cycle = 1000000000UL / cpu_khz; | ||
183 | #elif defined(__alpha__) | ||
184 | extern struct hwrpb_struct *hwrpb; | ||
185 | ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq; | ||
186 | #endif | ||
187 | TRACE_EXIT; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Input: function taking int count as parameter. | ||
192 | * pointers to calculated calibration variables. | ||
193 | */ | ||
194 | void ftape_calibrate(char *name, | ||
195 | void (*fun) (unsigned int), | ||
196 | unsigned int *calibr_count, | ||
197 | unsigned int *calibr_time) | ||
198 | { | ||
199 | static int first_time = 1; | ||
200 | int i; | ||
201 | unsigned int tc = 0; | ||
202 | unsigned int count; | ||
203 | unsigned int time; | ||
204 | #if defined(__i386__) | ||
205 | unsigned int old_tc = 0; | ||
206 | unsigned int old_count = 1; | ||
207 | unsigned int old_time = 1; | ||
208 | #endif | ||
209 | TRACE_FUN(ft_t_flow); | ||
210 | |||
211 | if (first_time) { /* get idea of I/O performance */ | ||
212 | init_clock(); | ||
213 | time_inb(); | ||
214 | first_time = 0; | ||
215 | } | ||
216 | /* value of timeout must be set so that on very slow systems | ||
217 | * it will give a time less than one jiffy, and on | ||
218 | * very fast systems it'll give reasonable precision. | ||
219 | */ | ||
220 | |||
221 | count = 40; | ||
222 | for (i = 0; i < 15; ++i) { | ||
223 | unsigned int t0; | ||
224 | unsigned int t1; | ||
225 | unsigned int once; | ||
226 | unsigned int multiple; | ||
227 | unsigned long flags; | ||
228 | |||
229 | *calibr_count = | ||
230 | *calibr_time = count; /* set TC to 1 */ | ||
231 | spin_lock_irqsave(&calibr_lock, flags); | ||
232 | fun(0); /* dummy, get code into cache */ | ||
233 | t0 = short_ftape_timestamp(); | ||
234 | fun(0); /* overhead + one test */ | ||
235 | t1 = short_ftape_timestamp(); | ||
236 | once = diff(t0, t1); | ||
237 | t0 = short_ftape_timestamp(); | ||
238 | fun(count); /* overhead + count tests */ | ||
239 | t1 = short_ftape_timestamp(); | ||
240 | multiple = diff(t0, t1); | ||
241 | spin_unlock_irqrestore(&calibr_lock, flags); | ||
242 | time = ftape_timediff(0, multiple - once); | ||
243 | tc = (1000 * time) / (count - 1); | ||
244 | TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns", | ||
245 | usecs(once), count - 1, usecs(multiple), tc); | ||
246 | #if defined(__alpha__) || defined(__x86_64__) | ||
247 | /* | ||
248 | * Increase the calibration count exponentially until the | ||
249 | * calibration time exceeds 100 ms. | ||
250 | */ | ||
251 | if (time >= 100*1000) { | ||
252 | break; | ||
253 | } | ||
254 | #elif defined(__i386__) | ||
255 | /* | ||
256 | * increase the count until the resulting time nears 2/HZ, | ||
257 | * then the tc will drop sharply because we lose LATCH counts. | ||
258 | */ | ||
259 | if (tc <= old_tc / 2) { | ||
260 | time = old_time; | ||
261 | count = old_count; | ||
262 | break; | ||
263 | } | ||
264 | old_tc = tc; | ||
265 | old_count = count; | ||
266 | old_time = time; | ||
267 | #endif | ||
268 | count *= 2; | ||
269 | } | ||
270 | *calibr_count = count - 1; | ||
271 | *calibr_time = time; | ||
272 | TRACE(ft_t_info, "TC for `%s()' = %d nsec (at %d counts)", | ||
273 | name, (1000 * *calibr_time) / *calibr_count, *calibr_count); | ||
274 | TRACE_EXIT; | ||
275 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.h b/drivers/char/ftape/lowlevel/ftape-calibr.h deleted file mode 100644 index 0c7e75246c7d..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-calibr.h +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | #ifndef _FTAPE_CALIBR_H | ||
2 | #define _FTAPE_CALIBR_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-calibr.h,v $ | ||
23 | * $Revision: 1.1 $ | ||
24 | * $Date: 1997/09/19 09:05:26 $ | ||
25 | * | ||
26 | * This file contains a gp calibration routine for | ||
27 | * hardware dependent timeout functions. | ||
28 | */ | ||
29 | |||
30 | extern void ftape_calibrate(char *name, | ||
31 | void (*fun) (unsigned int), | ||
32 | unsigned int *calibr_count, | ||
33 | unsigned int *calibr_time); | ||
34 | extern unsigned int ftape_timestamp(void); | ||
35 | extern unsigned int ftape_timediff(unsigned int t0, unsigned int t1); | ||
36 | |||
37 | #endif /* _FTAPE_CALIBR_H */ | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.c b/drivers/char/ftape/lowlevel/ftape-ctl.c deleted file mode 100644 index 5d7c1ce92d59..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-ctl.c +++ /dev/null | |||
@@ -1,896 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
3 | * 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.c,v $ | ||
21 | * $Revision: 1.4 $ | ||
22 | * $Date: 1997/11/11 14:37:44 $ | ||
23 | * | ||
24 | * This file contains the non-read/write ftape functions for the | ||
25 | * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. | ||
26 | */ | ||
27 | |||
28 | #include <linux/errno.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/mman.h> | ||
31 | |||
32 | #include <linux/ftape.h> | ||
33 | #include <linux/qic117.h> | ||
34 | #include <asm/uaccess.h> | ||
35 | #include <asm/io.h> | ||
36 | |||
37 | /* ease porting between pre-2.4.x and later kernels */ | ||
38 | #define vma_get_pgoff(v) ((v)->vm_pgoff) | ||
39 | |||
40 | #include "../lowlevel/ftape-tracing.h" | ||
41 | #include "../lowlevel/ftape-io.h" | ||
42 | #include "../lowlevel/ftape-ctl.h" | ||
43 | #include "../lowlevel/ftape-write.h" | ||
44 | #include "../lowlevel/ftape-read.h" | ||
45 | #include "../lowlevel/ftape-rw.h" | ||
46 | #include "../lowlevel/ftape-bsm.h" | ||
47 | |||
48 | /* Global vars. | ||
49 | */ | ||
50 | ftape_info ftape_status = { | ||
51 | /* vendor information */ | ||
52 | { 0, }, /* drive type */ | ||
53 | /* data rates */ | ||
54 | 500, /* used data rate */ | ||
55 | 500, /* drive max rate */ | ||
56 | 500, /* fdc max rate */ | ||
57 | /* drive selection, either FTAPE_SEL_A/B/C/D */ | ||
58 | -1, /* drive selection */ | ||
59 | /* flags set after decode the drive and tape status */ | ||
60 | 0, /* formatted */ | ||
61 | 1, /* no tape */ | ||
62 | 1, /* write protected */ | ||
63 | 1, /* new tape */ | ||
64 | /* values of last queried drive/tape status and error */ | ||
65 | {{0,}}, /* last error code */ | ||
66 | {{0,}}, /* drive status, configuration, tape status */ | ||
67 | /* cartridge geometry */ | ||
68 | 20, /* tracks_per_tape */ | ||
69 | 102, /* segments_per_track */ | ||
70 | /* location of header segments, etc. */ | ||
71 | -1, /* used_header_segment */ | ||
72 | -1, /* header_segment_1 */ | ||
73 | -1, /* header_segment_2 */ | ||
74 | -1, /* first_data_segment */ | ||
75 | -1, /* last_data_segment */ | ||
76 | /* the format code as stored in the header segment */ | ||
77 | fmt_normal, /* format code */ | ||
78 | /* the default for the qic std: unknown */ | ||
79 | -1, | ||
80 | /* is tape running? */ | ||
81 | idle, /* runner_state */ | ||
82 | /* is tape reading/writing/verifying/formatting/deleting */ | ||
83 | idle, /* driver state */ | ||
84 | /* flags fatal hardware error */ | ||
85 | 1, /* failure */ | ||
86 | /* history record */ | ||
87 | { 0, } /* history record */ | ||
88 | }; | ||
89 | |||
90 | int ftape_segments_per_head = 1020; | ||
91 | int ftape_segments_per_cylinder = 4; | ||
92 | int ftape_init_drive_needed = 1; /* need to be global for ftape_reset_drive() | ||
93 | * in ftape-io.c | ||
94 | */ | ||
95 | |||
96 | /* Local vars. | ||
97 | */ | ||
98 | static const vendor_struct vendors[] = QIC117_VENDORS; | ||
99 | static const wakeup_method methods[] = WAKEUP_METHODS; | ||
100 | |||
101 | const ftape_info *ftape_get_status(void) | ||
102 | { | ||
103 | #if defined(STATUS_PARANOYA) | ||
104 | static ftape_info get_status; | ||
105 | |||
106 | get_status = ftape_status; | ||
107 | return &get_status; | ||
108 | #else | ||
109 | return &ftape_status; /* maybe return only a copy of it to assure | ||
110 | * read only access | ||
111 | */ | ||
112 | #endif | ||
113 | } | ||
114 | |||
115 | static int ftape_not_operational(int status) | ||
116 | { | ||
117 | /* return true if status indicates tape can not be used. | ||
118 | */ | ||
119 | return ((status ^ QIC_STATUS_CARTRIDGE_PRESENT) & | ||
120 | (QIC_STATUS_ERROR | | ||
121 | QIC_STATUS_CARTRIDGE_PRESENT | | ||
122 | QIC_STATUS_NEW_CARTRIDGE)); | ||
123 | } | ||
124 | |||
125 | int ftape_seek_to_eot(void) | ||
126 | { | ||
127 | int status; | ||
128 | TRACE_FUN(ft_t_any); | ||
129 | |||
130 | TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),); | ||
131 | while ((status & QIC_STATUS_AT_EOT) == 0) { | ||
132 | if (ftape_not_operational(status)) { | ||
133 | TRACE_EXIT -EIO; | ||
134 | } | ||
135 | TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_FORWARD, | ||
136 | ftape_timeout.rewind,&status),); | ||
137 | } | ||
138 | TRACE_EXIT 0; | ||
139 | } | ||
140 | |||
141 | int ftape_seek_to_bot(void) | ||
142 | { | ||
143 | int status; | ||
144 | TRACE_FUN(ft_t_any); | ||
145 | |||
146 | TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),); | ||
147 | while ((status & QIC_STATUS_AT_BOT) == 0) { | ||
148 | if (ftape_not_operational(status)) { | ||
149 | TRACE_EXIT -EIO; | ||
150 | } | ||
151 | TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_REVERSE, | ||
152 | ftape_timeout.rewind,&status),); | ||
153 | } | ||
154 | TRACE_EXIT 0; | ||
155 | } | ||
156 | |||
157 | static int ftape_new_cartridge(void) | ||
158 | { | ||
159 | ft_location.track = -1; /* force seek on first access */ | ||
160 | ftape_zap_read_buffers(); | ||
161 | ftape_zap_write_buffers(); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | int ftape_abort_operation(void) | ||
166 | { | ||
167 | int result = 0; | ||
168 | int status; | ||
169 | TRACE_FUN(ft_t_flow); | ||
170 | |||
171 | if (ft_runner_status == running) { | ||
172 | TRACE(ft_t_noise, "aborting runner, waiting"); | ||
173 | |||
174 | ft_runner_status = do_abort; | ||
175 | /* set timeout so that the tape will run to logical EOT | ||
176 | * if we missed the last sector and there are no queue pulses. | ||
177 | */ | ||
178 | result = ftape_dumb_stop(); | ||
179 | } | ||
180 | if (ft_runner_status != idle) { | ||
181 | if (ft_runner_status == do_abort) { | ||
182 | TRACE(ft_t_noise, "forcing runner abort"); | ||
183 | } | ||
184 | TRACE(ft_t_noise, "stopping tape"); | ||
185 | result = ftape_stop_tape(&status); | ||
186 | ft_location.known = 0; | ||
187 | ft_runner_status = idle; | ||
188 | } | ||
189 | ftape_reset_buffer(); | ||
190 | ftape_zap_read_buffers(); | ||
191 | ftape_set_state(idle); | ||
192 | TRACE_EXIT result; | ||
193 | } | ||
194 | |||
195 | static int lookup_vendor_id(unsigned int vendor_id) | ||
196 | { | ||
197 | int i = 0; | ||
198 | |||
199 | while (vendors[i].vendor_id != vendor_id) { | ||
200 | if (++i >= NR_ITEMS(vendors)) { | ||
201 | return -1; | ||
202 | } | ||
203 | } | ||
204 | return i; | ||
205 | } | ||
206 | |||
207 | static void ftape_detach_drive(void) | ||
208 | { | ||
209 | TRACE_FUN(ft_t_any); | ||
210 | |||
211 | TRACE(ft_t_flow, "disabling tape drive and fdc"); | ||
212 | ftape_put_drive_to_sleep(ft_drive_type.wake_up); | ||
213 | fdc_catch_stray_interrupts(1); /* one always comes */ | ||
214 | fdc_disable(); | ||
215 | fdc_release_irq_and_dma(); | ||
216 | fdc_release_regions(); | ||
217 | TRACE_EXIT; | ||
218 | } | ||
219 | |||
220 | static void clear_history(void) | ||
221 | { | ||
222 | ft_history.used = 0; | ||
223 | ft_history.id_am_errors = | ||
224 | ft_history.id_crc_errors = | ||
225 | ft_history.data_am_errors = | ||
226 | ft_history.data_crc_errors = | ||
227 | ft_history.overrun_errors = | ||
228 | ft_history.no_data_errors = | ||
229 | ft_history.retries = | ||
230 | ft_history.crc_errors = | ||
231 | ft_history.crc_failures = | ||
232 | ft_history.ecc_failures = | ||
233 | ft_history.corrected = | ||
234 | ft_history.defects = | ||
235 | ft_history.rewinds = 0; | ||
236 | } | ||
237 | |||
238 | static int ftape_activate_drive(vendor_struct * drive_type) | ||
239 | { | ||
240 | int result = 0; | ||
241 | TRACE_FUN(ft_t_flow); | ||
242 | |||
243 | /* If we already know the drive type, wake it up. | ||
244 | * Else try to find out what kind of drive is attached. | ||
245 | */ | ||
246 | if (drive_type->wake_up != unknown_wake_up) { | ||
247 | TRACE(ft_t_flow, "enabling tape drive and fdc"); | ||
248 | result = ftape_wakeup_drive(drive_type->wake_up); | ||
249 | if (result < 0) { | ||
250 | TRACE(ft_t_err, "known wakeup method failed"); | ||
251 | } | ||
252 | } else { | ||
253 | wake_up_types method; | ||
254 | const ft_trace_t old_tracing = TRACE_LEVEL; | ||
255 | if (TRACE_LEVEL < ft_t_flow) { | ||
256 | SET_TRACE_LEVEL(ft_t_bug); | ||
257 | } | ||
258 | |||
259 | /* Try to awaken the drive using all known methods. | ||
260 | * Lower tracing for a while. | ||
261 | */ | ||
262 | for (method=no_wake_up; method < NR_ITEMS(methods); ++method) { | ||
263 | drive_type->wake_up = method; | ||
264 | #ifdef CONFIG_FT_TWO_DRIVES | ||
265 | /* Test setup for dual drive configuration. | ||
266 | * /dev/rft2 uses mountain wakeup | ||
267 | * /dev/rft3 uses colorado wakeup | ||
268 | * Other systems will use the normal scheme. | ||
269 | */ | ||
270 | if ((ft_drive_sel < 2) || | ||
271 | (ft_drive_sel == 2 && method == FT_WAKE_UP_1) || | ||
272 | (ft_drive_sel == 3 && method == FT_WAKE_UP_2)) { | ||
273 | result=ftape_wakeup_drive(drive_type->wake_up); | ||
274 | } else { | ||
275 | result = -EIO; | ||
276 | } | ||
277 | #else | ||
278 | result = ftape_wakeup_drive(drive_type->wake_up); | ||
279 | #endif | ||
280 | if (result >= 0) { | ||
281 | TRACE(ft_t_warn, "drive wakeup method: %s", | ||
282 | methods[drive_type->wake_up].name); | ||
283 | break; | ||
284 | } | ||
285 | } | ||
286 | SET_TRACE_LEVEL(old_tracing); | ||
287 | |||
288 | if (method >= NR_ITEMS(methods)) { | ||
289 | /* no response at all, cannot open this drive */ | ||
290 | drive_type->wake_up = unknown_wake_up; | ||
291 | TRACE(ft_t_err, "no tape drive found !"); | ||
292 | result = -ENODEV; | ||
293 | } | ||
294 | } | ||
295 | TRACE_EXIT result; | ||
296 | } | ||
297 | |||
298 | static int ftape_get_drive_status(void) | ||
299 | { | ||
300 | int result; | ||
301 | int status; | ||
302 | TRACE_FUN(ft_t_flow); | ||
303 | |||
304 | ft_no_tape = ft_write_protected = 0; | ||
305 | /* Tape drive is activated now. | ||
306 | * First clear error status if present. | ||
307 | */ | ||
308 | do { | ||
309 | result = ftape_ready_wait(ftape_timeout.reset, &status); | ||
310 | if (result < 0) { | ||
311 | if (result == -ETIME) { | ||
312 | TRACE(ft_t_err, "ftape_ready_wait timeout"); | ||
313 | } else if (result == -EINTR) { | ||
314 | TRACE(ft_t_err, "ftape_ready_wait aborted"); | ||
315 | } else { | ||
316 | TRACE(ft_t_err, "ftape_ready_wait failed"); | ||
317 | } | ||
318 | TRACE_EXIT -EIO; | ||
319 | } | ||
320 | /* Clear error condition (drive is ready !) | ||
321 | */ | ||
322 | if (status & QIC_STATUS_ERROR) { | ||
323 | unsigned int error; | ||
324 | qic117_cmd_t command; | ||
325 | |||
326 | TRACE(ft_t_err, "error status set"); | ||
327 | result = ftape_report_error(&error, &command, 1); | ||
328 | if (result < 0) { | ||
329 | TRACE(ft_t_err, | ||
330 | "report_error_code failed: %d", result); | ||
331 | /* hope it's working next time */ | ||
332 | ftape_reset_drive(); | ||
333 | TRACE_EXIT -EIO; | ||
334 | } else if (error != 0) { | ||
335 | TRACE(ft_t_noise, "error code : %d", error); | ||
336 | TRACE(ft_t_noise, "error command: %d", command); | ||
337 | } | ||
338 | } | ||
339 | if (status & QIC_STATUS_NEW_CARTRIDGE) { | ||
340 | unsigned int error; | ||
341 | qic117_cmd_t command; | ||
342 | const ft_trace_t old_tracing = TRACE_LEVEL; | ||
343 | SET_TRACE_LEVEL(ft_t_bug); | ||
344 | |||
345 | /* Undocumented feature: Must clear (not present!) | ||
346 | * error here or we'll fail later. | ||
347 | */ | ||
348 | ftape_report_error(&error, &command, 1); | ||
349 | |||
350 | SET_TRACE_LEVEL(old_tracing); | ||
351 | TRACE(ft_t_info, "status: new cartridge"); | ||
352 | ft_new_tape = 1; | ||
353 | } else { | ||
354 | ft_new_tape = 0; | ||
355 | } | ||
356 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
357 | } while (status & QIC_STATUS_ERROR); | ||
358 | |||
359 | ft_no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT); | ||
360 | ft_write_protected = (status & QIC_STATUS_WRITE_PROTECT) != 0; | ||
361 | if (ft_no_tape) { | ||
362 | TRACE(ft_t_warn, "no cartridge present"); | ||
363 | } else { | ||
364 | if (ft_write_protected) { | ||
365 | TRACE(ft_t_noise, "Write protected cartridge"); | ||
366 | } | ||
367 | } | ||
368 | TRACE_EXIT 0; | ||
369 | } | ||
370 | |||
371 | static void ftape_log_vendor_id(void) | ||
372 | { | ||
373 | int vendor_index; | ||
374 | TRACE_FUN(ft_t_flow); | ||
375 | |||
376 | ftape_report_vendor_id(&ft_drive_type.vendor_id); | ||
377 | vendor_index = lookup_vendor_id(ft_drive_type.vendor_id); | ||
378 | if (ft_drive_type.vendor_id == UNKNOWN_VENDOR && | ||
379 | ft_drive_type.wake_up == wake_up_colorado) { | ||
380 | vendor_index = 0; | ||
381 | /* hack to get rid of all this mail */ | ||
382 | ft_drive_type.vendor_id = 0; | ||
383 | } | ||
384 | if (vendor_index < 0) { | ||
385 | /* Unknown vendor id, first time opening device. The | ||
386 | * drive_type remains set to type found at wakeup | ||
387 | * time, this will probably keep the driver operating | ||
388 | * for this new vendor. | ||
389 | */ | ||
390 | TRACE(ft_t_warn, "\n" | ||
391 | KERN_INFO "============ unknown vendor id ===========\n" | ||
392 | KERN_INFO "A new, yet unsupported tape drive is found\n" | ||
393 | KERN_INFO "Please report the following values:\n" | ||
394 | KERN_INFO " Vendor id : 0x%04x\n" | ||
395 | KERN_INFO " Wakeup method : %s\n" | ||
396 | KERN_INFO "And a description of your tape drive\n" | ||
397 | KERN_INFO "to "THE_FTAPE_MAINTAINER"\n" | ||
398 | KERN_INFO "==========================================", | ||
399 | ft_drive_type.vendor_id, | ||
400 | methods[ft_drive_type.wake_up].name); | ||
401 | ft_drive_type.speed = 0; /* unknown */ | ||
402 | } else { | ||
403 | ft_drive_type.name = vendors[vendor_index].name; | ||
404 | ft_drive_type.speed = vendors[vendor_index].speed; | ||
405 | TRACE(ft_t_info, "tape drive type: %s", ft_drive_type.name); | ||
406 | /* scan all methods for this vendor_id in table */ | ||
407 | while(ft_drive_type.wake_up != vendors[vendor_index].wake_up) { | ||
408 | if (vendor_index < NR_ITEMS(vendors) - 1 && | ||
409 | vendors[vendor_index + 1].vendor_id | ||
410 | == | ||
411 | ft_drive_type.vendor_id) { | ||
412 | ++vendor_index; | ||
413 | } else { | ||
414 | break; | ||
415 | } | ||
416 | } | ||
417 | if (ft_drive_type.wake_up != vendors[vendor_index].wake_up) { | ||
418 | TRACE(ft_t_warn, "\n" | ||
419 | KERN_INFO "==========================================\n" | ||
420 | KERN_INFO "wakeup type mismatch:\n" | ||
421 | KERN_INFO "found: %s, expected: %s\n" | ||
422 | KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n" | ||
423 | KERN_INFO "==========================================", | ||
424 | methods[ft_drive_type.wake_up].name, | ||
425 | methods[vendors[vendor_index].wake_up].name); | ||
426 | } | ||
427 | } | ||
428 | TRACE_EXIT; | ||
429 | } | ||
430 | |||
431 | void ftape_calc_timeouts(unsigned int qic_std, | ||
432 | unsigned int data_rate, | ||
433 | unsigned int tape_len) | ||
434 | { | ||
435 | int speed; /* deci-ips ! */ | ||
436 | int ff_speed; | ||
437 | int length; | ||
438 | TRACE_FUN(ft_t_any); | ||
439 | |||
440 | /* tape transport speed | ||
441 | * data rate: QIC-40 QIC-80 QIC-3010 QIC-3020 | ||
442 | * | ||
443 | * 250 Kbps 25 ips n/a n/a n/a | ||
444 | * 500 Kbps 50 ips 34 ips 22.6 ips n/a | ||
445 | * 1 Mbps n/a 68 ips 45.2 ips 22.6 ips | ||
446 | * 2 Mbps n/a n/a n/a 45.2 ips | ||
447 | * | ||
448 | * fast tape transport speed is at least 68 ips. | ||
449 | */ | ||
450 | switch (qic_std) { | ||
451 | case QIC_TAPE_QIC40: | ||
452 | speed = (data_rate == 250) ? 250 : 500; | ||
453 | break; | ||
454 | case QIC_TAPE_QIC80: | ||
455 | speed = (data_rate == 500) ? 340 : 680; | ||
456 | break; | ||
457 | case QIC_TAPE_QIC3010: | ||
458 | speed = (data_rate == 500) ? 226 : 452; | ||
459 | break; | ||
460 | case QIC_TAPE_QIC3020: | ||
461 | speed = (data_rate == 1000) ? 226 : 452; | ||
462 | break; | ||
463 | default: | ||
464 | TRACE(ft_t_bug, "Unknown qic_std (bug) ?"); | ||
465 | speed = 500; | ||
466 | break; | ||
467 | } | ||
468 | if (ft_drive_type.speed == 0) { | ||
469 | unsigned long t0; | ||
470 | static int dt = 0; /* keep gcc from complaining */ | ||
471 | static int first_time = 1; | ||
472 | |||
473 | /* Measure the time it takes to wind to EOT and back to BOT. | ||
474 | * If the tape length is known, calculate the rewind speed. | ||
475 | * Else keep the time value for calculation of the rewind | ||
476 | * speed later on, when the length _is_ known. | ||
477 | * Ask for a report only when length and speed are both known. | ||
478 | */ | ||
479 | if (first_time) { | ||
480 | ftape_seek_to_bot(); | ||
481 | t0 = jiffies; | ||
482 | ftape_seek_to_eot(); | ||
483 | ftape_seek_to_bot(); | ||
484 | dt = (int) (((jiffies - t0) * FT_USPT) / 1000); | ||
485 | if (dt < 1) { | ||
486 | dt = 1; /* prevent div by zero on failures */ | ||
487 | } | ||
488 | first_time = 0; | ||
489 | TRACE(ft_t_info, | ||
490 | "trying to determine seek timeout, got %d msec", | ||
491 | dt); | ||
492 | } | ||
493 | if (tape_len != 0) { | ||
494 | ft_drive_type.speed = | ||
495 | (2 * 12 * tape_len * 1000) / dt; | ||
496 | TRACE(ft_t_warn, "\n" | ||
497 | KERN_INFO "==========================================\n" | ||
498 | KERN_INFO "drive type: %s\n" | ||
499 | KERN_INFO "delta time = %d ms, length = %d ft\n" | ||
500 | KERN_INFO "has a maximum tape speed of %d ips\n" | ||
501 | KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n" | ||
502 | KERN_INFO "==========================================", | ||
503 | ft_drive_type.name, dt, tape_len, | ||
504 | ft_drive_type.speed); | ||
505 | } | ||
506 | } | ||
507 | /* Handle unknown length tapes as very long ones. We'll | ||
508 | * determine the actual length from a header segment later. | ||
509 | * This is normal for all modern (Wide,TR1/2/3) formats. | ||
510 | */ | ||
511 | if (tape_len <= 0) { | ||
512 | TRACE(ft_t_noise, | ||
513 | "Unknown tape length, using maximal timeouts"); | ||
514 | length = QIC_TOP_TAPE_LEN; /* use worst case values */ | ||
515 | } else { | ||
516 | length = tape_len; /* use actual values */ | ||
517 | } | ||
518 | if (ft_drive_type.speed == 0) { | ||
519 | ff_speed = speed; | ||
520 | } else { | ||
521 | ff_speed = ft_drive_type.speed; | ||
522 | } | ||
523 | /* time to go from bot to eot at normal speed (data rate): | ||
524 | * time = (1+delta) * length (ft) * 12 (inch/ft) / speed (ips) | ||
525 | * delta = 10 % for seek speed, 20 % for rewind speed. | ||
526 | */ | ||
527 | ftape_timeout.seek = (length * 132 * FT_SECOND) / speed; | ||
528 | ftape_timeout.rewind = (length * 144 * FT_SECOND) / (10 * ff_speed); | ||
529 | ftape_timeout.reset = 20 * FT_SECOND + ftape_timeout.rewind; | ||
530 | TRACE(ft_t_noise, "timeouts for speed = %d, length = %d\n" | ||
531 | KERN_INFO "seek timeout : %d sec\n" | ||
532 | KERN_INFO "rewind timeout: %d sec\n" | ||
533 | KERN_INFO "reset timeout : %d sec", | ||
534 | speed, length, | ||
535 | (ftape_timeout.seek + 500) / 1000, | ||
536 | (ftape_timeout.rewind + 500) / 1000, | ||
537 | (ftape_timeout.reset + 500) / 1000); | ||
538 | TRACE_EXIT; | ||
539 | } | ||
540 | |||
541 | /* This function calibrates the datarate (i.e. determines the maximal | ||
542 | * usable data rate) and sets the global variable ft_qic_std to qic_std | ||
543 | * | ||
544 | */ | ||
545 | int ftape_calibrate_data_rate(unsigned int qic_std) | ||
546 | { | ||
547 | int rate = ft_fdc_rate_limit; | ||
548 | int result; | ||
549 | TRACE_FUN(ft_t_flow); | ||
550 | |||
551 | ft_qic_std = qic_std; | ||
552 | |||
553 | if (ft_qic_std == -1) { | ||
554 | TRACE_ABORT(-EIO, ft_t_err, | ||
555 | "Unable to determine data rate if QIC standard is unknown"); | ||
556 | } | ||
557 | |||
558 | /* Select highest rate supported by both fdc and drive. | ||
559 | * Start with highest rate supported by the fdc. | ||
560 | */ | ||
561 | while (fdc_set_data_rate(rate) < 0 && rate > 250) { | ||
562 | rate /= 2; | ||
563 | } | ||
564 | TRACE(ft_t_info, | ||
565 | "Highest FDC supported data rate: %d Kbps", rate); | ||
566 | ft_fdc_max_rate = rate; | ||
567 | do { | ||
568 | result = ftape_set_data_rate(rate, ft_qic_std); | ||
569 | } while (result == -EINVAL && (rate /= 2) > 250); | ||
570 | if (result < 0) { | ||
571 | TRACE_ABORT(-EIO, ft_t_err, "set datarate failed"); | ||
572 | } | ||
573 | ft_data_rate = rate; | ||
574 | TRACE_EXIT 0; | ||
575 | } | ||
576 | |||
577 | static int ftape_init_drive(void) | ||
578 | { | ||
579 | int status; | ||
580 | qic_model model; | ||
581 | unsigned int qic_std; | ||
582 | unsigned int data_rate; | ||
583 | TRACE_FUN(ft_t_flow); | ||
584 | |||
585 | ftape_init_drive_needed = 0; /* don't retry if this fails ? */ | ||
586 | TRACE_CATCH(ftape_report_raw_drive_status(&status),); | ||
587 | if (status & QIC_STATUS_CARTRIDGE_PRESENT) { | ||
588 | if (!(status & QIC_STATUS_AT_BOT)) { | ||
589 | /* Antique drives will get here after a soft reset, | ||
590 | * modern ones only if the driver is loaded when the | ||
591 | * tape wasn't rewound properly. | ||
592 | */ | ||
593 | /* Tape should be at bot if new cartridge ! */ | ||
594 | ftape_seek_to_bot(); | ||
595 | } | ||
596 | if (!(status & QIC_STATUS_REFERENCED)) { | ||
597 | TRACE(ft_t_flow, "starting seek_load_point"); | ||
598 | TRACE_CATCH(ftape_command_wait(QIC_SEEK_LOAD_POINT, | ||
599 | ftape_timeout.reset, | ||
600 | &status),); | ||
601 | } | ||
602 | } | ||
603 | ft_formatted = (status & QIC_STATUS_REFERENCED) != 0; | ||
604 | if (!ft_formatted) { | ||
605 | TRACE(ft_t_warn, "Warning: tape is not formatted !"); | ||
606 | } | ||
607 | |||
608 | /* report configuration aborts when ftape_tape_len == -1 | ||
609 | * unknown qic_std is okay if not formatted. | ||
610 | */ | ||
611 | TRACE_CATCH(ftape_report_configuration(&model, | ||
612 | &data_rate, | ||
613 | &qic_std, | ||
614 | &ftape_tape_len),); | ||
615 | |||
616 | /* Maybe add the following to the /proc entry | ||
617 | */ | ||
618 | TRACE(ft_t_info, "%s drive @ %d Kbps", | ||
619 | (model == prehistoric) ? "prehistoric" : | ||
620 | ((model == pre_qic117c) ? "pre QIC-117C" : | ||
621 | ((model == post_qic117b) ? "post QIC-117B" : | ||
622 | "post QIC-117D")), data_rate); | ||
623 | |||
624 | if (ft_formatted) { | ||
625 | /* initialize ft_used_data_rate to maximum value | ||
626 | * and set ft_qic_std | ||
627 | */ | ||
628 | TRACE_CATCH(ftape_calibrate_data_rate(qic_std),); | ||
629 | if (ftape_tape_len == 0) { | ||
630 | TRACE(ft_t_info, "unknown length QIC-%s tape", | ||
631 | (ft_qic_std == QIC_TAPE_QIC40) ? "40" : | ||
632 | ((ft_qic_std == QIC_TAPE_QIC80) ? "80" : | ||
633 | ((ft_qic_std == QIC_TAPE_QIC3010) | ||
634 | ? "3010" : "3020"))); | ||
635 | } else { | ||
636 | TRACE(ft_t_info, "%d ft. QIC-%s tape", ftape_tape_len, | ||
637 | (ft_qic_std == QIC_TAPE_QIC40) ? "40" : | ||
638 | ((ft_qic_std == QIC_TAPE_QIC80) ? "80" : | ||
639 | ((ft_qic_std == QIC_TAPE_QIC3010) | ||
640 | ? "3010" : "3020"))); | ||
641 | } | ||
642 | ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len); | ||
643 | /* soft write-protect QIC-40/QIC-80 cartridges used with a | ||
644 | * Colorado T3000 drive. Buggy hardware! | ||
645 | */ | ||
646 | if ((ft_drive_type.vendor_id == 0x011c6) && | ||
647 | ((ft_qic_std == QIC_TAPE_QIC40 || | ||
648 | ft_qic_std == QIC_TAPE_QIC80) && | ||
649 | !ft_write_protected)) { | ||
650 | TRACE(ft_t_warn, "\n" | ||
651 | KERN_INFO "The famous Colorado T3000 bug:\n" | ||
652 | KERN_INFO "%s drives can't write QIC40 and QIC80\n" | ||
653 | KERN_INFO "cartridges but don't set the write-protect flag!", | ||
654 | ft_drive_type.name); | ||
655 | ft_write_protected = 1; | ||
656 | } | ||
657 | } else { | ||
658 | /* Doesn't make too much sense to set the data rate | ||
659 | * because we don't know what to use for the write | ||
660 | * precompensation. | ||
661 | * Need to do this again when formatting the cartridge. | ||
662 | */ | ||
663 | ft_data_rate = data_rate; | ||
664 | ftape_calc_timeouts(QIC_TAPE_QIC40, | ||
665 | data_rate, | ||
666 | ftape_tape_len); | ||
667 | } | ||
668 | ftape_new_cartridge(); | ||
669 | TRACE_EXIT 0; | ||
670 | } | ||
671 | |||
672 | static void ftape_munmap(void) | ||
673 | { | ||
674 | int i; | ||
675 | TRACE_FUN(ft_t_flow); | ||
676 | |||
677 | for (i = 0; i < ft_nr_buffers; i++) { | ||
678 | ft_buffer[i]->mmapped = 0; | ||
679 | } | ||
680 | TRACE_EXIT; | ||
681 | } | ||
682 | |||
683 | /* Map the dma buffers into the virtual address range given by vma. | ||
684 | * We only check the caller doesn't map non-existent buffers. We | ||
685 | * don't check for multiple mappings. | ||
686 | */ | ||
687 | int ftape_mmap(struct vm_area_struct *vma) | ||
688 | { | ||
689 | int num_buffers; | ||
690 | int i; | ||
691 | TRACE_FUN(ft_t_flow); | ||
692 | |||
693 | if (ft_failure) { | ||
694 | TRACE_EXIT -ENODEV; | ||
695 | } | ||
696 | if (!(vma->vm_flags & (VM_READ|VM_WRITE))) { | ||
697 | TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access"); | ||
698 | } | ||
699 | if (vma_get_pgoff(vma) != 0) { | ||
700 | TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0"); | ||
701 | } | ||
702 | if ((vma->vm_end - vma->vm_start) % FT_BUFF_SIZE != 0) { | ||
703 | TRACE_ABORT(-EINVAL, ft_t_err, | ||
704 | "size = %ld, should be a multiple of %d", | ||
705 | vma->vm_end - vma->vm_start, | ||
706 | FT_BUFF_SIZE); | ||
707 | } | ||
708 | num_buffers = (vma->vm_end - vma->vm_start) / FT_BUFF_SIZE; | ||
709 | if (num_buffers > ft_nr_buffers) { | ||
710 | TRACE_ABORT(-EINVAL, | ||
711 | ft_t_err, "size = %ld, should be less than %d", | ||
712 | vma->vm_end - vma->vm_start, | ||
713 | ft_nr_buffers * FT_BUFF_SIZE); | ||
714 | } | ||
715 | if (ft_driver_state != idle) { | ||
716 | /* this also clears the buffer states | ||
717 | */ | ||
718 | ftape_abort_operation(); | ||
719 | } else { | ||
720 | ftape_reset_buffer(); | ||
721 | } | ||
722 | for (i = 0; i < num_buffers; i++) { | ||
723 | unsigned long pfn; | ||
724 | |||
725 | pfn = virt_to_phys(ft_buffer[i]->address) >> PAGE_SHIFT; | ||
726 | TRACE_CATCH(remap_pfn_range(vma, vma->vm_start + | ||
727 | i * FT_BUFF_SIZE, | ||
728 | pfn, | ||
729 | FT_BUFF_SIZE, | ||
730 | vma->vm_page_prot), | ||
731 | _res = -EAGAIN); | ||
732 | TRACE(ft_t_noise, "remapped dma buffer @ %p to location @ %p", | ||
733 | ft_buffer[i]->address, | ||
734 | (void *)(vma->vm_start + i * FT_BUFF_SIZE)); | ||
735 | } | ||
736 | for (i = 0; i < num_buffers; i++) { | ||
737 | memset(ft_buffer[i]->address, 0xAA, FT_BUFF_SIZE); | ||
738 | ft_buffer[i]->mmapped++; | ||
739 | } | ||
740 | TRACE_EXIT 0; | ||
741 | } | ||
742 | |||
743 | static void ftape_init_driver(void); /* forward declaration */ | ||
744 | |||
745 | /* OPEN routine called by kernel-interface code | ||
746 | */ | ||
747 | int ftape_enable(int drive_selection) | ||
748 | { | ||
749 | TRACE_FUN(ft_t_any); | ||
750 | |||
751 | if (ft_drive_sel == -1 || ft_drive_sel != drive_selection) { | ||
752 | /* Other selection than last time | ||
753 | */ | ||
754 | ftape_init_driver(); | ||
755 | } | ||
756 | ft_drive_sel = FTAPE_SEL(drive_selection); | ||
757 | ft_failure = 0; | ||
758 | TRACE_CATCH(fdc_init(),); /* init & detect fdc */ | ||
759 | TRACE_CATCH(ftape_activate_drive(&ft_drive_type), | ||
760 | fdc_disable(); | ||
761 | fdc_release_irq_and_dma(); | ||
762 | fdc_release_regions()); | ||
763 | TRACE_CATCH(ftape_get_drive_status(), ftape_detach_drive()); | ||
764 | if (ft_drive_type.vendor_id == UNKNOWN_VENDOR) { | ||
765 | ftape_log_vendor_id(); | ||
766 | } | ||
767 | if (ft_new_tape) { | ||
768 | ftape_init_drive_needed = 1; | ||
769 | } | ||
770 | if (!ft_no_tape && ftape_init_drive_needed) { | ||
771 | TRACE_CATCH(ftape_init_drive(), ftape_detach_drive()); | ||
772 | } | ||
773 | ftape_munmap(); /* clear the mmap flag */ | ||
774 | clear_history(); | ||
775 | TRACE_EXIT 0; | ||
776 | } | ||
777 | |||
778 | /* release routine called by the high level interface modules | ||
779 | * zftape or sftape. | ||
780 | */ | ||
781 | void ftape_disable(void) | ||
782 | { | ||
783 | int i; | ||
784 | TRACE_FUN(ft_t_any); | ||
785 | |||
786 | for (i = 0; i < ft_nr_buffers; i++) { | ||
787 | if (ft_buffer[i]->mmapped) { | ||
788 | TRACE(ft_t_noise, "first byte of buffer %d: 0x%02x", | ||
789 | i, *ft_buffer[i]->address); | ||
790 | } | ||
791 | } | ||
792 | if (sigtestsetmask(¤t->pending.signal, _DONT_BLOCK) && | ||
793 | !(sigtestsetmask(¤t->pending.signal, _NEVER_BLOCK)) && | ||
794 | ftape_tape_running) { | ||
795 | TRACE(ft_t_warn, | ||
796 | "Interrupted by fatal signal and tape still running"); | ||
797 | ftape_dumb_stop(); | ||
798 | ftape_abort_operation(); /* it's annoying */ | ||
799 | } else { | ||
800 | ftape_set_state(idle); | ||
801 | } | ||
802 | ftape_detach_drive(); | ||
803 | if (ft_history.used) { | ||
804 | TRACE(ft_t_info, "== Non-fatal errors this run: =="); | ||
805 | TRACE(ft_t_info, "fdc isr statistics:\n" | ||
806 | KERN_INFO " id_am_errors : %3d\n" | ||
807 | KERN_INFO " id_crc_errors : %3d\n" | ||
808 | KERN_INFO " data_am_errors : %3d\n" | ||
809 | KERN_INFO " data_crc_errors : %3d\n" | ||
810 | KERN_INFO " overrun_errors : %3d\n" | ||
811 | KERN_INFO " no_data_errors : %3d\n" | ||
812 | KERN_INFO " retries : %3d", | ||
813 | ft_history.id_am_errors, ft_history.id_crc_errors, | ||
814 | ft_history.data_am_errors, ft_history.data_crc_errors, | ||
815 | ft_history.overrun_errors, ft_history.no_data_errors, | ||
816 | ft_history.retries); | ||
817 | if (ft_history.used & 1) { | ||
818 | TRACE(ft_t_info, "ecc statistics:\n" | ||
819 | KERN_INFO " crc_errors : %3d\n" | ||
820 | KERN_INFO " crc_failures : %3d\n" | ||
821 | KERN_INFO " ecc_failures : %3d\n" | ||
822 | KERN_INFO " sectors corrected: %3d", | ||
823 | ft_history.crc_errors, ft_history.crc_failures, | ||
824 | ft_history.ecc_failures, ft_history.corrected); | ||
825 | } | ||
826 | if (ft_history.defects > 0) { | ||
827 | TRACE(ft_t_warn, "Warning: %d media defects!", | ||
828 | ft_history.defects); | ||
829 | } | ||
830 | if (ft_history.rewinds > 0) { | ||
831 | TRACE(ft_t_info, "tape motion statistics:\n" | ||
832 | KERN_INFO "repositions : %3d", | ||
833 | ft_history.rewinds); | ||
834 | } | ||
835 | } | ||
836 | ft_failure = 1; | ||
837 | TRACE_EXIT; | ||
838 | } | ||
839 | |||
840 | static void ftape_init_driver(void) | ||
841 | { | ||
842 | TRACE_FUN(ft_t_flow); | ||
843 | |||
844 | ft_drive_type.vendor_id = UNKNOWN_VENDOR; | ||
845 | ft_drive_type.speed = 0; | ||
846 | ft_drive_type.wake_up = unknown_wake_up; | ||
847 | ft_drive_type.name = "Unknown"; | ||
848 | |||
849 | ftape_timeout.seek = 650 * FT_SECOND; | ||
850 | ftape_timeout.reset = 670 * FT_SECOND; | ||
851 | ftape_timeout.rewind = 650 * FT_SECOND; | ||
852 | ftape_timeout.head_seek = 15 * FT_SECOND; | ||
853 | ftape_timeout.stop = 5 * FT_SECOND; | ||
854 | ftape_timeout.pause = 16 * FT_SECOND; | ||
855 | |||
856 | ft_qic_std = -1; | ||
857 | ftape_tape_len = 0; /* unknown */ | ||
858 | ftape_current_command = 0; | ||
859 | ftape_current_cylinder = -1; | ||
860 | |||
861 | ft_segments_per_track = 102; | ||
862 | ftape_segments_per_head = 1020; | ||
863 | ftape_segments_per_cylinder = 4; | ||
864 | ft_tracks_per_tape = 20; | ||
865 | |||
866 | ft_failure = 1; | ||
867 | |||
868 | ft_formatted = 0; | ||
869 | ft_no_tape = 1; | ||
870 | ft_write_protected = 1; | ||
871 | ft_new_tape = 1; | ||
872 | |||
873 | ft_driver_state = idle; | ||
874 | |||
875 | ft_data_rate = | ||
876 | ft_fdc_max_rate = 500; | ||
877 | ft_drive_max_rate = 0; /* triggers set_rate_test() */ | ||
878 | |||
879 | ftape_init_drive_needed = 1; | ||
880 | |||
881 | ft_header_segment_1 = -1; | ||
882 | ft_header_segment_2 = -1; | ||
883 | ft_used_header_segment = -1; | ||
884 | ft_first_data_segment = -1; | ||
885 | ft_last_data_segment = -1; | ||
886 | |||
887 | ft_location.track = -1; | ||
888 | ft_location.known = 0; | ||
889 | |||
890 | ftape_tape_running = 0; | ||
891 | ftape_might_be_off_track = 1; | ||
892 | |||
893 | ftape_new_cartridge(); /* init some tape related variables */ | ||
894 | ftape_init_bsm(); | ||
895 | TRACE_EXIT; | ||
896 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.h b/drivers/char/ftape/lowlevel/ftape-ctl.h deleted file mode 100644 index 5f5e30bc3615..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-ctl.h +++ /dev/null | |||
@@ -1,162 +0,0 @@ | |||
1 | #ifndef _FTAPE_CTL_H | ||
2 | #define _FTAPE_CTL_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:09 $ | ||
26 | * | ||
27 | * This file contains the non-standard IOCTL related definitions | ||
28 | * for the QIC-40/80/3010/3020 floppy-tape driver "ftape" for | ||
29 | * Linux. | ||
30 | */ | ||
31 | |||
32 | #include <linux/ioctl.h> | ||
33 | #include <linux/mtio.h> | ||
34 | #include <linux/ftape-vendors.h> | ||
35 | |||
36 | #include "../lowlevel/ftape-rw.h" | ||
37 | #include <linux/ftape-header-segment.h> | ||
38 | |||
39 | typedef struct { | ||
40 | int used; /* any reading or writing done */ | ||
41 | /* isr statistics */ | ||
42 | unsigned int id_am_errors; /* id address mark not found */ | ||
43 | unsigned int id_crc_errors; /* crc error in id address mark */ | ||
44 | unsigned int data_am_errors; /* data address mark not found */ | ||
45 | unsigned int data_crc_errors; /* crc error in data field */ | ||
46 | unsigned int overrun_errors; /* fdc access timing problem */ | ||
47 | unsigned int no_data_errors; /* sector not found */ | ||
48 | unsigned int retries; /* number of tape retries */ | ||
49 | /* ecc statistics */ | ||
50 | unsigned int crc_errors; /* crc error in data */ | ||
51 | unsigned int crc_failures; /* bad data without crc error */ | ||
52 | unsigned int ecc_failures; /* failed to correct */ | ||
53 | unsigned int corrected; /* total sectors corrected */ | ||
54 | /* general statistics */ | ||
55 | unsigned int rewinds; /* number of tape rewinds */ | ||
56 | unsigned int defects; /* bad sectors due to media defects */ | ||
57 | } history_record; | ||
58 | |||
59 | /* this structure contains * ALL * information that we want | ||
60 | * our child modules to know about, but don't want them to | ||
61 | * modify. | ||
62 | */ | ||
63 | typedef struct { | ||
64 | /* vendor information */ | ||
65 | vendor_struct fti_drive_type; | ||
66 | /* data rates */ | ||
67 | unsigned int fti_used_data_rate; | ||
68 | unsigned int fti_drive_max_rate; | ||
69 | unsigned int fti_fdc_max_rate; | ||
70 | /* drive selection, either FTAPE_SEL_A/B/C/D */ | ||
71 | int fti_drive_sel; | ||
72 | /* flags set after decode the drive and tape status */ | ||
73 | unsigned int fti_formatted :1; | ||
74 | unsigned int fti_no_tape :1; | ||
75 | unsigned int fti_write_protected:1; | ||
76 | unsigned int fti_new_tape :1; | ||
77 | /* values of last queried drive/tape status and error */ | ||
78 | ft_drive_error fti_last_error; | ||
79 | ft_drive_status fti_last_status; | ||
80 | /* cartridge geometry */ | ||
81 | unsigned int fti_tracks_per_tape; | ||
82 | unsigned int fti_segments_per_track; | ||
83 | /* location of header segments, etc. */ | ||
84 | int fti_used_header_segment; | ||
85 | int fti_header_segment_1; | ||
86 | int fti_header_segment_2; | ||
87 | int fti_first_data_segment; | ||
88 | int fti_last_data_segment; | ||
89 | /* the format code as stored in the header segment */ | ||
90 | ft_format_type fti_format_code; | ||
91 | /* the following is the sole reason for the ftape_set_status() call */ | ||
92 | unsigned int fti_qic_std; | ||
93 | /* is tape running? */ | ||
94 | volatile enum runner_status_enum fti_runner_status; | ||
95 | /* is tape reading/writing/verifying/formatting/deleting */ | ||
96 | buffer_state_enum fti_state; | ||
97 | /* flags fatal hardware error */ | ||
98 | unsigned int fti_failure:1; | ||
99 | /* history record */ | ||
100 | history_record fti_history; | ||
101 | } ftape_info; | ||
102 | |||
103 | /* vendor information */ | ||
104 | #define ft_drive_type ftape_status.fti_drive_type | ||
105 | /* data rates */ | ||
106 | #define ft_data_rate ftape_status.fti_used_data_rate | ||
107 | #define ft_drive_max_rate ftape_status.fti_drive_max_rate | ||
108 | #define ft_fdc_max_rate ftape_status.fti_fdc_max_rate | ||
109 | /* drive selection, either FTAPE_SEL_A/B/C/D */ | ||
110 | #define ft_drive_sel ftape_status.fti_drive_sel | ||
111 | /* flags set after decode the drive and tape status */ | ||
112 | #define ft_formatted ftape_status.fti_formatted | ||
113 | #define ft_no_tape ftape_status.fti_no_tape | ||
114 | #define ft_write_protected ftape_status.fti_write_protected | ||
115 | #define ft_new_tape ftape_status.fti_new_tape | ||
116 | /* values of last queried drive/tape status and error */ | ||
117 | #define ft_last_error ftape_status.fti_last_error | ||
118 | #define ft_last_status ftape_status.fti_last_status | ||
119 | /* cartridge geometry */ | ||
120 | #define ft_tracks_per_tape ftape_status.fti_tracks_per_tape | ||
121 | #define ft_segments_per_track ftape_status.fti_segments_per_track | ||
122 | /* the format code as stored in the header segment */ | ||
123 | #define ft_format_code ftape_status.fti_format_code | ||
124 | /* the qic status as returned by report drive configuration */ | ||
125 | #define ft_qic_std ftape_status.fti_qic_std | ||
126 | #define ft_used_header_segment ftape_status.fti_used_header_segment | ||
127 | #define ft_header_segment_1 ftape_status.fti_header_segment_1 | ||
128 | #define ft_header_segment_2 ftape_status.fti_header_segment_2 | ||
129 | #define ft_first_data_segment ftape_status.fti_first_data_segment | ||
130 | #define ft_last_data_segment ftape_status.fti_last_data_segment | ||
131 | /* is tape running? */ | ||
132 | #define ft_runner_status ftape_status.fti_runner_status | ||
133 | /* is tape reading/writing/verifying/formatting/deleting */ | ||
134 | #define ft_driver_state ftape_status.fti_state | ||
135 | /* flags fatal hardware error */ | ||
136 | #define ft_failure ftape_status.fti_failure | ||
137 | /* history record */ | ||
138 | #define ft_history ftape_status.fti_history | ||
139 | |||
140 | /* | ||
141 | * ftape-ctl.c defined global vars. | ||
142 | */ | ||
143 | extern ftape_info ftape_status; | ||
144 | extern int ftape_segments_per_head; | ||
145 | extern int ftape_segments_per_cylinder; | ||
146 | extern int ftape_init_drive_needed; | ||
147 | |||
148 | /* | ||
149 | * ftape-ctl.c defined global functions. | ||
150 | */ | ||
151 | extern int ftape_mmap(struct vm_area_struct *vma); | ||
152 | extern int ftape_enable(int drive_selection); | ||
153 | extern void ftape_disable(void); | ||
154 | extern int ftape_seek_to_bot(void); | ||
155 | extern int ftape_seek_to_eot(void); | ||
156 | extern int ftape_abort_operation(void); | ||
157 | extern void ftape_calc_timeouts(unsigned int qic_std, | ||
158 | unsigned int data_rate, | ||
159 | unsigned int tape_len); | ||
160 | extern int ftape_calibrate_data_rate(unsigned int qic_std); | ||
161 | extern const ftape_info *ftape_get_status(void); | ||
162 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-ecc.c b/drivers/char/ftape/lowlevel/ftape-ecc.c deleted file mode 100644 index e5632f674bc8..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-ecc.c +++ /dev/null | |||
@@ -1,853 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 1993 Ning and David Mosberger. | ||
4 | |||
5 | This is based on code originally written by Bas Laarhoven (bas@vimec.nl) | ||
6 | and David L. Brown, Jr., and incorporates improvements suggested by | ||
7 | Kai Harrekilde-Petersen. | ||
8 | |||
9 | This program is free software; you can redistribute it and/or | ||
10 | modify it under the terms of the GNU General Public License as | ||
11 | published by the Free Software Foundation; either version 2, or (at | ||
12 | your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; see the file COPYING. If not, write to | ||
21 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
22 | USA. | ||
23 | |||
24 | * | ||
25 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.c,v $ | ||
26 | * $Revision: 1.3 $ | ||
27 | * $Date: 1997/10/05 19:18:10 $ | ||
28 | * | ||
29 | * This file contains the Reed-Solomon error correction code | ||
30 | * for the QIC-40/80 floppy-tape driver for Linux. | ||
31 | */ | ||
32 | |||
33 | #include <linux/ftape.h> | ||
34 | |||
35 | #include "../lowlevel/ftape-tracing.h" | ||
36 | #include "../lowlevel/ftape-ecc.h" | ||
37 | |||
38 | /* Machines that are big-endian should define macro BIG_ENDIAN. | ||
39 | * Unfortunately, there doesn't appear to be a standard include file | ||
40 | * that works for all OSs. | ||
41 | */ | ||
42 | |||
43 | #if defined(__sparc__) || defined(__hppa) | ||
44 | #define BIG_ENDIAN | ||
45 | #endif /* __sparc__ || __hppa */ | ||
46 | |||
47 | #if defined(__mips__) | ||
48 | #error Find a smart way to determine the Endianness of the MIPS CPU | ||
49 | #endif | ||
50 | |||
51 | /* Notice: to minimize the potential for confusion, we use r to | ||
52 | * denote the independent variable of the polynomials in the | ||
53 | * Galois Field GF(2^8). We reserve x for polynomials that | ||
54 | * that have coefficients in GF(2^8). | ||
55 | * | ||
56 | * The Galois Field in which coefficient arithmetic is performed are | ||
57 | * the polynomials over Z_2 (i.e., 0 and 1) modulo the irreducible | ||
58 | * polynomial f(r), where f(r)=r^8 + r^7 + r^2 + r + 1. A polynomial | ||
59 | * is represented as a byte with the MSB as the coefficient of r^7 and | ||
60 | * the LSB as the coefficient of r^0. For example, the binary | ||
61 | * representation of f(x) is 0x187 (of course, this doesn't fit into 8 | ||
62 | * bits). In this field, the polynomial r is a primitive element. | ||
63 | * That is, r^i with i in 0,...,255 enumerates all elements in the | ||
64 | * field. | ||
65 | * | ||
66 | * The generator polynomial for the QIC-80 ECC is | ||
67 | * | ||
68 | * g(x) = x^3 + r^105*x^2 + r^105*x + 1 | ||
69 | * | ||
70 | * which can be factored into: | ||
71 | * | ||
72 | * g(x) = (x-r^-1)(x-r^0)(x-r^1) | ||
73 | * | ||
74 | * the byte representation of the coefficients are: | ||
75 | * | ||
76 | * r^105 = 0xc0 | ||
77 | * r^-1 = 0xc3 | ||
78 | * r^0 = 0x01 | ||
79 | * r^1 = 0x02 | ||
80 | * | ||
81 | * Notice that r^-1 = r^254 as exponent arithmetic is performed | ||
82 | * modulo 2^8-1 = 255. | ||
83 | * | ||
84 | * For more information on Galois Fields and Reed-Solomon codes, refer | ||
85 | * to any good book. I found _An Introduction to Error Correcting | ||
86 | * Codes with Applications_ by S. A. Vanstone and P. C. van Oorschot | ||
87 | * to be a good introduction into the former. _CODING THEORY: The | ||
88 | * Essentials_ I found very useful for its concise description of | ||
89 | * Reed-Solomon encoding/decoding. | ||
90 | * | ||
91 | */ | ||
92 | |||
93 | typedef __u8 Matrix[3][3]; | ||
94 | |||
95 | /* | ||
96 | * gfpow[] is defined such that gfpow[i] returns r^i if | ||
97 | * i is in the range [0..255]. | ||
98 | */ | ||
99 | static const __u8 gfpow[] = | ||
100 | { | ||
101 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, | ||
102 | 0x87, 0x89, 0x95, 0xad, 0xdd, 0x3d, 0x7a, 0xf4, | ||
103 | 0x6f, 0xde, 0x3b, 0x76, 0xec, 0x5f, 0xbe, 0xfb, | ||
104 | 0x71, 0xe2, 0x43, 0x86, 0x8b, 0x91, 0xa5, 0xcd, | ||
105 | 0x1d, 0x3a, 0x74, 0xe8, 0x57, 0xae, 0xdb, 0x31, | ||
106 | 0x62, 0xc4, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x67, | ||
107 | 0xce, 0x1b, 0x36, 0x6c, 0xd8, 0x37, 0x6e, 0xdc, | ||
108 | 0x3f, 0x7e, 0xfc, 0x7f, 0xfe, 0x7b, 0xf6, 0x6b, | ||
109 | 0xd6, 0x2b, 0x56, 0xac, 0xdf, 0x39, 0x72, 0xe4, | ||
110 | 0x4f, 0x9e, 0xbb, 0xf1, 0x65, 0xca, 0x13, 0x26, | ||
111 | 0x4c, 0x98, 0xb7, 0xe9, 0x55, 0xaa, 0xd3, 0x21, | ||
112 | 0x42, 0x84, 0x8f, 0x99, 0xb5, 0xed, 0x5d, 0xba, | ||
113 | 0xf3, 0x61, 0xc2, 0x03, 0x06, 0x0c, 0x18, 0x30, | ||
114 | 0x60, 0xc0, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, | ||
115 | 0x47, 0x8e, 0x9b, 0xb1, 0xe5, 0x4d, 0x9a, 0xb3, | ||
116 | 0xe1, 0x45, 0x8a, 0x93, 0xa1, 0xc5, 0x0d, 0x1a, | ||
117 | 0x34, 0x68, 0xd0, 0x27, 0x4e, 0x9c, 0xbf, 0xf9, | ||
118 | 0x75, 0xea, 0x53, 0xa6, 0xcb, 0x11, 0x22, 0x44, | ||
119 | 0x88, 0x97, 0xa9, 0xd5, 0x2d, 0x5a, 0xb4, 0xef, | ||
120 | 0x59, 0xb2, 0xe3, 0x41, 0x82, 0x83, 0x81, 0x85, | ||
121 | 0x8d, 0x9d, 0xbd, 0xfd, 0x7d, 0xfa, 0x73, 0xe6, | ||
122 | 0x4b, 0x96, 0xab, 0xd1, 0x25, 0x4a, 0x94, 0xaf, | ||
123 | 0xd9, 0x35, 0x6a, 0xd4, 0x2f, 0x5e, 0xbc, 0xff, | ||
124 | 0x79, 0xf2, 0x63, 0xc6, 0x0b, 0x16, 0x2c, 0x58, | ||
125 | 0xb0, 0xe7, 0x49, 0x92, 0xa3, 0xc1, 0x05, 0x0a, | ||
126 | 0x14, 0x28, 0x50, 0xa0, 0xc7, 0x09, 0x12, 0x24, | ||
127 | 0x48, 0x90, 0xa7, 0xc9, 0x15, 0x2a, 0x54, 0xa8, | ||
128 | 0xd7, 0x29, 0x52, 0xa4, 0xcf, 0x19, 0x32, 0x64, | ||
129 | 0xc8, 0x17, 0x2e, 0x5c, 0xb8, 0xf7, 0x69, 0xd2, | ||
130 | 0x23, 0x46, 0x8c, 0x9f, 0xb9, 0xf5, 0x6d, 0xda, | ||
131 | 0x33, 0x66, 0xcc, 0x1f, 0x3e, 0x7c, 0xf8, 0x77, | ||
132 | 0xee, 0x5b, 0xb6, 0xeb, 0x51, 0xa2, 0xc3, 0x01 | ||
133 | }; | ||
134 | |||
135 | /* | ||
136 | * This is a log table. That is, gflog[r^i] returns i (modulo f(r)). | ||
137 | * gflog[0] is undefined and the first element is therefore not valid. | ||
138 | */ | ||
139 | static const __u8 gflog[256] = | ||
140 | { | ||
141 | 0xff, 0x00, 0x01, 0x63, 0x02, 0xc6, 0x64, 0x6a, | ||
142 | 0x03, 0xcd, 0xc7, 0xbc, 0x65, 0x7e, 0x6b, 0x2a, | ||
143 | 0x04, 0x8d, 0xce, 0x4e, 0xc8, 0xd4, 0xbd, 0xe1, | ||
144 | 0x66, 0xdd, 0x7f, 0x31, 0x6c, 0x20, 0x2b, 0xf3, | ||
145 | 0x05, 0x57, 0x8e, 0xe8, 0xcf, 0xac, 0x4f, 0x83, | ||
146 | 0xc9, 0xd9, 0xd5, 0x41, 0xbe, 0x94, 0xe2, 0xb4, | ||
147 | 0x67, 0x27, 0xde, 0xf0, 0x80, 0xb1, 0x32, 0x35, | ||
148 | 0x6d, 0x45, 0x21, 0x12, 0x2c, 0x0d, 0xf4, 0x38, | ||
149 | 0x06, 0x9b, 0x58, 0x1a, 0x8f, 0x79, 0xe9, 0x70, | ||
150 | 0xd0, 0xc2, 0xad, 0xa8, 0x50, 0x75, 0x84, 0x48, | ||
151 | 0xca, 0xfc, 0xda, 0x8a, 0xd6, 0x54, 0x42, 0x24, | ||
152 | 0xbf, 0x98, 0x95, 0xf9, 0xe3, 0x5e, 0xb5, 0x15, | ||
153 | 0x68, 0x61, 0x28, 0xba, 0xdf, 0x4c, 0xf1, 0x2f, | ||
154 | 0x81, 0xe6, 0xb2, 0x3f, 0x33, 0xee, 0x36, 0x10, | ||
155 | 0x6e, 0x18, 0x46, 0xa6, 0x22, 0x88, 0x13, 0xf7, | ||
156 | 0x2d, 0xb8, 0x0e, 0x3d, 0xf5, 0xa4, 0x39, 0x3b, | ||
157 | 0x07, 0x9e, 0x9c, 0x9d, 0x59, 0x9f, 0x1b, 0x08, | ||
158 | 0x90, 0x09, 0x7a, 0x1c, 0xea, 0xa0, 0x71, 0x5a, | ||
159 | 0xd1, 0x1d, 0xc3, 0x7b, 0xae, 0x0a, 0xa9, 0x91, | ||
160 | 0x51, 0x5b, 0x76, 0x72, 0x85, 0xa1, 0x49, 0xeb, | ||
161 | 0xcb, 0x7c, 0xfd, 0xc4, 0xdb, 0x1e, 0x8b, 0xd2, | ||
162 | 0xd7, 0x92, 0x55, 0xaa, 0x43, 0x0b, 0x25, 0xaf, | ||
163 | 0xc0, 0x73, 0x99, 0x77, 0x96, 0x5c, 0xfa, 0x52, | ||
164 | 0xe4, 0xec, 0x5f, 0x4a, 0xb6, 0xa2, 0x16, 0x86, | ||
165 | 0x69, 0xc5, 0x62, 0xfe, 0x29, 0x7d, 0xbb, 0xcc, | ||
166 | 0xe0, 0xd3, 0x4d, 0x8c, 0xf2, 0x1f, 0x30, 0xdc, | ||
167 | 0x82, 0xab, 0xe7, 0x56, 0xb3, 0x93, 0x40, 0xd8, | ||
168 | 0x34, 0xb0, 0xef, 0x26, 0x37, 0x0c, 0x11, 0x44, | ||
169 | 0x6f, 0x78, 0x19, 0x9a, 0x47, 0x74, 0xa7, 0xc1, | ||
170 | 0x23, 0x53, 0x89, 0xfb, 0x14, 0x5d, 0xf8, 0x97, | ||
171 | 0x2e, 0x4b, 0xb9, 0x60, 0x0f, 0xed, 0x3e, 0xe5, | ||
172 | 0xf6, 0x87, 0xa5, 0x17, 0x3a, 0xa3, 0x3c, 0xb7 | ||
173 | }; | ||
174 | |||
175 | /* This is a multiplication table for the factor 0xc0 (i.e., r^105 (mod f(r)). | ||
176 | * gfmul_c0[f] returns r^105 * f(r) (modulo f(r)). | ||
177 | */ | ||
178 | static const __u8 gfmul_c0[256] = | ||
179 | { | ||
180 | 0x00, 0xc0, 0x07, 0xc7, 0x0e, 0xce, 0x09, 0xc9, | ||
181 | 0x1c, 0xdc, 0x1b, 0xdb, 0x12, 0xd2, 0x15, 0xd5, | ||
182 | 0x38, 0xf8, 0x3f, 0xff, 0x36, 0xf6, 0x31, 0xf1, | ||
183 | 0x24, 0xe4, 0x23, 0xe3, 0x2a, 0xea, 0x2d, 0xed, | ||
184 | 0x70, 0xb0, 0x77, 0xb7, 0x7e, 0xbe, 0x79, 0xb9, | ||
185 | 0x6c, 0xac, 0x6b, 0xab, 0x62, 0xa2, 0x65, 0xa5, | ||
186 | 0x48, 0x88, 0x4f, 0x8f, 0x46, 0x86, 0x41, 0x81, | ||
187 | 0x54, 0x94, 0x53, 0x93, 0x5a, 0x9a, 0x5d, 0x9d, | ||
188 | 0xe0, 0x20, 0xe7, 0x27, 0xee, 0x2e, 0xe9, 0x29, | ||
189 | 0xfc, 0x3c, 0xfb, 0x3b, 0xf2, 0x32, 0xf5, 0x35, | ||
190 | 0xd8, 0x18, 0xdf, 0x1f, 0xd6, 0x16, 0xd1, 0x11, | ||
191 | 0xc4, 0x04, 0xc3, 0x03, 0xca, 0x0a, 0xcd, 0x0d, | ||
192 | 0x90, 0x50, 0x97, 0x57, 0x9e, 0x5e, 0x99, 0x59, | ||
193 | 0x8c, 0x4c, 0x8b, 0x4b, 0x82, 0x42, 0x85, 0x45, | ||
194 | 0xa8, 0x68, 0xaf, 0x6f, 0xa6, 0x66, 0xa1, 0x61, | ||
195 | 0xb4, 0x74, 0xb3, 0x73, 0xba, 0x7a, 0xbd, 0x7d, | ||
196 | 0x47, 0x87, 0x40, 0x80, 0x49, 0x89, 0x4e, 0x8e, | ||
197 | 0x5b, 0x9b, 0x5c, 0x9c, 0x55, 0x95, 0x52, 0x92, | ||
198 | 0x7f, 0xbf, 0x78, 0xb8, 0x71, 0xb1, 0x76, 0xb6, | ||
199 | 0x63, 0xa3, 0x64, 0xa4, 0x6d, 0xad, 0x6a, 0xaa, | ||
200 | 0x37, 0xf7, 0x30, 0xf0, 0x39, 0xf9, 0x3e, 0xfe, | ||
201 | 0x2b, 0xeb, 0x2c, 0xec, 0x25, 0xe5, 0x22, 0xe2, | ||
202 | 0x0f, 0xcf, 0x08, 0xc8, 0x01, 0xc1, 0x06, 0xc6, | ||
203 | 0x13, 0xd3, 0x14, 0xd4, 0x1d, 0xdd, 0x1a, 0xda, | ||
204 | 0xa7, 0x67, 0xa0, 0x60, 0xa9, 0x69, 0xae, 0x6e, | ||
205 | 0xbb, 0x7b, 0xbc, 0x7c, 0xb5, 0x75, 0xb2, 0x72, | ||
206 | 0x9f, 0x5f, 0x98, 0x58, 0x91, 0x51, 0x96, 0x56, | ||
207 | 0x83, 0x43, 0x84, 0x44, 0x8d, 0x4d, 0x8a, 0x4a, | ||
208 | 0xd7, 0x17, 0xd0, 0x10, 0xd9, 0x19, 0xde, 0x1e, | ||
209 | 0xcb, 0x0b, 0xcc, 0x0c, 0xc5, 0x05, 0xc2, 0x02, | ||
210 | 0xef, 0x2f, 0xe8, 0x28, 0xe1, 0x21, 0xe6, 0x26, | ||
211 | 0xf3, 0x33, 0xf4, 0x34, 0xfd, 0x3d, 0xfa, 0x3a | ||
212 | }; | ||
213 | |||
214 | |||
215 | /* Returns V modulo 255 provided V is in the range -255,-254,...,509. | ||
216 | */ | ||
217 | static inline __u8 mod255(int v) | ||
218 | { | ||
219 | if (v > 0) { | ||
220 | if (v < 255) { | ||
221 | return v; | ||
222 | } else { | ||
223 | return v - 255; | ||
224 | } | ||
225 | } else { | ||
226 | return v + 255; | ||
227 | } | ||
228 | } | ||
229 | |||
230 | |||
231 | /* Add two numbers in the field. Addition in this field is equivalent | ||
232 | * to a bit-wise exclusive OR operation---subtraction is therefore | ||
233 | * identical to addition. | ||
234 | */ | ||
235 | static inline __u8 gfadd(__u8 a, __u8 b) | ||
236 | { | ||
237 | return a ^ b; | ||
238 | } | ||
239 | |||
240 | |||
241 | /* Add two vectors of numbers in the field. Each byte in A and B gets | ||
242 | * added individually. | ||
243 | */ | ||
244 | static inline unsigned long gfadd_long(unsigned long a, unsigned long b) | ||
245 | { | ||
246 | return a ^ b; | ||
247 | } | ||
248 | |||
249 | |||
250 | /* Multiply two numbers in the field: | ||
251 | */ | ||
252 | static inline __u8 gfmul(__u8 a, __u8 b) | ||
253 | { | ||
254 | if (a && b) { | ||
255 | return gfpow[mod255(gflog[a] + gflog[b])]; | ||
256 | } else { | ||
257 | return 0; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | |||
262 | /* Just like gfmul, except we have already looked up the log of the | ||
263 | * second number. | ||
264 | */ | ||
265 | static inline __u8 gfmul_exp(__u8 a, int b) | ||
266 | { | ||
267 | if (a) { | ||
268 | return gfpow[mod255(gflog[a] + b)]; | ||
269 | } else { | ||
270 | return 0; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | |||
275 | /* Just like gfmul_exp, except that A is a vector of numbers. That | ||
276 | * is, each byte in A gets multiplied by gfpow[mod255(B)]. | ||
277 | */ | ||
278 | static inline unsigned long gfmul_exp_long(unsigned long a, int b) | ||
279 | { | ||
280 | __u8 t; | ||
281 | |||
282 | if (sizeof(long) == 4) { | ||
283 | return ( | ||
284 | ((t = (__u32)a >> 24 & 0xff) ? | ||
285 | (((__u32) gfpow[mod255(gflog[t] + b)]) << 24) : 0) | | ||
286 | ((t = (__u32)a >> 16 & 0xff) ? | ||
287 | (((__u32) gfpow[mod255(gflog[t] + b)]) << 16) : 0) | | ||
288 | ((t = (__u32)a >> 8 & 0xff) ? | ||
289 | (((__u32) gfpow[mod255(gflog[t] + b)]) << 8) : 0) | | ||
290 | ((t = (__u32)a >> 0 & 0xff) ? | ||
291 | (((__u32) gfpow[mod255(gflog[t] + b)]) << 0) : 0)); | ||
292 | } else if (sizeof(long) == 8) { | ||
293 | return ( | ||
294 | ((t = (__u64)a >> 56 & 0xff) ? | ||
295 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 56) : 0) | | ||
296 | ((t = (__u64)a >> 48 & 0xff) ? | ||
297 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 48) : 0) | | ||
298 | ((t = (__u64)a >> 40 & 0xff) ? | ||
299 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 40) : 0) | | ||
300 | ((t = (__u64)a >> 32 & 0xff) ? | ||
301 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 32) : 0) | | ||
302 | ((t = (__u64)a >> 24 & 0xff) ? | ||
303 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 24) : 0) | | ||
304 | ((t = (__u64)a >> 16 & 0xff) ? | ||
305 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 16) : 0) | | ||
306 | ((t = (__u64)a >> 8 & 0xff) ? | ||
307 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 8) : 0) | | ||
308 | ((t = (__u64)a >> 0 & 0xff) ? | ||
309 | (((__u64) gfpow[mod255(gflog[t] + b)]) << 0) : 0)); | ||
310 | } else { | ||
311 | TRACE_FUN(ft_t_any); | ||
312 | TRACE_ABORT(-1, ft_t_err, "Error: size of long is %d bytes", | ||
313 | (int)sizeof(long)); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | |||
318 | /* Divide two numbers in the field. Returns a/b (modulo f(x)). | ||
319 | */ | ||
320 | static inline __u8 gfdiv(__u8 a, __u8 b) | ||
321 | { | ||
322 | if (!b) { | ||
323 | TRACE_FUN(ft_t_any); | ||
324 | TRACE_ABORT(0xff, ft_t_bug, "Error: division by zero"); | ||
325 | } else if (a == 0) { | ||
326 | return 0; | ||
327 | } else { | ||
328 | return gfpow[mod255(gflog[a] - gflog[b])]; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | |||
333 | /* The following functions return the inverse of the matrix of the | ||
334 | * linear system that needs to be solved to determine the error | ||
335 | * magnitudes. The first deals with matrices of rank 3, while the | ||
336 | * second deals with matrices of rank 2. The error indices are passed | ||
337 | * in arguments L0,..,L2 (0=first sector, 31=last sector). The error | ||
338 | * indices must be sorted in ascending order, i.e., L0<L1<L2. | ||
339 | * | ||
340 | * The linear system that needs to be solved for the error magnitudes | ||
341 | * is A * b = s, where s is the known vector of syndromes, b is the | ||
342 | * vector of error magnitudes and A in the ORDER=3 case: | ||
343 | * | ||
344 | * A_3 = {{1/r^L[0], 1/r^L[1], 1/r^L[2]}, | ||
345 | * { 1, 1, 1}, | ||
346 | * { r^L[0], r^L[1], r^L[2]}} | ||
347 | */ | ||
348 | static inline int gfinv3(__u8 l0, | ||
349 | __u8 l1, | ||
350 | __u8 l2, | ||
351 | Matrix Ainv) | ||
352 | { | ||
353 | __u8 det; | ||
354 | __u8 t20, t10, t21, t12, t01, t02; | ||
355 | int log_det; | ||
356 | |||
357 | /* compute some intermediate results: */ | ||
358 | t20 = gfpow[l2 - l0]; /* t20 = r^l2/r^l0 */ | ||
359 | t10 = gfpow[l1 - l0]; /* t10 = r^l1/r^l0 */ | ||
360 | t21 = gfpow[l2 - l1]; /* t21 = r^l2/r^l1 */ | ||
361 | t12 = gfpow[l1 - l2 + 255]; /* t12 = r^l1/r^l2 */ | ||
362 | t01 = gfpow[l0 - l1 + 255]; /* t01 = r^l0/r^l1 */ | ||
363 | t02 = gfpow[l0 - l2 + 255]; /* t02 = r^l0/r^l2 */ | ||
364 | /* Calculate the determinant of matrix A_3^-1 (sometimes | ||
365 | * called the Vandermonde determinant): | ||
366 | */ | ||
367 | det = gfadd(t20, gfadd(t10, gfadd(t21, gfadd(t12, gfadd(t01, t02))))); | ||
368 | if (!det) { | ||
369 | TRACE_FUN(ft_t_any); | ||
370 | TRACE_ABORT(0, ft_t_err, | ||
371 | "Inversion failed (3 CRC errors, >0 CRC failures)"); | ||
372 | } | ||
373 | log_det = 255 - gflog[det]; | ||
374 | |||
375 | /* Now, calculate all of the coefficients: | ||
376 | */ | ||
377 | Ainv[0][0]= gfmul_exp(gfadd(gfpow[l1], gfpow[l2]), log_det); | ||
378 | Ainv[0][1]= gfmul_exp(gfadd(t21, t12), log_det); | ||
379 | Ainv[0][2]= gfmul_exp(gfadd(gfpow[255 - l1], gfpow[255 - l2]),log_det); | ||
380 | |||
381 | Ainv[1][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l2]), log_det); | ||
382 | Ainv[1][1]= gfmul_exp(gfadd(t20, t02), log_det); | ||
383 | Ainv[1][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l2]),log_det); | ||
384 | |||
385 | Ainv[2][0]= gfmul_exp(gfadd(gfpow[l0], gfpow[l1]), log_det); | ||
386 | Ainv[2][1]= gfmul_exp(gfadd(t10, t01), log_det); | ||
387 | Ainv[2][2]= gfmul_exp(gfadd(gfpow[255 - l0], gfpow[255 - l1]),log_det); | ||
388 | |||
389 | return 1; | ||
390 | } | ||
391 | |||
392 | |||
393 | static inline int gfinv2(__u8 l0, __u8 l1, Matrix Ainv) | ||
394 | { | ||
395 | __u8 det; | ||
396 | __u8 t1, t2; | ||
397 | int log_det; | ||
398 | |||
399 | t1 = gfpow[255 - l0]; | ||
400 | t2 = gfpow[255 - l1]; | ||
401 | det = gfadd(t1, t2); | ||
402 | if (!det) { | ||
403 | TRACE_FUN(ft_t_any); | ||
404 | TRACE_ABORT(0, ft_t_err, | ||
405 | "Inversion failed (2 CRC errors, >0 CRC failures)"); | ||
406 | } | ||
407 | log_det = 255 - gflog[det]; | ||
408 | |||
409 | /* Now, calculate all of the coefficients: | ||
410 | */ | ||
411 | Ainv[0][0] = Ainv[1][0] = gfpow[log_det]; | ||
412 | |||
413 | Ainv[0][1] = gfmul_exp(t2, log_det); | ||
414 | Ainv[1][1] = gfmul_exp(t1, log_det); | ||
415 | |||
416 | return 1; | ||
417 | } | ||
418 | |||
419 | |||
420 | /* Multiply matrix A by vector S and return result in vector B. M is | ||
421 | * assumed to be of order NxN, S and B of order Nx1. | ||
422 | */ | ||
423 | static inline void gfmat_mul(int n, Matrix A, | ||
424 | __u8 *s, __u8 *b) | ||
425 | { | ||
426 | int i, j; | ||
427 | __u8 dot_prod; | ||
428 | |||
429 | for (i = 0; i < n; ++i) { | ||
430 | dot_prod = 0; | ||
431 | for (j = 0; j < n; ++j) { | ||
432 | dot_prod = gfadd(dot_prod, gfmul(A[i][j], s[j])); | ||
433 | } | ||
434 | b[i] = dot_prod; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | |||
439 | |||
440 | /* The Reed Solomon ECC codes are computed over the N-th byte of each | ||
441 | * block, where N=SECTOR_SIZE. There are up to 29 blocks of data, and | ||
442 | * 3 blocks of ECC. The blocks are stored contiguously in memory. A | ||
443 | * segment, consequently, is assumed to have at least 4 blocks: one or | ||
444 | * more data blocks plus three ECC blocks. | ||
445 | * | ||
446 | * Notice: In QIC-80 speak, a CRC error is a sector with an incorrect | ||
447 | * CRC. A CRC failure is a sector with incorrect data, but | ||
448 | * a valid CRC. In the error control literature, the former | ||
449 | * is usually called "erasure", the latter "error." | ||
450 | */ | ||
451 | /* Compute the parity bytes for C columns of data, where C is the | ||
452 | * number of bytes that fit into a long integer. We use a linear | ||
453 | * feed-back register to do this. The parity bytes P[0], P[STRIDE], | ||
454 | * P[2*STRIDE] are computed such that: | ||
455 | * | ||
456 | * x^k * p(x) + m(x) = 0 (modulo g(x)) | ||
457 | * | ||
458 | * where k = NBLOCKS, | ||
459 | * p(x) = P[0] + P[STRIDE]*x + P[2*STRIDE]*x^2, and | ||
460 | * m(x) = sum_{i=0}^k m_i*x^i. | ||
461 | * m_i = DATA[i*SECTOR_SIZE] | ||
462 | */ | ||
463 | static inline void set_parity(unsigned long *data, | ||
464 | int nblocks, | ||
465 | unsigned long *p, | ||
466 | int stride) | ||
467 | { | ||
468 | unsigned long p0, p1, p2, t1, t2, *end; | ||
469 | |||
470 | end = data + nblocks * (FT_SECTOR_SIZE / sizeof(long)); | ||
471 | p0 = p1 = p2 = 0; | ||
472 | while (data < end) { | ||
473 | /* The new parity bytes p0_i, p1_i, p2_i are computed | ||
474 | * from the old values p0_{i-1}, p1_{i-1}, p2_{i-1} | ||
475 | * recursively as: | ||
476 | * | ||
477 | * p0_i = p1_{i-1} + r^105 * (m_{i-1} - p0_{i-1}) | ||
478 | * p1_i = p2_{i-1} + r^105 * (m_{i-1} - p0_{i-1}) | ||
479 | * p2_i = (m_{i-1} - p0_{i-1}) | ||
480 | * | ||
481 | * With the initial condition: p0_0 = p1_0 = p2_0 = 0. | ||
482 | */ | ||
483 | t1 = gfadd_long(*data, p0); | ||
484 | /* | ||
485 | * Multiply each byte in t1 by 0xc0: | ||
486 | */ | ||
487 | if (sizeof(long) == 4) { | ||
488 | t2= (((__u32) gfmul_c0[(__u32)t1 >> 24 & 0xff]) << 24 | | ||
489 | ((__u32) gfmul_c0[(__u32)t1 >> 16 & 0xff]) << 16 | | ||
490 | ((__u32) gfmul_c0[(__u32)t1 >> 8 & 0xff]) << 8 | | ||
491 | ((__u32) gfmul_c0[(__u32)t1 >> 0 & 0xff]) << 0); | ||
492 | } else if (sizeof(long) == 8) { | ||
493 | t2= (((__u64) gfmul_c0[(__u64)t1 >> 56 & 0xff]) << 56 | | ||
494 | ((__u64) gfmul_c0[(__u64)t1 >> 48 & 0xff]) << 48 | | ||
495 | ((__u64) gfmul_c0[(__u64)t1 >> 40 & 0xff]) << 40 | | ||
496 | ((__u64) gfmul_c0[(__u64)t1 >> 32 & 0xff]) << 32 | | ||
497 | ((__u64) gfmul_c0[(__u64)t1 >> 24 & 0xff]) << 24 | | ||
498 | ((__u64) gfmul_c0[(__u64)t1 >> 16 & 0xff]) << 16 | | ||
499 | ((__u64) gfmul_c0[(__u64)t1 >> 8 & 0xff]) << 8 | | ||
500 | ((__u64) gfmul_c0[(__u64)t1 >> 0 & 0xff]) << 0); | ||
501 | } else { | ||
502 | TRACE_FUN(ft_t_any); | ||
503 | TRACE(ft_t_err, "Error: long is of size %d", | ||
504 | (int) sizeof(long)); | ||
505 | TRACE_EXIT; | ||
506 | } | ||
507 | p0 = gfadd_long(t2, p1); | ||
508 | p1 = gfadd_long(t2, p2); | ||
509 | p2 = t1; | ||
510 | data += FT_SECTOR_SIZE / sizeof(long); | ||
511 | } | ||
512 | *p = p0; | ||
513 | p += stride; | ||
514 | *p = p1; | ||
515 | p += stride; | ||
516 | *p = p2; | ||
517 | return; | ||
518 | } | ||
519 | |||
520 | |||
521 | /* Compute the 3 syndrome values. DATA should point to the first byte | ||
522 | * of the column for which the syndromes are desired. The syndromes | ||
523 | * are computed over the first NBLOCKS of rows. The three bytes will | ||
524 | * be placed in S[0], S[1], and S[2]. | ||
525 | * | ||
526 | * S[i] is the value of the "message" polynomial m(x) evaluated at the | ||
527 | * i-th root of the generator polynomial g(x). | ||
528 | * | ||
529 | * As g(x)=(x-r^-1)(x-1)(x-r^1) we evaluate the message polynomial at | ||
530 | * x=r^-1 to get S[0], at x=r^0=1 to get S[1], and at x=r to get S[2]. | ||
531 | * This could be done directly and efficiently via the Horner scheme. | ||
532 | * However, it would require multiplication tables for the factors | ||
533 | * r^-1 (0xc3) and r (0x02). The following scheme does not require | ||
534 | * any multiplication tables beyond what's needed for set_parity() | ||
535 | * anyway and is slightly faster if there are no errors and slightly | ||
536 | * slower if there are errors. The latter is hopefully the infrequent | ||
537 | * case. | ||
538 | * | ||
539 | * To understand the alternative algorithm, notice that set_parity(m, | ||
540 | * k, p) computes parity bytes such that: | ||
541 | * | ||
542 | * x^k * p(x) = m(x) (modulo g(x)). | ||
543 | * | ||
544 | * That is, to evaluate m(r^m), where r^m is a root of g(x), we can | ||
545 | * simply evaluate (r^m)^k*p(r^m). Also, notice that p is 0 if and | ||
546 | * only if s is zero. That is, if all parity bytes are 0, we know | ||
547 | * there is no error in the data and consequently there is no need to | ||
548 | * compute s(x) at all! In all other cases, we compute s(x) from p(x) | ||
549 | * by evaluating (r^m)^k*p(r^m) for m=-1, m=0, and m=1. The p(x) | ||
550 | * polynomial is evaluated via the Horner scheme. | ||
551 | */ | ||
552 | static int compute_syndromes(unsigned long *data, int nblocks, unsigned long *s) | ||
553 | { | ||
554 | unsigned long p[3]; | ||
555 | |||
556 | set_parity(data, nblocks, p, 1); | ||
557 | if (p[0] | p[1] | p[2]) { | ||
558 | /* Some of the checked columns do not have a zero | ||
559 | * syndrome. For simplicity, we compute the syndromes | ||
560 | * for all columns that we have computed the | ||
561 | * remainders for. | ||
562 | */ | ||
563 | s[0] = gfmul_exp_long( | ||
564 | gfadd_long(p[0], | ||
565 | gfmul_exp_long( | ||
566 | gfadd_long(p[1], | ||
567 | gfmul_exp_long(p[2], -1)), | ||
568 | -1)), | ||
569 | -nblocks); | ||
570 | s[1] = gfadd_long(gfadd_long(p[2], p[1]), p[0]); | ||
571 | s[2] = gfmul_exp_long( | ||
572 | gfadd_long(p[0], | ||
573 | gfmul_exp_long( | ||
574 | gfadd_long(p[1], | ||
575 | gfmul_exp_long(p[2], 1)), | ||
576 | 1)), | ||
577 | nblocks); | ||
578 | return 0; | ||
579 | } else { | ||
580 | return 1; | ||
581 | } | ||
582 | } | ||
583 | |||
584 | |||
585 | /* Correct the block in the column pointed to by DATA. There are NBAD | ||
586 | * CRC errors and their indices are in BAD_LOC[0], up to | ||
587 | * BAD_LOC[NBAD-1]. If NBAD>1, Ainv holds the inverse of the matrix | ||
588 | * of the linear system that needs to be solved to determine the error | ||
589 | * magnitudes. S[0], S[1], and S[2] are the syndrome values. If row | ||
590 | * j gets corrected, then bit j will be set in CORRECTION_MAP. | ||
591 | */ | ||
592 | static inline int correct_block(__u8 *data, int nblocks, | ||
593 | int nbad, int *bad_loc, Matrix Ainv, | ||
594 | __u8 *s, | ||
595 | SectorMap * correction_map) | ||
596 | { | ||
597 | int ncorrected = 0; | ||
598 | int i; | ||
599 | __u8 t1, t2; | ||
600 | __u8 c0, c1, c2; /* check bytes */ | ||
601 | __u8 error_mag[3], log_error_mag; | ||
602 | __u8 *dp, l, e; | ||
603 | TRACE_FUN(ft_t_any); | ||
604 | |||
605 | switch (nbad) { | ||
606 | case 0: | ||
607 | /* might have a CRC failure: */ | ||
608 | if (s[0] == 0) { | ||
609 | /* more than one error */ | ||
610 | TRACE_ABORT(-1, ft_t_err, | ||
611 | "ECC failed (0 CRC errors, >1 CRC failures)"); | ||
612 | } | ||
613 | t1 = gfdiv(s[1], s[0]); | ||
614 | if ((bad_loc[nbad++] = gflog[t1]) >= nblocks) { | ||
615 | TRACE(ft_t_err, | ||
616 | "ECC failed (0 CRC errors, >1 CRC failures)"); | ||
617 | TRACE_ABORT(-1, ft_t_err, | ||
618 | "attempt to correct data at %d", bad_loc[0]); | ||
619 | } | ||
620 | error_mag[0] = s[1]; | ||
621 | break; | ||
622 | case 1: | ||
623 | t1 = gfadd(gfmul_exp(s[1], bad_loc[0]), s[2]); | ||
624 | t2 = gfadd(gfmul_exp(s[0], bad_loc[0]), s[1]); | ||
625 | if (t1 == 0 && t2 == 0) { | ||
626 | /* one erasure, no error: */ | ||
627 | Ainv[0][0] = gfpow[bad_loc[0]]; | ||
628 | } else if (t1 == 0 || t2 == 0) { | ||
629 | /* one erasure and more than one error: */ | ||
630 | TRACE_ABORT(-1, ft_t_err, | ||
631 | "ECC failed (1 erasure, >1 error)"); | ||
632 | } else { | ||
633 | /* one erasure, one error: */ | ||
634 | if ((bad_loc[nbad++] = gflog[gfdiv(t1, t2)]) | ||
635 | >= nblocks) { | ||
636 | TRACE(ft_t_err, "ECC failed " | ||
637 | "(1 CRC errors, >1 CRC failures)"); | ||
638 | TRACE_ABORT(-1, ft_t_err, | ||
639 | "attempt to correct data at %d", | ||
640 | bad_loc[1]); | ||
641 | } | ||
642 | if (!gfinv2(bad_loc[0], bad_loc[1], Ainv)) { | ||
643 | /* inversion failed---must have more | ||
644 | * than one error | ||
645 | */ | ||
646 | TRACE_EXIT -1; | ||
647 | } | ||
648 | } | ||
649 | /* FALL THROUGH TO ERROR MAGNITUDE COMPUTATION: | ||
650 | */ | ||
651 | case 2: | ||
652 | case 3: | ||
653 | /* compute error magnitudes: */ | ||
654 | gfmat_mul(nbad, Ainv, s, error_mag); | ||
655 | break; | ||
656 | |||
657 | default: | ||
658 | TRACE_ABORT(-1, ft_t_err, | ||
659 | "Internal Error: number of CRC errors > 3"); | ||
660 | } | ||
661 | |||
662 | /* Perform correction by adding ERROR_MAG[i] to the byte at | ||
663 | * offset BAD_LOC[i]. Also add the value of the computed | ||
664 | * error polynomial to the syndrome values. If the correction | ||
665 | * was successful, the resulting check bytes should be zero | ||
666 | * (i.e., the corrected data is a valid code word). | ||
667 | */ | ||
668 | c0 = s[0]; | ||
669 | c1 = s[1]; | ||
670 | c2 = s[2]; | ||
671 | for (i = 0; i < nbad; ++i) { | ||
672 | e = error_mag[i]; | ||
673 | if (e) { | ||
674 | /* correct the byte at offset L by magnitude E: */ | ||
675 | l = bad_loc[i]; | ||
676 | dp = &data[l * FT_SECTOR_SIZE]; | ||
677 | *dp = gfadd(*dp, e); | ||
678 | *correction_map |= 1 << l; | ||
679 | ++ncorrected; | ||
680 | |||
681 | log_error_mag = gflog[e]; | ||
682 | c0 = gfadd(c0, gfpow[mod255(log_error_mag - l)]); | ||
683 | c1 = gfadd(c1, e); | ||
684 | c2 = gfadd(c2, gfpow[mod255(log_error_mag + l)]); | ||
685 | } | ||
686 | } | ||
687 | if (c0 || c1 || c2) { | ||
688 | TRACE_ABORT(-1, ft_t_err, | ||
689 | "ECC self-check failed, too many errors"); | ||
690 | } | ||
691 | TRACE_EXIT ncorrected; | ||
692 | } | ||
693 | |||
694 | |||
695 | #if defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID) | ||
696 | |||
697 | /* Perform a sanity check on the computed parity bytes: | ||
698 | */ | ||
699 | static int sanity_check(unsigned long *data, int nblocks) | ||
700 | { | ||
701 | TRACE_FUN(ft_t_any); | ||
702 | unsigned long s[3]; | ||
703 | |||
704 | if (!compute_syndromes(data, nblocks, s)) { | ||
705 | TRACE_ABORT(0, ft_bug, | ||
706 | "Internal Error: syndrome self-check failed"); | ||
707 | } | ||
708 | TRACE_EXIT 1; | ||
709 | } | ||
710 | |||
711 | #endif /* defined(ECC_SANITY_CHECK) || defined(ECC_PARANOID) */ | ||
712 | |||
713 | /* Compute the parity for an entire segment of data. | ||
714 | */ | ||
715 | int ftape_ecc_set_segment_parity(struct memory_segment *mseg) | ||
716 | { | ||
717 | int i; | ||
718 | __u8 *parity_bytes; | ||
719 | |||
720 | parity_bytes = &mseg->data[(mseg->blocks - 3) * FT_SECTOR_SIZE]; | ||
721 | for (i = 0; i < FT_SECTOR_SIZE; i += sizeof(long)) { | ||
722 | set_parity((unsigned long *) &mseg->data[i], mseg->blocks - 3, | ||
723 | (unsigned long *) &parity_bytes[i], | ||
724 | FT_SECTOR_SIZE / sizeof(long)); | ||
725 | #ifdef ECC_PARANOID | ||
726 | if (!sanity_check((unsigned long *) &mseg->data[i], | ||
727 | mseg->blocks)) { | ||
728 | return -1; | ||
729 | } | ||
730 | #endif /* ECC_PARANOID */ | ||
731 | } | ||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | |||
736 | /* Checks and corrects (if possible) the segment MSEG. Returns one of | ||
737 | * ECC_OK, ECC_CORRECTED, and ECC_FAILED. | ||
738 | */ | ||
739 | int ftape_ecc_correct_data(struct memory_segment *mseg) | ||
740 | { | ||
741 | int col, i, result; | ||
742 | int ncorrected = 0; | ||
743 | int nerasures = 0; /* # of erasures (CRC errors) */ | ||
744 | int erasure_loc[3]; /* erasure locations */ | ||
745 | unsigned long ss[3]; | ||
746 | __u8 s[3]; | ||
747 | Matrix Ainv; | ||
748 | TRACE_FUN(ft_t_flow); | ||
749 | |||
750 | mseg->corrected = 0; | ||
751 | |||
752 | /* find first column that has non-zero syndromes: */ | ||
753 | for (col = 0; col < FT_SECTOR_SIZE; col += sizeof(long)) { | ||
754 | if (!compute_syndromes((unsigned long *) &mseg->data[col], | ||
755 | mseg->blocks, ss)) { | ||
756 | /* something is wrong---have to fix things */ | ||
757 | break; | ||
758 | } | ||
759 | } | ||
760 | if (col >= FT_SECTOR_SIZE) { | ||
761 | /* all syndromes are ok, therefore nothing to correct */ | ||
762 | TRACE_EXIT ECC_OK; | ||
763 | } | ||
764 | /* count the number of CRC errors if there were any: */ | ||
765 | if (mseg->read_bad) { | ||
766 | for (i = 0; i < mseg->blocks; i++) { | ||
767 | if (BAD_CHECK(mseg->read_bad, i)) { | ||
768 | if (nerasures >= 3) { | ||
769 | /* this is too much for ECC */ | ||
770 | TRACE_ABORT(ECC_FAILED, ft_t_err, | ||
771 | "ECC failed (>3 CRC errors)"); | ||
772 | } /* if */ | ||
773 | erasure_loc[nerasures++] = i; | ||
774 | } | ||
775 | } | ||
776 | } | ||
777 | /* | ||
778 | * If there are at least 2 CRC errors, determine inverse of matrix | ||
779 | * of linear system to be solved: | ||
780 | */ | ||
781 | switch (nerasures) { | ||
782 | case 2: | ||
783 | if (!gfinv2(erasure_loc[0], erasure_loc[1], Ainv)) { | ||
784 | TRACE_EXIT ECC_FAILED; | ||
785 | } | ||
786 | break; | ||
787 | case 3: | ||
788 | if (!gfinv3(erasure_loc[0], erasure_loc[1], | ||
789 | erasure_loc[2], Ainv)) { | ||
790 | TRACE_EXIT ECC_FAILED; | ||
791 | } | ||
792 | break; | ||
793 | default: | ||
794 | /* this is not an error condition... */ | ||
795 | break; | ||
796 | } | ||
797 | |||
798 | do { | ||
799 | for (i = 0; i < sizeof(long); ++i) { | ||
800 | s[0] = ss[0]; | ||
801 | s[1] = ss[1]; | ||
802 | s[2] = ss[2]; | ||
803 | if (s[0] | s[1] | s[2]) { | ||
804 | #ifdef BIG_ENDIAN | ||
805 | result = correct_block( | ||
806 | &mseg->data[col + sizeof(long) - 1 - i], | ||
807 | mseg->blocks, | ||
808 | nerasures, | ||
809 | erasure_loc, | ||
810 | Ainv, | ||
811 | s, | ||
812 | &mseg->corrected); | ||
813 | #else | ||
814 | result = correct_block(&mseg->data[col + i], | ||
815 | mseg->blocks, | ||
816 | nerasures, | ||
817 | erasure_loc, | ||
818 | Ainv, | ||
819 | s, | ||
820 | &mseg->corrected); | ||
821 | #endif | ||
822 | if (result < 0) { | ||
823 | TRACE_EXIT ECC_FAILED; | ||
824 | } | ||
825 | ncorrected += result; | ||
826 | } | ||
827 | ss[0] >>= 8; | ||
828 | ss[1] >>= 8; | ||
829 | ss[2] >>= 8; | ||
830 | } | ||
831 | |||
832 | #ifdef ECC_SANITY_CHECK | ||
833 | if (!sanity_check((unsigned long *) &mseg->data[col], | ||
834 | mseg->blocks)) { | ||
835 | TRACE_EXIT ECC_FAILED; | ||
836 | } | ||
837 | #endif /* ECC_SANITY_CHECK */ | ||
838 | |||
839 | /* find next column with non-zero syndromes: */ | ||
840 | while ((col += sizeof(long)) < FT_SECTOR_SIZE) { | ||
841 | if (!compute_syndromes((unsigned long *) | ||
842 | &mseg->data[col], mseg->blocks, ss)) { | ||
843 | /* something is wrong---have to fix things */ | ||
844 | break; | ||
845 | } | ||
846 | } | ||
847 | } while (col < FT_SECTOR_SIZE); | ||
848 | if (ncorrected && nerasures == 0) { | ||
849 | TRACE(ft_t_warn, "block contained error not caught by CRC"); | ||
850 | } | ||
851 | TRACE((ncorrected > 0) ? ft_t_noise : ft_t_any, "number of corrections: %d", ncorrected); | ||
852 | TRACE_EXIT ncorrected ? ECC_CORRECTED : ECC_OK; | ||
853 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-ecc.h b/drivers/char/ftape/lowlevel/ftape-ecc.h deleted file mode 100644 index 4829146fe9a0..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-ecc.h +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | #ifndef _FTAPE_ECC_H_ | ||
2 | #define _FTAPE_ECC_H_ | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993 Ning and David Mosberger. | ||
6 | * Original: | ||
7 | * Copyright (C) 1993 Bas Laarhoven. | ||
8 | * Copyright (C) 1992 David L. Brown, Jr. | ||
9 | |||
10 | This program is free software; you can redistribute it and/or | ||
11 | modify it under the terms of the GNU General Public License as | ||
12 | published by the Free Software Foundation; either version 2, or (at | ||
13 | your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, but | ||
16 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; see the file COPYING. If not, write to | ||
22 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
23 | USA. | ||
24 | |||
25 | * | ||
26 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ecc.h,v $ | ||
27 | * $Revision: 1.2 $ | ||
28 | * $Date: 1997/10/05 19:18:11 $ | ||
29 | * | ||
30 | * This file contains the definitions for the | ||
31 | * Reed-Solomon error correction code | ||
32 | * for the QIC-40/80 tape streamer device driver. | ||
33 | */ | ||
34 | |||
35 | #include "../lowlevel/ftape-bsm.h" | ||
36 | |||
37 | #define BAD_CLEAR(entry) ((entry)=0) | ||
38 | #define BAD_SET(entry,sector) ((entry)|=(1<<(sector))) | ||
39 | #define BAD_CHECK(entry,sector) ((entry)&(1<<(sector))) | ||
40 | |||
41 | /* | ||
42 | * Return values for ecc_correct_data: | ||
43 | */ | ||
44 | enum { | ||
45 | ECC_OK, /* Data was correct. */ | ||
46 | ECC_CORRECTED, /* Correctable error in data. */ | ||
47 | ECC_FAILED, /* Could not correct data. */ | ||
48 | }; | ||
49 | |||
50 | /* | ||
51 | * Representation of an in memory segment. MARKED_BAD lists the | ||
52 | * sectors that were marked bad during formatting. If the N-th sector | ||
53 | * in a segment is marked bad, bit 1<<N will be set in MARKED_BAD. | ||
54 | * The sectors should be read in from the disk and packed, as if the | ||
55 | * bad sectors were not there, and the segment just contained fewer | ||
56 | * sectors. READ_SECTORS is a bitmap of errors encountered while | ||
57 | * reading the data. These offsets are relative to the packed data. | ||
58 | * BLOCKS is a count of the sectors not marked bad. This is just to | ||
59 | * prevent having to count the zero bits in MARKED_BAD each time this | ||
60 | * is needed. DATA is the actual sector packed data from (or to) the | ||
61 | * tape. | ||
62 | */ | ||
63 | struct memory_segment { | ||
64 | SectorMap marked_bad; | ||
65 | SectorMap read_bad; | ||
66 | int blocks; | ||
67 | __u8 *data; | ||
68 | SectorMap corrected; | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * ecc.c defined global variables: | ||
73 | */ | ||
74 | #ifdef TEST | ||
75 | extern int ftape_ecc_tracing; | ||
76 | #endif | ||
77 | |||
78 | /* | ||
79 | * ecc.c defined global functions: | ||
80 | */ | ||
81 | extern int ftape_ecc_correct_data(struct memory_segment *data); | ||
82 | extern int ftape_ecc_set_segment_parity(struct memory_segment *data); | ||
83 | |||
84 | #endif /* _FTAPE_ECC_H_ */ | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-format.c b/drivers/char/ftape/lowlevel/ftape-format.c deleted file mode 100644 index 5dd4c59a3f34..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-format.c +++ /dev/null | |||
@@ -1,344 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1997 Claus-Justus Heine. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.c,v $ | ||
20 | * $Revision: 1.2.4.1 $ | ||
21 | * $Date: 1997/11/14 16:05:39 $ | ||
22 | * | ||
23 | * This file contains the code to support formatting of floppy | ||
24 | * tape cartridges with the QIC-40/80/3010/3020 floppy-tape | ||
25 | * driver "ftape" for Linux. | ||
26 | */ | ||
27 | |||
28 | #include <linux/string.h> | ||
29 | #include <linux/errno.h> | ||
30 | |||
31 | #include <linux/ftape.h> | ||
32 | #include <linux/qic117.h> | ||
33 | #include "../lowlevel/ftape-tracing.h" | ||
34 | #include "../lowlevel/ftape-io.h" | ||
35 | #include "../lowlevel/ftape-ctl.h" | ||
36 | #include "../lowlevel/ftape-rw.h" | ||
37 | #include "../lowlevel/ftape-ecc.h" | ||
38 | #include "../lowlevel/ftape-bsm.h" | ||
39 | #include "../lowlevel/ftape-format.h" | ||
40 | |||
41 | #if defined(TESTING) | ||
42 | #define FT_FMT_SEGS_PER_BUF 50 | ||
43 | #else | ||
44 | #define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT)) | ||
45 | #endif | ||
46 | |||
47 | static spinlock_t ftape_format_lock; | ||
48 | |||
49 | /* | ||
50 | * first segment of the new buffer | ||
51 | */ | ||
52 | static int switch_segment; | ||
53 | |||
54 | /* | ||
55 | * at most 256 segments fit into one 32 kb buffer. Even TR-1 cartridges have | ||
56 | * more than this many segments per track, so better be careful. | ||
57 | * | ||
58 | * buffer_struct *buff: buffer to store the formatting coordinates in | ||
59 | * int start: starting segment for this buffer. | ||
60 | * int spt: segments per track | ||
61 | * | ||
62 | * Note: segment ids are relative to the start of the track here. | ||
63 | */ | ||
64 | static void setup_format_buffer(buffer_struct *buff, int start, int spt, | ||
65 | __u8 gap3) | ||
66 | { | ||
67 | int to_do = spt - start; | ||
68 | TRACE_FUN(ft_t_flow); | ||
69 | |||
70 | if (to_do > FT_FMT_SEGS_PER_BUF) { | ||
71 | to_do = FT_FMT_SEGS_PER_BUF; | ||
72 | } | ||
73 | buff->ptr = buff->address; | ||
74 | buff->remaining = to_do * FT_SECTORS_PER_SEGMENT; /* # sectors */ | ||
75 | buff->bytes = buff->remaining * 4; /* need 4 bytes per sector */ | ||
76 | buff->gap3 = gap3; | ||
77 | buff->segment_id = start; | ||
78 | buff->next_segment = start + to_do; | ||
79 | if (buff->next_segment >= spt) { | ||
80 | buff->next_segment = 0; /* 0 means: stop runner */ | ||
81 | } | ||
82 | buff->status = waiting; /* tells the isr that it can use | ||
83 | * this buffer | ||
84 | */ | ||
85 | TRACE_EXIT; | ||
86 | } | ||
87 | |||
88 | |||
89 | /* | ||
90 | * start formatting a new track. | ||
91 | */ | ||
92 | int ftape_format_track(const unsigned int track, const __u8 gap3) | ||
93 | { | ||
94 | unsigned long flags; | ||
95 | buffer_struct *tail, *head; | ||
96 | int status; | ||
97 | TRACE_FUN(ft_t_flow); | ||
98 | |||
99 | TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),); | ||
100 | if (track & 1) { | ||
101 | if (!(status & QIC_STATUS_AT_EOT)) { | ||
102 | TRACE_CATCH(ftape_seek_to_eot(),); | ||
103 | } | ||
104 | } else { | ||
105 | if (!(status & QIC_STATUS_AT_BOT)) { | ||
106 | TRACE_CATCH(ftape_seek_to_bot(),); | ||
107 | } | ||
108 | } | ||
109 | ftape_abort_operation(); /* this sets ft_head = ft_tail = 0 */ | ||
110 | ftape_set_state(formatting); | ||
111 | |||
112 | TRACE(ft_t_noise, | ||
113 | "Formatting track %d, logical: from segment %d to %d", | ||
114 | track, track * ft_segments_per_track, | ||
115 | (track + 1) * ft_segments_per_track - 1); | ||
116 | |||
117 | /* | ||
118 | * initialize the buffer switching protocol for this track | ||
119 | */ | ||
120 | head = ftape_get_buffer(ft_queue_head); /* tape isn't running yet */ | ||
121 | tail = ftape_get_buffer(ft_queue_tail); /* tape isn't running yet */ | ||
122 | switch_segment = 0; | ||
123 | do { | ||
124 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
125 | setup_format_buffer(tail, switch_segment, | ||
126 | ft_segments_per_track, gap3); | ||
127 | switch_segment = tail->next_segment; | ||
128 | } while ((switch_segment != 0) && | ||
129 | ((tail = ftape_next_buffer(ft_queue_tail)) != head)); | ||
130 | /* go */ | ||
131 | head->status = formatting; | ||
132 | TRACE_CATCH(ftape_seek_head_to_track(track),); | ||
133 | TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD),); | ||
134 | spin_lock_irqsave(&ftape_format_lock, flags); | ||
135 | TRACE_CATCH(fdc_setup_formatting(head), restore_flags(flags)); | ||
136 | spin_unlock_irqrestore(&ftape_format_lock, flags); | ||
137 | TRACE_EXIT 0; | ||
138 | } | ||
139 | |||
140 | /* return segment id of segment currently being formatted and do the | ||
141 | * buffer switching stuff. | ||
142 | */ | ||
143 | int ftape_format_status(unsigned int *segment_id) | ||
144 | { | ||
145 | buffer_struct *tail = ftape_get_buffer(ft_queue_tail); | ||
146 | int result; | ||
147 | TRACE_FUN(ft_t_flow); | ||
148 | |||
149 | while (switch_segment != 0 && | ||
150 | ftape_get_buffer(ft_queue_head) != tail) { | ||
151 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
152 | /* need more buffers, first wait for empty buffer | ||
153 | */ | ||
154 | TRACE_CATCH(ftape_wait_segment(formatting),); | ||
155 | /* don't worry for gap3. If we ever hit this piece of code, | ||
156 | * then all buffer already have the correct gap3 set! | ||
157 | */ | ||
158 | setup_format_buffer(tail, switch_segment, | ||
159 | ft_segments_per_track, tail->gap3); | ||
160 | switch_segment = tail->next_segment; | ||
161 | if (switch_segment != 0) { | ||
162 | tail = ftape_next_buffer(ft_queue_tail); | ||
163 | } | ||
164 | } | ||
165 | /* should runner stop ? | ||
166 | */ | ||
167 | if (ft_runner_status == aborting || ft_runner_status == do_abort) { | ||
168 | buffer_struct *head = ftape_get_buffer(ft_queue_head); | ||
169 | TRACE(ft_t_warn, "Error formatting segment %d", | ||
170 | ftape_get_buffer(ft_queue_head)->segment_id); | ||
171 | (void)ftape_abort_operation(); | ||
172 | TRACE_EXIT (head->status != error) ? -EAGAIN : -EIO; | ||
173 | } | ||
174 | /* | ||
175 | * don't care if the timer expires, this is just kind of a | ||
176 | * "select" operation that lets the calling process sleep | ||
177 | * until something has happened | ||
178 | */ | ||
179 | if (fdc_interrupt_wait(5 * FT_SECOND) < 0) { | ||
180 | TRACE(ft_t_noise, "End of track %d at segment %d", | ||
181 | ft_location.track, | ||
182 | ftape_get_buffer(ft_queue_head)->segment_id); | ||
183 | result = 1; /* end of track, unlock module */ | ||
184 | } else { | ||
185 | result = 0; | ||
186 | } | ||
187 | /* | ||
188 | * the calling process should use the seg id to determine | ||
189 | * which parts of the dma buffers can be safely overwritten | ||
190 | * with new data. | ||
191 | */ | ||
192 | *segment_id = ftape_get_buffer(ft_queue_head)->segment_id; | ||
193 | /* | ||
194 | * Internally we start counting segment ids from the start of | ||
195 | * each track when formatting, but externally we keep them | ||
196 | * relative to the start of the tape: | ||
197 | */ | ||
198 | *segment_id += ft_location.track * ft_segments_per_track; | ||
199 | TRACE_EXIT result; | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * The segment id is relative to the start of the tape | ||
204 | */ | ||
205 | int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm) | ||
206 | { | ||
207 | int result; | ||
208 | int verify_done = 0; | ||
209 | TRACE_FUN(ft_t_flow); | ||
210 | |||
211 | TRACE(ft_t_noise, "Verifying segment %d", segment_id); | ||
212 | |||
213 | if (ft_driver_state != verifying) { | ||
214 | TRACE(ft_t_noise, "calling ftape_abort_operation"); | ||
215 | if (ftape_abort_operation() < 0) { | ||
216 | TRACE(ft_t_err, "ftape_abort_operation failed"); | ||
217 | TRACE_EXIT -EIO; | ||
218 | } | ||
219 | } | ||
220 | *bsm = 0x00000000; | ||
221 | ftape_set_state(verifying); | ||
222 | for (;;) { | ||
223 | buffer_struct *tail; | ||
224 | /* | ||
225 | * Allow escape from this loop on signal | ||
226 | */ | ||
227 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
228 | /* | ||
229 | * Search all full buffers for the first matching the | ||
230 | * wanted segment. Clear other buffers on the fly. | ||
231 | */ | ||
232 | tail = ftape_get_buffer(ft_queue_tail); | ||
233 | while (!verify_done && tail->status == done) { | ||
234 | /* | ||
235 | * Allow escape from this loop on signal ! | ||
236 | */ | ||
237 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
238 | if (tail->segment_id == segment_id) { | ||
239 | /* If out buffer is already full, | ||
240 | * return its contents. | ||
241 | */ | ||
242 | TRACE(ft_t_flow, "found segment in cache: %d", | ||
243 | segment_id); | ||
244 | if ((tail->soft_error_map | | ||
245 | tail->hard_error_map) != 0) { | ||
246 | TRACE(ft_t_info,"bsm[%d] = 0x%08lx", | ||
247 | segment_id, | ||
248 | (unsigned long) | ||
249 | (tail->soft_error_map | | ||
250 | tail->hard_error_map)); | ||
251 | *bsm = (tail->soft_error_map | | ||
252 | tail->hard_error_map); | ||
253 | } | ||
254 | verify_done = 1; | ||
255 | } else { | ||
256 | TRACE(ft_t_flow,"zapping segment in cache: %d", | ||
257 | tail->segment_id); | ||
258 | } | ||
259 | tail->status = waiting; | ||
260 | tail = ftape_next_buffer(ft_queue_tail); | ||
261 | } | ||
262 | if (!verify_done && tail->status == verifying) { | ||
263 | if (tail->segment_id == segment_id) { | ||
264 | switch(ftape_wait_segment(verifying)) { | ||
265 | case 0: | ||
266 | break; | ||
267 | case -EINTR: | ||
268 | TRACE_ABORT(-EINTR, ft_t_warn, | ||
269 | "interrupted by " | ||
270 | "non-blockable signal"); | ||
271 | break; | ||
272 | default: | ||
273 | ftape_abort_operation(); | ||
274 | ftape_set_state(verifying); | ||
275 | /* be picky */ | ||
276 | TRACE_ABORT(-EIO, ft_t_warn, | ||
277 | "wait_segment failed"); | ||
278 | } | ||
279 | } else { | ||
280 | /* We're reading the wrong segment, | ||
281 | * stop runner. | ||
282 | */ | ||
283 | TRACE(ft_t_noise, "verifying wrong segment"); | ||
284 | ftape_abort_operation(); | ||
285 | ftape_set_state(verifying); | ||
286 | } | ||
287 | } | ||
288 | /* should runner stop ? | ||
289 | */ | ||
290 | if (ft_runner_status == aborting) { | ||
291 | buffer_struct *head = ftape_get_buffer(ft_queue_head); | ||
292 | if (head->status == error || | ||
293 | head->status == verifying) { | ||
294 | /* no data or overrun error */ | ||
295 | head->status = waiting; | ||
296 | } | ||
297 | TRACE_CATCH(ftape_dumb_stop(),); | ||
298 | } else { | ||
299 | /* If just passed last segment on tape: wait | ||
300 | * for BOT or EOT mark. Sets ft_runner_status to | ||
301 | * idle if at lEOT and successful | ||
302 | */ | ||
303 | TRACE_CATCH(ftape_handle_logical_eot(),); | ||
304 | } | ||
305 | if (verify_done) { | ||
306 | TRACE_EXIT 0; | ||
307 | } | ||
308 | /* Now at least one buffer is idle! | ||
309 | * Restart runner & tape if needed. | ||
310 | */ | ||
311 | /* We could optimize the following a little bit. We know that | ||
312 | * the bad sector map is empty. | ||
313 | */ | ||
314 | tail = ftape_get_buffer(ft_queue_tail); | ||
315 | if (tail->status == waiting) { | ||
316 | buffer_struct *head = ftape_get_buffer(ft_queue_head); | ||
317 | |||
318 | ftape_setup_new_segment(head, segment_id, -1); | ||
319 | ftape_calc_next_cluster(head); | ||
320 | if (ft_runner_status == idle) { | ||
321 | result = ftape_start_tape(segment_id, | ||
322 | head->sector_offset); | ||
323 | switch(result) { | ||
324 | case 0: | ||
325 | break; | ||
326 | case -ETIME: | ||
327 | case -EINTR: | ||
328 | TRACE_ABORT(result, ft_t_err, "Error: " | ||
329 | "segment %d unreachable", | ||
330 | segment_id); | ||
331 | break; | ||
332 | default: | ||
333 | *bsm = EMPTY_SEGMENT; | ||
334 | TRACE_EXIT 0; | ||
335 | break; | ||
336 | } | ||
337 | } | ||
338 | head->status = verifying; | ||
339 | fdc_setup_read_write(head, FDC_VERIFY); | ||
340 | } | ||
341 | } | ||
342 | /* not reached */ | ||
343 | TRACE_EXIT -EIO; | ||
344 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-format.h b/drivers/char/ftape/lowlevel/ftape-format.h deleted file mode 100644 index f15161566643..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-format.h +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | #ifndef _FTAPE_FORMAT_H | ||
2 | #define _FTAPE_FORMAT_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996-1997 Claus-Justus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:18:13 $ | ||
25 | * | ||
26 | * This file contains the low level definitions for the | ||
27 | * formatting support for the QIC-40/80/3010/3020 floppy-tape | ||
28 | * driver "ftape" for Linux. | ||
29 | */ | ||
30 | |||
31 | #ifdef __KERNEL__ | ||
32 | extern int ftape_format_track(const unsigned int track, const __u8 gap3); | ||
33 | extern int ftape_format_status(unsigned int *segment_id); | ||
34 | extern int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm); | ||
35 | #endif /* __KERNEL__ */ | ||
36 | |||
37 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c deleted file mode 100644 index 4998132a81d1..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-init.c +++ /dev/null | |||
@@ -1,160 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * This file contains the code that interfaces the kernel | ||
21 | * for the QIC-40/80/3010/3020 floppy-tape driver for Linux. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/fs.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/signal.h> | ||
29 | #include <linux/major.h> | ||
30 | |||
31 | #include <linux/ftape.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/qic117.h> | ||
34 | #ifdef CONFIG_ZFTAPE | ||
35 | #include <linux/zftape.h> | ||
36 | #endif | ||
37 | |||
38 | #include "../lowlevel/ftape-init.h" | ||
39 | #include "../lowlevel/ftape-io.h" | ||
40 | #include "../lowlevel/ftape-read.h" | ||
41 | #include "../lowlevel/ftape-write.h" | ||
42 | #include "../lowlevel/ftape-ctl.h" | ||
43 | #include "../lowlevel/ftape-rw.h" | ||
44 | #include "../lowlevel/fdc-io.h" | ||
45 | #include "../lowlevel/ftape-buffer.h" | ||
46 | #include "../lowlevel/ftape-proc.h" | ||
47 | #include "../lowlevel/ftape-tracing.h" | ||
48 | |||
49 | |||
50 | #if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL) | ||
51 | static int ft_tracing = -1; | ||
52 | #endif | ||
53 | |||
54 | |||
55 | /* Called by modules package when installing the driver | ||
56 | * or by kernel during the initialization phase | ||
57 | */ | ||
58 | static int __init ftape_init(void) | ||
59 | { | ||
60 | TRACE_FUN(ft_t_flow); | ||
61 | |||
62 | #ifdef MODULE | ||
63 | #ifndef CONFIG_FT_NO_TRACE_AT_ALL | ||
64 | if (ft_tracing != -1) { | ||
65 | ftape_tracing = ft_tracing; | ||
66 | } | ||
67 | #endif | ||
68 | printk(KERN_INFO FTAPE_VERSION "\n"); | ||
69 | if (TRACE_LEVEL >= ft_t_info) { | ||
70 | printk( | ||
71 | KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n" | ||
72 | KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n" | ||
73 | KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n" | ||
74 | KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n"); | ||
75 | } | ||
76 | #else /* !MODULE */ | ||
77 | /* print a short no-nonsense boot message */ | ||
78 | printk(KERN_INFO FTAPE_VERSION "\n"); | ||
79 | #endif /* MODULE */ | ||
80 | TRACE(ft_t_info, "installing QIC-117 floppy tape hardware drive ... "); | ||
81 | TRACE(ft_t_info, "ftape_init @ 0x%p", ftape_init); | ||
82 | /* Allocate the DMA buffers. They are deallocated at cleanup() time. | ||
83 | */ | ||
84 | #ifdef TESTING | ||
85 | #ifdef MODULE | ||
86 | while (ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS) < 0) { | ||
87 | ftape_sleep(FT_SECOND/20); | ||
88 | if (signal_pending(current)) { | ||
89 | (void)ftape_set_nr_buffers(0); | ||
90 | TRACE(ft_t_bug, | ||
91 | "Killed by signal while allocating buffers."); | ||
92 | TRACE_ABORT(-EINTR, | ||
93 | ft_t_bug, "Free up memory and retry"); | ||
94 | } | ||
95 | } | ||
96 | #else | ||
97 | TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS), | ||
98 | (void)ftape_set_nr_buffers(0)); | ||
99 | #endif | ||
100 | #else | ||
101 | TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS), | ||
102 | (void)ftape_set_nr_buffers(0)); | ||
103 | #endif | ||
104 | ft_drive_sel = -1; | ||
105 | ft_failure = 1; /* inhibit any operation but open */ | ||
106 | ftape_udelay_calibrate(); /* must be before fdc_wait_calibrate ! */ | ||
107 | fdc_wait_calibrate(); | ||
108 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) | ||
109 | (void)ftape_proc_init(); | ||
110 | #endif | ||
111 | #ifdef CONFIG_ZFTAPE | ||
112 | (void)zft_init(); | ||
113 | #endif | ||
114 | TRACE_EXIT 0; | ||
115 | } | ||
116 | |||
117 | module_param(ft_fdc_base, uint, 0); | ||
118 | MODULE_PARM_DESC(ft_fdc_base, "Base address of FDC controller."); | ||
119 | module_param(ft_fdc_irq, uint, 0); | ||
120 | MODULE_PARM_DESC(ft_fdc_irq, "IRQ (interrupt channel) to use."); | ||
121 | module_param(ft_fdc_dma, uint, 0); | ||
122 | MODULE_PARM_DESC(ft_fdc_dma, "DMA channel to use."); | ||
123 | module_param(ft_fdc_threshold, uint, 0); | ||
124 | MODULE_PARM_DESC(ft_fdc_threshold, "Threshold of the FDC Fifo."); | ||
125 | module_param(ft_fdc_rate_limit, uint, 0); | ||
126 | MODULE_PARM_DESC(ft_fdc_rate_limit, "Maximal data rate for FDC."); | ||
127 | module_param(ft_probe_fc10, bool, 0); | ||
128 | MODULE_PARM_DESC(ft_probe_fc10, | ||
129 | "If non-zero, probe for a Colorado FC-10/FC-20 controller."); | ||
130 | module_param(ft_mach2, bool, 0); | ||
131 | MODULE_PARM_DESC(ft_mach2, | ||
132 | "If non-zero, probe for a Mountain MACH-2 controller."); | ||
133 | #if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL) | ||
134 | module_param(ft_tracing, int, 0644); | ||
135 | MODULE_PARM_DESC(ft_tracing, | ||
136 | "Amount of debugging output, 0 <= tracing <= 8, default 3."); | ||
137 | #endif | ||
138 | |||
139 | MODULE_AUTHOR( | ||
140 | "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl), " | ||
141 | "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no), " | ||
142 | "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)"); | ||
143 | MODULE_DESCRIPTION( | ||
144 | "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives."); | ||
145 | MODULE_LICENSE("GPL"); | ||
146 | |||
147 | static void __exit ftape_exit(void) | ||
148 | { | ||
149 | TRACE_FUN(ft_t_flow); | ||
150 | |||
151 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) | ||
152 | ftape_proc_destroy(); | ||
153 | #endif | ||
154 | (void)ftape_set_nr_buffers(0); | ||
155 | printk(KERN_INFO "ftape: unloaded.\n"); | ||
156 | TRACE_EXIT; | ||
157 | } | ||
158 | |||
159 | module_init(ftape_init); | ||
160 | module_exit(ftape_exit); | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-init.h b/drivers/char/ftape/lowlevel/ftape-init.h deleted file mode 100644 index 99a7b8ab086f..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-init.h +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | #ifndef _FTAPE_INIT_H | ||
2 | #define _FTAPE_INIT_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-init.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:16 $ | ||
26 | * | ||
27 | * This file contains the definitions for the interface to | ||
28 | * the Linux kernel for floppy tape driver ftape. | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/linkage.h> | ||
33 | #include <linux/signal.h> | ||
34 | |||
35 | #define _NEVER_BLOCK (sigmask(SIGKILL) | sigmask(SIGSTOP)) | ||
36 | #define _DONT_BLOCK (_NEVER_BLOCK | sigmask(SIGINT)) | ||
37 | #define _DO_BLOCK (sigmask(SIGPIPE)) | ||
38 | |||
39 | #ifndef QIC117_TAPE_MAJOR | ||
40 | #define QIC117_TAPE_MAJOR 27 | ||
41 | #endif | ||
42 | |||
43 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-io.c b/drivers/char/ftape/lowlevel/ftape-io.c deleted file mode 100644 index 259015aeff55..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-io.c +++ /dev/null | |||
@@ -1,992 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
3 | * (C) 1996 Kai Harrekilde-Petersen, | ||
4 | * (C) 1997 Claus-Justus Heine. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; see the file COPYING. If not, write to | ||
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | |||
20 | * | ||
21 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.c,v $ | ||
22 | * $Revision: 1.4 $ | ||
23 | * $Date: 1997/11/11 14:02:36 $ | ||
24 | * | ||
25 | * This file contains the general control functions for the | ||
26 | * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. | ||
27 | */ | ||
28 | |||
29 | #include <linux/errno.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <linux/ioctl.h> | ||
34 | #include <linux/mtio.h> | ||
35 | #include <linux/delay.h> | ||
36 | |||
37 | #include <linux/ftape.h> | ||
38 | #include <linux/qic117.h> | ||
39 | #include "../lowlevel/ftape-tracing.h" | ||
40 | #include "../lowlevel/fdc-io.h" | ||
41 | #include "../lowlevel/ftape-io.h" | ||
42 | #include "../lowlevel/ftape-ctl.h" | ||
43 | #include "../lowlevel/ftape-rw.h" | ||
44 | #include "../lowlevel/ftape-write.h" | ||
45 | #include "../lowlevel/ftape-read.h" | ||
46 | #include "../lowlevel/ftape-init.h" | ||
47 | #include "../lowlevel/ftape-calibr.h" | ||
48 | |||
49 | /* Global vars. | ||
50 | */ | ||
51 | /* NOTE: sectors start numbering at 1, all others at 0 ! */ | ||
52 | ft_timeout_table ftape_timeout; | ||
53 | unsigned int ftape_tape_len; | ||
54 | volatile qic117_cmd_t ftape_current_command; | ||
55 | const struct qic117_command_table qic117_cmds[] = QIC117_COMMANDS; | ||
56 | int ftape_might_be_off_track; | ||
57 | |||
58 | /* Local vars. | ||
59 | */ | ||
60 | static int diagnostic_mode; | ||
61 | static unsigned int ftape_udelay_count; | ||
62 | static unsigned int ftape_udelay_time; | ||
63 | |||
64 | void ftape_udelay(unsigned int usecs) | ||
65 | { | ||
66 | volatile int count = (ftape_udelay_count * usecs + | ||
67 | ftape_udelay_count - 1) / ftape_udelay_time; | ||
68 | volatile int i; | ||
69 | |||
70 | while (count-- > 0) { | ||
71 | for (i = 0; i < 20; ++i); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | void ftape_udelay_calibrate(void) | ||
76 | { | ||
77 | ftape_calibrate("ftape_udelay", | ||
78 | ftape_udelay, &ftape_udelay_count, &ftape_udelay_time); | ||
79 | } | ||
80 | |||
81 | /* Delay (msec) routine. | ||
82 | */ | ||
83 | void ftape_sleep(unsigned int time) | ||
84 | { | ||
85 | TRACE_FUN(ft_t_any); | ||
86 | |||
87 | time *= 1000; /* msecs -> usecs */ | ||
88 | if (time < FT_USPT) { | ||
89 | /* Time too small for scheduler, do a busy wait ! */ | ||
90 | ftape_udelay(time); | ||
91 | } else { | ||
92 | long timeout; | ||
93 | unsigned long flags; | ||
94 | unsigned int ticks = (time + FT_USPT - 1) / FT_USPT; | ||
95 | |||
96 | TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks); | ||
97 | timeout = ticks; | ||
98 | save_flags(flags); | ||
99 | sti(); | ||
100 | msleep_interruptible(jiffies_to_msecs(timeout)); | ||
101 | /* Mmm. Isn't current->blocked == 0xffffffff ? | ||
102 | */ | ||
103 | if (signal_pending(current)) { | ||
104 | TRACE(ft_t_err, "awoken by non-blocked signal :-("); | ||
105 | } | ||
106 | restore_flags(flags); | ||
107 | } | ||
108 | TRACE_EXIT; | ||
109 | } | ||
110 | |||
111 | /* send a command or parameter to the drive | ||
112 | * Generates # of step pulses. | ||
113 | */ | ||
114 | static inline int ft_send_to_drive(int arg) | ||
115 | { | ||
116 | /* Always wait for a command_timeout period to separate | ||
117 | * individuals commands and/or parameters. | ||
118 | */ | ||
119 | ftape_sleep(3 * FT_MILLISECOND); | ||
120 | /* Keep cylinder nr within range, step towards home if possible. | ||
121 | */ | ||
122 | if (ftape_current_cylinder >= arg) { | ||
123 | return fdc_seek(ftape_current_cylinder - arg); | ||
124 | } else { | ||
125 | return fdc_seek(ftape_current_cylinder + arg); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /* forward */ int ftape_report_raw_drive_status(int *status); | ||
130 | |||
131 | static int ft_check_cmd_restrictions(qic117_cmd_t command) | ||
132 | { | ||
133 | int status = -1; | ||
134 | TRACE_FUN(ft_t_any); | ||
135 | |||
136 | TRACE(ft_t_flow, "%s", qic117_cmds[command].name); | ||
137 | /* A new motion command during an uninterruptible (motion) | ||
138 | * command requires a ready status before the new command can | ||
139 | * be issued. Otherwise a new motion command needs to be | ||
140 | * checked against required status. | ||
141 | */ | ||
142 | if (qic117_cmds[command].cmd_type == motion && | ||
143 | qic117_cmds[ftape_current_command].non_intr) { | ||
144 | ftape_report_raw_drive_status(&status); | ||
145 | if ((status & QIC_STATUS_READY) == 0) { | ||
146 | TRACE(ft_t_noise, | ||
147 | "motion cmd (%d) during non-intr cmd (%d)", | ||
148 | command, ftape_current_command); | ||
149 | TRACE(ft_t_noise, "waiting until drive gets ready"); | ||
150 | ftape_ready_wait(ftape_timeout.seek, | ||
151 | &status); | ||
152 | } | ||
153 | } | ||
154 | if (qic117_cmds[command].mask != 0) { | ||
155 | __u8 difference; | ||
156 | /* Some commands do require a certain status: | ||
157 | */ | ||
158 | if (status == -1) { /* not yet set */ | ||
159 | ftape_report_raw_drive_status(&status); | ||
160 | } | ||
161 | difference = ((status ^ qic117_cmds[command].state) & | ||
162 | qic117_cmds[command].mask); | ||
163 | /* Wait until the drive gets | ||
164 | * ready. This may last forever if | ||
165 | * the drive never gets ready... | ||
166 | */ | ||
167 | while ((difference & QIC_STATUS_READY) != 0) { | ||
168 | TRACE(ft_t_noise, "command %d issued while not ready", | ||
169 | command); | ||
170 | TRACE(ft_t_noise, "waiting until drive gets ready"); | ||
171 | if (ftape_ready_wait(ftape_timeout.seek, | ||
172 | &status) == -EINTR) { | ||
173 | /* Bail out on signal ! | ||
174 | */ | ||
175 | TRACE_ABORT(-EINTR, ft_t_warn, | ||
176 | "interrupted by non-blockable signal"); | ||
177 | } | ||
178 | difference = ((status ^ qic117_cmds[command].state) & | ||
179 | qic117_cmds[command].mask); | ||
180 | } | ||
181 | while ((difference & QIC_STATUS_ERROR) != 0) { | ||
182 | int err; | ||
183 | qic117_cmd_t cmd; | ||
184 | |||
185 | TRACE(ft_t_noise, | ||
186 | "command %d issued while error pending", | ||
187 | command); | ||
188 | TRACE(ft_t_noise, "clearing error status"); | ||
189 | ftape_report_error(&err, &cmd, 1); | ||
190 | ftape_report_raw_drive_status(&status); | ||
191 | difference = ((status ^ qic117_cmds[command].state) & | ||
192 | qic117_cmds[command].mask); | ||
193 | if ((difference & QIC_STATUS_ERROR) != 0) { | ||
194 | /* Bail out on fatal signal ! | ||
195 | */ | ||
196 | FT_SIGNAL_EXIT(_NEVER_BLOCK); | ||
197 | } | ||
198 | } | ||
199 | if (difference) { | ||
200 | /* Any remaining difference can't be solved | ||
201 | * here. | ||
202 | */ | ||
203 | if (difference & (QIC_STATUS_CARTRIDGE_PRESENT | | ||
204 | QIC_STATUS_NEW_CARTRIDGE | | ||
205 | QIC_STATUS_REFERENCED)) { | ||
206 | TRACE(ft_t_warn, | ||
207 | "Fatal: tape removed or reinserted !"); | ||
208 | ft_failure = 1; | ||
209 | } else { | ||
210 | TRACE(ft_t_err, "wrong state: 0x%02x should be: 0x%02x", | ||
211 | status & qic117_cmds[command].mask, | ||
212 | qic117_cmds[command].state); | ||
213 | } | ||
214 | TRACE_EXIT -EIO; | ||
215 | } | ||
216 | if (~status & QIC_STATUS_READY & qic117_cmds[command].mask) { | ||
217 | TRACE_ABORT(-EBUSY, ft_t_err, "Bad: still busy!"); | ||
218 | } | ||
219 | } | ||
220 | TRACE_EXIT 0; | ||
221 | } | ||
222 | |||
223 | /* Issue a tape command: | ||
224 | */ | ||
225 | int ftape_command(qic117_cmd_t command) | ||
226 | { | ||
227 | int result = 0; | ||
228 | static int level; | ||
229 | TRACE_FUN(ft_t_any); | ||
230 | |||
231 | if ((unsigned int)command > NR_ITEMS(qic117_cmds)) { | ||
232 | /* This is a bug we'll want to know about too. | ||
233 | */ | ||
234 | TRACE_ABORT(-EIO, ft_t_bug, "bug - bad command: %d", command); | ||
235 | } | ||
236 | if (++level > 5) { /* This is a bug we'll want to know about. */ | ||
237 | --level; | ||
238 | TRACE_ABORT(-EIO, ft_t_bug, "bug - recursion for command: %d", | ||
239 | command); | ||
240 | } | ||
241 | /* disable logging and restriction check for some commands, | ||
242 | * check all other commands that have a prescribed starting | ||
243 | * status. | ||
244 | */ | ||
245 | if (diagnostic_mode) { | ||
246 | TRACE(ft_t_flow, "diagnostic command %d", command); | ||
247 | } else if (command == QIC_REPORT_DRIVE_STATUS || | ||
248 | command == QIC_REPORT_NEXT_BIT) { | ||
249 | TRACE(ft_t_any, "%s", qic117_cmds[command].name); | ||
250 | } else { | ||
251 | TRACE_CATCH(ft_check_cmd_restrictions(command), --level); | ||
252 | } | ||
253 | /* Now all conditions are met or result was < 0. | ||
254 | */ | ||
255 | result = ft_send_to_drive((unsigned int)command); | ||
256 | if (qic117_cmds[command].cmd_type == motion && | ||
257 | command != QIC_LOGICAL_FORWARD && command != QIC_STOP_TAPE) { | ||
258 | ft_location.known = 0; | ||
259 | } | ||
260 | ftape_current_command = command; | ||
261 | --level; | ||
262 | TRACE_EXIT result; | ||
263 | } | ||
264 | |||
265 | /* Send a tape command parameter: | ||
266 | * Generates command # of step pulses. | ||
267 | * Skips tape-status call ! | ||
268 | */ | ||
269 | int ftape_parameter(unsigned int parameter) | ||
270 | { | ||
271 | TRACE_FUN(ft_t_any); | ||
272 | |||
273 | TRACE(ft_t_flow, "called with parameter = %d", parameter); | ||
274 | TRACE_EXIT ft_send_to_drive(parameter + 2); | ||
275 | } | ||
276 | |||
277 | /* Wait for the drive to get ready. | ||
278 | * timeout time in milli-seconds | ||
279 | * Returned status is valid if result != -EIO | ||
280 | * | ||
281 | * Should we allow to be killed by SIGINT? (^C) | ||
282 | * Would be nice at least for large timeouts. | ||
283 | */ | ||
284 | int ftape_ready_wait(unsigned int timeout, int *status) | ||
285 | { | ||
286 | unsigned long t0; | ||
287 | unsigned int poll_delay; | ||
288 | int signal_retries; | ||
289 | TRACE_FUN(ft_t_any); | ||
290 | |||
291 | /* the following ** REALLY ** reduces the system load when | ||
292 | * e.g. one simply rewinds or retensions. The tape is slow | ||
293 | * anyway. It is really not necessary to detect error | ||
294 | * conditions with 1/10 seconds granularity | ||
295 | * | ||
296 | * On my AMD 133MHZ 486: 100 ms: 23% system load | ||
297 | * 1 sec: 5% | ||
298 | * 5 sec: 0.6%, yeah | ||
299 | */ | ||
300 | if (timeout <= FT_SECOND) { | ||
301 | poll_delay = 100 * FT_MILLISECOND; | ||
302 | signal_retries = 20; /* two seconds */ | ||
303 | } else if (timeout < 20 * FT_SECOND) { | ||
304 | TRACE(ft_t_flow, "setting poll delay to 1 second"); | ||
305 | poll_delay = FT_SECOND; | ||
306 | signal_retries = 2; /* two seconds */ | ||
307 | } else { | ||
308 | TRACE(ft_t_flow, "setting poll delay to 5 seconds"); | ||
309 | poll_delay = 5 * FT_SECOND; | ||
310 | signal_retries = 1; /* five seconds */ | ||
311 | } | ||
312 | for (;;) { | ||
313 | t0 = jiffies; | ||
314 | TRACE_CATCH(ftape_report_raw_drive_status(status),); | ||
315 | if (*status & QIC_STATUS_READY) { | ||
316 | TRACE_EXIT 0; | ||
317 | } | ||
318 | if (!signal_retries--) { | ||
319 | FT_SIGNAL_EXIT(_NEVER_BLOCK); | ||
320 | } | ||
321 | if ((int)timeout >= 0) { | ||
322 | /* this will fail when jiffies wraps around about | ||
323 | * once every year :-) | ||
324 | */ | ||
325 | timeout -= ((jiffies - t0) * FT_SECOND) / HZ; | ||
326 | if (timeout <= 0) { | ||
327 | TRACE_ABORT(-ETIME, ft_t_err, "timeout"); | ||
328 | } | ||
329 | ftape_sleep(poll_delay); | ||
330 | timeout -= poll_delay; | ||
331 | } else { | ||
332 | ftape_sleep(poll_delay); | ||
333 | } | ||
334 | } | ||
335 | TRACE_EXIT -ETIME; | ||
336 | } | ||
337 | |||
338 | /* Issue command and wait up to timeout milli seconds for drive ready | ||
339 | */ | ||
340 | int ftape_command_wait(qic117_cmd_t command, unsigned int timeout, int *status) | ||
341 | { | ||
342 | int result; | ||
343 | |||
344 | /* Drive should be ready, issue command | ||
345 | */ | ||
346 | result = ftape_command(command); | ||
347 | if (result >= 0) { | ||
348 | result = ftape_ready_wait(timeout, status); | ||
349 | } | ||
350 | return result; | ||
351 | } | ||
352 | |||
353 | static int ftape_parameter_wait(unsigned int parm, unsigned int timeout, int *status) | ||
354 | { | ||
355 | int result; | ||
356 | |||
357 | /* Drive should be ready, issue command | ||
358 | */ | ||
359 | result = ftape_parameter(parm); | ||
360 | if (result >= 0) { | ||
361 | result = ftape_ready_wait(timeout, status); | ||
362 | } | ||
363 | return result; | ||
364 | } | ||
365 | |||
366 | /*-------------------------------------------------------------------------- | ||
367 | * Report operations | ||
368 | */ | ||
369 | |||
370 | /* Query the drive about its status. The command is sent and | ||
371 | result_length bits of status are returned (2 extra bits are read | ||
372 | for start and stop). */ | ||
373 | |||
374 | int ftape_report_operation(int *status, | ||
375 | qic117_cmd_t command, | ||
376 | int result_length) | ||
377 | { | ||
378 | int i, st3; | ||
379 | unsigned int t0; | ||
380 | unsigned int dt; | ||
381 | TRACE_FUN(ft_t_any); | ||
382 | |||
383 | TRACE_CATCH(ftape_command(command),); | ||
384 | t0 = ftape_timestamp(); | ||
385 | i = 0; | ||
386 | do { | ||
387 | ++i; | ||
388 | ftape_sleep(3 * FT_MILLISECOND); /* see remark below */ | ||
389 | TRACE_CATCH(fdc_sense_drive_status(&st3),); | ||
390 | dt = ftape_timediff(t0, ftape_timestamp()); | ||
391 | /* Ack should be asserted within Ttimout + Tack = 6 msec. | ||
392 | * Looks like some drives fail to do this so extend this | ||
393 | * period to 300 msec. | ||
394 | */ | ||
395 | } while (!(st3 & ST3_TRACK_0) && dt < 300000); | ||
396 | if (!(st3 & ST3_TRACK_0)) { | ||
397 | TRACE(ft_t_err, | ||
398 | "No acknowledge after %u msec. (%i iter)", dt / 1000, i); | ||
399 | TRACE_ABORT(-EIO, ft_t_err, "timeout on Acknowledge"); | ||
400 | } | ||
401 | /* dt may be larger than expected because of other tasks | ||
402 | * scheduled while we were sleeping. | ||
403 | */ | ||
404 | if (i > 1 && dt > 6000) { | ||
405 | TRACE(ft_t_err, "Acknowledge after %u msec. (%i iter)", | ||
406 | dt / 1000, i); | ||
407 | } | ||
408 | *status = 0; | ||
409 | for (i = 0; i < result_length + 1; i++) { | ||
410 | TRACE_CATCH(ftape_command(QIC_REPORT_NEXT_BIT),); | ||
411 | TRACE_CATCH(fdc_sense_drive_status(&st3),); | ||
412 | if (i < result_length) { | ||
413 | *status |= ((st3 & ST3_TRACK_0) ? 1 : 0) << i; | ||
414 | } else if ((st3 & ST3_TRACK_0) == 0) { | ||
415 | TRACE_ABORT(-EIO, ft_t_err, "missing status stop bit"); | ||
416 | } | ||
417 | } | ||
418 | /* this command will put track zero and index back into normal state */ | ||
419 | (void)ftape_command(QIC_REPORT_NEXT_BIT); | ||
420 | TRACE_EXIT 0; | ||
421 | } | ||
422 | |||
423 | /* Report the current drive status. */ | ||
424 | |||
425 | int ftape_report_raw_drive_status(int *status) | ||
426 | { | ||
427 | int result; | ||
428 | int count = 0; | ||
429 | TRACE_FUN(ft_t_any); | ||
430 | |||
431 | do { | ||
432 | result = ftape_report_operation(status, | ||
433 | QIC_REPORT_DRIVE_STATUS, 8); | ||
434 | } while (result < 0 && ++count <= 3); | ||
435 | if (result < 0) { | ||
436 | TRACE_ABORT(-EIO, ft_t_err, | ||
437 | "report_operation failed after %d trials", count); | ||
438 | } | ||
439 | if ((*status & 0xff) == 0xff) { | ||
440 | TRACE_ABORT(-EIO, ft_t_err, | ||
441 | "impossible drive status 0xff"); | ||
442 | } | ||
443 | if (*status & QIC_STATUS_READY) { | ||
444 | ftape_current_command = QIC_NO_COMMAND; /* completed */ | ||
445 | } | ||
446 | ft_last_status.status.drive_status = (__u8)(*status & 0xff); | ||
447 | TRACE_EXIT 0; | ||
448 | } | ||
449 | |||
450 | int ftape_report_drive_status(int *status) | ||
451 | { | ||
452 | TRACE_FUN(ft_t_any); | ||
453 | |||
454 | TRACE_CATCH(ftape_report_raw_drive_status(status),); | ||
455 | if (*status & QIC_STATUS_NEW_CARTRIDGE || | ||
456 | !(*status & QIC_STATUS_CARTRIDGE_PRESENT)) { | ||
457 | ft_failure = 1; /* will inhibit further operations */ | ||
458 | TRACE_EXIT -EIO; | ||
459 | } | ||
460 | if (*status & QIC_STATUS_READY && *status & QIC_STATUS_ERROR) { | ||
461 | /* Let caller handle all errors */ | ||
462 | TRACE_ABORT(1, ft_t_warn, "warning: error status set!"); | ||
463 | } | ||
464 | TRACE_EXIT 0; | ||
465 | } | ||
466 | |||
467 | int ftape_report_error(unsigned int *error, | ||
468 | qic117_cmd_t *command, int report) | ||
469 | { | ||
470 | static const ftape_error ftape_errors[] = QIC117_ERRORS; | ||
471 | int code; | ||
472 | TRACE_FUN(ft_t_any); | ||
473 | |||
474 | TRACE_CATCH(ftape_report_operation(&code, QIC_REPORT_ERROR_CODE, 16),); | ||
475 | *error = (unsigned int)(code & 0xff); | ||
476 | *command = (qic117_cmd_t)((code>>8)&0xff); | ||
477 | /* remember hardware status, maybe useful for status ioctls | ||
478 | */ | ||
479 | ft_last_error.error.command = (__u8)*command; | ||
480 | ft_last_error.error.error = (__u8)*error; | ||
481 | if (!report) { | ||
482 | TRACE_EXIT 0; | ||
483 | } | ||
484 | if (*error == 0) { | ||
485 | TRACE_ABORT(0, ft_t_info, "No error"); | ||
486 | } | ||
487 | TRACE(ft_t_info, "errorcode: %d", *error); | ||
488 | if (*error < NR_ITEMS(ftape_errors)) { | ||
489 | TRACE(ft_t_noise, "%sFatal ERROR:", | ||
490 | (ftape_errors[*error].fatal ? "" : "Non-")); | ||
491 | TRACE(ft_t_noise, "%s ...", ftape_errors[*error].message); | ||
492 | } else { | ||
493 | TRACE(ft_t_noise, "Unknown ERROR !"); | ||
494 | } | ||
495 | if ((unsigned int)*command < NR_ITEMS(qic117_cmds) && | ||
496 | qic117_cmds[*command].name != NULL) { | ||
497 | TRACE(ft_t_noise, "... caused by command \'%s\'", | ||
498 | qic117_cmds[*command].name); | ||
499 | } else { | ||
500 | TRACE(ft_t_noise, "... caused by unknown command %d", | ||
501 | *command); | ||
502 | } | ||
503 | TRACE_EXIT 0; | ||
504 | } | ||
505 | |||
506 | int ftape_report_configuration(qic_model *model, | ||
507 | unsigned int *rate, | ||
508 | int *qic_std, | ||
509 | int *tape_len) | ||
510 | { | ||
511 | int result; | ||
512 | int config; | ||
513 | int status; | ||
514 | static const unsigned int qic_rates[ 4] = { 250, 2000, 500, 1000 }; | ||
515 | TRACE_FUN(ft_t_any); | ||
516 | |||
517 | result = ftape_report_operation(&config, | ||
518 | QIC_REPORT_DRIVE_CONFIGURATION, 8); | ||
519 | if (result < 0) { | ||
520 | ft_last_status.status.drive_config = (__u8)0x00; | ||
521 | *model = prehistoric; | ||
522 | *rate = 500; | ||
523 | *qic_std = QIC_TAPE_QIC40; | ||
524 | *tape_len = 205; | ||
525 | TRACE_EXIT 0; | ||
526 | } else { | ||
527 | ft_last_status.status.drive_config = (__u8)(config & 0xff); | ||
528 | } | ||
529 | *rate = qic_rates[(config & QIC_CONFIG_RATE_MASK) >> QIC_CONFIG_RATE_SHIFT]; | ||
530 | result = ftape_report_operation(&status, QIC_REPORT_TAPE_STATUS, 8); | ||
531 | if (result < 0) { | ||
532 | ft_last_status.status.tape_status = (__u8)0x00; | ||
533 | /* pre- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is valid. | ||
534 | */ | ||
535 | *qic_std = (config & QIC_CONFIG_80) ? | ||
536 | QIC_TAPE_QIC80 : QIC_TAPE_QIC40; | ||
537 | /* ?? how's about 425ft tapes? */ | ||
538 | *tape_len = (config & QIC_CONFIG_LONG) ? 307 : 0; | ||
539 | *model = pre_qic117c; | ||
540 | result = 0; | ||
541 | } else { | ||
542 | ft_last_status.status.tape_status = (__u8)(status & 0xff); | ||
543 | *model = post_qic117b; | ||
544 | TRACE(ft_t_any, "report tape status result = %02x", status); | ||
545 | /* post- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is | ||
546 | * invalid. | ||
547 | */ | ||
548 | switch (status & QIC_TAPE_STD_MASK) { | ||
549 | case QIC_TAPE_QIC40: | ||
550 | case QIC_TAPE_QIC80: | ||
551 | case QIC_TAPE_QIC3020: | ||
552 | case QIC_TAPE_QIC3010: | ||
553 | *qic_std = status & QIC_TAPE_STD_MASK; | ||
554 | break; | ||
555 | default: | ||
556 | *qic_std = -1; | ||
557 | break; | ||
558 | } | ||
559 | switch (status & QIC_TAPE_LEN_MASK) { | ||
560 | case QIC_TAPE_205FT: | ||
561 | /* 205 or 425+ ft 550 Oe tape */ | ||
562 | *tape_len = 0; | ||
563 | break; | ||
564 | case QIC_TAPE_307FT: | ||
565 | /* 307.5 ft 550 Oe Extended Length (XL) tape */ | ||
566 | *tape_len = 307; | ||
567 | break; | ||
568 | case QIC_TAPE_VARIABLE: | ||
569 | /* Variable length 550 Oe tape */ | ||
570 | *tape_len = 0; | ||
571 | break; | ||
572 | case QIC_TAPE_1100FT: | ||
573 | /* 1100 ft 550 Oe tape */ | ||
574 | *tape_len = 1100; | ||
575 | break; | ||
576 | case QIC_TAPE_FLEX: | ||
577 | /* Variable length 900 Oe tape */ | ||
578 | *tape_len = 0; | ||
579 | break; | ||
580 | default: | ||
581 | *tape_len = -1; | ||
582 | break; | ||
583 | } | ||
584 | if (*qic_std == -1 || *tape_len == -1) { | ||
585 | TRACE(ft_t_any, | ||
586 | "post qic-117b spec drive with unknown tape"); | ||
587 | } | ||
588 | result = *tape_len == -1 ? -EIO : 0; | ||
589 | if (status & QIC_TAPE_WIDE) { | ||
590 | switch (*qic_std) { | ||
591 | case QIC_TAPE_QIC80: | ||
592 | TRACE(ft_t_info, "TR-1 tape detected"); | ||
593 | break; | ||
594 | case QIC_TAPE_QIC3010: | ||
595 | TRACE(ft_t_info, "TR-2 tape detected"); | ||
596 | break; | ||
597 | case QIC_TAPE_QIC3020: | ||
598 | TRACE(ft_t_info, "TR-3 tape detected"); | ||
599 | break; | ||
600 | default: | ||
601 | TRACE(ft_t_warn, | ||
602 | "Unknown Travan tape type detected"); | ||
603 | break; | ||
604 | } | ||
605 | } | ||
606 | } | ||
607 | TRACE_EXIT (result < 0) ? -EIO : 0; | ||
608 | } | ||
609 | |||
610 | static int ftape_report_rom_version(int *version) | ||
611 | { | ||
612 | |||
613 | if (ftape_report_operation(version, QIC_REPORT_ROM_VERSION, 8) < 0) { | ||
614 | return -EIO; | ||
615 | } else { | ||
616 | return 0; | ||
617 | } | ||
618 | } | ||
619 | |||
620 | void ftape_report_vendor_id(unsigned int *id) | ||
621 | { | ||
622 | int result; | ||
623 | TRACE_FUN(ft_t_any); | ||
624 | |||
625 | /* We'll try to get a vendor id from the drive. First | ||
626 | * according to the QIC-117 spec, a 16-bit id is requested. | ||
627 | * If that fails we'll try an 8-bit version, otherwise we'll | ||
628 | * try an undocumented query. | ||
629 | */ | ||
630 | result = ftape_report_operation((int *) id, QIC_REPORT_VENDOR_ID, 16); | ||
631 | if (result < 0) { | ||
632 | result = ftape_report_operation((int *) id, | ||
633 | QIC_REPORT_VENDOR_ID, 8); | ||
634 | if (result < 0) { | ||
635 | /* The following is an undocumented call found | ||
636 | * in the CMS code. | ||
637 | */ | ||
638 | result = ftape_report_operation((int *) id, 24, 8); | ||
639 | if (result < 0) { | ||
640 | *id = UNKNOWN_VENDOR; | ||
641 | } else { | ||
642 | TRACE(ft_t_noise, "got old 8 bit id: %04x", | ||
643 | *id); | ||
644 | *id |= 0x20000; | ||
645 | } | ||
646 | } else { | ||
647 | TRACE(ft_t_noise, "got 8 bit id: %04x", *id); | ||
648 | *id |= 0x10000; | ||
649 | } | ||
650 | } else { | ||
651 | TRACE(ft_t_noise, "got 16 bit id: %04x", *id); | ||
652 | } | ||
653 | if (*id == 0x0047) { | ||
654 | int version; | ||
655 | int sign; | ||
656 | |||
657 | if (ftape_report_rom_version(&version) < 0) { | ||
658 | TRACE(ft_t_bug, "report rom version failed"); | ||
659 | TRACE_EXIT; | ||
660 | } | ||
661 | TRACE(ft_t_noise, "CMS rom version: %d", version); | ||
662 | ftape_command(QIC_ENTER_DIAGNOSTIC_1); | ||
663 | ftape_command(QIC_ENTER_DIAGNOSTIC_1); | ||
664 | diagnostic_mode = 1; | ||
665 | if (ftape_report_operation(&sign, 9, 8) < 0) { | ||
666 | unsigned int error; | ||
667 | qic117_cmd_t command; | ||
668 | |||
669 | ftape_report_error(&error, &command, 1); | ||
670 | ftape_command(QIC_ENTER_PRIMARY_MODE); | ||
671 | diagnostic_mode = 0; | ||
672 | TRACE_EXIT; /* failure ! */ | ||
673 | } else { | ||
674 | TRACE(ft_t_noise, "CMS signature: %02x", sign); | ||
675 | } | ||
676 | if (sign == 0xa5) { | ||
677 | result = ftape_report_operation(&sign, 37, 8); | ||
678 | if (result < 0) { | ||
679 | if (version >= 63) { | ||
680 | *id = 0x8880; | ||
681 | TRACE(ft_t_noise, | ||
682 | "This is an Iomega drive !"); | ||
683 | } else { | ||
684 | *id = 0x0047; | ||
685 | TRACE(ft_t_noise, | ||
686 | "This is a real CMS drive !"); | ||
687 | } | ||
688 | } else { | ||
689 | *id = 0x0047; | ||
690 | TRACE(ft_t_noise, "CMS status: %d", sign); | ||
691 | } | ||
692 | } else { | ||
693 | *id = UNKNOWN_VENDOR; | ||
694 | } | ||
695 | ftape_command(QIC_ENTER_PRIMARY_MODE); | ||
696 | diagnostic_mode = 0; | ||
697 | } | ||
698 | TRACE_EXIT; | ||
699 | } | ||
700 | |||
701 | static int qic_rate_code(unsigned int rate) | ||
702 | { | ||
703 | switch (rate) { | ||
704 | case 250: | ||
705 | return QIC_CONFIG_RATE_250; | ||
706 | case 500: | ||
707 | return QIC_CONFIG_RATE_500; | ||
708 | case 1000: | ||
709 | return QIC_CONFIG_RATE_1000; | ||
710 | case 2000: | ||
711 | return QIC_CONFIG_RATE_2000; | ||
712 | default: | ||
713 | return QIC_CONFIG_RATE_500; | ||
714 | } | ||
715 | } | ||
716 | |||
717 | static int ftape_set_rate_test(unsigned int *max_rate) | ||
718 | { | ||
719 | unsigned int error; | ||
720 | qic117_cmd_t command; | ||
721 | int status; | ||
722 | int supported = 0; | ||
723 | TRACE_FUN(ft_t_any); | ||
724 | |||
725 | /* Check if the drive does support the select rate command | ||
726 | * by testing all different settings. If any one is accepted | ||
727 | * we assume the command is supported, else not. | ||
728 | */ | ||
729 | for (*max_rate = 2000; *max_rate >= 250; *max_rate /= 2) { | ||
730 | if (ftape_command(QIC_SELECT_RATE) < 0) { | ||
731 | continue; | ||
732 | } | ||
733 | if (ftape_parameter_wait(qic_rate_code(*max_rate), | ||
734 | 1 * FT_SECOND, &status) < 0) { | ||
735 | continue; | ||
736 | } | ||
737 | if (status & QIC_STATUS_ERROR) { | ||
738 | ftape_report_error(&error, &command, 0); | ||
739 | continue; | ||
740 | } | ||
741 | supported = 1; /* did accept a request */ | ||
742 | break; | ||
743 | } | ||
744 | TRACE(ft_t_noise, "Select Rate command is%s supported", | ||
745 | supported ? "" : " not"); | ||
746 | TRACE_EXIT supported; | ||
747 | } | ||
748 | |||
749 | int ftape_set_data_rate(unsigned int new_rate /* Kbps */, unsigned int qic_std) | ||
750 | { | ||
751 | int status; | ||
752 | int result = 0; | ||
753 | unsigned int data_rate = new_rate; | ||
754 | static int supported; | ||
755 | int rate_changed = 0; | ||
756 | qic_model dummy_model; | ||
757 | unsigned int dummy_qic_std, dummy_tape_len; | ||
758 | TRACE_FUN(ft_t_any); | ||
759 | |||
760 | if (ft_drive_max_rate == 0) { /* first time */ | ||
761 | supported = ftape_set_rate_test(&ft_drive_max_rate); | ||
762 | } | ||
763 | if (supported) { | ||
764 | ftape_command(QIC_SELECT_RATE); | ||
765 | result = ftape_parameter_wait(qic_rate_code(new_rate), | ||
766 | 1 * FT_SECOND, &status); | ||
767 | if (result >= 0 && !(status & QIC_STATUS_ERROR)) { | ||
768 | rate_changed = 1; | ||
769 | } | ||
770 | } | ||
771 | TRACE_CATCH(result = ftape_report_configuration(&dummy_model, | ||
772 | &data_rate, | ||
773 | &dummy_qic_std, | ||
774 | &dummy_tape_len),); | ||
775 | if (data_rate != new_rate) { | ||
776 | if (!supported) { | ||
777 | TRACE(ft_t_warn, "Rate change not supported!"); | ||
778 | } else if (rate_changed) { | ||
779 | TRACE(ft_t_warn, "Requested: %d, got %d", | ||
780 | new_rate, data_rate); | ||
781 | } else { | ||
782 | TRACE(ft_t_warn, "Rate change failed!"); | ||
783 | } | ||
784 | result = -EINVAL; | ||
785 | } | ||
786 | /* | ||
787 | * Set data rate and write precompensation as specified: | ||
788 | * | ||
789 | * | QIC-40/80 | QIC-3010/3020 | ||
790 | * rate | precomp | precomp | ||
791 | * ----------+-------------+-------------- | ||
792 | * 250 Kbps. | 250 ns. | 0 ns. | ||
793 | * 500 Kbps. | 125 ns. | 0 ns. | ||
794 | * 1 Mbps. | 42 ns. | 0 ns. | ||
795 | * 2 Mbps | N/A | 0 ns. | ||
796 | */ | ||
797 | if ((qic_std == QIC_TAPE_QIC40 && data_rate > 500) || | ||
798 | (qic_std == QIC_TAPE_QIC80 && data_rate > 1000)) { | ||
799 | TRACE_ABORT(-EINVAL, | ||
800 | ft_t_warn, "Datarate too high for QIC-mode"); | ||
801 | } | ||
802 | TRACE_CATCH(fdc_set_data_rate(data_rate),_res = -EINVAL); | ||
803 | ft_data_rate = data_rate; | ||
804 | if (qic_std == QIC_TAPE_QIC40 || qic_std == QIC_TAPE_QIC80) { | ||
805 | switch (data_rate) { | ||
806 | case 250: | ||
807 | fdc_set_write_precomp(250); | ||
808 | break; | ||
809 | default: | ||
810 | case 500: | ||
811 | fdc_set_write_precomp(125); | ||
812 | break; | ||
813 | case 1000: | ||
814 | fdc_set_write_precomp(42); | ||
815 | break; | ||
816 | } | ||
817 | } else { | ||
818 | fdc_set_write_precomp(0); | ||
819 | } | ||
820 | TRACE_EXIT result; | ||
821 | } | ||
822 | |||
823 | /* The next two functions are used to cope with excessive overrun errors | ||
824 | */ | ||
825 | int ftape_increase_threshold(void) | ||
826 | { | ||
827 | TRACE_FUN(ft_t_flow); | ||
828 | |||
829 | if (fdc.type < i82077 || ft_fdc_threshold >= 12) { | ||
830 | TRACE_ABORT(-EIO, ft_t_err, "cannot increase fifo threshold"); | ||
831 | } | ||
832 | if (fdc_fifo_threshold(++ft_fdc_threshold, NULL, NULL, NULL) < 0) { | ||
833 | TRACE(ft_t_err, "cannot increase fifo threshold"); | ||
834 | ft_fdc_threshold --; | ||
835 | fdc_reset(); | ||
836 | } | ||
837 | TRACE(ft_t_info, "New FIFO threshold: %d", ft_fdc_threshold); | ||
838 | TRACE_EXIT 0; | ||
839 | } | ||
840 | |||
841 | int ftape_half_data_rate(void) | ||
842 | { | ||
843 | if (ft_data_rate < 500) { | ||
844 | return -1; | ||
845 | } | ||
846 | if (ftape_set_data_rate(ft_data_rate / 2, ft_qic_std) < 0) { | ||
847 | return -EIO; | ||
848 | } | ||
849 | ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len); | ||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | /* Seek the head to the specified track. | ||
854 | */ | ||
855 | int ftape_seek_head_to_track(unsigned int track) | ||
856 | { | ||
857 | int status; | ||
858 | TRACE_FUN(ft_t_any); | ||
859 | |||
860 | ft_location.track = -1; /* remains set in case of error */ | ||
861 | if (track >= ft_tracks_per_tape) { | ||
862 | TRACE_ABORT(-EINVAL, ft_t_bug, "track out of bounds"); | ||
863 | } | ||
864 | TRACE(ft_t_flow, "seeking track %d", track); | ||
865 | TRACE_CATCH(ftape_command(QIC_SEEK_HEAD_TO_TRACK),); | ||
866 | TRACE_CATCH(ftape_parameter_wait(track, ftape_timeout.head_seek, | ||
867 | &status),); | ||
868 | ft_location.track = track; | ||
869 | ftape_might_be_off_track = 0; | ||
870 | TRACE_EXIT 0; | ||
871 | } | ||
872 | |||
873 | int ftape_wakeup_drive(wake_up_types method) | ||
874 | { | ||
875 | int status; | ||
876 | int motor_on = 0; | ||
877 | TRACE_FUN(ft_t_any); | ||
878 | |||
879 | switch (method) { | ||
880 | case wake_up_colorado: | ||
881 | TRACE_CATCH(ftape_command(QIC_PHANTOM_SELECT),); | ||
882 | TRACE_CATCH(ftape_parameter(0 /* ft_drive_sel ?? */),); | ||
883 | break; | ||
884 | case wake_up_mountain: | ||
885 | TRACE_CATCH(ftape_command(QIC_SOFT_SELECT),); | ||
886 | ftape_sleep(FT_MILLISECOND); /* NEEDED */ | ||
887 | TRACE_CATCH(ftape_parameter(18),); | ||
888 | break; | ||
889 | case wake_up_insight: | ||
890 | ftape_sleep(100 * FT_MILLISECOND); | ||
891 | motor_on = 1; | ||
892 | fdc_motor(motor_on); /* enable is done by motor-on */ | ||
893 | case no_wake_up: | ||
894 | break; | ||
895 | default: | ||
896 | TRACE_EXIT -ENODEV; /* unknown wakeup method */ | ||
897 | break; | ||
898 | } | ||
899 | /* If wakeup succeeded we shouldn't get an error here.. | ||
900 | */ | ||
901 | TRACE_CATCH(ftape_report_raw_drive_status(&status), | ||
902 | if (motor_on) { | ||
903 | fdc_motor(0); | ||
904 | }); | ||
905 | TRACE_EXIT 0; | ||
906 | } | ||
907 | |||
908 | int ftape_put_drive_to_sleep(wake_up_types method) | ||
909 | { | ||
910 | TRACE_FUN(ft_t_any); | ||
911 | |||
912 | switch (method) { | ||
913 | case wake_up_colorado: | ||
914 | TRACE_CATCH(ftape_command(QIC_PHANTOM_DESELECT),); | ||
915 | break; | ||
916 | case wake_up_mountain: | ||
917 | TRACE_CATCH(ftape_command(QIC_SOFT_DESELECT),); | ||
918 | break; | ||
919 | case wake_up_insight: | ||
920 | fdc_motor(0); /* enable is done by motor-on */ | ||
921 | case no_wake_up: /* no wakeup / no sleep ! */ | ||
922 | break; | ||
923 | default: | ||
924 | TRACE_EXIT -ENODEV; /* unknown wakeup method */ | ||
925 | } | ||
926 | TRACE_EXIT 0; | ||
927 | } | ||
928 | |||
929 | int ftape_reset_drive(void) | ||
930 | { | ||
931 | int result = 0; | ||
932 | int status; | ||
933 | unsigned int err_code; | ||
934 | qic117_cmd_t err_command; | ||
935 | int i; | ||
936 | TRACE_FUN(ft_t_any); | ||
937 | |||
938 | /* We want to re-establish contact with our drive. Fire a | ||
939 | * number of reset commands (single step pulses) and pray for | ||
940 | * success. | ||
941 | */ | ||
942 | for (i = 0; i < 2; ++i) { | ||
943 | TRACE(ft_t_flow, "Resetting fdc"); | ||
944 | fdc_reset(); | ||
945 | ftape_sleep(10 * FT_MILLISECOND); | ||
946 | TRACE(ft_t_flow, "Reset command to drive"); | ||
947 | result = ftape_command(QIC_RESET); | ||
948 | if (result == 0) { | ||
949 | ftape_sleep(1 * FT_SECOND); /* drive not | ||
950 | * accessible | ||
951 | * during 1 second | ||
952 | */ | ||
953 | TRACE(ft_t_flow, "Re-selecting drive"); | ||
954 | |||
955 | /* Strange, the QIC-117 specs don't mention | ||
956 | * this but the drive gets deselected after a | ||
957 | * soft reset ! So we need to enable it | ||
958 | * again. | ||
959 | */ | ||
960 | if (ftape_wakeup_drive(ft_drive_type.wake_up) < 0) { | ||
961 | TRACE(ft_t_err, "Wakeup failed !"); | ||
962 | } | ||
963 | TRACE(ft_t_flow, "Waiting until drive gets ready"); | ||
964 | result= ftape_ready_wait(ftape_timeout.reset, &status); | ||
965 | if (result == 0 && (status & QIC_STATUS_ERROR)) { | ||
966 | result = ftape_report_error(&err_code, | ||
967 | &err_command, 1); | ||
968 | if (result == 0 && err_code == 27) { | ||
969 | /* Okay, drive saw reset | ||
970 | * command and responded as it | ||
971 | * should | ||
972 | */ | ||
973 | break; | ||
974 | } else { | ||
975 | result = -EIO; | ||
976 | } | ||
977 | } else { | ||
978 | result = -EIO; | ||
979 | } | ||
980 | } | ||
981 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
982 | } | ||
983 | if (result != 0) { | ||
984 | TRACE(ft_t_err, "General failure to reset tape drive"); | ||
985 | } else { | ||
986 | /* Restore correct settings: keep original rate | ||
987 | */ | ||
988 | ftape_set_data_rate(ft_data_rate, ft_qic_std); | ||
989 | } | ||
990 | ftape_init_drive_needed = 1; | ||
991 | TRACE_EXIT result; | ||
992 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-io.h b/drivers/char/ftape/lowlevel/ftape-io.h deleted file mode 100644 index 26a7baad8717..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-io.h +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | #ifndef _FTAPE_IO_H | ||
2 | #define _FTAPE_IO_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
6 | * (C) 1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-io.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:18 $ | ||
26 | * | ||
27 | * This file contains definitions for the glue part of the | ||
28 | * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. | ||
29 | */ | ||
30 | |||
31 | #include <linux/qic117.h> | ||
32 | #include <linux/ftape-vendors.h> | ||
33 | |||
34 | typedef struct { | ||
35 | unsigned int seek; | ||
36 | unsigned int reset; | ||
37 | unsigned int rewind; | ||
38 | unsigned int head_seek; | ||
39 | unsigned int stop; | ||
40 | unsigned int pause; | ||
41 | } ft_timeout_table; | ||
42 | |||
43 | typedef enum { | ||
44 | prehistoric, pre_qic117c, post_qic117b, post_qic117d | ||
45 | } qic_model; | ||
46 | |||
47 | /* | ||
48 | * ftape-io.c defined global vars. | ||
49 | */ | ||
50 | extern ft_timeout_table ftape_timeout; | ||
51 | extern unsigned int ftape_tape_len; | ||
52 | extern volatile qic117_cmd_t ftape_current_command; | ||
53 | extern const struct qic117_command_table qic117_cmds[]; | ||
54 | extern int ftape_might_be_off_track; | ||
55 | |||
56 | /* | ||
57 | * ftape-io.c defined global functions. | ||
58 | */ | ||
59 | extern void ftape_udelay(unsigned int usecs); | ||
60 | extern void ftape_udelay_calibrate(void); | ||
61 | extern void ftape_sleep(unsigned int time); | ||
62 | extern void ftape_report_vendor_id(unsigned int *id); | ||
63 | extern int ftape_command(qic117_cmd_t command); | ||
64 | extern int ftape_command_wait(qic117_cmd_t command, | ||
65 | unsigned int timeout, | ||
66 | int *status); | ||
67 | extern int ftape_parameter(unsigned int parameter); | ||
68 | extern int ftape_report_operation(int *status, | ||
69 | qic117_cmd_t command, | ||
70 | int result_length); | ||
71 | extern int ftape_report_configuration(qic_model *model, | ||
72 | unsigned int *rate, | ||
73 | int *qic_std, | ||
74 | int *tape_len); | ||
75 | extern int ftape_report_drive_status(int *status); | ||
76 | extern int ftape_report_raw_drive_status(int *status); | ||
77 | extern int ftape_report_status(int *status); | ||
78 | extern int ftape_ready_wait(unsigned int timeout, int *status); | ||
79 | extern int ftape_seek_head_to_track(unsigned int track); | ||
80 | extern int ftape_set_data_rate(unsigned int new_rate, unsigned int qic_std); | ||
81 | extern int ftape_report_error(unsigned int *error, | ||
82 | qic117_cmd_t *command, | ||
83 | int report); | ||
84 | extern int ftape_reset_drive(void); | ||
85 | extern int ftape_put_drive_to_sleep(wake_up_types method); | ||
86 | extern int ftape_wakeup_drive(wake_up_types method); | ||
87 | extern int ftape_increase_threshold(void); | ||
88 | extern int ftape_half_data_rate(void); | ||
89 | |||
90 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-proc.c b/drivers/char/ftape/lowlevel/ftape-proc.c deleted file mode 100644 index e805b15e0a12..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-proc.c +++ /dev/null | |||
@@ -1,214 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.c,v $ | ||
20 | * $Revision: 1.11 $ | ||
21 | * $Date: 1997/10/24 14:47:37 $ | ||
22 | * | ||
23 | * This file contains the procfs interface for the | ||
24 | * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. | ||
25 | |||
26 | * Old code removed, switched to dynamic proc entry. | ||
27 | */ | ||
28 | |||
29 | |||
30 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) | ||
31 | |||
32 | #include <linux/proc_fs.h> | ||
33 | |||
34 | #include <linux/ftape.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/qic117.h> | ||
37 | |||
38 | #include "../lowlevel/ftape-io.h" | ||
39 | #include "../lowlevel/ftape-ctl.h" | ||
40 | #include "../lowlevel/ftape-proc.h" | ||
41 | #include "../lowlevel/ftape-tracing.h" | ||
42 | |||
43 | static size_t get_driver_info(char *buf) | ||
44 | { | ||
45 | const char *debug_level[] = { "bugs" , | ||
46 | "errors", | ||
47 | "warnings", | ||
48 | "informational", | ||
49 | "noisy", | ||
50 | "program flow", | ||
51 | "fdc and dma", | ||
52 | "data flow", | ||
53 | "anything" }; | ||
54 | |||
55 | return sprintf(buf, | ||
56 | "version : %s\n" | ||
57 | "used data rate: %d kbit/sec\n" | ||
58 | "dma memory : %d kb\n" | ||
59 | "debug messages: %s\n", | ||
60 | FTAPE_VERSION, | ||
61 | ft_data_rate, | ||
62 | FT_BUFF_SIZE * ft_nr_buffers >> 10, | ||
63 | debug_level[TRACE_LEVEL]); | ||
64 | } | ||
65 | |||
66 | static size_t get_tapedrive_info(char *buf) | ||
67 | { | ||
68 | return sprintf(buf, | ||
69 | "vendor id : 0x%04x\n" | ||
70 | "drive name: %s\n" | ||
71 | "wind speed: %d ips\n" | ||
72 | "wakeup : %s\n" | ||
73 | "max. rate : %d kbit/sec\n", | ||
74 | ft_drive_type.vendor_id, | ||
75 | ft_drive_type.name, | ||
76 | ft_drive_type.speed, | ||
77 | ((ft_drive_type.wake_up == no_wake_up) | ||
78 | ? "No wakeup needed" : | ||
79 | ((ft_drive_type.wake_up == wake_up_colorado) | ||
80 | ? "Colorado" : | ||
81 | ((ft_drive_type.wake_up == wake_up_mountain) | ||
82 | ? "Mountain" : | ||
83 | ((ft_drive_type.wake_up == wake_up_insight) | ||
84 | ? "Motor on" : | ||
85 | "Unknown")))), | ||
86 | ft_drive_max_rate); | ||
87 | } | ||
88 | |||
89 | static size_t get_cartridge_info(char *buf) | ||
90 | { | ||
91 | if (ftape_init_drive_needed) { | ||
92 | return sprintf(buf, "uninitialized\n"); | ||
93 | } | ||
94 | if (ft_no_tape) { | ||
95 | return sprintf(buf, "no cartridge inserted\n"); | ||
96 | } | ||
97 | return sprintf(buf, | ||
98 | "segments : %5d\n" | ||
99 | "tracks : %5d\n" | ||
100 | "length : %5dft\n" | ||
101 | "formatted : %3s\n" | ||
102 | "writable : %3s\n" | ||
103 | "QIC spec. : QIC-%s\n" | ||
104 | "fmt-code : %1d\n", | ||
105 | ft_segments_per_track, | ||
106 | ft_tracks_per_tape, | ||
107 | ftape_tape_len, | ||
108 | (ft_formatted == 1) ? "yes" : "no", | ||
109 | (ft_write_protected == 1) ? "no" : "yes", | ||
110 | ((ft_qic_std == QIC_TAPE_QIC40) ? "40" : | ||
111 | ((ft_qic_std == QIC_TAPE_QIC80) ? "80" : | ||
112 | ((ft_qic_std == QIC_TAPE_QIC3010) ? "3010" : | ||
113 | ((ft_qic_std == QIC_TAPE_QIC3020) ? "3020" : | ||
114 | "???")))), | ||
115 | ft_format_code); | ||
116 | } | ||
117 | |||
118 | static size_t get_controller_info(char *buf) | ||
119 | { | ||
120 | const char *fdc_name[] = { "no fdc", | ||
121 | "i8272", | ||
122 | "i82077", | ||
123 | "i82077AA", | ||
124 | "Colorado FC-10 or FC-20", | ||
125 | "i82078", | ||
126 | "i82078_1" }; | ||
127 | |||
128 | return sprintf(buf, | ||
129 | "FDC type : %s\n" | ||
130 | "FDC base : 0x%03x\n" | ||
131 | "FDC irq : %d\n" | ||
132 | "FDC dma : %d\n" | ||
133 | "FDC thr. : %d\n" | ||
134 | "max. rate : %d kbit/sec\n", | ||
135 | ft_mach2 ? "Mountain MACH-2" : fdc_name[fdc.type], | ||
136 | fdc.sra, fdc.irq, fdc.dma, | ||
137 | ft_fdc_threshold, ft_fdc_max_rate); | ||
138 | } | ||
139 | |||
140 | static size_t get_history_info(char *buf) | ||
141 | { | ||
142 | size_t len; | ||
143 | |||
144 | len = sprintf(buf, | ||
145 | "\nFDC isr statistics\n" | ||
146 | " id_am_errors : %3d\n" | ||
147 | " id_crc_errors : %3d\n" | ||
148 | " data_am_errors : %3d\n" | ||
149 | " data_crc_errors : %3d\n" | ||
150 | " overrun_errors : %3d\n" | ||
151 | " no_data_errors : %3d\n" | ||
152 | " retries : %3d\n", | ||
153 | ft_history.id_am_errors, ft_history.id_crc_errors, | ||
154 | ft_history.data_am_errors, ft_history.data_crc_errors, | ||
155 | ft_history.overrun_errors, ft_history.no_data_errors, | ||
156 | ft_history.retries); | ||
157 | len += sprintf(buf + len, | ||
158 | "\nECC statistics\n" | ||
159 | " crc_errors : %3d\n" | ||
160 | " crc_failures : %3d\n" | ||
161 | " ecc_failures : %3d\n" | ||
162 | " sectors corrected: %3d\n", | ||
163 | ft_history.crc_errors, ft_history.crc_failures, | ||
164 | ft_history.ecc_failures, ft_history.corrected); | ||
165 | len += sprintf(buf + len, | ||
166 | "\ntape quality statistics\n" | ||
167 | " media defects : %3d\n", | ||
168 | ft_history.defects); | ||
169 | len += sprintf(buf + len, | ||
170 | "\ntape motion statistics\n" | ||
171 | " repositions : %3d\n", | ||
172 | ft_history.rewinds); | ||
173 | return len; | ||
174 | } | ||
175 | |||
176 | static int ftape_read_proc(char *page, char **start, off_t off, | ||
177 | int count, int *eof, void *data) | ||
178 | { | ||
179 | char *ptr = page; | ||
180 | size_t len; | ||
181 | |||
182 | ptr += sprintf(ptr, "Kernel Driver\n\n"); | ||
183 | ptr += get_driver_info(ptr); | ||
184 | ptr += sprintf(ptr, "\nTape Drive\n\n"); | ||
185 | ptr += get_tapedrive_info(ptr); | ||
186 | ptr += sprintf(ptr, "\nFDC Controller\n\n"); | ||
187 | ptr += get_controller_info(ptr); | ||
188 | ptr += sprintf(ptr, "\nTape Cartridge\n\n"); | ||
189 | ptr += get_cartridge_info(ptr); | ||
190 | ptr += sprintf(ptr, "\nHistory Record\n\n"); | ||
191 | ptr += get_history_info(ptr); | ||
192 | |||
193 | len = strlen(page); | ||
194 | *start = NULL; | ||
195 | if (off+count >= len) { | ||
196 | *eof = 1; | ||
197 | } else { | ||
198 | *eof = 0; | ||
199 | } | ||
200 | return len; | ||
201 | } | ||
202 | |||
203 | int __init ftape_proc_init(void) | ||
204 | { | ||
205 | return create_proc_read_entry("ftape", 0, &proc_root, | ||
206 | ftape_read_proc, NULL) != NULL; | ||
207 | } | ||
208 | |||
209 | void ftape_proc_destroy(void) | ||
210 | { | ||
211 | remove_proc_entry("ftape", &proc_root); | ||
212 | } | ||
213 | |||
214 | #endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) */ | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-proc.h b/drivers/char/ftape/lowlevel/ftape-proc.h deleted file mode 100644 index 264dfcc1d22d..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-proc.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | #ifndef _FTAPE_PROC_H | ||
2 | #define _FTAPE_PROC_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1997 Claus-Justus Heine | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-proc.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:18:20 $ | ||
25 | * | ||
26 | * This file contains definitions for the procfs interface of the | ||
27 | * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. | ||
28 | */ | ||
29 | |||
30 | #include <linux/proc_fs.h> | ||
31 | |||
32 | extern int ftape_proc_init(void); | ||
33 | extern void ftape_proc_destroy(void); | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-read.c b/drivers/char/ftape/lowlevel/ftape-read.c deleted file mode 100644 index d967d8cd86dc..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-read.c +++ /dev/null | |||
@@ -1,621 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.c,v $ | ||
21 | * $Revision: 1.6 $ | ||
22 | * $Date: 1997/10/21 14:39:22 $ | ||
23 | * | ||
24 | * This file contains the reading code | ||
25 | * for the QIC-117 floppy-tape driver for Linux. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include <linux/string.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/mm.h> | ||
32 | |||
33 | #include <linux/ftape.h> | ||
34 | #include <linux/qic117.h> | ||
35 | #include "../lowlevel/ftape-tracing.h" | ||
36 | #include "../lowlevel/ftape-read.h" | ||
37 | #include "../lowlevel/ftape-io.h" | ||
38 | #include "../lowlevel/ftape-ctl.h" | ||
39 | #include "../lowlevel/ftape-rw.h" | ||
40 | #include "../lowlevel/ftape-write.h" | ||
41 | #include "../lowlevel/ftape-ecc.h" | ||
42 | #include "../lowlevel/ftape-bsm.h" | ||
43 | |||
44 | /* Global vars. | ||
45 | */ | ||
46 | |||
47 | /* Local vars. | ||
48 | */ | ||
49 | |||
50 | void ftape_zap_read_buffers(void) | ||
51 | { | ||
52 | int i; | ||
53 | |||
54 | for (i = 0; i < ft_nr_buffers; ++i) { | ||
55 | /* changed to "fit" with dynamic allocation of tape_buffer. --khp */ | ||
56 | ft_buffer[i]->status = waiting; | ||
57 | ft_buffer[i]->bytes = 0; | ||
58 | ft_buffer[i]->skip = 0; | ||
59 | ft_buffer[i]->retry = 0; | ||
60 | } | ||
61 | /* ftape_reset_buffer(); */ | ||
62 | } | ||
63 | |||
64 | static SectorMap convert_sector_map(buffer_struct * buff) | ||
65 | { | ||
66 | int i = 0; | ||
67 | SectorMap bad_map = ftape_get_bad_sector_entry(buff->segment_id); | ||
68 | SectorMap src_map = buff->soft_error_map | buff->hard_error_map; | ||
69 | SectorMap dst_map = 0; | ||
70 | TRACE_FUN(ft_t_any); | ||
71 | |||
72 | if (bad_map || src_map) { | ||
73 | TRACE(ft_t_flow, "bad_map = 0x%08lx", (long) bad_map); | ||
74 | TRACE(ft_t_flow, "src_map = 0x%08lx", (long) src_map); | ||
75 | } | ||
76 | while (bad_map) { | ||
77 | while ((bad_map & 1) == 0) { | ||
78 | if (src_map & 1) { | ||
79 | dst_map |= (1 << i); | ||
80 | } | ||
81 | src_map >>= 1; | ||
82 | bad_map >>= 1; | ||
83 | ++i; | ||
84 | } | ||
85 | /* (bad_map & 1) == 1 */ | ||
86 | src_map >>= 1; | ||
87 | bad_map >>= 1; | ||
88 | } | ||
89 | if (src_map) { | ||
90 | dst_map |= (src_map << i); | ||
91 | } | ||
92 | if (dst_map) { | ||
93 | TRACE(ft_t_flow, "dst_map = 0x%08lx", (long) dst_map); | ||
94 | } | ||
95 | TRACE_EXIT dst_map; | ||
96 | } | ||
97 | |||
98 | static int correct_and_copy_fraction(buffer_struct *buff, __u8 * destination, | ||
99 | int start, int size) | ||
100 | { | ||
101 | struct memory_segment mseg; | ||
102 | int result; | ||
103 | SectorMap read_bad; | ||
104 | TRACE_FUN(ft_t_any); | ||
105 | |||
106 | mseg.read_bad = convert_sector_map(buff); | ||
107 | mseg.marked_bad = 0; /* not used... */ | ||
108 | mseg.blocks = buff->bytes / FT_SECTOR_SIZE; | ||
109 | mseg.data = buff->address; | ||
110 | /* If there are no data sectors we can skip this segment. | ||
111 | */ | ||
112 | if (mseg.blocks <= 3) { | ||
113 | TRACE_ABORT(0, ft_t_noise, "empty segment"); | ||
114 | } | ||
115 | read_bad = mseg.read_bad; | ||
116 | ft_history.crc_errors += count_ones(read_bad); | ||
117 | result = ftape_ecc_correct_data(&mseg); | ||
118 | if (read_bad != 0 || mseg.corrected != 0) { | ||
119 | TRACE(ft_t_noise, "crc error map: 0x%08lx", (unsigned long)read_bad); | ||
120 | TRACE(ft_t_noise, "corrected map: 0x%08lx", (unsigned long)mseg.corrected); | ||
121 | ft_history.corrected += count_ones(mseg.corrected); | ||
122 | } | ||
123 | if (result == ECC_CORRECTED || result == ECC_OK) { | ||
124 | if (result == ECC_CORRECTED) { | ||
125 | TRACE(ft_t_info, "ecc corrected segment: %d", buff->segment_id); | ||
126 | } | ||
127 | if(start < 0) { | ||
128 | start= 0; | ||
129 | } | ||
130 | if((start+size) > ((mseg.blocks - 3) * FT_SECTOR_SIZE)) { | ||
131 | size = (mseg.blocks - 3) * FT_SECTOR_SIZE - start; | ||
132 | } | ||
133 | if (size < 0) { | ||
134 | size= 0; | ||
135 | } | ||
136 | if(size > 0) { | ||
137 | memcpy(destination + start, mseg.data + start, size); | ||
138 | } | ||
139 | if ((read_bad ^ mseg.corrected) & mseg.corrected) { | ||
140 | /* sectors corrected without crc errors set */ | ||
141 | ft_history.crc_failures++; | ||
142 | } | ||
143 | TRACE_EXIT size; /* (mseg.blocks - 3) * FT_SECTOR_SIZE; */ | ||
144 | } else { | ||
145 | ft_history.ecc_failures++; | ||
146 | TRACE_ABORT(-EAGAIN, | ||
147 | ft_t_err, "ecc failure on segment %d", | ||
148 | buff->segment_id); | ||
149 | } | ||
150 | TRACE_EXIT 0; | ||
151 | } | ||
152 | |||
153 | /* Read given segment into buffer at address. | ||
154 | */ | ||
155 | int ftape_read_segment_fraction(const int segment_id, | ||
156 | void *address, | ||
157 | const ft_read_mode_t read_mode, | ||
158 | const int start, | ||
159 | const int size) | ||
160 | { | ||
161 | int result = 0; | ||
162 | int retry = 0; | ||
163 | int bytes_read = 0; | ||
164 | int read_done = 0; | ||
165 | TRACE_FUN(ft_t_flow); | ||
166 | |||
167 | ft_history.used |= 1; | ||
168 | TRACE(ft_t_data_flow, "segment_id = %d", segment_id); | ||
169 | if (ft_driver_state != reading) { | ||
170 | TRACE(ft_t_noise, "calling ftape_abort_operation"); | ||
171 | TRACE_CATCH(ftape_abort_operation(),); | ||
172 | ftape_set_state(reading); | ||
173 | } | ||
174 | for(;;) { | ||
175 | buffer_struct *tail; | ||
176 | /* Allow escape from this loop on signal ! | ||
177 | */ | ||
178 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
179 | /* Search all full buffers for the first matching the | ||
180 | * wanted segment. Clear other buffers on the fly. | ||
181 | */ | ||
182 | tail = ftape_get_buffer(ft_queue_tail); | ||
183 | while (!read_done && tail->status == done) { | ||
184 | /* Allow escape from this loop on signal ! | ||
185 | */ | ||
186 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
187 | if (tail->segment_id == segment_id) { | ||
188 | /* If out buffer is already full, | ||
189 | * return its contents. | ||
190 | */ | ||
191 | TRACE(ft_t_flow, "found segment in cache: %d", | ||
192 | segment_id); | ||
193 | if (tail->deleted) { | ||
194 | /* Return a value that | ||
195 | * read_header_segment | ||
196 | * understands. As this | ||
197 | * should only occur when | ||
198 | * searching for the header | ||
199 | * segments it shouldn't be | ||
200 | * misinterpreted elsewhere. | ||
201 | */ | ||
202 | TRACE_EXIT 0; | ||
203 | } | ||
204 | result = correct_and_copy_fraction( | ||
205 | tail, | ||
206 | address, | ||
207 | start, | ||
208 | size); | ||
209 | TRACE(ft_t_flow, "segment contains (bytes): %d", | ||
210 | result); | ||
211 | if (result < 0) { | ||
212 | if (result != -EAGAIN) { | ||
213 | TRACE_EXIT result; | ||
214 | } | ||
215 | /* keep read_done == 0, will | ||
216 | * trigger | ||
217 | * ftape_abort_operation | ||
218 | * because reading wrong | ||
219 | * segment. | ||
220 | */ | ||
221 | TRACE(ft_t_err, "ecc failed, retry"); | ||
222 | ++retry; | ||
223 | } else { | ||
224 | read_done = 1; | ||
225 | bytes_read = result; | ||
226 | } | ||
227 | } else { | ||
228 | TRACE(ft_t_flow,"zapping segment in cache: %d", | ||
229 | tail->segment_id); | ||
230 | } | ||
231 | tail->status = waiting; | ||
232 | tail = ftape_next_buffer(ft_queue_tail); | ||
233 | } | ||
234 | if (!read_done && tail->status == reading) { | ||
235 | if (tail->segment_id == segment_id) { | ||
236 | switch(ftape_wait_segment(reading)) { | ||
237 | case 0: | ||
238 | break; | ||
239 | case -EINTR: | ||
240 | TRACE_ABORT(-EINTR, ft_t_warn, | ||
241 | "interrupted by " | ||
242 | "non-blockable signal"); | ||
243 | break; | ||
244 | default: | ||
245 | TRACE(ft_t_noise, | ||
246 | "wait_segment failed"); | ||
247 | ftape_abort_operation(); | ||
248 | ftape_set_state(reading); | ||
249 | break; | ||
250 | } | ||
251 | } else { | ||
252 | /* We're reading the wrong segment, | ||
253 | * stop runner. | ||
254 | */ | ||
255 | TRACE(ft_t_noise, "reading wrong segment"); | ||
256 | ftape_abort_operation(); | ||
257 | ftape_set_state(reading); | ||
258 | } | ||
259 | } | ||
260 | /* should runner stop ? | ||
261 | */ | ||
262 | if (ft_runner_status == aborting) { | ||
263 | buffer_struct *head = ftape_get_buffer(ft_queue_head); | ||
264 | switch(head->status) { | ||
265 | case error: | ||
266 | ft_history.defects += | ||
267 | count_ones(head->hard_error_map); | ||
268 | case reading: | ||
269 | head->status = waiting; | ||
270 | break; | ||
271 | default: | ||
272 | break; | ||
273 | } | ||
274 | TRACE_CATCH(ftape_dumb_stop(),); | ||
275 | } else { | ||
276 | /* If just passed last segment on tape: wait | ||
277 | * for BOT or EOT mark. Sets ft_runner_status to | ||
278 | * idle if at lEOT and successful | ||
279 | */ | ||
280 | TRACE_CATCH(ftape_handle_logical_eot(),); | ||
281 | } | ||
282 | /* If we got a segment: quit, or else retry up to limit. | ||
283 | * | ||
284 | * If segment to read is empty, do not start runner for it, | ||
285 | * but wait for next read call. | ||
286 | */ | ||
287 | if (read_done || | ||
288 | ftape_get_bad_sector_entry(segment_id) == EMPTY_SEGMENT ) { | ||
289 | /* bytes_read = 0; should still be zero */ | ||
290 | TRACE_EXIT bytes_read; | ||
291 | |||
292 | } | ||
293 | if (retry > FT_RETRIES_ON_ECC_ERROR) { | ||
294 | ft_history.defects++; | ||
295 | TRACE_ABORT(-ENODATA, ft_t_err, | ||
296 | "too many retries on ecc failure"); | ||
297 | } | ||
298 | /* Now at least one buffer is empty ! | ||
299 | * Restart runner & tape if needed. | ||
300 | */ | ||
301 | TRACE(ft_t_any, "head: %d, tail: %d, ft_runner_status: %d", | ||
302 | ftape_buffer_id(ft_queue_head), | ||
303 | ftape_buffer_id(ft_queue_tail), | ||
304 | ft_runner_status); | ||
305 | TRACE(ft_t_any, "buffer[].status, [head]: %d, [tail]: %d", | ||
306 | ftape_get_buffer(ft_queue_head)->status, | ||
307 | ftape_get_buffer(ft_queue_tail)->status); | ||
308 | tail = ftape_get_buffer(ft_queue_tail); | ||
309 | if (tail->status == waiting) { | ||
310 | buffer_struct *head = ftape_get_buffer(ft_queue_head); | ||
311 | |||
312 | ftape_setup_new_segment(head, segment_id, -1); | ||
313 | if (read_mode == FT_RD_SINGLE) { | ||
314 | /* disable read-ahead */ | ||
315 | head->next_segment = 0; | ||
316 | } | ||
317 | ftape_calc_next_cluster(head); | ||
318 | if (ft_runner_status == idle) { | ||
319 | result = ftape_start_tape(segment_id, | ||
320 | head->sector_offset); | ||
321 | if (result < 0) { | ||
322 | TRACE_ABORT(result, ft_t_err, "Error: " | ||
323 | "segment %d unreachable", | ||
324 | segment_id); | ||
325 | } | ||
326 | } | ||
327 | head->status = reading; | ||
328 | fdc_setup_read_write(head, FDC_READ); | ||
329 | } | ||
330 | } | ||
331 | /* not reached */ | ||
332 | TRACE_EXIT -EIO; | ||
333 | } | ||
334 | |||
335 | int ftape_read_header_segment(__u8 *address) | ||
336 | { | ||
337 | int result; | ||
338 | int header_segment; | ||
339 | int first_failed = 0; | ||
340 | int status; | ||
341 | TRACE_FUN(ft_t_flow); | ||
342 | |||
343 | ft_used_header_segment = -1; | ||
344 | TRACE_CATCH(ftape_report_drive_status(&status),); | ||
345 | TRACE(ft_t_flow, "reading..."); | ||
346 | /* We're looking for the first header segment. | ||
347 | * A header segment cannot contain bad sectors, therefor at the | ||
348 | * tape start, segments with bad sectors are (according to QIC-40/80) | ||
349 | * written with deleted data marks and must be skipped. | ||
350 | */ | ||
351 | memset(address, '\0', (FT_SECTORS_PER_SEGMENT - 3) * FT_SECTOR_SIZE); | ||
352 | result = 0; | ||
353 | #define HEADER_SEGMENT_BOUNDARY 68 /* why not 42? */ | ||
354 | for (header_segment = 0; | ||
355 | header_segment < HEADER_SEGMENT_BOUNDARY && result == 0; | ||
356 | ++header_segment) { | ||
357 | /* Set no read-ahead, the isr will force read-ahead whenever | ||
358 | * it encounters deleted data ! | ||
359 | */ | ||
360 | result = ftape_read_segment(header_segment, | ||
361 | address, | ||
362 | FT_RD_SINGLE); | ||
363 | if (result < 0 && !first_failed) { | ||
364 | TRACE(ft_t_err, "header segment damaged, trying backup"); | ||
365 | first_failed = 1; | ||
366 | result = 0; /* force read of next (backup) segment */ | ||
367 | } | ||
368 | } | ||
369 | if (result < 0 || header_segment >= HEADER_SEGMENT_BOUNDARY) { | ||
370 | TRACE_ABORT(-EIO, ft_t_err, | ||
371 | "no readable header segment found"); | ||
372 | } | ||
373 | TRACE_CATCH(ftape_abort_operation(),); | ||
374 | ft_used_header_segment = header_segment; | ||
375 | result = ftape_decode_header_segment(address); | ||
376 | TRACE_EXIT result; | ||
377 | } | ||
378 | |||
379 | int ftape_decode_header_segment(__u8 *address) | ||
380 | { | ||
381 | unsigned int max_floppy_side; | ||
382 | unsigned int max_floppy_track; | ||
383 | unsigned int max_floppy_sector; | ||
384 | unsigned int new_tape_len; | ||
385 | TRACE_FUN(ft_t_flow); | ||
386 | |||
387 | if (GET4(address, FT_SIGNATURE) == FT_D2G_MAGIC) { | ||
388 | /* Ditto 2GB header segment. They encrypt the bad sector map. | ||
389 | * We decrypt it and store them in normal format. | ||
390 | * I hope this is correct. | ||
391 | */ | ||
392 | int i; | ||
393 | TRACE(ft_t_warn, | ||
394 | "Found Ditto 2GB tape, " | ||
395 | "trying to decrypt bad sector map"); | ||
396 | for (i=256; i < 29 * FT_SECTOR_SIZE; i++) { | ||
397 | address[i] = ~(address[i] - (i&0xff)); | ||
398 | } | ||
399 | PUT4(address, 0,FT_HSEG_MAGIC); | ||
400 | } else if (GET4(address, FT_SIGNATURE) != FT_HSEG_MAGIC) { | ||
401 | TRACE_ABORT(-EIO, ft_t_err, | ||
402 | "wrong signature in header segment"); | ||
403 | } | ||
404 | ft_format_code = (ft_format_type) address[FT_FMT_CODE]; | ||
405 | if (ft_format_code != fmt_big) { | ||
406 | ft_header_segment_1 = GET2(address, FT_HSEG_1); | ||
407 | ft_header_segment_2 = GET2(address, FT_HSEG_2); | ||
408 | ft_first_data_segment = GET2(address, FT_FRST_SEG); | ||
409 | ft_last_data_segment = GET2(address, FT_LAST_SEG); | ||
410 | } else { | ||
411 | ft_header_segment_1 = GET4(address, FT_6_HSEG_1); | ||
412 | ft_header_segment_2 = GET4(address, FT_6_HSEG_2); | ||
413 | ft_first_data_segment = GET4(address, FT_6_FRST_SEG); | ||
414 | ft_last_data_segment = GET4(address, FT_6_LAST_SEG); | ||
415 | } | ||
416 | TRACE(ft_t_noise, "first data segment: %d", ft_first_data_segment); | ||
417 | TRACE(ft_t_noise, "last data segment: %d", ft_last_data_segment); | ||
418 | TRACE(ft_t_noise, "header segments are %d and %d", | ||
419 | ft_header_segment_1, ft_header_segment_2); | ||
420 | |||
421 | /* Verify tape parameters... | ||
422 | * QIC-40/80 spec: tape_parameters: | ||
423 | * | ||
424 | * segments-per-track segments_per_track | ||
425 | * tracks-per-cartridge tracks_per_tape | ||
426 | * max-floppy-side (segments_per_track * | ||
427 | * tracks_per_tape - 1) / | ||
428 | * ftape_segments_per_head | ||
429 | * max-floppy-track ftape_segments_per_head / | ||
430 | * ftape_segments_per_cylinder - 1 | ||
431 | * max-floppy-sector ftape_segments_per_cylinder * | ||
432 | * FT_SECTORS_PER_SEGMENT | ||
433 | */ | ||
434 | ft_segments_per_track = GET2(address, FT_SPT); | ||
435 | ft_tracks_per_tape = address[FT_TPC]; | ||
436 | max_floppy_side = address[FT_FHM]; | ||
437 | max_floppy_track = address[FT_FTM]; | ||
438 | max_floppy_sector = address[FT_FSM]; | ||
439 | TRACE(ft_t_noise, "(fmt/spt/tpc/fhm/ftm/fsm) = %d/%d/%d/%d/%d/%d", | ||
440 | ft_format_code, ft_segments_per_track, ft_tracks_per_tape, | ||
441 | max_floppy_side, max_floppy_track, max_floppy_sector); | ||
442 | new_tape_len = ftape_tape_len; | ||
443 | switch (ft_format_code) { | ||
444 | case fmt_425ft: | ||
445 | new_tape_len = 425; | ||
446 | break; | ||
447 | case fmt_normal: | ||
448 | if (ftape_tape_len == 0) { /* otherwise 307 ft */ | ||
449 | new_tape_len = 205; | ||
450 | } | ||
451 | break; | ||
452 | case fmt_1100ft: | ||
453 | new_tape_len = 1100; | ||
454 | break; | ||
455 | case fmt_var:{ | ||
456 | int segments_per_1000_inch = 1; /* non-zero default for switch */ | ||
457 | switch (ft_qic_std) { | ||
458 | case QIC_TAPE_QIC40: | ||
459 | segments_per_1000_inch = 332; | ||
460 | break; | ||
461 | case QIC_TAPE_QIC80: | ||
462 | segments_per_1000_inch = 488; | ||
463 | break; | ||
464 | case QIC_TAPE_QIC3010: | ||
465 | segments_per_1000_inch = 730; | ||
466 | break; | ||
467 | case QIC_TAPE_QIC3020: | ||
468 | segments_per_1000_inch = 1430; | ||
469 | break; | ||
470 | } | ||
471 | new_tape_len = (1000 * ft_segments_per_track + | ||
472 | (segments_per_1000_inch - 1)) / segments_per_1000_inch; | ||
473 | break; | ||
474 | } | ||
475 | case fmt_big:{ | ||
476 | int segments_per_1000_inch = 1; /* non-zero default for switch */ | ||
477 | switch (ft_qic_std) { | ||
478 | case QIC_TAPE_QIC40: | ||
479 | segments_per_1000_inch = 332; | ||
480 | break; | ||
481 | case QIC_TAPE_QIC80: | ||
482 | segments_per_1000_inch = 488; | ||
483 | break; | ||
484 | case QIC_TAPE_QIC3010: | ||
485 | segments_per_1000_inch = 730; | ||
486 | break; | ||
487 | case QIC_TAPE_QIC3020: | ||
488 | segments_per_1000_inch = 1430; | ||
489 | break; | ||
490 | default: | ||
491 | TRACE_ABORT(-EIO, ft_t_bug, | ||
492 | "%x QIC-standard with fmt-code %d, please report", | ||
493 | ft_qic_std, ft_format_code); | ||
494 | } | ||
495 | new_tape_len = ((1000 * ft_segments_per_track + | ||
496 | (segments_per_1000_inch - 1)) / | ||
497 | segments_per_1000_inch); | ||
498 | break; | ||
499 | } | ||
500 | default: | ||
501 | TRACE_ABORT(-EIO, ft_t_err, | ||
502 | "unknown tape format, please report !"); | ||
503 | } | ||
504 | if (new_tape_len != ftape_tape_len) { | ||
505 | ftape_tape_len = new_tape_len; | ||
506 | TRACE(ft_t_info, "calculated tape length is %d ft", | ||
507 | ftape_tape_len); | ||
508 | ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len); | ||
509 | } | ||
510 | if (ft_segments_per_track == 0 && ft_tracks_per_tape == 0 && | ||
511 | max_floppy_side == 0 && max_floppy_track == 0 && | ||
512 | max_floppy_sector == 0) { | ||
513 | /* QIC-40 Rev E and earlier has no values in the header. | ||
514 | */ | ||
515 | ft_segments_per_track = 68; | ||
516 | ft_tracks_per_tape = 20; | ||
517 | max_floppy_side = 1; | ||
518 | max_floppy_track = 169; | ||
519 | max_floppy_sector = 128; | ||
520 | } | ||
521 | /* This test will compensate for the wrong parameter on tapes | ||
522 | * formatted by Conner software. | ||
523 | */ | ||
524 | if (ft_segments_per_track == 150 && | ||
525 | ft_tracks_per_tape == 28 && | ||
526 | max_floppy_side == 7 && | ||
527 | max_floppy_track == 149 && | ||
528 | max_floppy_sector == 128) { | ||
529 | TRACE(ft_t_info, "the famous CONNER bug: max_floppy_side off by one !"); | ||
530 | max_floppy_side = 6; | ||
531 | } | ||
532 | /* These tests will compensate for the wrong parameter on tapes | ||
533 | * formatted by ComByte Windows software. | ||
534 | * | ||
535 | * First, for 205 foot tapes | ||
536 | */ | ||
537 | if (ft_segments_per_track == 100 && | ||
538 | ft_tracks_per_tape == 28 && | ||
539 | max_floppy_side == 9 && | ||
540 | max_floppy_track == 149 && | ||
541 | max_floppy_sector == 128) { | ||
542 | TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!"); | ||
543 | max_floppy_side = 4; | ||
544 | } | ||
545 | /* Next, for 307 foot tapes. */ | ||
546 | if (ft_segments_per_track == 150 && | ||
547 | ft_tracks_per_tape == 28 && | ||
548 | max_floppy_side == 9 && | ||
549 | max_floppy_track == 149 && | ||
550 | max_floppy_sector == 128) { | ||
551 | TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!"); | ||
552 | max_floppy_side = 6; | ||
553 | } | ||
554 | /* This test will compensate for the wrong parameter on tapes | ||
555 | * formatted by Colorado Windows software. | ||
556 | */ | ||
557 | if (ft_segments_per_track == 150 && | ||
558 | ft_tracks_per_tape == 28 && | ||
559 | max_floppy_side == 6 && | ||
560 | max_floppy_track == 150 && | ||
561 | max_floppy_sector == 128) { | ||
562 | TRACE(ft_t_info, "the famous Colorado bug: max_floppy_track off by one !"); | ||
563 | max_floppy_track = 149; | ||
564 | } | ||
565 | ftape_segments_per_head = ((max_floppy_sector/FT_SECTORS_PER_SEGMENT) * | ||
566 | (max_floppy_track + 1)); | ||
567 | /* This test will compensate for some bug reported by Dima | ||
568 | * Brodsky. Seems to be a Colorado bug, either. (freebee | ||
569 | * Imation tape shipped together with Colorado T3000 | ||
570 | */ | ||
571 | if ((ft_format_code == fmt_var || ft_format_code == fmt_big) && | ||
572 | ft_tracks_per_tape == 50 && | ||
573 | max_floppy_side == 54 && | ||
574 | max_floppy_track == 255 && | ||
575 | max_floppy_sector == 128) { | ||
576 | TRACE(ft_t_info, "the famous ??? bug: max_floppy_track off by one !"); | ||
577 | max_floppy_track = 254; | ||
578 | } | ||
579 | /* | ||
580 | * Verify drive_configuration with tape parameters | ||
581 | */ | ||
582 | if (ftape_segments_per_head == 0 || ftape_segments_per_cylinder == 0 || | ||
583 | ((ft_segments_per_track * ft_tracks_per_tape - 1) / ftape_segments_per_head | ||
584 | != max_floppy_side) || | ||
585 | (ftape_segments_per_head / ftape_segments_per_cylinder - 1 != max_floppy_track) || | ||
586 | (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT != max_floppy_sector) | ||
587 | #ifdef TESTING | ||
588 | || ((ft_format_code == fmt_var || ft_format_code == fmt_big) && | ||
589 | (max_floppy_track != 254 || max_floppy_sector != 128)) | ||
590 | #endif | ||
591 | ) { | ||
592 | char segperheadz = ftape_segments_per_head ? ' ' : '?'; | ||
593 | char segpercylz = ftape_segments_per_cylinder ? ' ' : '?'; | ||
594 | TRACE(ft_t_err,"Tape parameters inconsistency, please report"); | ||
595 | TRACE(ft_t_err, "reported = %d/%d/%d/%d/%d/%d", | ||
596 | ft_format_code, | ||
597 | ft_segments_per_track, | ||
598 | ft_tracks_per_tape, | ||
599 | max_floppy_side, | ||
600 | max_floppy_track, | ||
601 | max_floppy_sector); | ||
602 | TRACE(ft_t_err, "required = %d/%d/%d/%d%c/%d%c/%d", | ||
603 | ft_format_code, | ||
604 | ft_segments_per_track, | ||
605 | ft_tracks_per_tape, | ||
606 | ftape_segments_per_head ? | ||
607 | ((ft_segments_per_track * ft_tracks_per_tape -1) / | ||
608 | ftape_segments_per_head ) : | ||
609 | (ft_segments_per_track * ft_tracks_per_tape -1), | ||
610 | segperheadz, | ||
611 | ftape_segments_per_cylinder ? | ||
612 | (ftape_segments_per_head / | ||
613 | ftape_segments_per_cylinder - 1 ) : | ||
614 | ftape_segments_per_head - 1, | ||
615 | segpercylz, | ||
616 | (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT)); | ||
617 | TRACE_EXIT -EIO; | ||
618 | } | ||
619 | ftape_extract_bad_sector_map(address); | ||
620 | TRACE_EXIT 0; | ||
621 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-read.h b/drivers/char/ftape/lowlevel/ftape-read.h deleted file mode 100644 index 069f99f2a984..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-read.h +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | #ifndef _FTAPE_READ_H | ||
2 | #define _FTAPE_READ_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1994-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:22 $ | ||
26 | * | ||
27 | * This file contains the definitions for the read functions | ||
28 | * for the QIC-117 floppy-tape driver for Linux. | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | /* ftape-read.c defined global functions. | ||
33 | */ | ||
34 | typedef enum { | ||
35 | FT_RD_SINGLE = 0, | ||
36 | FT_RD_AHEAD = 1, | ||
37 | } ft_read_mode_t; | ||
38 | |||
39 | extern int ftape_read_header_segment(__u8 *address); | ||
40 | extern int ftape_decode_header_segment(__u8 *address); | ||
41 | extern int ftape_read_segment_fraction(const int segment, | ||
42 | void *address, | ||
43 | const ft_read_mode_t read_mode, | ||
44 | const int start, | ||
45 | const int size); | ||
46 | #define ftape_read_segment(segment, address, read_mode) \ | ||
47 | ftape_read_segment_fraction(segment, address, read_mode, \ | ||
48 | 0, FT_SEGMENT_SIZE) | ||
49 | extern void ftape_zap_read_buffers(void); | ||
50 | |||
51 | #endif /* _FTAPE_READ_H */ | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-rw.c b/drivers/char/ftape/lowlevel/ftape-rw.c deleted file mode 100644 index c0d6dc2cbfd3..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-rw.c +++ /dev/null | |||
@@ -1,1092 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-rw.c,v $ | ||
21 | * $Revision: 1.7 $ | ||
22 | * $Date: 1997/10/28 14:26:49 $ | ||
23 | * | ||
24 | * This file contains some common code for the segment read and | ||
25 | * segment write routines for the QIC-117 floppy-tape driver for | ||
26 | * Linux. | ||
27 | */ | ||
28 | |||
29 | #include <linux/string.h> | ||
30 | #include <linux/errno.h> | ||
31 | |||
32 | #include <linux/ftape.h> | ||
33 | #include <linux/qic117.h> | ||
34 | #include "../lowlevel/ftape-tracing.h" | ||
35 | #include "../lowlevel/ftape-rw.h" | ||
36 | #include "../lowlevel/fdc-io.h" | ||
37 | #include "../lowlevel/ftape-init.h" | ||
38 | #include "../lowlevel/ftape-io.h" | ||
39 | #include "../lowlevel/ftape-ctl.h" | ||
40 | #include "../lowlevel/ftape-read.h" | ||
41 | #include "../lowlevel/ftape-ecc.h" | ||
42 | #include "../lowlevel/ftape-bsm.h" | ||
43 | |||
44 | /* Global vars. | ||
45 | */ | ||
46 | int ft_nr_buffers; | ||
47 | buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS]; | ||
48 | static volatile int ft_head; | ||
49 | static volatile int ft_tail; /* not volatile but need same type as head */ | ||
50 | int fdc_setup_error; | ||
51 | location_record ft_location = {-1, 0}; | ||
52 | volatile int ftape_tape_running; | ||
53 | |||
54 | /* Local vars. | ||
55 | */ | ||
56 | static int overrun_count_offset; | ||
57 | static int inhibit_correction; | ||
58 | |||
59 | /* maxmimal allowed overshoot when fast seeking | ||
60 | */ | ||
61 | #define OVERSHOOT_LIMIT 10 | ||
62 | |||
63 | /* Increment cyclic buffer nr. | ||
64 | */ | ||
65 | buffer_struct *ftape_next_buffer(ft_buffer_queue_t pos) | ||
66 | { | ||
67 | switch (pos) { | ||
68 | case ft_queue_head: | ||
69 | if (++ft_head >= ft_nr_buffers) { | ||
70 | ft_head = 0; | ||
71 | } | ||
72 | return ft_buffer[ft_head]; | ||
73 | case ft_queue_tail: | ||
74 | if (++ft_tail >= ft_nr_buffers) { | ||
75 | ft_tail = 0; | ||
76 | } | ||
77 | return ft_buffer[ft_tail]; | ||
78 | default: | ||
79 | return NULL; | ||
80 | } | ||
81 | } | ||
82 | int ftape_buffer_id(ft_buffer_queue_t pos) | ||
83 | { | ||
84 | switch(pos) { | ||
85 | case ft_queue_head: return ft_head; | ||
86 | case ft_queue_tail: return ft_tail; | ||
87 | default: return -1; | ||
88 | } | ||
89 | } | ||
90 | buffer_struct *ftape_get_buffer(ft_buffer_queue_t pos) | ||
91 | { | ||
92 | switch(pos) { | ||
93 | case ft_queue_head: return ft_buffer[ft_head]; | ||
94 | case ft_queue_tail: return ft_buffer[ft_tail]; | ||
95 | default: return NULL; | ||
96 | } | ||
97 | } | ||
98 | void ftape_reset_buffer(void) | ||
99 | { | ||
100 | ft_head = ft_tail = 0; | ||
101 | } | ||
102 | |||
103 | buffer_state_enum ftape_set_state(buffer_state_enum new_state) | ||
104 | { | ||
105 | buffer_state_enum old_state = ft_driver_state; | ||
106 | |||
107 | ft_driver_state = new_state; | ||
108 | return old_state; | ||
109 | } | ||
110 | /* Calculate Floppy Disk Controller and DMA parameters for a segment. | ||
111 | * head: selects buffer struct in array. | ||
112 | * offset: number of physical sectors to skip (including bad ones). | ||
113 | * count: number of physical sectors to handle (including bad ones). | ||
114 | */ | ||
115 | static int setup_segment(buffer_struct * buff, | ||
116 | int segment_id, | ||
117 | unsigned int sector_offset, | ||
118 | unsigned int sector_count, | ||
119 | int retry) | ||
120 | { | ||
121 | SectorMap offset_mask; | ||
122 | SectorMap mask; | ||
123 | TRACE_FUN(ft_t_any); | ||
124 | |||
125 | buff->segment_id = segment_id; | ||
126 | buff->sector_offset = sector_offset; | ||
127 | buff->remaining = sector_count; | ||
128 | buff->head = segment_id / ftape_segments_per_head; | ||
129 | buff->cyl = (segment_id % ftape_segments_per_head) / ftape_segments_per_cylinder; | ||
130 | buff->sect = (segment_id % ftape_segments_per_cylinder) * FT_SECTORS_PER_SEGMENT + 1; | ||
131 | buff->deleted = 0; | ||
132 | offset_mask = (1 << buff->sector_offset) - 1; | ||
133 | mask = ftape_get_bad_sector_entry(segment_id) & offset_mask; | ||
134 | while (mask) { | ||
135 | if (mask & 1) { | ||
136 | offset_mask >>= 1; /* don't count bad sector */ | ||
137 | } | ||
138 | mask >>= 1; | ||
139 | } | ||
140 | buff->data_offset = count_ones(offset_mask); /* good sectors to skip */ | ||
141 | buff->ptr = buff->address + buff->data_offset * FT_SECTOR_SIZE; | ||
142 | TRACE(ft_t_flow, "data offset = %d sectors", buff->data_offset); | ||
143 | if (retry) { | ||
144 | buff->soft_error_map &= offset_mask; /* keep skipped part */ | ||
145 | } else { | ||
146 | buff->hard_error_map = buff->soft_error_map = 0; | ||
147 | } | ||
148 | buff->bad_sector_map = ftape_get_bad_sector_entry(buff->segment_id); | ||
149 | if (buff->bad_sector_map != 0) { | ||
150 | TRACE(ft_t_noise, "segment: %d, bad sector map: %08lx", | ||
151 | buff->segment_id, (long)buff->bad_sector_map); | ||
152 | } else { | ||
153 | TRACE(ft_t_flow, "segment: %d", buff->segment_id); | ||
154 | } | ||
155 | if (buff->sector_offset > 0) { | ||
156 | buff->bad_sector_map >>= buff->sector_offset; | ||
157 | } | ||
158 | if (buff->sector_offset != 0 || buff->remaining != FT_SECTORS_PER_SEGMENT) { | ||
159 | TRACE(ft_t_flow, "sector offset = %d, count = %d", | ||
160 | buff->sector_offset, buff->remaining); | ||
161 | } | ||
162 | /* Segments with 3 or less sectors are not written with valid | ||
163 | * data because there is no space left for the ecc. The | ||
164 | * data written is whatever happens to be in the buffer. | ||
165 | * Reading such a segment will return a zero byte-count. | ||
166 | * To allow us to read/write segments with all bad sectors | ||
167 | * we fake one readable sector in the segment. This | ||
168 | * prevents having to handle these segments in a very | ||
169 | * special way. It is not important if the reading of this | ||
170 | * bad sector fails or not (the data is ignored). It is | ||
171 | * only read to keep the driver running. | ||
172 | * | ||
173 | * The QIC-40/80 spec. has no information on how to handle | ||
174 | * this case, so this is my interpretation. | ||
175 | */ | ||
176 | if (buff->bad_sector_map == EMPTY_SEGMENT) { | ||
177 | TRACE(ft_t_flow, "empty segment %d, fake first sector good", | ||
178 | buff->segment_id); | ||
179 | if (buff->ptr != buff->address) { | ||
180 | TRACE(ft_t_bug, "This is a bug: %p/%p", | ||
181 | buff->ptr, buff->address); | ||
182 | } | ||
183 | buff->bad_sector_map = FAKE_SEGMENT; | ||
184 | } | ||
185 | fdc_setup_error = 0; | ||
186 | buff->next_segment = segment_id + 1; | ||
187 | TRACE_EXIT 0; | ||
188 | } | ||
189 | |||
190 | /* Calculate Floppy Disk Controller and DMA parameters for a new segment. | ||
191 | */ | ||
192 | int ftape_setup_new_segment(buffer_struct * buff, int segment_id, int skip) | ||
193 | { | ||
194 | int result = 0; | ||
195 | static int old_segment_id = -1; | ||
196 | static buffer_state_enum old_ft_driver_state = idle; | ||
197 | int retry = 0; | ||
198 | unsigned offset = 0; | ||
199 | int count = FT_SECTORS_PER_SEGMENT; | ||
200 | TRACE_FUN(ft_t_flow); | ||
201 | |||
202 | TRACE(ft_t_flow, "%s segment %d (old = %d)", | ||
203 | (ft_driver_state == reading || ft_driver_state == verifying) | ||
204 | ? "reading" : "writing", | ||
205 | segment_id, old_segment_id); | ||
206 | if (ft_driver_state != old_ft_driver_state) { /* when verifying */ | ||
207 | old_segment_id = -1; | ||
208 | old_ft_driver_state = ft_driver_state; | ||
209 | } | ||
210 | if (segment_id == old_segment_id) { | ||
211 | ++buff->retry; | ||
212 | ++ft_history.retries; | ||
213 | TRACE(ft_t_flow, "setting up for retry nr %d", buff->retry); | ||
214 | retry = 1; | ||
215 | if (skip && buff->skip > 0) { /* allow skip on retry */ | ||
216 | offset = buff->skip; | ||
217 | count -= offset; | ||
218 | TRACE(ft_t_flow, "skipping %d sectors", offset); | ||
219 | } | ||
220 | } else { | ||
221 | buff->retry = 0; | ||
222 | buff->skip = 0; | ||
223 | old_segment_id = segment_id; | ||
224 | } | ||
225 | result = setup_segment(buff, segment_id, offset, count, retry); | ||
226 | TRACE_EXIT result; | ||
227 | } | ||
228 | |||
229 | /* Determine size of next cluster of good sectors. | ||
230 | */ | ||
231 | int ftape_calc_next_cluster(buffer_struct * buff) | ||
232 | { | ||
233 | /* Skip bad sectors. | ||
234 | */ | ||
235 | while (buff->remaining > 0 && (buff->bad_sector_map & 1) != 0) { | ||
236 | buff->bad_sector_map >>= 1; | ||
237 | ++buff->sector_offset; | ||
238 | --buff->remaining; | ||
239 | } | ||
240 | /* Find next cluster of good sectors | ||
241 | */ | ||
242 | if (buff->bad_sector_map == 0) { /* speed up */ | ||
243 | buff->sector_count = buff->remaining; | ||
244 | } else { | ||
245 | SectorMap map = buff->bad_sector_map; | ||
246 | |||
247 | buff->sector_count = 0; | ||
248 | while (buff->sector_count < buff->remaining && (map & 1) == 0) { | ||
249 | ++buff->sector_count; | ||
250 | map >>= 1; | ||
251 | } | ||
252 | } | ||
253 | return buff->sector_count; | ||
254 | } | ||
255 | |||
256 | /* if just passed the last segment on a track, wait for BOT | ||
257 | * or EOT mark. | ||
258 | */ | ||
259 | int ftape_handle_logical_eot(void) | ||
260 | { | ||
261 | TRACE_FUN(ft_t_flow); | ||
262 | |||
263 | if (ft_runner_status == logical_eot) { | ||
264 | int status; | ||
265 | |||
266 | TRACE(ft_t_noise, "tape at logical EOT"); | ||
267 | TRACE_CATCH(ftape_ready_wait(ftape_timeout.seek, &status),); | ||
268 | if ((status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) { | ||
269 | TRACE_ABORT(-EIO, ft_t_err, "eot/bot not reached"); | ||
270 | } | ||
271 | ft_runner_status = end_of_tape; | ||
272 | } | ||
273 | if (ft_runner_status == end_of_tape) { | ||
274 | TRACE(ft_t_noise, "runner stopped because of logical EOT"); | ||
275 | ft_runner_status = idle; | ||
276 | } | ||
277 | TRACE_EXIT 0; | ||
278 | } | ||
279 | |||
280 | static int check_bot_eot(int status) | ||
281 | { | ||
282 | TRACE_FUN(ft_t_flow); | ||
283 | |||
284 | if (status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) { | ||
285 | ft_location.bot = ((ft_location.track & 1) == 0 ? | ||
286 | (status & QIC_STATUS_AT_BOT) != 0: | ||
287 | (status & QIC_STATUS_AT_EOT) != 0); | ||
288 | ft_location.eot = !ft_location.bot; | ||
289 | ft_location.segment = (ft_location.track + | ||
290 | (ft_location.bot ? 0 : 1)) * ft_segments_per_track - 1; | ||
291 | ft_location.sector = -1; | ||
292 | ft_location.known = 1; | ||
293 | TRACE(ft_t_flow, "tape at logical %s", | ||
294 | ft_location.bot ? "bot" : "eot"); | ||
295 | TRACE(ft_t_flow, "segment = %d", ft_location.segment); | ||
296 | } else { | ||
297 | ft_location.known = 0; | ||
298 | } | ||
299 | TRACE_EXIT ft_location.known; | ||
300 | } | ||
301 | |||
302 | /* Read Id of first sector passing tape head. | ||
303 | */ | ||
304 | static int ftape_read_id(void) | ||
305 | { | ||
306 | int status; | ||
307 | __u8 out[2]; | ||
308 | TRACE_FUN(ft_t_any); | ||
309 | |||
310 | /* Assume tape is running on entry, be able to handle | ||
311 | * situation where it stopped or is stopping. | ||
312 | */ | ||
313 | ft_location.known = 0; /* default is location not known */ | ||
314 | out[0] = FDC_READID; | ||
315 | out[1] = ft_drive_sel; | ||
316 | TRACE_CATCH(fdc_command(out, 2),); | ||
317 | switch (fdc_interrupt_wait(20 * FT_SECOND)) { | ||
318 | case 0: | ||
319 | if (fdc_sect == 0) { | ||
320 | if (ftape_report_drive_status(&status) >= 0 && | ||
321 | (status & QIC_STATUS_READY)) { | ||
322 | ftape_tape_running = 0; | ||
323 | TRACE(ft_t_flow, "tape has stopped"); | ||
324 | check_bot_eot(status); | ||
325 | } | ||
326 | } else { | ||
327 | ft_location.known = 1; | ||
328 | ft_location.segment = (ftape_segments_per_head | ||
329 | * fdc_head | ||
330 | + ftape_segments_per_cylinder | ||
331 | * fdc_cyl | ||
332 | + (fdc_sect - 1) | ||
333 | / FT_SECTORS_PER_SEGMENT); | ||
334 | ft_location.sector = ((fdc_sect - 1) | ||
335 | % FT_SECTORS_PER_SEGMENT); | ||
336 | ft_location.eot = ft_location.bot = 0; | ||
337 | } | ||
338 | break; | ||
339 | case -ETIME: | ||
340 | /* Didn't find id on tape, must be near end: Wait | ||
341 | * until stopped. | ||
342 | */ | ||
343 | if (ftape_ready_wait(FT_FOREVER, &status) >= 0) { | ||
344 | ftape_tape_running = 0; | ||
345 | TRACE(ft_t_flow, "tape has stopped"); | ||
346 | check_bot_eot(status); | ||
347 | } | ||
348 | break; | ||
349 | default: | ||
350 | /* Interrupted or otherwise failing | ||
351 | * fdc_interrupt_wait() | ||
352 | */ | ||
353 | TRACE(ft_t_err, "fdc_interrupt_wait failed"); | ||
354 | break; | ||
355 | } | ||
356 | if (!ft_location.known) { | ||
357 | TRACE_ABORT(-EIO, ft_t_flow, "no id found"); | ||
358 | } | ||
359 | if (ft_location.sector == 0) { | ||
360 | TRACE(ft_t_flow, "passing segment %d/%d", | ||
361 | ft_location.segment, ft_location.sector); | ||
362 | } else { | ||
363 | TRACE(ft_t_fdc_dma, "passing segment %d/%d", | ||
364 | ft_location.segment, ft_location.sector); | ||
365 | } | ||
366 | TRACE_EXIT 0; | ||
367 | } | ||
368 | |||
369 | static int logical_forward(void) | ||
370 | { | ||
371 | ftape_tape_running = 1; | ||
372 | return ftape_command(QIC_LOGICAL_FORWARD); | ||
373 | } | ||
374 | |||
375 | int ftape_stop_tape(int *pstatus) | ||
376 | { | ||
377 | int retry = 0; | ||
378 | int result; | ||
379 | TRACE_FUN(ft_t_flow); | ||
380 | |||
381 | do { | ||
382 | result = ftape_command_wait(QIC_STOP_TAPE, | ||
383 | ftape_timeout.stop, pstatus); | ||
384 | if (result == 0) { | ||
385 | if ((*pstatus & QIC_STATUS_READY) == 0) { | ||
386 | result = -EIO; | ||
387 | } else { | ||
388 | ftape_tape_running = 0; | ||
389 | } | ||
390 | } | ||
391 | } while (result < 0 && ++retry <= 3); | ||
392 | if (result < 0) { | ||
393 | TRACE(ft_t_err, "failed ! (fatal)"); | ||
394 | } | ||
395 | TRACE_EXIT result; | ||
396 | } | ||
397 | |||
398 | int ftape_dumb_stop(void) | ||
399 | { | ||
400 | int result; | ||
401 | int status; | ||
402 | TRACE_FUN(ft_t_flow); | ||
403 | |||
404 | /* Abort current fdc operation if it's busy (probably read | ||
405 | * or write operation pending) with a reset. | ||
406 | */ | ||
407 | if (fdc_ready_wait(100 /* usec */) < 0) { | ||
408 | TRACE(ft_t_noise, "aborting fdc operation"); | ||
409 | fdc_reset(); | ||
410 | } | ||
411 | /* Reading id's after the last segment on a track may fail | ||
412 | * but eventually the drive will become ready (logical eot). | ||
413 | */ | ||
414 | result = ftape_report_drive_status(&status); | ||
415 | ft_location.known = 0; | ||
416 | do { | ||
417 | if (result == 0 && status & QIC_STATUS_READY) { | ||
418 | /* Tape is not running any more. | ||
419 | */ | ||
420 | TRACE(ft_t_noise, "tape already halted"); | ||
421 | check_bot_eot(status); | ||
422 | ftape_tape_running = 0; | ||
423 | } else if (ftape_tape_running) { | ||
424 | /* Tape is (was) still moving. | ||
425 | */ | ||
426 | #ifdef TESTING | ||
427 | ftape_read_id(); | ||
428 | #endif | ||
429 | result = ftape_stop_tape(&status); | ||
430 | } else { | ||
431 | /* Tape not yet ready but stopped. | ||
432 | */ | ||
433 | result = ftape_ready_wait(ftape_timeout.pause,&status); | ||
434 | } | ||
435 | } while (ftape_tape_running | ||
436 | && !(sigtestsetmask(¤t->pending.signal, _NEVER_BLOCK))); | ||
437 | #ifndef TESTING | ||
438 | ft_location.known = 0; | ||
439 | #endif | ||
440 | if (ft_runner_status == aborting || ft_runner_status == do_abort) { | ||
441 | ft_runner_status = idle; | ||
442 | } | ||
443 | TRACE_EXIT result; | ||
444 | } | ||
445 | |||
446 | /* Wait until runner has finished tail buffer. | ||
447 | * | ||
448 | */ | ||
449 | int ftape_wait_segment(buffer_state_enum state) | ||
450 | { | ||
451 | int status; | ||
452 | int result = 0; | ||
453 | TRACE_FUN(ft_t_flow); | ||
454 | |||
455 | while (ft_buffer[ft_tail]->status == state) { | ||
456 | TRACE(ft_t_flow, "state: %d", ft_buffer[ft_tail]->status); | ||
457 | /* First buffer still being worked on, wait up to timeout. | ||
458 | * | ||
459 | * Note: we check two times for being killed. 50 | ||
460 | * seconds are quite long. Note that | ||
461 | * fdc_interrupt_wait() is not killable by any | ||
462 | * means. ftape_read_segment() wants us to return | ||
463 | * -EINTR in case of a signal. | ||
464 | */ | ||
465 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
466 | result = fdc_interrupt_wait(50 * FT_SECOND); | ||
467 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
468 | if (result < 0) { | ||
469 | TRACE_ABORT(result, | ||
470 | ft_t_err, "fdc_interrupt_wait failed"); | ||
471 | } | ||
472 | if (fdc_setup_error) { | ||
473 | /* recover... FIXME */ | ||
474 | TRACE_ABORT(-EIO, ft_t_err, "setup error"); | ||
475 | } | ||
476 | } | ||
477 | if (ft_buffer[ft_tail]->status != error) { | ||
478 | TRACE_EXIT 0; | ||
479 | } | ||
480 | TRACE_CATCH(ftape_report_drive_status(&status),); | ||
481 | TRACE(ft_t_noise, "ftape_report_drive_status: 0x%02x", status); | ||
482 | if ((status & QIC_STATUS_READY) && | ||
483 | (status & QIC_STATUS_ERROR)) { | ||
484 | unsigned int error; | ||
485 | qic117_cmd_t command; | ||
486 | |||
487 | /* Report and clear error state. | ||
488 | * In case the drive can't operate at the selected | ||
489 | * rate, select the next lower data rate. | ||
490 | */ | ||
491 | ftape_report_error(&error, &command, 1); | ||
492 | if (error == 31 && command == QIC_LOGICAL_FORWARD) { | ||
493 | /* drive does not accept this data rate */ | ||
494 | if (ft_data_rate > 250) { | ||
495 | TRACE(ft_t_info, | ||
496 | "Probable data rate conflict"); | ||
497 | TRACE(ft_t_info, | ||
498 | "Lowering data rate to %d Kbps", | ||
499 | ft_data_rate / 2); | ||
500 | ftape_half_data_rate(); | ||
501 | if (ft_buffer[ft_tail]->retry > 0) { | ||
502 | /* give it a chance */ | ||
503 | --ft_buffer[ft_tail]->retry; | ||
504 | } | ||
505 | } else { | ||
506 | /* no rate is accepted... */ | ||
507 | TRACE(ft_t_err, "We're dead :("); | ||
508 | } | ||
509 | } else { | ||
510 | TRACE(ft_t_err, "Unknown error"); | ||
511 | } | ||
512 | TRACE_EXIT -EIO; /* g.p. error */ | ||
513 | } | ||
514 | TRACE_EXIT 0; | ||
515 | } | ||
516 | |||
517 | /* forward */ static int seek_forward(int segment_id, int fast); | ||
518 | |||
519 | static int fast_seek(int count, int reverse) | ||
520 | { | ||
521 | int result = 0; | ||
522 | int status; | ||
523 | TRACE_FUN(ft_t_flow); | ||
524 | |||
525 | if (count > 0) { | ||
526 | /* If positioned at begin or end of tape, fast seeking needs | ||
527 | * special treatment. | ||
528 | * Starting from logical bot needs a (slow) seek to the first | ||
529 | * segment before the high speed seek. Most drives do this | ||
530 | * automatically but some older don't, so we treat them | ||
531 | * all the same. | ||
532 | * Starting from logical eot is even more difficult because | ||
533 | * we cannot (slow) reverse seek to the last segment. | ||
534 | * TO BE IMPLEMENTED. | ||
535 | */ | ||
536 | inhibit_correction = 0; | ||
537 | if (ft_location.known && | ||
538 | ((ft_location.bot && !reverse) || | ||
539 | (ft_location.eot && reverse))) { | ||
540 | if (!reverse) { | ||
541 | /* (slow) skip to first segment on a track | ||
542 | */ | ||
543 | seek_forward(ft_location.track * ft_segments_per_track, 0); | ||
544 | --count; | ||
545 | } else { | ||
546 | /* When seeking backwards from | ||
547 | * end-of-tape the number of erased | ||
548 | * gaps found seems to be higher than | ||
549 | * expected. Therefor the drive must | ||
550 | * skip some more segments than | ||
551 | * calculated, but we don't know how | ||
552 | * many. Thus we will prevent the | ||
553 | * re-calculation of offset and | ||
554 | * overshoot when seeking backwards. | ||
555 | */ | ||
556 | inhibit_correction = 1; | ||
557 | count += 3; /* best guess */ | ||
558 | } | ||
559 | } | ||
560 | } else { | ||
561 | TRACE(ft_t_flow, "warning: zero or negative count: %d", count); | ||
562 | } | ||
563 | if (count > 0) { | ||
564 | int i; | ||
565 | int nibbles = count > 255 ? 3 : 2; | ||
566 | |||
567 | if (count > 4095) { | ||
568 | TRACE(ft_t_noise, "skipping clipped at 4095 segment"); | ||
569 | count = 4095; | ||
570 | } | ||
571 | /* Issue this tape command first. */ | ||
572 | if (!reverse) { | ||
573 | TRACE(ft_t_noise, "skipping %d segment(s)", count); | ||
574 | result = ftape_command(nibbles == 3 ? | ||
575 | QIC_SKIP_EXTENDED_FORWARD : QIC_SKIP_FORWARD); | ||
576 | } else { | ||
577 | TRACE(ft_t_noise, "backing up %d segment(s)", count); | ||
578 | result = ftape_command(nibbles == 3 ? | ||
579 | QIC_SKIP_EXTENDED_REVERSE : QIC_SKIP_REVERSE); | ||
580 | } | ||
581 | if (result < 0) { | ||
582 | TRACE(ft_t_noise, "Skip command failed"); | ||
583 | } else { | ||
584 | --count; /* 0 means one gap etc. */ | ||
585 | for (i = 0; i < nibbles; ++i) { | ||
586 | if (result >= 0) { | ||
587 | result = ftape_parameter(count & 15); | ||
588 | count /= 16; | ||
589 | } | ||
590 | } | ||
591 | result = ftape_ready_wait(ftape_timeout.rewind, &status); | ||
592 | if (result >= 0) { | ||
593 | ftape_tape_running = 0; | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | TRACE_EXIT result; | ||
598 | } | ||
599 | |||
600 | static int validate(int id) | ||
601 | { | ||
602 | /* Check to see if position found is off-track as reported | ||
603 | * once. Because all tracks in one direction lie next to | ||
604 | * each other, if off-track the error will be approximately | ||
605 | * 2 * ft_segments_per_track. | ||
606 | */ | ||
607 | if (ft_location.track == -1) { | ||
608 | return 1; /* unforseen situation, don't generate error */ | ||
609 | } else { | ||
610 | /* Use margin of ft_segments_per_track on both sides | ||
611 | * because ftape needs some margin and the error we're | ||
612 | * looking for is much larger ! | ||
613 | */ | ||
614 | int lo = (ft_location.track - 1) * ft_segments_per_track; | ||
615 | int hi = (ft_location.track + 2) * ft_segments_per_track; | ||
616 | |||
617 | return (id >= lo && id < hi); | ||
618 | } | ||
619 | } | ||
620 | |||
621 | static int seek_forward(int segment_id, int fast) | ||
622 | { | ||
623 | int failures = 0; | ||
624 | int count; | ||
625 | static int margin = 1; /* fixed: stop this before target */ | ||
626 | static int overshoot = 1; | ||
627 | static int min_count = 8; | ||
628 | int expected = -1; | ||
629 | int target = segment_id - margin; | ||
630 | int fast_seeking; | ||
631 | int prev_segment = ft_location.segment; | ||
632 | TRACE_FUN(ft_t_flow); | ||
633 | |||
634 | if (!ft_location.known) { | ||
635 | TRACE_ABORT(-EIO, ft_t_err, | ||
636 | "fatal: cannot seek from unknown location"); | ||
637 | } | ||
638 | if (!validate(segment_id)) { | ||
639 | ftape_sleep(1 * FT_SECOND); | ||
640 | ft_failure = 1; | ||
641 | TRACE_ABORT(-EIO, ft_t_err, | ||
642 | "fatal: head off track (bad hardware?)"); | ||
643 | } | ||
644 | TRACE(ft_t_noise, "from %d/%d to %d/0 - %d", | ||
645 | ft_location.segment, ft_location.sector,segment_id,margin); | ||
646 | count = target - ft_location.segment - overshoot; | ||
647 | fast_seeking = (fast && | ||
648 | count > (min_count + (ft_location.bot ? 1 : 0))); | ||
649 | if (fast_seeking) { | ||
650 | TRACE(ft_t_noise, "fast skipping %d segments", count); | ||
651 | expected = segment_id - margin; | ||
652 | fast_seek(count, 0); | ||
653 | } | ||
654 | if (!ftape_tape_running) { | ||
655 | logical_forward(); | ||
656 | } | ||
657 | while (ft_location.segment < segment_id) { | ||
658 | /* This requires at least one sector in a (bad) segment to | ||
659 | * have a valid and readable sector id ! | ||
660 | * It looks like this is not guaranteed, so we must try | ||
661 | * to find a way to skip an EMPTY_SEGMENT. !!! FIXME !!! | ||
662 | */ | ||
663 | if (ftape_read_id() < 0 || !ft_location.known || | ||
664 | sigtestsetmask(¤t->pending.signal, _DONT_BLOCK)) { | ||
665 | ft_location.known = 0; | ||
666 | if (!ftape_tape_running || | ||
667 | ++failures > FT_SECTORS_PER_SEGMENT) { | ||
668 | TRACE_ABORT(-EIO, ft_t_err, | ||
669 | "read_id failed completely"); | ||
670 | } | ||
671 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
672 | TRACE(ft_t_flow, "read_id failed, retry (%d)", | ||
673 | failures); | ||
674 | continue; | ||
675 | } | ||
676 | if (fast_seeking) { | ||
677 | TRACE(ft_t_noise, "ended at %d/%d (%d,%d)", | ||
678 | ft_location.segment, ft_location.sector, | ||
679 | overshoot, inhibit_correction); | ||
680 | if (!inhibit_correction && | ||
681 | (ft_location.segment < expected || | ||
682 | ft_location.segment > expected + margin)) { | ||
683 | int error = ft_location.segment - expected; | ||
684 | TRACE(ft_t_noise, | ||
685 | "adjusting overshoot from %d to %d", | ||
686 | overshoot, overshoot + error); | ||
687 | overshoot += error; | ||
688 | /* All overshoots have the same | ||
689 | * direction, so it should never | ||
690 | * become negative, but who knows. | ||
691 | */ | ||
692 | if (overshoot < -5 || | ||
693 | overshoot > OVERSHOOT_LIMIT) { | ||
694 | if (overshoot < 0) { | ||
695 | /* keep sane value */ | ||
696 | overshoot = -5; | ||
697 | } else { | ||
698 | /* keep sane value */ | ||
699 | overshoot = OVERSHOOT_LIMIT; | ||
700 | } | ||
701 | TRACE(ft_t_noise, | ||
702 | "clipped overshoot to %d", | ||
703 | overshoot); | ||
704 | } | ||
705 | } | ||
706 | fast_seeking = 0; | ||
707 | } | ||
708 | if (ft_location.known) { | ||
709 | if (ft_location.segment > prev_segment + 1) { | ||
710 | TRACE(ft_t_noise, | ||
711 | "missed segment %d while skipping", | ||
712 | prev_segment + 1); | ||
713 | } | ||
714 | prev_segment = ft_location.segment; | ||
715 | } | ||
716 | } | ||
717 | if (ft_location.segment > segment_id) { | ||
718 | TRACE_ABORT(-EIO, | ||
719 | ft_t_noise, "failed: skip ended at segment %d/%d", | ||
720 | ft_location.segment, ft_location.sector); | ||
721 | } | ||
722 | TRACE_EXIT 0; | ||
723 | } | ||
724 | |||
725 | static int skip_reverse(int segment_id, int *pstatus) | ||
726 | { | ||
727 | int failures = 0; | ||
728 | static int overshoot = 1; | ||
729 | static int min_rewind = 2; /* 1 + overshoot */ | ||
730 | static const int margin = 1; /* stop this before target */ | ||
731 | int expected = 0; | ||
732 | int count = 1; | ||
733 | int short_seek; | ||
734 | int target = segment_id - margin; | ||
735 | TRACE_FUN(ft_t_flow); | ||
736 | |||
737 | if (ft_location.known && !validate(segment_id)) { | ||
738 | ftape_sleep(1 * FT_SECOND); | ||
739 | ft_failure = 1; | ||
740 | TRACE_ABORT(-EIO, ft_t_err, | ||
741 | "fatal: head off track (bad hardware?)"); | ||
742 | } | ||
743 | do { | ||
744 | if (!ft_location.known) { | ||
745 | TRACE(ft_t_warn, "warning: location not known"); | ||
746 | } | ||
747 | TRACE(ft_t_noise, "from %d/%d to %d/0 - %d", | ||
748 | ft_location.segment, ft_location.sector, | ||
749 | segment_id, margin); | ||
750 | /* min_rewind == 1 + overshoot_when_doing_minimum_rewind | ||
751 | * overshoot == overshoot_when_doing_larger_rewind | ||
752 | * Initially min_rewind == 1 + overshoot, optimization | ||
753 | * of both values will be done separately. | ||
754 | * overshoot and min_rewind can be negative as both are | ||
755 | * sums of three components: | ||
756 | * any_overshoot == rewind_overshoot - | ||
757 | * stop_overshoot - | ||
758 | * start_overshoot | ||
759 | */ | ||
760 | if (ft_location.segment - target - (min_rewind - 1) < 1) { | ||
761 | short_seek = 1; | ||
762 | } else { | ||
763 | count = ft_location.segment - target - overshoot; | ||
764 | short_seek = (count < 1); | ||
765 | } | ||
766 | if (short_seek) { | ||
767 | count = 1; /* do shortest rewind */ | ||
768 | expected = ft_location.segment - min_rewind; | ||
769 | if (expected/ft_segments_per_track != ft_location.track) { | ||
770 | expected = (ft_location.track * | ||
771 | ft_segments_per_track); | ||
772 | } | ||
773 | } else { | ||
774 | expected = target; | ||
775 | } | ||
776 | fast_seek(count, 1); | ||
777 | logical_forward(); | ||
778 | if (ftape_read_id() < 0 || !ft_location.known || | ||
779 | (sigtestsetmask(¤t->pending.signal, _DONT_BLOCK))) { | ||
780 | if ((!ftape_tape_running && !ft_location.known) || | ||
781 | ++failures > FT_SECTORS_PER_SEGMENT) { | ||
782 | TRACE_ABORT(-EIO, ft_t_err, | ||
783 | "read_id failed completely"); | ||
784 | } | ||
785 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
786 | TRACE_CATCH(ftape_report_drive_status(pstatus),); | ||
787 | TRACE(ft_t_noise, "ftape_read_id failed, retry (%d)", | ||
788 | failures); | ||
789 | continue; | ||
790 | } | ||
791 | TRACE(ft_t_noise, "ended at %d/%d (%d,%d,%d)", | ||
792 | ft_location.segment, ft_location.sector, | ||
793 | min_rewind, overshoot, inhibit_correction); | ||
794 | if (!inhibit_correction && | ||
795 | (ft_location.segment < expected || | ||
796 | ft_location.segment > expected + margin)) { | ||
797 | int error = expected - ft_location.segment; | ||
798 | if (short_seek) { | ||
799 | TRACE(ft_t_noise, | ||
800 | "adjusting min_rewind from %d to %d", | ||
801 | min_rewind, min_rewind + error); | ||
802 | min_rewind += error; | ||
803 | if (min_rewind < -5) { | ||
804 | /* is this right ? FIXME ! */ | ||
805 | /* keep sane value */ | ||
806 | min_rewind = -5; | ||
807 | TRACE(ft_t_noise, | ||
808 | "clipped min_rewind to %d", | ||
809 | min_rewind); | ||
810 | } | ||
811 | } else { | ||
812 | TRACE(ft_t_noise, | ||
813 | "adjusting overshoot from %d to %d", | ||
814 | overshoot, overshoot + error); | ||
815 | overshoot += error; | ||
816 | if (overshoot < -5 || | ||
817 | overshoot > OVERSHOOT_LIMIT) { | ||
818 | if (overshoot < 0) { | ||
819 | /* keep sane value */ | ||
820 | overshoot = -5; | ||
821 | } else { | ||
822 | /* keep sane value */ | ||
823 | overshoot = OVERSHOOT_LIMIT; | ||
824 | } | ||
825 | TRACE(ft_t_noise, | ||
826 | "clipped overshoot to %d", | ||
827 | overshoot); | ||
828 | } | ||
829 | } | ||
830 | } | ||
831 | } while (ft_location.segment > segment_id); | ||
832 | if (ft_location.known) { | ||
833 | TRACE(ft_t_noise, "current location: %d/%d", | ||
834 | ft_location.segment, ft_location.sector); | ||
835 | } | ||
836 | TRACE_EXIT 0; | ||
837 | } | ||
838 | |||
839 | static int determine_position(void) | ||
840 | { | ||
841 | int retry = 0; | ||
842 | int status; | ||
843 | int result; | ||
844 | TRACE_FUN(ft_t_flow); | ||
845 | |||
846 | if (!ftape_tape_running) { | ||
847 | /* This should only happen if tape is stopped by isr. | ||
848 | */ | ||
849 | TRACE(ft_t_flow, "waiting for tape stop"); | ||
850 | if (ftape_ready_wait(ftape_timeout.pause, &status) < 0) { | ||
851 | TRACE(ft_t_flow, "drive still running (fatal)"); | ||
852 | ftape_tape_running = 1; /* ? */ | ||
853 | } | ||
854 | } else { | ||
855 | ftape_report_drive_status(&status); | ||
856 | } | ||
857 | if (status & QIC_STATUS_READY) { | ||
858 | /* Drive must be ready to check error state ! | ||
859 | */ | ||
860 | TRACE(ft_t_flow, "drive is ready"); | ||
861 | if (status & QIC_STATUS_ERROR) { | ||
862 | unsigned int error; | ||
863 | qic117_cmd_t command; | ||
864 | |||
865 | /* Report and clear error state, try to continue. | ||
866 | */ | ||
867 | TRACE(ft_t_flow, "error status set"); | ||
868 | ftape_report_error(&error, &command, 1); | ||
869 | ftape_ready_wait(ftape_timeout.reset, &status); | ||
870 | ftape_tape_running = 0; /* ? */ | ||
871 | } | ||
872 | if (check_bot_eot(status)) { | ||
873 | if (ft_location.bot) { | ||
874 | if ((status & QIC_STATUS_READY) == 0) { | ||
875 | /* tape moving away from | ||
876 | * bot/eot, let's see if we | ||
877 | * can catch up with the first | ||
878 | * segment on this track. | ||
879 | */ | ||
880 | } else { | ||
881 | TRACE(ft_t_flow, | ||
882 | "start tape from logical bot"); | ||
883 | logical_forward(); /* start moving */ | ||
884 | } | ||
885 | } else { | ||
886 | if ((status & QIC_STATUS_READY) == 0) { | ||
887 | TRACE(ft_t_noise, "waiting for logical end of track"); | ||
888 | result = ftape_ready_wait(ftape_timeout.reset, &status); | ||
889 | /* error handling needed ? */ | ||
890 | } else { | ||
891 | TRACE(ft_t_noise, | ||
892 | "tape at logical end of track"); | ||
893 | } | ||
894 | } | ||
895 | } else { | ||
896 | TRACE(ft_t_flow, "start tape"); | ||
897 | logical_forward(); /* start moving */ | ||
898 | ft_location.known = 0; /* not cleared by logical forward ! */ | ||
899 | } | ||
900 | } | ||
901 | /* tape should be moving now, start reading id's | ||
902 | */ | ||
903 | while (!ft_location.known && | ||
904 | retry++ < FT_SECTORS_PER_SEGMENT && | ||
905 | (result = ftape_read_id()) < 0) { | ||
906 | |||
907 | TRACE(ft_t_flow, "location unknown"); | ||
908 | |||
909 | /* exit on signal | ||
910 | */ | ||
911 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
912 | |||
913 | /* read-id somehow failed, tape may | ||
914 | * have reached end or some other | ||
915 | * error happened. | ||
916 | */ | ||
917 | TRACE(ft_t_flow, "read-id failed"); | ||
918 | TRACE_CATCH(ftape_report_drive_status(&status),); | ||
919 | TRACE(ft_t_err, "ftape_report_drive_status: 0x%02x", status); | ||
920 | if (status & QIC_STATUS_READY) { | ||
921 | ftape_tape_running = 0; | ||
922 | TRACE(ft_t_noise, "tape stopped for unknown reason! " | ||
923 | "status = 0x%02x", status); | ||
924 | if (status & QIC_STATUS_ERROR || | ||
925 | !check_bot_eot(status)) { | ||
926 | /* oops, tape stopped but not at end! | ||
927 | */ | ||
928 | TRACE_EXIT -EIO; | ||
929 | } | ||
930 | } | ||
931 | } | ||
932 | TRACE(ft_t_flow, | ||
933 | "tape is positioned at segment %d", ft_location.segment); | ||
934 | TRACE_EXIT ft_location.known ? 0 : -EIO; | ||
935 | } | ||
936 | |||
937 | /* Get the tape running and position it just before the | ||
938 | * requested segment. | ||
939 | * Seek tape-track and reposition as needed. | ||
940 | */ | ||
941 | int ftape_start_tape(int segment_id, int sector_offset) | ||
942 | { | ||
943 | int track = segment_id / ft_segments_per_track; | ||
944 | int result = -EIO; | ||
945 | int status; | ||
946 | static int last_segment = -1; | ||
947 | static int bad_bus_timing = 0; | ||
948 | /* number of segments passing the head between starting the tape | ||
949 | * and being able to access the first sector. | ||
950 | */ | ||
951 | static int start_offset = 1; | ||
952 | int retry; | ||
953 | TRACE_FUN(ft_t_flow); | ||
954 | |||
955 | /* If sector_offset > 0, seek into wanted segment instead of | ||
956 | * into previous. | ||
957 | * This allows error recovery if a part of the segment is bad | ||
958 | * (erased) causing the tape drive to generate an index pulse | ||
959 | * thus causing a no-data error before the requested sector | ||
960 | * is reached. | ||
961 | */ | ||
962 | ftape_tape_running = 0; | ||
963 | TRACE(ft_t_noise, "target segment: %d/%d%s", segment_id, sector_offset, | ||
964 | ft_buffer[ft_head]->retry > 0 ? " retry" : ""); | ||
965 | if (ft_buffer[ft_head]->retry > 0) { /* this is a retry */ | ||
966 | int dist = segment_id - last_segment; | ||
967 | |||
968 | if ((int)ft_history.overrun_errors < overrun_count_offset) { | ||
969 | overrun_count_offset = ft_history.overrun_errors; | ||
970 | } else if (dist < 0 || dist > 50) { | ||
971 | overrun_count_offset = ft_history.overrun_errors; | ||
972 | } else if ((ft_history.overrun_errors - | ||
973 | overrun_count_offset) >= 8) { | ||
974 | if (ftape_increase_threshold() >= 0) { | ||
975 | --ft_buffer[ft_head]->retry; | ||
976 | overrun_count_offset = | ||
977 | ft_history.overrun_errors; | ||
978 | TRACE(ft_t_warn, "increased threshold because " | ||
979 | "of excessive overrun errors"); | ||
980 | } else if (!bad_bus_timing && ft_data_rate >= 1000) { | ||
981 | ftape_half_data_rate(); | ||
982 | --ft_buffer[ft_head]->retry; | ||
983 | bad_bus_timing = 1; | ||
984 | overrun_count_offset = | ||
985 | ft_history.overrun_errors; | ||
986 | TRACE(ft_t_warn, "reduced datarate because " | ||
987 | "of excessive overrun errors"); | ||
988 | } | ||
989 | } | ||
990 | } | ||
991 | last_segment = segment_id; | ||
992 | if (ft_location.track != track || | ||
993 | (ftape_might_be_off_track && ft_buffer[ft_head]->retry== 0)) { | ||
994 | /* current track unknown or not equal to destination | ||
995 | */ | ||
996 | ftape_ready_wait(ftape_timeout.seek, &status); | ||
997 | ftape_seek_head_to_track(track); | ||
998 | /* overrun_count_offset = ft_history.overrun_errors; */ | ||
999 | } | ||
1000 | result = -EIO; | ||
1001 | retry = 0; | ||
1002 | while (result < 0 && | ||
1003 | retry++ <= 5 && | ||
1004 | !ft_failure && | ||
1005 | !(sigtestsetmask(¤t->pending.signal, _DONT_BLOCK))) { | ||
1006 | |||
1007 | if (retry && start_offset < 5) { | ||
1008 | start_offset ++; | ||
1009 | } | ||
1010 | /* Check if we are able to catch the requested | ||
1011 | * segment in time. | ||
1012 | */ | ||
1013 | if ((ft_location.known || (determine_position() == 0)) && | ||
1014 | ft_location.segment >= | ||
1015 | (segment_id - | ||
1016 | ((ftape_tape_running || ft_location.bot) | ||
1017 | ? 0 : start_offset))) { | ||
1018 | /* Too far ahead (in or past target segment). | ||
1019 | */ | ||
1020 | if (ftape_tape_running) { | ||
1021 | if ((result = ftape_stop_tape(&status)) < 0) { | ||
1022 | TRACE(ft_t_err, | ||
1023 | "stop tape failed with code %d", | ||
1024 | result); | ||
1025 | break; | ||
1026 | } | ||
1027 | TRACE(ft_t_noise, "tape stopped"); | ||
1028 | ftape_tape_running = 0; | ||
1029 | } | ||
1030 | TRACE(ft_t_noise, "repositioning"); | ||
1031 | ++ft_history.rewinds; | ||
1032 | if (segment_id % ft_segments_per_track < start_offset){ | ||
1033 | TRACE(ft_t_noise, "end of track condition\n" | ||
1034 | KERN_INFO "segment_id : %d\n" | ||
1035 | KERN_INFO "ft_segments_per_track: %d\n" | ||
1036 | KERN_INFO "start_offset : %d", | ||
1037 | segment_id, ft_segments_per_track, | ||
1038 | start_offset); | ||
1039 | |||
1040 | /* If seeking to first segments on | ||
1041 | * track better do a complete rewind | ||
1042 | * to logical begin of track to get a | ||
1043 | * more steady tape motion. | ||
1044 | */ | ||
1045 | result = ftape_command_wait( | ||
1046 | (ft_location.track & 1) | ||
1047 | ? QIC_PHYSICAL_FORWARD | ||
1048 | : QIC_PHYSICAL_REVERSE, | ||
1049 | ftape_timeout.rewind, &status); | ||
1050 | check_bot_eot(status); /* update location */ | ||
1051 | } else { | ||
1052 | result= skip_reverse(segment_id - start_offset, | ||
1053 | &status); | ||
1054 | } | ||
1055 | } | ||
1056 | if (!ft_location.known) { | ||
1057 | TRACE(ft_t_bug, "panic: location not known"); | ||
1058 | result = -EIO; | ||
1059 | continue; /* while() will check for failure */ | ||
1060 | } | ||
1061 | TRACE(ft_t_noise, "current segment: %d/%d", | ||
1062 | ft_location.segment, ft_location.sector); | ||
1063 | /* We're on the right track somewhere before the | ||
1064 | * wanted segment. Start tape movement if needed and | ||
1065 | * skip to just before or inside the requested | ||
1066 | * segment. Keep tape running. | ||
1067 | */ | ||
1068 | result = 0; | ||
1069 | if (ft_location.segment < | ||
1070 | (segment_id - ((ftape_tape_running || ft_location.bot) | ||
1071 | ? 0 : start_offset))) { | ||
1072 | if (sector_offset > 0) { | ||
1073 | result = seek_forward(segment_id, | ||
1074 | retry <= 3); | ||
1075 | } else { | ||
1076 | result = seek_forward(segment_id - 1, | ||
1077 | retry <= 3); | ||
1078 | } | ||
1079 | } | ||
1080 | if (result == 0 && | ||
1081 | ft_location.segment != | ||
1082 | (segment_id - (sector_offset > 0 ? 0 : 1))) { | ||
1083 | result = -EIO; | ||
1084 | } | ||
1085 | } | ||
1086 | if (result < 0) { | ||
1087 | TRACE(ft_t_err, "failed to reposition"); | ||
1088 | } else { | ||
1089 | ft_runner_status = running; | ||
1090 | } | ||
1091 | TRACE_EXIT result; | ||
1092 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-rw.h b/drivers/char/ftape/lowlevel/ftape-rw.h deleted file mode 100644 index 32f4feeb887c..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-rw.h +++ /dev/null | |||
@@ -1,111 +0,0 @@ | |||
1 | #ifndef _FTAPE_RW_H | ||
2 | #define _FTAPE_RW_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-rw.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:25 $ | ||
26 | * | ||
27 | * This file contains the definitions for the read and write | ||
28 | * functions for the QIC-117 floppy-tape driver for Linux. | ||
29 | * | ||
30 | * Claus-Justus Heine (1996/09/20): Add definition of format code 6 | ||
31 | * Claus-Justus Heine (1996/10/04): Changed GET/PUT macros to cast to (__u8 *) | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | #include "../lowlevel/fdc-io.h" | ||
36 | #include "../lowlevel/ftape-init.h" | ||
37 | #include "../lowlevel/ftape-bsm.h" | ||
38 | |||
39 | #include <asm/unaligned.h> | ||
40 | |||
41 | #define GET2(address, offset) get_unaligned((__u16*)((__u8 *)address + offset)) | ||
42 | #define GET4(address, offset) get_unaligned((__u32*)((__u8 *)address + offset)) | ||
43 | #define GET8(address, offset) get_unaligned((__u64*)((__u8 *)address + offset)) | ||
44 | #define PUT2(address, offset , value) put_unaligned((value), (__u16*)((__u8 *)address + offset)) | ||
45 | #define PUT4(address, offset , value) put_unaligned((value), (__u32*)((__u8 *)address + offset)) | ||
46 | #define PUT8(address, offset , value) put_unaligned((value), (__u64*)((__u8 *)address + offset)) | ||
47 | |||
48 | enum runner_status_enum { | ||
49 | idle = 0, | ||
50 | running, | ||
51 | do_abort, | ||
52 | aborting, | ||
53 | logical_eot, | ||
54 | end_of_tape, | ||
55 | }; | ||
56 | |||
57 | typedef enum ft_buffer_queue { | ||
58 | ft_queue_head = 0, | ||
59 | ft_queue_tail = 1 | ||
60 | } ft_buffer_queue_t; | ||
61 | |||
62 | |||
63 | typedef struct { | ||
64 | int track; /* tape head position */ | ||
65 | volatile int segment; /* current segment */ | ||
66 | volatile int sector; /* sector offset within current segment */ | ||
67 | volatile unsigned int bot; /* logical begin of track */ | ||
68 | volatile unsigned int eot; /* logical end of track */ | ||
69 | volatile unsigned int known; /* validates bot, segment, sector */ | ||
70 | } location_record; | ||
71 | |||
72 | /* Count nr of 1's in pattern. | ||
73 | */ | ||
74 | static inline int count_ones(unsigned long mask) | ||
75 | { | ||
76 | int bits; | ||
77 | |||
78 | for (bits = 0; mask != 0; mask >>= 1) { | ||
79 | if (mask & 1) { | ||
80 | ++bits; | ||
81 | } | ||
82 | } | ||
83 | return bits; | ||
84 | } | ||
85 | |||
86 | #define FT_MAX_NR_BUFFERS 16 /* arbitrary value */ | ||
87 | /* ftape-rw.c defined global vars. | ||
88 | */ | ||
89 | extern buffer_struct *ft_buffer[FT_MAX_NR_BUFFERS]; | ||
90 | extern int ft_nr_buffers; | ||
91 | extern location_record ft_location; | ||
92 | extern volatile int ftape_tape_running; | ||
93 | |||
94 | /* ftape-rw.c defined global functions. | ||
95 | */ | ||
96 | extern int ftape_setup_new_segment(buffer_struct * buff, | ||
97 | int segment_id, | ||
98 | int offset); | ||
99 | extern int ftape_calc_next_cluster(buffer_struct * buff); | ||
100 | extern buffer_struct *ftape_next_buffer (ft_buffer_queue_t pos); | ||
101 | extern buffer_struct *ftape_get_buffer (ft_buffer_queue_t pos); | ||
102 | extern int ftape_buffer_id (ft_buffer_queue_t pos); | ||
103 | extern void ftape_reset_buffer(void); | ||
104 | extern void ftape_tape_parameters(__u8 drive_configuration); | ||
105 | extern int ftape_wait_segment(buffer_state_enum state); | ||
106 | extern int ftape_dumb_stop(void); | ||
107 | extern int ftape_start_tape(int segment_id, int offset); | ||
108 | extern int ftape_stop_tape(int *pstatus); | ||
109 | extern int ftape_handle_logical_eot(void); | ||
110 | extern buffer_state_enum ftape_set_state(buffer_state_enum new_state); | ||
111 | #endif /* _FTAPE_RW_H */ | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-setup.c b/drivers/char/ftape/lowlevel/ftape-setup.c deleted file mode 100644 index 678340acd0b7..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-setup.c +++ /dev/null | |||
@@ -1,104 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996, 1997 Claus-Justus Heine. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-setup.c,v $ | ||
20 | * $Revision: 1.7 $ | ||
21 | * $Date: 1997/10/10 09:57:06 $ | ||
22 | * | ||
23 | * This file contains the code for processing the kernel command | ||
24 | * line options for the QIC-40/80/3010/3020 floppy-tape driver | ||
25 | * "ftape" for Linux. | ||
26 | */ | ||
27 | |||
28 | #include <linux/string.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/mm.h> | ||
31 | |||
32 | #include <linux/ftape.h> | ||
33 | #include <linux/init.h> | ||
34 | #include "../lowlevel/ftape-tracing.h" | ||
35 | #include "../lowlevel/fdc-io.h" | ||
36 | |||
37 | static struct param_table { | ||
38 | const char *name; | ||
39 | int *var; | ||
40 | int def_param; | ||
41 | int min; | ||
42 | int max; | ||
43 | } config_params[] __initdata = { | ||
44 | #ifndef CONFIG_FT_NO_TRACE_AT_ALL | ||
45 | { "tracing", &ftape_tracing, 3, ft_t_bug, ft_t_any}, | ||
46 | #endif | ||
47 | { "ioport", &ft_fdc_base, CONFIG_FT_FDC_BASE, 0x0, 0xfff}, | ||
48 | { "irq", &ft_fdc_irq, CONFIG_FT_FDC_IRQ, 2, 15}, | ||
49 | { "dma", &ft_fdc_dma, CONFIG_FT_FDC_DMA, 0, 3}, | ||
50 | { "threshold", &ft_fdc_threshold, CONFIG_FT_FDC_THR, 1, 16}, | ||
51 | { "datarate", &ft_fdc_rate_limit, CONFIG_FT_FDC_MAX_RATE, 500, 2000}, | ||
52 | { "fc10", &ft_probe_fc10, CONFIG_FT_PROBE_FC10, 0, 1}, | ||
53 | { "mach2", &ft_mach2, CONFIG_FT_MACH2, 0, 1} | ||
54 | }; | ||
55 | |||
56 | static int __init ftape_setup(char *str) | ||
57 | { | ||
58 | int i; | ||
59 | int param; | ||
60 | int ints[2]; | ||
61 | |||
62 | TRACE_FUN(ft_t_flow); | ||
63 | |||
64 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
65 | if (str) { | ||
66 | for (i=0; i < NR_ITEMS(config_params); i++) { | ||
67 | if (strcmp(str,config_params[i].name) == 0){ | ||
68 | if (ints[0]) { | ||
69 | param = ints[1]; | ||
70 | } else { | ||
71 | param = config_params[i].def_param; | ||
72 | } | ||
73 | if (param < config_params[i].min || | ||
74 | param > config_params[i].max) { | ||
75 | TRACE(ft_t_err, | ||
76 | "parameter %s out of range %d ... %d", | ||
77 | config_params[i].name, | ||
78 | config_params[i].min, | ||
79 | config_params[i].max); | ||
80 | goto out; | ||
81 | } | ||
82 | if(config_params[i].var) { | ||
83 | TRACE(ft_t_info, "%s=%d", str, param); | ||
84 | *config_params[i].var = param; | ||
85 | } | ||
86 | goto out; | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | if (str) { | ||
91 | TRACE(ft_t_err, "unknown ftape option [%s]", str); | ||
92 | |||
93 | TRACE(ft_t_err, "allowed options are:"); | ||
94 | for (i=0; i < NR_ITEMS(config_params); i++) { | ||
95 | TRACE(ft_t_err, " %s",config_params[i].name); | ||
96 | } | ||
97 | } else { | ||
98 | TRACE(ft_t_err, "botched ftape option"); | ||
99 | } | ||
100 | out: | ||
101 | TRACE_EXIT 1; | ||
102 | } | ||
103 | |||
104 | __setup("ftape=", ftape_setup); | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-tracing.c b/drivers/char/ftape/lowlevel/ftape-tracing.c deleted file mode 100644 index 7fdc6567440b..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-tracing.c +++ /dev/null | |||
@@ -1,118 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-tracing.c,v $ | ||
21 | * $Revision: 1.2 $ | ||
22 | * $Date: 1997/10/05 19:18:27 $ | ||
23 | * | ||
24 | * This file contains the reading code | ||
25 | * for the QIC-117 floppy-tape driver for Linux. | ||
26 | */ | ||
27 | |||
28 | #include <linux/ftape.h> | ||
29 | #include "../lowlevel/ftape-tracing.h" | ||
30 | |||
31 | /* Global vars. | ||
32 | */ | ||
33 | /* tracing | ||
34 | * set it to: to log : | ||
35 | * 0 bugs | ||
36 | * 1 + errors | ||
37 | * 2 + warnings | ||
38 | * 3 + information | ||
39 | * 4 + more information | ||
40 | * 5 + program flow | ||
41 | * 6 + fdc/dma info | ||
42 | * 7 + data flow | ||
43 | * 8 + everything else | ||
44 | */ | ||
45 | ft_trace_t ftape_tracing = ft_t_info; /* Default level: information and up */ | ||
46 | int ftape_function_nest_level; | ||
47 | |||
48 | /* Local vars. | ||
49 | */ | ||
50 | static __u8 trace_id; | ||
51 | static char spacing[] = "* "; | ||
52 | |||
53 | void ftape_trace_call(const char *file, const char *name) | ||
54 | { | ||
55 | char *indent; | ||
56 | |||
57 | /* Since printk seems not to work with "%*s" format | ||
58 | * we'll use this work-around. | ||
59 | */ | ||
60 | if (ftape_function_nest_level < 0) { | ||
61 | printk(KERN_INFO "function nest level (%d) < 0\n", | ||
62 | ftape_function_nest_level); | ||
63 | ftape_function_nest_level = 0; | ||
64 | } | ||
65 | if (ftape_function_nest_level < sizeof(spacing)) { | ||
66 | indent = (spacing + | ||
67 | sizeof(spacing) - 1 - | ||
68 | ftape_function_nest_level); | ||
69 | } else { | ||
70 | indent = spacing; | ||
71 | } | ||
72 | printk(KERN_INFO "[%03d]%s+%s (%s)\n", | ||
73 | (int) trace_id++, indent, file, name); | ||
74 | } | ||
75 | |||
76 | void ftape_trace_exit(const char *file, const char *name) | ||
77 | { | ||
78 | char *indent; | ||
79 | |||
80 | /* Since printk seems not to work with "%*s" format | ||
81 | * we'll use this work-around. | ||
82 | */ | ||
83 | if (ftape_function_nest_level < 0) { | ||
84 | printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level); | ||
85 | ftape_function_nest_level = 0; | ||
86 | } | ||
87 | if (ftape_function_nest_level < sizeof(spacing)) { | ||
88 | indent = (spacing + | ||
89 | sizeof(spacing) - 1 - | ||
90 | ftape_function_nest_level); | ||
91 | } else { | ||
92 | indent = spacing; | ||
93 | } | ||
94 | printk(KERN_INFO "[%03d]%s-%s (%s)\n", | ||
95 | (int) trace_id++, indent, file, name); | ||
96 | } | ||
97 | |||
98 | void ftape_trace_log(const char *file, const char *function) | ||
99 | { | ||
100 | char *indent; | ||
101 | |||
102 | /* Since printk seems not to work with "%*s" format | ||
103 | * we'll use this work-around. | ||
104 | */ | ||
105 | if (ftape_function_nest_level < 0) { | ||
106 | printk(KERN_INFO "function nest level (%d) < 0\n", ftape_function_nest_level); | ||
107 | ftape_function_nest_level = 0; | ||
108 | } | ||
109 | if (ftape_function_nest_level < sizeof(spacing)) { | ||
110 | indent = (spacing + | ||
111 | sizeof(spacing) - 1 - | ||
112 | ftape_function_nest_level); | ||
113 | } else { | ||
114 | indent = spacing; | ||
115 | } | ||
116 | printk(KERN_INFO "[%03d]%s%s (%s) - ", | ||
117 | (int) trace_id++, indent, file, function); | ||
118 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-tracing.h b/drivers/char/ftape/lowlevel/ftape-tracing.h deleted file mode 100644 index 2950810c7085..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-tracing.h +++ /dev/null | |||
@@ -1,179 +0,0 @@ | |||
1 | #ifndef _FTAPE_TRACING_H | ||
2 | #define _FTAPE_TRACING_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1994-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-tracing.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:18:28 $ | ||
26 | * | ||
27 | * This file contains definitions that eases the debugging of the | ||
28 | * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. | ||
29 | */ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | |||
33 | /* | ||
34 | * Be very careful with TRACE_EXIT and TRACE_ABORT. | ||
35 | * | ||
36 | * if (something) TRACE_EXIT error; | ||
37 | * | ||
38 | * will NOT work. Use | ||
39 | * | ||
40 | * if (something) { | ||
41 | * TRACE_EXIT error; | ||
42 | * } | ||
43 | * | ||
44 | * instead. Maybe a bit dangerous, but save lots of lines of code. | ||
45 | */ | ||
46 | |||
47 | #define LL_X "%d/%d KB" | ||
48 | #define LL(x) (unsigned int)((__u64)(x)>>10), (unsigned int)((x)&1023) | ||
49 | |||
50 | typedef enum { | ||
51 | ft_t_nil = -1, | ||
52 | ft_t_bug, | ||
53 | ft_t_err, | ||
54 | ft_t_warn, | ||
55 | ft_t_info, | ||
56 | ft_t_noise, | ||
57 | ft_t_flow, | ||
58 | ft_t_fdc_dma, | ||
59 | ft_t_data_flow, | ||
60 | ft_t_any | ||
61 | } ft_trace_t; | ||
62 | |||
63 | #ifdef CONFIG_FT_NO_TRACE_AT_ALL | ||
64 | /* the compiler will optimize away most TRACE() macros | ||
65 | */ | ||
66 | #define FT_TRACE_TOP_LEVEL ft_t_bug | ||
67 | #define TRACE_FUN(level) do {} while(0) | ||
68 | #define TRACE_EXIT return | ||
69 | #define TRACE(l, m, i...) \ | ||
70 | { \ | ||
71 | if ((ft_trace_t)(l) == FT_TRACE_TOP_LEVEL) { \ | ||
72 | printk(KERN_INFO"ftape%s(%s):\n" \ | ||
73 | KERN_INFO m".\n" ,__FILE__, __FUNCTION__ , ##i); \ | ||
74 | } \ | ||
75 | } | ||
76 | #define SET_TRACE_LEVEL(l) if ((l) == (l)) do {} while(0) | ||
77 | #define TRACE_LEVEL FT_TRACE_TOP_LEVEL | ||
78 | |||
79 | #else | ||
80 | |||
81 | #ifdef CONFIG_FT_NO_TRACE | ||
82 | /* the compiler will optimize away many TRACE() macros | ||
83 | * the ftape_simple_trace_call() function simply increments | ||
84 | * the function nest level. | ||
85 | */ | ||
86 | #define FT_TRACE_TOP_LEVEL ft_t_warn | ||
87 | #define TRACE_FUN(level) ftape_function_nest_level++ | ||
88 | #define TRACE_EXIT ftape_function_nest_level--; return | ||
89 | |||
90 | #else | ||
91 | #ifdef CONFIG_FT_FULL_DEBUG | ||
92 | #define FT_TRACE_TOP_LEVEL ft_t_any | ||
93 | #else | ||
94 | #define FT_TRACE_TOP_LEVEL ft_t_flow | ||
95 | #endif | ||
96 | #define TRACE_FUN(level) \ | ||
97 | const ft_trace_t _tracing = level; \ | ||
98 | if (ftape_tracing >= (ft_trace_t)(level) && \ | ||
99 | (ft_trace_t)(level) <= FT_TRACE_TOP_LEVEL) \ | ||
100 | ftape_trace_call(__FILE__, __FUNCTION__); \ | ||
101 | ftape_function_nest_level ++; | ||
102 | |||
103 | #define TRACE_EXIT \ | ||
104 | --ftape_function_nest_level; \ | ||
105 | if (ftape_tracing >= (ft_trace_t)(_tracing) && \ | ||
106 | (ft_trace_t)(_tracing) <= FT_TRACE_TOP_LEVEL) \ | ||
107 | ftape_trace_exit(__FILE__, __FUNCTION__); \ | ||
108 | return | ||
109 | |||
110 | #endif | ||
111 | |||
112 | #define TRACE(l, m, i...) \ | ||
113 | { \ | ||
114 | if (ftape_tracing >= (ft_trace_t)(l) && \ | ||
115 | (ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \ | ||
116 | ftape_trace_log(__FILE__, __FUNCTION__); \ | ||
117 | printk(m".\n" ,##i); \ | ||
118 | } \ | ||
119 | } | ||
120 | |||
121 | #define SET_TRACE_LEVEL(l) \ | ||
122 | { \ | ||
123 | if ((ft_trace_t)(l) <= FT_TRACE_TOP_LEVEL) { \ | ||
124 | ftape_tracing = (ft_trace_t)(l); \ | ||
125 | } else { \ | ||
126 | ftape_tracing = FT_TRACE_TOP_LEVEL; \ | ||
127 | } \ | ||
128 | } | ||
129 | #define TRACE_LEVEL \ | ||
130 | ((ftape_tracing <= FT_TRACE_TOP_LEVEL) ? ftape_tracing : FT_TRACE_TOP_LEVEL) | ||
131 | |||
132 | |||
133 | /* Global variables declared in tracing.c | ||
134 | */ | ||
135 | extern ft_trace_t ftape_tracing; /* sets default level */ | ||
136 | extern int ftape_function_nest_level; | ||
137 | |||
138 | /* Global functions declared in tracing.c | ||
139 | */ | ||
140 | extern void ftape_trace_call(const char *file, const char *name); | ||
141 | extern void ftape_trace_exit(const char *file, const char *name); | ||
142 | extern void ftape_trace_log (const char *file, const char *name); | ||
143 | |||
144 | #endif /* !defined(CONFIG_FT_NO_TRACE_AT_ALL) */ | ||
145 | |||
146 | /* | ||
147 | * Abort with a message. | ||
148 | */ | ||
149 | #define TRACE_ABORT(res, i...) \ | ||
150 | { \ | ||
151 | TRACE(i); \ | ||
152 | TRACE_EXIT res; \ | ||
153 | } | ||
154 | |||
155 | /* The following transforms the common "if(result < 0) ... " into a | ||
156 | * one-liner. | ||
157 | */ | ||
158 | #define _TRACE_CATCH(level, fun, action) \ | ||
159 | { \ | ||
160 | int _res = (fun); \ | ||
161 | if (_res < 0) { \ | ||
162 | do { action /* */ ; } while(0); \ | ||
163 | TRACE_ABORT(_res, level, "%s failed: %d", #fun, _res); \ | ||
164 | } \ | ||
165 | } | ||
166 | |||
167 | #define TRACE_CATCH(fun, fail) _TRACE_CATCH(ft_t_err, fun, fail) | ||
168 | |||
169 | /* Abort the current function when signalled. This doesn't belong here, | ||
170 | * but rather into ftape-rw.h (maybe) | ||
171 | */ | ||
172 | #define FT_SIGNAL_EXIT(sig_mask) \ | ||
173 | if (sigtestsetmask(¤t->pending.signal, sig_mask)) { \ | ||
174 | TRACE_ABORT(-EINTR, \ | ||
175 | ft_t_warn, \ | ||
176 | "interrupted by non-blockable signal"); \ | ||
177 | } | ||
178 | |||
179 | #endif /* _FTAPE_TRACING_H */ | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-write.c b/drivers/char/ftape/lowlevel/ftape-write.c deleted file mode 100644 index 45601ec801ee..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-write.c +++ /dev/null | |||
@@ -1,336 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1993-1995 Bas Laarhoven, | ||
3 | * (C) 1996-1997 Claus-Justus Heine. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; see the file COPYING. If not, write to | ||
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.c,v $ | ||
21 | * $Revision: 1.3.4.1 $ | ||
22 | * $Date: 1997/11/14 18:07:04 $ | ||
23 | * | ||
24 | * This file contains the writing code | ||
25 | * for the QIC-117 floppy-tape driver for Linux. | ||
26 | */ | ||
27 | |||
28 | #include <linux/string.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/mm.h> | ||
31 | |||
32 | #include <linux/ftape.h> | ||
33 | #include <linux/qic117.h> | ||
34 | #include "../lowlevel/ftape-tracing.h" | ||
35 | #include "../lowlevel/ftape-write.h" | ||
36 | #include "../lowlevel/ftape-read.h" | ||
37 | #include "../lowlevel/ftape-io.h" | ||
38 | #include "../lowlevel/ftape-ctl.h" | ||
39 | #include "../lowlevel/ftape-rw.h" | ||
40 | #include "../lowlevel/ftape-ecc.h" | ||
41 | #include "../lowlevel/ftape-bsm.h" | ||
42 | #include "../lowlevel/fdc-isr.h" | ||
43 | |||
44 | /* Global vars. | ||
45 | */ | ||
46 | |||
47 | /* Local vars. | ||
48 | */ | ||
49 | static int last_write_failed; | ||
50 | |||
51 | void ftape_zap_write_buffers(void) | ||
52 | { | ||
53 | int i; | ||
54 | |||
55 | for (i = 0; i < ft_nr_buffers; ++i) { | ||
56 | ft_buffer[i]->status = done; | ||
57 | } | ||
58 | ftape_reset_buffer(); | ||
59 | } | ||
60 | |||
61 | static int copy_and_gen_ecc(void *destination, | ||
62 | const void *source, | ||
63 | const SectorMap bad_sector_map) | ||
64 | { | ||
65 | int result; | ||
66 | struct memory_segment mseg; | ||
67 | int bads = count_ones(bad_sector_map); | ||
68 | TRACE_FUN(ft_t_any); | ||
69 | |||
70 | if (bads > 0) { | ||
71 | TRACE(ft_t_noise, "bad sectors in map: %d", bads); | ||
72 | } | ||
73 | if (bads + 3 >= FT_SECTORS_PER_SEGMENT) { | ||
74 | TRACE(ft_t_noise, "empty segment"); | ||
75 | mseg.blocks = 0; /* skip entire segment */ | ||
76 | result = 0; /* nothing written */ | ||
77 | } else { | ||
78 | mseg.blocks = FT_SECTORS_PER_SEGMENT - bads; | ||
79 | mseg.data = destination; | ||
80 | memcpy(mseg.data, source, (mseg.blocks - 3) * FT_SECTOR_SIZE); | ||
81 | result = ftape_ecc_set_segment_parity(&mseg); | ||
82 | if (result < 0) { | ||
83 | TRACE(ft_t_err, "ecc_set_segment_parity failed"); | ||
84 | } else { | ||
85 | result = (mseg.blocks - 3) * FT_SECTOR_SIZE; | ||
86 | } | ||
87 | } | ||
88 | TRACE_EXIT result; | ||
89 | } | ||
90 | |||
91 | |||
92 | int ftape_start_writing(const ft_write_mode_t mode) | ||
93 | { | ||
94 | buffer_struct *head = ftape_get_buffer(ft_queue_head); | ||
95 | int segment_id = head->segment_id; | ||
96 | int result; | ||
97 | buffer_state_enum wanted_state = (mode == FT_WR_DELETE | ||
98 | ? deleting | ||
99 | : writing); | ||
100 | TRACE_FUN(ft_t_flow); | ||
101 | |||
102 | if ((ft_driver_state != wanted_state) || head->status != waiting) { | ||
103 | TRACE_EXIT 0; | ||
104 | } | ||
105 | ftape_setup_new_segment(head, segment_id, 1); | ||
106 | if (mode == FT_WR_SINGLE) { | ||
107 | /* stop tape instead of pause */ | ||
108 | head->next_segment = 0; | ||
109 | } | ||
110 | ftape_calc_next_cluster(head); /* prepare */ | ||
111 | head->status = ft_driver_state; /* either writing or deleting */ | ||
112 | if (ft_runner_status == idle) { | ||
113 | TRACE(ft_t_noise, | ||
114 | "starting runner for segment %d", segment_id); | ||
115 | TRACE_CATCH(ftape_start_tape(segment_id,head->sector_offset),); | ||
116 | } else { | ||
117 | TRACE(ft_t_noise, "runner not idle, not starting tape"); | ||
118 | } | ||
119 | /* go */ | ||
120 | result = fdc_setup_read_write(head, (mode == FT_WR_DELETE | ||
121 | ? FDC_WRITE_DELETED : FDC_WRITE)); | ||
122 | ftape_set_state(wanted_state); /* should not be necessary */ | ||
123 | TRACE_EXIT result; | ||
124 | } | ||
125 | |||
126 | /* Wait until all data is actually written to tape. | ||
127 | * | ||
128 | * There is a problem: when the tape runs into logical EOT, then this | ||
129 | * failes. We need to restart the runner in this case. | ||
130 | */ | ||
131 | int ftape_loop_until_writes_done(void) | ||
132 | { | ||
133 | buffer_struct *head; | ||
134 | TRACE_FUN(ft_t_flow); | ||
135 | |||
136 | while ((ft_driver_state == writing || ft_driver_state == deleting) && | ||
137 | ftape_get_buffer(ft_queue_head)->status != done) { | ||
138 | /* set the runner status to idle if at lEOT */ | ||
139 | TRACE_CATCH(ftape_handle_logical_eot(), last_write_failed = 1); | ||
140 | /* restart the tape if necessary */ | ||
141 | if (ft_runner_status == idle) { | ||
142 | TRACE(ft_t_noise, "runner is idle, restarting"); | ||
143 | if (ft_driver_state == deleting) { | ||
144 | TRACE_CATCH(ftape_start_writing(FT_WR_DELETE), | ||
145 | last_write_failed = 1); | ||
146 | } else { | ||
147 | TRACE_CATCH(ftape_start_writing(FT_WR_MULTI), | ||
148 | last_write_failed = 1); | ||
149 | } | ||
150 | } | ||
151 | TRACE(ft_t_noise, "tail: %d, head: %d", | ||
152 | ftape_buffer_id(ft_queue_tail), | ||
153 | ftape_buffer_id(ft_queue_head)); | ||
154 | TRACE_CATCH(fdc_interrupt_wait(5 * FT_SECOND), | ||
155 | last_write_failed = 1); | ||
156 | head = ftape_get_buffer(ft_queue_head); | ||
157 | if (head->status == error) { | ||
158 | /* Allow escape from loop when signaled ! | ||
159 | */ | ||
160 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
161 | if (head->hard_error_map != 0) { | ||
162 | /* Implement hard write error recovery here | ||
163 | */ | ||
164 | } | ||
165 | /* retry this one */ | ||
166 | head->status = waiting; | ||
167 | if (ft_runner_status == aborting) { | ||
168 | ftape_dumb_stop(); | ||
169 | } | ||
170 | if (ft_runner_status != idle) { | ||
171 | TRACE_ABORT(-EIO, ft_t_err, | ||
172 | "unexpected state: " | ||
173 | "ft_runner_status != idle"); | ||
174 | } | ||
175 | ftape_start_writing(ft_driver_state == deleting | ||
176 | ? FT_WR_MULTI : FT_WR_DELETE); | ||
177 | } | ||
178 | TRACE(ft_t_noise, "looping until writes done"); | ||
179 | } | ||
180 | ftape_set_state(idle); | ||
181 | TRACE_EXIT 0; | ||
182 | } | ||
183 | |||
184 | /* Write given segment from buffer at address to tape. | ||
185 | */ | ||
186 | static int write_segment(const int segment_id, | ||
187 | const void *address, | ||
188 | const ft_write_mode_t write_mode) | ||
189 | { | ||
190 | int bytes_written = 0; | ||
191 | buffer_struct *tail; | ||
192 | buffer_state_enum wanted_state = (write_mode == FT_WR_DELETE | ||
193 | ? deleting : writing); | ||
194 | TRACE_FUN(ft_t_flow); | ||
195 | |||
196 | TRACE(ft_t_noise, "segment_id = %d", segment_id); | ||
197 | if (ft_driver_state != wanted_state) { | ||
198 | if (ft_driver_state == deleting || | ||
199 | wanted_state == deleting) { | ||
200 | TRACE_CATCH(ftape_loop_until_writes_done(),); | ||
201 | } | ||
202 | TRACE(ft_t_noise, "calling ftape_abort_operation"); | ||
203 | TRACE_CATCH(ftape_abort_operation(),); | ||
204 | ftape_zap_write_buffers(); | ||
205 | ftape_set_state(wanted_state); | ||
206 | } | ||
207 | /* if all buffers full we'll have to wait... | ||
208 | */ | ||
209 | ftape_wait_segment(wanted_state); | ||
210 | tail = ftape_get_buffer(ft_queue_tail); | ||
211 | switch(tail->status) { | ||
212 | case done: | ||
213 | ft_history.defects += count_ones(tail->hard_error_map); | ||
214 | break; | ||
215 | case waiting: | ||
216 | /* this could happen with multiple EMPTY_SEGMENTs, but | ||
217 | * shouldn't happen any more as we re-start the runner even | ||
218 | * with an empty segment. | ||
219 | */ | ||
220 | bytes_written = -EAGAIN; | ||
221 | break; | ||
222 | case error: | ||
223 | /* setup for a retry | ||
224 | */ | ||
225 | tail->status = waiting; | ||
226 | bytes_written = -EAGAIN; /* force retry */ | ||
227 | if (tail->hard_error_map != 0) { | ||
228 | TRACE(ft_t_warn, | ||
229 | "warning: %d hard error(s) in written segment", | ||
230 | count_ones(tail->hard_error_map)); | ||
231 | TRACE(ft_t_noise, "hard_error_map = 0x%08lx", | ||
232 | (long)tail->hard_error_map); | ||
233 | /* Implement hard write error recovery here | ||
234 | */ | ||
235 | } | ||
236 | break; | ||
237 | default: | ||
238 | TRACE_ABORT(-EIO, ft_t_err, | ||
239 | "wait for empty segment failed, tail status: %d", | ||
240 | tail->status); | ||
241 | } | ||
242 | /* should runner stop ? | ||
243 | */ | ||
244 | if (ft_runner_status == aborting) { | ||
245 | buffer_struct *head = ftape_get_buffer(ft_queue_head); | ||
246 | if (head->status == wanted_state) { | ||
247 | head->status = done; /* ???? */ | ||
248 | } | ||
249 | /* don't call abort_operation(), we don't want to zap | ||
250 | * the dma buffers | ||
251 | */ | ||
252 | TRACE_CATCH(ftape_dumb_stop(),); | ||
253 | } else { | ||
254 | /* If just passed last segment on tape: wait for BOT | ||
255 | * or EOT mark. Sets ft_runner_status to idle if at lEOT | ||
256 | * and successful | ||
257 | */ | ||
258 | TRACE_CATCH(ftape_handle_logical_eot(),); | ||
259 | } | ||
260 | if (tail->status == done) { | ||
261 | /* now at least one buffer is empty, fill it with our | ||
262 | * data. skip bad sectors and generate ecc. | ||
263 | * copy_and_gen_ecc return nr of bytes written, range | ||
264 | * 0..29 Kb inclusive! | ||
265 | * | ||
266 | * Empty segments are handled inside coyp_and_gen_ecc() | ||
267 | */ | ||
268 | if (write_mode != FT_WR_DELETE) { | ||
269 | TRACE_CATCH(bytes_written = copy_and_gen_ecc( | ||
270 | tail->address, address, | ||
271 | ftape_get_bad_sector_entry(segment_id)),); | ||
272 | } | ||
273 | tail->segment_id = segment_id; | ||
274 | tail->status = waiting; | ||
275 | tail = ftape_next_buffer(ft_queue_tail); | ||
276 | } | ||
277 | /* Start tape only if all buffers full or flush mode. | ||
278 | * This will give higher probability of streaming. | ||
279 | */ | ||
280 | if (ft_runner_status != running && | ||
281 | ((tail->status == waiting && | ||
282 | ftape_get_buffer(ft_queue_head) == tail) || | ||
283 | write_mode != FT_WR_ASYNC)) { | ||
284 | TRACE_CATCH(ftape_start_writing(write_mode),); | ||
285 | } | ||
286 | TRACE_EXIT bytes_written; | ||
287 | } | ||
288 | |||
289 | /* Write as much as fits from buffer to the given segment on tape | ||
290 | * and handle retries. | ||
291 | * Return the number of bytes written (>= 0), or: | ||
292 | * -EIO write failed | ||
293 | * -EINTR interrupted by signal | ||
294 | * -ENOSPC device full | ||
295 | */ | ||
296 | int ftape_write_segment(const int segment_id, | ||
297 | const void *buffer, | ||
298 | const ft_write_mode_t flush) | ||
299 | { | ||
300 | int retry = 0; | ||
301 | int result; | ||
302 | TRACE_FUN(ft_t_flow); | ||
303 | |||
304 | ft_history.used |= 2; | ||
305 | if (segment_id >= ft_tracks_per_tape*ft_segments_per_track) { | ||
306 | /* tape full */ | ||
307 | TRACE_ABORT(-ENOSPC, ft_t_err, | ||
308 | "invalid segment id: %d (max %d)", | ||
309 | segment_id, | ||
310 | ft_tracks_per_tape * ft_segments_per_track -1); | ||
311 | } | ||
312 | for (;;) { | ||
313 | if ((result = write_segment(segment_id, buffer, flush)) >= 0) { | ||
314 | if (result == 0) { /* empty segment */ | ||
315 | TRACE(ft_t_noise, | ||
316 | "empty segment, nothing written"); | ||
317 | } | ||
318 | TRACE_EXIT result; | ||
319 | } | ||
320 | if (result == -EAGAIN) { | ||
321 | if (++retry > 100) { /* give up */ | ||
322 | TRACE_ABORT(-EIO, ft_t_err, | ||
323 | "write failed, >100 retries in segment"); | ||
324 | } | ||
325 | TRACE(ft_t_warn, "write error, retry %d (%d)", | ||
326 | retry, | ||
327 | ftape_get_buffer(ft_queue_tail)->segment_id); | ||
328 | } else { | ||
329 | TRACE_ABORT(result, ft_t_err, | ||
330 | "write_segment failed, error: %d", result); | ||
331 | } | ||
332 | /* Allow escape from loop when signaled ! | ||
333 | */ | ||
334 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
335 | } | ||
336 | } | ||
diff --git a/drivers/char/ftape/lowlevel/ftape-write.h b/drivers/char/ftape/lowlevel/ftape-write.h deleted file mode 100644 index 0e7f898b7af9..000000000000 --- a/drivers/char/ftape/lowlevel/ftape-write.h +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | #ifndef _FTAPE_WRITE_H | ||
2 | #define _FTAPE_WRITE_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1994-1995 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.h,v $ | ||
24 | $Author: claus $ | ||
25 | * | ||
26 | $Revision: 1.2 $ | ||
27 | $Date: 1997/10/05 19:18:30 $ | ||
28 | $State: Exp $ | ||
29 | * | ||
30 | * This file contains the definitions for the write functions | ||
31 | * for the QIC-117 floppy-tape driver for Linux. | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | |||
36 | /* ftape-write.c defined global functions. | ||
37 | */ | ||
38 | typedef enum { | ||
39 | FT_WR_ASYNC = 0, /* start tape only when all buffers are full */ | ||
40 | FT_WR_MULTI = 1, /* start tape, but don't necessarily stop */ | ||
41 | FT_WR_SINGLE = 2, /* write a single segment and stop afterwards */ | ||
42 | FT_WR_DELETE = 3 /* write deleted data marks */ | ||
43 | } ft_write_mode_t; | ||
44 | |||
45 | extern int ftape_start_writing(const ft_write_mode_t mode); | ||
46 | extern int ftape_write_segment(const int segment, | ||
47 | const void *address, | ||
48 | const ft_write_mode_t flushing); | ||
49 | extern void ftape_zap_write_buffers(void); | ||
50 | extern int ftape_loop_until_writes_done(void); | ||
51 | |||
52 | #endif /* _FTAPE_WRITE_H */ | ||
53 | |||
diff --git a/drivers/char/ftape/lowlevel/ftape_syms.c b/drivers/char/ftape/lowlevel/ftape_syms.c deleted file mode 100644 index 8e0dc4a07ca6..000000000000 --- a/drivers/char/ftape/lowlevel/ftape_syms.c +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape_syms.c,v $ | ||
20 | * $Revision: 1.4 $ | ||
21 | * $Date: 1997/10/17 00:03:51 $ | ||
22 | * | ||
23 | * This file contains the symbols that the ftape low level | ||
24 | * part of the QIC-40/80/3010/3020 floppy-tape driver "ftape" | ||
25 | * exports to its high level clients | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | |||
30 | #include <linux/ftape.h> | ||
31 | #include "../lowlevel/ftape-tracing.h" | ||
32 | #include "../lowlevel/ftape-init.h" | ||
33 | #include "../lowlevel/fdc-io.h" | ||
34 | #include "../lowlevel/ftape-read.h" | ||
35 | #include "../lowlevel/ftape-write.h" | ||
36 | #include "../lowlevel/ftape-io.h" | ||
37 | #include "../lowlevel/ftape-ctl.h" | ||
38 | #include "../lowlevel/ftape-rw.h" | ||
39 | #include "../lowlevel/ftape-bsm.h" | ||
40 | #include "../lowlevel/ftape-buffer.h" | ||
41 | #include "../lowlevel/ftape-format.h" | ||
42 | |||
43 | /* bad sector handling from ftape-bsm.c */ | ||
44 | EXPORT_SYMBOL(ftape_get_bad_sector_entry); | ||
45 | EXPORT_SYMBOL(ftape_find_end_of_bsm_list); | ||
46 | /* from ftape-rw.c */ | ||
47 | EXPORT_SYMBOL(ftape_set_state); | ||
48 | /* from ftape-ctl.c */ | ||
49 | EXPORT_SYMBOL(ftape_seek_to_bot); | ||
50 | EXPORT_SYMBOL(ftape_seek_to_eot); | ||
51 | EXPORT_SYMBOL(ftape_abort_operation); | ||
52 | EXPORT_SYMBOL(ftape_get_status); | ||
53 | EXPORT_SYMBOL(ftape_enable); | ||
54 | EXPORT_SYMBOL(ftape_disable); | ||
55 | EXPORT_SYMBOL(ftape_mmap); | ||
56 | EXPORT_SYMBOL(ftape_calibrate_data_rate); | ||
57 | /* from ftape-io.c */ | ||
58 | EXPORT_SYMBOL(ftape_reset_drive); | ||
59 | EXPORT_SYMBOL(ftape_command); | ||
60 | EXPORT_SYMBOL(ftape_parameter); | ||
61 | EXPORT_SYMBOL(ftape_ready_wait); | ||
62 | EXPORT_SYMBOL(ftape_report_operation); | ||
63 | EXPORT_SYMBOL(ftape_report_error); | ||
64 | /* from ftape-read.c */ | ||
65 | EXPORT_SYMBOL(ftape_read_segment_fraction); | ||
66 | EXPORT_SYMBOL(ftape_zap_read_buffers); | ||
67 | EXPORT_SYMBOL(ftape_read_header_segment); | ||
68 | EXPORT_SYMBOL(ftape_decode_header_segment); | ||
69 | /* from ftape-write.c */ | ||
70 | EXPORT_SYMBOL(ftape_write_segment); | ||
71 | EXPORT_SYMBOL(ftape_start_writing); | ||
72 | EXPORT_SYMBOL(ftape_loop_until_writes_done); | ||
73 | /* from ftape-buffer.h */ | ||
74 | EXPORT_SYMBOL(ftape_set_nr_buffers); | ||
75 | /* from ftape-format.h */ | ||
76 | EXPORT_SYMBOL(ftape_format_track); | ||
77 | EXPORT_SYMBOL(ftape_format_status); | ||
78 | EXPORT_SYMBOL(ftape_verify_segment); | ||
79 | /* from tracing.c */ | ||
80 | #ifndef CONFIG_FT_NO_TRACE_AT_ALL | ||
81 | EXPORT_SYMBOL(ftape_tracing); | ||
82 | EXPORT_SYMBOL(ftape_function_nest_level); | ||
83 | EXPORT_SYMBOL(ftape_trace_call); | ||
84 | EXPORT_SYMBOL(ftape_trace_exit); | ||
85 | EXPORT_SYMBOL(ftape_trace_log); | ||
86 | #endif | ||
87 | |||
diff --git a/drivers/char/ftape/zftape/Makefile b/drivers/char/ftape/zftape/Makefile deleted file mode 100644 index 6d91c1f77c05..000000000000 --- a/drivers/char/ftape/zftape/Makefile +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 1996, 1997 Claus-Justus Heine. | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 2, or (at your option) | ||
7 | # any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program; see the file COPYING. If not, write to | ||
16 | # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | # | ||
18 | # $Source: /homes/cvs/ftape-stacked/ftape/zftape/Makefile,v $ | ||
19 | # $Revision: 1.4 $ | ||
20 | # $Date: 1997/10/05 19:18:58 $ | ||
21 | # | ||
22 | # Makefile for the QIC-40/80/3010/3020 zftape interface VFS to | ||
23 | # ftape | ||
24 | # | ||
25 | |||
26 | |||
27 | # ZFT_OBSOLETE - enable the MTIOC_ZFTAPE_GETBLKSZ ioctl. You should | ||
28 | # leave this enabled for compatibility with taper. | ||
29 | |||
30 | obj-$(CONFIG_ZFTAPE) += zftape.o | ||
31 | |||
32 | zftape-objs := zftape-rw.o zftape-ctl.o zftape-read.o \ | ||
33 | zftape-write.o zftape-vtbl.o zftape-eof.o \ | ||
34 | zftape-init.o zftape-buffers.o zftape_syms.o | ||
35 | |||
36 | EXTRA_CFLAGS := -DZFT_OBSOLETE | ||
diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c deleted file mode 100644 index 7ebce2ec7897..000000000000 --- a/drivers/char/ftape/zftape/zftape-buffers.c +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1995-1997 Claus-Justus Heine. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-buffers.c,v $ | ||
20 | * $Revision: 1.2 $ | ||
21 | * $Date: 1997/10/05 19:18:59 $ | ||
22 | * | ||
23 | * This file contains the dynamic buffer allocation routines | ||
24 | * of zftape | ||
25 | */ | ||
26 | |||
27 | #include <linux/errno.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/delay.h> | ||
31 | |||
32 | #include <linux/zftape.h> | ||
33 | |||
34 | #include <linux/vmalloc.h> | ||
35 | |||
36 | #include "../zftape/zftape-init.h" | ||
37 | #include "../zftape/zftape-eof.h" | ||
38 | #include "../zftape/zftape-ctl.h" | ||
39 | #include "../zftape/zftape-write.h" | ||
40 | #include "../zftape/zftape-read.h" | ||
41 | #include "../zftape/zftape-rw.h" | ||
42 | #include "../zftape/zftape-vtbl.h" | ||
43 | |||
44 | /* global variables | ||
45 | */ | ||
46 | |||
47 | /* local varibales | ||
48 | */ | ||
49 | static unsigned int used_memory; | ||
50 | static unsigned int peak_memory; | ||
51 | |||
52 | void zft_memory_stats(void) | ||
53 | { | ||
54 | TRACE_FUN(ft_t_flow); | ||
55 | |||
56 | TRACE(ft_t_noise, "Memory usage (vmalloc allocations):\n" | ||
57 | KERN_INFO "total allocated: %d\n" | ||
58 | KERN_INFO "peak allocation: %d", | ||
59 | used_memory, peak_memory); | ||
60 | peak_memory = used_memory; | ||
61 | TRACE_EXIT; | ||
62 | } | ||
63 | |||
64 | int zft_vcalloc_once(void *new, size_t size) | ||
65 | { | ||
66 | TRACE_FUN(ft_t_flow); | ||
67 | if (zft_vmalloc_once(new, size) < 0) { | ||
68 | TRACE_EXIT -ENOMEM; | ||
69 | } | ||
70 | memset(*(void **)new, '\0', size); | ||
71 | TRACE_EXIT 0; | ||
72 | } | ||
73 | int zft_vmalloc_once(void *new, size_t size) | ||
74 | { | ||
75 | TRACE_FUN(ft_t_flow); | ||
76 | |||
77 | if (*(void **)new != NULL || size == 0) { | ||
78 | TRACE_EXIT 0; | ||
79 | } | ||
80 | if ((*(void **)new = vmalloc(size)) == NULL) { | ||
81 | TRACE_EXIT -ENOMEM; | ||
82 | } | ||
83 | used_memory += size; | ||
84 | if (peak_memory < used_memory) { | ||
85 | peak_memory = used_memory; | ||
86 | } | ||
87 | TRACE_ABORT(0, ft_t_noise, | ||
88 | "allocated buffer @ %p, %zd bytes", *(void **)new, size); | ||
89 | } | ||
90 | int zft_vmalloc_always(void *new, size_t size) | ||
91 | { | ||
92 | TRACE_FUN(ft_t_flow); | ||
93 | |||
94 | zft_vfree(new, size); | ||
95 | TRACE_EXIT zft_vmalloc_once(new, size); | ||
96 | } | ||
97 | void zft_vfree(void *old, size_t size) | ||
98 | { | ||
99 | TRACE_FUN(ft_t_flow); | ||
100 | |||
101 | if (*(void **)old) { | ||
102 | vfree(*(void **)old); | ||
103 | used_memory -= size; | ||
104 | TRACE(ft_t_noise, "released buffer @ %p, %zd bytes", | ||
105 | *(void **)old, size); | ||
106 | *(void **)old = NULL; | ||
107 | } | ||
108 | TRACE_EXIT; | ||
109 | } | ||
110 | |||
111 | void *zft_kmalloc(size_t size) | ||
112 | { | ||
113 | void *new; | ||
114 | |||
115 | while ((new = kmalloc(size, GFP_KERNEL)) == NULL) { | ||
116 | msleep_interruptible(100); | ||
117 | } | ||
118 | memset(new, 0, size); | ||
119 | used_memory += size; | ||
120 | if (peak_memory < used_memory) { | ||
121 | peak_memory = used_memory; | ||
122 | } | ||
123 | return new; | ||
124 | } | ||
125 | |||
126 | void zft_kfree(void *old, size_t size) | ||
127 | { | ||
128 | kfree(old); | ||
129 | used_memory -= size; | ||
130 | } | ||
131 | |||
132 | /* there are some more buffers that are allocated on demand. | ||
133 | * cleanup_module() calles this function to be sure to have released | ||
134 | * them | ||
135 | */ | ||
136 | void zft_uninit_mem(void) | ||
137 | { | ||
138 | TRACE_FUN(ft_t_flow); | ||
139 | |||
140 | zft_vfree(&zft_hseg_buf, FT_SEGMENT_SIZE); | ||
141 | zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); zft_deblock_segment = -1; | ||
142 | zft_free_vtbl(); | ||
143 | if (zft_cmpr_lock(0 /* don't load */) == 0) { | ||
144 | (*zft_cmpr_ops->cleanup)(); | ||
145 | (*zft_cmpr_ops->reset)(); /* unlock it again */ | ||
146 | } | ||
147 | zft_memory_stats(); | ||
148 | TRACE_EXIT; | ||
149 | } | ||
diff --git a/drivers/char/ftape/zftape/zftape-buffers.h b/drivers/char/ftape/zftape/zftape-buffers.h deleted file mode 100644 index 798e3128c682..000000000000 --- a/drivers/char/ftape/zftape/zftape-buffers.h +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | #ifndef _FTAPE_DYNMEM_H | ||
2 | #define _FTAPE_DYNMEM_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1995-1997 Claus-Justus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-buffers.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:18:59 $ | ||
25 | * | ||
26 | * memory allocation routines. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | /* we do not allocate all of the really large buffer memory before | ||
31 | * someone tries to open the drive. ftape_open() may fail with | ||
32 | * -ENOMEM, but that's better having 200k of vmalloced memory which | ||
33 | * cannot be swapped out. | ||
34 | */ | ||
35 | |||
36 | extern void zft_memory_stats(void); | ||
37 | extern int zft_vmalloc_once(void *new, size_t size); | ||
38 | extern int zft_vcalloc_once(void *new, size_t size); | ||
39 | extern int zft_vmalloc_always(void *new, size_t size); | ||
40 | extern void zft_vfree(void *old, size_t size); | ||
41 | extern void *zft_kmalloc(size_t size); | ||
42 | extern void zft_kfree(void *old, size_t size); | ||
43 | |||
44 | /* called by cleanup_module() | ||
45 | */ | ||
46 | extern void zft_uninit_mem(void); | ||
47 | |||
48 | #endif | ||
49 | |||
50 | |||
51 | |||
52 | |||
53 | |||
54 | |||
55 | |||
diff --git a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c deleted file mode 100644 index 22ba0f5d00cf..000000000000 --- a/drivers/char/ftape/zftape/zftape-ctl.c +++ /dev/null | |||
@@ -1,1417 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996, 1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.c,v $ | ||
20 | * $Revision: 1.2.6.2 $ | ||
21 | * $Date: 1997/11/14 18:07:33 $ | ||
22 | * | ||
23 | * This file contains the non-read/write zftape functions | ||
24 | * for the QIC-40/80/3010/3020 floppy-tape driver for Linux. | ||
25 | */ | ||
26 | |||
27 | #include <linux/errno.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/fcntl.h> | ||
31 | |||
32 | #include <linux/zftape.h> | ||
33 | |||
34 | #include <asm/uaccess.h> | ||
35 | |||
36 | #include "../zftape/zftape-init.h" | ||
37 | #include "../zftape/zftape-eof.h" | ||
38 | #include "../zftape/zftape-ctl.h" | ||
39 | #include "../zftape/zftape-write.h" | ||
40 | #include "../zftape/zftape-read.h" | ||
41 | #include "../zftape/zftape-rw.h" | ||
42 | #include "../zftape/zftape-vtbl.h" | ||
43 | |||
44 | /* Global vars. | ||
45 | */ | ||
46 | int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */ | ||
47 | int zft_header_read; | ||
48 | int zft_offline; | ||
49 | unsigned int zft_unit; | ||
50 | int zft_resid; | ||
51 | int zft_mt_compression; | ||
52 | |||
53 | /* Local vars. | ||
54 | */ | ||
55 | static int going_offline; | ||
56 | |||
57 | typedef int (mt_fun)(int *argptr); | ||
58 | typedef int (*mt_funp)(int *argptr); | ||
59 | typedef struct | ||
60 | { | ||
61 | mt_funp function; | ||
62 | unsigned offline : 1; /* op permitted if offline or no_tape */ | ||
63 | unsigned write_protected : 1; /* op permitted if write-protected */ | ||
64 | unsigned not_formatted : 1; /* op permitted if tape not formatted */ | ||
65 | unsigned raw_mode : 1; /* op permitted if zft_mode == 0 */ | ||
66 | unsigned need_idle_state : 1; /* need to call def_idle_state */ | ||
67 | char *name; | ||
68 | } fun_entry; | ||
69 | |||
70 | static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop, | ||
71 | mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity, | ||
72 | mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf, | ||
73 | mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression; | ||
74 | |||
75 | static fun_entry mt_funs[]= | ||
76 | { | ||
77 | {mt_reset , 1, 1, 1, 1, 0, "MT_RESET" }, /* 0 */ | ||
78 | {mt_fsf , 0, 1, 0, 0, 1, "MT_FSF" }, | ||
79 | {mt_bsf , 0, 1, 0, 0, 1, "MT_BSF" }, | ||
80 | {mt_fsr , 0, 1, 0, 1, 1, "MT_FSR" }, | ||
81 | {mt_bsr , 0, 1, 0, 1, 1, "MT_BSR" }, | ||
82 | {mt_weof , 0, 0, 0, 0, 0, "MT_WEOF" }, /* 5 */ | ||
83 | {mt_rew , 0, 1, 1, 1, 0, "MT_REW" }, | ||
84 | {mt_offl , 0, 1, 1, 1, 0, "MT_OFFL" }, | ||
85 | {mt_nop , 1, 1, 1, 1, 0, "MT_NOP" }, | ||
86 | {mt_reten , 0, 1, 1, 1, 0, "MT_RETEN" }, | ||
87 | {mt_bsfm , 0, 1, 0, 0, 1, "MT_BSFM" }, /* 10 */ | ||
88 | {mt_fsfm , 0, 1, 0, 0, 1, "MT_FSFM" }, | ||
89 | {mt_eom , 0, 1, 0, 0, 1, "MT_EOM" }, | ||
90 | {mt_erase , 0, 0, 0, 1, 0, "MT_ERASE" }, | ||
91 | {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS1" }, | ||
92 | {mt_ras2 , 0, 0, 0, 1, 0, "MT_RAS2" }, | ||
93 | {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS3" }, | ||
94 | {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" }, | ||
95 | {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" }, | ||
96 | {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" }, | ||
97 | {mt_setblk , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */ | ||
98 | {mt_setdensity , 1, 1, 1, 1, 0, "MT_SETDENSITY"}, | ||
99 | {mt_seek , 0, 1, 0, 1, 1, "MT_SEEK" }, | ||
100 | {mt_dummy , 0, 1, 0, 1, 1, "MT_TELL" }, /* wr-only ?! */ | ||
101 | {mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" }, | ||
102 | {mt_dummy , 1, 1, 1, 1, 0, "MT_FSS" }, /* 25 */ | ||
103 | {mt_dummy , 1, 1, 1, 1, 0, "MT_BSS" }, | ||
104 | {mt_dummy , 1, 1, 1, 1, 0, "MT_WSM" }, | ||
105 | {mt_dummy , 1, 1, 1, 1, 0, "MT_LOCK" }, | ||
106 | {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOCK"}, | ||
107 | {mt_dummy , 1, 1, 1, 1, 0, "MT_LOAD" }, /* 30 */ | ||
108 | {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOAD"}, | ||
109 | {mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"}, | ||
110 | {mt_dummy , 1, 1, 1, 1, 0, "MT_SETPART"}, | ||
111 | {mt_dummy , 1, 1, 1, 1, 0, "MT_MKPART"} | ||
112 | }; | ||
113 | |||
114 | #define NR_MT_CMDS NR_ITEMS(mt_funs) | ||
115 | |||
116 | void zft_reset_position(zft_position *pos) | ||
117 | { | ||
118 | TRACE_FUN(ft_t_flow); | ||
119 | |||
120 | pos->seg_byte_pos = | ||
121 | pos->volume_pos = 0; | ||
122 | if (zft_header_read) { | ||
123 | /* need to keep track of the volume table and | ||
124 | * compression map. We therefor simply | ||
125 | * position at the beginning of the first | ||
126 | * volume. This covers old ftape archives as | ||
127 | * well has various flavours of the | ||
128 | * compression map segments. The worst case is | ||
129 | * that the compression map shows up as a | ||
130 | * additional volume in front of all others. | ||
131 | */ | ||
132 | pos->seg_pos = zft_find_volume(0)->start_seg; | ||
133 | pos->tape_pos = zft_calc_tape_pos(pos->seg_pos); | ||
134 | } else { | ||
135 | pos->tape_pos = 0; | ||
136 | pos->seg_pos = -1; | ||
137 | } | ||
138 | zft_just_before_eof = 0; | ||
139 | zft_deblock_segment = -1; | ||
140 | zft_io_state = zft_idle; | ||
141 | zft_zap_read_buffers(); | ||
142 | zft_prevent_flush(); | ||
143 | /* unlock the compresison module if it is loaded. | ||
144 | * The zero arg means not to try to load the module. | ||
145 | */ | ||
146 | if (zft_cmpr_lock(0) == 0) { | ||
147 | (*zft_cmpr_ops->reset)(); /* unlock */ | ||
148 | } | ||
149 | TRACE_EXIT; | ||
150 | } | ||
151 | |||
152 | static void zft_init_driver(void) | ||
153 | { | ||
154 | TRACE_FUN(ft_t_flow); | ||
155 | |||
156 | zft_resid = | ||
157 | zft_header_read = | ||
158 | zft_old_ftape = | ||
159 | zft_offline = | ||
160 | zft_write_protected = | ||
161 | going_offline = | ||
162 | zft_mt_compression = | ||
163 | zft_header_changed = | ||
164 | zft_volume_table_changed = | ||
165 | zft_written_segments = 0; | ||
166 | zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ; | ||
167 | zft_reset_position(&zft_pos); /* does most of the stuff */ | ||
168 | ftape_zap_read_buffers(); | ||
169 | ftape_set_state(idle); | ||
170 | TRACE_EXIT; | ||
171 | } | ||
172 | |||
173 | int zft_def_idle_state(void) | ||
174 | { | ||
175 | int result = 0; | ||
176 | TRACE_FUN(ft_t_flow); | ||
177 | |||
178 | if (!zft_header_read) { | ||
179 | result = zft_read_header_segments(); | ||
180 | } else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) { | ||
181 | /* don't move past eof | ||
182 | */ | ||
183 | (void)zft_close_volume(&zft_pos); | ||
184 | } | ||
185 | if (ftape_abort_operation() < 0) { | ||
186 | TRACE(ft_t_warn, "ftape_abort_operation() failed"); | ||
187 | result = -EIO; | ||
188 | } | ||
189 | /* clear remaining read buffers */ | ||
190 | zft_zap_read_buffers(); | ||
191 | zft_io_state = zft_idle; | ||
192 | TRACE_EXIT result; | ||
193 | } | ||
194 | |||
195 | /***************************************************************************** | ||
196 | * * | ||
197 | * functions for the MTIOCTOP commands * | ||
198 | * * | ||
199 | *****************************************************************************/ | ||
200 | |||
201 | static int mt_dummy(int *dummy) | ||
202 | { | ||
203 | TRACE_FUN(ft_t_flow); | ||
204 | |||
205 | TRACE_EXIT -ENOSYS; | ||
206 | } | ||
207 | |||
208 | static int mt_reset(int *dummy) | ||
209 | { | ||
210 | TRACE_FUN(ft_t_flow); | ||
211 | |||
212 | (void)ftape_seek_to_bot(); | ||
213 | TRACE_CATCH(ftape_reset_drive(), | ||
214 | zft_init_driver(); zft_uninit_mem(); zft_offline = 1); | ||
215 | /* fake a re-open of the device. This will set all flage and | ||
216 | * allocate buffers as appropriate. The new tape condition will | ||
217 | * force the open routine to do anything we need. | ||
218 | */ | ||
219 | TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),); | ||
220 | TRACE_EXIT 0; | ||
221 | } | ||
222 | |||
223 | static int mt_fsf(int *arg) | ||
224 | { | ||
225 | int result; | ||
226 | TRACE_FUN(ft_t_flow); | ||
227 | |||
228 | result = zft_skip_volumes(*arg, &zft_pos); | ||
229 | zft_just_before_eof = 0; | ||
230 | TRACE_EXIT result; | ||
231 | } | ||
232 | |||
233 | static int mt_bsf(int *arg) | ||
234 | { | ||
235 | int result = 0; | ||
236 | TRACE_FUN(ft_t_flow); | ||
237 | |||
238 | if (*arg != 0) { | ||
239 | result = zft_skip_volumes(-*arg + 1, &zft_pos); | ||
240 | } | ||
241 | TRACE_EXIT result; | ||
242 | } | ||
243 | |||
244 | static int seek_block(__s64 data_offset, | ||
245 | __s64 block_increment, | ||
246 | zft_position *pos) | ||
247 | { | ||
248 | int result = 0; | ||
249 | __s64 new_block_pos; | ||
250 | __s64 vol_block_count; | ||
251 | const zft_volinfo *volume; | ||
252 | int exceed; | ||
253 | TRACE_FUN(ft_t_flow); | ||
254 | |||
255 | volume = zft_find_volume(pos->seg_pos); | ||
256 | if (volume->start_seg == 0 || volume->end_seg == 0) { | ||
257 | TRACE_EXIT -EIO; | ||
258 | } | ||
259 | new_block_pos = (zft_div_blksz(data_offset, volume->blk_sz) | ||
260 | + block_increment); | ||
261 | vol_block_count = zft_div_blksz(volume->size, volume->blk_sz); | ||
262 | if (new_block_pos < 0) { | ||
263 | TRACE(ft_t_noise, | ||
264 | "new_block_pos " LL_X " < 0", LL(new_block_pos)); | ||
265 | zft_resid = (int)new_block_pos; | ||
266 | new_block_pos = 0; | ||
267 | exceed = 1; | ||
268 | } else if (new_block_pos > vol_block_count) { | ||
269 | TRACE(ft_t_noise, | ||
270 | "new_block_pos " LL_X " exceeds size of volume " LL_X, | ||
271 | LL(new_block_pos), LL(vol_block_count)); | ||
272 | zft_resid = (int)(vol_block_count - new_block_pos); | ||
273 | new_block_pos = vol_block_count; | ||
274 | exceed = 1; | ||
275 | } else { | ||
276 | exceed = 0; | ||
277 | } | ||
278 | if (zft_use_compression && volume->use_compression) { | ||
279 | TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),); | ||
280 | result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume, | ||
281 | zft_deblock_buf); | ||
282 | pos->tape_pos = zft_calc_tape_pos(pos->seg_pos); | ||
283 | pos->tape_pos += pos->seg_byte_pos; | ||
284 | } else { | ||
285 | pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz); | ||
286 | pos->tape_pos = zft_calc_tape_pos(volume->start_seg); | ||
287 | pos->tape_pos += pos->volume_pos; | ||
288 | pos->seg_pos = zft_calc_seg_byte_coord(&pos->seg_byte_pos, | ||
289 | pos->tape_pos); | ||
290 | } | ||
291 | zft_just_before_eof = volume->size == pos->volume_pos; | ||
292 | if (zft_just_before_eof) { | ||
293 | /* why this? because zft_file_no checks agains start | ||
294 | * and end segment of a volume. We do not want to | ||
295 | * advance to the next volume with this function. | ||
296 | */ | ||
297 | TRACE(ft_t_noise, "set zft_just_before_eof"); | ||
298 | zft_position_before_eof(pos, volume); | ||
299 | } | ||
300 | TRACE(ft_t_noise, "\n" | ||
301 | KERN_INFO "new_seg_pos : %d\n" | ||
302 | KERN_INFO "new_tape_pos: " LL_X "\n" | ||
303 | KERN_INFO "vol_size : " LL_X "\n" | ||
304 | KERN_INFO "seg_byte_pos: %d\n" | ||
305 | KERN_INFO "blk_sz : %d", | ||
306 | pos->seg_pos, LL(pos->tape_pos), | ||
307 | LL(volume->size), pos->seg_byte_pos, | ||
308 | volume->blk_sz); | ||
309 | if (!exceed) { | ||
310 | zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos, | ||
311 | volume->blk_sz); | ||
312 | } | ||
313 | if (zft_resid < 0) { | ||
314 | zft_resid = -zft_resid; | ||
315 | } | ||
316 | TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result; | ||
317 | } | ||
318 | |||
319 | static int mt_fsr(int *arg) | ||
320 | { | ||
321 | int result; | ||
322 | TRACE_FUN(ft_t_flow); | ||
323 | |||
324 | result = seek_block(zft_pos.volume_pos, *arg, &zft_pos); | ||
325 | TRACE_EXIT result; | ||
326 | } | ||
327 | |||
328 | static int mt_bsr(int *arg) | ||
329 | { | ||
330 | int result; | ||
331 | TRACE_FUN(ft_t_flow); | ||
332 | |||
333 | result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos); | ||
334 | TRACE_EXIT result; | ||
335 | } | ||
336 | |||
337 | static int mt_weof(int *arg) | ||
338 | { | ||
339 | int result; | ||
340 | TRACE_FUN(ft_t_flow); | ||
341 | |||
342 | TRACE_CATCH(zft_flush_buffers(),); | ||
343 | result = zft_weof(*arg, &zft_pos); | ||
344 | TRACE_EXIT result; | ||
345 | } | ||
346 | |||
347 | static int mt_rew(int *dummy) | ||
348 | { | ||
349 | int result; | ||
350 | TRACE_FUN(ft_t_flow); | ||
351 | |||
352 | if(zft_header_read) { | ||
353 | (void)zft_def_idle_state(); | ||
354 | } | ||
355 | result = ftape_seek_to_bot(); | ||
356 | zft_reset_position(&zft_pos); | ||
357 | TRACE_EXIT result; | ||
358 | } | ||
359 | |||
360 | static int mt_offl(int *dummy) | ||
361 | { | ||
362 | int result; | ||
363 | TRACE_FUN(ft_t_flow); | ||
364 | |||
365 | going_offline= 1; | ||
366 | result = mt_rew(NULL); | ||
367 | TRACE_EXIT result; | ||
368 | } | ||
369 | |||
370 | static int mt_nop(int *dummy) | ||
371 | { | ||
372 | TRACE_FUN(ft_t_flow); | ||
373 | /* should we set tape status? | ||
374 | */ | ||
375 | if (!zft_offline) { /* offline includes no_tape */ | ||
376 | (void)zft_def_idle_state(); | ||
377 | } | ||
378 | TRACE_EXIT 0; | ||
379 | } | ||
380 | |||
381 | static int mt_reten(int *dummy) | ||
382 | { | ||
383 | int result; | ||
384 | TRACE_FUN(ft_t_flow); | ||
385 | |||
386 | if(zft_header_read) { | ||
387 | (void)zft_def_idle_state(); | ||
388 | } | ||
389 | result = ftape_seek_to_eot(); | ||
390 | if (result >= 0) { | ||
391 | result = ftape_seek_to_bot(); | ||
392 | } | ||
393 | TRACE_EXIT(result); | ||
394 | } | ||
395 | |||
396 | static int fsfbsfm(int arg, zft_position *pos) | ||
397 | { | ||
398 | const zft_volinfo *vtbl; | ||
399 | __s64 block_pos; | ||
400 | TRACE_FUN(ft_t_flow); | ||
401 | |||
402 | /* What to do? This should seek to the next file-mark and | ||
403 | * position BEFORE. That is, a next write would just extend | ||
404 | * the current file. Well. Let's just seek to the end of the | ||
405 | * current file, if count == 1. If count > 1, then do a | ||
406 | * "mt_fsf(count - 1)", and then seek to the end of that file. | ||
407 | * If count == 0, do nothing | ||
408 | */ | ||
409 | if (arg == 0) { | ||
410 | TRACE_EXIT 0; | ||
411 | } | ||
412 | zft_just_before_eof = 0; | ||
413 | TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos), | ||
414 | if (arg > 0) { | ||
415 | zft_resid ++; | ||
416 | }); | ||
417 | vtbl = zft_find_volume(pos->seg_pos); | ||
418 | block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz); | ||
419 | (void)seek_block(0, block_pos, pos); | ||
420 | if (pos->volume_pos != vtbl->size) { | ||
421 | zft_just_before_eof = 0; | ||
422 | zft_resid = 1; | ||
423 | /* we didn't managed to go there */ | ||
424 | TRACE_ABORT(-EIO, ft_t_err, | ||
425 | "wanted file position " LL_X ", arrived at " LL_X, | ||
426 | LL(vtbl->size), LL(pos->volume_pos)); | ||
427 | } | ||
428 | zft_just_before_eof = 1; | ||
429 | TRACE_EXIT 0; | ||
430 | } | ||
431 | |||
432 | static int mt_bsfm(int *arg) | ||
433 | { | ||
434 | int result; | ||
435 | TRACE_FUN(ft_t_flow); | ||
436 | |||
437 | result = fsfbsfm(-*arg, &zft_pos); | ||
438 | TRACE_EXIT result; | ||
439 | } | ||
440 | |||
441 | static int mt_fsfm(int *arg) | ||
442 | { | ||
443 | int result; | ||
444 | TRACE_FUN(ft_t_flow); | ||
445 | |||
446 | result = fsfbsfm(*arg, &zft_pos); | ||
447 | TRACE_EXIT result; | ||
448 | } | ||
449 | |||
450 | static int mt_eom(int *dummy) | ||
451 | { | ||
452 | TRACE_FUN(ft_t_flow); | ||
453 | |||
454 | zft_skip_to_eom(&zft_pos); | ||
455 | TRACE_EXIT 0; | ||
456 | } | ||
457 | |||
458 | static int mt_erase(int *dummy) | ||
459 | { | ||
460 | int result; | ||
461 | TRACE_FUN(ft_t_flow); | ||
462 | |||
463 | result = zft_erase(); | ||
464 | TRACE_EXIT result; | ||
465 | } | ||
466 | |||
467 | static int mt_ras2(int *dummy) | ||
468 | { | ||
469 | int result; | ||
470 | TRACE_FUN(ft_t_flow); | ||
471 | |||
472 | result = -ENOSYS; | ||
473 | TRACE_EXIT result; | ||
474 | } | ||
475 | |||
476 | /* Sets the new blocksize in BYTES | ||
477 | * | ||
478 | */ | ||
479 | static int mt_setblk(int *new_size) | ||
480 | { | ||
481 | TRACE_FUN(ft_t_flow); | ||
482 | |||
483 | if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) { | ||
484 | TRACE_ABORT(-EINVAL, ft_t_info, | ||
485 | "desired blk_sz (%d) should be <= %d bytes", | ||
486 | *new_size, ZFT_MAX_BLK_SZ); | ||
487 | } | ||
488 | if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) { | ||
489 | TRACE_ABORT(-EINVAL, ft_t_info, | ||
490 | "desired blk_sz (%d) must be a multiple of %d bytes", | ||
491 | *new_size, FT_SECTOR_SIZE); | ||
492 | } | ||
493 | if (*new_size == 0) { | ||
494 | if (zft_use_compression) { | ||
495 | TRACE_ABORT(-EINVAL, ft_t_info, | ||
496 | "Variable block size not yet " | ||
497 | "supported with compression"); | ||
498 | } | ||
499 | *new_size = 1; | ||
500 | } | ||
501 | zft_blk_sz = *new_size; | ||
502 | TRACE_EXIT 0; | ||
503 | } | ||
504 | |||
505 | static int mt_setdensity(int *arg) | ||
506 | { | ||
507 | TRACE_FUN(ft_t_flow); | ||
508 | |||
509 | SET_TRACE_LEVEL(*arg); | ||
510 | TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL); | ||
511 | if ((int)TRACE_LEVEL != *arg) { | ||
512 | TRACE_EXIT -EINVAL; | ||
513 | } | ||
514 | TRACE_EXIT 0; | ||
515 | } | ||
516 | |||
517 | static int mt_seek(int *new_block_pos) | ||
518 | { | ||
519 | int result= 0; | ||
520 | TRACE_FUN(ft_t_any); | ||
521 | |||
522 | result = seek_block(0, (__s64)*new_block_pos, &zft_pos); | ||
523 | TRACE_EXIT result; | ||
524 | } | ||
525 | |||
526 | /* OK, this is totally different from SCSI, but the worst thing that can | ||
527 | * happen is that there is not enough defragmentated memory that can be | ||
528 | * allocated. Also, there is a hardwired limit of 16 dma buffers in the | ||
529 | * stock ftape module. This shouldn't bring the system down. | ||
530 | * | ||
531 | * NOTE: the argument specifies the total number of dma buffers to use. | ||
532 | * The driver needs at least 3 buffers to function at all. | ||
533 | * | ||
534 | */ | ||
535 | static int mt_setdrvbuffer(int *cnt) | ||
536 | { | ||
537 | TRACE_FUN(ft_t_flow); | ||
538 | |||
539 | if (*cnt < 3) { | ||
540 | TRACE_EXIT -EINVAL; | ||
541 | } | ||
542 | TRACE_CATCH(ftape_set_nr_buffers(*cnt),); | ||
543 | TRACE_EXIT 0; | ||
544 | } | ||
545 | /* return the block position from start of volume | ||
546 | */ | ||
547 | static int mt_tell(int *arg) | ||
548 | { | ||
549 | TRACE_FUN(ft_t_flow); | ||
550 | |||
551 | *arg = zft_div_blksz(zft_pos.volume_pos, | ||
552 | zft_find_volume(zft_pos.seg_pos)->blk_sz); | ||
553 | TRACE_EXIT 0; | ||
554 | } | ||
555 | |||
556 | static int mt_compression(int *arg) | ||
557 | { | ||
558 | TRACE_FUN(ft_t_flow); | ||
559 | |||
560 | /* Ok. We could also check whether compression is available at | ||
561 | * all by trying to load the compression module. We could | ||
562 | * also check for a block size of 1 byte which is illegal | ||
563 | * with compression. Instead of doing it here we rely on | ||
564 | * zftape_write() to do the proper checks. | ||
565 | */ | ||
566 | if ((unsigned int)*arg > 1) { | ||
567 | TRACE_EXIT -EINVAL; | ||
568 | } | ||
569 | if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */ | ||
570 | TRACE_ABORT(-EINVAL, ft_t_info, | ||
571 | "Compression not yet supported " | ||
572 | "with variable block size"); | ||
573 | } | ||
574 | zft_mt_compression = *arg; | ||
575 | if ((zft_unit & ZFT_ZIP_MODE) == 0) { | ||
576 | zft_use_compression = zft_mt_compression; | ||
577 | } | ||
578 | TRACE_EXIT 0; | ||
579 | } | ||
580 | |||
581 | /* check whether write access is allowed. Write access is denied when | ||
582 | * + zft_write_protected == 1 -- this accounts for either hard write | ||
583 | * protection of the cartridge or for | ||
584 | * O_RDONLY access mode of the tape device | ||
585 | * + zft_offline == 1 -- this meany that there is either no tape | ||
586 | * or that the MTOFFLINE ioctl has been | ||
587 | * previously issued (`soft eject') | ||
588 | * + ft_formatted == 0 -- this means that the cartridge is not | ||
589 | * formatted | ||
590 | * Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try | ||
591 | * to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we | ||
592 | * deny writes when | ||
593 | * + zft_qic_mode ==1 && | ||
594 | * (!zft_tape_at_lbot() && -- tape no at logical BOT | ||
595 | * !(zft_tape_at_eom() || -- tape not at logical EOM (or EOD) | ||
596 | * (zft_tape_at_eom() && | ||
597 | * zft_old_ftape()))) -- we can't add new volume to tapes | ||
598 | * written by old ftape because ftape | ||
599 | * don't use the volume table | ||
600 | * | ||
601 | * when the drive is in true raw mode (aka /dev/rawft0) then we don't | ||
602 | * care about LBOT and EOM conditions. This device is intended for a | ||
603 | * user level program that wants to truly implement the QIC-80 compliance | ||
604 | * at the logical data layout level of the cartridge, i.e. implement all | ||
605 | * that volume table and volume directory stuff etc.< | ||
606 | */ | ||
607 | int zft_check_write_access(zft_position *pos) | ||
608 | { | ||
609 | TRACE_FUN(ft_t_flow); | ||
610 | |||
611 | if (zft_offline) { /* offline includes no_tape */ | ||
612 | TRACE_ABORT(-ENXIO, | ||
613 | ft_t_info, "tape is offline or no cartridge"); | ||
614 | } | ||
615 | if (!ft_formatted) { | ||
616 | TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted"); | ||
617 | } | ||
618 | if (zft_write_protected) { | ||
619 | TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected"); | ||
620 | } | ||
621 | if (zft_qic_mode) { | ||
622 | /* check BOT condition */ | ||
623 | if (!zft_tape_at_lbot(pos)) { | ||
624 | /* protect cartridges written by old ftape if | ||
625 | * not at BOT because they use the vtbl | ||
626 | * segment for storing data | ||
627 | */ | ||
628 | if (zft_old_ftape) { | ||
629 | TRACE_ABORT(-EACCES, ft_t_warn, | ||
630 | "Cannot write to cartridges written by old ftape when not at BOT"); | ||
631 | } | ||
632 | /* not at BOT, but allow writes at EOD, of course | ||
633 | */ | ||
634 | if (!zft_tape_at_eod(pos)) { | ||
635 | TRACE_ABORT(-EACCES, ft_t_info, | ||
636 | "tape not at BOT and not at EOD"); | ||
637 | } | ||
638 | } | ||
639 | /* fine. Now the tape is either at BOT or at EOD. */ | ||
640 | } | ||
641 | /* or in raw mode in which case we don't care about BOT and EOD */ | ||
642 | TRACE_EXIT 0; | ||
643 | } | ||
644 | |||
645 | /* OPEN routine called by kernel-interface code | ||
646 | * | ||
647 | * NOTE: this is also called by mt_reset() with dev_minor == -1 | ||
648 | * to fake a reopen after a reset. | ||
649 | */ | ||
650 | int _zft_open(unsigned int dev_minor, unsigned int access_mode) | ||
651 | { | ||
652 | static unsigned int tape_unit; | ||
653 | static unsigned int file_access_mode; | ||
654 | int result; | ||
655 | TRACE_FUN(ft_t_flow); | ||
656 | |||
657 | if ((int)dev_minor == -1) { | ||
658 | /* fake reopen */ | ||
659 | zft_unit = tape_unit; | ||
660 | access_mode = file_access_mode; | ||
661 | zft_init_driver(); /* reset all static data to defaults */ | ||
662 | } else { | ||
663 | tape_unit = dev_minor; | ||
664 | file_access_mode = access_mode; | ||
665 | if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) { | ||
666 | TRACE_ABORT(-ENXIO, ft_t_err, | ||
667 | "ftape_enable failed: %d", result); | ||
668 | } | ||
669 | if (ft_new_tape || ft_no_tape || !ft_formatted || | ||
670 | (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) || | ||
671 | (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) { | ||
672 | /* reset all static data to defaults, | ||
673 | */ | ||
674 | zft_init_driver(); | ||
675 | } | ||
676 | zft_unit = dev_minor; | ||
677 | } | ||
678 | zft_set_flags(zft_unit); /* decode the minor bits */ | ||
679 | if (zft_blk_sz == 1 && zft_use_compression) { | ||
680 | ftape_disable(); /* resets ft_no_tape */ | ||
681 | TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet " | ||
682 | "supported with compression"); | ||
683 | } | ||
684 | /* no need for most of the buffers when no tape or not | ||
685 | * formatted. for the read/write operations, it is the | ||
686 | * regardless whether there is no tape, a not-formatted tape | ||
687 | * or the whether the driver is soft offline. | ||
688 | * Nevertheless we allow some ioctls with non-formatted tapes, | ||
689 | * like rewind and reset. | ||
690 | */ | ||
691 | if (ft_no_tape || !ft_formatted) { | ||
692 | zft_uninit_mem(); | ||
693 | } | ||
694 | if (ft_no_tape) { | ||
695 | zft_offline = 1; /* so we need not test two variables */ | ||
696 | } | ||
697 | if ((access_mode == O_WRONLY || access_mode == O_RDWR) && | ||
698 | (ft_write_protected || ft_no_tape)) { | ||
699 | ftape_disable(); /* resets ft_no_tape */ | ||
700 | TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS, | ||
701 | ft_t_warn, "wrong access mode %s cartridge", | ||
702 | ft_no_tape ? "without a" : "with write protected"); | ||
703 | } | ||
704 | zft_write_protected = (access_mode == O_RDONLY || | ||
705 | ft_write_protected != 0); | ||
706 | if (zft_write_protected) { | ||
707 | TRACE(ft_t_noise, | ||
708 | "read only access mode: %d, " | ||
709 | "drive write protected: %d", | ||
710 | access_mode == O_RDONLY, | ||
711 | ft_write_protected != 0); | ||
712 | } | ||
713 | if (!zft_offline) { | ||
714 | TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE), | ||
715 | ftape_disable()); | ||
716 | } | ||
717 | /* zft_seg_pos should be greater than the vtbl segpos but not | ||
718 | * if in compatibility mode and only after we read in the | ||
719 | * header segments | ||
720 | * | ||
721 | * might also be a problem if the user makes a backup with a | ||
722 | * *qft* device and rewinds it with a raw device. | ||
723 | */ | ||
724 | if (zft_qic_mode && | ||
725 | !zft_old_ftape && | ||
726 | zft_pos.seg_pos >= 0 && | ||
727 | zft_header_read && | ||
728 | zft_pos.seg_pos <= ft_first_data_segment) { | ||
729 | TRACE(ft_t_noise, "you probably mixed up the zftape devices!"); | ||
730 | zft_reset_position(&zft_pos); | ||
731 | } | ||
732 | TRACE_EXIT 0; | ||
733 | } | ||
734 | |||
735 | /* RELEASE routine called by kernel-interface code | ||
736 | */ | ||
737 | int _zft_close(void) | ||
738 | { | ||
739 | int result = 0; | ||
740 | TRACE_FUN(ft_t_flow); | ||
741 | |||
742 | if (zft_offline) { | ||
743 | /* call the hardware release routine. Puts the drive offline */ | ||
744 | ftape_disable(); | ||
745 | TRACE_EXIT 0; | ||
746 | } | ||
747 | if (!(ft_write_protected || zft_old_ftape)) { | ||
748 | result = zft_flush_buffers(); | ||
749 | TRACE(ft_t_noise, "writing file mark at current position"); | ||
750 | if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) { | ||
751 | zft_move_past_eof(&zft_pos); | ||
752 | } | ||
753 | if ((zft_tape_at_lbot(&zft_pos) || | ||
754 | !(zft_unit & FTAPE_NO_REWIND))) { | ||
755 | if (result >= 0) { | ||
756 | result = zft_update_header_segments(); | ||
757 | } else { | ||
758 | TRACE(ft_t_err, | ||
759 | "Error: unable to update header segments"); | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | ftape_abort_operation(); | ||
764 | if (!(zft_unit & FTAPE_NO_REWIND)) { | ||
765 | TRACE(ft_t_noise, "rewinding tape"); | ||
766 | if (ftape_seek_to_bot() < 0 && result >= 0) { | ||
767 | result = -EIO; /* keep old value */ | ||
768 | } | ||
769 | zft_reset_position(&zft_pos); | ||
770 | } | ||
771 | zft_zap_read_buffers(); | ||
772 | /* now free up memory as much as possible. We don't destroy | ||
773 | * the deblock buffer if it containes a valid segment. | ||
774 | */ | ||
775 | if (zft_deblock_segment == -1) { | ||
776 | zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); | ||
777 | } | ||
778 | /* high level driver status, forces creation of a new volume | ||
779 | * when calling ftape_write again and not zft_just_before_eof | ||
780 | */ | ||
781 | zft_io_state = zft_idle; | ||
782 | if (going_offline) { | ||
783 | zft_init_driver(); | ||
784 | zft_uninit_mem(); | ||
785 | going_offline = 0; | ||
786 | zft_offline = 1; | ||
787 | } else if (zft_cmpr_lock(0 /* don't load */) == 0) { | ||
788 | (*zft_cmpr_ops->reset)(); /* unlock it again */ | ||
789 | } | ||
790 | zft_memory_stats(); | ||
791 | /* call the hardware release routine. Puts the drive offline */ | ||
792 | ftape_disable(); | ||
793 | TRACE_EXIT result; | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * the wrapper function around the wrapper MTIOCTOP ioctl | ||
798 | */ | ||
799 | static int mtioctop(struct mtop *mtop, int arg_size) | ||
800 | { | ||
801 | int result = 0; | ||
802 | fun_entry *mt_fun_entry; | ||
803 | TRACE_FUN(ft_t_flow); | ||
804 | |||
805 | if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) { | ||
806 | TRACE_EXIT -EINVAL; | ||
807 | } | ||
808 | TRACE(ft_t_noise, "calling MTIOCTOP command: %s", | ||
809 | mt_funs[mtop->mt_op].name); | ||
810 | mt_fun_entry= &mt_funs[mtop->mt_op]; | ||
811 | zft_resid = mtop->mt_count; | ||
812 | if (!mt_fun_entry->offline && zft_offline) { | ||
813 | if (ft_no_tape) { | ||
814 | TRACE_ABORT(-ENXIO, ft_t_info, "no tape present"); | ||
815 | } else { | ||
816 | TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline"); | ||
817 | } | ||
818 | } | ||
819 | if (!mt_fun_entry->not_formatted && !ft_formatted) { | ||
820 | TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted"); | ||
821 | } | ||
822 | if (!mt_fun_entry->write_protected) { | ||
823 | TRACE_CATCH(zft_check_write_access(&zft_pos),); | ||
824 | } | ||
825 | if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) { | ||
826 | TRACE_CATCH(zft_def_idle_state(),); | ||
827 | } | ||
828 | if (!zft_qic_mode && !mt_fun_entry->raw_mode) { | ||
829 | TRACE_ABORT(-EACCES, ft_t_info, | ||
830 | "Drive needs to be in QIC-80 compatibility mode for this command"); | ||
831 | } | ||
832 | result = (mt_fun_entry->function)(&mtop->mt_count); | ||
833 | if (zft_tape_at_lbot(&zft_pos)) { | ||
834 | TRACE_CATCH(zft_update_header_segments(),); | ||
835 | } | ||
836 | if (result >= 0) { | ||
837 | zft_resid = 0; | ||
838 | } | ||
839 | TRACE_EXIT result; | ||
840 | } | ||
841 | |||
842 | /* | ||
843 | * standard MTIOCGET ioctl | ||
844 | */ | ||
845 | static int mtiocget(struct mtget *mtget, int arg_size) | ||
846 | { | ||
847 | const zft_volinfo *volume; | ||
848 | __s64 max_tape_pos; | ||
849 | TRACE_FUN(ft_t_flow); | ||
850 | |||
851 | if (arg_size != sizeof(struct mtget)) { | ||
852 | TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d", | ||
853 | arg_size); | ||
854 | } | ||
855 | mtget->mt_type = ft_drive_type.vendor_id + 0x800000; | ||
856 | mtget->mt_dsreg = ft_last_status.space; | ||
857 | mtget->mt_erreg = ft_last_error.space; /* error register */ | ||
858 | mtget->mt_resid = zft_resid; /* residuum of writes, reads and | ||
859 | * MTIOCTOP commands | ||
860 | */ | ||
861 | if (!zft_offline) { /* neither no_tape nor soft offline */ | ||
862 | mtget->mt_gstat = GMT_ONLINE(~0UL); | ||
863 | /* should rather return the status of the cartridge | ||
864 | * than the access mode of the file, therefor use | ||
865 | * ft_write_protected, not zft_write_protected | ||
866 | */ | ||
867 | if (ft_write_protected) { | ||
868 | mtget->mt_gstat |= GMT_WR_PROT(~0UL); | ||
869 | } | ||
870 | if(zft_header_read) { /* this catches non-formatted */ | ||
871 | volume = zft_find_volume(zft_pos.seg_pos); | ||
872 | mtget->mt_fileno = volume->count; | ||
873 | max_tape_pos = zft_capacity - zft_blk_sz; | ||
874 | if (zft_use_compression) { | ||
875 | max_tape_pos -= ZFT_CMPR_OVERHEAD; | ||
876 | } | ||
877 | if (zft_tape_at_eod(&zft_pos)) { | ||
878 | mtget->mt_gstat |= GMT_EOD(~0UL); | ||
879 | } | ||
880 | if (zft_pos.tape_pos > max_tape_pos) { | ||
881 | mtget->mt_gstat |= GMT_EOT(~0UL); | ||
882 | } | ||
883 | mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos, | ||
884 | volume->blk_sz); | ||
885 | if (zft_just_before_eof) { | ||
886 | mtget->mt_gstat |= GMT_EOF(~0UL); | ||
887 | } | ||
888 | if (zft_tape_at_lbot(&zft_pos)) { | ||
889 | mtget->mt_gstat |= GMT_BOT(~0UL); | ||
890 | } | ||
891 | } else { | ||
892 | mtget->mt_fileno = mtget->mt_blkno = -1; | ||
893 | if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) { | ||
894 | mtget->mt_gstat |= GMT_BOT(~0UL); | ||
895 | } | ||
896 | } | ||
897 | } else { | ||
898 | if (ft_no_tape) { | ||
899 | mtget->mt_gstat = GMT_DR_OPEN(~0UL); | ||
900 | } else { | ||
901 | mtget->mt_gstat = 0UL; | ||
902 | } | ||
903 | mtget->mt_fileno = mtget->mt_blkno = -1; | ||
904 | } | ||
905 | TRACE_EXIT 0; | ||
906 | } | ||
907 | |||
908 | #ifdef MTIOCRDFTSEG | ||
909 | /* | ||
910 | * Read a floppy tape segment. This is useful for manipulating the | ||
911 | * volume table, and read the old header segment before re-formatting | ||
912 | * the cartridge. | ||
913 | */ | ||
914 | static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size) | ||
915 | { | ||
916 | TRACE_FUN(ft_t_flow); | ||
917 | |||
918 | TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG"); | ||
919 | if (zft_qic_mode) { | ||
920 | TRACE_ABORT(-EACCES, ft_t_info, | ||
921 | "driver needs to be in raw mode for this ioctl"); | ||
922 | } | ||
923 | if (arg_size != sizeof(struct mtftseg)) { | ||
924 | TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d", | ||
925 | arg_size); | ||
926 | } | ||
927 | if (zft_offline) { | ||
928 | TRACE_EXIT -ENXIO; | ||
929 | } | ||
930 | if (mtftseg->mt_mode != FT_RD_SINGLE && | ||
931 | mtftseg->mt_mode != FT_RD_AHEAD) { | ||
932 | TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode"); | ||
933 | } | ||
934 | if (!ft_formatted) { | ||
935 | TRACE_EXIT -EACCES; /* -ENXIO ? */ | ||
936 | |||
937 | } | ||
938 | if (!zft_header_read) { | ||
939 | TRACE_CATCH(zft_def_idle_state(),); | ||
940 | } | ||
941 | if (mtftseg->mt_segno > ft_last_data_segment) { | ||
942 | TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large"); | ||
943 | } | ||
944 | mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno, | ||
945 | zft_deblock_buf, | ||
946 | mtftseg->mt_mode); | ||
947 | if (mtftseg->mt_result < 0) { | ||
948 | /* a negativ result is not an ioctl error. if | ||
949 | * the user wants to read damaged tapes, | ||
950 | * it's up to her/him | ||
951 | */ | ||
952 | TRACE_EXIT 0; | ||
953 | } | ||
954 | if (copy_to_user(mtftseg->mt_data, | ||
955 | zft_deblock_buf, | ||
956 | mtftseg->mt_result) != 0) { | ||
957 | TRACE_EXIT -EFAULT; | ||
958 | } | ||
959 | TRACE_EXIT 0; | ||
960 | } | ||
961 | #endif | ||
962 | |||
963 | #ifdef MTIOCWRFTSEG | ||
964 | /* | ||
965 | * write a floppy tape segment. This version features writing of | ||
966 | * deleted address marks, and gracefully ignores the (software) | ||
967 | * ft_formatted flag to support writing of header segments after | ||
968 | * formatting. | ||
969 | */ | ||
970 | static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size) | ||
971 | { | ||
972 | int result; | ||
973 | TRACE_FUN(ft_t_flow); | ||
974 | |||
975 | TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG"); | ||
976 | if (zft_write_protected || zft_qic_mode) { | ||
977 | TRACE_EXIT -EACCES; | ||
978 | } | ||
979 | if (arg_size != sizeof(struct mtftseg)) { | ||
980 | TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d", | ||
981 | arg_size); | ||
982 | } | ||
983 | if (zft_offline) { | ||
984 | TRACE_EXIT -ENXIO; | ||
985 | } | ||
986 | if (mtftseg->mt_mode != FT_WR_ASYNC && | ||
987 | mtftseg->mt_mode != FT_WR_MULTI && | ||
988 | mtftseg->mt_mode != FT_WR_SINGLE && | ||
989 | mtftseg->mt_mode != FT_WR_DELETE) { | ||
990 | TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode"); | ||
991 | } | ||
992 | /* | ||
993 | * We don't check for ft_formatted, because this gives | ||
994 | * only the software status of the driver. | ||
995 | * | ||
996 | * We assume that the user knows what it is | ||
997 | * doing. And rely on the low level stuff to fail | ||
998 | * when the tape isn't formatted. We only make sure | ||
999 | * that The header segment buffer is allocated, | ||
1000 | * because it holds the bad sector map. | ||
1001 | */ | ||
1002 | if (zft_hseg_buf == NULL) { | ||
1003 | TRACE_EXIT -ENXIO; | ||
1004 | } | ||
1005 | if (mtftseg->mt_mode != FT_WR_DELETE) { | ||
1006 | if (copy_from_user(zft_deblock_buf, | ||
1007 | mtftseg->mt_data, | ||
1008 | FT_SEGMENT_SIZE) != 0) { | ||
1009 | TRACE_EXIT -EFAULT; | ||
1010 | } | ||
1011 | } | ||
1012 | mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno, | ||
1013 | zft_deblock_buf, | ||
1014 | mtftseg->mt_mode); | ||
1015 | if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) { | ||
1016 | /* | ||
1017 | * a negativ result is not an ioctl error. if | ||
1018 | * the user wants to write damaged tapes, | ||
1019 | * it's up to her/him | ||
1020 | */ | ||
1021 | if ((result = ftape_loop_until_writes_done()) < 0) { | ||
1022 | mtftseg->mt_result = result; | ||
1023 | } | ||
1024 | } | ||
1025 | TRACE_EXIT 0; | ||
1026 | } | ||
1027 | #endif | ||
1028 | |||
1029 | #ifdef MTIOCVOLINFO | ||
1030 | /* | ||
1031 | * get information about volume positioned at. | ||
1032 | */ | ||
1033 | static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size) | ||
1034 | { | ||
1035 | const zft_volinfo *volume; | ||
1036 | TRACE_FUN(ft_t_flow); | ||
1037 | |||
1038 | TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO"); | ||
1039 | if (arg_size != sizeof(struct mtvolinfo)) { | ||
1040 | TRACE_ABORT(-EINVAL, | ||
1041 | ft_t_info, "bad argument size: %d", arg_size); | ||
1042 | } | ||
1043 | if (zft_offline) { | ||
1044 | TRACE_EXIT -ENXIO; | ||
1045 | } | ||
1046 | if (!ft_formatted) { | ||
1047 | TRACE_EXIT -EACCES; | ||
1048 | } | ||
1049 | TRACE_CATCH(zft_def_idle_state(),); | ||
1050 | volume = zft_find_volume(zft_pos.seg_pos); | ||
1051 | volinfo->mt_volno = volume->count; | ||
1052 | volinfo->mt_blksz = volume->blk_sz == 1 ? 0 : volume->blk_sz; | ||
1053 | volinfo->mt_size = volume->size >> 10; | ||
1054 | volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) - | ||
1055 | (zft_calc_tape_pos(volume->start_seg) >> 10)); | ||
1056 | volinfo->mt_cmpr = volume->use_compression; | ||
1057 | TRACE_EXIT 0; | ||
1058 | } | ||
1059 | #endif | ||
1060 | |||
1061 | #ifdef ZFT_OBSOLETE | ||
1062 | static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size) | ||
1063 | { | ||
1064 | TRACE_FUN(ft_t_flow); | ||
1065 | |||
1066 | TRACE(ft_t_noise, "\n" | ||
1067 | KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n" | ||
1068 | KERN_INFO "This ioctl is here merely for compatibility.\n" | ||
1069 | KERN_INFO "Please use MTIOCVOLINFO instead"); | ||
1070 | if (arg_size != sizeof(struct mtblksz)) { | ||
1071 | TRACE_ABORT(-EINVAL, | ||
1072 | ft_t_info, "bad argument size: %d", arg_size); | ||
1073 | } | ||
1074 | if (zft_offline) { | ||
1075 | TRACE_EXIT -ENXIO; | ||
1076 | } | ||
1077 | if (!ft_formatted) { | ||
1078 | TRACE_EXIT -EACCES; | ||
1079 | } | ||
1080 | TRACE_CATCH(zft_def_idle_state(),); | ||
1081 | blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz; | ||
1082 | TRACE_EXIT 0; | ||
1083 | } | ||
1084 | #endif | ||
1085 | |||
1086 | #ifdef MTIOCGETSIZE | ||
1087 | /* | ||
1088 | * get the capacity of the tape cartridge. | ||
1089 | */ | ||
1090 | static int mtiocgetsize(struct mttapesize *size, int arg_size) | ||
1091 | { | ||
1092 | TRACE_FUN(ft_t_flow); | ||
1093 | |||
1094 | TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE"); | ||
1095 | if (arg_size != sizeof(struct mttapesize)) { | ||
1096 | TRACE_ABORT(-EINVAL, | ||
1097 | ft_t_info, "bad argument size: %d", arg_size); | ||
1098 | } | ||
1099 | if (zft_offline) { | ||
1100 | TRACE_EXIT -ENXIO; | ||
1101 | } | ||
1102 | if (!ft_formatted) { | ||
1103 | TRACE_EXIT -EACCES; | ||
1104 | } | ||
1105 | TRACE_CATCH(zft_def_idle_state(),); | ||
1106 | size->mt_capacity = (unsigned int)(zft_capacity>>10); | ||
1107 | size->mt_used = (unsigned int)(zft_get_eom_pos()>>10); | ||
1108 | TRACE_EXIT 0; | ||
1109 | } | ||
1110 | #endif | ||
1111 | |||
1112 | static int mtiocpos(struct mtpos *mtpos, int arg_size) | ||
1113 | { | ||
1114 | int result; | ||
1115 | TRACE_FUN(ft_t_flow); | ||
1116 | |||
1117 | TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS"); | ||
1118 | if (arg_size != sizeof(struct mtpos)) { | ||
1119 | TRACE_ABORT(-EINVAL, | ||
1120 | ft_t_info, "bad argument size: %d", arg_size); | ||
1121 | } | ||
1122 | result = mt_tell((int *)&mtpos->mt_blkno); | ||
1123 | TRACE_EXIT result; | ||
1124 | } | ||
1125 | |||
1126 | #ifdef MTIOCFTFORMAT | ||
1127 | /* | ||
1128 | * formatting of floppy tape cartridges. This is intended to be used | ||
1129 | * together with the MTIOCFTCMD ioctl and the new mmap feature | ||
1130 | */ | ||
1131 | |||
1132 | /* | ||
1133 | * This function uses ftape_decode_header_segment() to inform the low | ||
1134 | * level ftape module about the new parameters. | ||
1135 | * | ||
1136 | * It erases the hseg_buf. The calling process must specify all | ||
1137 | * parameters to assure proper operation. | ||
1138 | * | ||
1139 | * return values: -EINVAL - wrong argument size | ||
1140 | * -EINVAL - if ftape_decode_header_segment() failed. | ||
1141 | */ | ||
1142 | static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf) | ||
1143 | { | ||
1144 | ft_trace_t old_level = TRACE_LEVEL; | ||
1145 | TRACE_FUN(ft_t_flow); | ||
1146 | |||
1147 | TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS"); | ||
1148 | memset(hseg_buf, 0, FT_SEGMENT_SIZE); | ||
1149 | PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC); | ||
1150 | |||
1151 | /* fill in user specified parameters | ||
1152 | */ | ||
1153 | hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode; | ||
1154 | PUT2(hseg_buf, FT_SPT, p->ft_spt); | ||
1155 | hseg_buf[FT_TPC] = (__u8)p->ft_tpc; | ||
1156 | hseg_buf[FT_FHM] = (__u8)p->ft_fhm; | ||
1157 | hseg_buf[FT_FTM] = (__u8)p->ft_ftm; | ||
1158 | |||
1159 | /* fill in sane defaults to make ftape happy. | ||
1160 | */ | ||
1161 | hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */ | ||
1162 | if (p->ft_fmtcode == fmt_big) { | ||
1163 | PUT4(hseg_buf, FT_6_HSEG_1, 0); | ||
1164 | PUT4(hseg_buf, FT_6_HSEG_2, 1); | ||
1165 | PUT4(hseg_buf, FT_6_FRST_SEG, 2); | ||
1166 | PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1); | ||
1167 | } else { | ||
1168 | PUT2(hseg_buf, FT_HSEG_1, 0); | ||
1169 | PUT2(hseg_buf, FT_HSEG_2, 1); | ||
1170 | PUT2(hseg_buf, FT_FRST_SEG, 2); | ||
1171 | PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1); | ||
1172 | } | ||
1173 | |||
1174 | /* Synchronize with the low level module. This is particularly | ||
1175 | * needed for unformatted cartridges as the QIC std was previously | ||
1176 | * unknown BUT is needed to set data rate and to calculate timeouts. | ||
1177 | */ | ||
1178 | TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK), | ||
1179 | _res = -EINVAL); | ||
1180 | |||
1181 | /* The following will also recalcualte the timeouts for the tape | ||
1182 | * length and QIC std we want to format to. | ||
1183 | * abort with -EINVAL rather than -EIO | ||
1184 | */ | ||
1185 | SET_TRACE_LEVEL(ft_t_warn); | ||
1186 | TRACE_CATCH(ftape_decode_header_segment(hseg_buf), | ||
1187 | SET_TRACE_LEVEL(old_level); _res = -EINVAL); | ||
1188 | SET_TRACE_LEVEL(old_level); | ||
1189 | TRACE_EXIT 0; | ||
1190 | } | ||
1191 | |||
1192 | /* | ||
1193 | * Return the internal SOFTWARE status of the kernel driver. This does | ||
1194 | * NOT query the tape drive about its status. | ||
1195 | */ | ||
1196 | static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer) | ||
1197 | { | ||
1198 | TRACE_FUN(ft_t_flow); | ||
1199 | |||
1200 | TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS"); | ||
1201 | p->ft_qicstd = ft_qic_std; | ||
1202 | p->ft_fmtcode = ft_format_code; | ||
1203 | p->ft_fhm = hseg_buffer[FT_FHM]; | ||
1204 | p->ft_ftm = hseg_buffer[FT_FTM]; | ||
1205 | p->ft_spt = ft_segments_per_track; | ||
1206 | p->ft_tpc = ft_tracks_per_tape; | ||
1207 | TRACE_EXIT 0; | ||
1208 | } | ||
1209 | |||
1210 | static int mtiocftformat(struct mtftformat *mtftformat, int arg_size) | ||
1211 | { | ||
1212 | int result; | ||
1213 | union fmt_arg *arg = &mtftformat->fmt_arg; | ||
1214 | TRACE_FUN(ft_t_flow); | ||
1215 | |||
1216 | TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT"); | ||
1217 | if (zft_offline) { | ||
1218 | if (ft_no_tape) { | ||
1219 | TRACE_ABORT(-ENXIO, ft_t_info, "no tape present"); | ||
1220 | } else { | ||
1221 | TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline"); | ||
1222 | } | ||
1223 | } | ||
1224 | if (zft_qic_mode) { | ||
1225 | TRACE_ABORT(-EACCES, ft_t_info, | ||
1226 | "driver needs to be in raw mode for this ioctl"); | ||
1227 | } | ||
1228 | if (zft_hseg_buf == NULL) { | ||
1229 | TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),); | ||
1230 | } | ||
1231 | zft_header_read = 0; | ||
1232 | switch(mtftformat->fmt_op) { | ||
1233 | case FTFMT_SET_PARMS: | ||
1234 | TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),); | ||
1235 | TRACE_EXIT 0; | ||
1236 | case FTFMT_GET_PARMS: | ||
1237 | TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),); | ||
1238 | TRACE_EXIT 0; | ||
1239 | case FTFMT_FORMAT_TRACK: | ||
1240 | if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) || | ||
1241 | (!ft_formatted && zft_write_protected)) { | ||
1242 | TRACE_ABORT(-EACCES, ft_t_info, "Write access denied"); | ||
1243 | } | ||
1244 | TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track, | ||
1245 | arg->fmt_track.ft_gap3),); | ||
1246 | TRACE_EXIT 0; | ||
1247 | case FTFMT_STATUS: | ||
1248 | TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),); | ||
1249 | TRACE_EXIT 0; | ||
1250 | case FTFMT_VERIFY: | ||
1251 | TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment, | ||
1252 | (SectorMap *)&arg->fmt_verify.ft_bsm),); | ||
1253 | TRACE_EXIT 0; | ||
1254 | default: | ||
1255 | TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation"); | ||
1256 | } | ||
1257 | TRACE_EXIT result; | ||
1258 | } | ||
1259 | #endif | ||
1260 | |||
1261 | #ifdef MTIOCFTCMD | ||
1262 | /* | ||
1263 | * send a QIC-117 command to the drive, with optional timeouts, | ||
1264 | * parameter and result bits. This is intended to be used together | ||
1265 | * with the formatting ioctl. | ||
1266 | */ | ||
1267 | static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size) | ||
1268 | { | ||
1269 | int i; | ||
1270 | TRACE_FUN(ft_t_flow); | ||
1271 | |||
1272 | TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD"); | ||
1273 | if (!capable(CAP_SYS_ADMIN)) { | ||
1274 | TRACE_ABORT(-EPERM, ft_t_info, | ||
1275 | "need CAP_SYS_ADMIN capability to send raw qic-117 commands"); | ||
1276 | } | ||
1277 | if (zft_qic_mode) { | ||
1278 | TRACE_ABORT(-EACCES, ft_t_info, | ||
1279 | "driver needs to be in raw mode for this ioctl"); | ||
1280 | } | ||
1281 | if (arg_size != sizeof(struct mtftcmd)) { | ||
1282 | TRACE_ABORT(-EINVAL, | ||
1283 | ft_t_info, "bad argument size: %d", arg_size); | ||
1284 | } | ||
1285 | if (ftcmd->ft_wait_before) { | ||
1286 | TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before, | ||
1287 | &ftcmd->ft_status),); | ||
1288 | } | ||
1289 | if (ftcmd->ft_status & QIC_STATUS_ERROR) | ||
1290 | goto ftmtcmd_error; | ||
1291 | if (ftcmd->ft_result_bits != 0) { | ||
1292 | TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result, | ||
1293 | ftcmd->ft_cmd, | ||
1294 | ftcmd->ft_result_bits),); | ||
1295 | } else { | ||
1296 | TRACE_CATCH(ftape_command(ftcmd->ft_cmd),); | ||
1297 | if (ftcmd->ft_status & QIC_STATUS_ERROR) | ||
1298 | goto ftmtcmd_error; | ||
1299 | for (i = 0; i < ftcmd->ft_parm_cnt; i++) { | ||
1300 | TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),); | ||
1301 | if (ftcmd->ft_status & QIC_STATUS_ERROR) | ||
1302 | goto ftmtcmd_error; | ||
1303 | } | ||
1304 | } | ||
1305 | if (ftcmd->ft_wait_after != 0) { | ||
1306 | TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after, | ||
1307 | &ftcmd->ft_status),); | ||
1308 | } | ||
1309 | ftmtcmd_error: | ||
1310 | if (ftcmd->ft_status & QIC_STATUS_ERROR) { | ||
1311 | TRACE(ft_t_noise, "error status set"); | ||
1312 | TRACE_CATCH(ftape_report_error(&ftcmd->ft_error, | ||
1313 | &ftcmd->ft_cmd, 1),); | ||
1314 | } | ||
1315 | TRACE_EXIT 0; /* this is not an i/o error */ | ||
1316 | } | ||
1317 | #endif | ||
1318 | |||
1319 | /* IOCTL routine called by kernel-interface code | ||
1320 | */ | ||
1321 | int _zft_ioctl(unsigned int command, void __user * arg) | ||
1322 | { | ||
1323 | int result; | ||
1324 | union { struct mtop mtop; | ||
1325 | struct mtget mtget; | ||
1326 | struct mtpos mtpos; | ||
1327 | #ifdef MTIOCRDFTSEG | ||
1328 | struct mtftseg mtftseg; | ||
1329 | #endif | ||
1330 | #ifdef MTIOCVOLINFO | ||
1331 | struct mtvolinfo mtvolinfo; | ||
1332 | #endif | ||
1333 | #ifdef MTIOCGETSIZE | ||
1334 | struct mttapesize mttapesize; | ||
1335 | #endif | ||
1336 | #ifdef MTIOCFTFORMAT | ||
1337 | struct mtftformat mtftformat; | ||
1338 | #endif | ||
1339 | #ifdef ZFT_OBSOLETE | ||
1340 | struct mtblksz mtblksz; | ||
1341 | #endif | ||
1342 | #ifdef MTIOCFTCMD | ||
1343 | struct mtftcmd mtftcmd; | ||
1344 | #endif | ||
1345 | } krnl_arg; | ||
1346 | int arg_size = _IOC_SIZE(command); | ||
1347 | int dir = _IOC_DIR(command); | ||
1348 | TRACE_FUN(ft_t_flow); | ||
1349 | |||
1350 | /* This check will only catch arguments that are too large ! | ||
1351 | */ | ||
1352 | if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) { | ||
1353 | TRACE_ABORT(-EINVAL, | ||
1354 | ft_t_info, "bad argument size: %d", arg_size); | ||
1355 | } | ||
1356 | if (dir & _IOC_WRITE) { | ||
1357 | if (copy_from_user(&krnl_arg, arg, arg_size) != 0) { | ||
1358 | TRACE_EXIT -EFAULT; | ||
1359 | } | ||
1360 | } | ||
1361 | TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command); | ||
1362 | switch (command) { | ||
1363 | case MTIOCTOP: | ||
1364 | result = mtioctop(&krnl_arg.mtop, arg_size); | ||
1365 | break; | ||
1366 | case MTIOCGET: | ||
1367 | result = mtiocget(&krnl_arg.mtget, arg_size); | ||
1368 | break; | ||
1369 | case MTIOCPOS: | ||
1370 | result = mtiocpos(&krnl_arg.mtpos, arg_size); | ||
1371 | break; | ||
1372 | #ifdef MTIOCVOLINFO | ||
1373 | case MTIOCVOLINFO: | ||
1374 | result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size); | ||
1375 | break; | ||
1376 | #endif | ||
1377 | #ifdef ZFT_OBSOLETE | ||
1378 | case MTIOC_ZFTAPE_GETBLKSZ: | ||
1379 | result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size); | ||
1380 | break; | ||
1381 | #endif | ||
1382 | #ifdef MTIOCRDFTSEG | ||
1383 | case MTIOCRDFTSEG: /* read a segment via ioctl */ | ||
1384 | result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size); | ||
1385 | break; | ||
1386 | #endif | ||
1387 | #ifdef MTIOCWRFTSEG | ||
1388 | case MTIOCWRFTSEG: /* write a segment via ioctl */ | ||
1389 | result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size); | ||
1390 | break; | ||
1391 | #endif | ||
1392 | #ifdef MTIOCGETSIZE | ||
1393 | case MTIOCGETSIZE: | ||
1394 | result = mtiocgetsize(&krnl_arg.mttapesize, arg_size); | ||
1395 | break; | ||
1396 | #endif | ||
1397 | #ifdef MTIOCFTFORMAT | ||
1398 | case MTIOCFTFORMAT: | ||
1399 | result = mtiocftformat(&krnl_arg.mtftformat, arg_size); | ||
1400 | break; | ||
1401 | #endif | ||
1402 | #ifdef MTIOCFTCMD | ||
1403 | case MTIOCFTCMD: | ||
1404 | result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size); | ||
1405 | break; | ||
1406 | #endif | ||
1407 | default: | ||
1408 | result = -EINVAL; | ||
1409 | break; | ||
1410 | } | ||
1411 | if ((result >= 0) && (dir & _IOC_READ)) { | ||
1412 | if (copy_to_user(arg, &krnl_arg, arg_size) != 0) { | ||
1413 | TRACE_EXIT -EFAULT; | ||
1414 | } | ||
1415 | } | ||
1416 | TRACE_EXIT result; | ||
1417 | } | ||
diff --git a/drivers/char/ftape/zftape/zftape-ctl.h b/drivers/char/ftape/zftape/zftape-ctl.h deleted file mode 100644 index 8e6f2d7ac74e..000000000000 --- a/drivers/char/ftape/zftape/zftape-ctl.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_CTL_H | ||
2 | #define _ZFTAPE_CTL_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996, 1997 Claus-Justus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:19:02 $ | ||
25 | * | ||
26 | * This file contains the non-standard IOCTL related definitions | ||
27 | * for the QIC-40/80 floppy-tape driver for Linux. | ||
28 | */ | ||
29 | |||
30 | #include <linux/ioctl.h> | ||
31 | #include <linux/mtio.h> | ||
32 | |||
33 | #include "../zftape/zftape-rw.h" | ||
34 | |||
35 | #ifdef CONFIG_ZFTAPE_MODULE | ||
36 | #define ftape_status (*zft_status) | ||
37 | #endif | ||
38 | |||
39 | extern int zft_offline; | ||
40 | extern int zft_mt_compression; | ||
41 | extern int zft_write_protected; | ||
42 | extern int zft_header_read; | ||
43 | extern unsigned int zft_unit; | ||
44 | extern int zft_resid; | ||
45 | |||
46 | extern void zft_reset_position(zft_position *pos); | ||
47 | extern int zft_check_write_access(zft_position *pos); | ||
48 | extern int zft_def_idle_state(void); | ||
49 | |||
50 | /* hooks for the VFS interface | ||
51 | */ | ||
52 | extern int _zft_open(unsigned int dev_minor, unsigned int access_mode); | ||
53 | extern int _zft_close(void); | ||
54 | extern int _zft_ioctl(unsigned int command, void __user *arg); | ||
55 | #endif | ||
56 | |||
57 | |||
58 | |||
diff --git a/drivers/char/ftape/zftape/zftape-eof.c b/drivers/char/ftape/zftape/zftape-eof.c deleted file mode 100644 index dcadcaee9ac1..000000000000 --- a/drivers/char/ftape/zftape/zftape-eof.c +++ /dev/null | |||
@@ -1,199 +0,0 @@ | |||
1 | /* | ||
2 | * I use these routines just to decide when I have to fake a | ||
3 | * volume-table to preserve compatibility to original ftape. | ||
4 | */ | ||
5 | /* | ||
6 | * Copyright (C) 1994-1995 Bas Laarhoven. | ||
7 | * | ||
8 | * Modified for zftape 1996, 1997 Claus Heine. | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2, or (at your option) | ||
13 | any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; see the file COPYING. If not, write to | ||
22 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | |||
24 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.c,v $ | ||
25 | * $Revision: 1.2 $ | ||
26 | * $Date: 1997/10/05 19:19:02 $ | ||
27 | * | ||
28 | * This file contains the eof mark handling code | ||
29 | * for the QIC-40/80 floppy-tape driver for Linux. | ||
30 | */ | ||
31 | |||
32 | #include <linux/string.h> | ||
33 | #include <linux/errno.h> | ||
34 | |||
35 | #include <linux/zftape.h> | ||
36 | |||
37 | #include "../zftape/zftape-init.h" | ||
38 | #include "../zftape/zftape-rw.h" | ||
39 | #include "../zftape/zftape-eof.h" | ||
40 | |||
41 | /* Global vars. | ||
42 | */ | ||
43 | |||
44 | /* a copy of the failed sector log from the header segment. | ||
45 | */ | ||
46 | eof_mark_union *zft_eof_map; | ||
47 | |||
48 | /* number of eof marks (entries in bad sector log) on tape. | ||
49 | */ | ||
50 | int zft_nr_eof_marks = -1; | ||
51 | |||
52 | |||
53 | /* Local vars. | ||
54 | */ | ||
55 | |||
56 | static char linux_tape_label[] = "Linux raw format V"; | ||
57 | enum { | ||
58 | min_fmt_version = 1, max_fmt_version = 2 | ||
59 | }; | ||
60 | static unsigned ftape_fmt_version = 0; | ||
61 | |||
62 | |||
63 | /* Ftape (mis)uses the bad sector log to record end-of-file marks. | ||
64 | * Initially (when the tape is erased) all entries in the bad sector | ||
65 | * log are added to the tape's bad sector map. The bad sector log then | ||
66 | * is cleared. | ||
67 | * | ||
68 | * The bad sector log normally contains entries of the form: | ||
69 | * even 16-bit word: segment number of bad sector | ||
70 | * odd 16-bit word: encoded date | ||
71 | * There can be a total of 448 entries (1792 bytes). | ||
72 | * | ||
73 | * My guess is that no program is using this bad sector log (the * | ||
74 | * format seems useless as there is no indication of the bad sector | ||
75 | * itself, only the segment) However, if any program does use the bad | ||
76 | * sector log, the format used by ftape will let the program think | ||
77 | * there are some bad sectors and no harm is done. | ||
78 | * | ||
79 | * The eof mark entries that ftape stores in the bad sector log: even | ||
80 | * 16-bit word: segment number of eof mark odd 16-bit word: sector | ||
81 | * number of eof mark [1..32] | ||
82 | * | ||
83 | * The zft_eof_map as maintained is a sorted list of eof mark entries. | ||
84 | * | ||
85 | * | ||
86 | * The tape name field in the header segments is used to store a linux | ||
87 | * tape identification string and a version number. This way the tape | ||
88 | * can be recognized as a Linux raw format tape when using tools under | ||
89 | * other OS's. | ||
90 | * | ||
91 | * 'Wide' QIC tapes (format code 4) don't have a failed sector list | ||
92 | * anymore. That space is used for the (longer) bad sector map that | ||
93 | * now is a variable length list too. We now store our end-of-file | ||
94 | * marker list after the bad-sector-map on tape. The list is delimited | ||
95 | * by a (__u32) 0 entry. | ||
96 | */ | ||
97 | |||
98 | int zft_ftape_validate_label(char *label) | ||
99 | { | ||
100 | static char tmp_label[45]; | ||
101 | int result = 0; | ||
102 | TRACE_FUN(ft_t_any); | ||
103 | |||
104 | memcpy(tmp_label, label, FT_LABEL_SZ); | ||
105 | tmp_label[FT_LABEL_SZ] = '\0'; | ||
106 | TRACE(ft_t_noise, "tape label = `%s'", tmp_label); | ||
107 | ftape_fmt_version = 0; | ||
108 | if (memcmp(label, linux_tape_label, strlen(linux_tape_label)) == 0) { | ||
109 | int pos = strlen(linux_tape_label); | ||
110 | while (label[pos] >= '0' && label[pos] <= '9') { | ||
111 | ftape_fmt_version *= 10; | ||
112 | ftape_fmt_version = label[ pos++] - '0'; | ||
113 | } | ||
114 | result = (ftape_fmt_version >= min_fmt_version && | ||
115 | ftape_fmt_version <= max_fmt_version); | ||
116 | } | ||
117 | TRACE(ft_t_noise, "format version = %d", ftape_fmt_version); | ||
118 | TRACE_EXIT result; | ||
119 | } | ||
120 | |||
121 | static __u8 * find_end_of_eof_list(__u8 * ptr, __u8 * limit) | ||
122 | { | ||
123 | while (ptr + 3 < limit) { | ||
124 | |||
125 | if (get_unaligned((__u32*)ptr)) { | ||
126 | ptr += sizeof(__u32); | ||
127 | } else { | ||
128 | return ptr; | ||
129 | } | ||
130 | } | ||
131 | return NULL; | ||
132 | } | ||
133 | |||
134 | void zft_ftape_extract_file_marks(__u8* address) | ||
135 | { | ||
136 | int i; | ||
137 | TRACE_FUN(ft_t_any); | ||
138 | |||
139 | zft_eof_map = NULL; | ||
140 | if (ft_format_code == fmt_var || ft_format_code == fmt_big) { | ||
141 | __u8* end; | ||
142 | __u8* start = ftape_find_end_of_bsm_list(address); | ||
143 | |||
144 | zft_nr_eof_marks = 0; | ||
145 | if (start) { | ||
146 | start += 3; /* skip end of list mark */ | ||
147 | end = find_end_of_eof_list(start, | ||
148 | address + FT_SEGMENT_SIZE); | ||
149 | if (end && end - start <= FT_FSL_SIZE) { | ||
150 | zft_nr_eof_marks = ((end - start) / | ||
151 | sizeof(eof_mark_union)); | ||
152 | zft_eof_map = (eof_mark_union *)start; | ||
153 | } else { | ||
154 | TRACE(ft_t_err, | ||
155 | "EOF Mark List is too long or damaged!"); | ||
156 | } | ||
157 | } else { | ||
158 | TRACE(ft_t_err, | ||
159 | "Bad Sector List is too long or damaged !"); | ||
160 | } | ||
161 | } else { | ||
162 | zft_eof_map = (eof_mark_union *)&address[FT_FSL]; | ||
163 | zft_nr_eof_marks = GET2(address, FT_FSL_CNT); | ||
164 | } | ||
165 | TRACE(ft_t_noise, "number of file marks: %d", zft_nr_eof_marks); | ||
166 | if (ftape_fmt_version == 1) { | ||
167 | TRACE(ft_t_info, "swapping version 1 fields"); | ||
168 | /* version 1 format uses swapped sector and segment | ||
169 | * fields, correct that ! | ||
170 | */ | ||
171 | for (i = 0; i < zft_nr_eof_marks; ++i) { | ||
172 | __u16 tmp = GET2(&zft_eof_map[i].mark.segment,0); | ||
173 | PUT2(&zft_eof_map[i].mark.segment, 0, | ||
174 | GET2(&zft_eof_map[i].mark.date,0)); | ||
175 | PUT2(&zft_eof_map[i].mark.date, 0, tmp); | ||
176 | } | ||
177 | } | ||
178 | for (i = 0; i < zft_nr_eof_marks; ++i) { | ||
179 | TRACE(ft_t_noise, "eof mark: %5d/%2d", | ||
180 | GET2(&zft_eof_map[i].mark.segment, 0), | ||
181 | GET2(&zft_eof_map[i].mark.date,0)); | ||
182 | } | ||
183 | TRACE_EXIT; | ||
184 | } | ||
185 | |||
186 | void zft_clear_ftape_file_marks(void) | ||
187 | { | ||
188 | TRACE_FUN(ft_t_flow); | ||
189 | /* Clear failed sector log: remove all tape marks. We | ||
190 | * don't use old ftape-style EOF-marks. | ||
191 | */ | ||
192 | TRACE(ft_t_info, "Clearing old ftape's eof map"); | ||
193 | memset(zft_eof_map, 0, zft_nr_eof_marks * sizeof(__u32)); | ||
194 | zft_nr_eof_marks = 0; | ||
195 | PUT2(zft_hseg_buf, FT_FSL_CNT, 0); /* nr of eof-marks */ | ||
196 | zft_header_changed = 1; | ||
197 | zft_update_label(zft_hseg_buf); | ||
198 | TRACE_EXIT; | ||
199 | } | ||
diff --git a/drivers/char/ftape/zftape/zftape-eof.h b/drivers/char/ftape/zftape/zftape-eof.h deleted file mode 100644 index 26568c26c518..000000000000 --- a/drivers/char/ftape/zftape/zftape-eof.h +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_EOF_H | ||
2 | #define _ZFTAPE_EOF_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1994-1995 Bas Laarhoven. | ||
6 | * adaptaed for zftape 1996, 1997 by Claus Heine | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.h,v $ | ||
24 | * $Revision: 1.2 $ | ||
25 | * $Date: 1997/10/05 19:19:03 $ | ||
26 | * | ||
27 | * Definitions and declarations for the end of file markers | ||
28 | * for the QIC-40/80 floppy-tape driver for Linux. | ||
29 | */ | ||
30 | |||
31 | #include <linux/ftape-header-segment.h> | ||
32 | #include "../zftape/zftape-buffers.h" | ||
33 | /* failed sector log size (only used if format code != 4). | ||
34 | */ | ||
35 | |||
36 | typedef union { | ||
37 | ft_fsl_entry mark; | ||
38 | __u32 entry; | ||
39 | } eof_mark_union; | ||
40 | |||
41 | /* ftape-eof.c defined global vars. | ||
42 | */ | ||
43 | extern int zft_nr_eof_marks; | ||
44 | extern eof_mark_union *zft_eof_map; | ||
45 | |||
46 | /* ftape-eof.c defined global functions. | ||
47 | */ | ||
48 | extern void zft_ftape_extract_file_marks(__u8* address); | ||
49 | extern int zft_ftape_validate_label(char* label); | ||
50 | extern void zft_clear_ftape_file_marks(void); | ||
51 | |||
52 | #endif | ||
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c deleted file mode 100644 index 164a1aa77a2f..000000000000 --- a/drivers/char/ftape/zftape/zftape-init.c +++ /dev/null | |||
@@ -1,377 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996, 1997 Claus-Justus Heine. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * This file contains the code that registers the zftape frontend | ||
20 | * to the ftape floppy tape driver for Linux | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/signal.h> | ||
28 | #include <linux/major.h> | ||
29 | #include <linux/slab.h> | ||
30 | #ifdef CONFIG_KMOD | ||
31 | #include <linux/kmod.h> | ||
32 | #endif | ||
33 | #include <linux/fcntl.h> | ||
34 | #include <linux/smp_lock.h> | ||
35 | |||
36 | #include <linux/zftape.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/device.h> | ||
39 | |||
40 | #include "../zftape/zftape-init.h" | ||
41 | #include "../zftape/zftape-read.h" | ||
42 | #include "../zftape/zftape-write.h" | ||
43 | #include "../zftape/zftape-ctl.h" | ||
44 | #include "../zftape/zftape-buffers.h" | ||
45 | |||
46 | MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine " | ||
47 | "(claus@momo.math.rwth-aachen.de)"); | ||
48 | MODULE_DESCRIPTION(ZFTAPE_VERSION " - " | ||
49 | "VFS interface for the Linux floppy tape driver. " | ||
50 | "Support for QIC-113 compatible volume table " | ||
51 | "and builtin compression (lzrw3 algorithm)"); | ||
52 | MODULE_SUPPORTED_DEVICE("char-major-27"); | ||
53 | MODULE_LICENSE("GPL"); | ||
54 | |||
55 | /* Global vars. | ||
56 | */ | ||
57 | struct zft_cmpr_ops *zft_cmpr_ops = NULL; | ||
58 | const ftape_info *zft_status; | ||
59 | |||
60 | /* Local vars. | ||
61 | */ | ||
62 | static unsigned long busy_flag; | ||
63 | |||
64 | static sigset_t orig_sigmask; | ||
65 | |||
66 | /* the interface to the kernel vfs layer | ||
67 | */ | ||
68 | |||
69 | /* Note about llseek(): | ||
70 | * | ||
71 | * st.c and tpqic.c update fp->f_pos but don't implment llseek() and | ||
72 | * initialize the llseek component of the file_ops struct with NULL. | ||
73 | * This means that the user will get the default seek, but the tape | ||
74 | * device will not respect the new position, but happily read from the | ||
75 | * old position. Think a zftape specific llseek() function would be | ||
76 | * better, returning -ESPIPE. TODO. | ||
77 | */ | ||
78 | |||
79 | static int zft_open (struct inode *ino, struct file *filep); | ||
80 | static int zft_close(struct inode *ino, struct file *filep); | ||
81 | static int zft_ioctl(struct inode *ino, struct file *filep, | ||
82 | unsigned int command, unsigned long arg); | ||
83 | static int zft_mmap(struct file *filep, struct vm_area_struct *vma); | ||
84 | static ssize_t zft_read (struct file *fp, char __user *buff, | ||
85 | size_t req_len, loff_t *ppos); | ||
86 | static ssize_t zft_write(struct file *fp, const char __user *buff, | ||
87 | size_t req_len, loff_t *ppos); | ||
88 | |||
89 | static const struct file_operations zft_cdev = | ||
90 | { | ||
91 | .owner = THIS_MODULE, | ||
92 | .read = zft_read, | ||
93 | .write = zft_write, | ||
94 | .ioctl = zft_ioctl, | ||
95 | .mmap = zft_mmap, | ||
96 | .open = zft_open, | ||
97 | .release = zft_close, | ||
98 | }; | ||
99 | |||
100 | static struct class *zft_class; | ||
101 | |||
102 | /* Open floppy tape device | ||
103 | */ | ||
104 | static int zft_open(struct inode *ino, struct file *filep) | ||
105 | { | ||
106 | int result; | ||
107 | TRACE_FUN(ft_t_flow); | ||
108 | |||
109 | nonseekable_open(ino, filep); | ||
110 | TRACE(ft_t_flow, "called for minor %d", iminor(ino)); | ||
111 | if ( test_and_set_bit(0,&busy_flag) ) { | ||
112 | TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy"); | ||
113 | } | ||
114 | if ((iminor(ino) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND)) | ||
115 | > | ||
116 | FTAPE_SEL_D) { | ||
117 | clear_bit(0,&busy_flag); | ||
118 | TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr"); | ||
119 | } | ||
120 | orig_sigmask = current->blocked; | ||
121 | sigfillset(¤t->blocked); | ||
122 | result = _zft_open(iminor(ino), filep->f_flags & O_ACCMODE); | ||
123 | if (result < 0) { | ||
124 | current->blocked = orig_sigmask; /* restore mask */ | ||
125 | clear_bit(0,&busy_flag); | ||
126 | TRACE_ABORT(result, ft_t_err, "_ftape_open failed"); | ||
127 | } else { | ||
128 | /* Mask signals that will disturb proper operation of the | ||
129 | * program that is calling. | ||
130 | */ | ||
131 | current->blocked = orig_sigmask; | ||
132 | sigaddsetmask (¤t->blocked, _DO_BLOCK); | ||
133 | TRACE_EXIT 0; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /* Close floppy tape device | ||
138 | */ | ||
139 | static int zft_close(struct inode *ino, struct file *filep) | ||
140 | { | ||
141 | int result; | ||
142 | TRACE_FUN(ft_t_flow); | ||
143 | |||
144 | if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit) { | ||
145 | TRACE(ft_t_err, "failed: not busy or wrong unit"); | ||
146 | TRACE_EXIT 0; | ||
147 | } | ||
148 | sigfillset(¤t->blocked); | ||
149 | result = _zft_close(); | ||
150 | if (result < 0) { | ||
151 | TRACE(ft_t_err, "_zft_close failed"); | ||
152 | } | ||
153 | current->blocked = orig_sigmask; /* restore before open state */ | ||
154 | clear_bit(0,&busy_flag); | ||
155 | TRACE_EXIT 0; | ||
156 | } | ||
157 | |||
158 | /* Ioctl for floppy tape device | ||
159 | */ | ||
160 | static int zft_ioctl(struct inode *ino, struct file *filep, | ||
161 | unsigned int command, unsigned long arg) | ||
162 | { | ||
163 | int result = -EIO; | ||
164 | sigset_t old_sigmask; | ||
165 | TRACE_FUN(ft_t_flow); | ||
166 | |||
167 | if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) { | ||
168 | TRACE_ABORT(-EIO, ft_t_err, | ||
169 | "failed: not busy, failure or wrong unit"); | ||
170 | } | ||
171 | old_sigmask = current->blocked; /* save mask */ | ||
172 | sigfillset(¤t->blocked); | ||
173 | /* This will work as long as sizeof(void *) == sizeof(long) */ | ||
174 | result = _zft_ioctl(command, (void __user *) arg); | ||
175 | current->blocked = old_sigmask; /* restore mask */ | ||
176 | TRACE_EXIT result; | ||
177 | } | ||
178 | |||
179 | /* Ioctl for floppy tape device | ||
180 | */ | ||
181 | static int zft_mmap(struct file *filep, struct vm_area_struct *vma) | ||
182 | { | ||
183 | int result = -EIO; | ||
184 | sigset_t old_sigmask; | ||
185 | TRACE_FUN(ft_t_flow); | ||
186 | |||
187 | if ( !test_bit(0,&busy_flag) || | ||
188 | iminor(filep->f_dentry->d_inode) != zft_unit || | ||
189 | ft_failure) | ||
190 | { | ||
191 | TRACE_ABORT(-EIO, ft_t_err, | ||
192 | "failed: not busy, failure or wrong unit"); | ||
193 | } | ||
194 | old_sigmask = current->blocked; /* save mask */ | ||
195 | sigfillset(¤t->blocked); | ||
196 | if ((result = ftape_mmap(vma)) >= 0) { | ||
197 | #ifndef MSYNC_BUG_WAS_FIXED | ||
198 | static struct vm_operations_struct dummy = { NULL, }; | ||
199 | vma->vm_ops = &dummy; | ||
200 | #endif | ||
201 | } | ||
202 | current->blocked = old_sigmask; /* restore mask */ | ||
203 | TRACE_EXIT result; | ||
204 | } | ||
205 | |||
206 | /* Read from floppy tape device | ||
207 | */ | ||
208 | static ssize_t zft_read(struct file *fp, char __user *buff, | ||
209 | size_t req_len, loff_t *ppos) | ||
210 | { | ||
211 | int result = -EIO; | ||
212 | sigset_t old_sigmask; | ||
213 | struct inode *ino = fp->f_dentry->d_inode; | ||
214 | TRACE_FUN(ft_t_flow); | ||
215 | |||
216 | TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len); | ||
217 | if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) { | ||
218 | TRACE_ABORT(-EIO, ft_t_err, | ||
219 | "failed: not busy, failure or wrong unit"); | ||
220 | } | ||
221 | old_sigmask = current->blocked; /* save mask */ | ||
222 | sigfillset(¤t->blocked); | ||
223 | result = _zft_read(buff, req_len); | ||
224 | current->blocked = old_sigmask; /* restore mask */ | ||
225 | TRACE(ft_t_data_flow, "return with count: %d", result); | ||
226 | TRACE_EXIT result; | ||
227 | } | ||
228 | |||
229 | /* Write to tape device | ||
230 | */ | ||
231 | static ssize_t zft_write(struct file *fp, const char __user *buff, | ||
232 | size_t req_len, loff_t *ppos) | ||
233 | { | ||
234 | int result = -EIO; | ||
235 | sigset_t old_sigmask; | ||
236 | struct inode *ino = fp->f_dentry->d_inode; | ||
237 | TRACE_FUN(ft_t_flow); | ||
238 | |||
239 | TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len); | ||
240 | if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) { | ||
241 | TRACE_ABORT(-EIO, ft_t_err, | ||
242 | "failed: not busy, failure or wrong unit"); | ||
243 | } | ||
244 | old_sigmask = current->blocked; /* save mask */ | ||
245 | sigfillset(¤t->blocked); | ||
246 | result = _zft_write(buff, req_len); | ||
247 | current->blocked = old_sigmask; /* restore mask */ | ||
248 | TRACE(ft_t_data_flow, "return with count: %d", result); | ||
249 | TRACE_EXIT result; | ||
250 | } | ||
251 | |||
252 | /* END OF VFS INTERFACE | ||
253 | * | ||
254 | *****************************************************************************/ | ||
255 | |||
256 | /* driver/module initialization | ||
257 | */ | ||
258 | |||
259 | /* the compression module has to call this function to hook into the zftape | ||
260 | * code | ||
261 | */ | ||
262 | int zft_cmpr_register(struct zft_cmpr_ops *new_ops) | ||
263 | { | ||
264 | TRACE_FUN(ft_t_flow); | ||
265 | |||
266 | if (zft_cmpr_ops != NULL) { | ||
267 | TRACE_EXIT -EBUSY; | ||
268 | } else { | ||
269 | zft_cmpr_ops = new_ops; | ||
270 | TRACE_EXIT 0; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | /* lock the zft-compressor() module. | ||
275 | */ | ||
276 | int zft_cmpr_lock(int try_to_load) | ||
277 | { | ||
278 | if (zft_cmpr_ops == NULL) { | ||
279 | #ifdef CONFIG_KMOD | ||
280 | if (try_to_load) { | ||
281 | request_module("zft-compressor"); | ||
282 | if (zft_cmpr_ops == NULL) { | ||
283 | return -ENOSYS; | ||
284 | } | ||
285 | } else { | ||
286 | return -ENOSYS; | ||
287 | } | ||
288 | #else | ||
289 | return -ENOSYS; | ||
290 | #endif | ||
291 | } | ||
292 | (*zft_cmpr_ops->lock)(); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | #ifdef CONFIG_ZFT_COMPRESSOR | ||
297 | extern int zft_compressor_init(void); | ||
298 | #endif | ||
299 | |||
300 | /* Called by modules package when installing the driver or by kernel | ||
301 | * during the initialization phase | ||
302 | */ | ||
303 | int __init zft_init(void) | ||
304 | { | ||
305 | int i; | ||
306 | TRACE_FUN(ft_t_flow); | ||
307 | |||
308 | #ifdef MODULE | ||
309 | printk(KERN_INFO ZFTAPE_VERSION "\n"); | ||
310 | if (TRACE_LEVEL >= ft_t_info) { | ||
311 | printk( | ||
312 | KERN_INFO | ||
313 | "(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n" | ||
314 | KERN_INFO | ||
315 | "vfs interface for ftape floppy tape driver.\n" | ||
316 | KERN_INFO | ||
317 | "Support for QIC-113 compatible volume table, dynamic memory allocation\n" | ||
318 | KERN_INFO | ||
319 | "and builtin compression (lzrw3 algorithm).\n"); | ||
320 | } | ||
321 | #else /* !MODULE */ | ||
322 | /* print a short no-nonsense boot message */ | ||
323 | printk(KERN_INFO ZFTAPE_VERSION "\n"); | ||
324 | #endif /* MODULE */ | ||
325 | TRACE(ft_t_info, "zft_init @ 0x%p", zft_init); | ||
326 | TRACE(ft_t_info, | ||
327 | "installing zftape VFS interface for ftape driver ..."); | ||
328 | TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),); | ||
329 | |||
330 | zft_class = class_create(THIS_MODULE, "zft"); | ||
331 | for (i = 0; i < 4; i++) { | ||
332 | class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i); | ||
333 | class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i); | ||
334 | class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i); | ||
335 | class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i); | ||
336 | class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i); | ||
337 | class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i); | ||
338 | } | ||
339 | |||
340 | #ifdef CONFIG_ZFT_COMPRESSOR | ||
341 | (void)zft_compressor_init(); | ||
342 | #endif | ||
343 | zft_status = ftape_get_status(); /* fetch global data of ftape | ||
344 | * hardware driver | ||
345 | */ | ||
346 | TRACE_EXIT 0; | ||
347 | } | ||
348 | |||
349 | |||
350 | /* Called by modules package when removing the driver | ||
351 | */ | ||
352 | static void zft_exit(void) | ||
353 | { | ||
354 | int i; | ||
355 | TRACE_FUN(ft_t_flow); | ||
356 | |||
357 | if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) { | ||
358 | TRACE(ft_t_warn, "failed"); | ||
359 | } else { | ||
360 | TRACE(ft_t_info, "successful"); | ||
361 | } | ||
362 | for (i = 0; i < 4; i++) { | ||
363 | class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i)); | ||
364 | class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4)); | ||
365 | class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16)); | ||
366 | class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20)); | ||
367 | class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32)); | ||
368 | class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36)); | ||
369 | } | ||
370 | class_destroy(zft_class); | ||
371 | zft_uninit_mem(); /* release remaining memory, if any */ | ||
372 | printk(KERN_INFO "zftape successfully unloaded.\n"); | ||
373 | TRACE_EXIT; | ||
374 | } | ||
375 | |||
376 | module_init(zft_init); | ||
377 | module_exit(zft_exit); | ||
diff --git a/drivers/char/ftape/zftape/zftape-init.h b/drivers/char/ftape/zftape/zftape-init.h deleted file mode 100644 index 937e5d48c20e..000000000000 --- a/drivers/char/ftape/zftape/zftape-init.h +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_INIT_H | ||
2 | #define _ZFTAPE_INIT_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996, 1997 Claus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-init.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:19:05 $ | ||
25 | * | ||
26 | * This file contains definitions and macro for the vfs | ||
27 | * interface defined by zftape | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <linux/ftape-header-segment.h> | ||
32 | |||
33 | #include "../lowlevel/ftape-tracing.h" | ||
34 | #include "../lowlevel/ftape-ctl.h" | ||
35 | #include "../lowlevel/ftape-read.h" | ||
36 | #include "../lowlevel/ftape-write.h" | ||
37 | #include "../lowlevel/ftape-bsm.h" | ||
38 | #include "../lowlevel/ftape-io.h" | ||
39 | #include "../lowlevel/ftape-buffer.h" | ||
40 | #include "../lowlevel/ftape-format.h" | ||
41 | |||
42 | #include "../zftape/zftape-rw.h" | ||
43 | |||
44 | #ifdef MODULE | ||
45 | #define ftape_status (*zft_status) | ||
46 | #endif | ||
47 | |||
48 | extern const ftape_info *zft_status; /* needed for zftape-vtbl.h */ | ||
49 | |||
50 | #include "../zftape/zftape-vtbl.h" | ||
51 | |||
52 | struct zft_cmpr_ops { | ||
53 | int (*write)(int *write_cnt, | ||
54 | __u8 *dst_buf, const int seg_sz, | ||
55 | const __u8 __user *src_buf, const int req_len, | ||
56 | const zft_position *pos, const zft_volinfo *volume); | ||
57 | int (*read)(int *read_cnt, | ||
58 | __u8 __user *dst_buf, const int req_len, | ||
59 | const __u8 *src_buf, const int seg_sz, | ||
60 | const zft_position *pos, const zft_volinfo *volume); | ||
61 | int (*seek)(unsigned int new_block_pos, | ||
62 | zft_position *pos, const zft_volinfo *volume, | ||
63 | __u8 *buffer); | ||
64 | void (*lock) (void); | ||
65 | void (*reset) (void); | ||
66 | void (*cleanup)(void); | ||
67 | }; | ||
68 | |||
69 | extern struct zft_cmpr_ops *zft_cmpr_ops; | ||
70 | /* zftape-init.c defined global functions. | ||
71 | */ | ||
72 | extern int zft_cmpr_register(struct zft_cmpr_ops *new_ops); | ||
73 | extern int zft_cmpr_lock(int try_to_load); | ||
74 | |||
75 | #endif | ||
76 | |||
77 | |||
diff --git a/drivers/char/ftape/zftape/zftape-read.c b/drivers/char/ftape/zftape/zftape-read.c deleted file mode 100644 index 214bf03dce68..000000000000 --- a/drivers/char/ftape/zftape/zftape-read.c +++ /dev/null | |||
@@ -1,377 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996, 1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-read.c,v $ | ||
20 | * $Revision: 1.2 $ | ||
21 | * $Date: 1997/10/05 19:19:06 $ | ||
22 | * | ||
23 | * This file contains the high level reading code | ||
24 | * for the QIC-117 floppy-tape driver for Linux. | ||
25 | */ | ||
26 | |||
27 | #include <linux/errno.h> | ||
28 | #include <linux/mm.h> | ||
29 | |||
30 | #include <linux/zftape.h> | ||
31 | |||
32 | #include <asm/uaccess.h> | ||
33 | |||
34 | #include "../zftape/zftape-init.h" | ||
35 | #include "../zftape/zftape-eof.h" | ||
36 | #include "../zftape/zftape-ctl.h" | ||
37 | #include "../zftape/zftape-write.h" | ||
38 | #include "../zftape/zftape-read.h" | ||
39 | #include "../zftape/zftape-rw.h" | ||
40 | #include "../zftape/zftape-vtbl.h" | ||
41 | |||
42 | /* Global vars. | ||
43 | */ | ||
44 | int zft_just_before_eof; | ||
45 | |||
46 | /* Local vars. | ||
47 | */ | ||
48 | static int buf_len_rd; | ||
49 | |||
50 | void zft_zap_read_buffers(void) | ||
51 | { | ||
52 | buf_len_rd = 0; | ||
53 | } | ||
54 | |||
55 | int zft_read_header_segments(void) | ||
56 | { | ||
57 | TRACE_FUN(ft_t_flow); | ||
58 | |||
59 | zft_header_read = 0; | ||
60 | TRACE_CATCH(zft_vmalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),); | ||
61 | TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),); | ||
62 | TRACE(ft_t_info, "Segments written since first format: %d", | ||
63 | (int)GET4(zft_hseg_buf, FT_SEG_CNT)); | ||
64 | zft_qic113 = (ft_format_code != fmt_normal && | ||
65 | ft_format_code != fmt_1100ft && | ||
66 | ft_format_code != fmt_425ft); | ||
67 | TRACE(ft_t_info, "ft_first_data_segment: %d, ft_last_data_segment: %d", | ||
68 | ft_first_data_segment, ft_last_data_segment); | ||
69 | zft_capacity = zft_get_capacity(); | ||
70 | zft_old_ftape = zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]); | ||
71 | if (zft_old_ftape) { | ||
72 | TRACE(ft_t_info, | ||
73 | "Found old ftaped tape, emulating eof marks, entering read-only mode"); | ||
74 | zft_ftape_extract_file_marks(zft_hseg_buf); | ||
75 | TRACE_CATCH(zft_fake_volume_headers(zft_eof_map, | ||
76 | zft_nr_eof_marks),); | ||
77 | } else { | ||
78 | /* the specs say that the volume table must be | ||
79 | * initialized with zeroes during formatting, so it | ||
80 | * MUST be readable, i.e. contain vaid ECC | ||
81 | * information. | ||
82 | */ | ||
83 | TRACE_CATCH(ftape_read_segment(ft_first_data_segment, | ||
84 | zft_deblock_buf, | ||
85 | FT_RD_SINGLE),); | ||
86 | TRACE_CATCH(zft_extract_volume_headers(zft_deblock_buf),); | ||
87 | } | ||
88 | zft_header_read = 1; | ||
89 | zft_set_flags(zft_unit); | ||
90 | zft_reset_position(&zft_pos); | ||
91 | TRACE_EXIT 0; | ||
92 | } | ||
93 | |||
94 | int zft_fetch_segment_fraction(const unsigned int segment, void *buffer, | ||
95 | const ft_read_mode_t read_mode, | ||
96 | const unsigned int start, | ||
97 | const unsigned int size) | ||
98 | { | ||
99 | int seg_sz; | ||
100 | TRACE_FUN(ft_t_flow); | ||
101 | |||
102 | if (segment == zft_deblock_segment) { | ||
103 | TRACE(ft_t_data_flow, | ||
104 | "re-using segment %d already in deblock buffer", | ||
105 | segment); | ||
106 | seg_sz = zft_get_seg_sz(segment); | ||
107 | if (start > seg_sz) { | ||
108 | TRACE_ABORT(-EINVAL, ft_t_bug, | ||
109 | "trying to read beyond end of segment:\n" | ||
110 | KERN_INFO "seg_sz : %d\n" | ||
111 | KERN_INFO "start : %d\n" | ||
112 | KERN_INFO "segment: %d", | ||
113 | seg_sz, start, segment); | ||
114 | } | ||
115 | if ((start + size) > seg_sz) { | ||
116 | TRACE_EXIT seg_sz - start; | ||
117 | } | ||
118 | TRACE_EXIT size; | ||
119 | } | ||
120 | seg_sz = ftape_read_segment_fraction(segment, buffer, read_mode, | ||
121 | start, size); | ||
122 | TRACE(ft_t_data_flow, "segment %d, result %d", segment, seg_sz); | ||
123 | if ((int)seg_sz >= 0 && start == 0 && size == FT_SEGMENT_SIZE) { | ||
124 | /* this implicitly assumes that we are always called with | ||
125 | * buffer == zft_deblock_buf | ||
126 | */ | ||
127 | zft_deblock_segment = segment; | ||
128 | } else { | ||
129 | zft_deblock_segment = -1; | ||
130 | } | ||
131 | TRACE_EXIT seg_sz; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * out: | ||
136 | * | ||
137 | * int *read_cnt: the number of bytes we removed from the | ||
138 | * zft_deblock_buf (result) | ||
139 | * | ||
140 | * int *to_do : the remaining size of the read-request. Is changed. | ||
141 | * | ||
142 | * in: | ||
143 | * | ||
144 | * char *buff : buff is the address of the upper part of the user | ||
145 | * buffer, that hasn't been filled with data yet. | ||
146 | * int buf_pos_read: copy of buf_pos_rd | ||
147 | * int buf_len_read: copy of buf_len_rd | ||
148 | * char *zft_deblock_buf: ftape_zft_deblock_buf | ||
149 | * | ||
150 | * returns the amount of data actually copied to the user-buffer | ||
151 | * | ||
152 | * to_do MUST NOT SHRINK except to indicate an EOT. In this case to_do | ||
153 | * has to be set to 0. We cannot return -ENOSPC, because we return the | ||
154 | * amount of data actually * copied to the user-buffer | ||
155 | */ | ||
156 | static int zft_simple_read (int *read_cnt, | ||
157 | __u8 __user *dst_buf, | ||
158 | const int to_do, | ||
159 | const __u8 *src_buf, | ||
160 | const int seg_sz, | ||
161 | const zft_position *pos, | ||
162 | const zft_volinfo *volume) | ||
163 | { | ||
164 | TRACE_FUN(ft_t_flow); | ||
165 | |||
166 | if (seg_sz - pos->seg_byte_pos < to_do) { | ||
167 | *read_cnt = seg_sz - pos->seg_byte_pos; | ||
168 | } else { | ||
169 | *read_cnt = to_do; | ||
170 | } | ||
171 | if (copy_to_user(dst_buf, | ||
172 | src_buf + pos->seg_byte_pos, *read_cnt) != 0) { | ||
173 | TRACE_EXIT -EFAULT; | ||
174 | } | ||
175 | TRACE(ft_t_noise, "nr bytes just read: %d", *read_cnt); | ||
176 | TRACE_EXIT *read_cnt; | ||
177 | } | ||
178 | |||
179 | /* req_len: gets clipped due to EOT of EOF. | ||
180 | * req_clipped: is a flag indicating whether req_len was clipped or not | ||
181 | * volume: contains information on current volume (blk_sz etc.) | ||
182 | */ | ||
183 | static int check_read_access(int *req_len, | ||
184 | const zft_volinfo **volume, | ||
185 | int *req_clipped, | ||
186 | const zft_position *pos) | ||
187 | { | ||
188 | static __s64 remaining; | ||
189 | static int eod; | ||
190 | TRACE_FUN(ft_t_flow); | ||
191 | |||
192 | if (zft_io_state != zft_reading) { | ||
193 | if (zft_offline) { /* offline includes no_tape */ | ||
194 | TRACE_ABORT(-ENXIO, ft_t_warn, | ||
195 | "tape is offline or no cartridge"); | ||
196 | } | ||
197 | if (!ft_formatted) { | ||
198 | TRACE_ABORT(-EACCES, | ||
199 | ft_t_warn, "tape is not formatted"); | ||
200 | } | ||
201 | /* now enter defined state, read header segment if not | ||
202 | * already done and flush write buffers | ||
203 | */ | ||
204 | TRACE_CATCH(zft_def_idle_state(),); | ||
205 | zft_io_state = zft_reading; | ||
206 | if (zft_tape_at_eod(pos)) { | ||
207 | eod = 1; | ||
208 | TRACE_EXIT 1; | ||
209 | } | ||
210 | eod = 0; | ||
211 | *volume = zft_find_volume(pos->seg_pos); | ||
212 | /* get the space left until EOF */ | ||
213 | remaining = zft_check_for_eof(*volume, pos); | ||
214 | buf_len_rd = 0; | ||
215 | TRACE(ft_t_noise, "remaining: " LL_X ", vol_no: %d", | ||
216 | LL(remaining), (*volume)->count); | ||
217 | } else if (zft_tape_at_eod(pos)) { | ||
218 | if (++eod > 2) { | ||
219 | TRACE_EXIT -EIO; /* st.c also returns -EIO */ | ||
220 | } else { | ||
221 | TRACE_EXIT 1; | ||
222 | } | ||
223 | } | ||
224 | if ((*req_len % (*volume)->blk_sz) != 0) { | ||
225 | /* this message is informational only. The user gets the | ||
226 | * proper return value | ||
227 | */ | ||
228 | TRACE_ABORT(-EINVAL, ft_t_info, | ||
229 | "req_len %d not a multiple of block size %d", | ||
230 | *req_len, (*volume)->blk_sz); | ||
231 | } | ||
232 | /* As GNU tar doesn't accept partial read counts when the | ||
233 | * multiple volume flag is set, we make sure to return the | ||
234 | * requested amount of data. Except, of course, at the end of | ||
235 | * the tape or file mark. | ||
236 | */ | ||
237 | remaining -= *req_len; | ||
238 | if (remaining <= 0) { | ||
239 | TRACE(ft_t_noise, | ||
240 | "clipped request from %d to %d.", | ||
241 | *req_len, (int)(*req_len + remaining)); | ||
242 | *req_len += remaining; | ||
243 | *req_clipped = 1; | ||
244 | } else { | ||
245 | *req_clipped = 0; | ||
246 | } | ||
247 | TRACE_EXIT 0; | ||
248 | } | ||
249 | |||
250 | /* this_segs_size: the current segment's size. | ||
251 | * buff: the USER-SPACE buffer provided by the calling function. | ||
252 | * req_len: how much data should be read at most. | ||
253 | * volume: contains information on current volume (blk_sz etc.) | ||
254 | */ | ||
255 | static int empty_deblock_buf(__u8 __user *usr_buf, const int req_len, | ||
256 | const __u8 *src_buf, const int seg_sz, | ||
257 | zft_position *pos, | ||
258 | const zft_volinfo *volume) | ||
259 | { | ||
260 | int cnt; | ||
261 | int result = 0; | ||
262 | TRACE_FUN(ft_t_flow); | ||
263 | |||
264 | TRACE(ft_t_data_flow, "this_segs_size: %d", seg_sz); | ||
265 | if (zft_use_compression && volume->use_compression) { | ||
266 | TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),); | ||
267 | TRACE_CATCH(result= (*zft_cmpr_ops->read)(&cnt, | ||
268 | usr_buf, req_len, | ||
269 | src_buf, seg_sz, | ||
270 | pos, volume),); | ||
271 | } else { | ||
272 | TRACE_CATCH(result= zft_simple_read (&cnt, | ||
273 | usr_buf, req_len, | ||
274 | src_buf, seg_sz, | ||
275 | pos, volume),); | ||
276 | } | ||
277 | pos->volume_pos += result; | ||
278 | pos->tape_pos += cnt; | ||
279 | pos->seg_byte_pos += cnt; | ||
280 | buf_len_rd -= cnt; /* remaining bytes in buffer */ | ||
281 | TRACE(ft_t_data_flow, "buf_len_rd: %d, cnt: %d", buf_len_rd, cnt); | ||
282 | if(pos->seg_byte_pos >= seg_sz) { | ||
283 | pos->seg_pos++; | ||
284 | pos->seg_byte_pos = 0; | ||
285 | } | ||
286 | TRACE(ft_t_data_flow, "bytes moved out of deblock-buffer: %d", cnt); | ||
287 | TRACE_EXIT result; | ||
288 | } | ||
289 | |||
290 | |||
291 | /* note: we store the segment id of the segment that is inside the | ||
292 | * deblock buffer. This spares a lot of ftape_read_segment()s when we | ||
293 | * use small block-sizes. The block-size may be 1kb (SECTOR_SIZE). In | ||
294 | * this case a MTFSR 28 maybe still inside the same segment. | ||
295 | */ | ||
296 | int _zft_read(char __user *buff, int req_len) | ||
297 | { | ||
298 | int req_clipped; | ||
299 | int result = 0; | ||
300 | int bytes_read = 0; | ||
301 | static unsigned int seg_sz = 0; | ||
302 | static const zft_volinfo *volume = NULL; | ||
303 | TRACE_FUN(ft_t_flow); | ||
304 | |||
305 | zft_resid = req_len; | ||
306 | result = check_read_access(&req_len, &volume, | ||
307 | &req_clipped, &zft_pos); | ||
308 | switch(result) { | ||
309 | case 0: | ||
310 | break; /* nothing special */ | ||
311 | case 1: | ||
312 | TRACE(ft_t_noise, "EOD reached"); | ||
313 | TRACE_EXIT 0; /* EOD */ | ||
314 | default: | ||
315 | TRACE_ABORT(result, ft_t_noise, | ||
316 | "check_read_access() failed with result %d", | ||
317 | result); | ||
318 | TRACE_EXIT result; | ||
319 | } | ||
320 | while (req_len > 0) { | ||
321 | /* Allow escape from this loop on signal ! | ||
322 | */ | ||
323 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
324 | /* buf_len_rd == 0 means that we need to read a new | ||
325 | * segment. | ||
326 | */ | ||
327 | if (buf_len_rd == 0) { | ||
328 | while((result = zft_fetch_segment(zft_pos.seg_pos, | ||
329 | zft_deblock_buf, | ||
330 | FT_RD_AHEAD)) == 0) { | ||
331 | zft_pos.seg_pos ++; | ||
332 | zft_pos.seg_byte_pos = 0; | ||
333 | } | ||
334 | if (result < 0) { | ||
335 | zft_resid -= bytes_read; | ||
336 | TRACE_ABORT(result, ft_t_noise, | ||
337 | "zft_fetch_segment(): %d", | ||
338 | result); | ||
339 | } | ||
340 | seg_sz = result; | ||
341 | buf_len_rd = seg_sz - zft_pos.seg_byte_pos; | ||
342 | } | ||
343 | TRACE_CATCH(result = empty_deblock_buf(buff, | ||
344 | req_len, | ||
345 | zft_deblock_buf, | ||
346 | seg_sz, | ||
347 | &zft_pos, | ||
348 | volume), | ||
349 | zft_resid -= bytes_read); | ||
350 | TRACE(ft_t_data_flow, "bytes just read: %d", result); | ||
351 | bytes_read += result; /* what we got so far */ | ||
352 | buff += result; /* index in user-buffer */ | ||
353 | req_len -= result; /* what's left from req_len */ | ||
354 | } /* while (req_len > 0) */ | ||
355 | if (req_clipped) { | ||
356 | TRACE(ft_t_data_flow, | ||
357 | "maybe partial count because of eof mark"); | ||
358 | if (zft_just_before_eof && bytes_read == 0) { | ||
359 | /* req_len was > 0, but user didn't get | ||
360 | * anything the user has read in the eof-mark | ||
361 | */ | ||
362 | zft_move_past_eof(&zft_pos); | ||
363 | ftape_abort_operation(); | ||
364 | } else { | ||
365 | /* don't skip to the next file before the user | ||
366 | * tried to read a second time past EOF Just | ||
367 | * mark that we are at EOF and maybe decrement | ||
368 | * zft_seg_pos to stay in the same volume; | ||
369 | */ | ||
370 | zft_just_before_eof = 1; | ||
371 | zft_position_before_eof(&zft_pos, volume); | ||
372 | TRACE(ft_t_noise, "just before eof"); | ||
373 | } | ||
374 | } | ||
375 | zft_resid -= result; /* for MTSTATUS */ | ||
376 | TRACE_EXIT bytes_read; | ||
377 | } | ||
diff --git a/drivers/char/ftape/zftape/zftape-read.h b/drivers/char/ftape/zftape/zftape-read.h deleted file mode 100644 index 42941de0c23a..000000000000 --- a/drivers/char/ftape/zftape/zftape-read.h +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_READ_H | ||
2 | #define _ZFTAPE_READ_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996, 1997 Claus-Justus Heine | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-read.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:19:07 $ | ||
25 | * | ||
26 | * This file contains the definitions for the read functions | ||
27 | * for the zftape driver for Linux. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include "../lowlevel/ftape-read.h" | ||
32 | |||
33 | /* ftape-read.c defined global vars. | ||
34 | */ | ||
35 | extern int zft_just_before_eof; | ||
36 | |||
37 | /* ftape-read.c defined global functions. | ||
38 | */ | ||
39 | extern void zft_zap_read_buffers(void); | ||
40 | extern int zft_read_header_segments(void); | ||
41 | extern int zft_fetch_segment_fraction(const unsigned int segment, | ||
42 | void *buffer, | ||
43 | const ft_read_mode_t read_mode, | ||
44 | const unsigned int start, | ||
45 | const unsigned int size); | ||
46 | #define zft_fetch_segment(segment, address, read_mode) \ | ||
47 | zft_fetch_segment_fraction(segment, address, read_mode, \ | ||
48 | 0, FT_SEGMENT_SIZE) | ||
49 | /* hook for the VFS interface | ||
50 | */ | ||
51 | extern int _zft_read(char __user *buff, int req_len); | ||
52 | |||
53 | #endif /* _ZFTAPE_READ_H */ | ||
diff --git a/drivers/char/ftape/zftape/zftape-rw.c b/drivers/char/ftape/zftape/zftape-rw.c deleted file mode 100644 index dab634686885..000000000000 --- a/drivers/char/ftape/zftape/zftape-rw.c +++ /dev/null | |||
@@ -1,375 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996, 1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.c,v $ | ||
20 | * $Revision: 1.2 $ | ||
21 | * $Date: 1997/10/05 19:19:08 $ | ||
22 | * | ||
23 | * This file contains some common code for the r/w code for | ||
24 | * zftape. | ||
25 | */ | ||
26 | |||
27 | #include <linux/errno.h> | ||
28 | #include <linux/mm.h> | ||
29 | |||
30 | #include <linux/zftape.h> | ||
31 | #include "../zftape/zftape-init.h" | ||
32 | #include "../zftape/zftape-eof.h" | ||
33 | #include "../zftape/zftape-ctl.h" | ||
34 | #include "../zftape/zftape-write.h" | ||
35 | #include "../zftape/zftape-read.h" | ||
36 | #include "../zftape/zftape-rw.h" | ||
37 | #include "../zftape/zftape-vtbl.h" | ||
38 | |||
39 | /* Global vars. | ||
40 | */ | ||
41 | |||
42 | __u8 *zft_deblock_buf; | ||
43 | __u8 *zft_hseg_buf; | ||
44 | int zft_deblock_segment = -1; | ||
45 | zft_status_enum zft_io_state = zft_idle; | ||
46 | int zft_header_changed; | ||
47 | int zft_qic113; /* conform to old specs. and old zftape */ | ||
48 | int zft_use_compression; | ||
49 | zft_position zft_pos = { | ||
50 | -1, /* seg_pos */ | ||
51 | 0, /* seg_byte_pos */ | ||
52 | 0, /* tape_pos */ | ||
53 | 0 /* volume_pos */ | ||
54 | }; | ||
55 | unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ; | ||
56 | __s64 zft_capacity; | ||
57 | |||
58 | unsigned int zft_written_segments; | ||
59 | int zft_label_changed; | ||
60 | |||
61 | /* Local vars. | ||
62 | */ | ||
63 | |||
64 | unsigned int zft_get_seg_sz(unsigned int segment) | ||
65 | { | ||
66 | int size; | ||
67 | TRACE_FUN(ft_t_any); | ||
68 | |||
69 | size = FT_SEGMENT_SIZE - | ||
70 | count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE; | ||
71 | if (size > 0) { | ||
72 | TRACE_EXIT (unsigned)size; | ||
73 | } else { | ||
74 | TRACE_EXIT 0; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | /* ftape_set_flags(). Claus-Justus Heine, 1994/1995 | ||
79 | */ | ||
80 | void zft_set_flags(unsigned minor_unit) | ||
81 | { | ||
82 | TRACE_FUN(ft_t_flow); | ||
83 | |||
84 | zft_use_compression = zft_qic_mode = 0; | ||
85 | switch (minor_unit & ZFT_MINOR_OP_MASK) { | ||
86 | case (ZFT_Q80_MODE | ZFT_ZIP_MODE): | ||
87 | case ZFT_ZIP_MODE: | ||
88 | zft_use_compression = 1; | ||
89 | case 0: | ||
90 | case ZFT_Q80_MODE: | ||
91 | zft_qic_mode = 1; | ||
92 | if (zft_mt_compression) { /* override the default */ | ||
93 | zft_use_compression = 1; | ||
94 | } | ||
95 | break; | ||
96 | case ZFT_RAW_MODE: | ||
97 | TRACE(ft_t_noise, "switching to raw mode"); | ||
98 | break; | ||
99 | default: | ||
100 | TRACE(ft_t_warn, "Warning:\n" | ||
101 | KERN_INFO "Wrong combination of minor device bits.\n" | ||
102 | KERN_INFO "Switching to raw read-only mode."); | ||
103 | zft_write_protected = 1; | ||
104 | break; | ||
105 | } | ||
106 | TRACE_EXIT; | ||
107 | } | ||
108 | |||
109 | /* computes the segment and byte offset inside the segment | ||
110 | * corresponding to tape_pos. | ||
111 | * | ||
112 | * tape_pos gives the offset in bytes from the beginning of the | ||
113 | * ft_first_data_segment *seg_byte_pos is the offset in the current | ||
114 | * segment in bytes | ||
115 | * | ||
116 | * Of, if this routine was called often one should cache the last data | ||
117 | * pos it was called with, but actually this is only needed in | ||
118 | * ftape_seek_block(), that is, almost never. | ||
119 | */ | ||
120 | int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos) | ||
121 | { | ||
122 | int segment; | ||
123 | int seg_sz; | ||
124 | TRACE_FUN(ft_t_flow); | ||
125 | |||
126 | if (tape_pos == 0) { | ||
127 | *seg_byte_pos = 0; | ||
128 | segment = ft_first_data_segment; | ||
129 | } else { | ||
130 | seg_sz = 0; | ||
131 | |||
132 | for (segment = ft_first_data_segment; | ||
133 | ((tape_pos > 0) && (segment <= ft_last_data_segment)); | ||
134 | segment++) { | ||
135 | seg_sz = zft_get_seg_sz(segment); | ||
136 | tape_pos -= seg_sz; | ||
137 | } | ||
138 | if(tape_pos >= 0) { | ||
139 | /* the case tape_pos > != 0 means that the | ||
140 | * argument tape_pos lies beyond the EOT. | ||
141 | */ | ||
142 | *seg_byte_pos= 0; | ||
143 | } else { /* tape_pos < 0 */ | ||
144 | segment--; | ||
145 | *seg_byte_pos= tape_pos + seg_sz; | ||
146 | } | ||
147 | } | ||
148 | TRACE_EXIT(segment); | ||
149 | } | ||
150 | |||
151 | /* ftape_calc_tape_pos(). | ||
152 | * | ||
153 | * computes the offset in bytes from the beginning of the | ||
154 | * ft_first_data_segment inverse to ftape_calc_seg_byte_coord | ||
155 | * | ||
156 | * We should do some caching. But how: | ||
157 | * | ||
158 | * Each time the header segments are read in, this routine is called | ||
159 | * with ft_tracks_per_tape*segments_per_track argumnet. So this should be | ||
160 | * the time to reset the cache. | ||
161 | * | ||
162 | * Also, it might be in the future that the bad sector map gets | ||
163 | * changed. -> reset the cache | ||
164 | */ | ||
165 | static int seg_pos; | ||
166 | static __s64 tape_pos; | ||
167 | |||
168 | __s64 zft_get_capacity(void) | ||
169 | { | ||
170 | seg_pos = ft_first_data_segment; | ||
171 | tape_pos = 0; | ||
172 | |||
173 | while (seg_pos <= ft_last_data_segment) { | ||
174 | tape_pos += zft_get_seg_sz(seg_pos ++); | ||
175 | } | ||
176 | return tape_pos; | ||
177 | } | ||
178 | |||
179 | __s64 zft_calc_tape_pos(int segment) | ||
180 | { | ||
181 | int d1, d2, d3; | ||
182 | TRACE_FUN(ft_t_any); | ||
183 | |||
184 | if (segment > ft_last_data_segment) { | ||
185 | TRACE_EXIT zft_capacity; | ||
186 | } | ||
187 | if (segment < ft_first_data_segment) { | ||
188 | TRACE_EXIT 0; | ||
189 | } | ||
190 | d2 = segment - seg_pos; | ||
191 | if (-d2 > 10) { | ||
192 | d1 = segment - ft_first_data_segment; | ||
193 | if (-d2 > d1) { | ||
194 | tape_pos = 0; | ||
195 | seg_pos = ft_first_data_segment; | ||
196 | d2 = d1; | ||
197 | } | ||
198 | } | ||
199 | if (d2 > 10) { | ||
200 | d3 = ft_last_data_segment - segment; | ||
201 | if (d2 > d3) { | ||
202 | tape_pos = zft_capacity; | ||
203 | seg_pos = ft_last_data_segment + 1; | ||
204 | d2 = -d3; | ||
205 | } | ||
206 | } | ||
207 | if (d2 > 0) { | ||
208 | while (seg_pos < segment) { | ||
209 | tape_pos += zft_get_seg_sz(seg_pos++); | ||
210 | } | ||
211 | } else { | ||
212 | while (seg_pos > segment) { | ||
213 | tape_pos -= zft_get_seg_sz(--seg_pos); | ||
214 | } | ||
215 | } | ||
216 | TRACE(ft_t_noise, "new cached pos: %d", seg_pos); | ||
217 | |||
218 | TRACE_EXIT tape_pos; | ||
219 | } | ||
220 | |||
221 | /* copy Z-label string to buffer, keeps track of the correct offset in | ||
222 | * `buffer' | ||
223 | */ | ||
224 | void zft_update_label(__u8 *buffer) | ||
225 | { | ||
226 | TRACE_FUN(ft_t_flow); | ||
227 | |||
228 | if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL, | ||
229 | sizeof(ZFTAPE_LABEL)-1) != 0) { | ||
230 | TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"", | ||
231 | &buffer[FT_LABEL], ZFTAPE_LABEL); | ||
232 | strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL); | ||
233 | memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ', | ||
234 | FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1)); | ||
235 | PUT4(buffer, FT_LABEL_DATE, 0); | ||
236 | zft_label_changed = zft_header_changed = 1; /* changed */ | ||
237 | } | ||
238 | TRACE_EXIT; | ||
239 | } | ||
240 | |||
241 | int zft_verify_write_segments(unsigned int segment, | ||
242 | __u8 *data, size_t size, | ||
243 | __u8 *buffer) | ||
244 | { | ||
245 | int result; | ||
246 | __u8 *write_buf; | ||
247 | __u8 *src_buf; | ||
248 | int single; | ||
249 | int seg_pos; | ||
250 | int seg_sz; | ||
251 | int remaining; | ||
252 | ft_write_mode_t write_mode; | ||
253 | TRACE_FUN(ft_t_flow); | ||
254 | |||
255 | seg_pos = segment; | ||
256 | seg_sz = zft_get_seg_sz(seg_pos); | ||
257 | src_buf = data; | ||
258 | single = size <= seg_sz; | ||
259 | remaining = size; | ||
260 | do { | ||
261 | TRACE(ft_t_noise, "\n" | ||
262 | KERN_INFO "remaining: %d\n" | ||
263 | KERN_INFO "seg_sz : %d\n" | ||
264 | KERN_INFO "segment : %d", | ||
265 | remaining, seg_sz, seg_pos); | ||
266 | if (remaining == seg_sz) { | ||
267 | write_buf = src_buf; | ||
268 | write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI; | ||
269 | remaining = 0; | ||
270 | } else if (remaining > seg_sz) { | ||
271 | write_buf = src_buf; | ||
272 | write_mode = FT_WR_ASYNC; /* don't start tape */ | ||
273 | remaining -= seg_sz; | ||
274 | } else { /* remaining < seg_sz */ | ||
275 | write_buf = buffer; | ||
276 | memcpy(write_buf, src_buf, remaining); | ||
277 | memset(&write_buf[remaining],'\0',seg_sz-remaining); | ||
278 | write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI; | ||
279 | remaining = 0; | ||
280 | } | ||
281 | if ((result = ftape_write_segment(seg_pos, | ||
282 | write_buf, | ||
283 | write_mode)) != seg_sz) { | ||
284 | TRACE(ft_t_err, "Error: " | ||
285 | "Couldn't write segment %d", seg_pos); | ||
286 | TRACE_EXIT result < 0 ? result : -EIO; /* bail out */ | ||
287 | } | ||
288 | zft_written_segments ++; | ||
289 | seg_sz = zft_get_seg_sz(++seg_pos); | ||
290 | src_buf += result; | ||
291 | } while (remaining > 0); | ||
292 | if (ftape_get_status()->fti_state == writing) { | ||
293 | TRACE_CATCH(ftape_loop_until_writes_done(),); | ||
294 | TRACE_CATCH(ftape_abort_operation(),); | ||
295 | zft_prevent_flush(); | ||
296 | } | ||
297 | seg_pos = segment; | ||
298 | src_buf = data; | ||
299 | remaining = size; | ||
300 | do { | ||
301 | TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer, | ||
302 | single ? FT_RD_SINGLE | ||
303 | : FT_RD_AHEAD),); | ||
304 | if (memcmp(src_buf, buffer, | ||
305 | remaining > result ? result : remaining) != 0) { | ||
306 | TRACE_ABORT(-EIO, ft_t_err, | ||
307 | "Failed to verify written segment %d", | ||
308 | seg_pos); | ||
309 | } | ||
310 | remaining -= result; | ||
311 | TRACE(ft_t_noise, "verify successful:\n" | ||
312 | KERN_INFO "segment : %d\n" | ||
313 | KERN_INFO "segsize : %d\n" | ||
314 | KERN_INFO "remaining: %d", | ||
315 | seg_pos, result, remaining); | ||
316 | src_buf += seg_sz; | ||
317 | seg_pos++; | ||
318 | } while (remaining > 0); | ||
319 | TRACE_EXIT size; | ||
320 | } | ||
321 | |||
322 | |||
323 | /* zft_erase(). implemented compression-handling | ||
324 | * | ||
325 | * calculate the first data-segment when using/not using compression. | ||
326 | * | ||
327 | * update header-segment and compression-map-segment. | ||
328 | */ | ||
329 | int zft_erase(void) | ||
330 | { | ||
331 | int result = 0; | ||
332 | TRACE_FUN(ft_t_flow); | ||
333 | |||
334 | if (!zft_header_read) { | ||
335 | TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf, | ||
336 | FT_SEGMENT_SIZE),); | ||
337 | /* no need to read the vtbl and compression map */ | ||
338 | TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),); | ||
339 | if ((zft_old_ftape = | ||
340 | zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) { | ||
341 | zft_ftape_extract_file_marks(zft_hseg_buf); | ||
342 | } | ||
343 | TRACE(ft_t_noise, | ||
344 | "ft_first_data_segment: %d, ft_last_data_segment: %d", | ||
345 | ft_first_data_segment, ft_last_data_segment); | ||
346 | zft_qic113 = (ft_format_code != fmt_normal && | ||
347 | ft_format_code != fmt_1100ft && | ||
348 | ft_format_code != fmt_425ft); | ||
349 | } | ||
350 | if (zft_old_ftape) { | ||
351 | zft_clear_ftape_file_marks(); | ||
352 | zft_old_ftape = 0; /* no longer old ftape */ | ||
353 | } | ||
354 | PUT2(zft_hseg_buf, FT_CMAP_START, 0); | ||
355 | zft_volume_table_changed = 1; | ||
356 | zft_capacity = zft_get_capacity(); | ||
357 | zft_init_vtbl(); | ||
358 | /* the rest must be done in ftape_update_header_segments | ||
359 | */ | ||
360 | zft_header_read = 1; | ||
361 | zft_header_changed = 1; /* force update of timestamp */ | ||
362 | result = zft_update_header_segments(); | ||
363 | |||
364 | ftape_abort_operation(); | ||
365 | |||
366 | zft_reset_position(&zft_pos); | ||
367 | zft_set_flags (zft_unit); | ||
368 | TRACE_EXIT result; | ||
369 | } | ||
370 | |||
371 | unsigned int zft_get_time(void) | ||
372 | { | ||
373 | unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */ | ||
374 | return date; | ||
375 | } | ||
diff --git a/drivers/char/ftape/zftape/zftape-rw.h b/drivers/char/ftape/zftape/zftape-rw.h deleted file mode 100644 index 1ceec22b60bd..000000000000 --- a/drivers/char/ftape/zftape/zftape-rw.h +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_RW_H | ||
2 | #define _ZFTAPE_RW_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996, 1997 Claus-Justus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:19:09 $ | ||
25 | * | ||
26 | * This file contains the definitions for the read and write | ||
27 | * functions for the QIC-117 floppy-tape driver for Linux. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include "../zftape/zftape-buffers.h" | ||
32 | |||
33 | #define SEGMENTS_PER_TAPE (ft_segments_per_track * ft_tracks_per_tape) | ||
34 | |||
35 | /* QIC-113 Rev. G says that `a maximum of 63488 raw bytes may be | ||
36 | * compressed into a single frame'. | ||
37 | * Maybe we should stick to 32kb to make it more `beautiful' | ||
38 | */ | ||
39 | #define ZFT_MAX_BLK_SZ (62*1024) /* bytes */ | ||
40 | #if !defined(CONFIG_ZFT_DFLT_BLK_SZ) | ||
41 | # define CONFIG_ZFT_DFLT_BLK_SZ (10*1024) /* bytes, default of gnu tar */ | ||
42 | #elif CONFIG_ZFT_DFLT_BLK_SZ == 0 | ||
43 | # undef CONFIG_ZFT_DFLT_BLK_SZ | ||
44 | # define CONFIG_ZFT_DFLT_BLK_SZ 1 | ||
45 | #elif (CONFIG_ZFT_DFLT_BLK_SZ % 1024) != 0 | ||
46 | # error CONFIG_ZFT_DFLT_BLK_SZ must be 1 or a multiple of 1024 | ||
47 | #endif | ||
48 | /* The *optional* compression routines need some overhead per tape | ||
49 | * block for their purposes. Instead of asking the actual compression | ||
50 | * implementation how much it needs, we restrict this overhead to be | ||
51 | * maximal of ZFT_CMPT_OVERHEAD size. We need this for EOT | ||
52 | * conditions. The tape is assumed to be logical at EOT when the | ||
53 | * distance from the physical EOT is less than | ||
54 | * one tape block + ZFT_CMPR_OVERHEAD | ||
55 | */ | ||
56 | #define ZFT_CMPR_OVERHEAD 16 /* bytes */ | ||
57 | |||
58 | typedef enum | ||
59 | { | ||
60 | zft_idle = 0, | ||
61 | zft_reading, | ||
62 | zft_writing, | ||
63 | } zft_status_enum; | ||
64 | |||
65 | typedef struct /* all values measured in bytes */ | ||
66 | { | ||
67 | int seg_pos; /* segment currently positioned at */ | ||
68 | int seg_byte_pos; /* offset in current segment */ | ||
69 | __s64 tape_pos; /* real offset from BOT */ | ||
70 | __s64 volume_pos; /* pos. in uncompressed data stream in | ||
71 | * current volume | ||
72 | */ | ||
73 | } zft_position; | ||
74 | |||
75 | extern zft_position zft_pos; | ||
76 | extern __u8 *zft_deblock_buf; | ||
77 | extern __u8 *zft_hseg_buf; | ||
78 | extern int zft_deblock_segment; | ||
79 | extern zft_status_enum zft_io_state; | ||
80 | extern int zft_header_changed; | ||
81 | extern int zft_qic113; /* conform to old specs. and old zftape */ | ||
82 | extern int zft_use_compression; | ||
83 | extern unsigned int zft_blk_sz; | ||
84 | extern __s64 zft_capacity; | ||
85 | extern unsigned int zft_written_segments; | ||
86 | extern int zft_label_changed; | ||
87 | |||
88 | /* zftape-rw.c exported functions | ||
89 | */ | ||
90 | extern unsigned int zft_get_seg_sz(unsigned int segment); | ||
91 | extern void zft_set_flags(unsigned int minor_unit); | ||
92 | extern int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos); | ||
93 | extern __s64 zft_calc_tape_pos(int segment); | ||
94 | extern __s64 zft_get_capacity(void); | ||
95 | extern void zft_update_label(__u8 *buffer); | ||
96 | extern int zft_erase(void); | ||
97 | extern int zft_verify_write_segments(unsigned int segment, | ||
98 | __u8 *data, size_t size, __u8 *buffer); | ||
99 | extern unsigned int zft_get_time(void); | ||
100 | #endif /* _ZFTAPE_RW_H */ | ||
101 | |||
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.c b/drivers/char/ftape/zftape/zftape-vtbl.c deleted file mode 100644 index ad7f8be6340b..000000000000 --- a/drivers/char/ftape/zftape/zftape-vtbl.c +++ /dev/null | |||
@@ -1,757 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 1995-1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 2, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
17 | USA. | ||
18 | |||
19 | * | ||
20 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.c,v $ | ||
21 | * $Revision: 1.7.6.1 $ | ||
22 | * $Date: 1997/11/24 13:48:31 $ | ||
23 | * | ||
24 | * This file defines a volume table as defined in various QIC | ||
25 | * standards. | ||
26 | * | ||
27 | * This is a minimal implementation, just allowing ordinary DOS | ||
28 | * :( prgrams to identify the cartridge as used. | ||
29 | */ | ||
30 | |||
31 | #include <linux/errno.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | #include <linux/zftape.h> | ||
36 | #include "../zftape/zftape-init.h" | ||
37 | #include "../zftape/zftape-eof.h" | ||
38 | #include "../zftape/zftape-ctl.h" | ||
39 | #include "../zftape/zftape-write.h" | ||
40 | #include "../zftape/zftape-read.h" | ||
41 | #include "../zftape/zftape-rw.h" | ||
42 | #include "../zftape/zftape-vtbl.h" | ||
43 | |||
44 | #define ZFT_CMAP_HACK /* leave this defined to hide the compression map */ | ||
45 | |||
46 | /* | ||
47 | * global variables | ||
48 | */ | ||
49 | int zft_qic_mode = 1; /* use the vtbl */ | ||
50 | int zft_old_ftape; /* prevents old ftaped tapes to be overwritten */ | ||
51 | int zft_volume_table_changed; /* for write_header_segments() */ | ||
52 | |||
53 | /* | ||
54 | * private variables (only exported for inline functions) | ||
55 | */ | ||
56 | LIST_HEAD(zft_vtbl); | ||
57 | |||
58 | /* We could also allocate these dynamically when extracting the volume table | ||
59 | * sizeof(zft_volinfo) is about 32 or something close to that | ||
60 | */ | ||
61 | static zft_volinfo tape_vtbl; | ||
62 | static zft_volinfo eot_vtbl; | ||
63 | static zft_volinfo *cur_vtbl; | ||
64 | |||
65 | static inline void zft_new_vtbl_entry(void) | ||
66 | { | ||
67 | struct list_head *tmp = &zft_last_vtbl->node; | ||
68 | zft_volinfo *new = zft_kmalloc(sizeof(zft_volinfo)); | ||
69 | |||
70 | list_add(&new->node, tmp); | ||
71 | new->count = zft_eom_vtbl->count ++; | ||
72 | } | ||
73 | |||
74 | void zft_free_vtbl(void) | ||
75 | { | ||
76 | for (;;) { | ||
77 | struct list_head *tmp = zft_vtbl.prev; | ||
78 | zft_volinfo *vtbl; | ||
79 | |||
80 | if (tmp == &zft_vtbl) | ||
81 | break; | ||
82 | list_del(tmp); | ||
83 | vtbl = list_entry(tmp, zft_volinfo, node); | ||
84 | zft_kfree(vtbl, sizeof(zft_volinfo)); | ||
85 | } | ||
86 | INIT_LIST_HEAD(&zft_vtbl); | ||
87 | cur_vtbl = NULL; | ||
88 | } | ||
89 | |||
90 | /* initialize vtbl, called by ftape_new_cartridge() | ||
91 | */ | ||
92 | void zft_init_vtbl(void) | ||
93 | { | ||
94 | zft_volinfo *new; | ||
95 | |||
96 | zft_free_vtbl(); | ||
97 | |||
98 | /* Create the two dummy vtbl entries | ||
99 | */ | ||
100 | new = zft_kmalloc(sizeof(zft_volinfo)); | ||
101 | list_add(&new->node, &zft_vtbl); | ||
102 | new = zft_kmalloc(sizeof(zft_volinfo)); | ||
103 | list_add(&new->node, &zft_vtbl); | ||
104 | zft_head_vtbl->end_seg = ft_first_data_segment; | ||
105 | zft_head_vtbl->blk_sz = zft_blk_sz; | ||
106 | zft_head_vtbl->count = -1; | ||
107 | zft_eom_vtbl->start_seg = ft_first_data_segment + 1; | ||
108 | zft_eom_vtbl->end_seg = ft_last_data_segment + 1; | ||
109 | zft_eom_vtbl->blk_sz = zft_blk_sz; | ||
110 | zft_eom_vtbl->count = 0; | ||
111 | |||
112 | /* Reset the pointer for zft_find_volume() | ||
113 | */ | ||
114 | cur_vtbl = zft_eom_vtbl; | ||
115 | |||
116 | /* initialize the dummy vtbl entries for zft_qic_mode == 0 | ||
117 | */ | ||
118 | eot_vtbl.start_seg = ft_last_data_segment + 1; | ||
119 | eot_vtbl.end_seg = ft_last_data_segment + 1; | ||
120 | eot_vtbl.blk_sz = zft_blk_sz; | ||
121 | eot_vtbl.count = -1; | ||
122 | tape_vtbl.start_seg = ft_first_data_segment; | ||
123 | tape_vtbl.end_seg = ft_last_data_segment; | ||
124 | tape_vtbl.blk_sz = zft_blk_sz; | ||
125 | tape_vtbl.size = zft_capacity; | ||
126 | tape_vtbl.count = 0; | ||
127 | } | ||
128 | |||
129 | /* check for a valid VTBL signature. | ||
130 | */ | ||
131 | static int vtbl_signature_valid(__u8 signature[4]) | ||
132 | { | ||
133 | const char *vtbl_ids[] = VTBL_IDS; /* valid signatures */ | ||
134 | int j; | ||
135 | |||
136 | for (j = 0; | ||
137 | (j < NR_ITEMS(vtbl_ids)) && (memcmp(signature, vtbl_ids[j], 4) != 0); | ||
138 | j++); | ||
139 | return j < NR_ITEMS(vtbl_ids); | ||
140 | } | ||
141 | |||
142 | /* We used to store the block-size of the volume in the volume-label, | ||
143 | * using the keyword "blocksize". The blocksize written to the | ||
144 | * volume-label is in bytes. | ||
145 | * | ||
146 | * We use this now only for compatibility with old zftape version. We | ||
147 | * store the blocksize directly as binary number in the vendor | ||
148 | * extension part of the volume entry. | ||
149 | */ | ||
150 | static int check_volume_label(const char *label, int *blk_sz) | ||
151 | { | ||
152 | int valid_format; | ||
153 | char *blocksize; | ||
154 | TRACE_FUN(ft_t_flow); | ||
155 | |||
156 | TRACE(ft_t_noise, "called with \"%s\" / \"%s\"", label, ZFT_VOL_NAME); | ||
157 | if (strncmp(label, ZFT_VOL_NAME, strlen(ZFT_VOL_NAME)) != 0) { | ||
158 | *blk_sz = 1; /* smallest block size that we allow */ | ||
159 | valid_format = 0; | ||
160 | } else { | ||
161 | TRACE(ft_t_noise, "got old style zftape vtbl entry"); | ||
162 | /* get the default blocksize */ | ||
163 | /* use the kernel strstr() */ | ||
164 | blocksize= strstr(label, " blocksize "); | ||
165 | if (blocksize) { | ||
166 | blocksize += strlen(" blocksize "); | ||
167 | for(*blk_sz= 0; | ||
168 | *blocksize >= '0' && *blocksize <= '9'; | ||
169 | blocksize++) { | ||
170 | *blk_sz *= 10; | ||
171 | *blk_sz += *blocksize - '0'; | ||
172 | } | ||
173 | if (*blk_sz > ZFT_MAX_BLK_SZ) { | ||
174 | *blk_sz= 1; | ||
175 | valid_format= 0; | ||
176 | } else { | ||
177 | valid_format = 1; | ||
178 | } | ||
179 | } else { | ||
180 | *blk_sz= 1; | ||
181 | valid_format= 0; | ||
182 | } | ||
183 | } | ||
184 | TRACE_EXIT valid_format; | ||
185 | } | ||
186 | |||
187 | /* check for a zftape volume | ||
188 | */ | ||
189 | static int check_volume(__u8 *entry, zft_volinfo *volume) | ||
190 | { | ||
191 | TRACE_FUN(ft_t_flow); | ||
192 | |||
193 | if(strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG, | ||
194 | strlen(ZFTAPE_SIG)) == 0) { | ||
195 | TRACE(ft_t_noise, "got new style zftape vtbl entry"); | ||
196 | volume->blk_sz = GET2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ); | ||
197 | volume->qic113 = entry[VTBL_EXT+EXT_ZFTAPE_QIC113]; | ||
198 | TRACE_EXIT 1; | ||
199 | } else { | ||
200 | TRACE_EXIT check_volume_label(&entry[VTBL_DESC], &volume->blk_sz); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | |||
205 | /* create zftape specific vtbl entry, the volume bounds are inserted | ||
206 | * in the calling function, zft_create_volume_headers() | ||
207 | */ | ||
208 | static void create_zft_volume(__u8 *entry, zft_volinfo *vtbl) | ||
209 | { | ||
210 | TRACE_FUN(ft_t_flow); | ||
211 | |||
212 | memset(entry, 0, VTBL_SIZE); | ||
213 | memcpy(&entry[VTBL_SIG], VTBL_ID, 4); | ||
214 | sprintf(&entry[VTBL_DESC], ZFT_VOL_NAME" %03d", vtbl->count); | ||
215 | entry[VTBL_FLAGS] = (VTBL_FL_NOT_VERIFIED | VTBL_FL_SEG_SPANNING); | ||
216 | entry[VTBL_M_NO] = 1; /* multi_cartridge_count */ | ||
217 | strcpy(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG); | ||
218 | PUT2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ, vtbl->blk_sz); | ||
219 | if (zft_qic113) { | ||
220 | PUT8(entry, VTBL_DATA_SIZE, vtbl->size); | ||
221 | entry[VTBL_CMPR] = VTBL_CMPR_UNREG; | ||
222 | if (vtbl->use_compression) { /* use compression: */ | ||
223 | entry[VTBL_CMPR] |= VTBL_CMPR_USED; | ||
224 | } | ||
225 | entry[VTBL_EXT+EXT_ZFTAPE_QIC113] = 1; | ||
226 | } else { | ||
227 | PUT4(entry, VTBL_DATA_SIZE, vtbl->size); | ||
228 | entry[VTBL_K_CMPR] = VTBL_CMPR_UNREG; | ||
229 | if (vtbl->use_compression) { /* use compression: */ | ||
230 | entry[VTBL_K_CMPR] |= VTBL_CMPR_USED; | ||
231 | } | ||
232 | } | ||
233 | if (ft_format_code == fmt_big) { | ||
234 | /* SCSI like vtbl, store the number of used | ||
235 | * segments as 4 byte value | ||
236 | */ | ||
237 | PUT4(entry, VTBL_SCSI_SEGS, vtbl->end_seg-vtbl->start_seg + 1); | ||
238 | } else { | ||
239 | /* normal, QIC-80MC like vtbl | ||
240 | */ | ||
241 | PUT2(entry, VTBL_START, vtbl->start_seg); | ||
242 | PUT2(entry, VTBL_END, vtbl->end_seg); | ||
243 | } | ||
244 | TRACE_EXIT; | ||
245 | } | ||
246 | |||
247 | /* this one creates the volume headers for each volume. It is assumed | ||
248 | * that buffer already contains the old volume-table, so that vtbl | ||
249 | * entries without the zft_volume flag set can savely be ignored. | ||
250 | */ | ||
251 | static void zft_create_volume_headers(__u8 *buffer) | ||
252 | { | ||
253 | __u8 *entry; | ||
254 | struct list_head *tmp; | ||
255 | zft_volinfo *vtbl; | ||
256 | TRACE_FUN(ft_t_flow); | ||
257 | |||
258 | #ifdef ZFT_CMAP_HACK | ||
259 | if((strncmp(&buffer[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG, | ||
260 | strlen(ZFTAPE_SIG)) == 0) && | ||
261 | buffer[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) { | ||
262 | TRACE(ft_t_noise, "deleting cmap volume"); | ||
263 | memmove(buffer, buffer + VTBL_SIZE, | ||
264 | FT_SEGMENT_SIZE - VTBL_SIZE); | ||
265 | } | ||
266 | #endif | ||
267 | entry = buffer; | ||
268 | for (tmp = zft_head_vtbl->node.next; | ||
269 | tmp != &zft_eom_vtbl->node; | ||
270 | tmp = tmp->next) { | ||
271 | vtbl = list_entry(tmp, zft_volinfo, node); | ||
272 | /* we now fill in the values only for newly created volumes. | ||
273 | */ | ||
274 | if (vtbl->new_volume) { | ||
275 | create_zft_volume(entry, vtbl); | ||
276 | vtbl->new_volume = 0; /* clear the flag */ | ||
277 | } | ||
278 | |||
279 | DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], vtbl); | ||
280 | entry += VTBL_SIZE; | ||
281 | } | ||
282 | memset(entry, 0, FT_SEGMENT_SIZE - zft_eom_vtbl->count * VTBL_SIZE); | ||
283 | TRACE_EXIT; | ||
284 | } | ||
285 | |||
286 | /* write volume table to tape. Calls zft_create_volume_headers() | ||
287 | */ | ||
288 | int zft_update_volume_table(unsigned int segment) | ||
289 | { | ||
290 | int result = 0; | ||
291 | __u8 *verify_buf = NULL; | ||
292 | TRACE_FUN(ft_t_flow); | ||
293 | |||
294 | TRACE_CATCH(result = ftape_read_segment(ft_first_data_segment, | ||
295 | zft_deblock_buf, | ||
296 | FT_RD_SINGLE),); | ||
297 | zft_create_volume_headers(zft_deblock_buf); | ||
298 | TRACE(ft_t_noise, "writing volume table segment %d", segment); | ||
299 | if (zft_vmalloc_once(&verify_buf, FT_SEGMENT_SIZE) == 0) { | ||
300 | TRACE_CATCH(zft_verify_write_segments(segment, | ||
301 | zft_deblock_buf, result, | ||
302 | verify_buf), | ||
303 | zft_vfree(&verify_buf, FT_SEGMENT_SIZE)); | ||
304 | zft_vfree(&verify_buf, FT_SEGMENT_SIZE); | ||
305 | } else { | ||
306 | TRACE_CATCH(ftape_write_segment(segment, zft_deblock_buf, | ||
307 | FT_WR_SINGLE),); | ||
308 | } | ||
309 | TRACE_EXIT 0; | ||
310 | } | ||
311 | |||
312 | /* non zftape volumes are handled in raw mode. Thus we need to | ||
313 | * calculate the raw amount of data contained in those segments. | ||
314 | */ | ||
315 | static void extract_alien_volume(__u8 *entry, zft_volinfo *vtbl) | ||
316 | { | ||
317 | TRACE_FUN(ft_t_flow); | ||
318 | |||
319 | vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) - | ||
320 | zft_calc_tape_pos(zft_last_vtbl->start_seg)); | ||
321 | vtbl->use_compression = 0; | ||
322 | vtbl->qic113 = zft_qic113; | ||
323 | if (vtbl->qic113) { | ||
324 | TRACE(ft_t_noise, | ||
325 | "Fake alien volume's size from " LL_X " to " LL_X, | ||
326 | LL(GET8(entry, VTBL_DATA_SIZE)), LL(vtbl->size)); | ||
327 | } else { | ||
328 | TRACE(ft_t_noise, | ||
329 | "Fake alien volume's size from %d to " LL_X, | ||
330 | (int)GET4(entry, VTBL_DATA_SIZE), LL(vtbl->size)); | ||
331 | } | ||
332 | TRACE_EXIT; | ||
333 | } | ||
334 | |||
335 | |||
336 | /* extract an zftape specific volume | ||
337 | */ | ||
338 | static void extract_zft_volume(__u8 *entry, zft_volinfo *vtbl) | ||
339 | { | ||
340 | TRACE_FUN(ft_t_flow); | ||
341 | |||
342 | if (vtbl->qic113) { | ||
343 | vtbl->size = GET8(entry, VTBL_DATA_SIZE); | ||
344 | vtbl->use_compression = | ||
345 | (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0; | ||
346 | } else { | ||
347 | vtbl->size = GET4(entry, VTBL_DATA_SIZE); | ||
348 | if (entry[VTBL_K_CMPR] & VTBL_CMPR_UNREG) { | ||
349 | vtbl->use_compression = | ||
350 | (entry[VTBL_K_CMPR] & VTBL_CMPR_USED) != 0; | ||
351 | } else if (entry[VTBL_CMPR] & VTBL_CMPR_UNREG) { | ||
352 | vtbl->use_compression = | ||
353 | (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0; | ||
354 | } else { | ||
355 | TRACE(ft_t_warn, "Geeh! There is something wrong:\n" | ||
356 | KERN_INFO "QIC compression (Rev = K): %x\n" | ||
357 | KERN_INFO "QIC compression (Rev > K): %x", | ||
358 | entry[VTBL_K_CMPR], entry[VTBL_CMPR]); | ||
359 | } | ||
360 | } | ||
361 | TRACE_EXIT; | ||
362 | } | ||
363 | |||
364 | /* extract the volume table from buffer. "buffer" must already contain | ||
365 | * the vtbl-segment | ||
366 | */ | ||
367 | int zft_extract_volume_headers(__u8 *buffer) | ||
368 | { | ||
369 | __u8 *entry; | ||
370 | TRACE_FUN(ft_t_flow); | ||
371 | |||
372 | zft_init_vtbl(); | ||
373 | entry = buffer; | ||
374 | #ifdef ZFT_CMAP_HACK | ||
375 | if ((strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG, | ||
376 | strlen(ZFTAPE_SIG)) == 0) && | ||
377 | entry[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) { | ||
378 | TRACE(ft_t_noise, "ignoring cmap volume"); | ||
379 | entry += VTBL_SIZE; | ||
380 | } | ||
381 | #endif | ||
382 | /* the end of the vtbl is indicated by an invalid signature | ||
383 | */ | ||
384 | while (vtbl_signature_valid(&entry[VTBL_SIG]) && | ||
385 | (entry - buffer) < FT_SEGMENT_SIZE) { | ||
386 | zft_new_vtbl_entry(); | ||
387 | if (ft_format_code == fmt_big) { | ||
388 | /* SCSI like vtbl, stores only the number of | ||
389 | * segments used | ||
390 | */ | ||
391 | unsigned int num_segments= GET4(entry, VTBL_SCSI_SEGS); | ||
392 | zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; | ||
393 | zft_last_vtbl->end_seg = | ||
394 | zft_last_vtbl->start_seg + num_segments - 1; | ||
395 | } else { | ||
396 | /* `normal', QIC-80 like vtbl | ||
397 | */ | ||
398 | zft_last_vtbl->start_seg = GET2(entry, VTBL_START); | ||
399 | zft_last_vtbl->end_seg = GET2(entry, VTBL_END); | ||
400 | } | ||
401 | zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1; | ||
402 | /* check if we created this volume and get the | ||
403 | * blk_sz | ||
404 | */ | ||
405 | zft_last_vtbl->zft_volume = check_volume(entry, zft_last_vtbl); | ||
406 | if (zft_last_vtbl->zft_volume == 0) { | ||
407 | extract_alien_volume(entry, zft_last_vtbl); | ||
408 | } else { | ||
409 | extract_zft_volume(entry, zft_last_vtbl); | ||
410 | } | ||
411 | DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], zft_last_vtbl); | ||
412 | entry +=VTBL_SIZE; | ||
413 | } | ||
414 | #if 0 | ||
415 | /* | ||
416 | * undefine to test end of tape handling | ||
417 | */ | ||
418 | zft_new_vtbl_entry(); | ||
419 | zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; | ||
420 | zft_last_vtbl->end_seg = ft_last_data_segment - 10; | ||
421 | zft_last_vtbl->blk_sz = zft_blk_sz; | ||
422 | zft_last_vtbl->zft_volume = 1; | ||
423 | zft_last_vtbl->qic113 = zft_qic113; | ||
424 | zft_last_vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) | ||
425 | - zft_calc_tape_pos(zft_last_vtbl->start_seg)); | ||
426 | #endif | ||
427 | TRACE_EXIT 0; | ||
428 | } | ||
429 | |||
430 | /* this functions translates the failed_sector_log, misused as | ||
431 | * EOF-marker list, into a virtual volume table. The table mustn't be | ||
432 | * written to tape, because this would occupy the first data segment, | ||
433 | * which should be the volume table, but is actually the first segment | ||
434 | * that is filled with data (when using standard ftape). We assume, | ||
435 | * that we get a non-empty failed_sector_log. | ||
436 | */ | ||
437 | int zft_fake_volume_headers (eof_mark_union *eof_map, int num_failed_sectors) | ||
438 | { | ||
439 | unsigned int segment, sector; | ||
440 | int have_eom = 0; | ||
441 | int vol_no; | ||
442 | TRACE_FUN(ft_t_flow); | ||
443 | |||
444 | if ((num_failed_sectors >= 2) && | ||
445 | (GET2(&eof_map[num_failed_sectors - 1].mark.segment, 0) | ||
446 | == | ||
447 | GET2(&eof_map[num_failed_sectors - 2].mark.segment, 0) + 1) && | ||
448 | (GET2(&eof_map[num_failed_sectors - 1].mark.date, 0) == 1)) { | ||
449 | /* this should be eom. We keep the remainder of the | ||
450 | * tape as another volume. | ||
451 | */ | ||
452 | have_eom = 1; | ||
453 | } | ||
454 | zft_init_vtbl(); | ||
455 | zft_eom_vtbl->start_seg = ft_first_data_segment; | ||
456 | for(vol_no = 0; vol_no < num_failed_sectors - have_eom; vol_no ++) { | ||
457 | zft_new_vtbl_entry(); | ||
458 | |||
459 | segment = GET2(&eof_map[vol_no].mark.segment, 0); | ||
460 | sector = GET2(&eof_map[vol_no].mark.date, 0); | ||
461 | |||
462 | zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; | ||
463 | zft_last_vtbl->end_seg = segment; | ||
464 | zft_eom_vtbl->start_seg = segment + 1; | ||
465 | zft_last_vtbl->blk_sz = 1; | ||
466 | zft_last_vtbl->size = | ||
467 | (zft_calc_tape_pos(zft_last_vtbl->end_seg) | ||
468 | - zft_calc_tape_pos(zft_last_vtbl->start_seg) | ||
469 | + (sector-1) * FT_SECTOR_SIZE); | ||
470 | TRACE(ft_t_noise, | ||
471 | "failed sector log: segment: %d, sector: %d", | ||
472 | segment, sector); | ||
473 | DUMP_VOLINFO(ft_t_noise, "Faked volume", zft_last_vtbl); | ||
474 | } | ||
475 | if (!have_eom) { | ||
476 | zft_new_vtbl_entry(); | ||
477 | zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg; | ||
478 | zft_last_vtbl->end_seg = ft_last_data_segment; | ||
479 | zft_eom_vtbl->start_seg = ft_last_data_segment + 1; | ||
480 | zft_last_vtbl->size = zft_capacity; | ||
481 | zft_last_vtbl->size -= zft_calc_tape_pos(zft_last_vtbl->start_seg); | ||
482 | zft_last_vtbl->blk_sz = 1; | ||
483 | DUMP_VOLINFO(ft_t_noise, "Faked volume",zft_last_vtbl); | ||
484 | } | ||
485 | TRACE_EXIT 0; | ||
486 | } | ||
487 | |||
488 | /* update the internal volume table | ||
489 | * | ||
490 | * if before start of last volume: erase all following volumes if | ||
491 | * inside a volume: set end of volume to infinity | ||
492 | * | ||
493 | * this function is intended to be called every time _ftape_write() is | ||
494 | * called | ||
495 | * | ||
496 | * return: 0 if no new volume was created, 1 if a new volume was | ||
497 | * created | ||
498 | * | ||
499 | * NOTE: we don't need to check for zft_mode as ftape_write() does | ||
500 | * that already. This function gets never called without accessing | ||
501 | * zftape via the *qft* devices | ||
502 | */ | ||
503 | |||
504 | int zft_open_volume(zft_position *pos, int blk_sz, int use_compression) | ||
505 | { | ||
506 | TRACE_FUN(ft_t_flow); | ||
507 | |||
508 | if (!zft_qic_mode) { | ||
509 | TRACE_EXIT 0; | ||
510 | } | ||
511 | if (zft_tape_at_lbot(pos)) { | ||
512 | zft_init_vtbl(); | ||
513 | if(zft_old_ftape) { | ||
514 | /* clear old ftape's eof marks */ | ||
515 | zft_clear_ftape_file_marks(); | ||
516 | zft_old_ftape = 0; /* no longer old ftape */ | ||
517 | } | ||
518 | zft_reset_position(pos); | ||
519 | } | ||
520 | if (pos->seg_pos != zft_last_vtbl->end_seg + 1) { | ||
521 | TRACE_ABORT(-EIO, ft_t_bug, | ||
522 | "BUG: seg_pos: %d, zft_last_vtbl->end_seg: %d", | ||
523 | pos->seg_pos, zft_last_vtbl->end_seg); | ||
524 | } | ||
525 | TRACE(ft_t_noise, "create new volume"); | ||
526 | if (zft_eom_vtbl->count >= ZFT_MAX_VOLUMES) { | ||
527 | TRACE_ABORT(-ENOSPC, ft_t_err, | ||
528 | "Error: maxmimal number of volumes exhausted " | ||
529 | "(maxmimum is %d)", ZFT_MAX_VOLUMES); | ||
530 | } | ||
531 | zft_new_vtbl_entry(); | ||
532 | pos->volume_pos = pos->seg_byte_pos = 0; | ||
533 | zft_last_vtbl->start_seg = pos->seg_pos; | ||
534 | zft_last_vtbl->end_seg = ft_last_data_segment; /* infinity */ | ||
535 | zft_last_vtbl->blk_sz = blk_sz; | ||
536 | zft_last_vtbl->size = zft_capacity; | ||
537 | zft_last_vtbl->zft_volume = 1; | ||
538 | zft_last_vtbl->use_compression = use_compression; | ||
539 | zft_last_vtbl->qic113 = zft_qic113; | ||
540 | zft_last_vtbl->new_volume = 1; | ||
541 | zft_last_vtbl->open = 1; | ||
542 | zft_volume_table_changed = 1; | ||
543 | zft_eom_vtbl->start_seg = ft_last_data_segment + 1; | ||
544 | TRACE_EXIT 0; | ||
545 | } | ||
546 | |||
547 | /* perform mtfsf, mtbsf, not allowed without zft_qic_mode | ||
548 | */ | ||
549 | int zft_skip_volumes(int count, zft_position *pos) | ||
550 | { | ||
551 | const zft_volinfo *vtbl; | ||
552 | TRACE_FUN(ft_t_flow); | ||
553 | |||
554 | TRACE(ft_t_noise, "count: %d", count); | ||
555 | |||
556 | vtbl= zft_find_volume(pos->seg_pos); | ||
557 | while (count > 0 && vtbl != zft_eom_vtbl) { | ||
558 | vtbl = list_entry(vtbl->node.next, zft_volinfo, node); | ||
559 | count --; | ||
560 | } | ||
561 | while (count < 0 && vtbl != zft_first_vtbl) { | ||
562 | vtbl = list_entry(vtbl->node.prev, zft_volinfo, node); | ||
563 | count ++; | ||
564 | } | ||
565 | pos->seg_pos = vtbl->start_seg; | ||
566 | pos->seg_byte_pos = 0; | ||
567 | pos->volume_pos = 0; | ||
568 | pos->tape_pos = zft_calc_tape_pos(pos->seg_pos); | ||
569 | zft_just_before_eof = vtbl->size == 0; | ||
570 | if (zft_cmpr_ops) { | ||
571 | (*zft_cmpr_ops->reset)(); | ||
572 | } | ||
573 | zft_deblock_segment = -1; /* no need to keep cache */ | ||
574 | TRACE(ft_t_noise, "repositioning to:\n" | ||
575 | KERN_INFO "zft_seg_pos : %d\n" | ||
576 | KERN_INFO "zft_seg_byte_pos : %d\n" | ||
577 | KERN_INFO "zft_tape_pos : " LL_X "\n" | ||
578 | KERN_INFO "zft_volume_pos : " LL_X "\n" | ||
579 | KERN_INFO "file number : %d", | ||
580 | pos->seg_pos, pos->seg_byte_pos, | ||
581 | LL(pos->tape_pos), LL(pos->volume_pos), vtbl->count); | ||
582 | zft_resid = count < 0 ? -count : count; | ||
583 | TRACE_EXIT zft_resid ? -EINVAL : 0; | ||
584 | } | ||
585 | |||
586 | /* the following simply returns the raw data position of the EOM | ||
587 | * marker, MTIOCSIZE ioctl | ||
588 | */ | ||
589 | __s64 zft_get_eom_pos(void) | ||
590 | { | ||
591 | if (zft_qic_mode) { | ||
592 | return zft_calc_tape_pos(zft_eom_vtbl->start_seg); | ||
593 | } else { | ||
594 | /* there is only one volume in raw mode */ | ||
595 | return zft_capacity; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | /* skip to eom, used for MTEOM | ||
600 | */ | ||
601 | void zft_skip_to_eom(zft_position *pos) | ||
602 | { | ||
603 | TRACE_FUN(ft_t_flow); | ||
604 | pos->seg_pos = zft_eom_vtbl->start_seg; | ||
605 | pos->seg_byte_pos = | ||
606 | pos->volume_pos = | ||
607 | zft_just_before_eof = 0; | ||
608 | pos->tape_pos = zft_calc_tape_pos(pos->seg_pos); | ||
609 | TRACE(ft_t_noise, "ftape positioned to segment %d, data pos " LL_X, | ||
610 | pos->seg_pos, LL(pos->tape_pos)); | ||
611 | TRACE_EXIT; | ||
612 | } | ||
613 | |||
614 | /* write an EOF-marker by setting zft_last_vtbl->end_seg to seg_pos. | ||
615 | * NOTE: this function assumes that zft_last_vtbl points to a valid | ||
616 | * vtbl entry | ||
617 | * | ||
618 | * NOTE: this routine always positions before the EOF marker | ||
619 | */ | ||
620 | int zft_close_volume(zft_position *pos) | ||
621 | { | ||
622 | TRACE_FUN(ft_t_any); | ||
623 | |||
624 | if (zft_vtbl_empty || !zft_last_vtbl->open) { /* should not happen */ | ||
625 | TRACE(ft_t_noise, "There are no volumes to finish"); | ||
626 | TRACE_EXIT -EIO; | ||
627 | } | ||
628 | if (pos->seg_byte_pos == 0 && | ||
629 | pos->seg_pos != zft_last_vtbl->start_seg) { | ||
630 | pos->seg_pos --; | ||
631 | pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos); | ||
632 | } | ||
633 | zft_last_vtbl->end_seg = pos->seg_pos; | ||
634 | zft_last_vtbl->size = pos->volume_pos; | ||
635 | zft_volume_table_changed = 1; | ||
636 | zft_just_before_eof = 1; | ||
637 | zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1; | ||
638 | zft_last_vtbl->open = 0; /* closed */ | ||
639 | TRACE_EXIT 0; | ||
640 | } | ||
641 | |||
642 | /* write count file-marks at current position. | ||
643 | * | ||
644 | * The tape is positioned after the eof-marker, that is at byte 0 of | ||
645 | * the segment following the eof-marker | ||
646 | * | ||
647 | * this function is only allowed in zft_qic_mode | ||
648 | * | ||
649 | * Only allowed when tape is at BOT or EOD. | ||
650 | */ | ||
651 | int zft_weof(unsigned int count, zft_position *pos) | ||
652 | { | ||
653 | |||
654 | TRACE_FUN(ft_t_flow); | ||
655 | |||
656 | if (!count) { /* write zero EOF marks should be a real no-op */ | ||
657 | TRACE_EXIT 0; | ||
658 | } | ||
659 | zft_volume_table_changed = 1; | ||
660 | if (zft_tape_at_lbot(pos)) { | ||
661 | zft_init_vtbl(); | ||
662 | if(zft_old_ftape) { | ||
663 | /* clear old ftape's eof marks */ | ||
664 | zft_clear_ftape_file_marks(); | ||
665 | zft_old_ftape = 0; /* no longer old ftape */ | ||
666 | } | ||
667 | } | ||
668 | if (zft_last_vtbl->open) { | ||
669 | zft_close_volume(pos); | ||
670 | zft_move_past_eof(pos); | ||
671 | count --; | ||
672 | } | ||
673 | /* now it's easy, just append eof-marks, that is empty | ||
674 | * volumes, to the end of the already recorded media. | ||
675 | */ | ||
676 | while (count > 0 && | ||
677 | pos->seg_pos <= ft_last_data_segment && | ||
678 | zft_eom_vtbl->count < ZFT_MAX_VOLUMES) { | ||
679 | TRACE(ft_t_noise, | ||
680 | "Writing zero sized file at segment %d", pos->seg_pos); | ||
681 | zft_new_vtbl_entry(); | ||
682 | zft_last_vtbl->start_seg = pos->seg_pos; | ||
683 | zft_last_vtbl->end_seg = pos->seg_pos; | ||
684 | zft_last_vtbl->size = 0; | ||
685 | zft_last_vtbl->blk_sz = zft_blk_sz; | ||
686 | zft_last_vtbl->zft_volume = 1; | ||
687 | zft_last_vtbl->use_compression = 0; | ||
688 | pos->tape_pos += zft_get_seg_sz(pos->seg_pos); | ||
689 | zft_eom_vtbl->start_seg = ++ pos->seg_pos; | ||
690 | count --; | ||
691 | } | ||
692 | if (count > 0) { | ||
693 | /* there are two possibilities: end of tape, or the | ||
694 | * maximum number of files is exhausted. | ||
695 | */ | ||
696 | zft_resid = count; | ||
697 | TRACE(ft_t_noise,"Number of marks NOT written: %d", zft_resid); | ||
698 | if (zft_eom_vtbl->count == ZFT_MAX_VOLUMES) { | ||
699 | TRACE_ABORT(-EINVAL, ft_t_warn, | ||
700 | "maximum allowed number of files " | ||
701 | "exhausted: %d", ZFT_MAX_VOLUMES); | ||
702 | } else { | ||
703 | TRACE_ABORT(-ENOSPC, | ||
704 | ft_t_noise, "reached end of tape"); | ||
705 | } | ||
706 | } | ||
707 | TRACE_EXIT 0; | ||
708 | } | ||
709 | |||
710 | const zft_volinfo *zft_find_volume(unsigned int seg_pos) | ||
711 | { | ||
712 | TRACE_FUN(ft_t_flow); | ||
713 | |||
714 | TRACE(ft_t_any, "called with seg_pos %d",seg_pos); | ||
715 | if (!zft_qic_mode) { | ||
716 | if (seg_pos > ft_last_data_segment) { | ||
717 | TRACE_EXIT &eot_vtbl; | ||
718 | } | ||
719 | tape_vtbl.blk_sz = zft_blk_sz; | ||
720 | TRACE_EXIT &tape_vtbl; | ||
721 | } | ||
722 | if (seg_pos < zft_first_vtbl->start_seg) { | ||
723 | TRACE_EXIT (cur_vtbl = zft_first_vtbl); | ||
724 | } | ||
725 | while (seg_pos > cur_vtbl->end_seg) { | ||
726 | cur_vtbl = list_entry(cur_vtbl->node.next, zft_volinfo, node); | ||
727 | TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg); | ||
728 | } | ||
729 | while (seg_pos < cur_vtbl->start_seg) { | ||
730 | cur_vtbl = list_entry(cur_vtbl->node.prev, zft_volinfo, node); | ||
731 | TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg); | ||
732 | } | ||
733 | if (seg_pos > cur_vtbl->end_seg || seg_pos < cur_vtbl->start_seg) { | ||
734 | TRACE(ft_t_bug, "This cannot happen"); | ||
735 | } | ||
736 | DUMP_VOLINFO(ft_t_noise, "", cur_vtbl); | ||
737 | TRACE_EXIT cur_vtbl; | ||
738 | } | ||
739 | |||
740 | /* this function really assumes that we are just before eof | ||
741 | */ | ||
742 | void zft_move_past_eof(zft_position *pos) | ||
743 | { | ||
744 | TRACE_FUN(ft_t_flow); | ||
745 | |||
746 | TRACE(ft_t_noise, "old seg. pos: %d", pos->seg_pos); | ||
747 | pos->tape_pos += zft_get_seg_sz(pos->seg_pos++) - pos->seg_byte_pos; | ||
748 | pos->seg_byte_pos = 0; | ||
749 | pos->volume_pos = 0; | ||
750 | if (zft_cmpr_ops) { | ||
751 | (*zft_cmpr_ops->reset)(); | ||
752 | } | ||
753 | zft_just_before_eof = 0; | ||
754 | zft_deblock_segment = -1; /* no need to cache it anymore */ | ||
755 | TRACE(ft_t_noise, "new seg. pos: %d", pos->seg_pos); | ||
756 | TRACE_EXIT; | ||
757 | } | ||
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.h b/drivers/char/ftape/zftape/zftape-vtbl.h deleted file mode 100644 index f31d196d1759..000000000000 --- a/drivers/char/ftape/zftape/zftape-vtbl.h +++ /dev/null | |||
@@ -1,227 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_VTBL_H | ||
2 | #define _ZFTAPE_VTBL_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 1995-1997 Claus-Justus Heine | ||
6 | |||
7 | This program is free software; you can redistribute it and/or | ||
8 | modify it under the terms of the GNU General Public License as | ||
9 | published by the Free Software Foundation; either version 2, or (at | ||
10 | your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, but | ||
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
20 | USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.h,v $ | ||
24 | * $Revision: 1.3 $ | ||
25 | * $Date: 1997/10/28 14:30:09 $ | ||
26 | * | ||
27 | * This file defines a volume table as defined in the QIC-80 | ||
28 | * development standards. | ||
29 | */ | ||
30 | |||
31 | #include <linux/list.h> | ||
32 | |||
33 | #include "../lowlevel/ftape-tracing.h" | ||
34 | |||
35 | #include "../zftape/zftape-eof.h" | ||
36 | #include "../zftape/zftape-ctl.h" | ||
37 | #include "../zftape/zftape-rw.h" | ||
38 | |||
39 | #define VTBL_SIZE 128 /* bytes */ | ||
40 | |||
41 | /* The following are offsets in the vtbl. */ | ||
42 | #define VTBL_SIG 0 | ||
43 | #define VTBL_START 4 | ||
44 | #define VTBL_END 6 | ||
45 | #define VTBL_DESC 8 | ||
46 | #define VTBL_DATE 52 | ||
47 | #define VTBL_FLAGS 56 | ||
48 | #define VTBL_FL_VENDOR_SPECIFIC (1<<0) | ||
49 | #define VTBL_FL_MUTLI_CARTRIDGE (1<<1) | ||
50 | #define VTBL_FL_NOT_VERIFIED (1<<2) | ||
51 | #define VTBL_FL_REDIR_INHIBIT (1<<3) | ||
52 | #define VTBL_FL_SEG_SPANNING (1<<4) | ||
53 | #define VTBL_FL_DIRECTORY_LAST (1<<5) | ||
54 | #define VTBL_FL_RESERVED_6 (1<<6) | ||
55 | #define VTBL_FL_RESERVED_7 (1<<7) | ||
56 | #define VTBL_M_NO 57 | ||
57 | #define VTBL_EXT 58 | ||
58 | #define EXT_ZFTAPE_SIG 0 | ||
59 | #define EXT_ZFTAPE_BLKSZ 10 | ||
60 | #define EXT_ZFTAPE_CMAP 12 | ||
61 | #define EXT_ZFTAPE_QIC113 13 | ||
62 | #define VTBL_PWD 84 | ||
63 | #define VTBL_DIR_SIZE 92 | ||
64 | #define VTBL_DATA_SIZE 96 | ||
65 | #define VTBL_OS_VERSION 104 | ||
66 | #define VTBL_SRC_DRIVE 106 | ||
67 | #define VTBL_DEV 122 | ||
68 | #define VTBL_RESERVED_1 123 | ||
69 | #define VTBL_CMPR 124 | ||
70 | #define VTBL_CMPR_UNREG 0x3f | ||
71 | #define VTBL_CMPR_USED 0x80 | ||
72 | #define VTBL_FMT 125 | ||
73 | #define VTBL_RESERVED_2 126 | ||
74 | #define VTBL_RESERVED_3 127 | ||
75 | /* compatibility with pre revision K */ | ||
76 | #define VTBL_K_CMPR 120 | ||
77 | |||
78 | /* the next is used by QIC-3020 tapes with format code 6 (>2^16 | ||
79 | * segments) It is specified in QIC-113, Rev. G, Section 5 (SCSI | ||
80 | * volume table). The difference is simply, that we only store the | ||
81 | * number of segments used, not the starting segment. | ||
82 | */ | ||
83 | #define VTBL_SCSI_SEGS 4 /* is a 4 byte value */ | ||
84 | |||
85 | /* one vtbl is 128 bytes, that results in a maximum number of | ||
86 | * 29*1024/128 = 232 volumes. | ||
87 | */ | ||
88 | #define ZFT_MAX_VOLUMES (FT_SEGMENT_SIZE/VTBL_SIZE) | ||
89 | #define VTBL_ID "VTBL" | ||
90 | #define VTBL_IDS { VTBL_ID, "XTBL", "UTID", "EXVT" } /* other valid ids */ | ||
91 | #define ZFT_VOL_NAME "zftape volume" /* volume label used by me */ | ||
92 | #define ZFTAPE_SIG "LINUX ZFT" | ||
93 | |||
94 | /* global variables | ||
95 | */ | ||
96 | typedef struct zft_internal_vtbl | ||
97 | { | ||
98 | struct list_head node; | ||
99 | int count; | ||
100 | unsigned int start_seg; /* 32 bits are enough for now */ | ||
101 | unsigned int end_seg; /* 32 bits are enough for now */ | ||
102 | __s64 size; /* uncompressed size */ | ||
103 | unsigned int blk_sz; /* block size for this volume */ | ||
104 | unsigned int zft_volume :1; /* zftape created this volume */ | ||
105 | unsigned int use_compression:1; /* compressed volume */ | ||
106 | unsigned int qic113 :1; /* layout of compressed block | ||
107 | * info and vtbl conforms to | ||
108 | * QIC-113, Rev. G | ||
109 | */ | ||
110 | unsigned int new_volume :1; /* it was created by us, this | ||
111 | * run. this allows the | ||
112 | * fields that aren't really | ||
113 | * used by zftape to be filled | ||
114 | * in by some user level | ||
115 | * program. | ||
116 | */ | ||
117 | unsigned int open :1; /* just in progress of being | ||
118 | * written | ||
119 | */ | ||
120 | } zft_volinfo; | ||
121 | |||
122 | extern struct list_head zft_vtbl; | ||
123 | #define zft_head_vtbl list_entry(zft_vtbl.next, zft_volinfo, node) | ||
124 | #define zft_eom_vtbl list_entry(zft_vtbl.prev, zft_volinfo, node) | ||
125 | #define zft_last_vtbl list_entry(zft_eom_vtbl->node.prev, zft_volinfo, node) | ||
126 | #define zft_first_vtbl list_entry(zft_head_vtbl->node.next, zft_volinfo, node) | ||
127 | #define zft_vtbl_empty (zft_eom_vtbl->node.prev == &zft_head_vtbl->node) | ||
128 | |||
129 | #define DUMP_VOLINFO(level, desc, info) \ | ||
130 | { \ | ||
131 | char tmp[21]; \ | ||
132 | strlcpy(tmp, desc, sizeof(tmp)); \ | ||
133 | TRACE(level, "Volume %d:\n" \ | ||
134 | KERN_INFO "description : %s\n" \ | ||
135 | KERN_INFO "first segment: %d\n" \ | ||
136 | KERN_INFO "last segment: %d\n" \ | ||
137 | KERN_INFO "size : " LL_X "\n" \ | ||
138 | KERN_INFO "block size : %d\n" \ | ||
139 | KERN_INFO "compression : %d\n" \ | ||
140 | KERN_INFO "zftape volume: %d\n" \ | ||
141 | KERN_INFO "QIC-113 conf.: %d", \ | ||
142 | (info)->count, tmp, (info)->start_seg, (info)->end_seg, \ | ||
143 | LL((info)->size), (info)->blk_sz, \ | ||
144 | (info)->use_compression != 0, (info)->zft_volume != 0, \ | ||
145 | (info)->qic113 != 0); \ | ||
146 | } | ||
147 | |||
148 | extern int zft_qic_mode; | ||
149 | extern int zft_old_ftape; | ||
150 | extern int zft_volume_table_changed; | ||
151 | |||
152 | /* exported functions */ | ||
153 | extern void zft_init_vtbl (void); | ||
154 | extern void zft_free_vtbl (void); | ||
155 | extern int zft_extract_volume_headers(__u8 *buffer); | ||
156 | extern int zft_update_volume_table (unsigned int segment); | ||
157 | extern int zft_open_volume (zft_position *pos, | ||
158 | int blk_sz, int use_compression); | ||
159 | extern int zft_close_volume (zft_position *pos); | ||
160 | extern const zft_volinfo *zft_find_volume(unsigned int seg_pos); | ||
161 | extern int zft_skip_volumes (int count, zft_position *pos); | ||
162 | extern __s64 zft_get_eom_pos (void); | ||
163 | extern void zft_skip_to_eom (zft_position *pos); | ||
164 | extern int zft_fake_volume_headers (eof_mark_union *eof_map, | ||
165 | int num_failed_sectors); | ||
166 | extern int zft_weof (unsigned int count, zft_position *pos); | ||
167 | extern void zft_move_past_eof (zft_position *pos); | ||
168 | |||
169 | static inline int zft_tape_at_eod (const zft_position *pos); | ||
170 | static inline int zft_tape_at_lbot (const zft_position *pos); | ||
171 | static inline void zft_position_before_eof (zft_position *pos, | ||
172 | const zft_volinfo *volume); | ||
173 | static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl, | ||
174 | const zft_position *pos); | ||
175 | |||
176 | /* this function decrements the zft_seg_pos counter if we are right | ||
177 | * at the beginning of a segment. This is to handle fsfm/bsfm -- we | ||
178 | * need to position before the eof mark. NOTE: zft_tape_pos is not | ||
179 | * changed | ||
180 | */ | ||
181 | static inline void zft_position_before_eof(zft_position *pos, | ||
182 | const zft_volinfo *volume) | ||
183 | { | ||
184 | TRACE_FUN(ft_t_flow); | ||
185 | |||
186 | if (pos->seg_pos == volume->end_seg + 1 && pos->seg_byte_pos == 0) { | ||
187 | pos->seg_pos --; | ||
188 | pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos); | ||
189 | } | ||
190 | TRACE_EXIT; | ||
191 | } | ||
192 | |||
193 | /* Mmmh. Is the position at the end of the last volume, that is right | ||
194 | * before the last EOF mark also logical an EOD condition? | ||
195 | */ | ||
196 | static inline int zft_tape_at_eod(const zft_position *pos) | ||
197 | { | ||
198 | TRACE_FUN(ft_t_any); | ||
199 | |||
200 | if (zft_qic_mode) { | ||
201 | TRACE_EXIT (pos->seg_pos >= zft_eom_vtbl->start_seg || | ||
202 | zft_last_vtbl->open); | ||
203 | } else { | ||
204 | TRACE_EXIT pos->seg_pos > ft_last_data_segment; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | static inline int zft_tape_at_lbot(const zft_position *pos) | ||
209 | { | ||
210 | if (zft_qic_mode) { | ||
211 | return (pos->seg_pos <= zft_first_vtbl->start_seg && | ||
212 | pos->volume_pos == 0); | ||
213 | } else { | ||
214 | return (pos->seg_pos <= ft_first_data_segment && | ||
215 | pos->volume_pos == 0); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* This one checks for EOF. return remaing space (may be negative) | ||
220 | */ | ||
221 | static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl, | ||
222 | const zft_position *pos) | ||
223 | { | ||
224 | return (__s64)(vtbl->size - pos->volume_pos); | ||
225 | } | ||
226 | |||
227 | #endif /* _ZFTAPE_VTBL_H */ | ||
diff --git a/drivers/char/ftape/zftape/zftape-write.c b/drivers/char/ftape/zftape/zftape-write.c deleted file mode 100644 index 94327b8c97b9..000000000000 --- a/drivers/char/ftape/zftape/zftape-write.c +++ /dev/null | |||
@@ -1,483 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996, 1997 Claus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.c,v $ | ||
20 | * $Revision: 1.3 $ | ||
21 | * $Date: 1997/11/06 00:50:29 $ | ||
22 | * | ||
23 | * This file contains the writing code | ||
24 | * for the QIC-117 floppy-tape driver for Linux. | ||
25 | */ | ||
26 | |||
27 | #include <linux/errno.h> | ||
28 | #include <linux/mm.h> | ||
29 | |||
30 | #include <linux/zftape.h> | ||
31 | |||
32 | #include <asm/uaccess.h> | ||
33 | |||
34 | #include "../zftape/zftape-init.h" | ||
35 | #include "../zftape/zftape-eof.h" | ||
36 | #include "../zftape/zftape-ctl.h" | ||
37 | #include "../zftape/zftape-write.h" | ||
38 | #include "../zftape/zftape-read.h" | ||
39 | #include "../zftape/zftape-rw.h" | ||
40 | #include "../zftape/zftape-vtbl.h" | ||
41 | |||
42 | /* Global vars. | ||
43 | */ | ||
44 | |||
45 | /* Local vars. | ||
46 | */ | ||
47 | static int last_write_failed; | ||
48 | static int need_flush; | ||
49 | |||
50 | void zft_prevent_flush(void) | ||
51 | { | ||
52 | need_flush = 0; | ||
53 | } | ||
54 | |||
55 | static int zft_write_header_segments(__u8* buffer) | ||
56 | { | ||
57 | int header_1_ok = 0; | ||
58 | int header_2_ok = 0; | ||
59 | unsigned int time_stamp; | ||
60 | TRACE_FUN(ft_t_noise); | ||
61 | |||
62 | TRACE_CATCH(ftape_abort_operation(),); | ||
63 | ftape_seek_to_bot(); /* prevents extra rewind */ | ||
64 | if (GET4(buffer, 0) != FT_HSEG_MAGIC) { | ||
65 | TRACE_ABORT(-EIO, ft_t_err, | ||
66 | "wrong header signature found, aborting"); | ||
67 | } | ||
68 | /* Be optimistic: */ | ||
69 | PUT4(buffer, FT_SEG_CNT, | ||
70 | zft_written_segments + GET4(buffer, FT_SEG_CNT) + 2); | ||
71 | if ((time_stamp = zft_get_time()) != 0) { | ||
72 | PUT4(buffer, FT_WR_DATE, time_stamp); | ||
73 | if (zft_label_changed) { | ||
74 | PUT4(buffer, FT_LABEL_DATE, time_stamp); | ||
75 | } | ||
76 | } | ||
77 | TRACE(ft_t_noise, | ||
78 | "writing first header segment %d", ft_header_segment_1); | ||
79 | header_1_ok = zft_verify_write_segments(ft_header_segment_1, | ||
80 | buffer, FT_SEGMENT_SIZE, | ||
81 | zft_deblock_buf) >= 0; | ||
82 | TRACE(ft_t_noise, | ||
83 | "writing second header segment %d", ft_header_segment_2); | ||
84 | header_2_ok = zft_verify_write_segments(ft_header_segment_2, | ||
85 | buffer, FT_SEGMENT_SIZE, | ||
86 | zft_deblock_buf) >= 0; | ||
87 | if (!header_1_ok) { | ||
88 | TRACE(ft_t_warn, "Warning: " | ||
89 | "update of first header segment failed"); | ||
90 | } | ||
91 | if (!header_2_ok) { | ||
92 | TRACE(ft_t_warn, "Warning: " | ||
93 | "update of second header segment failed"); | ||
94 | } | ||
95 | if (!header_1_ok && !header_2_ok) { | ||
96 | TRACE_ABORT(-EIO, ft_t_err, "Error: " | ||
97 | "update of both header segments failed."); | ||
98 | } | ||
99 | TRACE_EXIT 0; | ||
100 | } | ||
101 | |||
102 | int zft_update_header_segments(void) | ||
103 | { | ||
104 | TRACE_FUN(ft_t_noise); | ||
105 | |||
106 | /* must NOT use zft_write_protected, as it also includes the | ||
107 | * file access mode. But we also want to update when soft | ||
108 | * write protection is enabled (O_RDONLY) | ||
109 | */ | ||
110 | if (ft_write_protected || zft_old_ftape) { | ||
111 | TRACE_ABORT(0, ft_t_noise, "Tape set read-only: no update"); | ||
112 | } | ||
113 | if (!zft_header_read) { | ||
114 | TRACE_ABORT(0, ft_t_noise, "Nothing to update"); | ||
115 | } | ||
116 | if (!zft_header_changed) { | ||
117 | zft_header_changed = zft_written_segments > 0; | ||
118 | } | ||
119 | if (!zft_header_changed && !zft_volume_table_changed) { | ||
120 | TRACE_ABORT(0, ft_t_noise, "Nothing to update"); | ||
121 | } | ||
122 | TRACE(ft_t_noise, "Updating header segments"); | ||
123 | if (ftape_get_status()->fti_state == writing) { | ||
124 | TRACE_CATCH(ftape_loop_until_writes_done(),); | ||
125 | } | ||
126 | TRACE_CATCH(ftape_abort_operation(),); | ||
127 | |||
128 | zft_deblock_segment = -1; /* invalidate the cache */ | ||
129 | if (zft_header_changed) { | ||
130 | TRACE_CATCH(zft_write_header_segments(zft_hseg_buf),); | ||
131 | } | ||
132 | if (zft_volume_table_changed) { | ||
133 | TRACE_CATCH(zft_update_volume_table(ft_first_data_segment),); | ||
134 | } | ||
135 | zft_header_changed = | ||
136 | zft_volume_table_changed = | ||
137 | zft_label_changed = | ||
138 | zft_written_segments = 0; | ||
139 | TRACE_CATCH(ftape_abort_operation(),); | ||
140 | ftape_seek_to_bot(); | ||
141 | TRACE_EXIT 0; | ||
142 | } | ||
143 | |||
144 | static int read_merge_buffer(int seg_pos, __u8 *buffer, int offset, int seg_sz) | ||
145 | { | ||
146 | int result = 0; | ||
147 | const ft_trace_t old_tracing = TRACE_LEVEL; | ||
148 | TRACE_FUN(ft_t_flow); | ||
149 | |||
150 | if (zft_qic_mode) { | ||
151 | /* writing in the middle of a volume is NOT allowed | ||
152 | * | ||
153 | */ | ||
154 | TRACE(ft_t_noise, "No need to read a segment"); | ||
155 | memset(buffer + offset, 0, seg_sz - offset); | ||
156 | TRACE_EXIT 0; | ||
157 | } | ||
158 | TRACE(ft_t_any, "waiting"); | ||
159 | ftape_start_writing(FT_WR_MULTI); | ||
160 | TRACE_CATCH(ftape_loop_until_writes_done(),); | ||
161 | |||
162 | TRACE(ft_t_noise, "trying to read segment %d from offset %d", | ||
163 | seg_pos, offset); | ||
164 | SET_TRACE_LEVEL(ft_t_bug); | ||
165 | result = zft_fetch_segment_fraction(seg_pos, buffer, | ||
166 | FT_RD_SINGLE, | ||
167 | offset, seg_sz - offset); | ||
168 | SET_TRACE_LEVEL(old_tracing); | ||
169 | if (result != (seg_sz - offset)) { | ||
170 | TRACE(ft_t_noise, "Ignore error: read_segment() result: %d", | ||
171 | result); | ||
172 | memset(buffer + offset, 0, seg_sz - offset); | ||
173 | } | ||
174 | TRACE_EXIT 0; | ||
175 | } | ||
176 | |||
177 | /* flush the write buffer to tape and write an eof-marker at the | ||
178 | * current position if not in raw mode. This function always | ||
179 | * positions the tape before the eof-marker. _ftape_close() should | ||
180 | * then advance to the next segment. | ||
181 | * | ||
182 | * the parameter "finish_volume" describes whether to position before | ||
183 | * or after the possibly created file-mark. We always position after | ||
184 | * the file-mark when called from ftape_close() and a flush was needed | ||
185 | * (that is ftape_write() was the last tape operation before calling | ||
186 | * ftape_flush) But we always position before the file-mark when this | ||
187 | * function get's called from outside ftape_close() | ||
188 | */ | ||
189 | int zft_flush_buffers(void) | ||
190 | { | ||
191 | int result; | ||
192 | int data_remaining; | ||
193 | int this_segs_size; | ||
194 | TRACE_FUN(ft_t_flow); | ||
195 | |||
196 | TRACE(ft_t_data_flow, | ||
197 | "entered, ftape_state = %d", ftape_get_status()->fti_state); | ||
198 | if (ftape_get_status()->fti_state != writing && !need_flush) { | ||
199 | TRACE_ABORT(0, ft_t_noise, "no need for flush"); | ||
200 | } | ||
201 | zft_io_state = zft_idle; /* triggers some initializations for the | ||
202 | * read and write routines | ||
203 | */ | ||
204 | if (last_write_failed) { | ||
205 | ftape_abort_operation(); | ||
206 | TRACE_EXIT -EIO; | ||
207 | } | ||
208 | TRACE(ft_t_noise, "flushing write buffers"); | ||
209 | this_segs_size = zft_get_seg_sz(zft_pos.seg_pos); | ||
210 | if (this_segs_size == zft_pos.seg_byte_pos) { | ||
211 | zft_pos.seg_pos ++; | ||
212 | data_remaining = zft_pos.seg_byte_pos = 0; | ||
213 | } else { | ||
214 | data_remaining = zft_pos.seg_byte_pos; | ||
215 | } | ||
216 | /* If there is any data not written to tape yet, append zero's | ||
217 | * up to the end of the sector (if using compression) or merge | ||
218 | * it with the data existing on the tape Then write the | ||
219 | * segment(s) to tape. | ||
220 | */ | ||
221 | TRACE(ft_t_noise, "Position:\n" | ||
222 | KERN_INFO "seg_pos : %d\n" | ||
223 | KERN_INFO "byte pos : %d\n" | ||
224 | KERN_INFO "remaining: %d", | ||
225 | zft_pos.seg_pos, zft_pos.seg_byte_pos, data_remaining); | ||
226 | if (data_remaining > 0) { | ||
227 | do { | ||
228 | this_segs_size = zft_get_seg_sz(zft_pos.seg_pos); | ||
229 | if (this_segs_size > data_remaining) { | ||
230 | TRACE_CATCH(read_merge_buffer(zft_pos.seg_pos, | ||
231 | zft_deblock_buf, | ||
232 | data_remaining, | ||
233 | this_segs_size), | ||
234 | last_write_failed = 1); | ||
235 | } | ||
236 | result = ftape_write_segment(zft_pos.seg_pos, | ||
237 | zft_deblock_buf, | ||
238 | FT_WR_MULTI); | ||
239 | if (result != this_segs_size) { | ||
240 | TRACE(ft_t_err, "flush buffers failed"); | ||
241 | zft_pos.tape_pos -= zft_pos.seg_byte_pos; | ||
242 | zft_pos.seg_byte_pos = 0; | ||
243 | |||
244 | last_write_failed = 1; | ||
245 | TRACE_EXIT result; | ||
246 | } | ||
247 | zft_written_segments ++; | ||
248 | TRACE(ft_t_data_flow, | ||
249 | "flush, moved out buffer: %d", result); | ||
250 | /* need next segment for more data (empty segments?) | ||
251 | */ | ||
252 | if (result < data_remaining) { | ||
253 | if (result > 0) { | ||
254 | /* move remainder to buffer beginning | ||
255 | */ | ||
256 | memmove(zft_deblock_buf, | ||
257 | zft_deblock_buf + result, | ||
258 | FT_SEGMENT_SIZE - result); | ||
259 | } | ||
260 | } | ||
261 | data_remaining -= result; | ||
262 | zft_pos.seg_pos ++; | ||
263 | } while (data_remaining > 0); | ||
264 | TRACE(ft_t_any, "result: %d", result); | ||
265 | zft_deblock_segment = --zft_pos.seg_pos; | ||
266 | if (data_remaining == 0) { /* first byte next segment */ | ||
267 | zft_pos.seg_byte_pos = this_segs_size; | ||
268 | } else { /* after data previous segment, data_remaining < 0 */ | ||
269 | zft_pos.seg_byte_pos = data_remaining + result; | ||
270 | } | ||
271 | } else { | ||
272 | TRACE(ft_t_noise, "zft_deblock_buf empty"); | ||
273 | zft_pos.seg_pos --; | ||
274 | zft_pos.seg_byte_pos = zft_get_seg_sz (zft_pos.seg_pos); | ||
275 | ftape_start_writing(FT_WR_MULTI); | ||
276 | } | ||
277 | TRACE(ft_t_any, "waiting"); | ||
278 | if ((result = ftape_loop_until_writes_done()) < 0) { | ||
279 | /* that's really bad. What to to with zft_tape_pos? | ||
280 | */ | ||
281 | TRACE(ft_t_err, "flush buffers failed"); | ||
282 | } | ||
283 | TRACE(ft_t_any, "zft_seg_pos: %d, zft_seg_byte_pos: %d", | ||
284 | zft_pos.seg_pos, zft_pos.seg_byte_pos); | ||
285 | last_write_failed = | ||
286 | need_flush = 0; | ||
287 | TRACE_EXIT result; | ||
288 | } | ||
289 | |||
290 | /* return-value: the number of bytes removed from the user-buffer | ||
291 | * | ||
292 | * out: | ||
293 | * int *write_cnt: how much actually has been moved to the | ||
294 | * zft_deblock_buf | ||
295 | * int req_len : MUST NOT BE CHANGED, except at EOT, in | ||
296 | * which case it may be adjusted | ||
297 | * in : | ||
298 | * char *buff : the user buffer | ||
299 | * int buf_pos_write : copy of buf_len_wr int | ||
300 | * this_segs_size : the size in bytes of the actual segment | ||
301 | * char | ||
302 | * *zft_deblock_buf : zft_deblock_buf | ||
303 | */ | ||
304 | static int zft_simple_write(int *cnt, | ||
305 | __u8 *dst_buf, const int seg_sz, | ||
306 | const __u8 __user *src_buf, const int req_len, | ||
307 | const zft_position *pos,const zft_volinfo *volume) | ||
308 | { | ||
309 | int space_left; | ||
310 | TRACE_FUN(ft_t_flow); | ||
311 | |||
312 | /* volume->size holds the tape capacity while volume is open */ | ||
313 | if (pos->tape_pos + volume->blk_sz > volume->size) { | ||
314 | TRACE_EXIT -ENOSPC; | ||
315 | } | ||
316 | /* remaining space in this segment, NOT zft_deblock_buf | ||
317 | */ | ||
318 | space_left = seg_sz - pos->seg_byte_pos; | ||
319 | *cnt = req_len < space_left ? req_len : space_left; | ||
320 | if (copy_from_user(dst_buf + pos->seg_byte_pos, src_buf, *cnt) != 0) { | ||
321 | TRACE_EXIT -EFAULT; | ||
322 | } | ||
323 | TRACE_EXIT *cnt; | ||
324 | } | ||
325 | |||
326 | static int check_write_access(int req_len, | ||
327 | const zft_volinfo **volume, | ||
328 | zft_position *pos, | ||
329 | const unsigned int blk_sz) | ||
330 | { | ||
331 | int result; | ||
332 | TRACE_FUN(ft_t_flow); | ||
333 | |||
334 | if ((req_len % zft_blk_sz) != 0) { | ||
335 | TRACE_ABORT(-EINVAL, ft_t_info, | ||
336 | "write-count %d must be multiple of block-size %d", | ||
337 | req_len, blk_sz); | ||
338 | } | ||
339 | if (zft_io_state == zft_writing) { | ||
340 | /* all other error conditions have been checked earlier | ||
341 | */ | ||
342 | TRACE_EXIT 0; | ||
343 | } | ||
344 | zft_io_state = zft_idle; | ||
345 | TRACE_CATCH(zft_check_write_access(pos),); | ||
346 | /* If we haven't read the header segment yet, do it now. | ||
347 | * This will verify the configuration, get the bad sector | ||
348 | * table and read the volume table segment | ||
349 | */ | ||
350 | if (!zft_header_read) { | ||
351 | TRACE_CATCH(zft_read_header_segments(),); | ||
352 | } | ||
353 | /* fine. Now the tape is either at BOT or at EOD, | ||
354 | * Write start of volume now | ||
355 | */ | ||
356 | TRACE_CATCH(zft_open_volume(pos, blk_sz, zft_use_compression),); | ||
357 | *volume = zft_find_volume(pos->seg_pos); | ||
358 | DUMP_VOLINFO(ft_t_noise, "", *volume); | ||
359 | zft_just_before_eof = 0; | ||
360 | /* now merge with old data if necessary */ | ||
361 | if (!zft_qic_mode && pos->seg_byte_pos != 0){ | ||
362 | result = zft_fetch_segment(pos->seg_pos, | ||
363 | zft_deblock_buf, | ||
364 | FT_RD_SINGLE); | ||
365 | if (result < 0) { | ||
366 | if (result == -EINTR || result == -ENOSPC) { | ||
367 | TRACE_EXIT result; | ||
368 | } | ||
369 | TRACE(ft_t_noise, | ||
370 | "ftape_read_segment() result: %d. " | ||
371 | "This might be normal when using " | ||
372 | "a newly\nformatted tape", result); | ||
373 | memset(zft_deblock_buf, '\0', pos->seg_byte_pos); | ||
374 | } | ||
375 | } | ||
376 | zft_io_state = zft_writing; | ||
377 | TRACE_EXIT 0; | ||
378 | } | ||
379 | |||
380 | static int fill_deblock_buf(__u8 *dst_buf, const int seg_sz, | ||
381 | zft_position *pos, const zft_volinfo *volume, | ||
382 | const char __user *usr_buf, const int req_len) | ||
383 | { | ||
384 | int cnt = 0; | ||
385 | int result = 0; | ||
386 | TRACE_FUN(ft_t_flow); | ||
387 | |||
388 | if (seg_sz == 0) { | ||
389 | TRACE_ABORT(0, ft_t_data_flow, "empty segment"); | ||
390 | } | ||
391 | TRACE(ft_t_data_flow, "\n" | ||
392 | KERN_INFO "remaining req_len: %d\n" | ||
393 | KERN_INFO " buf_pos: %d", | ||
394 | req_len, pos->seg_byte_pos); | ||
395 | /* zft_deblock_buf will not contain a valid segment any longer */ | ||
396 | zft_deblock_segment = -1; | ||
397 | if (zft_use_compression) { | ||
398 | TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),); | ||
399 | TRACE_CATCH(result= (*zft_cmpr_ops->write)(&cnt, | ||
400 | dst_buf, seg_sz, | ||
401 | usr_buf, req_len, | ||
402 | pos, volume),); | ||
403 | } else { | ||
404 | TRACE_CATCH(result= zft_simple_write(&cnt, | ||
405 | dst_buf, seg_sz, | ||
406 | usr_buf, req_len, | ||
407 | pos, volume),); | ||
408 | } | ||
409 | pos->volume_pos += result; | ||
410 | pos->seg_byte_pos += cnt; | ||
411 | pos->tape_pos += cnt; | ||
412 | TRACE(ft_t_data_flow, "\n" | ||
413 | KERN_INFO "removed from user-buffer : %d bytes.\n" | ||
414 | KERN_INFO "copied to zft_deblock_buf: %d bytes.\n" | ||
415 | KERN_INFO "zft_tape_pos : " LL_X " bytes.", | ||
416 | result, cnt, LL(pos->tape_pos)); | ||
417 | TRACE_EXIT result; | ||
418 | } | ||
419 | |||
420 | |||
421 | /* called by the kernel-interface routine "zft_write()" | ||
422 | */ | ||
423 | int _zft_write(const char __user *buff, int req_len) | ||
424 | { | ||
425 | int result = 0; | ||
426 | int written = 0; | ||
427 | int write_cnt; | ||
428 | int seg_sz; | ||
429 | static const zft_volinfo *volume = NULL; | ||
430 | TRACE_FUN(ft_t_flow); | ||
431 | |||
432 | zft_resid = req_len; | ||
433 | last_write_failed = 1; /* reset to 0 when successful */ | ||
434 | /* check if write is allowed | ||
435 | */ | ||
436 | TRACE_CATCH(check_write_access(req_len, &volume,&zft_pos,zft_blk_sz),); | ||
437 | while (req_len > 0) { | ||
438 | /* Allow us to escape from this loop with a signal ! | ||
439 | */ | ||
440 | FT_SIGNAL_EXIT(_DONT_BLOCK); | ||
441 | seg_sz = zft_get_seg_sz(zft_pos.seg_pos); | ||
442 | if ((write_cnt = fill_deblock_buf(zft_deblock_buf, | ||
443 | seg_sz, | ||
444 | &zft_pos, | ||
445 | volume, | ||
446 | buff, | ||
447 | req_len)) < 0) { | ||
448 | zft_resid -= written; | ||
449 | if (write_cnt == -ENOSPC) { | ||
450 | /* leave the remainder to flush_buffers() | ||
451 | */ | ||
452 | TRACE(ft_t_info, "No space left on device"); | ||
453 | last_write_failed = 0; | ||
454 | if (!need_flush) { | ||
455 | need_flush = written > 0; | ||
456 | } | ||
457 | TRACE_EXIT written > 0 ? written : -ENOSPC; | ||
458 | } else { | ||
459 | TRACE_EXIT result; | ||
460 | } | ||
461 | } | ||
462 | if (zft_pos.seg_byte_pos == seg_sz) { | ||
463 | TRACE_CATCH(ftape_write_segment(zft_pos.seg_pos, | ||
464 | zft_deblock_buf, | ||
465 | FT_WR_ASYNC), | ||
466 | zft_resid -= written); | ||
467 | zft_written_segments ++; | ||
468 | zft_pos.seg_byte_pos = 0; | ||
469 | zft_deblock_segment = zft_pos.seg_pos; | ||
470 | ++zft_pos.seg_pos; | ||
471 | } | ||
472 | written += write_cnt; | ||
473 | buff += write_cnt; | ||
474 | req_len -= write_cnt; | ||
475 | } /* while (req_len > 0) */ | ||
476 | TRACE(ft_t_data_flow, "remaining in blocking buffer: %d", | ||
477 | zft_pos.seg_byte_pos); | ||
478 | TRACE(ft_t_data_flow, "just written bytes: %d", written); | ||
479 | last_write_failed = 0; | ||
480 | zft_resid -= written; | ||
481 | need_flush = need_flush || written > 0; | ||
482 | TRACE_EXIT written; /* bytes written */ | ||
483 | } | ||
diff --git a/drivers/char/ftape/zftape/zftape-write.h b/drivers/char/ftape/zftape/zftape-write.h deleted file mode 100644 index ea887015b493..000000000000 --- a/drivers/char/ftape/zftape/zftape-write.h +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_WRITE_H | ||
2 | #define _ZFTAPE_WRITE_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996, 1997 Claus-Justus Heine | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:19:13 $ | ||
25 | * | ||
26 | * This file contains the definitions for the write functions | ||
27 | * for the zftape driver for Linux. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | extern int zft_flush_buffers(void); | ||
32 | extern int zft_update_header_segments(void); | ||
33 | extern void zft_prevent_flush(void); | ||
34 | |||
35 | /* hook for the VFS interface | ||
36 | */ | ||
37 | extern int _zft_write(const char __user *buff, int req_len); | ||
38 | #endif /* _ZFTAPE_WRITE_H */ | ||
diff --git a/drivers/char/ftape/zftape/zftape_syms.c b/drivers/char/ftape/zftape/zftape_syms.c deleted file mode 100644 index 2db1401682df..000000000000 --- a/drivers/char/ftape/zftape/zftape_syms.c +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1997 Claus-Justus Heine | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | * | ||
19 | * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape_syms.c,v $ | ||
20 | * $Revision: 1.3 $ | ||
21 | * $Date: 1997/10/05 19:19:14 $ | ||
22 | * | ||
23 | * This file contains the symbols that the zftape frontend to | ||
24 | * the ftape floppy tape driver exports | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | |||
29 | #include <linux/zftape.h> | ||
30 | |||
31 | #include "../zftape/zftape-init.h" | ||
32 | #include "../zftape/zftape-read.h" | ||
33 | #include "../zftape/zftape-buffers.h" | ||
34 | #include "../zftape/zftape-ctl.h" | ||
35 | |||
36 | /* zftape-init.c */ | ||
37 | EXPORT_SYMBOL(zft_cmpr_register); | ||
38 | /* zftape-read.c */ | ||
39 | EXPORT_SYMBOL(zft_fetch_segment_fraction); | ||
40 | /* zftape-buffers.c */ | ||
41 | EXPORT_SYMBOL(zft_vmalloc_once); | ||
42 | EXPORT_SYMBOL(zft_vmalloc_always); | ||
43 | EXPORT_SYMBOL(zft_vfree); | ||
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 091a11cd878c..20dc3be5ecfc 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/fcntl.h> | 21 | #include <linux/fcntl.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/poll.h> | 23 | #include <linux/poll.h> |
24 | #include <linux/mm.h> | ||
24 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
25 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
26 | #include <linux/sysctl.h> | 27 | #include <linux/sysctl.h> |
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index ebace201bec6..26a860adcb38 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
38 | #include <linux/fs.h> | 38 | #include <linux/fs.h> |
39 | #include <linux/sched.h> | ||
39 | #include <linux/init.h> | 40 | #include <linux/init.h> |
40 | #include <linux/miscdevice.h> | 41 | #include <linux/miscdevice.h> |
41 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 050ced247f68..bb9a43c6cf3d 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/sched.h> | ||
25 | #include <linux/miscdevice.h> | 26 | #include <linux/miscdevice.h> |
26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index e5cb0fdab9b1..b1dc63e4ac7b 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c | |||
@@ -21,6 +21,7 @@ | |||
21 | etc voltage & frequency control is not supported! | 21 | etc voltage & frequency control is not supported! |
22 | */ | 22 | */ |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/sched.h> | ||
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 26be4ea8a38a..e8ef62b83d6b 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/timer.h> | 34 | #include <linux/timer.h> |
35 | #include <linux/dmi.h> | 35 | #include <linux/dmi.h> |
36 | #include <linux/jiffies.h> | ||
36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
37 | 38 | ||
38 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ | 39 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ |
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c index 0606744c3f84..5e122501fd80 100644 --- a/drivers/infiniband/ulp/iser/iser_memory.c +++ b/drivers/infiniband/ulp/iser/iser_memory.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/mm.h> | 37 | #include <linux/mm.h> |
38 | #include <linux/highmem.h> | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | #include <asm/scatterlist.h> | 40 | #include <asm/scatterlist.h> |
40 | #include <linux/scatterlist.h> | 41 | #include <linux/scatterlist.h> |
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 1f5ebe9ee72c..03319ea5aa0c 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c | |||
@@ -10,6 +10,8 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
13 | #include <linux/timer.h> | ||
14 | #include <linux/jiffies.h> | ||
13 | 15 | ||
14 | #include "isdn_divert.h" | 16 | #include "isdn_divert.h" |
15 | 17 | ||
diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c index fa651886ab4f..54b155c7026f 100644 --- a/drivers/leds/ledtrig-ide-disk.c +++ b/drivers/leds/ledtrig-ide-disk.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/jiffies.h> | ||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/timer.h> | 18 | #include <linux/timer.h> |
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 29a8818a32ec..d756bdb01c59 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/jiffies.h> | ||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/list.h> | 18 | #include <linux/list.h> |
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 55bc891768c2..8a7dd507cf6e 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/input.h> | 30 | #include <linux/input.h> |
31 | #include <linux/dvb/frontend.h> | 31 | #include <linux/dvb/frontend.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/mm.h> | ||
33 | 34 | ||
34 | #include "dmxdev.h" | 35 | #include "dmxdev.h" |
35 | #include "dvb_demux.h" | 36 | #include "dvb_demux.h" |
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 72ef7bde3346..f143e13b229d 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c | |||
@@ -26,6 +26,7 @@ | |||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/mm.h> | ||
29 | #include "ehea.h" | 30 | #include "ehea.h" |
30 | #include "ehea_phyp.h" | 31 | #include "ehea_phyp.h" |
31 | #include "ehea_qmr.h" | 32 | #include "ehea_qmr.h" |
diff --git a/drivers/net/lance.c b/drivers/net/lance.c index 6efbd499d752..4256c13c73c2 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c | |||
@@ -57,6 +57,7 @@ static const char version[] = "lance.c:v1.16 2006/11/09 dplatt@3do.com, becker@c | |||
57 | #include <linux/netdevice.h> | 57 | #include <linux/netdevice.h> |
58 | #include <linux/etherdevice.h> | 58 | #include <linux/etherdevice.h> |
59 | #include <linux/skbuff.h> | 59 | #include <linux/skbuff.h> |
60 | #include <linux/mm.h> | ||
60 | #include <linux/bitops.h> | 61 | #include <linux/bitops.h> |
61 | 62 | ||
62 | #include <asm/io.h> | 63 | #include <asm/io.h> |
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index d66328975425..1a6fed76d4cc 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/netdevice.h> | 37 | #include <linux/netdevice.h> |
38 | #include <linux/etherdevice.h> | 38 | #include <linux/etherdevice.h> |
39 | #include <linux/mm.h> | ||
39 | 40 | ||
40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
41 | #include <asm/system.h> | 42 | #include <asm/system.h> |
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 12cbfd190dd7..92d11b961db8 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c | |||
@@ -114,6 +114,7 @@ | |||
114 | #include <linux/dma-mapping.h> | 114 | #include <linux/dma-mapping.h> |
115 | #include <linux/ip.h> | 115 | #include <linux/ip.h> |
116 | #include <linux/mii.h> | 116 | #include <linux/mii.h> |
117 | #include <linux/mm.h> | ||
117 | 118 | ||
118 | #include "h/skdrv1st.h" | 119 | #include "h/skdrv1st.h" |
119 | #include "h/skdrv2nd.h" | 120 | #include "h/skdrv2nd.h" |
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 7a0aee6c869d..bf873ea25797 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/ethtool.h> | 41 | #include <linux/ethtool.h> |
42 | #include <linux/mii.h> | 42 | #include <linux/mii.h> |
43 | #include <linux/if_vlan.h> | 43 | #include <linux/if_vlan.h> |
44 | #include <linux/mm.h> | ||
44 | #include <asm/processor.h> /* Processor type for cache alignment. */ | 45 | #include <asm/processor.h> /* Processor type for cache alignment. */ |
45 | #include <asm/uaccess.h> | 46 | #include <asm/uaccess.h> |
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index b865db363ba0..47a1c09d19ac 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c | |||
@@ -38,6 +38,7 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.ne | |||
38 | #include <linux/skbuff.h> | 38 | #include <linux/skbuff.h> |
39 | #include <linux/bitops.h> | 39 | #include <linux/bitops.h> |
40 | 40 | ||
41 | #include <asm/cacheflush.h> | ||
41 | #include <asm/setup.h> | 42 | #include <asm/setup.h> |
42 | #include <asm/irq.h> | 43 | #include <asm/irq.h> |
43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 334c6cfd6595..cf44e72399b9 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/if_vlan.h> | 56 | #include <linux/if_vlan.h> |
57 | #include <linux/bitops.h> | 57 | #include <linux/bitops.h> |
58 | #include <linux/mutex.h> | 58 | #include <linux/mutex.h> |
59 | #include <linux/mm.h> | ||
59 | 60 | ||
60 | #include <asm/system.h> | 61 | #include <asm/system.h> |
61 | #include <asm/io.h> | 62 | #include <asm/io.h> |
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index ec432ea879fb..ef671739cfea 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
33 | #include <linux/etherdevice.h> | 33 | #include <linux/etherdevice.h> |
34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
35 | #include <linux/mm.h> | ||
35 | #include <linux/bitops.h> | 36 | #include <linux/bitops.h> |
36 | 37 | ||
37 | #include <asm/system.h> | 38 | #include <asm/system.h> |
@@ -3012,6 +3013,11 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, | |||
3012 | #endif | 3013 | #endif |
3013 | 3014 | ||
3014 | err = -ENODEV; | 3015 | err = -ENODEV; |
3016 | |||
3017 | if (pci_enable_device(pdev)) | ||
3018 | goto err_out; | ||
3019 | pci_set_master(pdev); | ||
3020 | |||
3015 | if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) { | 3021 | if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) { |
3016 | qp = quattro_pci_find(pdev); | 3022 | qp = quattro_pci_find(pdev); |
3017 | if (qp == NULL) | 3023 | if (qp == NULL) |
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 8ddea1da7c05..9781b16bb8b6 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c | |||
@@ -117,6 +117,7 @@ static const int multicast_filter_limit = 32; | |||
117 | #include <linux/netdevice.h> | 117 | #include <linux/netdevice.h> |
118 | #include <linux/etherdevice.h> | 118 | #include <linux/etherdevice.h> |
119 | #include <linux/skbuff.h> | 119 | #include <linux/skbuff.h> |
120 | #include <linux/mm.h> | ||
120 | #include <linux/init.h> | 121 | #include <linux/init.h> |
121 | #include <linux/delay.h> | 122 | #include <linux/delay.h> |
122 | #include <linux/ethtool.h> | 123 | #include <linux/ethtool.h> |
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 73a58c73d526..fc405f0165d9 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/pci.h> | 1 | #include <linux/pci.h> |
2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
3 | #include <linux/sched.h> | ||
3 | #include <linux/ioport.h> | 4 | #include <linux/ioport.h> |
4 | #include <linux/wait.h> | 5 | #include <linux/wait.h> |
5 | 6 | ||
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 79ffef6bfaf8..a2cef57d7bcb 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1264,15 +1264,21 @@ __dasd_check_expire(struct dasd_device * device) | |||
1264 | if (list_empty(&device->ccw_queue)) | 1264 | if (list_empty(&device->ccw_queue)) |
1265 | return; | 1265 | return; |
1266 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); | 1266 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); |
1267 | if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) { | 1267 | if ((cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) && |
1268 | if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) { | 1268 | (time_after_eq(jiffies, cqr->expires + cqr->starttime))) { |
1269 | if (device->discipline->term_IO(cqr) != 0) { | ||
1270 | /* Hmpf, try again in 5 sec */ | ||
1271 | dasd_set_timer(device, 5*HZ); | ||
1272 | DEV_MESSAGE(KERN_ERR, device, | ||
1273 | "internal error - timeout (%is) expired " | ||
1274 | "for cqr %p, termination failed, " | ||
1275 | "retrying in 5s", | ||
1276 | (cqr->expires/HZ), cqr); | ||
1277 | } else { | ||
1269 | DEV_MESSAGE(KERN_ERR, device, | 1278 | DEV_MESSAGE(KERN_ERR, device, |
1270 | "internal error - timeout (%is) expired " | 1279 | "internal error - timeout (%is) expired " |
1271 | "for cqr %p (%i retries left)", | 1280 | "for cqr %p (%i retries left)", |
1272 | (cqr->expires/HZ), cqr, cqr->retries); | 1281 | (cqr->expires/HZ), cqr, cqr->retries); |
1273 | if (device->discipline->term_IO(cqr) != 0) | ||
1274 | /* Hmpf, try again in 1/10 sec */ | ||
1275 | dasd_set_timer(device, 10); | ||
1276 | } | 1282 | } |
1277 | } | 1283 | } |
1278 | } | 1284 | } |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 91cf971f0652..17fdd8c9f740 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -684,21 +684,26 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, | |||
684 | const char *buf, size_t count) | 684 | const char *buf, size_t count) |
685 | { | 685 | { |
686 | struct dasd_devmap *devmap; | 686 | struct dasd_devmap *devmap; |
687 | int ro_flag; | 687 | int val; |
688 | char *endp; | ||
688 | 689 | ||
689 | devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); | 690 | devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); |
690 | if (IS_ERR(devmap)) | 691 | if (IS_ERR(devmap)) |
691 | return PTR_ERR(devmap); | 692 | return PTR_ERR(devmap); |
692 | ro_flag = buf[0] == '1'; | 693 | |
694 | val = simple_strtoul(buf, &endp, 0); | ||
695 | if (((endp + 1) < (buf + count)) || (val > 1)) | ||
696 | return -EINVAL; | ||
697 | |||
693 | spin_lock(&dasd_devmap_lock); | 698 | spin_lock(&dasd_devmap_lock); |
694 | if (ro_flag) | 699 | if (val) |
695 | devmap->features |= DASD_FEATURE_READONLY; | 700 | devmap->features |= DASD_FEATURE_READONLY; |
696 | else | 701 | else |
697 | devmap->features &= ~DASD_FEATURE_READONLY; | 702 | devmap->features &= ~DASD_FEATURE_READONLY; |
698 | if (devmap->device) | 703 | if (devmap->device) |
699 | devmap->device->features = devmap->features; | 704 | devmap->device->features = devmap->features; |
700 | if (devmap->device && devmap->device->gdp) | 705 | if (devmap->device && devmap->device->gdp) |
701 | set_disk_ro(devmap->device->gdp, ro_flag); | 706 | set_disk_ro(devmap->device->gdp, val); |
702 | spin_unlock(&dasd_devmap_lock); | 707 | spin_unlock(&dasd_devmap_lock); |
703 | return count; | 708 | return count; |
704 | } | 709 | } |
@@ -729,17 +734,22 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr, | |||
729 | { | 734 | { |
730 | struct dasd_devmap *devmap; | 735 | struct dasd_devmap *devmap; |
731 | ssize_t rc; | 736 | ssize_t rc; |
732 | int use_diag; | 737 | int val; |
738 | char *endp; | ||
733 | 739 | ||
734 | devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); | 740 | devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); |
735 | if (IS_ERR(devmap)) | 741 | if (IS_ERR(devmap)) |
736 | return PTR_ERR(devmap); | 742 | return PTR_ERR(devmap); |
737 | use_diag = buf[0] == '1'; | 743 | |
744 | val = simple_strtoul(buf, &endp, 0); | ||
745 | if (((endp + 1) < (buf + count)) || (val > 1)) | ||
746 | return -EINVAL; | ||
747 | |||
738 | spin_lock(&dasd_devmap_lock); | 748 | spin_lock(&dasd_devmap_lock); |
739 | /* Changing diag discipline flag is only allowed in offline state. */ | 749 | /* Changing diag discipline flag is only allowed in offline state. */ |
740 | rc = count; | 750 | rc = count; |
741 | if (!devmap->device) { | 751 | if (!devmap->device) { |
742 | if (use_diag) | 752 | if (val) |
743 | devmap->features |= DASD_FEATURE_USEDIAG; | 753 | devmap->features |= DASD_FEATURE_USEDIAG; |
744 | else | 754 | else |
745 | devmap->features &= ~DASD_FEATURE_USEDIAG; | 755 | devmap->features &= ~DASD_FEATURE_USEDIAG; |
@@ -854,14 +864,20 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr, | |||
854 | const char *buf, size_t count) | 864 | const char *buf, size_t count) |
855 | { | 865 | { |
856 | struct dasd_devmap *devmap; | 866 | struct dasd_devmap *devmap; |
857 | int rc; | 867 | int val, rc; |
868 | char *endp; | ||
858 | 869 | ||
859 | devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); | 870 | devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); |
860 | if (IS_ERR(devmap)) | 871 | if (IS_ERR(devmap)) |
861 | return PTR_ERR(devmap); | 872 | return PTR_ERR(devmap); |
862 | if (!devmap->device) | 873 | if (!devmap->device) |
863 | return count; | 874 | return -ENODEV; |
864 | if (buf[0] == '1') { | 875 | |
876 | val = simple_strtoul(buf, &endp, 0); | ||
877 | if (((endp + 1) < (buf + count)) || (val > 1)) | ||
878 | return -EINVAL; | ||
879 | |||
880 | if (val) { | ||
865 | rc = dasd_eer_enable(devmap->device); | 881 | rc = dasd_eer_enable(devmap->device); |
866 | if (rc) | 882 | if (rc) |
867 | return rc; | 883 | return rc; |
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index d7de175d53f0..c9321b920e90 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c | |||
@@ -299,14 +299,14 @@ raw3215_timeout(unsigned long __data) | |||
299 | struct raw3215_info *raw = (struct raw3215_info *) __data; | 299 | struct raw3215_info *raw = (struct raw3215_info *) __data; |
300 | unsigned long flags; | 300 | unsigned long flags; |
301 | 301 | ||
302 | spin_lock_irqsave(raw->lock, flags); | 302 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
303 | if (raw->flags & RAW3215_TIMER_RUNS) { | 303 | if (raw->flags & RAW3215_TIMER_RUNS) { |
304 | del_timer(&raw->timer); | 304 | del_timer(&raw->timer); |
305 | raw->flags &= ~RAW3215_TIMER_RUNS; | 305 | raw->flags &= ~RAW3215_TIMER_RUNS; |
306 | raw3215_mk_write_req(raw); | 306 | raw3215_mk_write_req(raw); |
307 | raw3215_start_io(raw); | 307 | raw3215_start_io(raw); |
308 | } | 308 | } |
309 | spin_unlock_irqrestore(raw->lock, flags); | 309 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
310 | } | 310 | } |
311 | 311 | ||
312 | /* | 312 | /* |
@@ -355,10 +355,10 @@ raw3215_tasklet(void *data) | |||
355 | unsigned long flags; | 355 | unsigned long flags; |
356 | 356 | ||
357 | raw = (struct raw3215_info *) data; | 357 | raw = (struct raw3215_info *) data; |
358 | spin_lock_irqsave(raw->lock, flags); | 358 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
359 | raw3215_mk_write_req(raw); | 359 | raw3215_mk_write_req(raw); |
360 | raw3215_try_io(raw); | 360 | raw3215_try_io(raw); |
361 | spin_unlock_irqrestore(raw->lock, flags); | 361 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
362 | /* Check for pending message from raw3215_irq */ | 362 | /* Check for pending message from raw3215_irq */ |
363 | if (raw->message != NULL) { | 363 | if (raw->message != NULL) { |
364 | printk(raw->message, raw->msg_dstat, raw->msg_cstat); | 364 | printk(raw->message, raw->msg_dstat, raw->msg_cstat); |
@@ -512,9 +512,9 @@ raw3215_make_room(struct raw3215_info *raw, unsigned int length) | |||
512 | if (RAW3215_BUFFER_SIZE - raw->count >= length) | 512 | if (RAW3215_BUFFER_SIZE - raw->count >= length) |
513 | break; | 513 | break; |
514 | /* there might be another cpu waiting for the lock */ | 514 | /* there might be another cpu waiting for the lock */ |
515 | spin_unlock(raw->lock); | 515 | spin_unlock(get_ccwdev_lock(raw->cdev)); |
516 | udelay(100); | 516 | udelay(100); |
517 | spin_lock(raw->lock); | 517 | spin_lock(get_ccwdev_lock(raw->cdev)); |
518 | } | 518 | } |
519 | } | 519 | } |
520 | 520 | ||
@@ -528,7 +528,7 @@ raw3215_write(struct raw3215_info *raw, const char *str, unsigned int length) | |||
528 | int c, count; | 528 | int c, count; |
529 | 529 | ||
530 | while (length > 0) { | 530 | while (length > 0) { |
531 | spin_lock_irqsave(raw->lock, flags); | 531 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
532 | count = (length > RAW3215_BUFFER_SIZE) ? | 532 | count = (length > RAW3215_BUFFER_SIZE) ? |
533 | RAW3215_BUFFER_SIZE : length; | 533 | RAW3215_BUFFER_SIZE : length; |
534 | length -= count; | 534 | length -= count; |
@@ -555,7 +555,7 @@ raw3215_write(struct raw3215_info *raw, const char *str, unsigned int length) | |||
555 | /* start or queue request */ | 555 | /* start or queue request */ |
556 | raw3215_try_io(raw); | 556 | raw3215_try_io(raw); |
557 | } | 557 | } |
558 | spin_unlock_irqrestore(raw->lock, flags); | 558 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
559 | } | 559 | } |
560 | } | 560 | } |
561 | 561 | ||
@@ -568,7 +568,7 @@ raw3215_putchar(struct raw3215_info *raw, unsigned char ch) | |||
568 | unsigned long flags; | 568 | unsigned long flags; |
569 | unsigned int length, i; | 569 | unsigned int length, i; |
570 | 570 | ||
571 | spin_lock_irqsave(raw->lock, flags); | 571 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
572 | if (ch == '\t') { | 572 | if (ch == '\t') { |
573 | length = TAB_STOP_SIZE - (raw->line_pos%TAB_STOP_SIZE); | 573 | length = TAB_STOP_SIZE - (raw->line_pos%TAB_STOP_SIZE); |
574 | raw->line_pos += length; | 574 | raw->line_pos += length; |
@@ -592,7 +592,7 @@ raw3215_putchar(struct raw3215_info *raw, unsigned char ch) | |||
592 | /* start or queue request */ | 592 | /* start or queue request */ |
593 | raw3215_try_io(raw); | 593 | raw3215_try_io(raw); |
594 | } | 594 | } |
595 | spin_unlock_irqrestore(raw->lock, flags); | 595 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
596 | } | 596 | } |
597 | 597 | ||
598 | /* | 598 | /* |
@@ -604,13 +604,13 @@ raw3215_flush_buffer(struct raw3215_info *raw) | |||
604 | { | 604 | { |
605 | unsigned long flags; | 605 | unsigned long flags; |
606 | 606 | ||
607 | spin_lock_irqsave(raw->lock, flags); | 607 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
608 | if (raw->count > 0) { | 608 | if (raw->count > 0) { |
609 | raw->flags |= RAW3215_FLUSHING; | 609 | raw->flags |= RAW3215_FLUSHING; |
610 | raw3215_try_io(raw); | 610 | raw3215_try_io(raw); |
611 | raw->flags &= ~RAW3215_FLUSHING; | 611 | raw->flags &= ~RAW3215_FLUSHING; |
612 | } | 612 | } |
613 | spin_unlock_irqrestore(raw->lock, flags); | 613 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
614 | } | 614 | } |
615 | 615 | ||
616 | /* | 616 | /* |
@@ -625,9 +625,9 @@ raw3215_startup(struct raw3215_info *raw) | |||
625 | return 0; | 625 | return 0; |
626 | raw->line_pos = 0; | 626 | raw->line_pos = 0; |
627 | raw->flags |= RAW3215_ACTIVE; | 627 | raw->flags |= RAW3215_ACTIVE; |
628 | spin_lock_irqsave(raw->lock, flags); | 628 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
629 | raw3215_try_io(raw); | 629 | raw3215_try_io(raw); |
630 | spin_unlock_irqrestore(raw->lock, flags); | 630 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
631 | 631 | ||
632 | return 0; | 632 | return 0; |
633 | } | 633 | } |
@@ -644,21 +644,21 @@ raw3215_shutdown(struct raw3215_info *raw) | |||
644 | if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED)) | 644 | if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED)) |
645 | return; | 645 | return; |
646 | /* Wait for outstanding requests, then free irq */ | 646 | /* Wait for outstanding requests, then free irq */ |
647 | spin_lock_irqsave(raw->lock, flags); | 647 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
648 | if ((raw->flags & RAW3215_WORKING) || | 648 | if ((raw->flags & RAW3215_WORKING) || |
649 | raw->queued_write != NULL || | 649 | raw->queued_write != NULL || |
650 | raw->queued_read != NULL) { | 650 | raw->queued_read != NULL) { |
651 | raw->flags |= RAW3215_CLOSING; | 651 | raw->flags |= RAW3215_CLOSING; |
652 | add_wait_queue(&raw->empty_wait, &wait); | 652 | add_wait_queue(&raw->empty_wait, &wait); |
653 | set_current_state(TASK_INTERRUPTIBLE); | 653 | set_current_state(TASK_INTERRUPTIBLE); |
654 | spin_unlock_irqrestore(raw->lock, flags); | 654 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
655 | schedule(); | 655 | schedule(); |
656 | spin_lock_irqsave(raw->lock, flags); | 656 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
657 | remove_wait_queue(&raw->empty_wait, &wait); | 657 | remove_wait_queue(&raw->empty_wait, &wait); |
658 | set_current_state(TASK_RUNNING); | 658 | set_current_state(TASK_RUNNING); |
659 | raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING); | 659 | raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING); |
660 | } | 660 | } |
661 | spin_unlock_irqrestore(raw->lock, flags); | 661 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
662 | } | 662 | } |
663 | 663 | ||
664 | static int | 664 | static int |
@@ -686,7 +686,6 @@ raw3215_probe (struct ccw_device *cdev) | |||
686 | } | 686 | } |
687 | 687 | ||
688 | raw->cdev = cdev; | 688 | raw->cdev = cdev; |
689 | raw->lock = get_ccwdev_lock(cdev); | ||
690 | raw->inbuf = (char *) raw + sizeof(struct raw3215_info); | 689 | raw->inbuf = (char *) raw + sizeof(struct raw3215_info); |
691 | memset(raw, 0, sizeof(struct raw3215_info)); | 690 | memset(raw, 0, sizeof(struct raw3215_info)); |
692 | raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE, | 691 | raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE, |
@@ -809,9 +808,9 @@ con3215_unblank(void) | |||
809 | unsigned long flags; | 808 | unsigned long flags; |
810 | 809 | ||
811 | raw = raw3215[0]; /* console 3215 is the first one */ | 810 | raw = raw3215[0]; /* console 3215 is the first one */ |
812 | spin_lock_irqsave(raw->lock, flags); | 811 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
813 | raw3215_make_room(raw, RAW3215_BUFFER_SIZE); | 812 | raw3215_make_room(raw, RAW3215_BUFFER_SIZE); |
814 | spin_unlock_irqrestore(raw->lock, flags); | 813 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
815 | } | 814 | } |
816 | 815 | ||
817 | static int __init | 816 | static int __init |
@@ -873,7 +872,6 @@ con3215_init(void) | |||
873 | raw->buffer = (char *) alloc_bootmem_low(RAW3215_BUFFER_SIZE); | 872 | raw->buffer = (char *) alloc_bootmem_low(RAW3215_BUFFER_SIZE); |
874 | raw->inbuf = (char *) alloc_bootmem_low(RAW3215_INBUF_SIZE); | 873 | raw->inbuf = (char *) alloc_bootmem_low(RAW3215_INBUF_SIZE); |
875 | raw->cdev = cdev; | 874 | raw->cdev = cdev; |
876 | raw->lock = get_ccwdev_lock(cdev); | ||
877 | cdev->dev.driver_data = raw; | 875 | cdev->dev.driver_data = raw; |
878 | cdev->handler = raw3215_irq; | 876 | cdev->handler = raw3215_irq; |
879 | 877 | ||
@@ -1066,10 +1064,10 @@ tty3215_unthrottle(struct tty_struct * tty) | |||
1066 | 1064 | ||
1067 | raw = (struct raw3215_info *) tty->driver_data; | 1065 | raw = (struct raw3215_info *) tty->driver_data; |
1068 | if (raw->flags & RAW3215_THROTTLED) { | 1066 | if (raw->flags & RAW3215_THROTTLED) { |
1069 | spin_lock_irqsave(raw->lock, flags); | 1067 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
1070 | raw->flags &= ~RAW3215_THROTTLED; | 1068 | raw->flags &= ~RAW3215_THROTTLED; |
1071 | raw3215_try_io(raw); | 1069 | raw3215_try_io(raw); |
1072 | spin_unlock_irqrestore(raw->lock, flags); | 1070 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
1073 | } | 1071 | } |
1074 | } | 1072 | } |
1075 | 1073 | ||
@@ -1096,10 +1094,10 @@ tty3215_start(struct tty_struct *tty) | |||
1096 | 1094 | ||
1097 | raw = (struct raw3215_info *) tty->driver_data; | 1095 | raw = (struct raw3215_info *) tty->driver_data; |
1098 | if (raw->flags & RAW3215_STOPPED) { | 1096 | if (raw->flags & RAW3215_STOPPED) { |
1099 | spin_lock_irqsave(raw->lock, flags); | 1097 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
1100 | raw->flags &= ~RAW3215_STOPPED; | 1098 | raw->flags &= ~RAW3215_STOPPED; |
1101 | raw3215_try_io(raw); | 1099 | raw3215_try_io(raw); |
1102 | spin_unlock_irqrestore(raw->lock, flags); | 1100 | spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); |
1103 | } | 1101 | } |
1104 | } | 1102 | } |
1105 | 1103 | ||
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c index 32004aae95c1..ffa9282ce97a 100644 --- a/drivers/s390/char/sclp_quiesce.c +++ b/drivers/s390/char/sclp_quiesce.c | |||
@@ -19,52 +19,17 @@ | |||
19 | 19 | ||
20 | #include "sclp.h" | 20 | #include "sclp.h" |
21 | 21 | ||
22 | |||
23 | #ifdef CONFIG_SMP | ||
24 | /* Signal completion of shutdown process. All CPUs except the first to enter | ||
25 | * this function: go to stopped state. First CPU: wait until all other | ||
26 | * CPUs are in stopped or check stop state. Afterwards, load special PSW | ||
27 | * to indicate completion. */ | ||
28 | static void | ||
29 | do_load_quiesce_psw(void * __unused) | ||
30 | { | ||
31 | static atomic_t cpuid = ATOMIC_INIT(-1); | ||
32 | psw_t quiesce_psw; | ||
33 | int cpu; | ||
34 | |||
35 | if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) | ||
36 | signal_processor(smp_processor_id(), sigp_stop); | ||
37 | /* Wait for all other cpus to enter stopped state */ | ||
38 | for_each_online_cpu(cpu) { | ||
39 | if (cpu == smp_processor_id()) | ||
40 | continue; | ||
41 | while(!smp_cpu_not_running(cpu)) | ||
42 | cpu_relax(); | ||
43 | } | ||
44 | /* Quiesce the last cpu with the special psw */ | ||
45 | quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; | ||
46 | quiesce_psw.addr = 0xfff; | ||
47 | __load_psw(quiesce_psw); | ||
48 | } | ||
49 | |||
50 | /* Shutdown handler. Perform shutdown function on all CPUs. */ | ||
51 | static void | ||
52 | do_machine_quiesce(void) | ||
53 | { | ||
54 | on_each_cpu(do_load_quiesce_psw, NULL, 0, 0); | ||
55 | } | ||
56 | #else | ||
57 | /* Shutdown handler. Signal completion of shutdown by loading special PSW. */ | 22 | /* Shutdown handler. Signal completion of shutdown by loading special PSW. */ |
58 | static void | 23 | static void |
59 | do_machine_quiesce(void) | 24 | do_machine_quiesce(void) |
60 | { | 25 | { |
61 | psw_t quiesce_psw; | 26 | psw_t quiesce_psw; |
62 | 27 | ||
28 | smp_send_stop(); | ||
63 | quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; | 29 | quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; |
64 | quiesce_psw.addr = 0xfff; | 30 | quiesce_psw.addr = 0xfff; |
65 | __load_psw(quiesce_psw); | 31 | __load_psw(quiesce_psw); |
66 | } | 32 | } |
67 | #endif | ||
68 | 33 | ||
69 | /* Handler for quiesce event. Start shutdown procedure. */ | 34 | /* Handler for quiesce event. Start shutdown procedure. */ |
70 | static void | 35 | static void |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 2d78f0f4a40f..dbfb77b03928 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -251,6 +251,8 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) | |||
251 | cc = cio_clear(sch); | 251 | cc = cio_clear(sch); |
252 | if (cc == -ENODEV) | 252 | if (cc == -ENODEV) |
253 | goto out_unreg; | 253 | goto out_unreg; |
254 | /* Request retry of internal operation. */ | ||
255 | device_set_intretry(sch); | ||
254 | /* Call handler. */ | 256 | /* Call handler. */ |
255 | if (sch->driver && sch->driver->termination) | 257 | if (sch->driver && sch->driver->termination) |
256 | sch->driver->termination(&sch->dev); | 258 | sch->driver->termination(&sch->dev); |
@@ -711,9 +713,6 @@ static inline int check_for_io_on_path(struct subchannel *sch, int index) | |||
711 | { | 713 | { |
712 | int cc; | 714 | int cc; |
713 | 715 | ||
714 | if (!device_is_online(sch)) | ||
715 | /* cio could be doing I/O. */ | ||
716 | return 0; | ||
717 | cc = stsch(sch->schid, &sch->schib); | 716 | cc = stsch(sch->schid, &sch->schib); |
718 | if (cc) | 717 | if (cc) |
719 | return 0; | 718 | return 0; |
@@ -722,6 +721,26 @@ static inline int check_for_io_on_path(struct subchannel *sch, int index) | |||
722 | return 0; | 721 | return 0; |
723 | } | 722 | } |
724 | 723 | ||
724 | static void terminate_internal_io(struct subchannel *sch) | ||
725 | { | ||
726 | if (cio_clear(sch)) { | ||
727 | /* Recheck device in case clear failed. */ | ||
728 | sch->lpm = 0; | ||
729 | if (device_trigger_verify(sch) != 0) { | ||
730 | if(css_enqueue_subchannel_slow(sch->schid)) { | ||
731 | css_clear_subchannel_slow_list(); | ||
732 | need_rescan = 1; | ||
733 | } | ||
734 | } | ||
735 | return; | ||
736 | } | ||
737 | /* Request retry of internal operation. */ | ||
738 | device_set_intretry(sch); | ||
739 | /* Call handler. */ | ||
740 | if (sch->driver && sch->driver->termination) | ||
741 | sch->driver->termination(&sch->dev); | ||
742 | } | ||
743 | |||
725 | static inline void | 744 | static inline void |
726 | __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | 745 | __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) |
727 | { | 746 | { |
@@ -744,20 +763,26 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | |||
744 | device_trigger_reprobe(sch); | 763 | device_trigger_reprobe(sch); |
745 | else if (sch->driver && sch->driver->verify) | 764 | else if (sch->driver && sch->driver->verify) |
746 | sch->driver->verify(&sch->dev); | 765 | sch->driver->verify(&sch->dev); |
747 | } else { | 766 | break; |
748 | sch->opm &= ~(0x80 >> chp); | 767 | } |
749 | sch->lpm &= ~(0x80 >> chp); | 768 | sch->opm &= ~(0x80 >> chp); |
750 | if (check_for_io_on_path(sch, chp)) | 769 | sch->lpm &= ~(0x80 >> chp); |
770 | if (check_for_io_on_path(sch, chp)) { | ||
771 | if (device_is_online(sch)) | ||
751 | /* Path verification is done after killing. */ | 772 | /* Path verification is done after killing. */ |
752 | device_kill_io(sch); | 773 | device_kill_io(sch); |
753 | else if (!sch->lpm) { | 774 | else |
775 | /* Kill and retry internal I/O. */ | ||
776 | terminate_internal_io(sch); | ||
777 | } else if (!sch->lpm) { | ||
778 | if (device_trigger_verify(sch) != 0) { | ||
754 | if (css_enqueue_subchannel_slow(sch->schid)) { | 779 | if (css_enqueue_subchannel_slow(sch->schid)) { |
755 | css_clear_subchannel_slow_list(); | 780 | css_clear_subchannel_slow_list(); |
756 | need_rescan = 1; | 781 | need_rescan = 1; |
757 | } | 782 | } |
758 | } else if (sch->driver && sch->driver->verify) | 783 | } |
759 | sch->driver->verify(&sch->dev); | 784 | } else if (sch->driver && sch->driver->verify) |
760 | } | 785 | sch->driver->verify(&sch->dev); |
761 | break; | 786 | break; |
762 | } | 787 | } |
763 | spin_unlock_irqrestore(&sch->lock, flags); | 788 | spin_unlock_irqrestore(&sch->lock, flags); |
@@ -1465,41 +1490,6 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no) | |||
1465 | return desc; | 1490 | return desc; |
1466 | } | 1491 | } |
1467 | 1492 | ||
1468 | static int reset_channel_path(struct channel_path *chp) | ||
1469 | { | ||
1470 | int cc; | ||
1471 | |||
1472 | cc = rchp(chp->id); | ||
1473 | switch (cc) { | ||
1474 | case 0: | ||
1475 | return 0; | ||
1476 | case 2: | ||
1477 | return -EBUSY; | ||
1478 | default: | ||
1479 | return -ENODEV; | ||
1480 | } | ||
1481 | } | ||
1482 | |||
1483 | static void reset_channel_paths_css(struct channel_subsystem *css) | ||
1484 | { | ||
1485 | int i; | ||
1486 | |||
1487 | for (i = 0; i <= __MAX_CHPID; i++) { | ||
1488 | if (css->chps[i]) | ||
1489 | reset_channel_path(css->chps[i]); | ||
1490 | } | ||
1491 | } | ||
1492 | |||
1493 | void cio_reset_channel_paths(void) | ||
1494 | { | ||
1495 | int i; | ||
1496 | |||
1497 | for (i = 0; i <= __MAX_CSSID; i++) { | ||
1498 | if (css[i] && css[i]->valid) | ||
1499 | reset_channel_paths_css(css[i]); | ||
1500 | } | ||
1501 | } | ||
1502 | |||
1503 | static int __init | 1493 | static int __init |
1504 | chsc_alloc_sei_area(void) | 1494 | chsc_alloc_sei_area(void) |
1505 | { | 1495 | { |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 8936e460a807..20aee2783847 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <asm/irq_regs.h> | 22 | #include <asm/irq_regs.h> |
23 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
24 | #include <asm/reset.h> | ||
24 | #include "airq.h" | 25 | #include "airq.h" |
25 | #include "cio.h" | 26 | #include "cio.h" |
26 | #include "css.h" | 27 | #include "css.h" |
@@ -28,6 +29,7 @@ | |||
28 | #include "ioasm.h" | 29 | #include "ioasm.h" |
29 | #include "blacklist.h" | 30 | #include "blacklist.h" |
30 | #include "cio_debug.h" | 31 | #include "cio_debug.h" |
32 | #include "../s390mach.h" | ||
31 | 33 | ||
32 | debug_info_t *cio_debug_msg_id; | 34 | debug_info_t *cio_debug_msg_id; |
33 | debug_info_t *cio_debug_trace_id; | 35 | debug_info_t *cio_debug_trace_id; |
@@ -841,26 +843,12 @@ __clear_subchannel_easy(struct subchannel_id schid) | |||
841 | return -EBUSY; | 843 | return -EBUSY; |
842 | } | 844 | } |
843 | 845 | ||
844 | struct sch_match_id { | 846 | static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) |
845 | struct subchannel_id schid; | ||
846 | struct ccw_dev_id devid; | ||
847 | int rc; | ||
848 | }; | ||
849 | |||
850 | static int __shutdown_subchannel_easy_and_match(struct subchannel_id schid, | ||
851 | void *data) | ||
852 | { | 847 | { |
853 | struct schib schib; | 848 | struct schib schib; |
854 | struct sch_match_id *match_id = data; | ||
855 | 849 | ||
856 | if (stsch_err(schid, &schib)) | 850 | if (stsch_err(schid, &schib)) |
857 | return -ENXIO; | 851 | return -ENXIO; |
858 | if (match_id && schib.pmcw.dnv && | ||
859 | (schib.pmcw.dev == match_id->devid.devno) && | ||
860 | (schid.ssid == match_id->devid.ssid)) { | ||
861 | match_id->schid = schid; | ||
862 | match_id->rc = 0; | ||
863 | } | ||
864 | if (!schib.pmcw.ena) | 852 | if (!schib.pmcw.ena) |
865 | return 0; | 853 | return 0; |
866 | switch(__disable_subchannel_easy(schid, &schib)) { | 854 | switch(__disable_subchannel_easy(schid, &schib)) { |
@@ -876,27 +864,111 @@ static int __shutdown_subchannel_easy_and_match(struct subchannel_id schid, | |||
876 | return 0; | 864 | return 0; |
877 | } | 865 | } |
878 | 866 | ||
879 | static int clear_all_subchannels_and_match(struct ccw_dev_id *devid, | 867 | static atomic_t chpid_reset_count; |
880 | struct subchannel_id *schid) | 868 | |
869 | static void s390_reset_chpids_mcck_handler(void) | ||
870 | { | ||
871 | struct crw crw; | ||
872 | struct mci *mci; | ||
873 | |||
874 | /* Check for pending channel report word. */ | ||
875 | mci = (struct mci *)&S390_lowcore.mcck_interruption_code; | ||
876 | if (!mci->cp) | ||
877 | return; | ||
878 | /* Process channel report words. */ | ||
879 | while (stcrw(&crw) == 0) { | ||
880 | /* Check for responses to RCHP. */ | ||
881 | if (crw.slct && crw.rsc == CRW_RSC_CPATH) | ||
882 | atomic_dec(&chpid_reset_count); | ||
883 | } | ||
884 | } | ||
885 | |||
886 | #define RCHP_TIMEOUT (30 * USEC_PER_SEC) | ||
887 | static void css_reset(void) | ||
888 | { | ||
889 | int i, ret; | ||
890 | unsigned long long timeout; | ||
891 | |||
892 | /* Reset subchannels. */ | ||
893 | for_each_subchannel(__shutdown_subchannel_easy, NULL); | ||
894 | /* Reset channel paths. */ | ||
895 | s390_reset_mcck_handler = s390_reset_chpids_mcck_handler; | ||
896 | /* Enable channel report machine checks. */ | ||
897 | __ctl_set_bit(14, 28); | ||
898 | /* Temporarily reenable machine checks. */ | ||
899 | local_mcck_enable(); | ||
900 | for (i = 0; i <= __MAX_CHPID; i++) { | ||
901 | ret = rchp(i); | ||
902 | if ((ret == 0) || (ret == 2)) | ||
903 | /* | ||
904 | * rchp either succeeded, or another rchp is already | ||
905 | * in progress. In either case, we'll get a crw. | ||
906 | */ | ||
907 | atomic_inc(&chpid_reset_count); | ||
908 | } | ||
909 | /* Wait for machine check for all channel paths. */ | ||
910 | timeout = get_clock() + (RCHP_TIMEOUT << 12); | ||
911 | while (atomic_read(&chpid_reset_count) != 0) { | ||
912 | if (get_clock() > timeout) | ||
913 | break; | ||
914 | cpu_relax(); | ||
915 | } | ||
916 | /* Disable machine checks again. */ | ||
917 | local_mcck_disable(); | ||
918 | /* Disable channel report machine checks. */ | ||
919 | __ctl_clear_bit(14, 28); | ||
920 | s390_reset_mcck_handler = NULL; | ||
921 | } | ||
922 | |||
923 | static struct reset_call css_reset_call = { | ||
924 | .fn = css_reset, | ||
925 | }; | ||
926 | |||
927 | static int __init init_css_reset_call(void) | ||
928 | { | ||
929 | atomic_set(&chpid_reset_count, 0); | ||
930 | register_reset_call(&css_reset_call); | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | arch_initcall(init_css_reset_call); | ||
935 | |||
936 | struct sch_match_id { | ||
937 | struct subchannel_id schid; | ||
938 | struct ccw_dev_id devid; | ||
939 | int rc; | ||
940 | }; | ||
941 | |||
942 | static int __reipl_subchannel_match(struct subchannel_id schid, void *data) | ||
943 | { | ||
944 | struct schib schib; | ||
945 | struct sch_match_id *match_id = data; | ||
946 | |||
947 | if (stsch_err(schid, &schib)) | ||
948 | return -ENXIO; | ||
949 | if (schib.pmcw.dnv && | ||
950 | (schib.pmcw.dev == match_id->devid.devno) && | ||
951 | (schid.ssid == match_id->devid.ssid)) { | ||
952 | match_id->schid = schid; | ||
953 | match_id->rc = 0; | ||
954 | return 1; | ||
955 | } | ||
956 | return 0; | ||
957 | } | ||
958 | |||
959 | static int reipl_find_schid(struct ccw_dev_id *devid, | ||
960 | struct subchannel_id *schid) | ||
881 | { | 961 | { |
882 | struct sch_match_id match_id; | 962 | struct sch_match_id match_id; |
883 | 963 | ||
884 | match_id.devid = *devid; | 964 | match_id.devid = *devid; |
885 | match_id.rc = -ENODEV; | 965 | match_id.rc = -ENODEV; |
886 | local_irq_disable(); | 966 | for_each_subchannel(__reipl_subchannel_match, &match_id); |
887 | for_each_subchannel(__shutdown_subchannel_easy_and_match, &match_id); | ||
888 | if (match_id.rc == 0) | 967 | if (match_id.rc == 0) |
889 | *schid = match_id.schid; | 968 | *schid = match_id.schid; |
890 | return match_id.rc; | 969 | return match_id.rc; |
891 | } | 970 | } |
892 | 971 | ||
893 | |||
894 | void clear_all_subchannels(void) | ||
895 | { | ||
896 | local_irq_disable(); | ||
897 | for_each_subchannel(__shutdown_subchannel_easy_and_match, NULL); | ||
898 | } | ||
899 | |||
900 | extern void do_reipl_asm(__u32 schid); | 972 | extern void do_reipl_asm(__u32 schid); |
901 | 973 | ||
902 | /* Make sure all subchannels are quiet before we re-ipl an lpar. */ | 974 | /* Make sure all subchannels are quiet before we re-ipl an lpar. */ |
@@ -904,9 +976,9 @@ void reipl_ccw_dev(struct ccw_dev_id *devid) | |||
904 | { | 976 | { |
905 | struct subchannel_id schid; | 977 | struct subchannel_id schid; |
906 | 978 | ||
907 | if (clear_all_subchannels_and_match(devid, &schid)) | 979 | s390_reset_system(); |
980 | if (reipl_find_schid(devid, &schid) != 0) | ||
908 | panic("IPL Device not found\n"); | 981 | panic("IPL Device not found\n"); |
909 | cio_reset_channel_paths(); | ||
910 | do_reipl_asm(*((__u32*)&schid)); | 982 | do_reipl_asm(*((__u32*)&schid)); |
911 | } | 983 | } |
912 | 984 | ||
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 4c2ff8336288..9ff064e71767 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -94,6 +94,7 @@ struct ccw_device_private { | |||
94 | unsigned int donotify:1; /* call notify function */ | 94 | unsigned int donotify:1; /* call notify function */ |
95 | unsigned int recog_done:1; /* dev. recog. complete */ | 95 | unsigned int recog_done:1; /* dev. recog. complete */ |
96 | unsigned int fake_irb:1; /* deliver faked irb */ | 96 | unsigned int fake_irb:1; /* deliver faked irb */ |
97 | unsigned int intretry:1; /* retry internal operation */ | ||
97 | } __attribute__((packed)) flags; | 98 | } __attribute__((packed)) flags; |
98 | unsigned long intparm; /* user interruption parameter */ | 99 | unsigned long intparm; /* user interruption parameter */ |
99 | struct qdio_irq *qdio_data; | 100 | struct qdio_irq *qdio_data; |
@@ -171,6 +172,8 @@ void device_trigger_reprobe(struct subchannel *); | |||
171 | /* Helper functions for vary on/off. */ | 172 | /* Helper functions for vary on/off. */ |
172 | int device_is_online(struct subchannel *); | 173 | int device_is_online(struct subchannel *); |
173 | void device_kill_io(struct subchannel *); | 174 | void device_kill_io(struct subchannel *); |
175 | void device_set_intretry(struct subchannel *sch); | ||
176 | int device_trigger_verify(struct subchannel *sch); | ||
174 | 177 | ||
175 | /* Machine check helper function. */ | 178 | /* Machine check helper function. */ |
176 | void device_kill_pending_timer(struct subchannel *); | 179 | void device_kill_pending_timer(struct subchannel *); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 39c98f940507..d3d3716ff84b 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -687,8 +687,20 @@ io_subchannel_register(void *data) | |||
687 | cdev = data; | 687 | cdev = data; |
688 | sch = to_subchannel(cdev->dev.parent); | 688 | sch = to_subchannel(cdev->dev.parent); |
689 | 689 | ||
690 | /* | ||
691 | * io_subchannel_register() will also be called after device | ||
692 | * recognition has been done for a boxed device (which will already | ||
693 | * be registered). We need to reprobe since we may now have sense id | ||
694 | * information. | ||
695 | */ | ||
690 | if (klist_node_attached(&cdev->dev.knode_parent)) { | 696 | if (klist_node_attached(&cdev->dev.knode_parent)) { |
691 | bus_rescan_devices(&ccw_bus_type); | 697 | if (!cdev->drv) { |
698 | ret = device_reprobe(&cdev->dev); | ||
699 | if (ret) | ||
700 | /* We can't do much here. */ | ||
701 | dev_info(&cdev->dev, "device_reprobe() returned" | ||
702 | " %d\n", ret); | ||
703 | } | ||
692 | goto out; | 704 | goto out; |
693 | } | 705 | } |
694 | /* make it known to the system */ | 706 | /* make it known to the system */ |
@@ -948,6 +960,9 @@ io_subchannel_ioterm(struct device *dev) | |||
948 | cdev = dev->driver_data; | 960 | cdev = dev->driver_data; |
949 | if (!cdev) | 961 | if (!cdev) |
950 | return; | 962 | return; |
963 | /* Internal I/O will be retried by the interrupt handler. */ | ||
964 | if (cdev->private->flags.intretry) | ||
965 | return; | ||
951 | cdev->private->state = DEV_STATE_CLEAR_VERIFY; | 966 | cdev->private->state = DEV_STATE_CLEAR_VERIFY; |
952 | if (cdev->handler) | 967 | if (cdev->handler) |
953 | cdev->handler(cdev, cdev->private->intparm, | 968 | cdev->handler(cdev, cdev->private->intparm, |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index de3d0857db9f..09c7672eb3f3 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -59,6 +59,27 @@ device_set_disconnected(struct subchannel *sch) | |||
59 | cdev->private->state = DEV_STATE_DISCONNECTED; | 59 | cdev->private->state = DEV_STATE_DISCONNECTED; |
60 | } | 60 | } |
61 | 61 | ||
62 | void device_set_intretry(struct subchannel *sch) | ||
63 | { | ||
64 | struct ccw_device *cdev; | ||
65 | |||
66 | cdev = sch->dev.driver_data; | ||
67 | if (!cdev) | ||
68 | return; | ||
69 | cdev->private->flags.intretry = 1; | ||
70 | } | ||
71 | |||
72 | int device_trigger_verify(struct subchannel *sch) | ||
73 | { | ||
74 | struct ccw_device *cdev; | ||
75 | |||
76 | cdev = sch->dev.driver_data; | ||
77 | if (!cdev || !cdev->online) | ||
78 | return -EINVAL; | ||
79 | dev_fsm_event(cdev, DEV_EVENT_VERIFY); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
62 | /* | 83 | /* |
63 | * Timeout function. It just triggers a DEV_EVENT_TIMEOUT. | 84 | * Timeout function. It just triggers a DEV_EVENT_TIMEOUT. |
64 | */ | 85 | */ |
@@ -893,6 +914,12 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) | |||
893 | * had killed the original request. | 914 | * had killed the original request. |
894 | */ | 915 | */ |
895 | if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { | 916 | if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { |
917 | /* Retry Basic Sense if requested. */ | ||
918 | if (cdev->private->flags.intretry) { | ||
919 | cdev->private->flags.intretry = 0; | ||
920 | ccw_device_do_sense(cdev, irb); | ||
921 | return; | ||
922 | } | ||
896 | cdev->private->flags.dosense = 0; | 923 | cdev->private->flags.dosense = 0; |
897 | memset(&cdev->private->irb, 0, sizeof(struct irb)); | 924 | memset(&cdev->private->irb, 0, sizeof(struct irb)); |
898 | ccw_device_accumulate_irb(cdev, irb); | 925 | ccw_device_accumulate_irb(cdev, irb); |
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index a74785b9e4eb..f17275917fe5 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c | |||
@@ -191,6 +191,8 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) | |||
191 | if ((sch->opm & cdev->private->imask) != 0 && | 191 | if ((sch->opm & cdev->private->imask) != 0 && |
192 | cdev->private->iretry > 0) { | 192 | cdev->private->iretry > 0) { |
193 | cdev->private->iretry--; | 193 | cdev->private->iretry--; |
194 | /* Reset internal retry indication. */ | ||
195 | cdev->private->flags.intretry = 0; | ||
194 | ret = cio_start (sch, cdev->private->iccws, | 196 | ret = cio_start (sch, cdev->private->iccws, |
195 | cdev->private->imask); | 197 | cdev->private->imask); |
196 | /* ret is 0, -EBUSY, -EACCES or -ENODEV */ | 198 | /* ret is 0, -EBUSY, -EACCES or -ENODEV */ |
@@ -237,8 +239,14 @@ ccw_device_check_sense_id(struct ccw_device *cdev) | |||
237 | return 0; /* Success */ | 239 | return 0; /* Success */ |
238 | } | 240 | } |
239 | /* Check the error cases. */ | 241 | /* Check the error cases. */ |
240 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) | 242 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { |
243 | /* Retry Sense ID if requested. */ | ||
244 | if (cdev->private->flags.intretry) { | ||
245 | cdev->private->flags.intretry = 0; | ||
246 | return -EAGAIN; | ||
247 | } | ||
241 | return -ETIME; | 248 | return -ETIME; |
249 | } | ||
242 | if (irb->esw.esw0.erw.cons && (irb->ecw[0] & SNS0_CMD_REJECT)) { | 250 | if (irb->esw.esw0.erw.cons && (irb->ecw[0] & SNS0_CMD_REJECT)) { |
243 | /* | 251 | /* |
244 | * if the device doesn't support the SenseID | 252 | * if the device doesn't support the SenseID |
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 2975ce888c19..cb1879a96818 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c | |||
@@ -71,6 +71,8 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev) | |||
71 | ccw->cda = (__u32) __pa (&cdev->private->pgid[i]); | 71 | ccw->cda = (__u32) __pa (&cdev->private->pgid[i]); |
72 | if (cdev->private->iretry > 0) { | 72 | if (cdev->private->iretry > 0) { |
73 | cdev->private->iretry--; | 73 | cdev->private->iretry--; |
74 | /* Reset internal retry indication. */ | ||
75 | cdev->private->flags.intretry = 0; | ||
74 | ret = cio_start (sch, cdev->private->iccws, | 76 | ret = cio_start (sch, cdev->private->iccws, |
75 | cdev->private->imask); | 77 | cdev->private->imask); |
76 | /* ret is 0, -EBUSY, -EACCES or -ENODEV */ | 78 | /* ret is 0, -EBUSY, -EACCES or -ENODEV */ |
@@ -122,8 +124,14 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev) | |||
122 | 124 | ||
123 | sch = to_subchannel(cdev->dev.parent); | 125 | sch = to_subchannel(cdev->dev.parent); |
124 | irb = &cdev->private->irb; | 126 | irb = &cdev->private->irb; |
125 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) | 127 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { |
128 | /* Retry Sense PGID if requested. */ | ||
129 | if (cdev->private->flags.intretry) { | ||
130 | cdev->private->flags.intretry = 0; | ||
131 | return -EAGAIN; | ||
132 | } | ||
126 | return -ETIME; | 133 | return -ETIME; |
134 | } | ||
127 | if (irb->esw.esw0.erw.cons && | 135 | if (irb->esw.esw0.erw.cons && |
128 | (irb->ecw[0]&(SNS0_CMD_REJECT|SNS0_INTERVENTION_REQ))) { | 136 | (irb->ecw[0]&(SNS0_CMD_REJECT|SNS0_INTERVENTION_REQ))) { |
129 | /* | 137 | /* |
@@ -253,6 +261,8 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func) | |||
253 | ret = -EACCES; | 261 | ret = -EACCES; |
254 | if (cdev->private->iretry > 0) { | 262 | if (cdev->private->iretry > 0) { |
255 | cdev->private->iretry--; | 263 | cdev->private->iretry--; |
264 | /* Reset internal retry indication. */ | ||
265 | cdev->private->flags.intretry = 0; | ||
256 | ret = cio_start (sch, cdev->private->iccws, | 266 | ret = cio_start (sch, cdev->private->iccws, |
257 | cdev->private->imask); | 267 | cdev->private->imask); |
258 | /* We expect an interrupt in case of success or busy | 268 | /* We expect an interrupt in case of success or busy |
@@ -293,6 +303,8 @@ static int __ccw_device_do_nop(struct ccw_device *cdev) | |||
293 | ret = -EACCES; | 303 | ret = -EACCES; |
294 | if (cdev->private->iretry > 0) { | 304 | if (cdev->private->iretry > 0) { |
295 | cdev->private->iretry--; | 305 | cdev->private->iretry--; |
306 | /* Reset internal retry indication. */ | ||
307 | cdev->private->flags.intretry = 0; | ||
296 | ret = cio_start (sch, cdev->private->iccws, | 308 | ret = cio_start (sch, cdev->private->iccws, |
297 | cdev->private->imask); | 309 | cdev->private->imask); |
298 | /* We expect an interrupt in case of success or busy | 310 | /* We expect an interrupt in case of success or busy |
@@ -321,8 +333,14 @@ __ccw_device_check_pgid(struct ccw_device *cdev) | |||
321 | 333 | ||
322 | sch = to_subchannel(cdev->dev.parent); | 334 | sch = to_subchannel(cdev->dev.parent); |
323 | irb = &cdev->private->irb; | 335 | irb = &cdev->private->irb; |
324 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) | 336 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { |
337 | /* Retry Set PGID if requested. */ | ||
338 | if (cdev->private->flags.intretry) { | ||
339 | cdev->private->flags.intretry = 0; | ||
340 | return -EAGAIN; | ||
341 | } | ||
325 | return -ETIME; | 342 | return -ETIME; |
343 | } | ||
326 | if (irb->esw.esw0.erw.cons) { | 344 | if (irb->esw.esw0.erw.cons) { |
327 | if (irb->ecw[0] & SNS0_CMD_REJECT) | 345 | if (irb->ecw[0] & SNS0_CMD_REJECT) |
328 | return -EOPNOTSUPP; | 346 | return -EOPNOTSUPP; |
@@ -360,8 +378,14 @@ static int __ccw_device_check_nop(struct ccw_device *cdev) | |||
360 | 378 | ||
361 | sch = to_subchannel(cdev->dev.parent); | 379 | sch = to_subchannel(cdev->dev.parent); |
362 | irb = &cdev->private->irb; | 380 | irb = &cdev->private->irb; |
363 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) | 381 | if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { |
382 | /* Retry NOP if requested. */ | ||
383 | if (cdev->private->flags.intretry) { | ||
384 | cdev->private->flags.intretry = 0; | ||
385 | return -EAGAIN; | ||
386 | } | ||
364 | return -ETIME; | 387 | return -ETIME; |
388 | } | ||
365 | if (irb->scsw.cc == 3) { | 389 | if (irb->scsw.cc == 3) { |
366 | CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x," | 390 | CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x," |
367 | " lpm %02X, became 'not operational'\n", | 391 | " lpm %02X, became 'not operational'\n", |
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index 3f7cbce4cd87..bdcf930f7beb 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c | |||
@@ -319,6 +319,9 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb) | |||
319 | sch->sense_ccw.count = SENSE_MAX_COUNT; | 319 | sch->sense_ccw.count = SENSE_MAX_COUNT; |
320 | sch->sense_ccw.flags = CCW_FLAG_SLI; | 320 | sch->sense_ccw.flags = CCW_FLAG_SLI; |
321 | 321 | ||
322 | /* Reset internal retry indication. */ | ||
323 | cdev->private->flags.intretry = 0; | ||
324 | |||
322 | return cio_start (sch, &sch->sense_ccw, 0xff); | 325 | return cio_start (sch, &sch->sense_ccw, 0xff); |
323 | } | 326 | } |
324 | 327 | ||
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 476aa1da5cbc..8d5fa1b4d11f 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -481,7 +481,7 @@ qdio_stop_polling(struct qdio_q *q) | |||
481 | unsigned char state = 0; | 481 | unsigned char state = 0; |
482 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | 482 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; |
483 | 483 | ||
484 | if (!atomic_swap(&q->polling,0)) | 484 | if (!atomic_xchg(&q->polling,0)) |
485 | return 1; | 485 | return 1; |
486 | 486 | ||
487 | QDIO_DBF_TEXT4(0,trace,"stoppoll"); | 487 | QDIO_DBF_TEXT4(0,trace,"stoppoll"); |
@@ -1964,8 +1964,8 @@ qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) | |||
1964 | QDIO_DBF_HEX0(0,sense,irb,QDIO_DBF_SENSE_LEN); | 1964 | QDIO_DBF_HEX0(0,sense,irb,QDIO_DBF_SENSE_LEN); |
1965 | 1965 | ||
1966 | QDIO_PRINT_WARN("sense data available on qdio channel.\n"); | 1966 | QDIO_PRINT_WARN("sense data available on qdio channel.\n"); |
1967 | HEXDUMP16(WARN,"irb: ",irb); | 1967 | QDIO_HEXDUMP16(WARN,"irb: ",irb); |
1968 | HEXDUMP16(WARN,"sense data: ",irb->ecw); | 1968 | QDIO_HEXDUMP16(WARN,"sense data: ",irb->ecw); |
1969 | } | 1969 | } |
1970 | 1970 | ||
1971 | } | 1971 | } |
@@ -3425,7 +3425,7 @@ do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags, | |||
3425 | 3425 | ||
3426 | if ((used_elements+count==QDIO_MAX_BUFFERS_PER_Q)&& | 3426 | if ((used_elements+count==QDIO_MAX_BUFFERS_PER_Q)&& |
3427 | (callflags&QDIO_FLAG_UNDER_INTERRUPT)) | 3427 | (callflags&QDIO_FLAG_UNDER_INTERRUPT)) |
3428 | atomic_swap(&q->polling,0); | 3428 | atomic_xchg(&q->polling,0); |
3429 | 3429 | ||
3430 | if (used_elements) | 3430 | if (used_elements) |
3431 | return; | 3431 | return; |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 49bb9e371c32..42927c1b7451 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -236,7 +236,7 @@ enum qdio_irq_states { | |||
236 | #define QDIO_PRINT_EMERG(x...) do { } while (0) | 236 | #define QDIO_PRINT_EMERG(x...) do { } while (0) |
237 | #endif | 237 | #endif |
238 | 238 | ||
239 | #define HEXDUMP16(importance,header,ptr) \ | 239 | #define QDIO_HEXDUMP16(importance,header,ptr) \ |
240 | QDIO_PRINT_##importance(header "%02x %02x %02x %02x " \ | 240 | QDIO_PRINT_##importance(header "%02x %02x %02x %02x " \ |
241 | "%02x %02x %02x %02x %02x %02x %02x %02x " \ | 241 | "%02x %02x %02x %02x %02x %02x %02x %02x " \ |
242 | "%02x %02x %02x %02x\n",*(((char*)ptr)), \ | 242 | "%02x %02x %02x %02x\n",*(((char*)ptr)), \ |
@@ -429,8 +429,6 @@ struct qdio_perf_stats { | |||
429 | }; | 429 | }; |
430 | #endif /* QDIO_PERFORMANCE_STATS */ | 430 | #endif /* QDIO_PERFORMANCE_STATS */ |
431 | 431 | ||
432 | #define atomic_swap(a,b) xchg((int*)a.counter,b) | ||
433 | |||
434 | /* unlikely as the later the better */ | 432 | /* unlikely as the later the better */ |
435 | #define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q) | 433 | #define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q) |
436 | #define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \ | 434 | #define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \ |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 79d89c368919..6a54334ffe09 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -431,7 +431,15 @@ static int ap_uevent (struct device *dev, char **envp, int num_envp, | |||
431 | ap_dev->device_type); | 431 | ap_dev->device_type); |
432 | if (buffer_size - length <= 0) | 432 | if (buffer_size - length <= 0) |
433 | return -ENOMEM; | 433 | return -ENOMEM; |
434 | envp[1] = 0; | 434 | buffer += length; |
435 | buffer_size -= length; | ||
436 | /* Add MODALIAS= */ | ||
437 | envp[1] = buffer; | ||
438 | length = scnprintf(buffer, buffer_size, "MODALIAS=ap:t%02X", | ||
439 | ap_dev->device_type); | ||
440 | if (buffer_size - length <= 0) | ||
441 | return -ENOMEM; | ||
442 | envp[2] = NULL; | ||
435 | return 0; | 443 | return 0; |
436 | } | 444 | } |
437 | 445 | ||
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 66a8aec6efa6..08d4e47070bd 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -54,6 +54,8 @@ | |||
54 | #error Cannot compile lcs.c without some net devices switched on. | 54 | #error Cannot compile lcs.c without some net devices switched on. |
55 | #endif | 55 | #endif |
56 | 56 | ||
57 | #define PRINTK_HEADER " lcs: " | ||
58 | |||
57 | /** | 59 | /** |
58 | * initialization string for output | 60 | * initialization string for output |
59 | */ | 61 | */ |
@@ -120,7 +122,7 @@ lcs_alloc_channel(struct lcs_channel *channel) | |||
120 | kzalloc(LCS_IOBUFFERSIZE, GFP_DMA | GFP_KERNEL); | 122 | kzalloc(LCS_IOBUFFERSIZE, GFP_DMA | GFP_KERNEL); |
121 | if (channel->iob[cnt].data == NULL) | 123 | if (channel->iob[cnt].data == NULL) |
122 | break; | 124 | break; |
123 | channel->iob[cnt].state = BUF_STATE_EMPTY; | 125 | channel->iob[cnt].state = LCS_BUF_STATE_EMPTY; |
124 | } | 126 | } |
125 | if (cnt < LCS_NUM_BUFFS) { | 127 | if (cnt < LCS_NUM_BUFFS) { |
126 | /* Not all io buffers could be allocated. */ | 128 | /* Not all io buffers could be allocated. */ |
@@ -236,7 +238,7 @@ lcs_setup_read_ccws(struct lcs_card *card) | |||
236 | ((struct lcs_header *) | 238 | ((struct lcs_header *) |
237 | card->read.iob[cnt].data)->offset = LCS_ILLEGAL_OFFSET; | 239 | card->read.iob[cnt].data)->offset = LCS_ILLEGAL_OFFSET; |
238 | card->read.iob[cnt].callback = lcs_get_frames_cb; | 240 | card->read.iob[cnt].callback = lcs_get_frames_cb; |
239 | card->read.iob[cnt].state = BUF_STATE_READY; | 241 | card->read.iob[cnt].state = LCS_BUF_STATE_READY; |
240 | card->read.iob[cnt].count = LCS_IOBUFFERSIZE; | 242 | card->read.iob[cnt].count = LCS_IOBUFFERSIZE; |
241 | } | 243 | } |
242 | card->read.ccws[0].flags &= ~CCW_FLAG_PCI; | 244 | card->read.ccws[0].flags &= ~CCW_FLAG_PCI; |
@@ -247,7 +249,7 @@ lcs_setup_read_ccws(struct lcs_card *card) | |||
247 | card->read.ccws[LCS_NUM_BUFFS].cda = | 249 | card->read.ccws[LCS_NUM_BUFFS].cda = |
248 | (__u32) __pa(card->read.ccws); | 250 | (__u32) __pa(card->read.ccws); |
249 | /* Setg initial state of the read channel. */ | 251 | /* Setg initial state of the read channel. */ |
250 | card->read.state = CH_STATE_INIT; | 252 | card->read.state = LCS_CH_STATE_INIT; |
251 | 253 | ||
252 | card->read.io_idx = 0; | 254 | card->read.io_idx = 0; |
253 | card->read.buf_idx = 0; | 255 | card->read.buf_idx = 0; |
@@ -294,7 +296,7 @@ lcs_setup_write_ccws(struct lcs_card *card) | |||
294 | card->write.ccws[LCS_NUM_BUFFS].cda = | 296 | card->write.ccws[LCS_NUM_BUFFS].cda = |
295 | (__u32) __pa(card->write.ccws); | 297 | (__u32) __pa(card->write.ccws); |
296 | /* Set initial state of the write channel. */ | 298 | /* Set initial state of the write channel. */ |
297 | card->read.state = CH_STATE_INIT; | 299 | card->read.state = LCS_CH_STATE_INIT; |
298 | 300 | ||
299 | card->write.io_idx = 0; | 301 | card->write.io_idx = 0; |
300 | card->write.buf_idx = 0; | 302 | card->write.buf_idx = 0; |
@@ -496,7 +498,7 @@ lcs_start_channel(struct lcs_channel *channel) | |||
496 | channel->ccws + channel->io_idx, 0, 0, | 498 | channel->ccws + channel->io_idx, 0, 0, |
497 | DOIO_DENY_PREFETCH | DOIO_ALLOW_SUSPEND); | 499 | DOIO_DENY_PREFETCH | DOIO_ALLOW_SUSPEND); |
498 | if (rc == 0) | 500 | if (rc == 0) |
499 | channel->state = CH_STATE_RUNNING; | 501 | channel->state = LCS_CH_STATE_RUNNING; |
500 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); | 502 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); |
501 | if (rc) { | 503 | if (rc) { |
502 | LCS_DBF_TEXT_(4,trace,"essh%s", channel->ccwdev->dev.bus_id); | 504 | LCS_DBF_TEXT_(4,trace,"essh%s", channel->ccwdev->dev.bus_id); |
@@ -520,8 +522,8 @@ lcs_clear_channel(struct lcs_channel *channel) | |||
520 | LCS_DBF_TEXT_(4,trace,"ecsc%s", channel->ccwdev->dev.bus_id); | 522 | LCS_DBF_TEXT_(4,trace,"ecsc%s", channel->ccwdev->dev.bus_id); |
521 | return rc; | 523 | return rc; |
522 | } | 524 | } |
523 | wait_event(channel->wait_q, (channel->state == CH_STATE_CLEARED)); | 525 | wait_event(channel->wait_q, (channel->state == LCS_CH_STATE_CLEARED)); |
524 | channel->state = CH_STATE_STOPPED; | 526 | channel->state = LCS_CH_STATE_STOPPED; |
525 | return rc; | 527 | return rc; |
526 | } | 528 | } |
527 | 529 | ||
@@ -535,11 +537,11 @@ lcs_stop_channel(struct lcs_channel *channel) | |||
535 | unsigned long flags; | 537 | unsigned long flags; |
536 | int rc; | 538 | int rc; |
537 | 539 | ||
538 | if (channel->state == CH_STATE_STOPPED) | 540 | if (channel->state == LCS_CH_STATE_STOPPED) |
539 | return 0; | 541 | return 0; |
540 | LCS_DBF_TEXT(4,trace,"haltsch"); | 542 | LCS_DBF_TEXT(4,trace,"haltsch"); |
541 | LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id); | 543 | LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id); |
542 | channel->state = CH_STATE_INIT; | 544 | channel->state = LCS_CH_STATE_INIT; |
543 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 545 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
544 | rc = ccw_device_halt(channel->ccwdev, (addr_t) channel); | 546 | rc = ccw_device_halt(channel->ccwdev, (addr_t) channel); |
545 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); | 547 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); |
@@ -548,7 +550,7 @@ lcs_stop_channel(struct lcs_channel *channel) | |||
548 | return rc; | 550 | return rc; |
549 | } | 551 | } |
550 | /* Asynchronous halt initialted. Wait for its completion. */ | 552 | /* Asynchronous halt initialted. Wait for its completion. */ |
551 | wait_event(channel->wait_q, (channel->state == CH_STATE_HALTED)); | 553 | wait_event(channel->wait_q, (channel->state == LCS_CH_STATE_HALTED)); |
552 | lcs_clear_channel(channel); | 554 | lcs_clear_channel(channel); |
553 | return 0; | 555 | return 0; |
554 | } | 556 | } |
@@ -596,8 +598,8 @@ __lcs_get_buffer(struct lcs_channel *channel) | |||
596 | LCS_DBF_TEXT(5, trace, "_getbuff"); | 598 | LCS_DBF_TEXT(5, trace, "_getbuff"); |
597 | index = channel->io_idx; | 599 | index = channel->io_idx; |
598 | do { | 600 | do { |
599 | if (channel->iob[index].state == BUF_STATE_EMPTY) { | 601 | if (channel->iob[index].state == LCS_BUF_STATE_EMPTY) { |
600 | channel->iob[index].state = BUF_STATE_LOCKED; | 602 | channel->iob[index].state = LCS_BUF_STATE_LOCKED; |
601 | return channel->iob + index; | 603 | return channel->iob + index; |
602 | } | 604 | } |
603 | index = (index + 1) & (LCS_NUM_BUFFS - 1); | 605 | index = (index + 1) & (LCS_NUM_BUFFS - 1); |
@@ -626,7 +628,7 @@ __lcs_resume_channel(struct lcs_channel *channel) | |||
626 | { | 628 | { |
627 | int rc; | 629 | int rc; |
628 | 630 | ||
629 | if (channel->state != CH_STATE_SUSPENDED) | 631 | if (channel->state != LCS_CH_STATE_SUSPENDED) |
630 | return 0; | 632 | return 0; |
631 | if (channel->ccws[channel->io_idx].flags & CCW_FLAG_SUSPEND) | 633 | if (channel->ccws[channel->io_idx].flags & CCW_FLAG_SUSPEND) |
632 | return 0; | 634 | return 0; |
@@ -636,7 +638,7 @@ __lcs_resume_channel(struct lcs_channel *channel) | |||
636 | LCS_DBF_TEXT_(4, trace, "ersc%s", channel->ccwdev->dev.bus_id); | 638 | LCS_DBF_TEXT_(4, trace, "ersc%s", channel->ccwdev->dev.bus_id); |
637 | PRINT_ERR("Error in lcs_resume_channel: rc=%d\n",rc); | 639 | PRINT_ERR("Error in lcs_resume_channel: rc=%d\n",rc); |
638 | } else | 640 | } else |
639 | channel->state = CH_STATE_RUNNING; | 641 | channel->state = LCS_CH_STATE_RUNNING; |
640 | return rc; | 642 | return rc; |
641 | 643 | ||
642 | } | 644 | } |
@@ -670,10 +672,10 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
670 | int index, rc; | 672 | int index, rc; |
671 | 673 | ||
672 | LCS_DBF_TEXT(5, trace, "rdybuff"); | 674 | LCS_DBF_TEXT(5, trace, "rdybuff"); |
673 | BUG_ON(buffer->state != BUF_STATE_LOCKED && | 675 | BUG_ON(buffer->state != LCS_BUF_STATE_LOCKED && |
674 | buffer->state != BUF_STATE_PROCESSED); | 676 | buffer->state != LCS_BUF_STATE_PROCESSED); |
675 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 677 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
676 | buffer->state = BUF_STATE_READY; | 678 | buffer->state = LCS_BUF_STATE_READY; |
677 | index = buffer - channel->iob; | 679 | index = buffer - channel->iob; |
678 | /* Set length. */ | 680 | /* Set length. */ |
679 | channel->ccws[index].count = buffer->count; | 681 | channel->ccws[index].count = buffer->count; |
@@ -695,8 +697,8 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
695 | int index, prev, next; | 697 | int index, prev, next; |
696 | 698 | ||
697 | LCS_DBF_TEXT(5, trace, "prcsbuff"); | 699 | LCS_DBF_TEXT(5, trace, "prcsbuff"); |
698 | BUG_ON(buffer->state != BUF_STATE_READY); | 700 | BUG_ON(buffer->state != LCS_BUF_STATE_READY); |
699 | buffer->state = BUF_STATE_PROCESSED; | 701 | buffer->state = LCS_BUF_STATE_PROCESSED; |
700 | index = buffer - channel->iob; | 702 | index = buffer - channel->iob; |
701 | prev = (index - 1) & (LCS_NUM_BUFFS - 1); | 703 | prev = (index - 1) & (LCS_NUM_BUFFS - 1); |
702 | next = (index + 1) & (LCS_NUM_BUFFS - 1); | 704 | next = (index + 1) & (LCS_NUM_BUFFS - 1); |
@@ -704,7 +706,7 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
704 | channel->ccws[index].flags |= CCW_FLAG_SUSPEND; | 706 | channel->ccws[index].flags |= CCW_FLAG_SUSPEND; |
705 | channel->ccws[index].flags &= ~CCW_FLAG_PCI; | 707 | channel->ccws[index].flags &= ~CCW_FLAG_PCI; |
706 | /* Check the suspend bit of the previous buffer. */ | 708 | /* Check the suspend bit of the previous buffer. */ |
707 | if (channel->iob[prev].state == BUF_STATE_READY) { | 709 | if (channel->iob[prev].state == LCS_BUF_STATE_READY) { |
708 | /* | 710 | /* |
709 | * Previous buffer is in state ready. It might have | 711 | * Previous buffer is in state ready. It might have |
710 | * happened in lcs_ready_buffer that the suspend bit | 712 | * happened in lcs_ready_buffer that the suspend bit |
@@ -727,10 +729,10 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
727 | unsigned long flags; | 729 | unsigned long flags; |
728 | 730 | ||
729 | LCS_DBF_TEXT(5, trace, "relbuff"); | 731 | LCS_DBF_TEXT(5, trace, "relbuff"); |
730 | BUG_ON(buffer->state != BUF_STATE_LOCKED && | 732 | BUG_ON(buffer->state != LCS_BUF_STATE_LOCKED && |
731 | buffer->state != BUF_STATE_PROCESSED); | 733 | buffer->state != LCS_BUF_STATE_PROCESSED); |
732 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 734 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
733 | buffer->state = BUF_STATE_EMPTY; | 735 | buffer->state = LCS_BUF_STATE_EMPTY; |
734 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); | 736 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); |
735 | } | 737 | } |
736 | 738 | ||
@@ -1264,7 +1266,7 @@ lcs_register_mc_addresses(void *data) | |||
1264 | netif_carrier_off(card->dev); | 1266 | netif_carrier_off(card->dev); |
1265 | netif_tx_disable(card->dev); | 1267 | netif_tx_disable(card->dev); |
1266 | wait_event(card->write.wait_q, | 1268 | wait_event(card->write.wait_q, |
1267 | (card->write.state != CH_STATE_RUNNING)); | 1269 | (card->write.state != LCS_CH_STATE_RUNNING)); |
1268 | lcs_fix_multicast_list(card); | 1270 | lcs_fix_multicast_list(card); |
1269 | if (card->state == DEV_STATE_UP) { | 1271 | if (card->state == DEV_STATE_UP) { |
1270 | netif_carrier_on(card->dev); | 1272 | netif_carrier_on(card->dev); |
@@ -1404,7 +1406,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1404 | } | 1406 | } |
1405 | } | 1407 | } |
1406 | /* How far in the ccw chain have we processed? */ | 1408 | /* How far in the ccw chain have we processed? */ |
1407 | if ((channel->state != CH_STATE_INIT) && | 1409 | if ((channel->state != LCS_CH_STATE_INIT) && |
1408 | (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) { | 1410 | (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) { |
1409 | index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa) | 1411 | index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa) |
1410 | - channel->ccws; | 1412 | - channel->ccws; |
@@ -1424,20 +1426,20 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1424 | (irb->scsw.dstat & DEV_STAT_CHN_END) || | 1426 | (irb->scsw.dstat & DEV_STAT_CHN_END) || |
1425 | (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)) | 1427 | (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)) |
1426 | /* Mark channel as stopped. */ | 1428 | /* Mark channel as stopped. */ |
1427 | channel->state = CH_STATE_STOPPED; | 1429 | channel->state = LCS_CH_STATE_STOPPED; |
1428 | else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED) | 1430 | else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED) |
1429 | /* CCW execution stopped on a suspend bit. */ | 1431 | /* CCW execution stopped on a suspend bit. */ |
1430 | channel->state = CH_STATE_SUSPENDED; | 1432 | channel->state = LCS_CH_STATE_SUSPENDED; |
1431 | if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) { | 1433 | if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) { |
1432 | if (irb->scsw.cc != 0) { | 1434 | if (irb->scsw.cc != 0) { |
1433 | ccw_device_halt(channel->ccwdev, (addr_t) channel); | 1435 | ccw_device_halt(channel->ccwdev, (addr_t) channel); |
1434 | return; | 1436 | return; |
1435 | } | 1437 | } |
1436 | /* The channel has been stopped by halt_IO. */ | 1438 | /* The channel has been stopped by halt_IO. */ |
1437 | channel->state = CH_STATE_HALTED; | 1439 | channel->state = LCS_CH_STATE_HALTED; |
1438 | } | 1440 | } |
1439 | if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) { | 1441 | if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) { |
1440 | channel->state = CH_STATE_CLEARED; | 1442 | channel->state = LCS_CH_STATE_CLEARED; |
1441 | } | 1443 | } |
1442 | /* Do the rest in the tasklet. */ | 1444 | /* Do the rest in the tasklet. */ |
1443 | tasklet_schedule(&channel->irq_tasklet); | 1445 | tasklet_schedule(&channel->irq_tasklet); |
@@ -1461,7 +1463,7 @@ lcs_tasklet(unsigned long data) | |||
1461 | /* Check for processed buffers. */ | 1463 | /* Check for processed buffers. */ |
1462 | iob = channel->iob; | 1464 | iob = channel->iob; |
1463 | buf_idx = channel->buf_idx; | 1465 | buf_idx = channel->buf_idx; |
1464 | while (iob[buf_idx].state == BUF_STATE_PROCESSED) { | 1466 | while (iob[buf_idx].state == LCS_BUF_STATE_PROCESSED) { |
1465 | /* Do the callback thing. */ | 1467 | /* Do the callback thing. */ |
1466 | if (iob[buf_idx].callback != NULL) | 1468 | if (iob[buf_idx].callback != NULL) |
1467 | iob[buf_idx].callback(channel, iob + buf_idx); | 1469 | iob[buf_idx].callback(channel, iob + buf_idx); |
@@ -1469,12 +1471,12 @@ lcs_tasklet(unsigned long data) | |||
1469 | } | 1471 | } |
1470 | channel->buf_idx = buf_idx; | 1472 | channel->buf_idx = buf_idx; |
1471 | 1473 | ||
1472 | if (channel->state == CH_STATE_STOPPED) | 1474 | if (channel->state == LCS_CH_STATE_STOPPED) |
1473 | // FIXME: what if rc != 0 ?? | 1475 | // FIXME: what if rc != 0 ?? |
1474 | rc = lcs_start_channel(channel); | 1476 | rc = lcs_start_channel(channel); |
1475 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 1477 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
1476 | if (channel->state == CH_STATE_SUSPENDED && | 1478 | if (channel->state == LCS_CH_STATE_SUSPENDED && |
1477 | channel->iob[channel->io_idx].state == BUF_STATE_READY) { | 1479 | channel->iob[channel->io_idx].state == LCS_BUF_STATE_READY) { |
1478 | // FIXME: what if rc != 0 ?? | 1480 | // FIXME: what if rc != 0 ?? |
1479 | rc = __lcs_resume_channel(channel); | 1481 | rc = __lcs_resume_channel(channel); |
1480 | } | 1482 | } |
@@ -1689,8 +1691,8 @@ lcs_detect(struct lcs_card *card) | |||
1689 | card->state = DEV_STATE_UP; | 1691 | card->state = DEV_STATE_UP; |
1690 | } else { | 1692 | } else { |
1691 | card->state = DEV_STATE_DOWN; | 1693 | card->state = DEV_STATE_DOWN; |
1692 | card->write.state = CH_STATE_INIT; | 1694 | card->write.state = LCS_CH_STATE_INIT; |
1693 | card->read.state = CH_STATE_INIT; | 1695 | card->read.state = LCS_CH_STATE_INIT; |
1694 | } | 1696 | } |
1695 | return rc; | 1697 | return rc; |
1696 | } | 1698 | } |
@@ -1705,8 +1707,8 @@ lcs_stopcard(struct lcs_card *card) | |||
1705 | 1707 | ||
1706 | LCS_DBF_TEXT(3, setup, "stopcard"); | 1708 | LCS_DBF_TEXT(3, setup, "stopcard"); |
1707 | 1709 | ||
1708 | if (card->read.state != CH_STATE_STOPPED && | 1710 | if (card->read.state != LCS_CH_STATE_STOPPED && |
1709 | card->write.state != CH_STATE_STOPPED && | 1711 | card->write.state != LCS_CH_STATE_STOPPED && |
1710 | card->state == DEV_STATE_UP) { | 1712 | card->state == DEV_STATE_UP) { |
1711 | lcs_clear_multicast_list(card); | 1713 | lcs_clear_multicast_list(card); |
1712 | rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP); | 1714 | rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP); |
@@ -1871,7 +1873,7 @@ lcs_stop_device(struct net_device *dev) | |||
1871 | netif_tx_disable(dev); | 1873 | netif_tx_disable(dev); |
1872 | dev->flags &= ~IFF_UP; | 1874 | dev->flags &= ~IFF_UP; |
1873 | wait_event(card->write.wait_q, | 1875 | wait_event(card->write.wait_q, |
1874 | (card->write.state != CH_STATE_RUNNING)); | 1876 | (card->write.state != LCS_CH_STATE_RUNNING)); |
1875 | rc = lcs_stopcard(card); | 1877 | rc = lcs_stopcard(card); |
1876 | if (rc) | 1878 | if (rc) |
1877 | PRINT_ERR("Try it again!\n "); | 1879 | PRINT_ERR("Try it again!\n "); |
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index b5247dc08b57..0e1e4a0a88f0 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h | |||
@@ -23,11 +23,6 @@ do { \ | |||
23 | } while (0) | 23 | } while (0) |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * some more definitions for debug or output stuff | ||
27 | */ | ||
28 | #define PRINTK_HEADER " lcs: " | ||
29 | |||
30 | /** | ||
31 | * sysfs related stuff | 26 | * sysfs related stuff |
32 | */ | 27 | */ |
33 | #define CARD_FROM_DEV(cdev) \ | 28 | #define CARD_FROM_DEV(cdev) \ |
@@ -127,22 +122,22 @@ do { \ | |||
127 | * LCS Buffer states | 122 | * LCS Buffer states |
128 | */ | 123 | */ |
129 | enum lcs_buffer_states { | 124 | enum lcs_buffer_states { |
130 | BUF_STATE_EMPTY, /* buffer is empty */ | 125 | LCS_BUF_STATE_EMPTY, /* buffer is empty */ |
131 | BUF_STATE_LOCKED, /* buffer is locked, don't touch */ | 126 | LCS_BUF_STATE_LOCKED, /* buffer is locked, don't touch */ |
132 | BUF_STATE_READY, /* buffer is ready for read/write */ | 127 | LCS_BUF_STATE_READY, /* buffer is ready for read/write */ |
133 | BUF_STATE_PROCESSED, | 128 | LCS_BUF_STATE_PROCESSED, |
134 | }; | 129 | }; |
135 | 130 | ||
136 | /** | 131 | /** |
137 | * LCS Channel State Machine declarations | 132 | * LCS Channel State Machine declarations |
138 | */ | 133 | */ |
139 | enum lcs_channel_states { | 134 | enum lcs_channel_states { |
140 | CH_STATE_INIT, | 135 | LCS_CH_STATE_INIT, |
141 | CH_STATE_HALTED, | 136 | LCS_CH_STATE_HALTED, |
142 | CH_STATE_STOPPED, | 137 | LCS_CH_STATE_STOPPED, |
143 | CH_STATE_RUNNING, | 138 | LCS_CH_STATE_RUNNING, |
144 | CH_STATE_SUSPENDED, | 139 | LCS_CH_STATE_SUSPENDED, |
145 | CH_STATE_CLEARED, | 140 | LCS_CH_STATE_CLEARED, |
146 | }; | 141 | }; |
147 | 142 | ||
148 | /** | 143 | /** |
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 821383d8cbe7..53c358c7d368 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -151,8 +151,6 @@ qeth_hex_dump(unsigned char *buf, size_t len) | |||
151 | #define SENSE_RESETTING_EVENT_BYTE 1 | 151 | #define SENSE_RESETTING_EVENT_BYTE 1 |
152 | #define SENSE_RESETTING_EVENT_FLAG 0x80 | 152 | #define SENSE_RESETTING_EVENT_FLAG 0x80 |
153 | 153 | ||
154 | #define atomic_swap(a,b) xchg((int *)a.counter, b) | ||
155 | |||
156 | /* | 154 | /* |
157 | * Common IO related definitions | 155 | * Common IO related definitions |
158 | */ | 156 | */ |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 8364d5475ac7..7fdc5272c446 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -2982,7 +2982,7 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) | |||
2982 | */ | 2982 | */ |
2983 | if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) || | 2983 | if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) || |
2984 | !atomic_read(&queue->set_pci_flags_count)){ | 2984 | !atomic_read(&queue->set_pci_flags_count)){ |
2985 | if (atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) == | 2985 | if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) == |
2986 | QETH_OUT_Q_UNLOCKED) { | 2986 | QETH_OUT_Q_UNLOCKED) { |
2987 | /* | 2987 | /* |
2988 | * If we get in here, there was no action in | 2988 | * If we get in here, there was no action in |
@@ -3245,7 +3245,7 @@ qeth_free_qdio_buffers(struct qeth_card *card) | |||
3245 | int i, j; | 3245 | int i, j; |
3246 | 3246 | ||
3247 | QETH_DBF_TEXT(trace, 2, "freeqdbf"); | 3247 | QETH_DBF_TEXT(trace, 2, "freeqdbf"); |
3248 | if (atomic_swap(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == | 3248 | if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == |
3249 | QETH_QDIO_UNINITIALIZED) | 3249 | QETH_QDIO_UNINITIALIZED) |
3250 | return; | 3250 | return; |
3251 | kfree(card->qdio.in_q); | 3251 | kfree(card->qdio.in_q); |
@@ -4366,7 +4366,7 @@ out: | |||
4366 | if (flush_count) | 4366 | if (flush_count) |
4367 | qeth_flush_buffers(queue, 0, start_index, flush_count); | 4367 | qeth_flush_buffers(queue, 0, start_index, flush_count); |
4368 | else if (!atomic_read(&queue->set_pci_flags_count)) | 4368 | else if (!atomic_read(&queue->set_pci_flags_count)) |
4369 | atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH); | 4369 | atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH); |
4370 | /* | 4370 | /* |
4371 | * queue->state will go from LOCKED -> UNLOCKED or from | 4371 | * queue->state will go from LOCKED -> UNLOCKED or from |
4372 | * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us | 4372 | * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us |
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index b5b0c2cba96b..5c0b75bbfa10 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/jiffies.h> | ||
28 | #include <linux/err.h> | 29 | #include <linux/err.h> |
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/string.h> | 31 | #include <linux/string.h> |
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c index 39d9b20f2038..c2f601f8e4f2 100644 --- a/drivers/spi/spi_butterfly.c +++ b/drivers/spi/spi_butterfly.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/parport.h> | 24 | #include <linux/parport.h> |
25 | 25 | ||
26 | #include <linux/sched.h> | ||
26 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
27 | #include <linux/spi/spi_bitbang.h> | 28 | #include <linux/spi/spi_bitbang.h> |
28 | #include <linux/spi/flash.h> | 29 | #include <linux/spi/flash.h> |
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 5372cfcbd054..b022fffd8c51 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
27 | #include <linux/sched.h> | ||
27 | #include <linux/device.h> | 28 | #include <linux/device.h> |
28 | #include <linux/types.h> | 29 | #include <linux/types.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 56d88c1a09c5..a3ed571eee31 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/sched.h> | ||
30 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
32 | #include "debug.h" | 33 | #include "debug.h" |
diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c index 8556097fcda8..dc336a67592f 100644 --- a/fs/9p/fcall.c +++ b/fs/9p/fcall.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/sched.h> | ||
30 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
31 | 32 | ||
32 | #include "debug.h" | 33 | #include "debug.h" |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 70492ccb4385..27507201f9e7 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/sched.h> | ||
26 | #include <linux/idr.h> | 27 | #include <linux/idr.h> |
27 | 28 | ||
28 | #include "debug.h" | 29 | #include "debug.h" |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 0f628041e3f7..0b96fae8b479 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/sched.h> | ||
29 | #include <linux/parser.h> | 30 | #include <linux/parser.h> |
30 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
31 | 32 | ||
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index e32d5971039b..905c882f4e2f 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/stat.h> | 30 | #include <linux/stat.h> |
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <linux/smp_lock.h> | 32 | #include <linux/smp_lock.h> |
33 | #include <linux/sched.h> | ||
33 | #include <linux/inet.h> | 34 | #include <linux/inet.h> |
34 | #include <linux/idr.h> | 35 | #include <linux/idr.h> |
35 | 36 | ||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index c3c47eda7574..79e6f9cd7340 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/sched.h> | ||
29 | #include <linux/file.h> | 30 | #include <linux/file.h> |
30 | #include <linux/stat.h> | 31 | #include <linux/stat.h> |
31 | #include <linux/string.h> | 32 | #include <linux/string.h> |
diff --git a/fs/compat.c b/fs/compat.c index 8d0a0018a7d2..06dad665b88f 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -45,6 +45,8 @@ | |||
45 | #include <linux/personality.h> | 45 | #include <linux/personality.h> |
46 | #include <linux/rwsem.h> | 46 | #include <linux/rwsem.h> |
47 | #include <linux/tsacct_kern.h> | 47 | #include <linux/tsacct_kern.h> |
48 | #include <linux/highmem.h> | ||
49 | #include <linux/poll.h> | ||
48 | #include <linux/mm.h> | 50 | #include <linux/mm.h> |
49 | 51 | ||
50 | #include <net/sock.h> /* siocdevprivate_ioctl */ | 52 | #include <net/sock.h> /* siocdevprivate_ioctl */ |
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c index 7365aec9511b..3799f19b282f 100644 --- a/fs/gfs2/locking/dlm/plock.c +++ b/fs/gfs2/locking/dlm/plock.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/miscdevice.h> | 9 | #include <linux/miscdevice.h> |
10 | #include <linux/lock_dlm_plock.h> | 10 | #include <linux/lock_dlm_plock.h> |
11 | #include <linux/poll.h> | ||
11 | 12 | ||
12 | #include "lock_dlm.h" | 13 | #include "lock_dlm.h" |
13 | 14 | ||
diff --git a/fs/inotify.c b/fs/inotify.c index 723836a1f718..f5099d86fd91 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/idr.h> | 27 | #include <linux/idr.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/sched.h> | ||
30 | #include <linux/init.h> | 31 | #include <linux/init.h> |
31 | #include <linux/list.h> | 32 | #include <linux/list.h> |
32 | #include <linux/writeback.h> | 33 | #include <linux/writeback.h> |
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 0ae3cd10702c..73f0d60f73a5 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/sched.h> | ||
14 | #include <linux/time.h> | 15 | #include <linux/time.h> |
15 | #include <linux/crc32.h> | 16 | #include <linux/crc32.h> |
16 | #include <linux/jffs2.h> | 17 | #include <linux/jffs2.h> |
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index b9b700730dfe..70707309dfa1 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/crc32.h> | 19 | #include <linux/crc32.h> |
20 | #include <linux/mtd/nand.h> | 20 | #include <linux/mtd/nand.h> |
21 | #include <linux/jiffies.h> | 21 | #include <linux/jiffies.h> |
22 | #include <linux/sched.h> | ||
22 | 23 | ||
23 | #include "nodelist.h" | 24 | #include "nodelist.h" |
24 | 25 | ||
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index 37db52488262..ed814b1ff4d9 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/ctype.h> | 9 | #include <linux/ctype.h> |
10 | #include <linux/capability.h> | 10 | #include <linux/capability.h> |
11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
12 | #include <linux/sched.h> | ||
12 | #include <asm/current.h> | 13 | #include <asm/current.h> |
13 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
14 | 15 | ||
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c index c0871002d00d..d4a0fad3563b 100644 --- a/fs/partitions/mac.c +++ b/fs/partitions/mac.c | |||
@@ -74,6 +74,8 @@ int mac_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
74 | be32_to_cpu(part->start_block) * (secsize/512), | 74 | be32_to_cpu(part->start_block) * (secsize/512), |
75 | be32_to_cpu(part->block_count) * (secsize/512)); | 75 | be32_to_cpu(part->block_count) * (secsize/512)); |
76 | 76 | ||
77 | if (!strnicmp(part->type, "Linux_RAID", 10)) | ||
78 | state->parts[slot].flags = 1; | ||
77 | #ifdef CONFIG_PPC_PMAC | 79 | #ifdef CONFIG_PPC_PMAC |
78 | /* | 80 | /* |
79 | * If this is the first bootable partition, tell the | 81 | * If this is the first bootable partition, tell the |
diff --git a/fs/proc/root.c b/fs/proc/root.c index ffe66c38488b..64d242b6dcfa 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
14 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/sched.h> | ||
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
18 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
diff --git a/fs/super.c b/fs/super.c index 47e554c12e76..84c320f6ad7e 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -221,6 +221,24 @@ static int grab_super(struct super_block *s) __releases(sb_lock) | |||
221 | } | 221 | } |
222 | 222 | ||
223 | /* | 223 | /* |
224 | * Superblock locking. We really ought to get rid of these two. | ||
225 | */ | ||
226 | void lock_super(struct super_block * sb) | ||
227 | { | ||
228 | get_fs_excl(); | ||
229 | mutex_lock(&sb->s_lock); | ||
230 | } | ||
231 | |||
232 | void unlock_super(struct super_block * sb) | ||
233 | { | ||
234 | put_fs_excl(); | ||
235 | mutex_unlock(&sb->s_lock); | ||
236 | } | ||
237 | |||
238 | EXPORT_SYMBOL(lock_super); | ||
239 | EXPORT_SYMBOL(unlock_super); | ||
240 | |||
241 | /* | ||
224 | * Write out and wait upon all dirty data associated with this | 242 | * Write out and wait upon all dirty data associated with this |
225 | * superblock. Filesystem data as well as the underlying block | 243 | * superblock. Filesystem data as well as the underlying block |
226 | * device. Takes the superblock lock. Requires a second blkdev | 244 | * device. Takes the superblock lock. Requires a second blkdev |
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/file.h> | 6 | #include <linux/file.h> |
7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/sched.h> | ||
9 | #include <linux/writeback.h> | 10 | #include <linux/writeback.h> |
10 | #include <linux/syscalls.h> | 11 | #include <linux/syscalls.h> |
11 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
diff --git a/fs/utimes.c b/fs/utimes.c index 1bcd852fc4a9..99cf2cb11fec 100644 --- a/fs/utimes.c +++ b/fs/utimes.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <linux/fs.h> | 2 | #include <linux/fs.h> |
3 | #include <linux/linkage.h> | 3 | #include <linux/linkage.h> |
4 | #include <linux/namei.h> | 4 | #include <linux/namei.h> |
5 | #include <linux/sched.h> | ||
5 | #include <linux/utime.h> | 6 | #include <linux/utime.h> |
6 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
7 | #include <asm/unistd.h> | 8 | #include <asm/unistd.h> |
diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h index 8d10a9187693..ab194e5f6653 100644 --- a/include/asm-arm/arch-ixp4xx/platform.h +++ b/include/asm-arm/arch-ixp4xx/platform.h | |||
@@ -86,6 +86,19 @@ struct ixp4xx_i2c_pins { | |||
86 | unsigned long scl_pin; | 86 | unsigned long scl_pin; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /* | ||
90 | * This structure provide a means for the board setup code | ||
91 | * to give information to th pata_ixp4xx driver. It is | ||
92 | * passed as platform_data. | ||
93 | */ | ||
94 | struct ixp4xx_pata_data { | ||
95 | volatile u32 *cs0_cfg; | ||
96 | volatile u32 *cs1_cfg; | ||
97 | unsigned long cs0_bits; | ||
98 | unsigned long cs1_bits; | ||
99 | void __iomem *cs0; | ||
100 | void __iomem *cs1; | ||
101 | }; | ||
89 | 102 | ||
90 | struct sys_timer; | 103 | struct sys_timer; |
91 | 104 | ||
diff --git a/include/asm-m68knommu/dma-mapping.h b/include/asm-m68knommu/dma-mapping.h index 5622b855a577..6aeab18e58bd 100644 --- a/include/asm-m68knommu/dma-mapping.h +++ b/include/asm-m68knommu/dma-mapping.h | |||
@@ -1,9 +1,10 @@ | |||
1 | #ifndef _M68KNOMMU_DMA_MAPPING_H | 1 | #ifndef _M68KNOMMU_DMA_MAPPING_H |
2 | #define _M68KNOMMU_DMA_MAPPING_H | 2 | #define _M68KNOMMU_DMA_MAPPING_H |
3 | 3 | ||
4 | |||
5 | #ifdef CONFIG_PCI | 4 | #ifdef CONFIG_PCI |
6 | #include <asm-generic/dma-mapping.h> | 5 | #include <asm-generic/dma-mapping.h> |
6 | #else | ||
7 | #include <asm-generic/dma-mapping-broken.h> | ||
7 | #endif | 8 | #endif |
8 | 9 | ||
9 | #endif /* _M68KNOMMU_DMA_MAPPING_H */ | 10 | #endif /* _M68KNOMMU_DMA_MAPPING_H */ |
diff --git a/include/asm-m68knommu/m520xsim.h b/include/asm-m68knommu/m520xsim.h index 1dac22ea95ba..49d016e6391a 100644 --- a/include/asm-m68knommu/m520xsim.h +++ b/include/asm-m68knommu/m520xsim.h | |||
@@ -31,6 +31,16 @@ | |||
31 | #define MCFINT_QSPI 31 /* Interrupt number for QSPI */ | 31 | #define MCFINT_QSPI 31 /* Interrupt number for QSPI */ |
32 | #define MCFINT_PIT1 4 /* Interrupt number for PIT1 (PIT0 in processor) */ | 32 | #define MCFINT_PIT1 4 /* Interrupt number for PIT1 (PIT0 in processor) */ |
33 | 33 | ||
34 | /* | ||
35 | * SDRAM configuration registers. | ||
36 | */ | ||
37 | #define MCFSIM_SDMR 0x000a8000 /* SDRAM Mode/Extended Mode Register */ | ||
38 | #define MCFSIM_SDCR 0x000a8004 /* SDRAM Control Register */ | ||
39 | #define MCFSIM_SDCFG1 0x000a8008 /* SDRAM Configuration Register 1 */ | ||
40 | #define MCFSIM_SDCFG2 0x000a800c /* SDRAM Configuration Register 2 */ | ||
41 | #define MCFSIM_SDCS0 0x000a8110 /* SDRAM Chip Select 0 Configuration */ | ||
42 | #define MCFSIM_SDCS1 0x000a8114 /* SDRAM Chip Select 1 Configuration */ | ||
43 | |||
34 | 44 | ||
35 | #define MCF_GPIO_PAR_UART (0xA4036) | 45 | #define MCF_GPIO_PAR_UART (0xA4036) |
36 | #define MCF_GPIO_PAR_FECI2C (0xA4033) | 46 | #define MCF_GPIO_PAR_FECI2C (0xA4033) |
@@ -47,7 +57,7 @@ | |||
47 | 57 | ||
48 | #define ICR_INTRCONF 0x05 | 58 | #define ICR_INTRCONF 0x05 |
49 | #define MCFPIT_IMR MCFINTC_IMRL | 59 | #define MCFPIT_IMR MCFINTC_IMRL |
50 | #define MCFPIT_IMR_IBIT (1 << MCFINT_PIT1) | 60 | #define MCFPIT_IMR_IBIT (1 << MCFINT_PIT1) |
51 | 61 | ||
52 | /****************************************************************************/ | 62 | /****************************************************************************/ |
53 | #endif /* m520xsim_h */ | 63 | #endif /* m520xsim_h */ |
diff --git a/include/asm-m68knommu/scatterlist.h b/include/asm-m68knommu/scatterlist.h index 12309b181d29..2085d6ff8782 100644 --- a/include/asm-m68knommu/scatterlist.h +++ b/include/asm-m68knommu/scatterlist.h | |||
@@ -10,7 +10,7 @@ struct scatterlist { | |||
10 | unsigned int length; | 10 | unsigned int length; |
11 | }; | 11 | }; |
12 | 12 | ||
13 | #define sg_address(sg) (page_address((sg)->page) + (sg)->offset | 13 | #define sg_address(sg) (page_address((sg)->page) + (sg)->offset) |
14 | #define sg_dma_address(sg) ((sg)->dma_address) | 14 | #define sg_dma_address(sg) ((sg)->dma_address) |
15 | #define sg_dma_len(sg) ((sg)->length) | 15 | #define sg_dma_len(sg) ((sg)->length) |
16 | 16 | ||
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index 81287d86329d..d92785030980 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h | |||
@@ -278,17 +278,16 @@ struct ccw_dev_id { | |||
278 | static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, | 278 | static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, |
279 | struct ccw_dev_id *dev_id2) | 279 | struct ccw_dev_id *dev_id2) |
280 | { | 280 | { |
281 | return !memcmp(dev_id1, dev_id2, sizeof(struct ccw_dev_id)); | 281 | if ((dev_id1->ssid == dev_id2->ssid) && |
282 | (dev_id1->devno == dev_id2->devno)) | ||
283 | return 1; | ||
284 | return 0; | ||
282 | } | 285 | } |
283 | 286 | ||
284 | extern int diag210(struct diag210 *addr); | 287 | extern int diag210(struct diag210 *addr); |
285 | 288 | ||
286 | extern void wait_cons_dev(void); | 289 | extern void wait_cons_dev(void); |
287 | 290 | ||
288 | extern void clear_all_subchannels(void); | ||
289 | |||
290 | extern void cio_reset_channel_paths(void); | ||
291 | |||
292 | extern void css_schedule_reprobe(void); | 291 | extern void css_schedule_reprobe(void); |
293 | 292 | ||
294 | extern void reipl_ccw_dev(struct ccw_dev_id *id); | 293 | extern void reipl_ccw_dev(struct ccw_dev_id *id); |
diff --git a/include/asm-s390/cpcmd.h b/include/asm-s390/cpcmd.h index 1fcf65be7a23..48a9eab16429 100644 --- a/include/asm-s390/cpcmd.h +++ b/include/asm-s390/cpcmd.h | |||
@@ -7,8 +7,8 @@ | |||
7 | * Christian Borntraeger (cborntra@de.ibm.com), | 7 | * Christian Borntraeger (cborntra@de.ibm.com), |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #ifndef __CPCMD__ | 10 | #ifndef _ASM_S390_CPCMD_H |
11 | #define __CPCMD__ | 11 | #define _ASM_S390_CPCMD_H |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * the lowlevel function for cpcmd | 14 | * the lowlevel function for cpcmd |
@@ -16,9 +16,6 @@ | |||
16 | */ | 16 | */ |
17 | extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code); | 17 | extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code); |
18 | 18 | ||
19 | #ifndef __s390x__ | ||
20 | #define cpcmd __cpcmd | ||
21 | #else | ||
22 | /* | 19 | /* |
23 | * cpcmd is the in-kernel interface for issuing CP commands | 20 | * cpcmd is the in-kernel interface for issuing CP commands |
24 | * | 21 | * |
@@ -33,6 +30,5 @@ extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code | |||
33 | * NOTE: If the response buffer is not below 2 GB, cpcmd can sleep | 30 | * NOTE: If the response buffer is not below 2 GB, cpcmd can sleep |
34 | */ | 31 | */ |
35 | extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code); | 32 | extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code); |
36 | #endif /*__s390x__*/ | ||
37 | 33 | ||
38 | #endif | 34 | #endif /* _ASM_S390_CPCMD_H */ |
diff --git a/include/asm-s390/kexec.h b/include/asm-s390/kexec.h index ce28ddda0f50..9c35c8ad1afd 100644 --- a/include/asm-s390/kexec.h +++ b/include/asm-s390/kexec.h | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | /* Maximum address we can use for the control pages */ | 27 | /* Maximum address we can use for the control pages */ |
28 | /* Not more than 2GB */ | 28 | /* Not more than 2GB */ |
29 | #define KEXEC_CONTROL_MEMORY_LIMIT (1<<31) | 29 | #define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31) |
30 | 30 | ||
31 | /* Allocate one page for the pdp and the second for the code */ | 31 | /* Allocate one page for the pdp and the second for the code */ |
32 | #define KEXEC_CONTROL_CODE_SIZE 4096 | 32 | #define KEXEC_CONTROL_CODE_SIZE 4096 |
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index 06583ed0bde7..74f7389bd3ee 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h | |||
@@ -362,6 +362,14 @@ static inline void set_prefix(__u32 address) | |||
362 | asm volatile("spx %0" : : "m" (address) : "memory"); | 362 | asm volatile("spx %0" : : "m" (address) : "memory"); |
363 | } | 363 | } |
364 | 364 | ||
365 | static inline __u32 store_prefix(void) | ||
366 | { | ||
367 | __u32 address; | ||
368 | |||
369 | asm volatile("stpx %0" : "=m" (address)); | ||
370 | return address; | ||
371 | } | ||
372 | |||
365 | #define __PANIC_MAGIC 0xDEADC0DE | 373 | #define __PANIC_MAGIC 0xDEADC0DE |
366 | 374 | ||
367 | #endif | 375 | #endif |
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 36bb6dacf008..2d968a69ed1f 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h | |||
@@ -110,13 +110,22 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
110 | #define VMALLOC_OFFSET (8*1024*1024) | 110 | #define VMALLOC_OFFSET (8*1024*1024) |
111 | #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \ | 111 | #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \ |
112 | & ~(VMALLOC_OFFSET-1)) | 112 | & ~(VMALLOC_OFFSET-1)) |
113 | |||
114 | /* | ||
115 | * We need some free virtual space to be able to do vmalloc. | ||
116 | * VMALLOC_MIN_SIZE defines the minimum size of the vmalloc | ||
117 | * area. On a machine with 2GB memory we make sure that we | ||
118 | * have at least 128MB free space for vmalloc. On a machine | ||
119 | * with 4TB we make sure we have at least 1GB. | ||
120 | */ | ||
113 | #ifndef __s390x__ | 121 | #ifndef __s390x__ |
114 | # define VMALLOC_END (0x7fffffffL) | 122 | #define VMALLOC_MIN_SIZE 0x8000000UL |
123 | #define VMALLOC_END 0x80000000UL | ||
115 | #else /* __s390x__ */ | 124 | #else /* __s390x__ */ |
116 | # define VMALLOC_END (0x40000000000L) | 125 | #define VMALLOC_MIN_SIZE 0x40000000UL |
126 | #define VMALLOC_END 0x40000000000UL | ||
117 | #endif /* __s390x__ */ | 127 | #endif /* __s390x__ */ |
118 | 128 | ||
119 | |||
120 | /* | 129 | /* |
121 | * A 31 bit pagetable entry of S390 has following format: | 130 | * A 31 bit pagetable entry of S390 has following format: |
122 | * | PFRA | | OS | | 131 | * | PFRA | | OS | |
diff --git a/include/asm-s390/reset.h b/include/asm-s390/reset.h new file mode 100644 index 000000000000..9b439cf67800 --- /dev/null +++ b/include/asm-s390/reset.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * include/asm-s390/reset.h | ||
3 | * | ||
4 | * Copyright IBM Corp. 2006 | ||
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #ifndef _ASM_S390_RESET_H | ||
9 | #define _ASM_S390_RESET_H | ||
10 | |||
11 | #include <linux/list.h> | ||
12 | |||
13 | struct reset_call { | ||
14 | struct list_head list; | ||
15 | void (*fn)(void); | ||
16 | }; | ||
17 | |||
18 | extern void register_reset_call(struct reset_call *reset); | ||
19 | extern void unregister_reset_call(struct reset_call *reset); | ||
20 | extern void s390_reset_system(void); | ||
21 | extern void (*s390_reset_mcck_handler)(void); | ||
22 | |||
23 | #endif /* _ASM_S390_RESET_H */ | ||
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h index 5d72eda8a11b..7664bacdd832 100644 --- a/include/asm-s390/setup.h +++ b/include/asm-s390/setup.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * include/asm-s390/setup.h | 2 | * include/asm-s390/setup.h |
3 | * | 3 | * |
4 | * S390 version | 4 | * S390 version |
5 | * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Copyright IBM Corp. 1999,2006 |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef _ASM_S390_SETUP_H | 8 | #ifndef _ASM_S390_SETUP_H |
@@ -30,6 +30,17 @@ | |||
30 | #endif /* __s390x__ */ | 30 | #endif /* __s390x__ */ |
31 | #define COMMAND_LINE ((char *) (0x10480)) | 31 | #define COMMAND_LINE ((char *) (0x10480)) |
32 | 32 | ||
33 | #define CHUNK_READ_WRITE 0 | ||
34 | #define CHUNK_READ_ONLY 1 | ||
35 | |||
36 | struct mem_chunk { | ||
37 | unsigned long addr; | ||
38 | unsigned long size; | ||
39 | unsigned long type; | ||
40 | }; | ||
41 | |||
42 | extern struct mem_chunk memory_chunk[]; | ||
43 | |||
33 | /* | 44 | /* |
34 | * Machine features detected in head.S | 45 | * Machine features detected in head.S |
35 | */ | 46 | */ |
@@ -53,7 +64,6 @@ extern unsigned long machine_flags; | |||
53 | #define MACHINE_HAS_MVCOS (machine_flags & 512) | 64 | #define MACHINE_HAS_MVCOS (machine_flags & 512) |
54 | #endif /* __s390x__ */ | 65 | #endif /* __s390x__ */ |
55 | 66 | ||
56 | |||
57 | #define MACHINE_HAS_SCLP (!MACHINE_IS_P390) | 67 | #define MACHINE_HAS_SCLP (!MACHINE_IS_P390) |
58 | 68 | ||
59 | /* | 69 | /* |
@@ -71,7 +81,6 @@ extern unsigned int console_irq; | |||
71 | #define SET_CONSOLE_3215 do { console_mode = 2; } while (0) | 81 | #define SET_CONSOLE_3215 do { console_mode = 2; } while (0) |
72 | #define SET_CONSOLE_3270 do { console_mode = 3; } while (0) | 82 | #define SET_CONSOLE_3270 do { console_mode = 3; } while (0) |
73 | 83 | ||
74 | |||
75 | struct ipl_list_hdr { | 84 | struct ipl_list_hdr { |
76 | u32 len; | 85 | u32 len; |
77 | u8 reserved1[3]; | 86 | u8 reserved1[3]; |
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h index c3cf030ada4d..7097c96ed026 100644 --- a/include/asm-s390/smp.h +++ b/include/asm-s390/smp.h | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <asm/lowcore.h> | 19 | #include <asm/lowcore.h> |
20 | #include <asm/sigp.h> | 20 | #include <asm/sigp.h> |
21 | #include <asm/ptrace.h> | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | s390 specific smp.c headers | 24 | s390 specific smp.c headers |
@@ -101,6 +102,13 @@ smp_call_function_on(void (*func) (void *info), void *info, | |||
101 | func(info); | 102 | func(info); |
102 | return 0; | 103 | return 0; |
103 | } | 104 | } |
105 | |||
106 | static inline void smp_send_stop(void) | ||
107 | { | ||
108 | /* Disable all interrupts/machine checks */ | ||
109 | __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK); | ||
110 | } | ||
111 | |||
104 | #define smp_cpu_not_running(cpu) 1 | 112 | #define smp_cpu_not_running(cpu) 1 |
105 | #define smp_get_cpu(cpu) ({ 0; }) | 113 | #define smp_get_cpu(cpu) ({ 0; }) |
106 | #define smp_put_cpu(cpu) ({ 0; }) | 114 | #define smp_put_cpu(cpu) ({ 0; }) |
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index ccbafe4bf2cb..bd0b05ae87d2 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
@@ -115,6 +115,16 @@ extern void account_system_vtime(struct task_struct *); | |||
115 | #define account_vtime(x) do { /* empty */ } while (0) | 115 | #define account_vtime(x) do { /* empty */ } while (0) |
116 | #endif | 116 | #endif |
117 | 117 | ||
118 | #ifdef CONFIG_PFAULT | ||
119 | extern void pfault_irq_init(void); | ||
120 | extern int pfault_init(void); | ||
121 | extern void pfault_fini(void); | ||
122 | #else /* CONFIG_PFAULT */ | ||
123 | #define pfault_irq_init() do { } while (0) | ||
124 | #define pfault_init() ({-1;}) | ||
125 | #define pfault_fini() do { } while (0) | ||
126 | #endif /* CONFIG_PFAULT */ | ||
127 | |||
118 | #define finish_arch_switch(prev) do { \ | 128 | #define finish_arch_switch(prev) do { \ |
119 | set_fs(current->thread.mm_segment); \ | 129 | set_fs(current->thread.mm_segment); \ |
120 | account_vtime(prev); \ | 130 | account_vtime(prev); \ |
diff --git a/include/asm-s390/termios.h b/include/asm-s390/termios.h index d1e29cca54c9..62b23caf370e 100644 --- a/include/asm-s390/termios.h +++ b/include/asm-s390/termios.h | |||
@@ -75,39 +75,7 @@ struct termio { | |||
75 | */ | 75 | */ |
76 | #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" | 76 | #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" |
77 | 77 | ||
78 | /* | 78 | #include <asm-generic/termios.h> |
79 | * Translate a "termio" structure into a "termios". Ugh. | ||
80 | */ | ||
81 | #define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ | ||
82 | unsigned short __tmp; \ | ||
83 | get_user(__tmp,&(termio)->x); \ | ||
84 | (termios)->x = (0xffff0000 & ((termios)->x)) | __tmp; \ | ||
85 | } | ||
86 | |||
87 | #define user_termio_to_kernel_termios(termios, termio) \ | ||
88 | ({ \ | ||
89 | SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ | ||
90 | SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ | ||
91 | SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ | ||
92 | SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ | ||
93 | copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ | ||
94 | }) | ||
95 | |||
96 | /* | ||
97 | * Translate a "termios" structure into a "termio". Ugh. | ||
98 | */ | ||
99 | #define kernel_termios_to_user_termio(termio, termios) \ | ||
100 | ({ \ | ||
101 | put_user((termios)->c_iflag, &(termio)->c_iflag); \ | ||
102 | put_user((termios)->c_oflag, &(termio)->c_oflag); \ | ||
103 | put_user((termios)->c_cflag, &(termio)->c_cflag); \ | ||
104 | put_user((termios)->c_lflag, &(termio)->c_lflag); \ | ||
105 | put_user((termios)->c_line, &(termio)->c_line); \ | ||
106 | copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ | ||
107 | }) | ||
108 | |||
109 | #define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) | ||
110 | #define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) | ||
111 | 79 | ||
112 | #endif /* __KERNEL__ */ | 80 | #endif /* __KERNEL__ */ |
113 | 81 | ||
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index 72ae4efddb49..73ac4e82217b 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h | |||
@@ -201,7 +201,7 @@ extern int __get_user_bad(void) __attribute__((noreturn)); | |||
201 | * Returns number of bytes that could not be copied. | 201 | * Returns number of bytes that could not be copied. |
202 | * On success, this will be zero. | 202 | * On success, this will be zero. |
203 | */ | 203 | */ |
204 | static inline unsigned long | 204 | static inline unsigned long __must_check |
205 | __copy_to_user(void __user *to, const void *from, unsigned long n) | 205 | __copy_to_user(void __user *to, const void *from, unsigned long n) |
206 | { | 206 | { |
207 | if (__builtin_constant_p(n) && (n <= 256)) | 207 | if (__builtin_constant_p(n) && (n <= 256)) |
@@ -226,7 +226,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) | |||
226 | * Returns number of bytes that could not be copied. | 226 | * Returns number of bytes that could not be copied. |
227 | * On success, this will be zero. | 227 | * On success, this will be zero. |
228 | */ | 228 | */ |
229 | static inline unsigned long | 229 | static inline unsigned long __must_check |
230 | copy_to_user(void __user *to, const void *from, unsigned long n) | 230 | copy_to_user(void __user *to, const void *from, unsigned long n) |
231 | { | 231 | { |
232 | might_sleep(); | 232 | might_sleep(); |
@@ -252,7 +252,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n) | |||
252 | * If some data could not be copied, this function will pad the copied | 252 | * If some data could not be copied, this function will pad the copied |
253 | * data to the requested size using zero bytes. | 253 | * data to the requested size using zero bytes. |
254 | */ | 254 | */ |
255 | static inline unsigned long | 255 | static inline unsigned long __must_check |
256 | __copy_from_user(void *to, const void __user *from, unsigned long n) | 256 | __copy_from_user(void *to, const void __user *from, unsigned long n) |
257 | { | 257 | { |
258 | if (__builtin_constant_p(n) && (n <= 256)) | 258 | if (__builtin_constant_p(n) && (n <= 256)) |
@@ -277,7 +277,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) | |||
277 | * If some data could not be copied, this function will pad the copied | 277 | * If some data could not be copied, this function will pad the copied |
278 | * data to the requested size using zero bytes. | 278 | * data to the requested size using zero bytes. |
279 | */ | 279 | */ |
280 | static inline unsigned long | 280 | static inline unsigned long __must_check |
281 | copy_from_user(void *to, const void __user *from, unsigned long n) | 281 | copy_from_user(void *to, const void __user *from, unsigned long n) |
282 | { | 282 | { |
283 | might_sleep(); | 283 | might_sleep(); |
@@ -288,13 +288,13 @@ copy_from_user(void *to, const void __user *from, unsigned long n) | |||
288 | return n; | 288 | return n; |
289 | } | 289 | } |
290 | 290 | ||
291 | static inline unsigned long | 291 | static inline unsigned long __must_check |
292 | __copy_in_user(void __user *to, const void __user *from, unsigned long n) | 292 | __copy_in_user(void __user *to, const void __user *from, unsigned long n) |
293 | { | 293 | { |
294 | return uaccess.copy_in_user(n, to, from); | 294 | return uaccess.copy_in_user(n, to, from); |
295 | } | 295 | } |
296 | 296 | ||
297 | static inline unsigned long | 297 | static inline unsigned long __must_check |
298 | copy_in_user(void __user *to, const void __user *from, unsigned long n) | 298 | copy_in_user(void __user *to, const void __user *from, unsigned long n) |
299 | { | 299 | { |
300 | might_sleep(); | 300 | might_sleep(); |
@@ -306,7 +306,7 @@ copy_in_user(void __user *to, const void __user *from, unsigned long n) | |||
306 | /* | 306 | /* |
307 | * Copy a null terminated string from userspace. | 307 | * Copy a null terminated string from userspace. |
308 | */ | 308 | */ |
309 | static inline long | 309 | static inline long __must_check |
310 | strncpy_from_user(char *dst, const char __user *src, long count) | 310 | strncpy_from_user(char *dst, const char __user *src, long count) |
311 | { | 311 | { |
312 | long res = -EFAULT; | 312 | long res = -EFAULT; |
@@ -343,13 +343,13 @@ strnlen_user(const char __user * src, unsigned long n) | |||
343 | * Zero Userspace | 343 | * Zero Userspace |
344 | */ | 344 | */ |
345 | 345 | ||
346 | static inline unsigned long | 346 | static inline unsigned long __must_check |
347 | __clear_user(void __user *to, unsigned long n) | 347 | __clear_user(void __user *to, unsigned long n) |
348 | { | 348 | { |
349 | return uaccess.clear_user(n, to); | 349 | return uaccess.clear_user(n, to); |
350 | } | 350 | } |
351 | 351 | ||
352 | static inline unsigned long | 352 | static inline unsigned long __must_check |
353 | clear_user(void __user *to, unsigned long n) | 353 | clear_user(void __user *to, unsigned long n) |
354 | { | 354 | { |
355 | might_sleep(); | 355 | might_sleep(); |
diff --git a/include/asm-s390/zcrypt.h b/include/asm-s390/zcrypt.h index 7244c68464f2..b90e55888a55 100644 --- a/include/asm-s390/zcrypt.h +++ b/include/asm-s390/zcrypt.h | |||
@@ -180,40 +180,8 @@ struct ica_xcRB { | |||
180 | * for the implementation details for the contents of the | 180 | * for the implementation details for the contents of the |
181 | * block | 181 | * block |
182 | * | 182 | * |
183 | * Z90STAT_TOTALCOUNT | 183 | * ZSECSENDCPRB |
184 | * Return an integer count of all device types together. | 184 | * Send an arbitrary CPRB to a crypto card. |
185 | * | ||
186 | * Z90STAT_PCICACOUNT | ||
187 | * Return an integer count of all PCICAs. | ||
188 | * | ||
189 | * Z90STAT_PCICCCOUNT | ||
190 | * Return an integer count of all PCICCs. | ||
191 | * | ||
192 | * Z90STAT_PCIXCCMCL2COUNT | ||
193 | * Return an integer count of all MCL2 PCIXCCs. | ||
194 | * | ||
195 | * Z90STAT_PCIXCCMCL3COUNT | ||
196 | * Return an integer count of all MCL3 PCIXCCs. | ||
197 | * | ||
198 | * Z90STAT_CEX2CCOUNT | ||
199 | * Return an integer count of all CEX2Cs. | ||
200 | * | ||
201 | * Z90STAT_CEX2ACOUNT | ||
202 | * Return an integer count of all CEX2As. | ||
203 | * | ||
204 | * Z90STAT_REQUESTQ_COUNT | ||
205 | * Return an integer count of the number of entries waiting to be | ||
206 | * sent to a device. | ||
207 | * | ||
208 | * Z90STAT_PENDINGQ_COUNT | ||
209 | * Return an integer count of the number of entries sent to a | ||
210 | * device awaiting the reply. | ||
211 | * | ||
212 | * Z90STAT_TOTALOPEN_COUNT | ||
213 | * Return an integer count of the number of open file handles. | ||
214 | * | ||
215 | * Z90STAT_DOMAIN_INDEX | ||
216 | * Return the integer value of the Cryptographic Domain. | ||
217 | * | 185 | * |
218 | * Z90STAT_STATUS_MASK | 186 | * Z90STAT_STATUS_MASK |
219 | * Return an 64 element array of unsigned chars for the status of | 187 | * Return an 64 element array of unsigned chars for the status of |
@@ -235,28 +203,51 @@ struct ica_xcRB { | |||
235 | * of successfully completed requests per device since the device | 203 | * of successfully completed requests per device since the device |
236 | * was detected and made available. | 204 | * was detected and made available. |
237 | * | 205 | * |
238 | * ICAZ90STATUS (deprecated) | 206 | * Z90STAT_REQUESTQ_COUNT |
207 | * Return an integer count of the number of entries waiting to be | ||
208 | * sent to a device. | ||
209 | * | ||
210 | * Z90STAT_PENDINGQ_COUNT | ||
211 | * Return an integer count of the number of entries sent to all | ||
212 | * devices awaiting the reply. | ||
213 | * | ||
214 | * Z90STAT_TOTALOPEN_COUNT | ||
215 | * Return an integer count of the number of open file handles. | ||
216 | * | ||
217 | * Z90STAT_DOMAIN_INDEX | ||
218 | * Return the integer value of the Cryptographic Domain. | ||
219 | * | ||
220 | * The following ioctls are deprecated and should be no longer used: | ||
221 | * | ||
222 | * Z90STAT_TOTALCOUNT | ||
223 | * Return an integer count of all device types together. | ||
224 | * | ||
225 | * Z90STAT_PCICACOUNT | ||
226 | * Return an integer count of all PCICAs. | ||
227 | * | ||
228 | * Z90STAT_PCICCCOUNT | ||
229 | * Return an integer count of all PCICCs. | ||
230 | * | ||
231 | * Z90STAT_PCIXCCMCL2COUNT | ||
232 | * Return an integer count of all MCL2 PCIXCCs. | ||
233 | * | ||
234 | * Z90STAT_PCIXCCMCL3COUNT | ||
235 | * Return an integer count of all MCL3 PCIXCCs. | ||
236 | * | ||
237 | * Z90STAT_CEX2CCOUNT | ||
238 | * Return an integer count of all CEX2Cs. | ||
239 | * | ||
240 | * Z90STAT_CEX2ACOUNT | ||
241 | * Return an integer count of all CEX2As. | ||
242 | * | ||
243 | * ICAZ90STATUS | ||
239 | * Return some device driver status in a ica_z90_status struct | 244 | * Return some device driver status in a ica_z90_status struct |
240 | * This takes an ica_z90_status struct as its arg. | 245 | * This takes an ica_z90_status struct as its arg. |
241 | * | 246 | * |
242 | * NOTE: this ioctl() is deprecated, and has been replaced with | 247 | * Z90STAT_PCIXCCCOUNT |
243 | * single ioctl()s for each type of status being requested | ||
244 | * | ||
245 | * Z90STAT_PCIXCCCOUNT (deprecated) | ||
246 | * Return an integer count of all PCIXCCs (MCL2 + MCL3). | 248 | * Return an integer count of all PCIXCCs (MCL2 + MCL3). |
247 | * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from | 249 | * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from |
248 | * MCL2 PCIXCCs. | 250 | * MCL2 PCIXCCs. |
249 | * | ||
250 | * Z90QUIESCE (not recommended) | ||
251 | * Quiesce the driver. This is intended to stop all new | ||
252 | * requests from being processed. Its use is NOT recommended, | ||
253 | * except in circumstances where there is no other way to stop | ||
254 | * callers from accessing the driver. Its original use was to | ||
255 | * allow the driver to be "drained" of work in preparation for | ||
256 | * a system shutdown. | ||
257 | * | ||
258 | * NOTE: once issued, this ban on new work cannot be undone | ||
259 | * except by unloading and reloading the driver. | ||
260 | */ | 251 | */ |
261 | 252 | ||
262 | /** | 253 | /** |
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h index a406fcb1e924..6d24ea7c4d9d 100644 --- a/include/asm-x86_64/elf.h +++ b/include/asm-x86_64/elf.h | |||
@@ -45,7 +45,6 @@ typedef struct user_i387_struct elf_fpregset_t; | |||
45 | 45 | ||
46 | #ifdef __KERNEL__ | 46 | #ifdef __KERNEL__ |
47 | #include <asm/processor.h> | 47 | #include <asm/processor.h> |
48 | #include <asm/compat.h> | ||
49 | 48 | ||
50 | /* | 49 | /* |
51 | * This is used to ensure we don't load something for the wrong architecture. | 50 | * This is used to ensure we don't load something for the wrong architecture. |
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h index 19f99178fe83..d5dbc87274f8 100644 --- a/include/asm-x86_64/uaccess.h +++ b/include/asm-x86_64/uaccess.h | |||
@@ -6,7 +6,6 @@ | |||
6 | */ | 6 | */ |
7 | #include <linux/compiler.h> | 7 | #include <linux/compiler.h> |
8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
9 | #include <linux/sched.h> | ||
10 | #include <linux/prefetch.h> | 9 | #include <linux/prefetch.h> |
11 | #include <asm/page.h> | 10 | #include <asm/page.h> |
12 | 11 | ||
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index d7e04689304c..ff433126361f 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
@@ -60,8 +60,6 @@ header-y += fadvise.h | |||
60 | header-y += fd.h | 60 | header-y += fd.h |
61 | header-y += fdreg.h | 61 | header-y += fdreg.h |
62 | header-y += fib_rules.h | 62 | header-y += fib_rules.h |
63 | header-y += ftape-header-segment.h | ||
64 | header-y += ftape-vendors.h | ||
65 | header-y += fuse.h | 63 | header-y += fuse.h |
66 | header-y += futex.h | 64 | header-y += futex.h |
67 | header-y += genetlink.h | 65 | header-y += genetlink.h |
@@ -206,7 +204,6 @@ unifdef-y += fcntl.h | |||
206 | unifdef-y += filter.h | 204 | unifdef-y += filter.h |
207 | unifdef-y += flat.h | 205 | unifdef-y += flat.h |
208 | unifdef-y += fs.h | 206 | unifdef-y += fs.h |
209 | unifdef-y += ftape.h | ||
210 | unifdef-y += gameport.h | 207 | unifdef-y += gameport.h |
211 | unifdef-y += generic_serial.h | 208 | unifdef-y += generic_serial.h |
212 | unifdef-y += genhd.h | 209 | unifdef-y += genhd.h |
@@ -341,6 +338,5 @@ unifdef-y += wait.h | |||
341 | unifdef-y += wanrouter.h | 338 | unifdef-y += wanrouter.h |
342 | unifdef-y += watchdog.h | 339 | unifdef-y += watchdog.h |
343 | unifdef-y += xfrm.h | 340 | unifdef-y += xfrm.h |
344 | unifdef-y += zftape.h | ||
345 | 341 | ||
346 | objhdr-y += version.h | 342 | objhdr-y += version.h |
diff --git a/include/linux/acct.h b/include/linux/acct.h index 0496d1f09952..302eb727ecb8 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h | |||
@@ -119,6 +119,7 @@ struct acct_v3 | |||
119 | #ifdef CONFIG_BSD_PROCESS_ACCT | 119 | #ifdef CONFIG_BSD_PROCESS_ACCT |
120 | struct vfsmount; | 120 | struct vfsmount; |
121 | struct super_block; | 121 | struct super_block; |
122 | struct pacct_struct; | ||
122 | extern void acct_auto_close_mnt(struct vfsmount *m); | 123 | extern void acct_auto_close_mnt(struct vfsmount *m); |
123 | extern void acct_auto_close(struct super_block *sb); | 124 | extern void acct_auto_close(struct super_block *sb); |
124 | extern void acct_init_pacct(struct pacct_struct *pacct); | 125 | extern void acct_init_pacct(struct pacct_struct *pacct); |
diff --git a/include/linux/ata.h b/include/linux/ata.h index d89441907024..1df941648a57 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -200,8 +200,9 @@ enum { | |||
200 | ATA_CBL_NONE = 0, | 200 | ATA_CBL_NONE = 0, |
201 | ATA_CBL_PATA40 = 1, | 201 | ATA_CBL_PATA40 = 1, |
202 | ATA_CBL_PATA80 = 2, | 202 | ATA_CBL_PATA80 = 2, |
203 | ATA_CBL_PATA_UNK = 3, | 203 | ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */ |
204 | ATA_CBL_SATA = 4, | 204 | ATA_CBL_PATA_UNK = 4, |
205 | ATA_CBL_SATA = 5, | ||
205 | 206 | ||
206 | /* SATA Status and Control Registers */ | 207 | /* SATA Status and Control Registers */ |
207 | SCR_STATUS = 0, | 208 | SCR_STATUS = 0, |
@@ -342,6 +343,15 @@ static inline int ata_id_is_cfa(const u16 *id) | |||
342 | return 0; | 343 | return 0; |
343 | } | 344 | } |
344 | 345 | ||
346 | static inline int ata_drive_40wire(const u16 *dev_id) | ||
347 | { | ||
348 | if (ata_id_major_version(dev_id) >= 5 && ata_id_is_sata(dev_id)) | ||
349 | return 0; /* SATA */ | ||
350 | if (dev_id[93] & 0x4000) | ||
351 | return 0; /* 80 wire */ | ||
352 | return 1; | ||
353 | } | ||
354 | |||
345 | static inline int atapi_cdb_len(const u16 *dev_id) | 355 | static inline int atapi_cdb_len(const u16 *dev_id) |
346 | { | 356 | { |
347 | u16 tmp = dev_id[0] & 0x3; | 357 | u16 tmp = dev_id[0] & 0x3; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 2fe6e3f900ba..cac7b1ef9543 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -276,7 +276,7 @@ extern int dir_notify_enable; | |||
276 | #include <linux/radix-tree.h> | 276 | #include <linux/radix-tree.h> |
277 | #include <linux/prio_tree.h> | 277 | #include <linux/prio_tree.h> |
278 | #include <linux/init.h> | 278 | #include <linux/init.h> |
279 | #include <linux/sched.h> | 279 | #include <linux/pid.h> |
280 | #include <linux/mutex.h> | 280 | #include <linux/mutex.h> |
281 | 281 | ||
282 | #include <asm/atomic.h> | 282 | #include <asm/atomic.h> |
@@ -977,36 +977,13 @@ enum { | |||
977 | #define vfs_check_frozen(sb, level) \ | 977 | #define vfs_check_frozen(sb, level) \ |
978 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) | 978 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) |
979 | 979 | ||
980 | static inline void get_fs_excl(void) | 980 | #define get_fs_excl() atomic_inc(¤t->fs_excl) |
981 | { | 981 | #define put_fs_excl() atomic_dec(¤t->fs_excl) |
982 | atomic_inc(¤t->fs_excl); | 982 | #define has_fs_excl() atomic_read(¤t->fs_excl) |
983 | } | ||
984 | |||
985 | static inline void put_fs_excl(void) | ||
986 | { | ||
987 | atomic_dec(¤t->fs_excl); | ||
988 | } | ||
989 | |||
990 | static inline int has_fs_excl(void) | ||
991 | { | ||
992 | return atomic_read(¤t->fs_excl); | ||
993 | } | ||
994 | 983 | ||
995 | 984 | /* not quite ready to be deprecated, but... */ | |
996 | /* | 985 | extern void lock_super(struct super_block *); |
997 | * Superblock locking. | 986 | extern void unlock_super(struct super_block *); |
998 | */ | ||
999 | static inline void lock_super(struct super_block * sb) | ||
1000 | { | ||
1001 | get_fs_excl(); | ||
1002 | mutex_lock(&sb->s_lock); | ||
1003 | } | ||
1004 | |||
1005 | static inline void unlock_super(struct super_block * sb) | ||
1006 | { | ||
1007 | put_fs_excl(); | ||
1008 | mutex_unlock(&sb->s_lock); | ||
1009 | } | ||
1010 | 987 | ||
1011 | /* | 988 | /* |
1012 | * VFS helper functions.. | 989 | * VFS helper functions.. |
diff --git a/include/linux/ftape-header-segment.h b/include/linux/ftape-header-segment.h deleted file mode 100644 index 4732218f0708..000000000000 --- a/include/linux/ftape-header-segment.h +++ /dev/null | |||
@@ -1,122 +0,0 @@ | |||
1 | #ifndef _FTAPE_HEADER_SEGMENT_H | ||
2 | #define _FTAPE_HEADER_SEGMENT_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996-1997 Claus-Justus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-header-segment.h,v $ | ||
23 | * $Revision: 1.2 $ | ||
24 | * $Date: 1997/10/05 19:19:28 $ | ||
25 | * | ||
26 | * This file defines some offsets into the header segment of a | ||
27 | * floppy tape cartridge. For use with the QIC-40/80/3010/3020 | ||
28 | * floppy-tape driver "ftape" for Linux. | ||
29 | */ | ||
30 | |||
31 | #define FT_SIGNATURE 0 /* must be 0xaa55aa55 */ | ||
32 | #define FT_FMT_CODE 4 | ||
33 | #define FT_REV_LEVEL 5 /* only for QIC-80 since. Rev. L (== 0x0c) */ | ||
34 | #define FT_HSEG_1 6 /* first header segment, except for format code 6 */ | ||
35 | #define FT_HSEG_2 8 /* second header segment, except for format code 6 */ | ||
36 | #define FT_FRST_SEG 10 /* first data segment, except for format code 6 */ | ||
37 | #define FT_LAST_SEG 12 /* last data segment, except for format code 6 */ | ||
38 | #define FT_FMT_DATE 14 /* date and time of most recent format, see below */ | ||
39 | #define FT_WR_DATE 18 /* date and time of most recent write or format */ | ||
40 | #define FT_SPT 24 /* segments per track */ | ||
41 | #define FT_TPC 26 /* tracks per cartridge */ | ||
42 | #define FT_FHM 27 /* floppy drive head (maximum of it) */ | ||
43 | #define FT_FTM 28 /* floppy track max. */ | ||
44 | #define FT_FSM 29 /* floppy sector max. (128) */ | ||
45 | #define FT_LABEL 30 /* floppy tape label */ | ||
46 | #define FT_LABEL_DATE 74 /* date and time the tape label was written */ | ||
47 | #define FT_LABEL_SZ (FT_LABEL_DATE - FT_LABEL) | ||
48 | #define FT_CMAP_START 78 /* starting segment of compression map */ | ||
49 | #define FT_FMT_ERROR 128 /* must be set to 0xff if remainder gets lost during | ||
50 | * tape format | ||
51 | */ | ||
52 | #define FT_SEG_CNT 130 /* number of seg. written, formatted or verified | ||
53 | * through lifetime of tape (why not read?) | ||
54 | */ | ||
55 | #define FT_INIT_DATE 138 /* date and time of initial tape format */ | ||
56 | #define FT_FMT_CNT 142 /* number of times tape has been formatted */ | ||
57 | #define FT_FSL_CNT 144 /* number of segments in failed sector log */ | ||
58 | #define FT_MK_CODE 146 /* id string of tape manufacturer */ | ||
59 | #define FT_LOT_CODE 190 /* tape manufacturer lot code */ | ||
60 | #define FT_6_HSEG_1 234 /* first header segment for format code 6 */ | ||
61 | #define FT_6_HSEG_2 238 /* second header segment for format code 6 */ | ||
62 | #define FT_6_FRST_SEG 242 /* first data segment for format code 6 */ | ||
63 | #define FT_6_LAST_SEG 246 /* last data segment for format code 6 */ | ||
64 | |||
65 | #define FT_FSL 256 | ||
66 | #define FT_HEADER_END 256 /* space beyond this point: | ||
67 | * format codes 2, 3 and 5: | ||
68 | * - failed sector log until byte 2047 | ||
69 | * - bad sector map in the reamining part of segment | ||
70 | * format codes 4 and 6: | ||
71 | * - bad sector map starts hear | ||
72 | */ | ||
73 | |||
74 | |||
75 | /* value to be stored at the FT_SIGNATURE offset | ||
76 | */ | ||
77 | #define FT_HSEG_MAGIC 0xaa55aa55 | ||
78 | #define FT_D2G_MAGIC 0x82288228 /* Ditto 2GB */ | ||
79 | |||
80 | /* data and time encoding: */ | ||
81 | #define FT_YEAR_SHIFT 25 | ||
82 | #define FT_YEAR_MASK 0xfe000000 | ||
83 | #define FT_YEAR_0 1970 | ||
84 | #define FT_YEAR_MAX 127 | ||
85 | #define FT_YEAR(year) ((((year)-FT_YEAR_0)<<FT_YEAR_SHIFT)&FT_YEAR_MASK) | ||
86 | |||
87 | #define FT_TIME_SHIFT 0 | ||
88 | #define FT_TIME_MASK 0x01FFFFFF | ||
89 | #define FT_TIME_MAX 0x01ea6dff /* last second of a year */ | ||
90 | #define FT_TIME(mo,d,h,m,s) \ | ||
91 | ((((s)+60*((m)+60*((h)+24*((d)+31*(mo))))) & FT_TIME_MASK)) | ||
92 | |||
93 | #define FT_TIME_STAMP(y,mo,d,h,m,s) (FT_YEAR(y) | FT_TIME(mo,d,h,m,s)) | ||
94 | |||
95 | /* values for the format code field */ | ||
96 | typedef enum { | ||
97 | fmt_normal = 2, /* QIC-80 post Rev. B 205Ft or 307Ft tape */ | ||
98 | fmt_1100ft = 3, /* QIC-80 post Rev. B 1100Ft tape */ | ||
99 | fmt_var = 4, /* QIC-80 post Rev. B variabel length format */ | ||
100 | fmt_425ft = 5, /* QIC-80 post Rev. B 425Ft tape */ | ||
101 | fmt_big = 6 /* QIC-3010/3020 variable length tape with more | ||
102 | * than 2^16 segments per tape | ||
103 | */ | ||
104 | } ft_format_type; | ||
105 | |||
106 | /* definitions for the failed sector log */ | ||
107 | #define FT_FSL_SIZE (2 * FT_SECTOR_SIZE - FT_HEADER_END) | ||
108 | #define FT_FSL_MAX_ENTRIES (FT_FSL_SIZE/sizeof(__u32)) | ||
109 | |||
110 | typedef struct ft_fsl_entry { | ||
111 | __u16 segment; | ||
112 | __u16 date; | ||
113 | } __attribute__ ((packed)) ft_fsl_entry; | ||
114 | |||
115 | |||
116 | /* date encoding for the failed sector log | ||
117 | * month: 1..12, day: 1..31, year: 1970..2097 | ||
118 | */ | ||
119 | #define FT_FSL_TIME_STAMP(y,m,d) \ | ||
120 | (((((y) - FT_YEAR_0)<<9)&0xfe00) | (((m)<<5)&0x01e0) | ((d)&0x001f)) | ||
121 | |||
122 | #endif /* _FTAPE_HEADER_SEGMENT_H */ | ||
diff --git a/include/linux/ftape-vendors.h b/include/linux/ftape-vendors.h deleted file mode 100644 index ec1a81f059e5..000000000000 --- a/include/linux/ftape-vendors.h +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | #ifndef _FTAPE_VENDORS_H | ||
2 | #define _FTAPE_VENDORS_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-vendors.h,v $ | ||
24 | * $Revision: 1.6 $ | ||
25 | * $Date: 1997/10/09 15:38:11 $ | ||
26 | * | ||
27 | * This file contains the supported drive types with their | ||
28 | * QIC-117 spec. vendor code and drive dependent configuration | ||
29 | * information. | ||
30 | */ | ||
31 | |||
32 | typedef enum { | ||
33 | unknown_wake_up = 0, | ||
34 | no_wake_up, | ||
35 | wake_up_colorado, | ||
36 | wake_up_mountain, | ||
37 | wake_up_insight, | ||
38 | } wake_up_types; | ||
39 | |||
40 | typedef struct { | ||
41 | wake_up_types wake_up; /* see wake_up_types */ | ||
42 | char *name; /* Text describing the drive */ | ||
43 | } wakeup_method; | ||
44 | |||
45 | /* Note: order of entries in WAKEUP_METHODS must be so that a variable | ||
46 | * of type wake_up_types can be used as an index in the array. | ||
47 | */ | ||
48 | #define WAKEUP_METHODS { \ | ||
49 | { unknown_wake_up, "Unknown" }, \ | ||
50 | { no_wake_up, "None" }, \ | ||
51 | { wake_up_colorado, "Colorado" }, \ | ||
52 | { wake_up_mountain, "Mountain" }, \ | ||
53 | { wake_up_insight, "Motor-on" }, \ | ||
54 | } | ||
55 | |||
56 | typedef struct { | ||
57 | unsigned int vendor_id; /* vendor id from drive */ | ||
58 | int speed; /* maximum tape transport speed (ips) */ | ||
59 | wake_up_types wake_up; /* see wake_up_types */ | ||
60 | char *name; /* Text describing the drive */ | ||
61 | } vendor_struct; | ||
62 | |||
63 | #define UNKNOWN_VENDOR (-1) | ||
64 | |||
65 | #define QIC117_VENDORS { \ | ||
66 | /* see _vendor_struct */ \ | ||
67 | { 0x00000, 82, wake_up_colorado, "Colorado DJ-10 (old)" }, \ | ||
68 | { 0x00047, 90, wake_up_colorado, "Colorado DJ-10/DJ-20" }, \ | ||
69 | { 0x011c2, 84, wake_up_colorado, "Colorado 700" }, \ | ||
70 | { 0x011c3, 90, wake_up_colorado, "Colorado 1400" }, \ | ||
71 | { 0x011c4, 84, wake_up_colorado, "Colorado DJ-10/DJ-20 (new)" }, \ | ||
72 | { 0x011c5, 84, wake_up_colorado, "HP Colorado T1000" }, \ | ||
73 | { 0x011c6, 90, wake_up_colorado, "HP Colorado T3000" }, \ | ||
74 | { 0x00005, 45, wake_up_mountain, "Archive 5580i" }, \ | ||
75 | { 0x10005, 50, wake_up_insight, "Insight 80Mb, Irwin 80SX" }, \ | ||
76 | { 0x00140, 74, wake_up_mountain, "Archive S.Hornet [Identity/Escom]" }, \ | ||
77 | { 0x00146, 72, wake_up_mountain, "Archive 31250Q [Escom]" }, \ | ||
78 | { 0x0014a, 100, wake_up_mountain, "Archive XL9250i [Conner/Escom]" }, \ | ||
79 | { 0x0014c, 98, wake_up_mountain, "Conner C250MQT" }, \ | ||
80 | { 0x0014e, 80, wake_up_mountain, "Conner C250MQ" }, \ | ||
81 | { 0x00150, 80, wake_up_mountain, "Conner TSM420R/TST800R" }, \ | ||
82 | { 0x00152, 80, wake_up_mountain, "Conner TSM850R" }, \ | ||
83 | { 0x00156, 80, wake_up_mountain, "Conner TSM850R/1700R/TST3200R" }, \ | ||
84 | { 0x00180, 0, wake_up_mountain, "Summit SE 150" }, \ | ||
85 | { 0x00181, 85, wake_up_mountain, "Summit SE 250, Mountain FS8000" }, \ | ||
86 | { 0x001c1, 82, no_wake_up, "Wangtek 3040F" }, \ | ||
87 | { 0x001c8, 64, no_wake_up, "Wangtek 3080F" }, \ | ||
88 | { 0x001c8, 64, wake_up_colorado, "Wangtek 3080F" }, \ | ||
89 | { 0x001ca, 67, no_wake_up, "Wangtek 3080F (new)" }, \ | ||
90 | { 0x001cc, 77, wake_up_colorado, "Wangtek 3200 / Teac 700" }, \ | ||
91 | { 0x001cd, 75, wake_up_colorado, "Reveal TB1400" }, \ | ||
92 | { 0x00380, 85, wake_up_colorado, "Exabyte Eagle-96" }, \ | ||
93 | { 0x00381, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \ | ||
94 | { 0x00382, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \ | ||
95 | { 0x003ce, 77, wake_up_colorado, "Teac 800" }, \ | ||
96 | { 0x003cf, 0, wake_up_colorado, "Teac FT3010TR" }, \ | ||
97 | { 0x08880, 64, no_wake_up, "Iomega 250, Ditto 800" }, \ | ||
98 | { 0x08880, 64, wake_up_colorado, "Iomega 250, Ditto 800" }, \ | ||
99 | { 0x08880, 64, wake_up_insight, "Iomega 250, Ditto 800" }, \ | ||
100 | { 0x08881, 80, wake_up_colorado, "Iomega 700" }, \ | ||
101 | { 0x08882, 80, wake_up_colorado, "Iomega 3200" }, \ | ||
102 | { 0x08883, 80, wake_up_colorado, "Iomega DITTO 2GB" }, \ | ||
103 | { 0x00021, 70, no_wake_up, "AIWA CT-803" }, \ | ||
104 | { 0x004c0, 80, no_wake_up, "AIWA TD-S1600" }, \ | ||
105 | { 0x00021, 0, wake_up_mountain, "COREtape QIC80" }, \ | ||
106 | { 0x00441, 0, wake_up_mountain, "ComByte DoublePlay" }, \ | ||
107 | { 0x00481, 127, wake_up_mountain, "PERTEC MyTape 800" }, \ | ||
108 | { 0x00483, 130, wake_up_mountain, "PERTEC MyTape 3200" }, \ | ||
109 | { UNKNOWN_VENDOR, 0, no_wake_up, "unknown" } \ | ||
110 | } | ||
111 | |||
112 | #define QIC117_MAKE_CODES { \ | ||
113 | { 0, "Unassigned" }, \ | ||
114 | { 1, "Alloy Computer Products" }, \ | ||
115 | { 2, "3M" }, \ | ||
116 | { 3, "Tandberg Data" }, \ | ||
117 | { 4, "Colorado" }, \ | ||
118 | { 5, "Archive/Conner" }, \ | ||
119 | { 6, "Mountain/Summit Memory Systems" }, \ | ||
120 | { 7, "Wangtek/Rexon/Tecmar" }, \ | ||
121 | { 8, "Sony" }, \ | ||
122 | { 9, "Cipher Data Products" }, \ | ||
123 | { 10, "Irwin Magnetic Systems" }, \ | ||
124 | { 11, "Braemar" }, \ | ||
125 | { 12, "Verbatim" }, \ | ||
126 | { 13, "Core International" }, \ | ||
127 | { 14, "Exabyte" }, \ | ||
128 | { 15, "Teac" }, \ | ||
129 | { 16, "Gigatek" }, \ | ||
130 | { 17, "ComByte" }, \ | ||
131 | { 18, "PERTEC Memories" }, \ | ||
132 | { 19, "Aiwa" }, \ | ||
133 | { 71, "Colorado" }, \ | ||
134 | { 546, "Iomega Inc" }, \ | ||
135 | } | ||
136 | |||
137 | #endif /* _FTAPE_VENDORS_H */ | ||
diff --git a/include/linux/ftape.h b/include/linux/ftape.h deleted file mode 100644 index 7e7038cba86a..000000000000 --- a/include/linux/ftape.h +++ /dev/null | |||
@@ -1,201 +0,0 @@ | |||
1 | #ifndef _FTAPE_H | ||
2 | #define _FTAPE_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1994-1996 Bas Laarhoven, | ||
6 | * (C) 1996-1997 Claus-Justus Heine. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2, or (at your option) | ||
11 | any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | * | ||
23 | * $Source: /homes/cvs/ftape-stacked/include/linux/ftape.h,v $ | ||
24 | * $Revision: 1.17.6.4 $ | ||
25 | * $Date: 1997/11/25 01:52:54 $ | ||
26 | * | ||
27 | * This file contains global definitions, typedefs and macro's | ||
28 | * for the QIC-40/80/3010/3020 floppy-tape driver for Linux. | ||
29 | */ | ||
30 | |||
31 | #define FTAPE_VERSION "ftape v3.04d 25/11/97" | ||
32 | |||
33 | #ifdef __KERNEL__ | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/mm.h> | ||
36 | #endif | ||
37 | #include <linux/types.h> | ||
38 | #include <linux/mtio.h> | ||
39 | |||
40 | #define FT_SECTOR(x) (x+1) /* sector offset into real sector */ | ||
41 | #define FT_SECTOR_SIZE 1024 | ||
42 | #define FT_SECTORS_PER_SEGMENT 32 | ||
43 | #define FT_ECC_SECTORS 3 | ||
44 | #define FT_SEGMENT_SIZE ((FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS) * FT_SECTOR_SIZE) | ||
45 | #define FT_BUFF_SIZE (FT_SECTORS_PER_SEGMENT * FT_SECTOR_SIZE) | ||
46 | |||
47 | /* | ||
48 | * bits of the minor device number that define drive selection | ||
49 | * methods. Could be used one day to access multiple tape | ||
50 | * drives on the same controller. | ||
51 | */ | ||
52 | #define FTAPE_SEL_A 0 | ||
53 | #define FTAPE_SEL_B 1 | ||
54 | #define FTAPE_SEL_C 2 | ||
55 | #define FTAPE_SEL_D 3 | ||
56 | #define FTAPE_SEL_MASK 3 | ||
57 | #define FTAPE_SEL(unit) ((unit) & FTAPE_SEL_MASK) | ||
58 | #define FTAPE_NO_REWIND 4 /* mask for minor nr */ | ||
59 | |||
60 | /* the following two may be reported when MTIOCGET is requested ... */ | ||
61 | typedef union { | ||
62 | struct { | ||
63 | __u8 error; | ||
64 | __u8 command; | ||
65 | } error; | ||
66 | long space; | ||
67 | } ft_drive_error; | ||
68 | typedef union { | ||
69 | struct { | ||
70 | __u8 drive_status; | ||
71 | __u8 drive_config; | ||
72 | __u8 tape_status; | ||
73 | } status; | ||
74 | long space; | ||
75 | } ft_drive_status; | ||
76 | |||
77 | #ifdef __KERNEL__ | ||
78 | |||
79 | #define FT_RQM_DELAY 12 | ||
80 | #define FT_MILLISECOND 1 | ||
81 | #define FT_SECOND 1000 | ||
82 | #define FT_FOREVER -1 | ||
83 | #ifndef HZ | ||
84 | #error "HZ undefined." | ||
85 | #endif | ||
86 | #define FT_USPT (1000000/HZ) /* microseconds per tick */ | ||
87 | |||
88 | /* This defines the number of retries that the driver will allow | ||
89 | * before giving up (and letting a higher level handle the error). | ||
90 | */ | ||
91 | #ifdef TESTING | ||
92 | #define FT_SOFT_RETRIES 1 /* number of low level retries */ | ||
93 | #define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */ | ||
94 | #else | ||
95 | #define FT_SOFT_RETRIES 6 /* number of low level retries (triple) */ | ||
96 | #define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */ | ||
97 | #endif | ||
98 | |||
99 | #ifndef THE_FTAPE_MAINTAINER | ||
100 | #define THE_FTAPE_MAINTAINER "the ftape maintainer" | ||
101 | #endif | ||
102 | |||
103 | /* Initialize missing configuration parameters. | ||
104 | */ | ||
105 | #ifndef CONFIG_FT_NR_BUFFERS | ||
106 | # define CONFIG_FT_NR_BUFFERS 3 | ||
107 | #endif | ||
108 | #ifndef CONFIG_FT_FDC_THR | ||
109 | # define CONFIG_FT_FDC_THR 8 | ||
110 | #endif | ||
111 | #ifndef CONFIG_FT_FDC_MAX_RATE | ||
112 | # define CONFIG_FT_FDC_MAX_RATE 2000 | ||
113 | #endif | ||
114 | #ifndef CONFIG_FT_FDC_BASE | ||
115 | # define CONFIG_FT_FDC_BASE 0 | ||
116 | #endif | ||
117 | #ifndef CONFIG_FT_FDC_IRQ | ||
118 | # define CONFIG_FT_FDC_IRQ 0 | ||
119 | #endif | ||
120 | #ifndef CONFIG_FT_FDC_DMA | ||
121 | # define CONFIG_FT_FDC_DMA 0 | ||
122 | #endif | ||
123 | |||
124 | /* Turn some booleans into numbers. | ||
125 | */ | ||
126 | #ifdef CONFIG_FT_PROBE_FC10 | ||
127 | # undef CONFIG_FT_PROBE_FC10 | ||
128 | # define CONFIG_FT_PROBE_FC10 1 | ||
129 | #else | ||
130 | # define CONFIG_FT_PROBE_FC10 0 | ||
131 | #endif | ||
132 | #ifdef CONFIG_FT_MACH2 | ||
133 | # undef CONFIG_FT_MACH2 | ||
134 | # define CONFIG_FT_MACH2 1 | ||
135 | #else | ||
136 | # define CONFIG_FT_MACH2 0 | ||
137 | #endif | ||
138 | |||
139 | /* Insert default settings | ||
140 | */ | ||
141 | #if CONFIG_FT_PROBE_FC10 == 1 | ||
142 | # if CONFIG_FT_FDC_BASE == 0 | ||
143 | # undef CONFIG_FT_FDC_BASE | ||
144 | # define CONFIG_FT_FDC_BASE 0x180 | ||
145 | # endif | ||
146 | # if CONFIG_FT_FDC_IRQ == 0 | ||
147 | # undef CONFIG_FT_FDC_IRQ | ||
148 | # define CONFIG_FT_FDC_IRQ 9 | ||
149 | # endif | ||
150 | # if CONFIG_FT_FDC_DMA == 0 | ||
151 | # undef CONFIG_FT_FDC_DMA | ||
152 | # define CONFIG_FT_FDC_DMA 3 | ||
153 | # endif | ||
154 | #elif CONFIG_FT_MACH2 == 1 /* CONFIG_FT_PROBE_FC10 == 1 */ | ||
155 | # if CONFIG_FT_FDC_BASE == 0 | ||
156 | # undef CONFIG_FT_FDC_BASE | ||
157 | # define CONFIG_FT_FDC_BASE 0x1E0 | ||
158 | # endif | ||
159 | # if CONFIG_FT_FDC_IRQ == 0 | ||
160 | # undef CONFIG_FT_FDC_IRQ | ||
161 | # define CONFIG_FT_FDC_IRQ 6 | ||
162 | # endif | ||
163 | # if CONFIG_FT_FDC_DMA == 0 | ||
164 | # undef CONFIG_FT_FDC_DMA | ||
165 | # define CONFIG_FT_FDC_DMA 2 | ||
166 | # endif | ||
167 | #elif defined(CONFIG_FT_ALT_FDC) /* CONFIG_FT_MACH2 */ | ||
168 | # if CONFIG_FT_FDC_BASE == 0 | ||
169 | # undef CONFIG_FT_FDC_BASE | ||
170 | # define CONFIG_FT_FDC_BASE 0x370 | ||
171 | # endif | ||
172 | # if CONFIG_FT_FDC_IRQ == 0 | ||
173 | # undef CONFIG_FT_FDC_IRQ | ||
174 | # define CONFIG_FT_FDC_IRQ 6 | ||
175 | # endif | ||
176 | # if CONFIG_FT_FDC_DMA == 0 | ||
177 | # undef CONFIG_FT_FDC_DMA | ||
178 | # define CONFIG_FT_FDC_DMA 2 | ||
179 | # endif | ||
180 | #else /* CONFIG_FT_ALT_FDC */ | ||
181 | # if CONFIG_FT_FDC_BASE == 0 | ||
182 | # undef CONFIG_FT_FDC_BASE | ||
183 | # define CONFIG_FT_FDC_BASE 0x3f0 | ||
184 | # endif | ||
185 | # if CONFIG_FT_FDC_IRQ == 0 | ||
186 | # undef CONFIG_FT_FDC_IRQ | ||
187 | # define CONFIG_FT_FDC_IRQ 6 | ||
188 | # endif | ||
189 | # if CONFIG_FT_FDC_DMA == 0 | ||
190 | # undef CONFIG_FT_FDC_DMA | ||
191 | # define CONFIG_FT_FDC_DMA 2 | ||
192 | # endif | ||
193 | #endif /* standard FDC */ | ||
194 | |||
195 | /* some useful macro's | ||
196 | */ | ||
197 | #define NR_ITEMS(x) (int)(sizeof(x)/ sizeof(*x)) | ||
198 | |||
199 | #endif /* __KERNEL__ */ | ||
200 | |||
201 | #endif | ||
diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 6e7ea2f0a57c..9dbb525c5178 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h | |||
@@ -127,6 +127,7 @@ struct igmpv3_query { | |||
127 | 127 | ||
128 | #ifdef __KERNEL__ | 128 | #ifdef __KERNEL__ |
129 | #include <linux/skbuff.h> | 129 | #include <linux/skbuff.h> |
130 | #include <linux/timer.h> | ||
130 | #include <linux/in.h> | 131 | #include <linux/in.h> |
131 | 132 | ||
132 | extern int sysctl_igmp_max_memberships; | 133 | extern int sysctl_igmp_max_memberships; |
diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h index 891bb2cf0aa8..aea34e74c496 100644 --- a/include/linux/kernelcapi.h +++ b/include/linux/kernelcapi.h | |||
@@ -47,6 +47,8 @@ typedef struct kcapi_carddef { | |||
47 | 47 | ||
48 | #include <linux/list.h> | 48 | #include <linux/list.h> |
49 | #include <linux/skbuff.h> | 49 | #include <linux/skbuff.h> |
50 | #include <linux/workqueue.h> | ||
51 | #include <asm/semaphore.h> | ||
50 | 52 | ||
51 | #define KCI_CONTRUP 0 /* arg: struct capi_profile */ | 53 | #define KCI_CONTRUP 0 /* arg: struct capi_profile */ |
52 | #define KCI_CONTRDOWN 1 /* arg: NULL */ | 54 | #define KCI_CONTRDOWN 1 /* arg: NULL */ |
diff --git a/include/linux/libata.h b/include/linux/libata.h index abd2debebca2..202283b5df96 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -140,6 +140,7 @@ enum { | |||
140 | ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ | 140 | ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ |
141 | ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */ | 141 | ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */ |
142 | ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */ | 142 | ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */ |
143 | ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */ | ||
143 | ATA_DFLAG_CFG_MASK = (1 << 8) - 1, | 144 | ATA_DFLAG_CFG_MASK = (1 << 8) - 1, |
144 | 145 | ||
145 | ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ | 146 | ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ |
@@ -175,6 +176,7 @@ enum { | |||
175 | ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H | 176 | ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H |
176 | * Register FIS clearing BSY */ | 177 | * Register FIS clearing BSY */ |
177 | ATA_FLAG_DEBUGMSG = (1 << 13), | 178 | ATA_FLAG_DEBUGMSG = (1 << 13), |
179 | ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */ | ||
178 | 180 | ||
179 | /* The following flag belongs to ap->pflags but is kept in | 181 | /* The following flag belongs to ap->pflags but is kept in |
180 | * ap->flags because it's referenced in many LLDs and will be | 182 | * ap->flags because it's referenced in many LLDs and will be |
@@ -283,6 +285,9 @@ enum { | |||
283 | ATA_EHI_QUIET = (1 << 3), /* be quiet */ | 285 | ATA_EHI_QUIET = (1 << 3), /* be quiet */ |
284 | 286 | ||
285 | ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ | 287 | ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ |
288 | ATA_EHI_PRINTINFO = (1 << 17), /* print configuration info */ | ||
289 | ATA_EHI_SETMODE = (1 << 18), /* configure transfer mode */ | ||
290 | ATA_EHI_POST_SETMODE = (1 << 19), /* revaildating after setmode */ | ||
286 | 291 | ||
287 | ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK, | 292 | ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK, |
288 | 293 | ||
@@ -307,10 +312,11 @@ enum { | |||
307 | (some horkage may be drive/controller pair dependant */ | 312 | (some horkage may be drive/controller pair dependant */ |
308 | 313 | ||
309 | ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ | 314 | ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ |
315 | ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */ | ||
316 | ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */ | ||
310 | }; | 317 | }; |
311 | 318 | ||
312 | enum hsm_task_states { | 319 | enum hsm_task_states { |
313 | HSM_ST_UNKNOWN, /* state unknown */ | ||
314 | HSM_ST_IDLE, /* no command on going */ | 320 | HSM_ST_IDLE, /* no command on going */ |
315 | HSM_ST, /* (waiting the device to) transfer data */ | 321 | HSM_ST, /* (waiting the device to) transfer data */ |
316 | HSM_ST_LAST, /* (waiting the device to) complete command */ | 322 | HSM_ST_LAST, /* (waiting the device to) complete command */ |
@@ -329,6 +335,7 @@ enum ata_completion_errors { | |||
329 | AC_ERR_SYSTEM = (1 << 6), /* system error */ | 335 | AC_ERR_SYSTEM = (1 << 6), /* system error */ |
330 | AC_ERR_INVALID = (1 << 7), /* invalid argument */ | 336 | AC_ERR_INVALID = (1 << 7), /* invalid argument */ |
331 | AC_ERR_OTHER = (1 << 8), /* unknown */ | 337 | AC_ERR_OTHER = (1 << 8), /* unknown */ |
338 | AC_ERR_NODEV_HINT = (1 << 9), /* polling device detection hint */ | ||
332 | }; | 339 | }; |
333 | 340 | ||
334 | /* forward declarations */ | 341 | /* forward declarations */ |
@@ -700,6 +707,8 @@ extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param); | |||
700 | extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param); | 707 | extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param); |
701 | extern int ata_std_prereset(struct ata_port *ap); | 708 | extern int ata_std_prereset(struct ata_port *ap); |
702 | extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); | 709 | extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); |
710 | extern int sata_port_hardreset(struct ata_port *ap, | ||
711 | const unsigned long *timing); | ||
703 | extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); | 712 | extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); |
704 | extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); | 713 | extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); |
705 | extern void ata_port_disable(struct ata_port *); | 714 | extern void ata_port_disable(struct ata_port *); |
@@ -744,9 +753,8 @@ extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg); | |||
744 | extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); | 753 | extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); |
745 | extern void ata_host_resume(struct ata_host *host); | 754 | extern void ata_host_resume(struct ata_host *host); |
746 | extern int ata_ratelimit(void); | 755 | extern int ata_ratelimit(void); |
747 | extern unsigned int ata_busy_sleep(struct ata_port *ap, | 756 | extern int ata_busy_sleep(struct ata_port *ap, |
748 | unsigned long timeout_pat, | 757 | unsigned long timeout_pat, unsigned long timeout); |
749 | unsigned long timeout); | ||
750 | extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), | 758 | extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), |
751 | void *data, unsigned long delay); | 759 | void *data, unsigned long delay); |
752 | extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, | 760 | extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, |
@@ -787,6 +795,7 @@ extern void ata_id_string(const u16 *id, unsigned char *s, | |||
787 | unsigned int ofs, unsigned int len); | 795 | unsigned int ofs, unsigned int len); |
788 | extern void ata_id_c_string(const u16 *id, unsigned char *s, | 796 | extern void ata_id_c_string(const u16 *id, unsigned char *s, |
789 | unsigned int ofs, unsigned int len); | 797 | unsigned int ofs, unsigned int len); |
798 | extern unsigned long ata_device_blacklisted(const struct ata_device *dev); | ||
790 | extern void ata_bmdma_setup (struct ata_queued_cmd *qc); | 799 | extern void ata_bmdma_setup (struct ata_queued_cmd *qc); |
791 | extern void ata_bmdma_start (struct ata_queued_cmd *qc); | 800 | extern void ata_bmdma_start (struct ata_queued_cmd *qc); |
792 | extern void ata_bmdma_stop(struct ata_queued_cmd *qc); | 801 | extern void ata_bmdma_stop(struct ata_queued_cmd *qc); |
@@ -1061,7 +1070,7 @@ static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits, | |||
1061 | udelay(10); | 1070 | udelay(10); |
1062 | status = ata_chk_status(ap); | 1071 | status = ata_chk_status(ap); |
1063 | max--; | 1072 | max--; |
1064 | } while ((status & bits) && (max > 0)); | 1073 | } while (status != 0xff && (status & bits) && (max > 0)); |
1065 | 1074 | ||
1066 | return status; | 1075 | return status; |
1067 | } | 1076 | } |
@@ -1082,7 +1091,7 @@ static inline u8 ata_wait_idle(struct ata_port *ap) | |||
1082 | { | 1091 | { |
1083 | u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); | 1092 | u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); |
1084 | 1093 | ||
1085 | if (status & (ATA_BUSY | ATA_DRQ)) { | 1094 | if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) { |
1086 | unsigned long l = ap->ioaddr.status_addr; | 1095 | unsigned long l = ap->ioaddr.status_addr; |
1087 | if (ata_msg_warn(ap)) | 1096 | if (ata_msg_warn(ap)) |
1088 | printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n", | 1097 | printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n", |
@@ -1148,37 +1157,6 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) | |||
1148 | } | 1157 | } |
1149 | 1158 | ||
1150 | /** | 1159 | /** |
1151 | * ata_irq_on - Enable interrupts on a port. | ||
1152 | * @ap: Port on which interrupts are enabled. | ||
1153 | * | ||
1154 | * Enable interrupts on a legacy IDE device using MMIO or PIO, | ||
1155 | * wait for idle, clear any pending interrupts. | ||
1156 | * | ||
1157 | * LOCKING: | ||
1158 | * Inherited from caller. | ||
1159 | */ | ||
1160 | |||
1161 | static inline u8 ata_irq_on(struct ata_port *ap) | ||
1162 | { | ||
1163 | struct ata_ioports *ioaddr = &ap->ioaddr; | ||
1164 | u8 tmp; | ||
1165 | |||
1166 | ap->ctl &= ~ATA_NIEN; | ||
1167 | ap->last_ctl = ap->ctl; | ||
1168 | |||
1169 | if (ap->flags & ATA_FLAG_MMIO) | ||
1170 | writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); | ||
1171 | else | ||
1172 | outb(ap->ctl, ioaddr->ctl_addr); | ||
1173 | tmp = ata_wait_idle(ap); | ||
1174 | |||
1175 | ap->ops->irq_clear(ap); | ||
1176 | |||
1177 | return tmp; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /** | ||
1182 | * ata_irq_ack - Acknowledge a device interrupt. | 1160 | * ata_irq_ack - Acknowledge a device interrupt. |
1183 | * @ap: Port on which interrupts are enabled. | 1161 | * @ap: Port on which interrupts are enabled. |
1184 | * | 1162 | * |
diff --git a/include/linux/module.h b/include/linux/module.h index 9258ffd8a7f0..d33df2408e05 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -6,7 +6,6 @@ | |||
6 | * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996 | 6 | * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996 |
7 | * Rewritten again by Rusty Russell, 2002 | 7 | * Rewritten again by Rusty Russell, 2002 |
8 | */ | 8 | */ |
9 | #include <linux/sched.h> | ||
10 | #include <linux/spinlock.h> | 9 | #include <linux/spinlock.h> |
11 | #include <linux/list.h> | 10 | #include <linux/list.h> |
12 | #include <linux/stat.h> | 11 | #include <linux/stat.h> |
@@ -411,17 +410,7 @@ static inline int try_module_get(struct module *module) | |||
411 | return ret; | 410 | return ret; |
412 | } | 411 | } |
413 | 412 | ||
414 | static inline void module_put(struct module *module) | 413 | extern void module_put(struct module *module); |
415 | { | ||
416 | if (module) { | ||
417 | unsigned int cpu = get_cpu(); | ||
418 | local_dec(&module->ref[cpu].count); | ||
419 | /* Maybe they're waiting for us to drop reference? */ | ||
420 | if (unlikely(!module_is_live(module))) | ||
421 | wake_up_process(module->waiter); | ||
422 | put_cpu(); | ||
423 | } | ||
424 | } | ||
425 | 414 | ||
426 | #else /*!CONFIG_MODULE_UNLOAD*/ | 415 | #else /*!CONFIG_MODULE_UNLOAD*/ |
427 | static inline int try_module_get(struct module *module) | 416 | static inline int try_module_get(struct module *module) |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 949eada46ce1..c57088f575a3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/if_packet.h> | 30 | #include <linux/if_packet.h> |
31 | 31 | ||
32 | #ifdef __KERNEL__ | 32 | #ifdef __KERNEL__ |
33 | #include <linux/timer.h> | ||
33 | #include <asm/atomic.h> | 34 | #include <asm/atomic.h> |
34 | #include <asm/cache.h> | 35 | #include <asm/cache.h> |
35 | #include <asm/byteorder.h> | 36 | #include <asm/byteorder.h> |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 61da56941dce..33581c13d947 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/compiler.h> | 9 | #include <linux/compiler.h> |
10 | #include <asm/atomic.h> | 10 | #include <asm/atomic.h> |
11 | 11 | ||
12 | #include <linux/timer.h> | ||
12 | #include <linux/netfilter_ipv4/ip_conntrack_tcp.h> | 13 | #include <linux/netfilter_ipv4/ip_conntrack_tcp.h> |
13 | #include <linux/netfilter_ipv4/ip_conntrack_icmp.h> | 14 | #include <linux/netfilter_ipv4/ip_conntrack_icmp.h> |
14 | #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> | 15 | #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> |
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h new file mode 100644 index 000000000000..2d5fd647e0e9 --- /dev/null +++ b/include/linux/pata_platform.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef __LINUX_PATA_PLATFORM_H | ||
2 | #define __LINUX_PATA_PLATFORM_H | ||
3 | |||
4 | struct pata_platform_info { | ||
5 | /* | ||
6 | * I/O port shift, for platforms with ports that are | ||
7 | * constantly spaced and need larger than the 1-byte | ||
8 | * spacing used by ata_std_ports(). | ||
9 | */ | ||
10 | unsigned int ioport_shift; | ||
11 | }; | ||
12 | |||
13 | #endif /* __LINUX_PATA_PLATFORM_H */ | ||
diff --git a/include/linux/poll.h b/include/linux/poll.h index 51e1b56741fb..27690798623f 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h | |||
@@ -8,7 +8,8 @@ | |||
8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
9 | #include <linux/wait.h> | 9 | #include <linux/wait.h> |
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/sched.h> | ||
12 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
13 | 14 | ||
14 | /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating | 15 | /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating |
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 9158a68140c9..cbfa11537421 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h | |||
@@ -19,7 +19,6 @@ | |||
19 | #ifndef _LINUX_RADIX_TREE_H | 19 | #ifndef _LINUX_RADIX_TREE_H |
20 | #define _LINUX_RADIX_TREE_H | 20 | #define _LINUX_RADIX_TREE_H |
21 | 21 | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/preempt.h> | 22 | #include <linux/preempt.h> |
24 | #include <linux/types.h> | 23 | #include <linux/types.h> |
25 | 24 | ||
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 14ec16d2d9ba..a05a5f7c0b73 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -22,12 +22,10 @@ | |||
22 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
23 | #include <asm/types.h> | 23 | #include <asm/types.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/mm.h> | ||
26 | #include <linux/highmem.h> | ||
27 | #include <linux/poll.h> | ||
28 | #include <linux/net.h> | 25 | #include <linux/net.h> |
29 | #include <linux/textsearch.h> | 26 | #include <linux/textsearch.h> |
30 | #include <net/checksum.h> | 27 | #include <net/checksum.h> |
28 | #include <linux/rcupdate.h> | ||
31 | #include <linux/dmaengine.h> | 29 | #include <linux/dmaengine.h> |
32 | 30 | ||
33 | #define HAVE_ALLOC_SKB /* For the drivers to know */ | 31 | #define HAVE_ALLOC_SKB /* For the drivers to know */ |
@@ -1295,24 +1293,6 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) | |||
1295 | return __pskb_trim(skb, len); | 1293 | return __pskb_trim(skb, len); |
1296 | } | 1294 | } |
1297 | 1295 | ||
1298 | static inline void *kmap_skb_frag(const skb_frag_t *frag) | ||
1299 | { | ||
1300 | #ifdef CONFIG_HIGHMEM | ||
1301 | BUG_ON(in_irq()); | ||
1302 | |||
1303 | local_bh_disable(); | ||
1304 | #endif | ||
1305 | return kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ); | ||
1306 | } | ||
1307 | |||
1308 | static inline void kunmap_skb_frag(void *vaddr) | ||
1309 | { | ||
1310 | kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); | ||
1311 | #ifdef CONFIG_HIGHMEM | ||
1312 | local_bh_enable(); | ||
1313 | #endif | ||
1314 | } | ||
1315 | |||
1316 | #define skb_queue_walk(queue, skb) \ | 1296 | #define skb_queue_walk(queue, skb) \ |
1317 | for (skb = (queue)->next; \ | 1297 | for (skb = (queue)->next; \ |
1318 | prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \ | 1298 | prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \ |
diff --git a/include/linux/zftape.h b/include/linux/zftape.h deleted file mode 100644 index b057c65366c6..000000000000 --- a/include/linux/zftape.h +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | #ifndef _ZFTAPE_H | ||
2 | #define _ZFTAPE_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1996, 1997 Claus-Justus Heine. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | * | ||
22 | * $Source: /homes/cvs/ftape-stacked/include/linux/zftape.h,v $ | ||
23 | * $Revision: 1.12 $ | ||
24 | * $Date: 1997/10/21 11:02:37 $ | ||
25 | * | ||
26 | * Special ioctl and other global info for the zftape VFS | ||
27 | * interface for the QIC-40/80/3010/3020 floppy-tape driver for | ||
28 | * Linux. | ||
29 | */ | ||
30 | |||
31 | #define ZFTAPE_VERSION "zftape for " FTAPE_VERSION | ||
32 | |||
33 | #include <linux/ftape.h> | ||
34 | |||
35 | #define ZFTAPE_LABEL "Ftape - The Linux Floppy Tape Project!" | ||
36 | |||
37 | /* Bits of the minor device number that control the operation mode */ | ||
38 | #define ZFT_Q80_MODE (1 << 3) | ||
39 | #define ZFT_ZIP_MODE (1 << 4) | ||
40 | #define ZFT_RAW_MODE (1 << 5) | ||
41 | #define ZFT_MINOR_OP_MASK (ZFT_Q80_MODE | \ | ||
42 | ZFT_ZIP_MODE | \ | ||
43 | ZFT_RAW_MODE) | ||
44 | #define ZFT_MINOR_MASK (FTAPE_SEL_MASK | \ | ||
45 | ZFT_MINOR_OP_MASK | \ | ||
46 | FTAPE_NO_REWIND) | ||
47 | |||
48 | #ifdef ZFT_OBSOLETE | ||
49 | struct mtblksz { | ||
50 | unsigned int mt_blksz; | ||
51 | }; | ||
52 | #define MTIOC_ZFTAPE_GETBLKSZ _IOR('m', 104, struct mtblksz) | ||
53 | #endif | ||
54 | |||
55 | #ifdef __KERNEL__ | ||
56 | |||
57 | extern int zft_init(void); | ||
58 | |||
59 | static inline __s64 zft_div_blksz(__s64 value, __u32 blk_sz) | ||
60 | { | ||
61 | if (blk_sz == 1) { | ||
62 | return value; | ||
63 | } else { | ||
64 | return (__s64)(((__u32)(value >> 10) + (blk_sz >> 10) - 1) | ||
65 | / (blk_sz >> 10)); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static inline __s64 zft_mul_blksz(__s64 value, __u32 blk_sz) | ||
70 | { | ||
71 | if (blk_sz == 1) { | ||
72 | return value; | ||
73 | } else { | ||
74 | /* if blk_sz != 1, then it is a multiple of 1024. In | ||
75 | * this case, `value' will also fit into 32 bits. | ||
76 | * | ||
77 | * Actually, this limits the capacity to 42 | ||
78 | * bits. This is (2^32)*1024, roughly a thousand | ||
79 | * times 2GB, or 3 Terabytes. Hopefully this is enough | ||
80 | */ | ||
81 | return(__s64)(((__u32)(value)*(blk_sz>>10))<<10); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | #endif | ||
86 | |||
87 | #endif | ||
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index cccea051e922..bf16d98d372c 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/compiler.h> | 18 | #include <linux/compiler.h> |
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/timer.h> | 20 | #include <linux/timer.h> |
21 | #include <linux/poll.h> | ||
21 | 22 | ||
22 | #include <net/inet_sock.h> | 23 | #include <net/inet_sock.h> |
23 | #include <net/request_sock.h> | 24 | #include <net/request_sock.h> |
diff --git a/include/net/irda/timer.h b/include/net/irda/timer.h index 2c5d8864ab77..cb61568547d1 100644 --- a/include/net/irda/timer.h +++ b/include/net/irda/timer.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define TIMER_H | 28 | #define TIMER_H |
29 | 29 | ||
30 | #include <linux/timer.h> | 30 | #include <linux/timer.h> |
31 | #include <linux/jiffies.h> | ||
31 | 32 | ||
32 | #include <asm/param.h> /* for HZ */ | 33 | #include <asm/param.h> /* for HZ */ |
33 | 34 | ||
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 032b36a0e378..bd01b4633ee2 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -56,6 +56,7 @@ union nf_conntrack_help { | |||
56 | 56 | ||
57 | #include <linux/types.h> | 57 | #include <linux/types.h> |
58 | #include <linux/skbuff.h> | 58 | #include <linux/skbuff.h> |
59 | #include <linux/timer.h> | ||
59 | 60 | ||
60 | #ifdef CONFIG_NETFILTER_DEBUG | 61 | #ifdef CONFIG_NETFILTER_DEBUG |
61 | #define NF_CT_ASSERT(x) \ | 62 | #define NF_CT_ASSERT(x) \ |
diff --git a/include/net/netlink.h b/include/net/netlink.h index fd75fd65d59e..bcaf67b7a19d 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <linux/netlink.h> | 5 | #include <linux/netlink.h> |
6 | #include <linux/jiffies.h> | ||
6 | 7 | ||
7 | /* ======================================================================== | 8 | /* ======================================================================== |
8 | * Netlink Messages and Attributes Interface (As Seen On TV) | 9 | * Netlink Messages and Attributes Interface (As Seen On TV) |
diff --git a/include/net/sock.h b/include/net/sock.h index 26fc0b16bc0c..fe3a33fad03f 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/lockdep.h> | 47 | #include <linux/lockdep.h> |
48 | #include <linux/netdevice.h> | 48 | #include <linux/netdevice.h> |
49 | #include <linux/skbuff.h> /* struct sk_buff */ | 49 | #include <linux/skbuff.h> /* struct sk_buff */ |
50 | #include <linux/mm.h> | ||
50 | #include <linux/security.h> | 51 | #include <linux/security.h> |
51 | 52 | ||
52 | #include <linux/filter.h> | 53 | #include <linux/filter.h> |
diff --git a/include/net/udp.h b/include/net/udp.h index 1548d68d45da..1b921fa81474 100644 --- a/include/net/udp.h +++ b/include/net/udp.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <net/ip.h> | 29 | #include <net/ip.h> |
30 | #include <linux/ipv6.h> | 30 | #include <linux/ipv6.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/poll.h> | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * struct udp_skb_cb - UDP(-Lite) private variables | 35 | * struct udp_skb_cb - UDP(-Lite) private variables |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 61eebec00a7b..ea0816d4904d 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -25,6 +25,8 @@ | |||
25 | 25 | ||
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/timer.h> | ||
29 | #include <linux/workqueue.h> | ||
28 | #include <scsi/iscsi_proto.h> | 30 | #include <scsi/iscsi_proto.h> |
29 | #include <scsi/iscsi_if.h> | 31 | #include <scsi/iscsi_if.h> |
30 | 32 | ||
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index afaf3e88e086..2f645dfd7f70 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <sound/asound.h> | 26 | #include <sound/asound.h> |
27 | #include <sound/memalloc.h> | 27 | #include <sound/memalloc.h> |
28 | #include <linux/poll.h> | 28 | #include <linux/poll.h> |
29 | #include <linux/mm.h> | ||
29 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
30 | 31 | ||
31 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) | 32 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 42f2f1179711..ab97e5101232 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/tty.h> | 64 | #include <linux/tty.h> |
65 | #include <linux/selinux.h> | 65 | #include <linux/selinux.h> |
66 | #include <linux/binfmts.h> | 66 | #include <linux/binfmts.h> |
67 | #include <linux/highmem.h> | ||
67 | #include <linux/syscalls.h> | 68 | #include <linux/syscalls.h> |
68 | 69 | ||
69 | #include "audit.h" | 70 | #include "audit.h" |
diff --git a/kernel/latency.c b/kernel/latency.c index 258f2555abbc..e63fcacb61a7 100644 --- a/kernel/latency.c +++ b/kernel/latency.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/notifier.h> | 38 | #include <linux/notifier.h> |
39 | #include <linux/jiffies.h> | ||
39 | #include <asm/atomic.h> | 40 | #include <asm/atomic.h> |
40 | 41 | ||
41 | struct latency_info { | 42 | struct latency_info { |
diff --git a/kernel/module.c b/kernel/module.c index 45e01cb60101..e2d09d604ca0 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -34,10 +34,10 @@ | |||
34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
35 | #include <linux/vermagic.h> | 35 | #include <linux/vermagic.h> |
36 | #include <linux/notifier.h> | 36 | #include <linux/notifier.h> |
37 | #include <linux/sched.h> | ||
37 | #include <linux/stop_machine.h> | 38 | #include <linux/stop_machine.h> |
38 | #include <linux/device.h> | 39 | #include <linux/device.h> |
39 | #include <linux/string.h> | 40 | #include <linux/string.h> |
40 | #include <linux/sched.h> | ||
41 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
42 | #include <linux/unwind.h> | 42 | #include <linux/unwind.h> |
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
@@ -790,6 +790,19 @@ static struct module_attribute refcnt = { | |||
790 | .show = show_refcnt, | 790 | .show = show_refcnt, |
791 | }; | 791 | }; |
792 | 792 | ||
793 | void module_put(struct module *module) | ||
794 | { | ||
795 | if (module) { | ||
796 | unsigned int cpu = get_cpu(); | ||
797 | local_dec(&module->ref[cpu].count); | ||
798 | /* Maybe they're waiting for us to drop reference? */ | ||
799 | if (unlikely(!module_is_live(module))) | ||
800 | wake_up_process(module->waiter); | ||
801 | put_cpu(); | ||
802 | } | ||
803 | } | ||
804 | EXPORT_SYMBOL(module_put); | ||
805 | |||
793 | #else /* !CONFIG_MODULE_UNLOAD */ | 806 | #else /* !CONFIG_MODULE_UNLOAD */ |
794 | static void print_unload_info(struct seq_file *m, struct module *mod) | 807 | static void print_unload_info(struct seq_file *m, struct module *mod) |
795 | { | 808 | { |
diff --git a/lib/random32.c b/lib/random32.c index 4a15ce51cea7..ec7f81d3fb18 100644 --- a/lib/random32.c +++ b/lib/random32.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/percpu.h> | 37 | #include <linux/percpu.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/jiffies.h> | ||
39 | #include <linux/random.h> | 40 | #include <linux/random.h> |
40 | 41 | ||
41 | struct rnd_state { | 42 | struct rnd_state { |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 485e35c3b28b..3a7052207708 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <net/tcp_states.h> | 61 | #include <net/tcp_states.h> |
62 | #include <net/route.h> | 62 | #include <net/route.h> |
63 | #include <linux/atalk.h> | 63 | #include <linux/atalk.h> |
64 | #include "../core/kmap_skb.h" | ||
64 | 65 | ||
65 | struct datalink_proto *ddp_dl, *aarp_dl; | 66 | struct datalink_proto *ddp_dl, *aarp_dl; |
66 | static const struct proto_ops atalk_dgram_ops; | 67 | static const struct proto_ops atalk_dgram_ops; |
diff --git a/net/core/kmap_skb.h b/net/core/kmap_skb.h new file mode 100644 index 000000000000..283c2b993fb8 --- /dev/null +++ b/net/core/kmap_skb.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #include <linux/highmem.h> | ||
2 | |||
3 | static inline void *kmap_skb_frag(const skb_frag_t *frag) | ||
4 | { | ||
5 | #ifdef CONFIG_HIGHMEM | ||
6 | BUG_ON(in_irq()); | ||
7 | |||
8 | local_bh_disable(); | ||
9 | #endif | ||
10 | return kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ); | ||
11 | } | ||
12 | |||
13 | static inline void kunmap_skb_frag(void *vaddr) | ||
14 | { | ||
15 | kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); | ||
16 | #ifdef CONFIG_HIGHMEM | ||
17 | local_bh_enable(); | ||
18 | #endif | ||
19 | } | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index a90bc439488e..8e1c385e5ba9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -56,7 +56,6 @@ | |||
56 | #include <linux/cache.h> | 56 | #include <linux/cache.h> |
57 | #include <linux/rtnetlink.h> | 57 | #include <linux/rtnetlink.h> |
58 | #include <linux/init.h> | 58 | #include <linux/init.h> |
59 | #include <linux/highmem.h> | ||
60 | 59 | ||
61 | #include <net/protocol.h> | 60 | #include <net/protocol.h> |
62 | #include <net/dst.h> | 61 | #include <net/dst.h> |
@@ -67,6 +66,8 @@ | |||
67 | #include <asm/uaccess.h> | 66 | #include <asm/uaccess.h> |
68 | #include <asm/system.h> | 67 | #include <asm/system.h> |
69 | 68 | ||
69 | #include "kmap_skb.h" | ||
70 | |||
70 | static kmem_cache_t *skbuff_head_cache __read_mostly; | 71 | static kmem_cache_t *skbuff_head_cache __read_mostly; |
71 | static kmem_cache_t *skbuff_fclone_cache __read_mostly; | 72 | static kmem_cache_t *skbuff_fclone_cache __read_mostly; |
72 | 73 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index ab8fafadb4ba..419c7d3289c7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -111,6 +111,7 @@ | |||
111 | #include <linux/poll.h> | 111 | #include <linux/poll.h> |
112 | #include <linux/tcp.h> | 112 | #include <linux/tcp.h> |
113 | #include <linux/init.h> | 113 | #include <linux/init.h> |
114 | #include <linux/highmem.h> | ||
114 | 115 | ||
115 | #include <asm/uaccess.h> | 116 | #include <asm/uaccess.h> |
116 | #include <asm/system.h> | 117 | #include <asm/system.h> |
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index dac89166eb18..80f469887691 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig | |||
@@ -89,4 +89,37 @@ config IP_DCCP_CCID3_DEBUG | |||
89 | parameter to 0 or 1. | 89 | parameter to 0 or 1. |
90 | 90 | ||
91 | If in doubt, say N. | 91 | If in doubt, say N. |
92 | |||
93 | config IP_DCCP_CCID3_RTO | ||
94 | int "Use higher bound for nofeedback timer" | ||
95 | default 100 | ||
96 | depends on IP_DCCP_CCID3 && EXPERIMENTAL | ||
97 | ---help--- | ||
98 | Use higher lower bound for nofeedback timer expiration. | ||
99 | |||
100 | The TFRC nofeedback timer normally expires after the maximum of 4 | ||
101 | RTTs and twice the current send interval (RFC 3448, 4.3). On LANs | ||
102 | with a small RTT this can mean a high processing load and reduced | ||
103 | performance, since then the nofeedback timer is triggered very | ||
104 | frequently. | ||
105 | |||
106 | This option enables to set a higher lower bound for the nofeedback | ||
107 | value. Values in units of milliseconds can be set here. | ||
108 | |||
109 | A value of 0 disables this feature by enforcing the value specified | ||
110 | in RFC 3448. The following values have been suggested as bounds for | ||
111 | experimental use: | ||
112 | * 16-20ms to match the typical multimedia inter-frame interval | ||
113 | * 100ms as a reasonable compromise [default] | ||
114 | * 1000ms corresponds to the lower TCP RTO bound (RFC 2988, 2.4) | ||
115 | |||
116 | The default of 100ms is a compromise between a large value for | ||
117 | efficient DCCP implementations, and a small value to avoid disrupting | ||
118 | the network in times of congestion. | ||
119 | |||
120 | The purpose of the nofeedback timer is to slow DCCP down when there | ||
121 | is serious network congestion: experimenting with larger values should | ||
122 | therefore not be performed on WANs. | ||
123 | |||
124 | |||
92 | endmenu | 125 | endmenu |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 70ebe705eb75..cf8c07b2704f 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -121,12 +121,15 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) | |||
121 | /* | 121 | /* |
122 | * Update X by | 122 | * Update X by |
123 | * If (p > 0) | 123 | * If (p > 0) |
124 | * x_calc = calcX(s, R, p); | 124 | * X_calc = calcX(s, R, p); |
125 | * X = max(min(X_calc, 2 * X_recv), s / t_mbi); | 125 | * X = max(min(X_calc, 2 * X_recv), s / t_mbi); |
126 | * Else | 126 | * Else |
127 | * If (now - tld >= R) | 127 | * If (now - tld >= R) |
128 | * X = max(min(2 * X, 2 * X_recv), s / R); | 128 | * X = max(min(2 * X, 2 * X_recv), s / R); |
129 | * tld = now; | 129 | * tld = now; |
130 | * | ||
131 | * If X has changed, we also update the scheduled send time t_now, | ||
132 | * the inter-packet interval t_ipi, and the delta value. | ||
130 | */ | 133 | */ |
131 | static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) | 134 | static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) |
132 | 135 | ||
@@ -134,8 +137,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) | |||
134 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 137 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
135 | const __u32 old_x = hctx->ccid3hctx_x; | 138 | const __u32 old_x = hctx->ccid3hctx_x; |
136 | 139 | ||
137 | /* To avoid large error in calcX */ | 140 | if (hctx->ccid3hctx_p > 0) { |
138 | if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { | ||
139 | hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, | 141 | hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, |
140 | hctx->ccid3hctx_rtt, | 142 | hctx->ccid3hctx_rtt, |
141 | hctx->ccid3hctx_p); | 143 | hctx->ccid3hctx_p); |
@@ -223,16 +225,14 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
223 | ccid3_tx_state_name(hctx->ccid3hctx_state)); | 225 | ccid3_tx_state_name(hctx->ccid3hctx_state)); |
224 | /* Halve sending rate */ | 226 | /* Halve sending rate */ |
225 | 227 | ||
226 | /* If (X_calc > 2 * X_recv) | 228 | /* If (p == 0 || X_calc > 2 * X_recv) |
227 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); | 229 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); |
228 | * Else | 230 | * Else |
229 | * X_recv = X_calc / 4; | 231 | * X_recv = X_calc / 4; |
230 | */ | 232 | */ |
231 | BUG_ON(hctx->ccid3hctx_p >= TFRC_SMALLEST_P && | 233 | BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc); |
232 | hctx->ccid3hctx_x_calc == 0); | ||
233 | 234 | ||
234 | /* check also if p is zero -> x_calc is infinity? */ | 235 | if (hctx->ccid3hctx_p == 0 || |
235 | if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || | ||
236 | hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) | 236 | hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) |
237 | hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, | 237 | hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, |
238 | hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); | 238 | hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); |
@@ -245,9 +245,10 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
245 | } | 245 | } |
246 | /* | 246 | /* |
247 | * Schedule no feedback timer to expire in | 247 | * Schedule no feedback timer to expire in |
248 | * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) | 248 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) |
249 | * See comments in packet_recv() regarding the value of t_RTO. | ||
249 | */ | 250 | */ |
250 | t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); | 251 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); |
251 | break; | 252 | break; |
252 | case TFRC_SSTATE_NO_SENT: | 253 | case TFRC_SSTATE_NO_SENT: |
253 | DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); | 254 | DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); |
@@ -338,7 +339,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
338 | * else | 339 | * else |
339 | * // send the packet in (t_nom - t_now) milliseconds. | 340 | * // send the packet in (t_nom - t_now) milliseconds. |
340 | */ | 341 | */ |
341 | if (delay >= hctx->ccid3hctx_delta) | 342 | if (delay - (long)hctx->ccid3hctx_delta >= 0) |
342 | return delay / 1000L; | 343 | return delay / 1000L; |
343 | break; | 344 | break; |
344 | case TFRC_SSTATE_TERM: | 345 | case TFRC_SSTATE_TERM: |
@@ -412,10 +413,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
412 | struct dccp_tx_hist_entry *packet; | 413 | struct dccp_tx_hist_entry *packet; |
413 | struct timeval now; | 414 | struct timeval now; |
414 | unsigned long t_nfb; | 415 | unsigned long t_nfb; |
415 | u32 t_elapsed; | ||
416 | u32 pinv; | 416 | u32 pinv; |
417 | u32 x_recv; | 417 | long r_sample, t_elapsed; |
418 | u32 r_sample; | ||
419 | 418 | ||
420 | BUG_ON(hctx == NULL); | 419 | BUG_ON(hctx == NULL); |
421 | 420 | ||
@@ -426,31 +425,44 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
426 | 425 | ||
427 | opt_recv = &hctx->ccid3hctx_options_received; | 426 | opt_recv = &hctx->ccid3hctx_options_received; |
428 | 427 | ||
429 | t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; | ||
430 | x_recv = opt_recv->ccid3or_receive_rate; | ||
431 | pinv = opt_recv->ccid3or_loss_event_rate; | ||
432 | |||
433 | switch (hctx->ccid3hctx_state) { | 428 | switch (hctx->ccid3hctx_state) { |
434 | case TFRC_SSTATE_NO_FBACK: | 429 | case TFRC_SSTATE_NO_FBACK: |
435 | case TFRC_SSTATE_FBACK: | 430 | case TFRC_SSTATE_FBACK: |
436 | /* Calculate new round trip sample by | 431 | /* get packet from history to look up t_recvdata */ |
437 | * R_sample = (now - t_recvdata) - t_delay */ | ||
438 | /* get t_recvdata from history */ | ||
439 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, | 432 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, |
440 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 433 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
441 | if (unlikely(packet == NULL)) { | 434 | if (unlikely(packet == NULL)) { |
442 | DCCP_WARN("%s, sk=%p, seqno %llu(%s) does't exist " | 435 | DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist " |
443 | "in history!\n", dccp_role(sk), sk, | 436 | "in history!\n", dccp_role(sk), sk, |
444 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, | 437 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, |
445 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); | 438 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); |
446 | return; | 439 | return; |
447 | } | 440 | } |
448 | 441 | ||
449 | /* Update RTT */ | 442 | /* Update receive rate */ |
443 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; | ||
444 | |||
445 | /* Update loss event rate */ | ||
446 | pinv = opt_recv->ccid3or_loss_event_rate; | ||
447 | if (pinv == ~0U || pinv == 0) | ||
448 | hctx->ccid3hctx_p = 0; | ||
449 | else | ||
450 | hctx->ccid3hctx_p = 1000000 / pinv; | ||
451 | |||
450 | dccp_timestamp(sk, &now); | 452 | dccp_timestamp(sk, &now); |
451 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); | 453 | |
452 | if (unlikely(r_sample <= t_elapsed)) | 454 | /* |
453 | DCCP_WARN("r_sample=%uus,t_elapsed=%uus\n", | 455 | * Calculate new round trip sample as per [RFC 3448, 4.3] by |
456 | * R_sample = (now - t_recvdata) - t_elapsed | ||
457 | */ | ||
458 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); | ||
459 | t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; | ||
460 | |||
461 | if (unlikely(r_sample <= 0)) { | ||
462 | DCCP_WARN("WARNING: R_sample (%ld) <= 0!\n", r_sample); | ||
463 | r_sample = 0; | ||
464 | } else if (unlikely(r_sample <= t_elapsed)) | ||
465 | DCCP_WARN("WARNING: r_sample=%ldus <= t_elapsed=%ldus\n", | ||
454 | r_sample, t_elapsed); | 466 | r_sample, t_elapsed); |
455 | else | 467 | else |
456 | r_sample -= t_elapsed; | 468 | r_sample -= t_elapsed; |
@@ -473,31 +485,25 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
473 | hctx->ccid3hctx_t_ld = now; | 485 | hctx->ccid3hctx_t_ld = now; |
474 | 486 | ||
475 | ccid3_update_send_time(hctx); | 487 | ccid3_update_send_time(hctx); |
476 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); | ||
477 | } else { | ||
478 | hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + | ||
479 | r_sample / 10; | ||
480 | ccid3_hc_tx_update_x(sk, &now); | ||
481 | } | ||
482 | 488 | ||
483 | ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " | 489 | ccid3_pr_debug("%s(%p), s=%u, w_init=%u, " |
484 | "r_sample=%us\n", dccp_role(sk), sk, | 490 | "R_sample=%ldus, X=%u\n", dccp_role(sk), |
485 | hctx->ccid3hctx_rtt, r_sample); | 491 | sk, hctx->ccid3hctx_s, w_init, r_sample, |
492 | hctx->ccid3hctx_x); | ||
486 | 493 | ||
487 | /* Update receive rate */ | 494 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); |
488 | hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */ | 495 | } else { |
496 | hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt + | ||
497 | (u32)r_sample ) / 10; | ||
489 | 498 | ||
490 | /* Update loss event rate */ | 499 | ccid3_hc_tx_update_x(sk, &now); |
491 | if (pinv == ~0 || pinv == 0) | ||
492 | hctx->ccid3hctx_p = 0; | ||
493 | else { | ||
494 | hctx->ccid3hctx_p = 1000000 / pinv; | ||
495 | 500 | ||
496 | if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) { | 501 | ccid3_pr_debug("%s(%p), RTT=%uus (sample=%ldus), s=%u, " |
497 | hctx->ccid3hctx_p = TFRC_SMALLEST_P; | 502 | "p=%u, X_calc=%u, X=%u\n", dccp_role(sk), |
498 | ccid3_pr_debug("%s, sk=%p, Smallest p used!\n", | 503 | sk, hctx->ccid3hctx_rtt, r_sample, |
499 | dccp_role(sk), sk); | 504 | hctx->ccid3hctx_s, hctx->ccid3hctx_p, |
500 | } | 505 | hctx->ccid3hctx_x_calc, |
506 | hctx->ccid3hctx_x); | ||
501 | } | 507 | } |
502 | 508 | ||
503 | /* unschedule no feedback timer */ | 509 | /* unschedule no feedback timer */ |
@@ -512,16 +518,20 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
512 | */ | 518 | */ |
513 | sk->sk_write_space(sk); | 519 | sk->sk_write_space(sk); |
514 | 520 | ||
515 | /* Update timeout interval. We use the alternative variant of | 521 | /* |
516 | * [RFC 3448, 3.1] which sets the upper bound of t_rto to one | 522 | * Update timeout interval for the nofeedback timer. |
517 | * second, as it is suggested for TCP (see RFC 2988, 2.4). */ | 523 | * We use a configuration option to increase the lower bound. |
524 | * This can help avoid triggering the nofeedback timer too often | ||
525 | * ('spinning') on LANs with small RTTs. | ||
526 | */ | ||
518 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, | 527 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, |
519 | USEC_PER_SEC ); | 528 | CONFIG_IP_DCCP_CCID3_RTO * |
529 | (USEC_PER_SEC/1000) ); | ||
520 | /* | 530 | /* |
521 | * Schedule no feedback timer to expire in | 531 | * Schedule no feedback timer to expire in |
522 | * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) | 532 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) |
523 | */ | 533 | */ |
524 | t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); | 534 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); |
525 | 535 | ||
526 | ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " | 536 | ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " |
527 | "expire in %lu jiffies (%luus)\n", | 537 | "expire in %lu jiffies (%luus)\n", |
@@ -535,7 +545,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
535 | hctx->ccid3hctx_idle = 1; | 545 | hctx->ccid3hctx_idle = 1; |
536 | break; | 546 | break; |
537 | case TFRC_SSTATE_NO_SENT: | 547 | case TFRC_SSTATE_NO_SENT: |
538 | DCCP_WARN("Illegal ACK received - no packet has been sent\n"); | 548 | if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) |
549 | DCCP_WARN("Illegal ACK received - no packet sent\n"); | ||
539 | /* fall through */ | 550 | /* fall through */ |
540 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ | 551 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ |
541 | break; | 552 | break; |
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 27cb20ae1da8..07596d704ef9 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -51,8 +51,6 @@ | |||
51 | /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */ | 51 | /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */ |
52 | #define TFRC_T_MBI 64 | 52 | #define TFRC_T_MBI 64 |
53 | 53 | ||
54 | #define TFRC_SMALLEST_P 40 | ||
55 | |||
56 | enum ccid3_options { | 54 | enum ccid3_options { |
57 | TFRC_OPT_LOSS_EVENT_RATE = 192, | 55 | TFRC_OPT_LOSS_EVENT_RATE = 192, |
58 | TFRC_OPT_LOSS_INTERVALS = 193, | 56 | TFRC_OPT_LOSS_INTERVALS = 193, |
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index 2601012383fb..ddac2c511e2f 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c | |||
@@ -18,10 +18,79 @@ | |||
18 | #include "tfrc.h" | 18 | #include "tfrc.h" |
19 | 19 | ||
20 | #define TFRC_CALC_X_ARRSIZE 500 | 20 | #define TFRC_CALC_X_ARRSIZE 500 |
21 | #define TFRC_CALC_X_SPLIT 50000 /* 0.05 * 1000000, details below */ | ||
22 | #define TFRC_SMALLEST_P (TFRC_CALC_X_SPLIT/TFRC_CALC_X_ARRSIZE) | ||
21 | 23 | ||
22 | #define TFRC_CALC_X_SPLIT 50000 | 24 | /* |
23 | /* equivalent to 0.05 */ | 25 | TFRC TCP Reno Throughput Equation Lookup Table for f(p) |
24 | 26 | ||
27 | The following two-column lookup table implements a part of the TCP throughput | ||
28 | equation from [RFC 3448, sec. 3.1]: | ||
29 | |||
30 | s | ||
31 | X_calc = -------------------------------------------------------------- | ||
32 | R * sqrt(2*b*p/3) + (3 * t_RTO * sqrt(3*b*p/8) * (p + 32*p^3)) | ||
33 | |||
34 | Where: | ||
35 | X is the transmit rate in bytes/second | ||
36 | s is the packet size in bytes | ||
37 | R is the round trip time in seconds | ||
38 | p is the loss event rate, between 0 and 1.0, of the number of loss | ||
39 | events as a fraction of the number of packets transmitted | ||
40 | t_RTO is the TCP retransmission timeout value in seconds | ||
41 | b is the number of packets acknowledged by a single TCP ACK | ||
42 | |||
43 | We can assume that b = 1 and t_RTO is 4 * R. The equation now becomes: | ||
44 | |||
45 | s | ||
46 | X_calc = ------------------------------------------------------- | ||
47 | R * sqrt(p*2/3) + (12 * R * sqrt(p*3/8) * (p + 32*p^3)) | ||
48 | |||
49 | which we can break down into: | ||
50 | |||
51 | s | ||
52 | X_calc = --------- | ||
53 | R * f(p) | ||
54 | |||
55 | where f(p) is given for 0 < p <= 1 by: | ||
56 | |||
57 | f(p) = sqrt(2*p/3) + 12 * sqrt(3*p/8) * (p + 32*p^3) | ||
58 | |||
59 | Since this is kernel code, floating-point arithmetic is avoided in favour of | ||
60 | integer arithmetic. This means that nearly all fractional parameters are | ||
61 | scaled by 1000000: | ||
62 | * the parameters p and R | ||
63 | * the return result f(p) | ||
64 | The lookup table therefore actually tabulates the following function g(q): | ||
65 | |||
66 | g(q) = 1000000 * f(q/1000000) | ||
67 | |||
68 | Hence, when p <= 1, q must be less than or equal to 1000000. To achieve finer | ||
69 | granularity for the practically more relevant case of small values of p (up to | ||
70 | 5%), the second column is used; the first one ranges up to 100%. This split | ||
71 | corresponds to the value of q = TFRC_CALC_X_SPLIT. At the same time this also | ||
72 | determines the smallest resolution possible with this lookup table: | ||
73 | |||
74 | TFRC_SMALLEST_P = TFRC_CALC_X_SPLIT / TFRC_CALC_X_ARRSIZE | ||
75 | |||
76 | The entire table is generated by: | ||
77 | for(i=0; i < TFRC_CALC_X_ARRSIZE; i++) { | ||
78 | lookup[i][0] = g((i+1) * 1000000/TFRC_CALC_X_ARRSIZE); | ||
79 | lookup[i][1] = g((i+1) * TFRC_CALC_X_SPLIT/TFRC_CALC_X_ARRSIZE); | ||
80 | } | ||
81 | |||
82 | With the given configuration, we have, with M = TFRC_CALC_X_ARRSIZE-1, | ||
83 | lookup[0][0] = g(1000000/(M+1)) = 1000000 * f(0.2%) | ||
84 | lookup[M][0] = g(1000000) = 1000000 * f(100%) | ||
85 | lookup[0][1] = g(TFRC_SMALLEST_P) = 1000000 * f(0.01%) | ||
86 | lookup[M][1] = g(TFRC_CALC_X_SPLIT) = 1000000 * f(5%) | ||
87 | |||
88 | In summary, the two columns represent f(p) for the following ranges: | ||
89 | * The first column is for 0.002 <= p <= 1.0 | ||
90 | * The second column is for 0.0001 <= p <= 0.05 | ||
91 | Where the columns overlap, the second (finer-grained) is given preference, | ||
92 | i.e. the first column is used only for p >= 0.05. | ||
93 | */ | ||
25 | static const u32 tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE][2] = { | 94 | static const u32 tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE][2] = { |
26 | { 37172, 8172 }, | 95 | { 37172, 8172 }, |
27 | { 53499, 11567 }, | 96 | { 53499, 11567 }, |
@@ -525,85 +594,69 @@ static const u32 tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE][2] = { | |||
525 | { 243315981, 271305 } | 594 | { 243315981, 271305 } |
526 | }; | 595 | }; |
527 | 596 | ||
528 | /* Calculate the send rate as per section 3.1 of RFC3448 | 597 | /* return largest index i such that fval <= lookup[i][small] */ |
529 | 598 | static inline u32 tfrc_binsearch(u32 fval, u8 small) | |
530 | Returns send rate in bytes per second | 599 | { |
531 | 600 | u32 try, low = 0, high = TFRC_CALC_X_ARRSIZE - 1; | |
532 | Integer maths and lookups are used as not allowed floating point in kernel | 601 | |
533 | 602 | while (low < high) { | |
534 | The function for Xcalc as per section 3.1 of RFC3448 is: | 603 | try = (low + high) / 2; |
535 | 604 | if (fval <= tfrc_calc_x_lookup[try][small]) | |
536 | X = s | 605 | high = try; |
537 | ------------------------------------------------------------- | 606 | else |
538 | R*sqrt(2*b*p/3) + (t_RTO * (3*sqrt(3*b*p/8) * p * (1+32*p^2))) | 607 | low = try + 1; |
539 | 608 | } | |
540 | where | 609 | return high; |
541 | X is the trasmit rate in bytes/second | 610 | } |
542 | s is the packet size in bytes | ||
543 | R is the round trip time in seconds | ||
544 | p is the loss event rate, between 0 and 1.0, of the number of loss events | ||
545 | as a fraction of the number of packets transmitted | ||
546 | t_RTO is the TCP retransmission timeout value in seconds | ||
547 | b is the number of packets acknowledged by a single TCP acknowledgement | ||
548 | |||
549 | we can assume that b = 1 and t_RTO is 4 * R. With this the equation becomes: | ||
550 | |||
551 | X = s | ||
552 | ----------------------------------------------------------------------- | ||
553 | R * sqrt(2 * p / 3) + (12 * R * (sqrt(3 * p / 8) * p * (1 + 32 * p^2))) | ||
554 | |||
555 | |||
556 | which we can break down into: | ||
557 | |||
558 | X = s | ||
559 | -------- | ||
560 | R * f(p) | ||
561 | |||
562 | where f(p) = sqrt(2 * p / 3) + (12 * sqrt(3 * p / 8) * p * (1 + 32 * p * p)) | ||
563 | |||
564 | Function parameters: | ||
565 | s - bytes | ||
566 | R - RTT in usecs | ||
567 | p - loss rate (decimal fraction multiplied by 1,000,000) | ||
568 | |||
569 | Returns Xcalc in bytes per second | ||
570 | |||
571 | DON'T alter this code unless you run test cases against it as the code | ||
572 | has been manipulated to stop underflow/overlow. | ||
573 | 611 | ||
574 | */ | 612 | /** |
613 | * tfrc_calc_x - Calculate the send rate as per section 3.1 of RFC3448 | ||
614 | * | ||
615 | * @s: packet size in bytes | ||
616 | * @R: RTT scaled by 1000000 (i.e., microseconds) | ||
617 | * @p: loss ratio estimate scaled by 1000000 | ||
618 | * Returns X_calc in bytes per second (not scaled). | ||
619 | * | ||
620 | * Note: DO NOT alter this code unless you run test cases against it, | ||
621 | * as the code has been optimized to stop underflow/overflow. | ||
622 | */ | ||
575 | u32 tfrc_calc_x(u16 s, u32 R, u32 p) | 623 | u32 tfrc_calc_x(u16 s, u32 R, u32 p) |
576 | { | 624 | { |
577 | int index; | 625 | int index; |
578 | u32 f; | 626 | u32 f; |
579 | u64 tmp1, tmp2; | 627 | u64 tmp1, tmp2; |
580 | 628 | ||
581 | if (p < TFRC_CALC_X_SPLIT) | 629 | /* check against invalid parameters and divide-by-zero */ |
582 | index = (p / (TFRC_CALC_X_SPLIT / TFRC_CALC_X_ARRSIZE)) - 1; | 630 | BUG_ON(p > 1000000); /* p must not exceed 100% */ |
583 | else | 631 | BUG_ON(p == 0); /* f(0) = 0, divide by zero */ |
584 | index = (p / (1000000 / TFRC_CALC_X_ARRSIZE)) - 1; | 632 | if (R == 0) { /* possible divide by zero */ |
633 | DCCP_CRIT("WARNING: RTT is 0, returning maximum X_calc."); | ||
634 | return ~0U; | ||
635 | } | ||
585 | 636 | ||
586 | if (index < 0) | 637 | if (p <= TFRC_CALC_X_SPLIT) { /* 0.0000 < p <= 0.05 */ |
587 | /* p should be 0 unless there is a bug in my code */ | 638 | if (p < TFRC_SMALLEST_P) { /* 0.0000 < p < 0.0001 */ |
588 | index = 0; | 639 | DCCP_WARN("Value of p (%d) below resolution. " |
640 | "Substituting %d\n", p, TFRC_SMALLEST_P); | ||
641 | index = 0; | ||
642 | } else /* 0.0001 <= p <= 0.05 */ | ||
643 | index = p/TFRC_SMALLEST_P - 1; | ||
589 | 644 | ||
590 | if (R == 0) { | 645 | f = tfrc_calc_x_lookup[index][1]; |
591 | DCCP_WARN("RTT==0, setting to 1\n"); | ||
592 | R = 1; /* RTT can't be zero or else divide by zero */ | ||
593 | } | ||
594 | 646 | ||
595 | BUG_ON(index >= TFRC_CALC_X_ARRSIZE); | 647 | } else { /* 0.05 < p <= 1.00 */ |
648 | index = p/(1000000/TFRC_CALC_X_ARRSIZE) - 1; | ||
596 | 649 | ||
597 | if (p >= TFRC_CALC_X_SPLIT) | ||
598 | f = tfrc_calc_x_lookup[index][0]; | 650 | f = tfrc_calc_x_lookup[index][0]; |
599 | else | 651 | } |
600 | f = tfrc_calc_x_lookup[index][1]; | ||
601 | 652 | ||
653 | /* The following computes X = s/(R*f(p)) in bytes per second. Since f(p) | ||
654 | * and R are both scaled by 1000000, we need to multiply by 1000000^2. | ||
655 | * ==> DO NOT alter this unless you test against overflow on 32 bit */ | ||
602 | tmp1 = ((u64)s * 100000000); | 656 | tmp1 = ((u64)s * 100000000); |
603 | tmp2 = ((u64)R * (u64)f); | 657 | tmp2 = ((u64)R * (u64)f); |
604 | do_div(tmp2, 10000); | 658 | do_div(tmp2, 10000); |
605 | do_div(tmp1, tmp2); | 659 | do_div(tmp1, tmp2); |
606 | /* Don't alter above math unless you test due to overflow on 32 bit */ | ||
607 | 660 | ||
608 | return (u32)tmp1; | 661 | return (u32)tmp1; |
609 | } | 662 | } |
@@ -611,33 +664,36 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) | |||
611 | EXPORT_SYMBOL_GPL(tfrc_calc_x); | 664 | EXPORT_SYMBOL_GPL(tfrc_calc_x); |
612 | 665 | ||
613 | /* | 666 | /* |
614 | * args: fvalue - function value to match | 667 | * tfrc_calc_x_reverse_lookup - try to find p given f(p) |
615 | * returns: p closest to that value | ||
616 | * | 668 | * |
617 | * both fvalue and p are multiplied by 1,000,000 to use ints | 669 | * @fvalue: function value to match, scaled by 1000000 |
670 | * Returns closest match for p, also scaled by 1000000 | ||
618 | */ | 671 | */ |
619 | u32 tfrc_calc_x_reverse_lookup(u32 fvalue) | 672 | u32 tfrc_calc_x_reverse_lookup(u32 fvalue) |
620 | { | 673 | { |
621 | int ctr = 0; | 674 | int index; |
622 | int small; | ||
623 | 675 | ||
624 | if (fvalue < tfrc_calc_x_lookup[0][1]) | 676 | if (fvalue == 0) /* f(p) = 0 whenever p = 0 */ |
625 | return 0; | 677 | return 0; |
626 | 678 | ||
627 | if (fvalue <= tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][1]) | 679 | /* Error cases. */ |
628 | small = 1; | 680 | if (fvalue < tfrc_calc_x_lookup[0][1]) { |
629 | else if (fvalue > tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][0]) | 681 | DCCP_WARN("fvalue %d smaller than resolution\n", fvalue); |
682 | return tfrc_calc_x_lookup[0][1]; | ||
683 | } | ||
684 | if (fvalue > tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][0]) { | ||
685 | DCCP_WARN("fvalue %d exceeds bounds!\n", fvalue); | ||
630 | return 1000000; | 686 | return 1000000; |
631 | else | 687 | } |
632 | small = 0; | ||
633 | |||
634 | while (fvalue > tfrc_calc_x_lookup[ctr][small]) | ||
635 | ctr++; | ||
636 | 688 | ||
637 | if (small) | 689 | if (fvalue <= tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][1]) { |
638 | return TFRC_CALC_X_SPLIT * ctr / TFRC_CALC_X_ARRSIZE; | 690 | index = tfrc_binsearch(fvalue, 1); |
639 | else | 691 | return (index + 1) * TFRC_CALC_X_SPLIT / TFRC_CALC_X_ARRSIZE; |
640 | return 1000000 * ctr / TFRC_CALC_X_ARRSIZE; | 692 | } |
693 | |||
694 | /* else ... it must be in the coarse-grained column */ | ||
695 | index = tfrc_binsearch(fvalue, 0); | ||
696 | return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE; | ||
641 | } | 697 | } |
642 | 698 | ||
643 | EXPORT_SYMBOL_GPL(tfrc_calc_x_reverse_lookup); | 699 | EXPORT_SYMBOL_GPL(tfrc_calc_x_reverse_lookup); |
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 4200ec509866..fc1f99a59732 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/random.h> | 16 | #include <linux/random.h> |
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/netdevice.h> | 18 | #include <linux/netdevice.h> |
19 | #include <linux/mm.h> | ||
19 | #include <linux/if_ether.h> | 20 | #include <linux/if_ether.h> |
20 | #include <linux/if_arp.h> | 21 | #include <linux/if_arp.h> |
21 | #include <asm/string.h> | 22 | #include <asm/string.h> |
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 1b2efff11d39..7a95c3d81314 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/random.h> | 16 | #include <linux/random.h> |
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/mm.h> | ||
18 | #include <asm/string.h> | 19 | #include <asm/string.h> |
19 | 20 | ||
20 | #include <net/ieee80211.h> | 21 | #include <net/ieee80211.h> |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 1da3d32f8289..a35209d517ad 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/mm.h> | 53 | #include <linux/mm.h> |
54 | #include <linux/string.h> | 54 | #include <linux/string.h> |
55 | #include <linux/errno.h> | 55 | #include <linux/errno.h> |
56 | #include <linux/highmem.h> | ||
56 | 57 | ||
57 | #include <linux/socket.h> | 58 | #include <linux/socket.h> |
58 | #include <linux/sockios.h> | 59 | #include <linux/sockios.h> |
diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c index 524751e031de..a4385a2180ee 100644 --- a/net/ipv4/ipvs/ip_vs_lblc.c +++ b/net/ipv4/ipvs/ip_vs_lblc.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/module.h> | 45 | #include <linux/module.h> |
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/skbuff.h> | 47 | #include <linux/skbuff.h> |
48 | #include <linux/jiffies.h> | ||
48 | 49 | ||
49 | /* for sysctl */ | 50 | /* for sysctl */ |
50 | #include <linux/fs.h> | 51 | #include <linux/fs.h> |
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c index 08990192b6ec..fe1af5d079af 100644 --- a/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/net/ipv4/ipvs/ip_vs_lblcr.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/kernel.h> | 44 | #include <linux/kernel.h> |
45 | #include <linux/skbuff.h> | 45 | #include <linux/skbuff.h> |
46 | #include <linux/jiffies.h> | ||
46 | 47 | ||
47 | /* for sysctl */ | 48 | /* for sysctl */ |
48 | #include <linux/fs.h> | 49 | #include <linux/fs.h> |
diff --git a/net/irda/discovery.c b/net/irda/discovery.c index 3fefc822c1c0..89fd2a2cbca6 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/socket.h> | 34 | #include <linux/socket.h> |
35 | #include <linux/fs.h> | ||
35 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
36 | 37 | ||
37 | #include <net/irda/irda.h> | 38 | #include <net/irda/irda.h> |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 8cfd076c4c12..8f1c6d65b247 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
30 | #include <linux/fs.h> | ||
30 | #include <linux/string.h> | 31 | #include <linux/string.h> |
31 | #include <linux/init.h> | 32 | #include <linux/init.h> |
32 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 9c446a72ff1f..252f11012566 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/fs.h> | ||
29 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
30 | 31 | ||
31 | #include <asm/byteorder.h> | 32 | #include <asm/byteorder.h> |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 93d97d9f9da8..eaa0f8a1adb6 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/netdevice.h> | 47 | #include <linux/netdevice.h> |
48 | #include <linux/socket.h> | 48 | #include <linux/socket.h> |
49 | #include <linux/mm.h> | ||
49 | 50 | ||
50 | #include <net/netfilter/nf_conntrack.h> | 51 | #include <net/netfilter/nf_conntrack.h> |
51 | #include <net/netfilter/nf_conntrack_l3proto.h> | 52 | #include <net/netfilter/nf_conntrack_l3proto.h> |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 58522fc65d33..8996584b8499 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/mm.h> | ||
24 | 25 | ||
25 | #include <linux/netfilter/x_tables.h> | 26 | #include <linux/netfilter/x_tables.h> |
26 | #include <linux/netfilter_arp.h> | 27 | #include <linux/netfilter_arp.h> |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 501c564e247f..a98de0b54d65 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | #include <linux/mm.h> | ||
20 | #include <linux/in.h> | 21 | #include <linux/in.h> |
21 | #include <linux/ip.h> | 22 | #include <linux/ip.h> |
22 | #include <linux/ipv6.h> | 23 | #include <linux/ipv6.h> |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 271d2eed0699..08e68b67bbf6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -71,6 +71,7 @@ | |||
71 | #include <asm/uaccess.h> | 71 | #include <asm/uaccess.h> |
72 | #include <asm/ioctls.h> | 72 | #include <asm/ioctls.h> |
73 | #include <asm/page.h> | 73 | #include <asm/page.h> |
74 | #include <asm/cacheflush.h> | ||
74 | #include <asm/io.h> | 75 | #include <asm/io.h> |
75 | #include <linux/proc_fs.h> | 76 | #include <linux/proc_fs.h> |
76 | #include <linux/seq_file.h> | 77 | #include <linux/seq_file.h> |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 6f97665983d2..311205ffa775 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -858,7 +858,6 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, | |||
858 | int i; | 858 | int i; |
859 | 859 | ||
860 | xp->xfrm_nr = nr; | 860 | xp->xfrm_nr = nr; |
861 | xp->family = ut->family; | ||
862 | for (i = 0; i < nr; i++, ut++) { | 861 | for (i = 0; i < nr; i++, ut++) { |
863 | struct xfrm_tmpl *t = &xp->xfrm_vec[i]; | 862 | struct xfrm_tmpl *t = &xp->xfrm_vec[i]; |
864 | 863 | ||
@@ -876,19 +875,53 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, | |||
876 | } | 875 | } |
877 | } | 876 | } |
878 | 877 | ||
878 | static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) | ||
879 | { | ||
880 | int i; | ||
881 | |||
882 | if (nr > XFRM_MAX_DEPTH) | ||
883 | return -EINVAL; | ||
884 | |||
885 | for (i = 0; i < nr; i++) { | ||
886 | /* We never validated the ut->family value, so many | ||
887 | * applications simply leave it at zero. The check was | ||
888 | * never made and ut->family was ignored because all | ||
889 | * templates could be assumed to have the same family as | ||
890 | * the policy itself. Now that we will have ipv4-in-ipv6 | ||
891 | * and ipv6-in-ipv4 tunnels, this is no longer true. | ||
892 | */ | ||
893 | if (!ut[i].family) | ||
894 | ut[i].family = family; | ||
895 | |||
896 | switch (ut[i].family) { | ||
897 | case AF_INET: | ||
898 | break; | ||
899 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
900 | case AF_INET6: | ||
901 | break; | ||
902 | #endif | ||
903 | default: | ||
904 | return -EINVAL; | ||
905 | }; | ||
906 | } | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
879 | static int copy_from_user_tmpl(struct xfrm_policy *pol, struct rtattr **xfrma) | 911 | static int copy_from_user_tmpl(struct xfrm_policy *pol, struct rtattr **xfrma) |
880 | { | 912 | { |
881 | struct rtattr *rt = xfrma[XFRMA_TMPL-1]; | 913 | struct rtattr *rt = xfrma[XFRMA_TMPL-1]; |
882 | struct xfrm_user_tmpl *utmpl; | ||
883 | int nr; | ||
884 | 914 | ||
885 | if (!rt) { | 915 | if (!rt) { |
886 | pol->xfrm_nr = 0; | 916 | pol->xfrm_nr = 0; |
887 | } else { | 917 | } else { |
888 | nr = (rt->rta_len - sizeof(*rt)) / sizeof(*utmpl); | 918 | struct xfrm_user_tmpl *utmpl = RTA_DATA(rt); |
919 | int nr = (rt->rta_len - sizeof(*rt)) / sizeof(*utmpl); | ||
920 | int err; | ||
889 | 921 | ||
890 | if (nr > XFRM_MAX_DEPTH) | 922 | err = validate_tmpl(nr, utmpl, pol->family); |
891 | return -EINVAL; | 923 | if (err) |
924 | return err; | ||
892 | 925 | ||
893 | copy_templates(pol, RTA_DATA(rt), nr); | 926 | copy_templates(pol, RTA_DATA(rt), nr); |
894 | } | 927 | } |
@@ -1530,7 +1563,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xf | |||
1530 | } | 1563 | } |
1531 | 1564 | ||
1532 | /* build an XP */ | 1565 | /* build an XP */ |
1533 | xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err); if (!xp) { | 1566 | xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err); |
1567 | if (!xp) { | ||
1534 | kfree(x); | 1568 | kfree(x); |
1535 | return err; | 1569 | return err; |
1536 | } | 1570 | } |
@@ -1979,7 +2013,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, | |||
1979 | return NULL; | 2013 | return NULL; |
1980 | 2014 | ||
1981 | nr = ((len - sizeof(*p)) / sizeof(*ut)); | 2015 | nr = ((len - sizeof(*p)) / sizeof(*ut)); |
1982 | if (nr > XFRM_MAX_DEPTH) | 2016 | if (validate_tmpl(nr, ut, p->sel.family)) |
1983 | return NULL; | 2017 | return NULL; |
1984 | 2018 | ||
1985 | if (p->dir > XFRM_POLICY_OUT) | 2019 | if (p->dir > XFRM_POLICY_OUT) |
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c index b1c5d8286e40..147c8a951137 100644 --- a/sound/oss/cs46xx.c +++ b/sound/oss/cs46xx.c | |||
@@ -91,6 +91,7 @@ | |||
91 | #include <linux/poll.h> | 91 | #include <linux/poll.h> |
92 | #include <linux/ac97_codec.h> | 92 | #include <linux/ac97_codec.h> |
93 | #include <linux/mutex.h> | 93 | #include <linux/mutex.h> |
94 | #include <linux/mm.h> | ||
94 | 95 | ||
95 | #include <asm/io.h> | 96 | #include <asm/io.h> |
96 | #include <asm/dma.h> | 97 | #include <asm/dma.h> |
diff --git a/sound/oss/dmabuf.c b/sound/oss/dmabuf.c index b256c0401161..eaf69971bf92 100644 --- a/sound/oss/dmabuf.c +++ b/sound/oss/dmabuf.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #define BE_CONSERVATIVE | 25 | #define BE_CONSERVATIVE |
26 | #define SAMPLE_ROUNDUP 0 | 26 | #define SAMPLE_ROUNDUP 0 |
27 | 27 | ||
28 | #include <linux/mm.h> | ||
28 | #include "sound_config.h" | 29 | #include "sound_config.h" |
29 | 30 | ||
30 | #define DMAP_FREE_ON_CLOSE 0 | 31 | #define DMAP_FREE_ON_CLOSE 0 |
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c index cde4d59d5430..86dd23974e05 100644 --- a/sound/oss/emu10k1/audio.c +++ b/sound/oss/emu10k1/audio.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/bitops.h> | 36 | #include <linux/bitops.h> |
37 | #include <asm/io.h> | 37 | #include <asm/io.h> |
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <linux/mm.h> | ||
39 | #include <linux/smp_lock.h> | 40 | #include <linux/smp_lock.h> |
40 | 41 | ||
41 | #include "hwaccess.h" | 42 | #include "hwaccess.h" |
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c index ddf6b0a0bca5..cc282a0cd539 100644 --- a/sound/oss/es1371.c +++ b/sound/oss/es1371.c | |||
@@ -130,6 +130,7 @@ | |||
130 | #include <linux/wait.h> | 130 | #include <linux/wait.h> |
131 | #include <linux/dma-mapping.h> | 131 | #include <linux/dma-mapping.h> |
132 | #include <linux/mutex.h> | 132 | #include <linux/mutex.h> |
133 | #include <linux/mm.h> | ||
133 | 134 | ||
134 | #include <asm/io.h> | 135 | #include <asm/io.h> |
135 | #include <asm/page.h> | 136 | #include <asm/page.h> |
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c index 240cc7939b69..c3c8a720d555 100644 --- a/sound/oss/i810_audio.c +++ b/sound/oss/i810_audio.c | |||
@@ -101,6 +101,7 @@ | |||
101 | #include <linux/ac97_codec.h> | 101 | #include <linux/ac97_codec.h> |
102 | #include <linux/bitops.h> | 102 | #include <linux/bitops.h> |
103 | #include <linux/mutex.h> | 103 | #include <linux/mutex.h> |
104 | #include <linux/mm.h> | ||
104 | 105 | ||
105 | #include <asm/uaccess.h> | 106 | #include <asm/uaccess.h> |
106 | 107 | ||
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 75c5e745705f..8fb8e7f99556 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
43 | #include <linux/smp_lock.h> | 43 | #include <linux/smp_lock.h> |
44 | #include <linux/module.h> | 44 | #include <linux/module.h> |
45 | #include <linux/mm.h> | ||
45 | 46 | ||
46 | /* | 47 | /* |
47 | * This ought to be moved into include/asm/dma.h | 48 | * This ought to be moved into include/asm/dma.h |
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c index 51f2fa615413..30c36d1f35d7 100644 --- a/sound/oss/sscape.c +++ b/sound/oss/sscape.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
41 | #include <linux/proc_fs.h> | 41 | #include <linux/proc_fs.h> |
42 | #include <linux/mm.h> | ||
42 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
43 | 44 | ||
44 | #include "coproc.h" | 45 | #include "coproc.h" |
diff --git a/sound/oss/trident.c b/sound/oss/trident.c index 7a363a178afd..6b1f8c9cdcf8 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c | |||
@@ -216,6 +216,7 @@ | |||
216 | #include <linux/gameport.h> | 216 | #include <linux/gameport.h> |
217 | #include <linux/kernel.h> | 217 | #include <linux/kernel.h> |
218 | #include <linux/mutex.h> | 218 | #include <linux/mutex.h> |
219 | #include <linux/mm.h> | ||
219 | 220 | ||
220 | #include <asm/uaccess.h> | 221 | #include <asm/uaccess.h> |
221 | #include <asm/io.h> | 222 | #include <asm/io.h> |