[DLM] Clean up lowcomms
[pandora-kernel.git] / drivers / char / ftape / lowlevel / fdc-io.c
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(&current->sighand->siglock);
382         old_sigmask = current->blocked;
383         sigfillset(&current->blocked);
384         recalc_sigpending();
385         spin_unlock_irq(&current->sighand->siglock);
386
387         set_current_state(TASK_INTERRUPTIBLE);
388         add_wait_queue(&ftape_wait_intr, &wait);
389         while (!ft_interrupt_seen && timeout)
390                 timeout = schedule_timeout_interruptible(timeout);
391
392         spin_lock_irq(&current->sighand->siglock);
393         current->blocked = old_sigmask;
394         recalc_sigpending();
395         spin_unlock_irq(&current->sighand->siglock);
396         
397         remove_wait_queue(&ftape_wait_intr, &wait);
398         /*  the following IS necessary. True: as well
399          *  wake_up_interruptible() as the schedule() set TASK_RUNNING
400          *  when they wakeup a task, BUT: it may very well be that
401          *  ft_interrupt_seen is already set to 1 when we enter here
402          *  in which case schedule() gets never called, and
403          *  TASK_RUNNING never set. This has the funny effect that we
404          *  execute all the code until we leave kernel space, but then
405          *  the task is stopped (a task CANNOT be preempted while in
406          *  kernel mode. Sending a pair of SIGSTOP/SIGCONT to the
407          *  tasks wakes it up again. Funny! :-)
408          */
409         current->state = TASK_RUNNING; 
410         if (ft_interrupt_seen) { /* woken up by interrupt */
411                 ft_interrupt_seen = 0;
412                 TRACE_EXIT 0;
413         }
414         /*  Original comment:
415          *  In first instance, next statement seems unnecessary since
416          *  it will be cleared in fdc_command. However, a small part of
417          *  the software seems to rely on this being cleared here
418          *  (ftape_close might fail) so stick to it until things get fixed !
419          */
420         /*  My deeply sought of knowledge:
421          *  Behold NO! It is obvious. fdc_reset() doesn't call fdc_command()
422          *  but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to
423          *  be reset here.
424          */
425         ft_interrupt_seen = 0;  /* clear for next call */
426         if (!resetting) {
427                 resetting = 1;  /* break infinite recursion if reset fails */
428                 TRACE(ft_t_any, "cleanup reset");
429                 fdc_reset();
430                 resetting = 0;
431         }
432         TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;
433 }
434
435 /*      Start/stop drive motor. Enable DMA mode.
436  */
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(&reg[i]);
976                 TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]);
977         }
978         if (fifo_state && lock_state && fifo_thr) {
979                 *fifo_state = (reg[8] & 0x20) == 0;
980                 *lock_state = reg[7] & 0x80;
981                 *fifo_thr = 1 + (reg[8] & 0x0f);
982         }
983         TRACE(ft_t_noise,
984               "original fifo state: %sabled, threshold %d, %slocked",
985               ((reg[8] & 0x20) == 0) ? "en" : "dis",
986               1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not ");
987         /*  If fdc is already locked, unlock it first ! */
988         if (reg[7] & 0x80) {
989                 fdc_ready_wait(100);
990                 TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1),
991                             TRACE(ft_t_bug, "FDC unlock command failed, "
992                                   "configuration unchanged"));
993         }
994         fdc_fifo_locked = 0;
995         /*  Enable fifo and set threshold at xx bytes to allow a
996          *  reasonably large latency and reduce number of dma bursts.
997          */
998         fdc_ready_wait(100);
999         if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) {
1000                 TRACE(ft_t_bug, "configure cmd failed, fifo unchanged");
1001         }
1002         /*  Now lock configuration so reset will not change it
1003          */
1004         if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 ||
1005            stat != 0x10) {
1006                 TRACE_ABORT(-EIO, ft_t_bug,
1007                             "FDC lock command failed, stat = 0x%02x", stat);
1008         }
1009         fdc_fifo_locked = 1;
1010         TRACE_EXIT result;
1011 }
1012
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 }