Import 2.1.81
[davej-history.git] / drivers / char / ftape / lowlevel / fdc-io.c
blobfd1ac0cd7135e9a661a17bfaa900645d53a9e462
1 /*
2 * Copyright (C) 1993-1996 Bas Laarhoven,
3 * (C) 1996-1997 Claus-Justus Heine.
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.
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.
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.
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 $
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.
29 #include <linux/errno.h>
30 #include <linux/sched.h>
31 #include <linux/ioport.h>
32 #include <linux/version.h>
33 #include <linux/interrupt.h>
34 #include <asm/system.h>
35 #include <asm/io.h>
36 #include <asm/dma.h>
37 #include <asm/irq.h>
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"
50 /* Global vars.
52 int ftape_motor = 0;
53 volatile int ftape_current_cylinder = -1;
54 volatile fdc_mode_enum fdc_mode = fdc_idle;
55 fdc_config_info fdc = {0};
56 struct wait_queue *ftape_wait_intr = NULL;
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;
66 /* Local vars.
68 static unsigned int fdc_calibr_count;
69 static unsigned int fdc_calibr_time;
70 static int fdc_status;
71 volatile __u8 fdc_head; /* FDC head from sector id */
72 volatile __u8 fdc_cyl; /* FDC track from sector id */
73 volatile __u8 fdc_sect; /* FDC sector from sector id */
74 static int fdc_data_rate = 500; /* data rate (Kbps) */
75 static int fdc_rate_code = 0; /* data rate code (0 == 500 Kbps) */
76 static int fdc_seek_rate = 2; /* step rate (msec) */
77 static void (*do_ftape) (void);
78 static int fdc_fifo_state; /* original fifo setting - fifo enabled */
79 static int fdc_fifo_thr; /* original fifo setting - threshold */
80 static int fdc_lock_state; /* original lock setting - locked */
81 static int fdc_fifo_locked = 0; /* has fifo && lock set ? */
82 static __u8 fdc_precomp = 0; /* default precomp. value (nsec) */
83 static __u8 fdc_prec_code = 0; /* fdc precomp. select code */
85 static char ftape_id[] = "ftape"; /* used by request irq and free irq */
87 void fdc_catch_stray_interrupts(int count)
89 unsigned long flags;
91 save_flags(flags);
92 cli();
93 if (count == 0) {
94 ft_expected_stray_interrupts = 0;
95 } else {
96 ft_expected_stray_interrupts += count;
98 restore_flags(flags);
101 /* Wait during a timeout period for a given FDC status.
102 * If usecs == 0 then just test status, else wait at least for usecs.
103 * Returns -ETIME on timeout. Function must be calibrated first !
105 int fdc_wait(unsigned int usecs, __u8 mask, __u8 state)
107 int count_1 = (fdc_calibr_count * usecs +
108 fdc_calibr_count - 1) / fdc_calibr_time;
110 do {
111 fdc_status = inb_p(fdc.msr);
112 if ((fdc_status & mask) == state) {
113 return 0;
115 } while (count_1-- >= 0);
116 return -ETIME;
119 int fdc_ready_wait(unsigned int usecs)
121 return fdc_wait(usecs, FDC_DATA_READY | FDC_BUSY, FDC_DATA_READY);
124 /* Why can't we just use udelay()?
126 static void fdc_usec_wait(unsigned int usecs)
128 fdc_wait(usecs, 0, 1); /* will always timeout ! */
131 int fdc_ready_out_wait(unsigned int usecs)
133 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
134 return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);
137 int fdc_ready_in_wait(unsigned int usecs)
139 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
140 return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_IN_READY);
143 void fdc_wait_calibrate(void)
145 ftape_calibrate("fdc_wait",
146 fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time);
149 /* Wait for a (short) while for the FDC to become ready
150 * and transfer the next command byte.
151 * Return -ETIME on timeout on getting ready (depends on hardware!).
153 static int fdc_write(const __u8 data)
155 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
156 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) {
157 return -ETIME;
158 } else {
159 outb(data, fdc.fifo);
160 return 0;
164 /* Wait for a (short) while for the FDC to become ready
165 * and transfer the next result byte.
166 * Return -ETIME if timeout on getting ready (depends on hardware!).
168 static int fdc_read(__u8 * data)
170 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
171 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) {
172 return -ETIME;
173 } else {
174 *data = inb(fdc.fifo);
175 return 0;
179 /* Output a cmd_len long command string to the FDC.
180 * The FDC should be ready to receive a new command or
181 * an error (EBUSY or ETIME) will occur.
183 int fdc_command(const __u8 * cmd_data, int cmd_len)
185 int result = 0;
186 unsigned long flags;
187 int count = cmd_len;
188 int retry = 0;
189 #ifdef TESTING
190 static unsigned int last_time = 0;
191 unsigned int time;
192 #endif
193 TRACE_FUN(ft_t_any);
195 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
196 save_flags(flags);
197 cli();
198 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,30)
199 if (!in_interrupt())
200 #else
201 if (!intr_count)
202 #endif
203 /* Yes, I know, too much comments inside this function
204 * ...
206 * Yet another bug in the original driver. All that
207 * havoc is caused by the fact that the isr() sends
208 * itself a command to the floppy tape driver (pause,
209 * micro step pause). Now, the problem is that
210 * commands are transmitted via the fdc_seek
211 * command. But: the fdc performs seeks in the
212 * background i.e. it doesn't signal busy while
213 * sending the step pulses to the drive. Therefore the
214 * non-interrupt level driver has no chance to tell
215 * whether the isr() just has issued a seek. Therefore
216 * we HAVE TO have a look at the the ft_hide_interrupt
217 * flag: it signals the non-interrupt level part of
218 * the driver that it has to wait for the fdc until it
219 * has completet seeking.
221 * THIS WAS PRESUMABLY THE REASON FOR ALL THAT
222 * "fdc_read timeout" errors, I HOPE :-)
224 if (ft_hide_interrupt) {
225 restore_flags(flags);
226 TRACE(ft_t_info,
227 "Waiting for the isr() completing fdc_seek()");
228 if (fdc_interrupt_wait(2 * FT_SECOND) < 0) {
229 TRACE(ft_t_warn,
230 "Warning: timeout waiting for isr() seek to complete");
232 if (ft_hide_interrupt || !ft_seek_completed) {
233 /* There cannot be another
234 * interrupt. The isr() only stops
235 * the tape and the next interrupt
236 * won't come until we have send our
237 * command to the drive.
239 TRACE_ABORT(-EIO, ft_t_bug,
240 "BUG? isr() is still seeking?\n"
241 KERN_INFO "hide: %d\n"
242 KERN_INFO "seek: %d",
243 ft_hide_interrupt,
244 ft_seek_completed);
247 fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */
248 save_flags(flags);
249 cli();
251 fdc_status = inb(fdc.msr);
252 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {
253 restore_flags(flags);
254 TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");
256 fdc_mode = *cmd_data; /* used by isr */
257 #ifdef TESTING
258 if (fdc_mode == FDC_SEEK) {
259 time = ftape_timediff(last_time, ftape_timestamp());
260 if (time < 6000) {
261 TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d",
262 time);
265 #endif
266 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,30)
267 if (!in_interrupt()) {
268 /* shouldn't be cleared if called from isr
270 ft_interrupt_seen = 0;
272 #else
273 if (!intr_count) {
274 /* shouldn't be cleared if called from isr
276 ft_interrupt_seen = 0;
278 #endif
279 while (count) {
280 result = fdc_write(*cmd_data);
281 if (result < 0) {
282 TRACE(ft_t_fdc_dma,
283 "fdc_mode = %02x, status = %02x at index %d",
284 (int) fdc_mode, (int) fdc_status,
285 cmd_len - count);
286 if (++retry <= 3) {
287 TRACE(ft_t_warn, "fdc_write timeout, retry");
288 } else {
289 TRACE(ft_t_err, "fdc_write timeout, fatal");
290 /* recover ??? */
291 break;
293 } else {
294 --count;
295 ++cmd_data;
298 #ifdef TESTING
299 if (fdc_mode == FDC_SEEK) {
300 last_time = ftape_timestamp();
302 #endif
303 restore_flags(flags);
304 TRACE_EXIT result;
307 /* Input a res_len long result string from the FDC.
308 * The FDC should be ready to send the result or an error
309 * (EBUSY or ETIME) will occur.
311 int fdc_result(__u8 * res_data, int res_len)
313 int result = 0;
314 unsigned long flags;
315 int count = res_len;
316 int retry = 0;
317 TRACE_FUN(ft_t_any);
319 save_flags(flags);
320 cli();
321 fdc_status = inb(fdc.msr);
322 if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {
323 TRACE(ft_t_err, "fdc not ready");
324 result = -EBUSY;
325 } else while (count) {
326 if (!(fdc_status & FDC_BUSY)) {
327 restore_flags(flags);
328 TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");
330 result = fdc_read(res_data);
331 if (result < 0) {
332 TRACE(ft_t_fdc_dma,
333 "fdc_mode = %02x, status = %02x at index %d",
334 (int) fdc_mode,
335 (int) fdc_status,
336 res_len - count);
337 if (++retry <= 3) {
338 TRACE(ft_t_warn, "fdc_read timeout, retry");
339 } else {
340 TRACE(ft_t_err, "fdc_read timeout, fatal");
341 /* recover ??? */
342 break;
343 ++retry;
345 } else {
346 --count;
347 ++res_data;
350 restore_flags(flags);
351 fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */
352 TRACE_EXIT result;
355 /* Handle command and result phases for
356 * commands without data phase.
358 int fdc_issue_command(const __u8 * out_data, int out_count,
359 __u8 * in_data, int in_count)
361 TRACE_FUN(ft_t_any);
363 if (out_count > 0) {
364 TRACE_CATCH(fdc_command(out_data, out_count),);
366 /* will take 24 - 30 usec for fdc_sense_drive_status and
367 * fdc_sense_interrupt_status commands.
368 * 35 fails sometimes (5/9/93 SJL)
369 * On a loaded system it incidentally takes longer than
370 * this for the fdc to get ready ! ?????? WHY ??????
371 * So until we know what's going on use a very long timeout.
373 TRACE_CATCH(fdc_ready_out_wait(500 /* usec */),);
374 if (in_count > 0) {
375 TRACE_CATCH(fdc_result(in_data, in_count),
376 TRACE(ft_t_err, "result phase aborted"));
378 TRACE_EXIT 0;
381 /* Wait for FDC interrupt with timeout (in milliseconds).
382 * Signals are blocked so the wait will not be aborted.
383 * Note: interrupts must be enabled ! (23/05/93 SJL)
385 int fdc_interrupt_wait(unsigned int time)
387 struct wait_queue wait = {current, NULL};
388 sigset_t old_sigmask;
389 static int resetting = 0;
390 TRACE_FUN(ft_t_fdc_dma);
392 #if LINUX_VERSION_CODE >= KERNEL_VER(2,0,16)
393 if (waitqueue_active(&ftape_wait_intr)) {
394 TRACE_ABORT(-EIO, ft_t_err, "error: nested call");
396 #else
397 if (ftape_wait_intr) {
398 TRACE_ABORT(-EIO, ft_t_err, "error: nested call");
400 #endif
401 /* timeout time will be up to USPT microseconds too long ! */
402 current->timeout = jiffies + (1000 * time + FT_USPT - 1) / FT_USPT;
403 current->state = TASK_INTERRUPTIBLE;
405 spin_lock_irq(&current->sigmask_lock);
406 old_sigmask = current->blocked;
407 siginitset(&current->blocked, _BLOCK_ALL);
408 recalc_sigpending(current);
409 spin_unlock_irq(&current->sigmask_lock);
411 add_wait_queue(&ftape_wait_intr, &wait);
412 while (!ft_interrupt_seen && current->state != TASK_RUNNING) {
413 schedule(); /* sets TASK_RUNNING on timeout */
416 spin_lock_irq(&current->sigmask_lock);
417 current->blocked = old_sigmask;
418 recalc_sigpending(current);
419 spin_unlock_irq(&current->sigmask_lock);
421 remove_wait_queue(&ftape_wait_intr, &wait);
422 /* the following IS necessary. True: as well
423 * wake_up_interruptible() as the schedule() set TASK_RUNNING
424 * when they wakeup a task, BUT: it may very well be that
425 * ft_interrupt_seen is already set to 1 when we enter here
426 * in which case schedule() gets never called, and
427 * TASK_RUNNING never set. This has the funny effect that we
428 * execute all the code until we leave kernel space, but then
429 * the task is stopped (a task CANNOT be preempted while in
430 * kernel mode. Sending a pair of SIGSTOP/SIGCONT to the
431 * tasks wakes it up again. Funny! :-)
433 current->state = TASK_RUNNING;
434 if (ft_interrupt_seen) { /* woken up by interrupt */
435 current->timeout = 0; /* interrupt hasn't cleared this */
436 ft_interrupt_seen = 0;
437 TRACE_EXIT 0;
439 /* Original comment:
440 * In first instance, next statement seems unnecessary since
441 * it will be cleared in fdc_command. However, a small part of
442 * the software seems to rely on this being cleared here
443 * (ftape_close might fail) so stick to it until things get fixed !
445 /* My deeply sought of knowledge:
446 * Behold NO! It is obvious. fdc_reset() doesn't call fdc_command()
447 * but nevertheless uses fdc_interrupt_wait(). OF COURSE this needs to
448 * be reset here.
450 ft_interrupt_seen = 0; /* clear for next call */
451 if (!resetting) {
452 resetting = 1; /* break infinite recursion if reset fails */
453 TRACE(ft_t_any, "cleanup reset");
454 fdc_reset();
455 resetting = 0;
457 TRACE_EXIT (signal_pending(current)) ? -EINTR : -ETIME;
460 /* Start/stop drive motor. Enable DMA mode.
462 void fdc_motor(int motor)
464 int unit = ft_drive_sel;
465 int data = unit | FDC_RESET_NOT | FDC_DMA_MODE;
466 TRACE_FUN(ft_t_any);
468 ftape_motor = motor;
469 if (ftape_motor) {
470 data |= FDC_MOTOR_0 << unit;
471 TRACE(ft_t_noise, "turning motor %d on", unit);
472 } else {
473 TRACE(ft_t_noise, "turning motor %d off", unit);
475 if (ft_mach2) {
476 outb_p(data, fdc.dor2);
477 } else {
478 outb_p(data, fdc.dor);
480 ftape_sleep(10 * FT_MILLISECOND);
481 TRACE_EXIT;
484 static void fdc_update_dsr(void)
486 TRACE_FUN(ft_t_any);
488 TRACE(ft_t_flow, "rate = %d Kbps, precomp = %d ns",
489 fdc_data_rate, fdc_precomp);
490 if (fdc.type >= i82077) {
491 outb_p((fdc_rate_code & 0x03) | fdc_prec_code, fdc.dsr);
492 } else {
493 outb_p(fdc_rate_code & 0x03, fdc.ccr);
495 TRACE_EXIT;
498 void fdc_set_write_precomp(int precomp)
500 TRACE_FUN(ft_t_any);
502 TRACE(ft_t_noise, "New precomp: %d nsec", precomp);
503 fdc_precomp = precomp;
504 /* write precompensation can be set in multiples of 41.67 nsec.
505 * round the parameter to the nearest multiple and convert it
506 * into a fdc setting. Note that 0 means default to the fdc,
507 * 7 is used instead of that.
509 fdc_prec_code = ((fdc_precomp + 21) / 42) << 2;
510 if (fdc_prec_code == 0 || fdc_prec_code > (6 << 2)) {
511 fdc_prec_code = 7 << 2;
513 fdc_update_dsr();
514 TRACE_EXIT;
517 /* Reprogram the 82078 registers to use Data Rate Table 1 on all drives.
519 void fdc_set_drive_specs(void)
521 __u8 cmd[] = { FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};
522 int result;
523 TRACE_FUN(ft_t_any);
525 TRACE(ft_t_flow, "Setting of drive specs called");
526 if (fdc.type >= i82078_1) {
527 cmd[1] = (0 << 5) | (2 << 2);
528 cmd[2] = (1 << 5) | (2 << 2);
529 cmd[3] = (2 << 5) | (2 << 2);
530 cmd[4] = (3 << 5) | (2 << 2);
531 result = fdc_command(cmd, NR_ITEMS(cmd));
532 if (result < 0) {
533 TRACE(ft_t_err, "Setting of drive specs failed");
536 TRACE_EXIT;
539 /* Select clock for fdc, must correspond with tape drive setting !
540 * This also influences the fdc timing so we must adjust some values.
542 int fdc_set_data_rate(int rate)
544 int bad_rate = 0;
545 TRACE_FUN(ft_t_any);
547 /* Select clock for fdc, must correspond with tape drive setting !
548 * This also influences the fdc timing so we must adjust some values.
550 TRACE(ft_t_fdc_dma, "new rate = %d", rate);
551 switch (rate) {
552 case 250:
553 fdc_rate_code = fdc_data_rate_250;
554 break;
555 case 500:
556 fdc_rate_code = fdc_data_rate_500;
557 break;
558 case 1000:
559 if (fdc.type < i82077) {
560 bad_rate = 1;
561 } else {
562 fdc_rate_code = fdc_data_rate_1000;
564 break;
565 case 2000:
566 if (fdc.type < i82078_1) {
567 bad_rate = 1;
568 } else {
569 fdc_rate_code = fdc_data_rate_2000;
571 break;
572 default:
573 bad_rate = 1;
575 if (bad_rate) {
576 TRACE_ABORT(-EIO,
577 ft_t_fdc_dma, "%d is not a valid data rate", rate);
579 fdc_data_rate = rate;
580 fdc_update_dsr();
581 fdc_set_seek_rate(fdc_seek_rate); /* clock changed! */
582 ftape_udelay(1000);
583 TRACE_EXIT 0;
586 /* keep the unit select if keep_select is != 0,
588 static void fdc_dor_reset(int keep_select)
590 __u8 fdc_ctl = ft_drive_sel;
592 if (keep_select != 0) {
593 fdc_ctl |= FDC_DMA_MODE;
594 if (ftape_motor) {
595 fdc_ctl |= FDC_MOTOR_0 << ft_drive_sel;
598 ftape_udelay(10); /* ??? but seems to be necessary */
599 if (ft_mach2) {
600 outb_p(fdc_ctl & 0x0f, fdc.dor);
601 outb_p(fdc_ctl, fdc.dor2);
602 } else {
603 outb_p(fdc_ctl, fdc.dor);
605 fdc_usec_wait(10); /* delay >= 14 fdc clocks */
606 if (keep_select == 0) {
607 fdc_ctl = 0;
609 fdc_ctl |= FDC_RESET_NOT;
610 if (ft_mach2) {
611 outb_p(fdc_ctl & 0x0f, fdc.dor);
612 outb_p(fdc_ctl, fdc.dor2);
613 } else {
614 outb_p(fdc_ctl, fdc.dor);
618 /* Reset the floppy disk controller. Leave the ftape_unit selected.
620 void fdc_reset(void)
622 int st0;
623 int i;
624 int dummy;
625 unsigned long flags;
626 TRACE_FUN(ft_t_any);
628 save_flags(flags);
629 cli();
631 fdc_dor_reset(1); /* keep unit selected */
633 fdc_mode = fdc_idle;
635 /* maybe the cli()/sti() pair is not necessary, BUT:
636 * the following line MUST be here. Otherwise fdc_interrupt_wait()
637 * won't wait. Note that fdc_reset() is called from
638 * ftape_dumb_stop() when the fdc is busy transferring data. In this
639 * case fdc_isr() MOST PROBABLY sets ft_interrupt_seen, and tries
640 * to get the result bytes from the fdc etc. CLASH.
642 ft_interrupt_seen = 0;
644 /* Program data rate
646 fdc_update_dsr(); /* restore data rate and precomp */
648 restore_flags(flags);
651 * Wait for first polling cycle to complete
653 if (fdc_interrupt_wait(1 * FT_SECOND) < 0) {
654 TRACE(ft_t_err, "no drive polling interrupt!");
655 } else { /* clear all disk-changed statuses */
656 for (i = 0; i < 4; ++i) {
657 if(fdc_sense_interrupt_status(&st0, &dummy) != 0) {
658 TRACE(ft_t_err, "sense failed for %d", i);
660 if (i == ft_drive_sel) {
661 ftape_current_cylinder = dummy;
664 TRACE(ft_t_noise, "drive polling completed");
667 * SPECIFY COMMAND
669 fdc_set_seek_rate(fdc_seek_rate);
671 * DRIVE SPECIFICATION COMMAND (if fdc type known)
673 if (fdc.type >= i82078_1) {
674 fdc_set_drive_specs();
676 TRACE_EXIT;
679 #if !defined(CLK_48MHZ)
680 # define CLK_48MHZ 1
681 #endif
683 /* When we're done, put the fdc into reset mode so that the regular
684 * floppy disk driver will figure out that something is wrong and
685 * initialize the controller the way it wants.
687 void fdc_disable(void)
689 __u8 cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00};
690 __u8 cmd2[] = {FDC_LOCK};
691 __u8 cmd3[] = {FDC_UNLOCK};
692 __u8 stat[1];
693 TRACE_FUN(ft_t_flow);
695 if (!fdc_fifo_locked) {
696 fdc_reset();
697 TRACE_EXIT;
699 if (fdc_issue_command(cmd3, 1, stat, 1) < 0 || stat[0] != 0x00) {
700 fdc_dor_reset(0);
701 TRACE_ABORT(/**/, ft_t_bug,
702 "couldn't unlock fifo, configuration remains changed");
704 fdc_fifo_locked = 0;
705 if (CLK_48MHZ && fdc.type >= i82078) {
706 cmd1[0] |= FDC_CLK48_BIT;
708 cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1);
709 if (fdc_command(cmd1, NR_ITEMS(cmd1)) < 0) {
710 fdc_dor_reset(0);
711 TRACE_ABORT(/**/, ft_t_bug,
712 "couldn't reconfigure fifo to old state");
714 if (fdc_lock_state &&
715 fdc_issue_command(cmd2, 1, stat, 1) < 0) {
716 fdc_dor_reset(0);
717 TRACE_ABORT(/**/, ft_t_bug, "couldn't lock old state again");
719 TRACE(ft_t_noise, "fifo restored: %sabled, thr. %d, %slocked",
720 fdc_fifo_state ? "en" : "dis",
721 fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");
722 fdc_dor_reset(0);
723 TRACE_EXIT;
726 /* Specify FDC seek-rate (milliseconds)
728 int fdc_set_seek_rate(int seek_rate)
730 /* set step rate, dma mode, and minimal head load and unload times
732 __u8 in[3] = { FDC_SPECIFY, 1, (1 << 1)};
734 fdc_seek_rate = seek_rate;
735 in[1] |= (16 - (fdc_data_rate * fdc_seek_rate) / 500) << 4;
737 return fdc_command(in, 3);
740 /* Sense drive status: get unit's drive status (ST3)
742 int fdc_sense_drive_status(int *st3)
744 __u8 out[2];
745 __u8 in[1];
746 TRACE_FUN(ft_t_any);
748 out[0] = FDC_SENSED;
749 out[1] = ft_drive_sel;
750 TRACE_CATCH(fdc_issue_command(out, 2, in, 1),);
751 *st3 = in[0];
752 TRACE_EXIT 0;
755 /* Sense Interrupt Status command:
756 * should be issued at the end of each seek.
757 * get ST0 and current cylinder.
759 int fdc_sense_interrupt_status(int *st0, int *current_cylinder)
761 __u8 out[1];
762 __u8 in[2];
763 TRACE_FUN(ft_t_any);
765 out[0] = FDC_SENSEI;
766 TRACE_CATCH(fdc_issue_command(out, 1, in, 2),);
767 *st0 = in[0];
768 *current_cylinder = in[1];
769 TRACE_EXIT 0;
772 /* step to track
774 int fdc_seek(int track)
776 __u8 out[3];
777 int st0, pcn;
778 #ifdef TESTING
779 unsigned int time;
780 #endif
781 TRACE_FUN(ft_t_any);
783 out[0] = FDC_SEEK;
784 out[1] = ft_drive_sel;
785 out[2] = track;
786 #ifdef TESTING
787 time = ftape_timestamp();
788 #endif
789 /* We really need this command to work !
791 ft_seek_completed = 0;
792 TRACE_CATCH(fdc_command(out, 3),
793 fdc_reset();
794 TRACE(ft_t_noise, "destination was: %d, resetting FDC...",
795 track));
796 /* Handle interrupts until ft_seek_completed or timeout.
798 for (;;) {
799 TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),);
800 if (ft_seek_completed) {
801 TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),);
802 if ((st0 & ST0_SEEK_END) == 0) {
803 TRACE_ABORT(-EIO, ft_t_err,
804 "no seek-end after seek completion !??");
806 break;
809 #ifdef TESTING
810 time = ftape_timediff(time, ftape_timestamp()) / ABS(track - ftape_current_cylinder);
811 if ((time < 900 || time > 3100) && ABS(track - ftape_current_cylinder) > 5) {
812 TRACE(ft_t_warn, "Wrong FDC STEP interval: %d usecs (%d)",
813 time, track - ftape_current_cylinder);
815 #endif
816 /* Verify whether we issued the right tape command.
818 /* Verify that we seek to the proper track. */
819 if (pcn != track) {
820 TRACE_ABORT(-EIO, ft_t_err, "bad seek..");
822 ftape_current_cylinder = track;
823 TRACE_EXIT 0;
826 /* Recalibrate and wait until home.
828 int fdc_recalibrate(void)
830 __u8 out[2];
831 int st0;
832 int pcn;
833 int retry;
834 int old_seek_rate = fdc_seek_rate;
835 TRACE_FUN(ft_t_any);
837 TRACE_CATCH(fdc_set_seek_rate(6),);
838 out[0] = FDC_RECAL;
839 out[1] = ft_drive_sel;
840 ft_seek_completed = 0;
841 TRACE_CATCH(fdc_command(out, 2),);
842 /* Handle interrupts until ft_seek_completed or timeout.
844 for (retry = 0;; ++retry) {
845 TRACE_CATCH(fdc_interrupt_wait(2 * FT_SECOND),);
846 if (ft_seek_completed) {
847 TRACE_CATCH(fdc_sense_interrupt_status(&st0, &pcn),);
848 if ((st0 & ST0_SEEK_END) == 0) {
849 if (retry < 1) {
850 continue; /* some drives/fdc's
851 * give an extra interrupt
853 } else {
854 TRACE_ABORT(-EIO, ft_t_err,
855 "no seek-end after seek completion !??");
858 break;
861 ftape_current_cylinder = pcn;
862 if (pcn != 0) {
863 TRACE(ft_t_err, "failed: resulting track = %d", pcn);
865 TRACE_CATCH(fdc_set_seek_rate(old_seek_rate),);
866 TRACE_EXIT 0;
869 static int perpend_mode = 0; /* set if fdc is in perpendicular mode */
871 static int perpend_off(void)
873 __u8 perpend[] = {FDC_PERPEND, 0x00};
874 TRACE_FUN(ft_t_any);
876 if (perpend_mode) {
877 /* Turn off perpendicular mode */
878 perpend[1] = 0x80;
879 TRACE_CATCH(fdc_command(perpend, 2),
880 TRACE(ft_t_err,"Perpendicular mode exit failed!"));
881 perpend_mode = 0;
883 TRACE_EXIT 0;
886 static int handle_perpend(int segment_id)
888 __u8 perpend[] = {FDC_PERPEND, 0x00};
889 TRACE_FUN(ft_t_any);
891 /* When writing QIC-3020 tapes, turn on perpendicular mode
892 * if tape is moving in forward direction (even tracks).
894 if (ft_qic_std == QIC_TAPE_QIC3020 &&
895 ((segment_id / ft_segments_per_track) & 1) == 0) {
896 /* FIXME: some i82077 seem to support perpendicular mode as
897 * well.
899 #if 0
900 if (fdc.type < i82077AA) {}
901 #else
902 if (fdc.type < i82077 && ft_data_rate < 1000) {
903 #endif
904 /* fdc does not support perpendicular mode: complain
906 TRACE_ABORT(-EIO, ft_t_err,
907 "Your FDC does not support QIC-3020.");
909 perpend[1] = 0x03 /* 0x83 + (0x4 << ft_drive_sel) */ ;
910 TRACE_CATCH(fdc_command(perpend, 2),
911 TRACE(ft_t_err,"Perpendicular mode entry failed!"));
912 TRACE(ft_t_flow, "Perpendicular mode set");
913 perpend_mode = 1;
914 TRACE_EXIT 0;
916 TRACE_EXIT perpend_off();
919 static inline void fdc_setup_dma(char mode,
920 volatile void *addr, unsigned int count)
922 /* Program the DMA controller.
924 disable_dma(fdc.dma);
925 clear_dma_ff(fdc.dma);
926 set_dma_mode(fdc.dma, mode);
927 set_dma_addr(fdc.dma, virt_to_bus((void*)addr));
928 set_dma_count(fdc.dma, count);
929 #ifdef GCC_2_4_5_BUG
930 /* This seemingly stupid construction confuses the gcc-2.4.5
931 * code generator enough to create correct code.
933 if (1) {
934 int i;
936 for (i = 0; i < 1; ++i) {
937 ftape_udelay(1);
940 #endif
941 enable_dma(fdc.dma);
944 /* Setup fdc and dma for formatting the next segment
946 int fdc_setup_formatting(buffer_struct * buff)
948 unsigned long flags;
949 __u8 out[6] = {
950 FDC_FORMAT, 0x00, 3, 4 * FT_SECTORS_PER_SEGMENT, 0x00, 0x6b
952 TRACE_FUN(ft_t_any);
954 TRACE_CATCH(handle_perpend(buff->segment_id),);
955 /* Program the DMA controller.
957 TRACE(ft_t_fdc_dma,
958 "phys. addr. = %lx", virt_to_bus((void*) buff->ptr));
959 save_flags(flags);
960 cli(); /* could be called from ISR ! */
961 fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4);
962 /* Issue FDC command to start reading/writing.
964 out[1] = ft_drive_sel;
965 out[4] = buff->gap3;
966 TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)),
967 restore_flags(flags); fdc_mode = fdc_idle);
968 restore_flags(flags);
969 TRACE_EXIT 0;
973 /* Setup Floppy Disk Controller and DMA to read or write the next cluster
974 * of good sectors from or to the current segment.
976 int fdc_setup_read_write(buffer_struct * buff, __u8 operation)
978 unsigned long flags;
979 __u8 out[9];
980 int dma_mode;
981 TRACE_FUN(ft_t_any);
983 switch(operation) {
984 case FDC_VERIFY:
985 if (fdc.type < i82077) {
986 operation = FDC_READ;
988 case FDC_READ:
989 case FDC_READ_DELETED:
990 dma_mode = DMA_MODE_READ;
991 TRACE(ft_t_fdc_dma, "xfer %d sectors to 0x%p",
992 buff->sector_count, buff->ptr);
993 TRACE_CATCH(perpend_off(),);
994 break;
995 case FDC_WRITE_DELETED:
996 TRACE(ft_t_noise, "deleting segment %d", buff->segment_id);
997 case FDC_WRITE:
998 dma_mode = DMA_MODE_WRITE;
999 /* When writing QIC-3020 tapes, turn on perpendicular mode
1000 * if tape is moving in forward direction (even tracks).
1002 TRACE_CATCH(handle_perpend(buff->segment_id),);
1003 TRACE(ft_t_fdc_dma, "xfer %d sectors from 0x%p",
1004 buff->sector_count, buff->ptr);
1005 break;
1006 default:
1007 TRACE_ABORT(-EIO,
1008 ft_t_bug, "bug: illegal operation parameter");
1010 TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr));
1011 save_flags(flags);
1012 cli(); /* could be called from ISR ! */
1013 if (operation != FDC_VERIFY) {
1014 fdc_setup_dma(dma_mode, buff->ptr,
1015 FT_SECTOR_SIZE * buff->sector_count);
1017 /* Issue FDC command to start reading/writing.
1019 out[0] = operation;
1020 out[1] = ft_drive_sel;
1021 out[2] = buff->cyl;
1022 out[3] = buff->head;
1023 out[4] = buff->sect + buff->sector_offset;
1024 out[5] = 3; /* Sector size of 1K. */
1025 out[6] = out[4] + buff->sector_count - 1; /* last sector */
1026 out[7] = 109; /* Gap length. */
1027 out[8] = 0xff; /* No limit to transfer size. */
1028 TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",
1029 out[2], out[3], out[4], out[6] - out[4] + 1);
1030 restore_flags(flags);
1031 TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle);
1032 TRACE_EXIT 0;
1035 int fdc_fifo_threshold(__u8 threshold,
1036 int *fifo_state, int *lock_state, int *fifo_thr)
1038 const __u8 cmd0[] = {FDC_DUMPREGS};
1039 __u8 cmd1[] = {FDC_CONFIGURE, 0, (0x0f & (threshold - 1)), 0};
1040 const __u8 cmd2[] = {FDC_LOCK};
1041 const __u8 cmd3[] = {FDC_UNLOCK};
1042 __u8 reg[10];
1043 __u8 stat;
1044 int i;
1045 int result;
1046 TRACE_FUN(ft_t_any);
1048 if (CLK_48MHZ && fdc.type >= i82078) {
1049 cmd1[0] |= FDC_CLK48_BIT;
1051 /* Dump fdc internal registers for examination
1053 TRACE_CATCH(fdc_command(cmd0, NR_ITEMS(cmd0)),
1054 TRACE(ft_t_warn, "dumpreg cmd failed, fifo unchanged"));
1055 /* Now read fdc internal registers from fifo
1057 for (i = 0; i < (int)NR_ITEMS(reg); ++i) {
1058 fdc_read(&reg[i]);
1059 TRACE(ft_t_fdc_dma, "Register %d = 0x%02x", i, reg[i]);
1061 if (fifo_state && lock_state && fifo_thr) {
1062 *fifo_state = (reg[8] & 0x20) == 0;
1063 *lock_state = reg[7] & 0x80;
1064 *fifo_thr = 1 + (reg[8] & 0x0f);
1066 TRACE(ft_t_noise,
1067 "original fifo state: %sabled, threshold %d, %slocked",
1068 ((reg[8] & 0x20) == 0) ? "en" : "dis",
1069 1 + (reg[8] & 0x0f), (reg[7] & 0x80) ? "" : "not ");
1070 /* If fdc is already locked, unlock it first ! */
1071 if (reg[7] & 0x80) {
1072 fdc_ready_wait(100);
1073 TRACE_CATCH(fdc_issue_command(cmd3, NR_ITEMS(cmd3), &stat, 1),
1074 TRACE(ft_t_bug, "FDC unlock command failed, "
1075 "configuration unchanged"));
1077 fdc_fifo_locked = 0;
1078 /* Enable fifo and set threshold at xx bytes to allow a
1079 * reasonably large latency and reduce number of dma bursts.
1081 fdc_ready_wait(100);
1082 if ((result = fdc_command(cmd1, NR_ITEMS(cmd1))) < 0) {
1083 TRACE(ft_t_bug, "configure cmd failed, fifo unchanged");
1085 /* Now lock configuration so reset will not change it
1087 if(fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1) < 0 ||
1088 stat != 0x10) {
1089 TRACE_ABORT(-EIO, ft_t_bug,
1090 "FDC lock command failed, stat = 0x%02x", stat);
1092 fdc_fifo_locked = 1;
1093 TRACE_EXIT result;
1096 static int fdc_fifo_enable(void)
1098 TRACE_FUN(ft_t_any);
1100 if (fdc_fifo_locked) {
1101 TRACE_ABORT(0, ft_t_warn, "Fifo not enabled because locked");
1103 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1104 &fdc_fifo_state,
1105 &fdc_lock_state,
1106 &fdc_fifo_thr),);
1107 TRACE_CATCH(fdc_fifo_threshold(ft_fdc_threshold /* bytes */,
1108 NULL, NULL, NULL),);
1109 TRACE_EXIT 0;
1112 /* Determine fd controller type
1114 static __u8 fdc_save_state[2] = {0, 0};
1116 int fdc_probe(void)
1118 __u8 cmd[1];
1119 __u8 stat[16]; /* must be able to hold dumpregs & save results */
1120 int i;
1121 TRACE_FUN(ft_t_any);
1123 /* Try to find out what kind of fd controller we have to deal with
1124 * Scheme borrowed from floppy driver:
1125 * first try if FDC_DUMPREGS command works
1126 * (this indicates that we have a 82072 or better)
1127 * then try the FDC_VERSION command (82072 doesn't support this)
1128 * then try the FDC_UNLOCK command (some older 82077's don't support this)
1129 * then try the FDC_PARTID command (82078's support this)
1131 cmd[0] = FDC_DUMPREGS;
1132 if (fdc_issue_command(cmd, 1, stat, 1) != 0) {
1133 TRACE_ABORT(no_fdc, ft_t_bug, "No FDC found");
1135 if (stat[0] == 0x80) {
1136 /* invalid command: must be pre 82072 */
1137 TRACE_ABORT(i8272,
1138 ft_t_warn, "Type 8272A/765A compatible FDC found");
1140 fdc_result(&stat[1], 9);
1141 fdc_save_state[0] = stat[7];
1142 fdc_save_state[1] = stat[8];
1143 cmd[0] = FDC_VERSION;
1144 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1145 TRACE_ABORT(i8272, ft_t_warn, "Type 82072 FDC found");
1147 if (*stat != 0x90) {
1148 TRACE_ABORT(i8272, ft_t_warn, "Unknown FDC found");
1150 cmd[0] = FDC_UNLOCK;
1151 if(fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] != 0x00) {
1152 TRACE_ABORT(i8272, ft_t_warn,
1153 "Type pre-1991 82077 FDC found, "
1154 "treating it like a 82072");
1156 if (fdc_save_state[0] & 0x80) { /* was locked */
1157 cmd[0] = FDC_LOCK; /* restore lock */
1158 (void)fdc_issue_command(cmd, 1, stat, 1);
1159 TRACE(ft_t_warn, "FDC is already locked");
1161 /* Test for a i82078 FDC */
1162 cmd[0] = FDC_PARTID;
1163 if (fdc_issue_command(cmd, 1, stat, 1) < 0 || stat[0] == 0x80) {
1164 /* invalid command: not a i82078xx type FDC */
1165 for (i = 0; i < 4; ++i) {
1166 outb_p(i, fdc.tdr);
1167 if ((inb_p(fdc.tdr) & 0x03) != i) {
1168 TRACE_ABORT(i82077,
1169 ft_t_warn, "Type 82077 FDC found");
1172 TRACE_ABORT(i82077AA, ft_t_warn, "Type 82077AA FDC found");
1174 /* FDC_PARTID cmd succeeded */
1175 switch (stat[0] >> 5) {
1176 case 0x0:
1177 /* i82078SL or i82078-1. The SL part cannot run at
1178 * 2Mbps (the SL and -1 dies are identical; they are
1179 * speed graded after production, according to Intel).
1180 * Some SL's can be detected by doing a SAVE cmd and
1181 * look at bit 7 of the first byte (the SEL3V# bit).
1182 * If it is 0, the part runs off 3Volts, and hence it
1183 * is a SL.
1185 cmd[0] = FDC_SAVE;
1186 if(fdc_issue_command(cmd, 1, stat, 16) < 0) {
1187 TRACE(ft_t_err, "FDC_SAVE failed. Dunno why");
1188 /* guess we better claim the fdc to be a i82078 */
1189 TRACE_ABORT(i82078,
1190 ft_t_warn,
1191 "Type i82078 FDC (i suppose) found");
1193 if ((stat[0] & FDC_SEL3V_BIT)) {
1194 /* fdc running off 5Volts; Pray that it's a i82078-1
1196 TRACE_ABORT(i82078_1, ft_t_warn,
1197 "Type i82078-1 or 5Volt i82078SL FDC found");
1199 TRACE_ABORT(i82078, ft_t_warn,
1200 "Type 3Volt i82078SL FDC (1Mbps) found");
1201 case 0x1:
1202 case 0x2: /* S82078B */
1203 /* The '78B isn't '78 compatible. Detect it as a '77AA */
1204 TRACE_ABORT(i82077AA, ft_t_warn, "Type i82077AA FDC found");
1205 case 0x3: /* NSC PC8744 core; used in several super-IO chips */
1206 TRACE_ABORT(i82077AA,
1207 ft_t_warn, "Type 82077AA compatible FDC found");
1208 default:
1209 TRACE(ft_t_warn, "A previously undetected FDC found");
1210 TRACE_ABORT(i82077AA, ft_t_warn,
1211 "Treating it as a 82077AA. Please report partid= %d",
1212 stat[0]);
1213 } /* switch(stat[ 0] >> 5) */
1214 TRACE_EXIT no_fdc;
1217 static int fdc_request_regions(void)
1219 TRACE_FUN(ft_t_flow);
1221 if (ft_mach2 || ft_probe_fc10) {
1222 if (check_region(fdc.sra, 8) < 0) {
1223 #ifndef BROKEN_FLOPPY_DRIVER
1224 TRACE_EXIT -EBUSY;
1225 #else
1226 TRACE(ft_t_warn,
1227 "address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1228 #endif
1230 request_region(fdc.sra, 8, "fdc (ft)");
1231 } else {
1232 if (check_region(fdc.sra, 6) < 0 ||
1233 check_region(fdc.dir, 1) < 0) {
1234 #ifndef BROKEN_FLOPPY_DRIVER
1235 TRACE_EXIT -EBUSY;
1236 #else
1237 TRACE(ft_t_warn,
1238 "address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
1239 #endif
1241 request_region(fdc.sra, 6, "fdc (ft)");
1242 request_region(fdc.sra + 7, 1, "fdc (ft)");
1244 TRACE_EXIT 0;
1247 void fdc_release_regions(void)
1249 TRACE_FUN(ft_t_flow);
1251 if (fdc.sra != 0) {
1252 if (fdc.dor2 != 0) {
1253 release_region(fdc.sra, 8);
1254 } else {
1255 release_region(fdc.sra, 6);
1256 release_region(fdc.dir, 1);
1259 TRACE_EXIT;
1262 static int fdc_config_regs(unsigned int fdc_base,
1263 unsigned int fdc_irq,
1264 unsigned int fdc_dma)
1266 TRACE_FUN(ft_t_flow);
1268 fdc.irq = fdc_irq;
1269 fdc.dma = fdc_dma;
1270 fdc.sra = fdc_base;
1271 fdc.srb = fdc_base + 1;
1272 fdc.dor = fdc_base + 2;
1273 fdc.tdr = fdc_base + 3;
1274 fdc.msr = fdc.dsr = fdc_base + 4;
1275 fdc.fifo = fdc_base + 5;
1276 fdc.dir = fdc.ccr = fdc_base + 7;
1277 fdc.dor2 = (ft_mach2 || ft_probe_fc10) ? fdc_base + 6 : 0;
1278 TRACE_CATCH(fdc_request_regions(), fdc.sra = 0);
1279 TRACE_EXIT 0;
1282 static int fdc_config(void)
1284 static int already_done = 0;
1285 TRACE_FUN(ft_t_any);
1287 if (already_done) {
1288 TRACE_CATCH(fdc_request_regions(),);
1289 *(fdc.hook) = fdc_isr; /* hook our handler in */
1290 TRACE_EXIT 0;
1292 if (ft_probe_fc10) {
1293 int fc_type;
1295 TRACE_CATCH(fdc_config_regs(ft_fdc_base,
1296 ft_fdc_irq, ft_fdc_dma),);
1297 fc_type = fc10_enable();
1298 if (fc_type != 0) {
1299 TRACE(ft_t_warn, "FC-%c0 controller found", '0' + fc_type);
1300 fdc.type = fc10;
1301 fdc.hook = &do_ftape;
1302 *(fdc.hook) = fdc_isr; /* hook our handler in */
1303 already_done = 1;
1304 TRACE_EXIT 0;
1305 } else {
1306 TRACE(ft_t_warn, "FC-10/20 controller not found");
1307 fdc_release_regions();
1308 fdc.type = no_fdc;
1309 ft_probe_fc10 = 0;
1310 ft_fdc_base = 0x3f0;
1311 ft_fdc_irq = 6;
1312 ft_fdc_dma = 2;
1315 TRACE(ft_t_warn, "fdc base: 0x%x, irq: %d, dma: %d",
1316 ft_fdc_base, ft_fdc_irq, ft_fdc_dma);
1317 TRACE_CATCH(fdc_config_regs(ft_fdc_base, ft_fdc_irq, ft_fdc_dma),);
1318 fdc.hook = &do_ftape;
1319 *(fdc.hook) = fdc_isr; /* hook our handler in */
1320 already_done = 1;
1321 TRACE_EXIT 0;
1324 #if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70)
1325 static void ftape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1326 #else
1327 static void ftape_interrupt(int irq, struct pt_regs *regs)
1328 #endif
1330 void (*handler) (void) = *fdc.hook;
1331 TRACE_FUN(ft_t_any);
1333 *fdc.hook = NULL;
1334 if (handler) {
1335 handler();
1336 } else {
1337 TRACE(ft_t_bug, "Unexpected ftape interrupt");
1339 TRACE_EXIT;
1342 int fdc_grab_irq_and_dma(void)
1344 TRACE_FUN(ft_t_any);
1346 if (fdc.hook == &do_ftape) {
1347 /* Get fast interrupt handler.
1349 #if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70)
1350 if (request_irq(fdc.irq, ftape_interrupt,
1351 SA_INTERRUPT, "ft", ftape_id)) {
1352 TRACE_ABORT(-EIO, ft_t_bug,
1353 "Unable to grab IRQ%d for ftape driver",
1354 fdc.irq);
1356 #else
1357 if (request_irq(fdc.irq, ftape_interrupt, SA_INTERRUPT,
1358 ftape_id)) {
1359 TRACE_ABORT(-EIO, ft_t_bug,
1360 "Unable to grab IRQ%d for ftape driver",
1361 fdc.irq);
1363 #endif
1364 if (request_dma(fdc.dma, ftape_id)) {
1365 #if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70)
1366 free_irq(fdc.irq, ftape_id);
1367 #else
1368 free_irq(fdc.irq);
1369 #endif
1370 TRACE_ABORT(-EIO, ft_t_bug,
1371 "Unable to grab DMA%d for ftape driver",
1372 fdc.dma);
1374 enable_irq(fdc.irq);
1376 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1377 /* Using same dma channel or irq as standard fdc, need
1378 * to disable the dma-gate on the std fdc. This
1379 * couldn't be done in the floppy driver as some
1380 * laptops are using the dma-gate to enter a low power
1381 * or even suspended state :-(
1383 outb_p(FDC_RESET_NOT, 0x3f2);
1384 TRACE(ft_t_noise, "DMA-gate on standard fdc disabled");
1386 TRACE_EXIT 0;
1389 int fdc_release_irq_and_dma(void)
1391 TRACE_FUN(ft_t_any);
1393 if (fdc.hook == &do_ftape) {
1394 disable_dma(fdc.dma); /* just in case... */
1395 free_dma(fdc.dma);
1396 disable_irq(fdc.irq);
1397 #if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70)
1398 free_irq(fdc.irq, ftape_id);
1399 #else
1400 free_irq(fdc.irq);
1401 #endif
1403 if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
1404 /* Using same dma channel as standard fdc, need to
1405 * disable the dma-gate on the std fdc. This couldn't
1406 * be done in the floppy driver as some laptops are
1407 * using the dma-gate to enter a low power or even
1408 * suspended state :-(
1410 outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);
1411 TRACE(ft_t_noise, "DMA-gate on standard fdc enabled again");
1413 TRACE_EXIT 0;
1416 int fdc_init(void)
1418 TRACE_FUN(ft_t_any);
1420 /* find a FDC to use */
1421 TRACE_CATCH(fdc_config(),);
1422 TRACE_CATCH(fdc_grab_irq_and_dma(), fdc_release_regions());
1423 ftape_motor = 0;
1424 fdc_catch_stray_interrupts(0); /* clear number of awainted
1425 * stray interrupte
1427 fdc_catch_stray_interrupts(1); /* one always comes (?) */
1428 TRACE(ft_t_flow, "resetting fdc");
1429 fdc_set_seek_rate(2); /* use nominal QIC step rate */
1430 fdc_reset(); /* init fdc & clear track counters */
1431 if (fdc.type == no_fdc) { /* no FC-10 or FC-20 found */
1432 fdc.type = fdc_probe();
1433 fdc_reset(); /* update with new knowledge */
1435 if (fdc.type == no_fdc) {
1436 fdc_release_irq_and_dma();
1437 fdc_release_regions();
1438 TRACE_EXIT -ENXIO;
1440 if (fdc.type >= i82077) {
1441 if (fdc_fifo_enable() < 0) {
1442 TRACE(ft_t_warn, "couldn't enable fdc fifo !");
1443 } else {
1444 TRACE(ft_t_flow, "fdc fifo enabled and locked");
1447 TRACE_EXIT 0;