aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ftape/lowlevel/fdc-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ftape/lowlevel/fdc-io.c')
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c1350
1 files changed, 0 insertions, 1350 deletions
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
deleted file mode 100644
index 65c9d2ec60bd..000000000000
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ /dev/null
@@ -1,1350 +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/config.h> /* for CONFIG_FT_* */
30#include <linux/errno.h>
31#include <linux/sched.h>
32#include <linux/ioport.h>
33#include <linux/interrupt.h>
34#include <linux/kernel.h>
35#include <asm/system.h>
36#include <asm/io.h>
37#include <asm/dma.h>
38#include <asm/irq.h>
39
40#include <linux/ftape.h>
41#include <linux/qic117.h>
42#include "../lowlevel/ftape-tracing.h"
43#include "../lowlevel/fdc-io.h"
44#include "../lowlevel/fdc-isr.h"
45#include "../lowlevel/ftape-io.h"
46#include "../lowlevel/ftape-rw.h"
47#include "../lowlevel/ftape-ctl.h"
48#include "../lowlevel/ftape-calibr.h"
49#include "../lowlevel/fc-10.h"
50
51/* Global vars.
52 */
53static int ftape_motor;
54volatile int ftape_current_cylinder = -1;
55volatile fdc_mode_enum fdc_mode = fdc_idle;
56fdc_config_info fdc;
57DECLARE_WAIT_QUEUE_HEAD(ftape_wait_intr);
58
59unsigned int ft_fdc_base = CONFIG_FT_FDC_BASE;
60unsigned int ft_fdc_irq = CONFIG_FT_FDC_IRQ;
61unsigned int ft_fdc_dma = CONFIG_FT_FDC_DMA;
62unsigned int ft_fdc_threshold = CONFIG_FT_FDC_THR; /* bytes */
63unsigned int ft_fdc_rate_limit = CONFIG_FT_FDC_MAX_RATE; /* bits/sec */
64int ft_probe_fc10 = CONFIG_FT_PROBE_FC10;
65int ft_mach2 = CONFIG_FT_MACH2;
66
67/* Local vars.
68 */
69static spinlock_t fdc_io_lock;
70static unsigned int fdc_calibr_count;
71static unsigned int fdc_calibr_time;
72static int fdc_status;
73volatile __u8 fdc_head; /* FDC head from sector id */
74volatile __u8 fdc_cyl; /* FDC track from sector id */
75volatile __u8 fdc_sect; /* FDC sector from sector id */
76static int fdc_data_rate = 500; /* data rate (Kbps) */
77static int fdc_rate_code; /* data rate code (0 == 500 Kbps) */
78static int fdc_seek_rate = 2; /* step rate (msec) */
79static void (*do_ftape) (void);
80static int fdc_fifo_state; /* original fifo setting - fifo enabled */
81static int fdc_fifo_thr; /* original fifo setting - threshold */
82static int fdc_lock_state; /* original lock setting - locked */
83static int fdc_fifo_locked; /* has fifo && lock set ? */
84static __u8 fdc_precomp; /* default precomp. value (nsec) */
85static __u8 fdc_prec_code; /* fdc precomp. select code */
86
87static char ftape_id[] = "ftape"; /* used by request irq and free irq */
88
89static int fdc_set_seek_rate(int seek_rate);
90
91void fdc_catch_stray_interrupts(int count)
92{
93 unsigned long flags;
94
95 spin_lock_irqsave(&fdc_io_lock, flags);
96 if (count == 0) {
97 ft_expected_stray_interrupts = 0;
98 } else {
99 ft_expected_stray_interrupts += count;
100 }
101 spin_unlock_irqrestore(&fdc_io_lock, flags);
102}
103
104/* Wait during a timeout period for a given FDC status.
105 * If usecs == 0 then just test status, else wait at least for usecs.
106 * Returns -ETIME on timeout. Function must be calibrated first !
107 */
108static int fdc_wait(unsigned int usecs, __u8 mask, __u8 state)
109{
110 int count_1 = (fdc_calibr_count * usecs +
111 fdc_calibr_count - 1) / fdc_calibr_time;
112
113 do {
114 fdc_status = inb_p(fdc.msr);
115 if ((fdc_status & mask) == state) {
116 return 0;
117 }
118 } while (count_1-- >= 0);
119 return -ETIME;
120}
121
122int fdc_ready_wait(unsigned int usecs)
123{
124 return fdc_wait(usecs, FDC_DATA_READY | FDC_BUSY, FDC_DATA_READY);
125}
126
127/* Why can't we just use udelay()?
128 */
129static void fdc_usec_wait(unsigned int usecs)
130{
131 fdc_wait(usecs, 0, 1); /* will always timeout ! */
132}
133
134static int fdc_ready_out_wait(unsigned int usecs)
135{
136 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
137 return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);
138}
139
140void fdc_wait_calibrate(void)
141{
142 ftape_calibrate("fdc_wait",
143 fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time);
144}
145
146/* Wait for a (short) while for the FDC to become ready
147 * and transfer the next command byte.
148 * Return -ETIME on timeout on getting ready (depends on hardware!).
149 */
150static int fdc_write(const __u8 data)
151{
152 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
153 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) {
154 return -ETIME;
155 } else {
156 outb(data, fdc.fifo);
157 return 0;
158 }
159}
160
161/* Wait for a (short) while for the FDC to become ready
162 * and transfer the next result byte.
163 * Return -ETIME if timeout on getting ready (depends on hardware!).
164 */
165static int fdc_read(__u8 * data)
166{
167 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
168 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) {
169 return -ETIME;
170 } else {
171 *data = inb(fdc.fifo);
172 return 0;
173 }
174}
175
176/* Output a cmd_len long command string to the FDC.
177 * The FDC should be ready to receive a new command or
178 * an error (EBUSY or ETIME) will occur.
179 */
180int fdc_command(const __u8 * cmd_data, int cmd_len)
181{
182 int result = 0;
183 unsigned long flags;
184 int count = cmd_len;
185 int retry = 0;
186#ifdef TESTING
187 static unsigned int last_time;
188 unsigned int time;
189#endif
190 TRACE_FUN(ft_t_any);
191
192 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
193 spin_lock_irqsave(&fdc_io_lock, flags);
194 if (!in_interrupt())
195 /* Yes, I know, too much comments inside this function
196 * ...
197 *
198 * Yet another bug in the original driver. All that
199 * havoc is caused by the fact that the isr() sends
200 * itself a command to the floppy tape driver (pause,
201 * micro step pause). Now, the problem is that
202 * commands are transmitted via the fdc_seek
203 * command. But: the fdc performs seeks in the
204 * background i.e. it doesn't signal busy while
205 * sending the step pulses to the drive. Therefore the
206 * non-interrupt level driver has no chance to tell
207 * whether the isr() just has issued a seek. Therefore
208 * we HAVE TO have a look at the ft_hide_interrupt
209 * flag: it signals the non-interrupt level part of
210 * the driver that it has to wait for the fdc until it
211 * has completet seeking.
212 *
213 * THIS WAS PRESUMABLY THE REASON FOR ALL THAT
214 * "fdc_read timeout" errors, I HOPE :-)
215 */
216 if (ft_hide_interrupt) {
217 restore_flags(flags);
218 TRACE(ft_t_info,
219 "Waiting for the isr() completing fdc_seek()");
220 if (fdc_interrupt_wait(2 * FT_SECOND) < 0) {
221 TRACE(ft_t_warn,
222 "Warning: timeout waiting for isr() seek to complete");
223 }
224 if (ft_hide_interrupt || !ft_seek_completed) {
225 /* There cannot be another
226 * interrupt. The isr() only stops
227 * the tape and the next interrupt
228 * won't come until we have send our
229 * command to the drive.
230 */
231 TRACE_ABORT(-EIO, ft_t_bug,
232 "BUG? isr() is still seeking?\n"
233 KERN_INFO "hide: %d\n"
234 KERN_INFO "seek: %d",
235 ft_hide_interrupt,
236 ft_seek_completed);
237
238 }
239 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
240 spin_lock_irqsave(&fdc_io_lock, flags);
241 }
242 fdc_status = inb(fdc.msr);
243 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {
244 spin_unlock_irqrestore(&fdc_io_lock, flags);
245 TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");
246 }
247 fdc_mode = *cmd_data; /* used by isr */
248#ifdef TESTING
249 if (fdc_mode == FDC_SEEK) {
250 time = ftape_timediff(last_time, ftape_timestamp());
251 if (time < 6000) {
252 TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d",
253 time);
254 }
255 }
256#endif
257 if (!in_interrupt()) {
258 /* shouldn't be cleared if called from isr
259 */
260 ft_interrupt_seen = 0;
261 }
262 while (count) {
263 result = fdc_write(*cmd_data);
264 if (result < 0) {
265 TRACE(ft_t_fdc_dma,
266 "fdc_mode = %02x, status = %02x at index %d",
267 (int) fdc_mode, (int) fdc_status,
268 cmd_len - count);
269 if (++retry <= 3) {
270 TRACE(ft_t_warn, "fdc_write timeout, retry");
271 } else {
272 TRACE(ft_t_err, "fdc_write timeout, fatal");
273 /* recover ??? */
274 break;
275 }
276 } else {
277 --count;
278 ++cmd_data;
279 }
280 }
281#ifdef TESTING
282 if (fdc_mode == FDC_SEEK) {
283 last_time = ftape_timestamp();
284 }
285#endif
286 spin_unlock_irqrestore(&fdc_io_lock, flags);
287 TRACE_EXIT result;
288}
289
290/* Input a res_len long result string from the FDC.
291 * The FDC should be ready to send the result or an error
292 * (EBUSY or ETIME) will occur.
293 */
294int fdc_result(__u8 * res_data, int res_len)
295{
296 int result = 0;
297 unsigned long flags;
298 int count = res_len;
299 int retry = 0;
300 TRACE_FUN(ft_t_any);
301
302 spin_lock_irqsave(&fdc_io_lock, flags);
303 fdc_status = inb(fdc.msr);
304 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {
305 TRACE(ft_t_err, "fdc not ready");
306 result = -EBUSY;
307 } else while (count) {
308 if (!(fdc_status & FDC_BUSY)) {
309 spin_unlock_irqrestore(&fdc_io_lock, flags);
310 TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");
311 }
312 result = fdc_read(res_data);
313 if (result < 0) {
314 TRACE(ft_t_fdc_dma,
315 "fdc_mode = %02x, status = %02x at index %d",
316 (int) fdc_mode,
317 (int) fdc_status,
318 res_len - count);
319 if (++retry <= 3) {
320 TRACE(ft_t_warn, "fdc_read timeout, retry");
321 } else {
322 TRACE(ft_t_err, "fdc_read timeout, fatal");
323 /* recover ??? */
324 break;
325 ++retry;
326 }
327 } else {
328 --count;
329 ++res_data;
330 }
331 }
332 spin_unlock_irqrestore(&fdc_io_lock, flags);
333 fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */
334 TRACE_EXIT result;
335}
336
337/* Handle command and result phases for
338 * commands without data phase.
339 */
340static int fdc_issue_command(const __u8 * out_data, int out_count,
341 __u8 * in_data, int in_count)
342{
343 TRACE_FUN(ft_t_any);
344
345 if (out_count > 0) {
346 TRACE_CATCH(fdc_command(out_data, out_count),);
347 }
348 /* will take 24 - 30 usec for fdc_sense_drive_status and
349 * fdc_sense_interrupt_status commands.
350 * 35 fails sometimes (5/9/93 SJL)
351 * On a loaded system it incidentally takes longer than
352 * this for the fdc to get ready ! ?????? WHY ??????
353 * So until we know what's going on use a very long timeout.
354 */
355 TRACE_CATCH(fdc_ready_out_wait(500 /* usec */),);
356 if (in_count > 0) {
357 TRACE_CATCH(fdc_result(in_data, in_count),
358 TRACE(ft_t_err, "result phase aborted"));
359 }
360 TRACE_EXIT 0;
361}
362
363/* Wait for FDC interrupt with timeout (in milliseconds).
364 * Signals are blocked so the wait will not be aborted.
365 * Note: interrupts must be enabled ! (23/05/93 SJL)
366 */
367int fdc_interrupt_wait(unsigned int time)
368{
369 DECLARE_WAITQUEUE(wait,current);
370 sigset_t old_sigmask;
371 static int resetting;
372 long timeout;
373
374 TRACE_FUN(ft_t_fdc_dma);
375
376 if (waitqueue_active(&ftape_wait_intr)) {
377 TRACE_ABORT(-EIO, ft_t_err, "error: nested call");
378 }
379 /* timeout time will be up to USPT microseconds too long ! */
380 timeout = (1000 * time + FT_USPT - 1) / FT_USPT;
381
382 spin_lock_irq(&current->sighand->siglock);
383 old_sigmask = current->blocked;
384 sigfillset(&current->blocked);
385 recalc_sigpending();
386 spin_unlock_irq(&current->sighand->siglock);
387
388 set_current_state(TASK_INTERRUPTIBLE);
389 add_wait_queue(&ftape_wait_intr, &wait);
390 while (!ft_interrupt_seen && timeout)
391 timeout = schedule_timeout_interruptible(timeout);
392
393 spin_lock_irq(&current->sighand->siglock);
394 current->blocked = old_sigmask;
395 recalc_sigpending();
396 spin_unlock_irq(&current->sighand->siglock);
397
398 remove_wait_queue(&ftape_wait_intr, &wait);
399 /* the following IS necessary. True: as well
400 * wake_up_interruptible() as the schedule() set TASK_RUNNING
401 * when they wakeup a task, BUT: it may very well be that
402 * ft_interrupt_seen is already set to 1 when we enter here
403 * in which case schedule() gets never called, and
404 * TASK_RUNNING never set. This has the funny effect that we
405 * execute all the code until we leave kernel space, but then
406 * the task is stopped (a task CANNOT be preempted while in
407 * kernel mode. Sending a pair of SIGSTOP/SIGCONT to the
408 * tasks wakes it up again. Funny! :-)
409 */
410 current->state = TASK_RUNNING;
411 if (ft_interrupt_seen) { /* woken up by interrupt */
412 ft_interrupt_seen = 0;
413 TRACE_EXIT 0;
414 }
415 /* Original comment:
416 * In first instance, next statement seems unnecessary since
417 * it will be cleared in fdc_command. However, a small part of
418 * the software seems to rely on this being cleared here
419 * (ftape_close might fail) so stick to it until things get fixed !
420 */
421 /* My deeply sought of knowledge:
422 * Behold NO! It is obvious. fdc_reset() doesn't call fdc_command()
423 * but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to
424 * be reset here.
425 */
426 ft_interrupt_seen = 0; /* clear for next call */
427 if (!resetting) {
428 resetting = 1; /* break infinite recursion if reset fails */
429 TRACE(ft_t_any, "cleanup reset");
430 fdc_reset();
431 resetting = 0;
432 }
433 TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;
434}
435
436/* Start/stop drive motor. Enable DMA mode.
437 */
438void fdc_motor(int motor)
439{
440 int unit = ft_drive_sel;
441 int data = unit | FDC_RESET_NOT | FDC_DMA_MODE;
442 TRACE_FUN(ft_t_any);
443
444 ftape_motor = motor;
445 if (ftape_motor) {
446 data |= FDC_MOTOR_0 << unit;
447 TRACE(ft_t_noise, "turning motor %d on", unit);
448 } else {
449 TRACE(ft_t_noise, "turning motor %d off", unit);
450 }
451 if (ft_mach2) {
452 outb_p(data, fdc.dor2);
453 } else {
454 outb_p(data, fdc.dor);
455 }
456 ftape_sleep(10 * FT_MILLISECOND);
457 TRACE_EXIT;
458}
459
460static void fdc_update_dsr(void)
461{
462 TRACE_FUN(ft_t_any);
463
464 TRACE(ft_t_flow, "rate = %d Kbps, precomp = %d ns",
465 fdc_data_rate, fdc_precomp);
466 if (fdc.type >= i82077) {
467 outb_p((fdc_rate_code & 0x03) | fdc_prec_code, fdc.dsr);
468 } else {
469 outb_p(fdc_rate_code & 0x03, fdc.ccr);
470 }
471 TRACE_EXIT;
472}
473
474void fdc_set_write_precomp(int precomp)
475{
476 TRACE_FUN(ft_t_any);
477
478 TRACE(ft_t_noise, "New precomp: %d nsec", precomp);
479 fdc_precomp = precomp;
480 /* write precompensation can be set in multiples of 41.67 nsec.
481 * round the parameter to the nearest multiple and convert it
482 * into a fdc setting. Note that 0 means default to the fdc,
483 * 7 is used instead of that.
484 */
485 fdc_prec_code = ((fdc_precomp + 21) / 42) << 2;
486 if (fdc_prec_code == 0 || fdc_prec_code > (6 << 2)) {
487 fdc_prec_code = 7 << 2;
488 }
489 fdc_update_dsr();
490 TRACE_EXIT;
491}
492
493/* Reprogram the 82078 registers to use Data Rate Table 1 on all drives.
494 */
495static void fdc_set_drive_specs(void)
496{
497 __u8 cmd[] = { FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};
498 int result;
499 TRACE_FUN(ft_t_any);
500
501 TRACE(ft_t_flow, "Setting of drive specs called");
502 if (fdc.type >= i82078_1) {
503 cmd[1] = (0 << 5) | (2 << 2);
504 cmd[2] = (1 << 5) | (2 << 2);
505 cmd[3] = (2 << 5) | (2 << 2);
506 cmd[4] = (3 << 5) | (2 << 2);
507 result = fdc_command(cmd, NR_ITEMS(cmd));
508 if (result < 0) {
509 TRACE(ft_t_err, "Setting of drive specs failed");
510 }
511 }
512 TRACE_EXIT;
513}
514
515/* Select clock for fdc, must correspond with tape drive setting !
516 * This also influences the fdc timing so we must adjust some values.
517 */
518int fdc_set_data_rate(int rate)
519{
520 int bad_rate = 0;
521 TRACE_FUN(ft_t_any);
522
523 /* Select clock for fdc, must correspond with tape drive setting !
524 * This also influences the fdc timing so we must adjust some values.
525 */
526 TRACE(ft_t_fdc_dma, "new rate = %d", rate);
527 switch (rate) {
528 case 250:
529 fdc_rate_code = fdc_data_rate_250;
530 break;
531 case 500:
532 fdc_rate_code = fdc_data_rate_500;
533 break;
534 case 1000:
535 if (fdc.type < i82077) {
536 bad_rate = 1;
537 } else {
538 fdc_rate_code = fdc_data_rate_1000;
539 }
540 break;
541 case 2000:
542 if (fdc.type < i82078_1) {
543 bad_rate = 1;
544 } else {
545 fdc_rate_code = fdc_data_rate_2000;
546 }
547 break;
548 default:
549 bad_rate = 1;
550 }
551 if (bad_rate) {
552 TRACE_ABORT(-EIO,
553 ft_t_fdc_dma, "%d is not a valid data rate", rate);
554 }
555 fdc_data_rate = rate;
556 fdc_update_dsr();
557 fdc_set_seek_rate(fdc_seek_rate); /* clock changed! */
558 ftape_udelay(1000);
559 TRACE_EXIT 0;
560}
561
562/* keep the unit select if keep_select is != 0,
563 */
564static void fdc_dor_reset(int keep_select)
565{
566 __u8 fdc_ctl = ft_drive_sel;
567
568 if (keep_select != 0) {
569 fdc_ctl |= FDC_DMA_MODE;
570 if (ftape_motor) {
571 fdc_ctl |= FDC_MOTOR_0 << ft_drive_sel;
572 }
573 }
574 ftape_udelay(10); /* ??? but seems to be necessary */
575 if (ft_mach2) {
576 outb_p(fdc_ctl & 0x0f, fdc.dor);
577 outb_p(fdc_ctl, fdc.dor2);
578 } else {
579 outb_p(fdc_ctl, fdc.dor);
580 }
581 fdc_usec_wait(10); /* delay >= 14 fdc clocks */
582 if (keep_select == 0) {
583 fdc_ctl = 0;
584 }
585 fdc_ctl |= FDC_RESET_NOT;
586 if (ft_mach2) {
587 outb_p(fdc_ctl & 0x0f, fdc.dor);
588 outb_p(fdc_ctl, fdc.dor2);
589 } else {
590 outb_p(fdc_ctl, fdc.dor);
591 }
592}
593
594/* Reset the floppy disk controller. Leave the ftape_unit selected.
595 */
596void fdc_reset(void)
597{
598 int st0;
599 int i;
600 int dummy;
601 unsigned long flags;
602 TRACE_FUN(ft_t_any);
603
604 spin_lock_irqsave(&fdc_io_lock, flags);
605
606 fdc_dor_reset(1); /* keep unit selected */
607
608 fdc_mode = fdc_idle;
609
610 /* maybe the spin_lock_irq* pair is not necessary, BUT:
611 * the following line MUST be here. Otherwise fdc_interrupt_wait()
612 * won't wait. Note that fdc_reset() is called from
613 * ftape_dumb_stop() when the fdc is busy transferring data. In this
614 * case fdc_isr() MOST PROBABLY sets ft_interrupt_seen, and tries
615 * to get the result bytes from the fdc etc. CLASH.
616 */
617 ft_interrupt_seen = 0;
618
619 /* Program data rate
620 */
621 fdc_update_dsr(); /* restore data rate and precomp */
622
623 spin_unlock_irqrestore(&fdc_io_lock, flags);
624
625 /*
626 * Wait for first polling cycle to complete
627 */
628 if (fdc_interrupt_wait(1 * FT_SECOND) < 0) {
629 TRACE(ft_t_err, "no drive polling interrupt!");
630 } else { /* clear all disk-changed statuses */
631 for (i = 0; i < 4; ++i) {
632 if(fdc_sense_interrupt_status(&st0, &dummy) != 0) {
633 TRACE(ft_t_err, "sense failed for %d", i);
634 }
635 if (i == ft_drive_sel) {
636 ftape_current_cylinder = dummy;
637 }
638 }
639 TRACE(ft_t_noise, "drive polling completed");
640 }
641 /*
642 * SPECIFY COMMAND
643 */
644 fdc_set_seek_rate(fdc_seek_rate);
645 /*
646 * DRIVE SPECIFICATION COMMAND (if fdc type known)
647 */
648 if (fdc.type >= i82078_1) {
649 fdc_set_drive_specs();
650 }
651 TRACE_EXIT;
652}
653
654#if !defined(CLK_48MHZ)
655# define CLK_48MHZ 1
656#endif
657
658/* When we're done, put the fdc into reset mode so that the regular
659 * floppy disk driver will figure out that something is wrong and
660 * initialize the controller the way it wants.
661 */
662void fdc_disable(void)
663{
664 __u8 cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00};
665 __u8 cmd2[] = {FDC_LOCK};
666 __u8 cmd3[] = {FDC_UNLOCK};
667 __u8 stat[1];
668 TRACE_FUN(ft_t_flow);
669
670 if (!fdc_fifo_locked) {
671 fdc_reset();
672 TRACE_EXIT;
673 }
674 if (fdc_issue_command(cmd3, 1, stat, 1) < 0 || stat[0] != 0x00) {
675 fdc_dor_reset(0);
676 TRACE_ABORT(/**/, ft_t_bug,
677 "couldn't unlock fifo, configuration remains changed");
678 }
679 fdc_fifo_locked = 0;
680 if (CLK_48MHZ && fdc.type >= i82078) {
681 cmd1[0] |= FDC_CLK48_BIT;
682 }
683 cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1);
684 if (fdc_command(cmd1, NR_ITEMS(cmd1)) < 0) {
685 fdc_dor_reset(0);
686 TRACE_ABORT(/**/, ft_t_bug,
687 "couldn't reconfigure fifo to old state");
688 }
689 if (fdc_lock_state &&
690 fdc_issue_command(cmd2, 1, stat, 1) < 0) {
691 fdc_dor_reset(0);
692 TRACE_ABORT(/**/, ft_t_bug, "couldn't lock old state again");
693 }
694 TRACE(ft_t_noise, "fifo restored: %sabled, thr. %d, %slocked",
695 fdc_fifo_state ? "en" : "dis",
696 fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");
697 fdc_dor_reset(0);
698 TRACE_EXIT;
699}
700
701/* Specify FDC seek-rate (milliseconds)
702 */
703static int fdc_set_seek_rate(int seek_rate)
704{
705 /* set step rate, dma mode, and minimal head load and unload times
706 */
707 __u8 in[3] = { FDC_SPECIFY, 1, (1 << 1)};
708
709 fdc_seek_rate = seek_rate;
710 in[1] |= (16 - (fdc_data_rate * fdc_seek_rate) / 500) << 4;
711
712 return fdc_command(in, 3);
713}
714
715/* Sense drive status: get unit's drive status (ST3)
716 */
717int fdc_sense_drive_status(int *st3)
718{
719 __u8 out[2];
720 __u8 in[1];
721 TRACE_FUN(ft_t_any);
722
723 out[0] = FDC_SENSED;
724 out[1] = ft_drive_sel;
725 TRACE_CATCH(fdc_issue_command(out, 2, in, 1),);
726 *st3 = in[0];
727 TRACE_EXIT 0;
728}
729
730/* Sense Interrupt Status command:
731 * should be issued at the end of each seek.
732 * get ST0 and current cylinder.
733 */
734int fdc_sense_interrupt_status(int *st0, int *current_cylinder)
735{
736 __u8 out[1];
737 __u8 in[2];
738 TRACE_FUN(ft_t_any);
739
740 out[0] = FDC_SENSEI;
741 TRACE_CATCH(fdc_issue_command(out, 1, in, 2),);
742 *st0 = in[0];
743 *current_cylinder = in[1];
744 TRACE_EXIT 0;
745}
746
747/* step to track
748 */
749int fdc_seek(int track)
750{
751 __u8 out[3];
752 int st0, pcn;
753#ifdef TESTING
754 unsigned int time;
755#endif
756 TRACE_FUN(ft_t_any);
757
758 out[0] = FDC_SEEK;
759 out[1] = ft_drive_sel;
760 out[2] = track;
761#ifdef TESTING
762 time = ftape_timestamp();
763#endif
764 /* We really need this command to work !
765 */
766 ft_seek_completed = 0;
767 TRACE_CATCH(fdc_command(out, 3),
768 fdc_reset();
769 TRACE(ft_t_noise, "destination was: %d, resetting FDC...",
770 track));
771 /* Handle interrupts until ft_seek_completed or timeout.
772 */
773 for (;;) {
774 TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),);
775 if (ft_seek_completed) {
776 TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),);
777 if ((st0 & ST0_SEEK_END) == 0) {
778 TRACE_ABORT(-EIO, ft_t_err,
779 "no seek-end after seek completion !??");
780 }
781 break;
782 }
783 }
784#ifdef TESTING
785 time = ftape_timediff(time, ftape_timestamp()) / abs(track - ftape_current_cylinder);
786 if ((time < 900 || time > 3100) && abs(track - ftape_current_cylinder) > 5) {
787 TRACE(ft_t_warn, "Wrong FDC STEP interval: %d usecs (%d)",
788 time, track - ftape_current_cylinder);
789 }
790#endif
791 /* Verify whether we issued the right tape command.
792 */
793 /* Verify that we seek to the proper track. */
794 if (pcn != track) {
795 TRACE_ABORT(-EIO, ft_t_err, "bad seek..");
796 }
797 ftape_current_cylinder = track;
798 TRACE_EXIT 0;
799}
800
801static int perpend_mode; /* set if fdc is in perpendicular mode */
802
803static int perpend_off(void)
804{
805 __u8 perpend[] = {FDC_PERPEND, 0x00};
806 TRACE_FUN(ft_t_any);
807
808 if (perpend_mode) {
809 /* Turn off perpendicular mode */
810 perpend[1] = 0x80;
811 TRACE_CATCH(fdc_command(perpend, 2),
812 TRACE(ft_t_err,"Perpendicular mode exit failed!"));
813 perpend_mode = 0;
814 }
815 TRACE_EXIT 0;
816}
817
818static int handle_perpend(int segment_id)
819{
820 __u8 perpend[] = {FDC_PERPEND, 0x00};
821 TRACE_FUN(ft_t_any);
822
823 /* When writing QIC-3020 tapes, turn on perpendicular mode
824 * if tape is moving in forward direction (even tracks).
825 */
826 if (ft_qic_std == QIC_TAPE_QIC3020 &&
827 ((segment_id / ft_segments_per_track) & 1) == 0) {
828/* FIXME: some i82077 seem to support perpendicular mode as
829 * well.
830 */
831#if 0
832 if (fdc.type < i82077AA) {}
833#else
834 if (fdc.type < i82077 && ft_data_rate < 1000) {
835#endif
836 /* fdc does not support perpendicular mode: complain
837 */
838 TRACE_ABORT(-EIO, ft_t_err,
839 "Your FDC does not support QIC-3020.");
840 }
841 perpend[1] = 0x03 /* 0x83 + (0x4 << ft_drive_sel) */ ;
842 TRACE_CATCH(fdc_command(perpend, 2),
843 TRACE(ft_t_err,"Perpendicular mode entry failed!"));
844 TRACE(ft_t_flow, "Perpendicular mode set");
845 perpend_mode = 1;
846 TRACE_EXIT 0;
847 }
848 TRACE_EXIT perpend_off();
849}
850
851static inline void fdc_setup_dma(char mode,
852 volatile void *addr, unsigned int count)
853{
854 /* Program the DMA controller.
855 */
856 disable_dma(fdc.dma);
857 clear_dma_ff(fdc.dma);
858 set_dma_mode(fdc.dma, mode);
859 set_dma_addr(fdc.dma, virt_to_bus((void*)addr));
860 set_dma_count(fdc.dma, count);
861 enable_dma(fdc.dma);
862}
863
864/* Setup fdc and dma for formatting the next segment
865 */
866int fdc_setup_formatting(buffer_struct * buff)
867{
868 unsigned long flags;
869 __u8 out[6] = {
870 FDC_FORMAT, 0x00, 3, 4 * FT_SECTORS_PER_SEGMENT, 0x00, 0x6b
871 };
872 TRACE_FUN(ft_t_any);
873
874 TRACE_CATCH(handle_perpend(buff->segment_id),);
875 /* Program the DMA controller.
876 */
877 TRACE(ft_t_fdc_dma,
878 "phys. addr. = %lx", virt_to_bus((void*) buff->ptr));
879 spin_lock_irqsave(&fdc_io_lock, flags);
880 fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4);
881 /* Issue FDC command to start reading/writing.
882 */
883 out[1] = ft_drive_sel;
884 out[4] = buff->gap3;
885 TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)),
886 restore_flags(flags); fdc_mode = fdc_idle);
887 spin_unlock_irqrestore(&fdc_io_lock, flags);
888 TRACE_EXIT 0;
889}
890
891
892/* Setup Floppy Disk Controller and DMA to read or write the next cluster
893 * of good sectors from or to the current segment.
894 */
895int fdc_setup_read_write(buffer_struct * buff, __u8 operation)
896{
897 unsigned long flags;
898 __u8 out[9];
899 int dma_mode;
900 TRACE_FUN(ft_t_any);
901
902 switch(operation) {
903 case FDC_VERIFY:
904 if (fdc.type < i82077) {
905 operation = FDC_READ;
906 }
907 case FDC_READ:
908 case FDC_READ_DELETED:
909 dma_mode = DMA_MODE_READ;
910 TRACE(ft_t_fdc_dma, "xfer %d sectors to 0x%p",
911 buff->sector_count, buff->ptr);
912 TRACE_CATCH(perpend_off(),);
913 break;
914 case FDC_WRITE_DELETED:
915 TRACE(ft_t_noise, "deleting segment %d", buff->segment_id);
916 case FDC_WRITE:
917 dma_mode = DMA_MODE_WRITE;
918 /* When writing QIC-3020 tapes, turn on perpendicular mode
919 * if tape is moving in forward direction (even tracks).
920 */
921 TRACE_CATCH(handle_perpend(buff->segment_id),);
922 TRACE(ft_t_fdc_dma, "xfer %d sectors from 0x%p",
923 buff->sector_count, buff->ptr);
924 break;
925 default:
926 TRACE_ABORT(-EIO,
927 ft_t_bug, "bug: invalid operation parameter");
928 }
929 TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr));
930 spin_lock_irqsave(&fdc_io_lock, flags);
931 if (operation != FDC_VERIFY) {
932 fdc_setup_dma(dma_mode, buff->ptr,
933 FT_SECTOR_SIZE * buff->sector_count);
934 }
935 /* Issue FDC command to start reading/writing.
936 */
937 out[0] = operation;
938 out[1] = ft_drive_sel;
939 out[2] = buff->cyl;
940 out[3] = buff->head;
941 out[4] = buff->sect + buff->sector_offset;
942 out[5] = 3; /* Sector size of 1K. */
943 out[6] = out[4] + buff->sector_count - 1; /* last sector */
944 out[7] = 109; /* Gap length. */
945 out[8] = 0xff; /* No limit to transfer size. */
946 TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",
947 out[2], out[3], out[4], out[6] - out[4] + 1);
948 spin_unlock_irqrestore(&fdc_io_lock, flags);
949 TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle);
950 TRACE_EXIT 0;
951}
952
953int fdc_fifo_threshold(__u8 threshold,
954 int *fifo_state, int *lock_state, int *fifo_thr)
955{
956 const __u8 cmd0[] = {FDC_DUMPREGS};
957 __u8 cmd1[] = {FDC_CONFIGURE, 0, (0x0f & (threshold - 1)), 0};
958 const __u8 cmd2[] = {FDC_LOCK};
959 const __u8 cmd3[] = {FDC_UNLOCK};
960 __u8 reg[10];
961 __u8 stat;
962 int i;
963 int result;
964 TRACE_FUN(ft_t_any);
965
966 if (CLK_48MHZ && fdc.type >= i82078) {
967 cmd1[0] |= FDC_CLK48_BIT;
968 }
969 /* Dump fdc internal registers for examination
970 */
971 TRACE_CATCH(fdc_command(cmd0, NR_ITEMS(cmd0)),
972 TRACE(ft_t_warn, "dumpreg cmd failed, fifo unchanged"));
973 /* Now read fdc internal registers from fifo
974 */
975 for (i = 0; i < (int)NR_ITEMS(reg); ++i) {
976 fdc_read(&reg[i]);
977 TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]);
978 }
979 if (fifo_state && lock_state && fifo_thr) {
980 *fifo_state = (reg[8] & 0x20) == 0;
981 *lock_state = reg[7] & 0x80;
982 *fifo_thr = 1 + (reg[8] & 0x0f);
983 }
984 TRACE(ft_t_noise,
985 "original fifo state: %sabled, threshold %d, %slocked",
986 ((reg[8] & 0x20) == 0) ? "en" : "dis",
987 1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not ");
988 /* If fdc is already locked, unlock it first ! */
989 if (reg[7] & 0x80) {
990 fdc_ready_wait(100);
991 TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1),
992 TRACE(ft_t_bug, "FDC unlock command failed, "
993 "configuration unchanged"));
994 }
995 fdc_fifo_locked = 0;
996 /* Enable fifo and set threshold at xx bytes to allow a
997 * reasonably large latency and reduce number of dma bursts.
998 */
999 fdc_ready_wait(100);
1000 if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) {
1001 TRACE(ft_t_bug, "configure cmd failed, fifo unchanged");
1002 }
1003 /* Now lock configuration so reset will not change it
1004 */
1005 if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 ||
1006 stat != 0x10) {
1007 TRACE_ABORT(-EIO, ft_t_bug,
1008 "FDC lock command failed, stat = 0x%02x", stat);
1009 }
1010 fdc_fifo_locked = 1;
1011 TRACE_EXIT result;
1012}
1013
1014static int fdc_fifo_enable(void)
1015{
1016 TRACE_FUN(ft_t_any);
1017
1018 if (fdc_fifo_locked) {
1019 TRACE_ABORT(0, ft_t_warn, "Fifo not enabled because locked");
1020 }
1021 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1022 &fdc_fifo_state,
1023 &fdc_lock_state,
1024 &fdc_fifo_thr),);
1025 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1026 NULL, NULL, NULL),);
1027 TRACE_EXIT 0;
1028}
1029
1030/* Determine fd controller type
1031 */
1032static __u8 fdc_save_state[2];
1033
1034static int fdc_probe(void)
1035{
1036 __u8 cmd[1];
1037 __u8 stat[16]; /* must be able to hold dumpregs & save results */
1038 int i;
1039 TRACE_FUN(ft_t_any);
1040
1041 /* Try to find out what kind of fd controller we have to deal with
1042 * Scheme borrowed from floppy driver:
1043 * first try if FDC_DUMPREGS command works
1044 * (this indicates that we have a 82072 or better)
1045 * then try the FDC_VERSION command (82072 doesn't support this)
1046 * then try the FDC_UNLOCK command (some older 82077's don't support this)
1047 * then try the FDC_PARTID command (82078's support this)
1048 */
1049 cmd[0] = FDC_DUMPREGS;
1050 if (fdc_issue_command(cmd, 1, stat, 1) != 0) {
1051 TRACE_ABORT(no_fdc, ft_t_bug, "No FDC found");
1052 }
1053 if (stat[0] == 0x80) {
1054 /* invalid command: must be pre 82072 */
1055 TRACE_ABORT(i8272,
1056 ft_t_warn, "Type 8272A/765A compatible FDC found");
1057 }
1058 fdc_result(&stat[1], 9);
1059 fdc_save_state[0] = stat[7];
1060 fdc_save_state[1] = stat[8];
1061 cmd[0] = FDC_VERSION;
1062 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1063 TRACE_ABORT(i8272, ft_t_warn, "Type 82072 FDC found");
1064 }
1065 if (*stat != 0x90) {
1066 TRACE_ABORT(i8272, ft_t_warn, "Unknown FDC found");
1067 }
1068 cmd[0] = FDC_UNLOCK;
1069 if(fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] != 0x00) {
1070 TRACE_ABORT(i8272, ft_t_warn,
1071 "Type pre-1991 82077 FDC found, "
1072 "treating it like a 82072");
1073 }
1074 if (fdc_save_state[0] & 0x80) { /* was locked */
1075 cmd[0] = FDC_LOCK; /* restore lock */
1076 (void)fdc_issue_command(cmd, 1, stat, 1);
1077 TRACE(ft_t_warn, "FDC is already locked");
1078 }
1079 /* Test for a i82078 FDC */
1080 cmd[0] = FDC_PARTID;
1081 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1082 /* invalid command: not a i82078xx type FDC */
1083 for (i = 0; i < 4; ++i) {
1084 outb_p(i, fdc.tdr);
1085 if ((inb_p(fdc.tdr) & 0x03) != i) {
1086 TRACE_ABORT(i82077,
1087 ft_t_warn, "Type 82077 FDC found");
1088 }
1089 }
1090 TRACE_ABORT(i82077AA, ft_t_warn, "Type 82077AA FDC found");
1091 }
1092 /* FDC_PARTID cmd succeeded */
1093 switch (stat[0] >> 5) {
1094 case 0x0:
1095 /* i82078SL or i82078-1. The SL part cannot run at
1096 * 2Mbps (the SL and -1 dies are identical; they are
1097 * speed graded after production, according to Intel).
1098 * Some SL's can be detected by doing a SAVE cmd and
1099 * look at bit 7 of the first byte (the SEL3V# bit).
1100 * If it is 0, the part runs off 3Volts, and hence it
1101 * is a SL.
1102 */
1103 cmd[0] = FDC_SAVE;
1104 if(fdc_issue_command(cmd, 1, stat, 16) < 0) {
1105 TRACE(ft_t_err, "FDC_SAVE failed. Dunno why");
1106 /* guess we better claim the fdc to be a i82078 */
1107 TRACE_ABORT(i82078,
1108 ft_t_warn,
1109 "Type i82078 FDC (i suppose) found");
1110 }
1111 if ((stat[0] & FDC_SEL3V_BIT)) {
1112 /* fdc running off 5Volts; Pray that it's a i82078-1
1113 */
1114 TRACE_ABORT(i82078_1, ft_t_warn,
1115 "Type i82078-1 or 5Volt i82078SL FDC found");
1116 }
1117 TRACE_ABORT(i82078, ft_t_warn,
1118 "Type 3Volt i82078SL FDC (1Mbps) found");
1119 case 0x1:
1120 case 0x2: /* S82078B */
1121 /* The '78B isn't '78 compatible. Detect it as a '77AA */
1122 TRACE_ABORT(i82077AA, ft_t_warn, "Type i82077AA FDC found");
1123 case 0x3: /* NSC PC8744 core; used in several super-IO chips */
1124 TRACE_ABORT(i82077AA,
1125 ft_t_warn, "Type 82077AA compatible FDC found");
1126 default:
1127 TRACE(ft_t_warn, "A previously undetected FDC found");
1128 TRACE_ABORT(i82077AA, ft_t_warn,
1129 "Treating it as a 82077AA. Please report partid= %d",
1130 stat[0]);
1131 } /* switch(stat[ 0] >> 5) */
1132 TRACE_EXIT no_fdc;
1133}
1134
1135static int fdc_request_regions(void)
1136{
1137 TRACE_FUN(ft_t_flow);
1138
1139 if (ft_mach2 || ft_probe_fc10) {
1140 if (!request_region(fdc.sra, 8, "fdc (ft)")) {
1141#ifndef BROKEN_FLOPPY_DRIVER
1142 TRACE_EXIT -EBUSY;
1143#else
1144 TRACE(ft_t_warn,
1145"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1146#endif
1147 }
1148 } else {
1149 if (!request_region(fdc.sra, 6, "fdc (ft)")) {
1150#ifndef BROKEN_FLOPPY_DRIVER
1151 TRACE_EXIT -EBUSY;
1152#else
1153 TRACE(ft_t_warn,
1154"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1155#endif
1156 }
1157 if (!request_region(fdc.sra + 7, 1, "fdc (ft)")) {
1158#ifndef BROKEN_FLOPPY_DRIVER
1159 release_region(fdc.sra, 6);
1160 TRACE_EXIT -EBUSY;
1161#else
1162 TRACE(ft_t_warn,
1163"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra + 7);
1164#endif
1165 }
1166 }
1167 TRACE_EXIT 0;
1168}
1169
1170void fdc_release_regions(void)
1171{
1172 TRACE_FUN(ft_t_flow);
1173
1174 if (fdc.sra != 0) {
1175 if (fdc.dor2 != 0) {
1176 release_region(fdc.sra, 8);
1177 } else {
1178 release_region(fdc.sra, 6);
1179 release_region(fdc.dir, 1);
1180 }
1181 }
1182 TRACE_EXIT;
1183}
1184
1185static int fdc_config_regs(unsigned int fdc_base,
1186 unsigned int fdc_irq,
1187 unsigned int fdc_dma)
1188{
1189 TRACE_FUN(ft_t_flow);
1190
1191 fdc.irq = fdc_irq;
1192 fdc.dma = fdc_dma;
1193 fdc.sra = fdc_base;
1194 fdc.srb = fdc_base + 1;
1195 fdc.dor = fdc_base + 2;
1196 fdc.tdr = fdc_base + 3;
1197 fdc.msr = fdc.dsr = fdc_base + 4;
1198 fdc.fifo = fdc_base + 5;
1199 fdc.dir = fdc.ccr = fdc_base + 7;
1200 fdc.dor2 = (ft_mach2 || ft_probe_fc10) ? fdc_base + 6 : 0;
1201 TRACE_CATCH(fdc_request_regions(), fdc.sra = 0);
1202 TRACE_EXIT 0;
1203}
1204
1205static int fdc_config(void)
1206{
1207 static int already_done;
1208 TRACE_FUN(ft_t_any);
1209
1210 if (already_done) {
1211 TRACE_CATCH(fdc_request_regions(),);
1212 *(fdc.hook) = fdc_isr; /* hook our handler in */
1213 TRACE_EXIT 0;
1214 }
1215 if (ft_probe_fc10) {
1216 int fc_type;
1217
1218 TRACE_CATCH(fdc_config_regs(ft_fdc_base,
1219 ft_fdc_irq, ft_fdc_dma),);
1220 fc_type = fc10_enable();
1221 if (fc_type != 0) {
1222 TRACE(ft_t_warn, "FC-%c0 controller found", '0' + fc_type);
1223 fdc.type = fc10;
1224 fdc.hook = &do_ftape;
1225 *(fdc.hook) = fdc_isr; /* hook our handler in */
1226 already_done = 1;
1227 TRACE_EXIT 0;
1228 } else {
1229 TRACE(ft_t_warn, "FC-10/20 controller not found");
1230 fdc_release_regions();
1231 fdc.type = no_fdc;
1232 ft_probe_fc10 = 0;
1233 ft_fdc_base = 0x3f0;
1234 ft_fdc_irq = 6;
1235 ft_fdc_dma = 2;
1236 }
1237 }
1238 TRACE(ft_t_warn, "fdc base: 0x%x, irq: %d, dma: %d",
1239 ft_fdc_base, ft_fdc_irq, ft_fdc_dma);
1240 TRACE_CATCH(fdc_config_regs(ft_fdc_base, ft_fdc_irq, ft_fdc_dma),);
1241 fdc.hook = &do_ftape;
1242 *(fdc.hook) = fdc_isr; /* hook our handler in */
1243 already_done = 1;
1244 TRACE_EXIT 0;
1245}
1246
1247static irqreturn_t ftape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1248{
1249 void (*handler) (void) = *fdc.hook;
1250 int handled = 0;
1251 TRACE_FUN(ft_t_any);
1252
1253 *fdc.hook = NULL;
1254 if (handler) {
1255 handled = 1;
1256 handler();
1257 } else {
1258 TRACE(ft_t_bug, "Unexpected ftape interrupt");
1259 }
1260 TRACE_EXIT IRQ_RETVAL(handled);
1261}
1262
1263static int fdc_grab_irq_and_dma(void)
1264{
1265 TRACE_FUN(ft_t_any);
1266
1267 if (fdc.hook == &do_ftape) {
1268 /* Get fast interrupt handler.
1269 */
1270 if (request_irq(fdc.irq, ftape_interrupt,
1271 IRQF_DISABLED, "ft", ftape_id)) {
1272 TRACE_ABORT(-EIO, ft_t_bug,
1273 "Unable to grab IRQ%d for ftape driver",
1274 fdc.irq);
1275 }
1276 if (request_dma(fdc.dma, ftape_id)) {
1277 free_irq(fdc.irq, ftape_id);
1278 TRACE_ABORT(-EIO, ft_t_bug,
1279 "Unable to grab DMA%d for ftape driver",
1280 fdc.dma);
1281 }
1282 }
1283 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1284 /* Using same dma channel or irq as standard fdc, need
1285 * to disable the dma-gate on the std fdc. This
1286 * couldn't be done in the floppy driver as some
1287 * laptops are using the dma-gate to enter a low power
1288 * or even suspended state :-(
1289 */
1290 outb_p(FDC_RESET_NOT, 0x3f2);
1291 TRACE(ft_t_noise, "DMA-gate on standard fdc disabled");
1292 }
1293 TRACE_EXIT 0;
1294}
1295
1296int fdc_release_irq_and_dma(void)
1297{
1298 TRACE_FUN(ft_t_any);
1299
1300 if (fdc.hook == &do_ftape) {
1301 disable_dma(fdc.dma); /* just in case... */
1302 free_dma(fdc.dma);
1303 free_irq(fdc.irq, ftape_id);
1304 }
1305 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1306 /* Using same dma channel as standard fdc, need to
1307 * disable the dma-gate on the std fdc. This couldn't
1308 * be done in the floppy driver as some laptops are
1309 * using the dma-gate to enter a low power or even
1310 * suspended state :-(
1311 */
1312 outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);
1313 TRACE(ft_t_noise, "DMA-gate on standard fdc enabled again");
1314 }
1315 TRACE_EXIT 0;
1316}
1317
1318int fdc_init(void)
1319{
1320 TRACE_FUN(ft_t_any);
1321
1322 /* find a FDC to use */
1323 TRACE_CATCH(fdc_config(),);
1324 TRACE_CATCH(fdc_grab_irq_and_dma(), fdc_release_regions());
1325 ftape_motor = 0;
1326 fdc_catch_stray_interrupts(0); /* clear number of awainted
1327 * stray interrupte
1328 */
1329 fdc_catch_stray_interrupts(1); /* one always comes (?) */
1330 TRACE(ft_t_flow, "resetting fdc");
1331 fdc_set_seek_rate(2); /* use nominal QIC step rate */
1332 fdc_reset(); /* init fdc & clear track counters */
1333 if (fdc.type == no_fdc) { /* no FC-10 or FC-20 found */
1334 fdc.type = fdc_probe();
1335 fdc_reset(); /* update with new knowledge */
1336 }
1337 if (fdc.type == no_fdc) {
1338 fdc_release_irq_and_dma();
1339 fdc_release_regions();
1340 TRACE_EXIT -ENXIO;
1341 }
1342 if (fdc.type >= i82077) {
1343 if (fdc_fifo_enable() < 0) {
1344 TRACE(ft_t_warn, "couldn't enable fdc fifo !");
1345 } else {
1346 TRACE(ft_t_flow, "fdc fifo enabled and locked");
1347 }
1348 }
1349 TRACE_EXIT 0;
1350}