This source file includes following definitions.
- fdc_catch_stray_interrupts
- fdc_wait
- fdc_ready_wait
- fdc_usec_wait
- fdc_ready_out_wait
- fdc_ready_in_wait
- fdc_wait_calibrate
- fdc_write
- fdc_read
- fdc_command
- fdc_result
- fdc_issue_command
- fdc_interrupt_wait
- fdc_motor
- fdc_update_dsr
- fdc_set_write_precomp
- fdc_save_drive_specs
- fdc_restore_drive_specs
- fdc_set_data_rate
- fdc_reset
- fdc_disable
- fdc_set_seek_rate
- fdc_sense_drive_status
- fdc_sense_interrupt_status
- fdc_seek
- fdc_recalibrate
- setup_fdc_and_dma
- fdc_fifo_enable
- fdc_probe
- fdc_config_regs
- fdc_config
- ftape_interrupt
- fdc_grab_irq_and_dma
- fdc_release_irq_and_dma
- fdc_uninit
- fdc_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <linux/module.h>
25 #include <linux/errno.h>
26 #include <linux/sched.h>
27 #include <linux/ioport.h>
28 #include <linux/ftape.h>
29 #include <asm/system.h>
30 #include <asm/io.h>
31 #include <asm/dma.h>
32 #include <asm/irq.h>
33
34 #include "tracing.h"
35 #include "fdc-io.h"
36 #include "fdc-isr.h"
37 #include "ftape-io.h"
38 #include "ftape-rw.h"
39 #include "calibr.h"
40 #include "fc-10.h"
41 #include "qic117.h"
42
43
44
45
46 int ftape_unit = -1;
47 int ftape_motor = 0;
48 int current_cylinder = -1;
49 fdc_mode_enum fdc_mode = fdc_idle;
50 fdc_config_info fdc = {0};
51
52
53
54 static int fdc_calibr_count;
55 static int fdc_calibr_time;
56 static int fdc_confused = 0;
57 static int fdc_status;
58 volatile byte fdc_head;
59 volatile byte fdc_cyl;
60 volatile byte fdc_sect;
61 static int fdc_data_rate = 0;
62 static int fdc_seek_rate = 14;
63 static void (*do_ftape) (void);
64 static int fdc_fifo_state;
65 static int fdc_fifo_thr;
66 static int fdc_lock_state;
67 static int fdc_fifo_locked = 0;
68 static byte fdc_precomp = 0;
69 static byte fdc_drv_spec[4];
70 static int perpend_mode;
71
72 void fdc_catch_stray_interrupts(unsigned count)
73 {
74 unsigned long flags;
75
76 save_flags(flags);
77 cli();
78 if (count == 0) {
79 expected_stray_interrupts = 0;
80 } else {
81 expected_stray_interrupts += count;
82 }
83 restore_flags(flags);
84 }
85
86
87
88
89
90 int fdc_wait(int usecs, byte mask, byte state)
91 {
92 int count_1 = (fdc_calibr_count * usecs - 1) / fdc_calibr_time;
93
94 do {
95 fdc_status = inb_p(fdc.msr);
96 if ((fdc_status & mask) == state) {
97 return 0;
98 }
99 } while (count_1-- >= 0);
100 return -ETIME;
101 }
102
103 int fdc_ready_wait(int usecs)
104 {
105 return fdc_wait(usecs, FDC_DATA_READY, FDC_DATA_READY);
106 }
107
108 static void fdc_usec_wait(int usecs)
109 {
110 fdc_wait(usecs, 0, 1);
111 }
112
113 int fdc_ready_out_wait(int usecs)
114 {
115 fdc_usec_wait(RQM_DELAY);
116 return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);
117 }
118
119 int fdc_ready_in_wait(int usecs)
120 {
121 fdc_usec_wait(RQM_DELAY);
122 return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_IN_READY);
123 }
124
125 int fdc_wait_calibrate(void)
126 {
127 return calibrate("fdc_wait",
128 fdc_usec_wait, &fdc_calibr_count, &fdc_calibr_time);
129 }
130
131
132
133
134
135 int fdc_write(byte data)
136 {
137 fdc_usec_wait(RQM_DELAY);
138 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_IN_READY) < 0) {
139 return -ETIME;
140 } else {
141 outb(data, fdc.fifo);
142 return 0;
143 }
144 }
145
146
147
148
149
150 int fdc_read(byte * data)
151 {
152 fdc_usec_wait(RQM_DELAY);
153 if (fdc_wait(150, FDC_DATA_READY_MASK, FDC_DATA_OUT_READY) < 0) {
154 return -ETIME;
155 } else {
156 *data = inb(fdc.fifo);
157 return 0;
158 }
159 }
160
161
162
163
164
165 int fdc_command(byte * cmd_data, int cmd_len)
166 {
167 TRACE_FUN(8, "fdc_command");
168 int result = 0;
169 unsigned long flags;
170 int count = cmd_len;
171
172 fdc_usec_wait(RQM_DELAY);
173 save_flags(flags);
174 cli();
175 fdc_status = inb(fdc.msr);
176 if ((fdc_status & FDC_DATA_READY_MASK) == FDC_DATA_IN_READY) {
177 int retry = 0;
178 fdc_mode = *cmd_data;
179 interrupt_seen = 0;
180 while (count) {
181 result = fdc_write(*cmd_data);
182 if (result < 0) {
183 TRACEx3(6, "fdc_mode = %02x, status = %02x at index %d",
184 (int) fdc_mode, (int) fdc_status, cmd_len - count);
185 if (++retry <= 3) {
186 TRACE(2, "fdc_write timeout, retry");
187 } else {
188 TRACE(1, "fdc_write timeout, fatal");
189 fdc_confused = 1;
190
191 break;
192 }
193 } else {
194 --count;
195 ++cmd_data;
196 }
197 }
198 } else {
199 TRACE(1, "fdc not ready");
200 result = -EBUSY;
201 }
202 restore_flags(flags);
203 TRACE_EXIT;
204 return result;
205 }
206
207
208
209
210
211 int fdc_result(byte * res_data, int res_len)
212 {
213 TRACE_FUN(8, "fdc_result");
214 int result = 0;
215 unsigned long flags;
216 int count = res_len;
217
218 save_flags(flags);
219 cli();
220 fdc_status = inb(fdc.msr);
221 if ((fdc_status & FDC_DATA_READY_MASK) == FDC_DATA_OUT_READY) {
222 int retry = 0;
223 while (count) {
224 if (!(fdc_status & FDC_BUSY)) {
225 TRACE(1, "premature end of result phase");
226 }
227 result = fdc_read(res_data);
228 if (result < 0) {
229 TRACEx3(6, "fdc_mode = %02x, status = %02x at index %d",
230 (int) fdc_mode, (int) fdc_status, res_len - count);
231 if (++retry <= 3) {
232 TRACE(2, "fdc_read timeout, retry");
233 } else {
234 TRACE(1, "fdc_read timeout, fatal");
235 fdc_confused = 1;
236
237 break;
238 }
239 } else {
240 --count;
241 ++res_data;
242 }
243 }
244 } else {
245 TRACE(1, "fdc not ready");
246 result = -EBUSY;
247 }
248 restore_flags(flags);
249 fdc_usec_wait(RQM_DELAY);
250 TRACE_EXIT;
251 return result;
252 }
253
254
255
256
257 int fdc_issue_command(byte * out_data, int out_count,
258 byte * in_data, int in_count)
259 {
260 TRACE_FUN(8, "fdc_issue_command");
261 int result;
262 int t0, t1;
263
264 if (out_count > 0) {
265 result = fdc_command(out_data, out_count);
266 if (result < 0) {
267 TRACE(1, "fdc_command failed");
268 TRACE_EXIT;
269 return result;
270 }
271 }
272
273
274
275
276
277
278
279 t0 = timestamp();
280 result = fdc_ready_out_wait(500 );
281 t1 = timestamp();
282 if (result < 0) {
283 TRACEi(1, "fdc_ready_out_wait failed after:", timediff(t0, t1));
284 TRACE_EXIT;
285 return result;
286 }
287 if (in_count > 0) {
288 result = fdc_result(in_data, in_count);
289 if (result < 0) {
290 TRACE(1, "result phase aborted");
291 TRACE_EXIT;
292 return result;
293 }
294 }
295 TRACE_EXIT;
296 return 0;
297 }
298
299
300
301
302
303 int fdc_interrupt_wait(int time)
304 {
305 TRACE_FUN(8, "fdc_interrupt_wait");
306 struct wait_queue wait =
307 {current, NULL};
308 int result = -ETIME;
309 int need_cleanup = 0;
310 int current_blocked = current->blocked;
311 static int resetting = 0;
312
313 if (wait_intr) {
314 TRACE(1, "error: nested call");
315 return -EIO;
316 }
317 if (interrupt_seen == 0) {
318
319
320 current->timeout = jiffies + 1 + (time + MSPT - 1) / MSPT;
321 current->state = TASK_INTERRUPTIBLE;
322 current->blocked = _BLOCK_ALL;
323 add_wait_queue(&wait_intr, &wait);
324 do {
325 schedule();
326 } while (!interrupt_seen && current->state != TASK_RUNNING);
327 current->blocked = current_blocked;
328 remove_wait_queue(&wait_intr, &wait);
329 if (interrupt_seen) {
330 current->timeout = 0;
331 result = 0;
332 } else {
333 #if 1
334
335 if (current->timeout > 0) {
336 TRACE(-1, "*** BUG: unexpected schedule exit ***");
337 if (current->signal & ~current->blocked) {
338 TRACE(4, "caused by signal ?");
339 }
340 }
341 #endif
342 if (current->signal & ~current->blocked) {
343 result = -EINTR;
344 } else {
345 result = -ETIME;
346 }
347 need_cleanup = 1;
348 }
349 } else {
350 result = 0;
351 }
352
353
354
355
356
357 interrupt_seen = 0;
358
359 if (need_cleanup & !resetting) {
360 resetting = 1;
361 TRACE(8, "cleanup reset");
362 fdc_reset();
363 resetting = 0;
364 }
365 TRACE_EXIT;
366 return result;
367 }
368
369
370
371 void fdc_motor(int motor)
372 {
373 TRACE_FUN(8, "fdc_motor");
374 int unit = FTAPE_UNIT;
375 int data = unit | FDC_RESET_NOT | FDC_DMA_MODE;
376
377 ftape_motor = motor;
378 if (ftape_motor) {
379 data |= FDC_MOTOR_0 << unit;
380 TRACEx1(4, "turning motor %d on", unit);
381 } else {
382 TRACEx1(4, "turning motor %d off", unit);
383 }
384 #ifdef MACH2
385 outb_p(data, fdc.dor2);
386 #else
387 outb_p(data, fdc.dor);
388 #endif
389 ftape_sleep(10 * MILLISECOND);
390 TRACE_EXIT;
391 }
392
393 static void fdc_update_dsr(void)
394 {
395 TRACE_FUN(8, "fdc_update_dsr");
396
397 TRACEx2(5, "rate = %d, precomp = %d", fdc_data_rate, fdc_precomp);
398 if (fdc.type >= i82077) {
399 outb_p((fdc_data_rate & 0x03) | fdc_precomp, fdc.dsr);
400 } else {
401 outb_p(fdc_data_rate, fdc.ccr);
402 }
403 TRACE_EXIT;
404 }
405
406 void fdc_set_write_precomp(int precomp)
407 {
408
409
410
411
412
413 fdc_precomp = ((precomp + 21) / 42) << 2;
414 if (fdc_precomp == 0) {
415 fdc_precomp = 7 << 2;
416 }
417 fdc_update_dsr();
418 }
419
420
421
422
423 void fdc_save_drive_specs(void)
424 {
425 byte cmd1[] =
426 {FDC_DRIVE_SPEC, 0x80};
427 byte cmd2[] =
428 {FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};
429 int result;
430
431 TRACE_FUN(8, "fdc_save_drive_specs");
432 if (fdc.type >= i82078_1) {
433 result = fdc_issue_command(cmd1, NR_ITEMS(cmd1), fdc_drv_spec, 4);
434 if (result >= 0) {
435 cmd2[1] = (fdc_drv_spec[0] & 0x03) | 0x04;
436 cmd2[2] = (fdc_drv_spec[1] & 0x03) | 0x24;
437 cmd2[3] = (fdc_drv_spec[2] & 0x03) | 0x44;
438 cmd2[4] = (fdc_drv_spec[3] & 0x03) | 0x64;
439 fdc_command(cmd2, NR_ITEMS(cmd2));
440 if (result < 0) {
441 TRACE(1, "Setting of drive specs failed");
442 return;
443 }
444 } else {
445 TRACE(2, "Save of drive specs failed");
446 }
447 }
448 TRACE_EXIT;
449 }
450
451
452 void fdc_restore_drive_specs(void)
453 {
454 byte cmd[] =
455 {FDC_DRIVE_SPEC, 0x00, 0x00, 0x00, 0x00, 0xc0};
456 int result;
457
458 TRACE_FUN(8, "fdc_restore_drive_specs");
459 if (fdc.type > i82078_1) {
460 cmd[1] = (fdc_drv_spec[0] & 0x1f) | 0x00;
461 cmd[2] = (fdc_drv_spec[1] & 0x1f) | 0x20;
462 cmd[3] = (fdc_drv_spec[2] & 0x1f) | 0x40;
463 cmd[4] = (fdc_drv_spec[3] & 0x1f) | 0x60;
464 result = fdc_command(cmd, NR_ITEMS(cmd));
465 if (result < 0) {
466 TRACE(2, "Restoration of drive specs failed");
467 }
468 }
469 TRACE_EXIT;
470 }
471
472
473
474
475 void fdc_set_data_rate(int rate)
476 {
477
478
479
480 fdc_data_rate = rate;
481 fdc_update_dsr();
482 fdc_set_seek_rate(fdc_seek_rate);
483 }
484
485
486
487 void fdc_reset(void)
488 {
489 TRACE_FUN(8, "fdc_reset");
490 int unit = FTAPE_UNIT;
491 byte fdc_ctl = unit | FDC_DMA_MODE;
492 int st0;
493 int i;
494 int result;
495 int dummy;
496
497 if (ftape_motor) {
498 fdc_ctl |= FDC_MOTOR_0 << unit;
499 }
500 #ifdef MACH2
501 outb_p(fdc_ctl & 0x0f, fdc.dor);
502 outb_p(fdc_ctl, fdc.dor2);
503 #else
504 outb_p(fdc_ctl, fdc.dor);
505 #endif
506 fdc_usec_wait(10 );
507 fdc_ctl |= FDC_RESET_NOT;
508 fdc_mode = fdc_idle;
509 #ifdef MACH2
510 outb_p(fdc_ctl & 0x0f, fdc.dor);
511 outb_p(fdc_ctl, fdc.dor2);
512 #else
513 outb_p(fdc_ctl, fdc.dor);
514 #endif
515 result = fdc_interrupt_wait(1 * SECOND);
516 if (result < 0) {
517 TRACE(1, "missing interrupt after reset");
518 }
519 fdc_set_data_rate(fdc_data_rate);
520 fdc_usec_wait(1000 );
521 for (i = 0; i < 4; ++i) {
522 fdc_sense_interrupt_status(&st0, &dummy);
523 if (i == unit) {
524 current_cylinder = dummy;
525 }
526 }
527 fdc_set_seek_rate(2);
528 TRACE_EXIT;
529 }
530
531
532
533
534 void fdc_disable(void)
535 {
536 TRACE_FUN(8, "fdc_disable");
537 int result;
538 byte cmd1[] = {FDC_CONFIGURE, 0x00, 0x00, 0x00};
539 byte cmd2[] = {FDC_LOCK};
540 byte cmd3[] = {FDC_UNLOCK};
541 byte stat[1];
542
543 if (CLK_48MHZ && fdc.type >= i82078)
544 cmd1[0] |= FDC_CLK48_BIT;
545 if (fdc_fifo_locked) {
546 result = fdc_issue_command(cmd3, 1, stat, 1);
547 if (result < 0 || stat[0] != 0x00) {
548 TRACE(-1, "couldn't unlock fifo, configuration remains changed");
549 } else {
550 cmd1[2] = ((fdc_fifo_state) ? 0 : 0x20) + (fdc_fifo_thr - 1);
551 result = fdc_command(cmd1, NR_ITEMS(cmd1));
552 if (result < 0) {
553 TRACE(-1, "couldn't reconfigure fifo to old state");
554 } else if (fdc_lock_state) {
555 result = fdc_issue_command(cmd2, 1, stat, 1);
556 if (result < 0) {
557 TRACE(-1, "couldn't lock old state again");
558 }
559 }
560 TRACEx3(5, "fifo restored: %sabled, thr. %d, %slocked",
561 fdc_fifo_state ? "en" : "dis",
562 fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");
563 }
564 fdc_fifo_locked = 0;
565 }
566 #ifdef MACH2
567 outb_p(FTAPE_UNIT & 0x0f, fdc.dor);
568 outb_p(FTAPE_UNIT, fdc.dor2);
569 udelay(10);
570 outb_p(FDC_RESET_NOT & 0x0f, fdc.dor);
571 outb_p(FDC_RESET_NOT, fdc.dor2);
572 #else
573 outb_p(FTAPE_UNIT, fdc.dor);
574 udelay(10);
575 outb_p(FDC_RESET_NOT, fdc.dor);
576 #endif
577 TRACE_EXIT;
578 }
579
580
581
582 int fdc_set_seek_rate(int seek_rate)
583 {
584 byte in[3];
585 const int hut = 1;
586 const int hlt = 1;
587 const int rates[] = {250, 2000, 500, 1000};
588
589 in[0] = FDC_SPECIFY;
590 in[1] = (((16 - (rates[fdc_data_rate & 0x03] * seek_rate) / 500) << 4) |
591 hut);
592 in[2] = (hlt << 1) | 0;
593 fdc_seek_rate = seek_rate;
594
595 return fdc_command(in, 3);
596 }
597
598
599
600 int fdc_sense_drive_status(int *st3)
601 {
602 TRACE_FUN(8, "fdc_sense_drive_status");
603 int result;
604 byte out[2];
605 byte in[1];
606
607 out[0] = FDC_SENSED;
608 out[1] = FTAPE_UNIT;
609 result = fdc_issue_command(out, 2, in, 1);
610 if (result < 0) {
611 TRACE(1, "issue_command failed");
612 } else {
613 *st3 = in[0];
614 result = 0;
615 }
616 TRACE_EXIT;
617 return result;
618 }
619
620
621
622
623
624 int fdc_sense_interrupt_status(int *st0, int *current_cylinder)
625 {
626 TRACE_FUN(8, "fdc_sense_interrupt_status");
627 int result;
628 byte out[1];
629 byte in[2];
630
631 out[0] = FDC_SENSEI;
632 result = fdc_issue_command(out, 1, in, 2);
633 if (result) {
634 TRACE(1, "issue_command failed");
635 } else {
636 *st0 = in[0];
637 *current_cylinder = in[1];
638 result = 0;
639 }
640 TRACE_EXIT;
641 return result;
642 }
643
644
645
646 int fdc_seek(int track)
647 {
648 TRACE_FUN(8, "fdc_seek");
649 int result;
650 byte out[3];
651 int st0, pcn;
652
653 out[0] = FDC_SEEK;
654 out[1] = FTAPE_UNIT;
655 out[2] = track;
656 seek_completed = 0;
657 result = fdc_command(out, 3);
658 if (result != 0) {
659 TRACEi(1, "failed, status =", result);
660 TRACEx1(4, "destination was: %d, resetting FDC...", track);
661
662
663 fdc_reset();
664 TRACE_EXIT;
665 return result;
666 }
667
668
669 for (;;) {
670 result = fdc_interrupt_wait(2 * SECOND);
671 if (result < 0) {
672 TRACEi(2, "fdc_interrupt_wait timeout, status =", result);
673 TRACE_EXIT;
674 return result;
675 } else if (seek_completed) {
676 result = fdc_sense_interrupt_status(&st0, &pcn);
677 if (result != 0) {
678 TRACEi(1, "fdc_sense_interrupt_status failed, status =", result);
679 TRACE_EXIT;
680 return result;
681 }
682 if ((st0 & ST0_SEEK_END) == 0) {
683 TRACE(1, "no seek-end after seek completion !??");
684 TRACE_EXIT;
685 return -EIO;
686 }
687 break;
688 }
689 }
690
691
692
693 if (pcn != track) {
694 TRACE(1, "bad seek..");
695 TRACE_EXIT;
696 return -EIO;
697 }
698 current_cylinder = pcn;
699 TRACE_EXIT;
700 return 0;
701 }
702
703
704
705 int fdc_recalibrate(void)
706 {
707 TRACE_FUN(8, "fdc_recalibrate");
708 int result;
709 byte out[2];
710 int st0;
711 int pcn;
712 int retry;
713
714 result = fdc_set_seek_rate(6);
715 if (result) {
716 TRACEi(1, "fdc_set_seek_rate failed, status =", result);
717 TRACE_EXIT;
718 return result;
719 }
720 out[0] = FDC_RECAL;
721 out[1] = FTAPE_UNIT;
722 seek_completed = 0;
723 result = fdc_command(out, 2);
724 if (result) {
725 TRACEi(1, "fdc_command failed, status =", result);
726 TRACE_EXIT;
727 return result;
728 }
729
730
731 for (retry = 0;; ++retry) {
732 result = fdc_interrupt_wait(2 * SECOND);
733 if (result < 0) {
734 TRACE(1, "fdc_interrupt_wait failed");
735 TRACE_EXIT;
736 return result;
737 } else if (result == 0 && seek_completed) {
738 result = fdc_sense_interrupt_status(&st0, &pcn);
739 if (result != 0) {
740 TRACEi(1, "fdc_sense_interrupt_status failed, status =", result);
741 TRACE_EXIT;
742 return result;
743 }
744 if ((st0 & ST0_SEEK_END) == 0) {
745 if (retry < 1) {
746 continue;
747 } else {
748 TRACE(1, "no seek-end after seek completion !??");
749 TRACE_EXIT;
750 return -EIO;
751 }
752 }
753 break;
754 }
755 }
756 current_cylinder = pcn;
757 if (pcn != 0) {
758 TRACEi(1, "failed: resulting track =", pcn);
759 }
760 result = fdc_set_seek_rate(2);
761 if (result != 0) {
762 TRACEi(1, "fdc_set_seek_rate failed, status =", result);
763 TRACE_EXIT;
764 return result;
765 }
766 TRACE_EXIT;
767 return 0;
768 }
769
770
771
772
773 int setup_fdc_and_dma(buffer_struct * buff, unsigned char operation)
774 {
775 TRACE_FUN(8, "setup_fdc_and_dma");
776 unsigned long flags;
777 byte perpend[] = {FDC_PERPEND, 0x00};
778 unsigned char out[9];
779 int result;
780 int dma_mode;
781
782 if (operation == FDC_READ || operation == FDC_READ_DELETED) {
783 dma_mode = DMA_MODE_READ;
784 if (qic_std == QIC_TAPE_QIC3020) {
785 if (fdc.type < i82077AA) {
786
787 TRACE(0, "Your FDC does not support QIC-3020.");
788 return -EIO;
789 }
790
791 perpend[1] = 0x83 + (0x04 << FTAPE_UNIT);
792 result = fdc_command(perpend, 2);
793 if (result < 0) {
794 TRACE(1, "Perpendicular mode entry failed!");
795 } else {
796 TRACE(4, "Perpendicular mode entered");
797 perpend_mode = 1;
798 }
799 } else if (perpend_mode) {
800
801 perpend[1] = 0x80;
802 result = fdc_command(perpend, 2);
803 if (result < 0) {
804 TRACE(1, "Perpendicular mode exit failed!");
805 } else {
806 TRACE(4, "Perpendicular mode exited");
807 perpend_mode = 0;
808 }
809 }
810 TRACEx2(5, "xfer %d sectors to 0x%p", buff->sector_count, buff->ptr);
811 } else if (operation == FDC_WRITE || operation == FDC_WRITE_DELETED) {
812 dma_mode = DMA_MODE_WRITE;
813
814
815 if (qic_std == QIC_TAPE_QIC3020) {
816 if (fdc.type < i82077AA) {
817
818 TRACE(0, "Your FDC does not support QIC-3020.");
819 return -EIO;
820 }
821 perpend[1] = 0x83 + (0x4 << FTAPE_UNIT);
822 result = fdc_command(perpend, 2);
823 if (result < 0) {
824 TRACE(1, "Perpendicular mode entry failed!");
825 } else {
826 TRACE(4, "Perpendicular mode entered");
827 perpend_mode = 1;
828 }
829 } else if (perpend_mode) {
830 perpend[1] = 0x80;
831 result = fdc_command(perpend, 2);
832 if (result < 0) {
833 TRACE(1, "Perpendicular mode exit failed!");
834 } else {
835 TRACE(4, "Perpendicular mode exited");
836 perpend_mode = 0;
837 }
838 }
839 TRACEx2(5, "xfer %d sectors from 0x%p", buff->sector_count, buff->ptr);
840 } else {
841 TRACE(-1, "bug: illegal operation parameter");
842 TRACE_EXIT;
843 return -EIO;
844 }
845
846
847 save_flags(flags);
848 cli();
849 disable_dma(fdc.dma);
850 clear_dma_ff(fdc.dma);
851 set_dma_mode(fdc.dma, dma_mode);
852 set_dma_addr(fdc.dma, (unsigned) buff->ptr);
853 set_dma_count(fdc.dma, SECTOR_SIZE * buff->sector_count);
854 #ifdef GCC_2_4_5_BUG
855
856
857
858 if (1) {
859 int i;
860
861 for (i = 0; i < 1; ++i) {
862 udelay(1);
863 }
864 }
865 #endif
866 enable_dma(fdc.dma);
867
868
869 out[0] = operation;
870 out[1] = FTAPE_UNIT;
871 out[2] = buff->cyl;
872 out[3] = buff->head;
873 out[4] = buff->sect + buff->sector_offset;
874 out[5] = 3;
875 out[6] = out[4] + buff->sector_count - 1;
876 out[7] = 109;
877 out[8] = 0xff;
878 restore_flags(flags);
879 TRACEx4(6, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",
880 out[2], out[3], out[4], out[6] - out[4] + 1);
881 result = fdc_command(out, 9);
882 if (result != 0) {
883 fdc_mode = fdc_idle;
884 TRACE(1, "fdc_command failed");
885 }
886 fdc_setup_error = result;
887 TRACE_EXIT;
888 return result;
889 }
890
891 int fdc_fifo_enable(void)
892 {
893 TRACE_FUN(8, "fdc_fifo_enable");
894 int result = 0;
895 byte cmd0[] = {FDC_DUMPREGS};
896 byte cmd1[] = {FDC_CONFIGURE, 0, 0x07, 0};
897 byte cmd2[] = {FDC_LOCK};
898 byte cmd3[] = {FDC_UNLOCK};
899 byte stat;
900 byte reg[10];
901 int i;
902
903 if (CLK_48MHZ && fdc.type >= i82078)
904 cmd1[0] |= FDC_CLK48_BIT;
905 if (!fdc_fifo_locked) {
906
907
908 result = fdc_command(cmd0, NR_ITEMS(cmd0));
909 if (result < 0) {
910 TRACE(2, "FDC dumpreg command failed, fifo unchanged");
911 result = -EIO;
912 } else {
913
914
915 for (i = 0; i < NR_ITEMS(reg); ++i) {
916 fdc_read(®[i]);
917 TRACEx2(6, "Register %d = 0x%02x", i, reg[i]);
918 }
919 fdc_fifo_state = (reg[8] & 0x20) == 0;
920 fdc_lock_state = reg[7] & 0x80;
921 fdc_fifo_thr = 1 + (reg[8] & 0x0f);
922 TRACEx3(5, "original fifo state: %sabled, thresshold %d, %slocked",
923 (fdc_fifo_state) ? "en" : "dis",
924 fdc_fifo_thr, (fdc_lock_state) ? "" : "not ");
925
926
927 if (fdc_lock_state) {
928 fdc_ready_wait(100);
929 result = fdc_command(cmd3, NR_ITEMS(cmd3));
930 if (result < 0) {
931 TRACE(-1, "FDC unlock command failed, configuration unchanged");
932 result = -EIO;
933 }
934 }
935
936
937
938 fdc_ready_wait(100);
939 result = fdc_command(cmd1, NR_ITEMS(cmd1));
940 if (result < 0) {
941 TRACE(-1, "FDC configure command failed, fifo unchanged");
942 result = -EIO;
943 } else {
944
945
946 result = fdc_issue_command(cmd2, NR_ITEMS(cmd2), &stat, 1);
947 if (result < 0 || stat != 0x10) {
948 TRACEx1(-1, "FDC lock command failed, stat = 0x%02x", stat);
949 result = -EIO;
950 } else {
951 fdc_fifo_locked = 1;
952 result = 0;
953 }
954 }
955 }
956 } else {
957 TRACE(2, "Fifo not enabled because locked");
958 }
959 TRACE_EXIT;
960 return result;
961 }
962
963
964
965 static byte fdc_save_state[2] = {0, 0};
966
967 int fdc_probe(void)
968 {
969 TRACE_FUN(8, "fdc_probe");
970 byte cmd[1];
971 byte stat[16];
972 int result;
973
974
975
976
977
978
979
980
981
982 cmd[0] = FDC_DUMPREGS;
983 result = fdc_issue_command(cmd, 1, stat, 1);
984 if (result == 0) {
985 if (stat[0] == 0x80) {
986
987
988 TRACE(2, "Type 8272A/765A compatible FDC found");
989 result = i8272;
990 } else {
991 fdc_result(&stat[1], 9);
992 fdc_save_state[0] = stat[7];
993 fdc_save_state[1] = stat[8];
994 cmd[0] = FDC_VERSION;
995 result = fdc_issue_command(cmd, 1, stat, 1);
996 if (result < 0 || stat[0] == 0x80) {
997 TRACE(2, "Type 82072 FDC found");
998 result = i8272;
999 } else if (*stat == 0x90) {
1000 cmd[0] = FDC_UNLOCK;
1001 result = fdc_issue_command(cmd, 1, stat, 1);
1002 if (result < 0 || stat[0] != 0x00) {
1003 TRACE(2, "Type pre-1991 82077 FDC found, treating it like a 82072");
1004 result = i8272;
1005 } else {
1006 int i;
1007
1008 if (fdc_save_state[0] & 0x80) {
1009 cmd[0] = FDC_LOCK;
1010 result = fdc_issue_command(cmd, 1, stat, 1);
1011 TRACE(2, "FDC is already locked");
1012 }
1013
1014 cmd[0] = FDC_PARTID;
1015 result = fdc_issue_command(cmd, 1, stat, 1);
1016 if (result < 0 || stat[0] == 0x80) {
1017
1018 result = no_fdc;
1019 for (i = 0; i < 4; ++i) {
1020 outb_p(i, fdc.tdr);
1021 if ((inb_p(fdc.tdr) & 0x03) != i) {
1022 result = i82077;
1023 break;
1024 }
1025 }
1026 if (result == no_fdc) {
1027 result = i82077AA;
1028 TRACE(2, "Type 82077AA FDC found");
1029 } else {
1030 TRACE(2, "Type 82077 FDC found");
1031 }
1032 } else {
1033
1034 switch (stat[0] >> 5) {
1035 case 0x0:
1036
1037
1038
1039
1040
1041
1042
1043 cmd[0] = FDC_SAVE;
1044 result = fdc_issue_command(cmd, 1, stat, 16);
1045 if (result < 0) {
1046 TRACE(1, "FDC_SAVE failed. Dunno why");
1047
1048 result = i82078;
1049 TRACE(2, "Type i82078 FDC (i suppose) found");
1050 } else {
1051 if ((stat[0] & FDC_SEL3V_BIT)) {
1052
1053
1054 TRACE(2, "Type i82078-1 or 5Volt i82078SL FDC found");
1055 TRACE(2, "Treating it as an i82078-1 (2Mbps) FDC");
1056 result = i82078_1;
1057 } else {
1058 TRACE(2, "Type 3Volt i82078SL FDC (1Mbps) found");
1059 result = i82078;
1060 }
1061 }
1062 break;
1063 case 0x1:
1064 case 0x2:
1065
1066 result = i82078;
1067 TRACE(2, "Type i82078 FDC found");
1068 break;
1069 case 0x3:
1070 result = i82077AA;
1071 TRACE(2, "Type 82077AA compatible FDC found");
1072 break;
1073 default:
1074 TRACE(2, "A previously undetected FDC found");
1075 TRACEi(2, "Treating it as a 82077AA. Please report partid=",
1076 stat[0]);
1077 result = i82077AA;
1078 }
1079 }
1080 }
1081 } else {
1082 TRACE(2, "Unknown FDC found");
1083 result = i8272;
1084 }
1085 }
1086 } else {
1087 TRACE(-1, "No FDC found");
1088 result = no_fdc;
1089 }
1090 TRACE_EXIT;
1091 return result;
1092 }
1093
1094 void fdc_config_regs(unsigned fdc_base, unsigned fdc_irq, unsigned fdc_dma)
1095 {
1096 fdc.irq = fdc_irq;
1097 fdc.dma = fdc_dma;
1098 fdc.sra = fdc_base;
1099 fdc.srb = fdc_base + 1;
1100 fdc.dor = fdc_base + 2;
1101 fdc.tdr = fdc_base + 3;
1102 fdc.msr = fdc.dsr = fdc_base + 4;
1103 fdc.fifo = fdc_base + 5;
1104 #if defined MACH2 || defined PROBE_FC10
1105 fdc.dor2 = fdc_base + 6;
1106 #endif
1107 fdc.dir = fdc.ccr = fdc_base + 7;
1108 }
1109
1110
1111
1112
1113
1114
1115 #if defined PROBE_FC10 && !defined FDC_BASE
1116 #error No FDC base address (FDC_BASE) specified in Makefile!
1117 #endif
1118 #if defined FDC_BASE && !defined FDC_IRQ
1119 #error No interrupt (FDC_IRQ) specified in Makefile!
1120 #endif
1121 #if defined FDC_BASE && !defined FDC_DMA
1122 #error No dma channel (FDC_DMA) specified in Makefile!
1123 #endif
1124
1125 void fdc_config(void)
1126 {
1127 TRACE_FUN(8, "fdc_config");
1128 static int already_done = 0;
1129
1130 if (!already_done) {
1131 #ifdef PROBE_FC10
1132 int fc_type;
1133
1134 fdc_config_regs(FDC_BASE, FDC_IRQ, FDC_DMA);
1135 fc_type = fc10_enable();
1136 if (fc_type != 0) {
1137 TRACEx1(2, "FC-%c0 controller found", '0' + fc_type);
1138 fdc.type = fc10;
1139 fdc.hook = &do_ftape;
1140 } else {
1141 TRACE(2, "FC-10/20 controller not found");
1142 fdc.type = no_fdc;
1143 fdc.dor2 = 0;
1144 fdc_config_regs(0x3f0, 6, 2);
1145 fdc.hook = &do_ftape;
1146 }
1147 #else
1148 #ifdef FDC_BASE
1149 TRACE(2, "Using fdc controller at alternate address");
1150 fdc_config_regs(FDC_BASE, FDC_IRQ, FDC_DMA);
1151 fdc.hook = &do_ftape;
1152 #else
1153 TRACE(2, "Using the standard fdc controller");
1154 fdc_config_regs(0x3f0, 6, 2);
1155 fdc.hook = &do_ftape;
1156 #endif
1157 #endif
1158 }
1159 *(fdc.hook) = fdc_isr;
1160 already_done = 1;
1161 TRACE_EXIT;
1162 }
1163
1164 static void ftape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1165 {
1166 TRACE_FUN(8, "ftape_interrupt");
1167 void (*handler) (void) = *fdc.hook;
1168
1169 *fdc.hook = NULL;
1170 if (handler) {
1171 handler();
1172 } else {
1173 TRACE(-1, "Unexpected ftape interrupt");
1174 }
1175 TRACE_EXIT;
1176 }
1177
1178 int fdc_grab_irq_and_dma(void)
1179 {
1180 TRACE_FUN(8, "fdc_grab_irq_and_dma");
1181 int result = 0;
1182 static char ftape_id[] = "ftape";
1183
1184 if (fdc.hook == &do_ftape) {
1185
1186
1187 result = request_irq(fdc.irq, ftape_interrupt, SA_INTERRUPT,
1188 "ftape", ftape_id);
1189 if (result) {
1190 TRACEx1(-1, "Unable to grab IRQ%d for ftape driver", fdc.irq);
1191 result = -EIO;
1192 } else {
1193 result = request_dma(fdc.dma, ftape_id);
1194 if (result) {
1195 TRACEx1(-1, "Unable to grab DMA%d for ftape driver", fdc.dma);
1196 free_irq(fdc.irq, NULL);
1197 result = -EIO;
1198 } else {
1199 enable_irq(fdc.irq);
1200 }
1201 }
1202 }
1203 #ifdef FDC_DMA
1204 if (result == 0 && FDC_DMA == 2) {
1205
1206
1207
1208
1209
1210 outb_p(FDC_RESET_NOT, 0x3f2);
1211 TRACE(2, "DMA-gate on standard fdc disabled");
1212 }
1213 #endif
1214 TRACE_EXIT;
1215 return result;
1216 }
1217
1218 int fdc_release_irq_and_dma(void)
1219 {
1220 TRACE_FUN(8, "fdc_grab_irq_and_dma");
1221 int result = 0;
1222
1223 if (fdc.hook == &do_ftape) {
1224 disable_dma(fdc.dma);
1225 free_dma(fdc.dma);
1226 disable_irq(fdc.irq);
1227 free_irq(fdc.irq, NULL);
1228 }
1229 #ifdef FDC_DMA
1230 if (result == 0 && FDC_DMA == 2) {
1231
1232
1233
1234
1235
1236 outb_p(FDC_RESET_NOT | FDC_DMA_MODE, 0x3f2);
1237 TRACE(2, "DMA-gate on standard fdc enabled again");
1238 }
1239 #endif
1240 TRACE_EXIT;
1241 return result;
1242 }
1243
1244 int fdc_uninit(void)
1245 {
1246 TRACE_FUN(8, "fdc_uninit");
1247 int result = 0;
1248
1249 if (fdc.sra != 0) {
1250 if (fdc.dor2 == 0) {
1251 release_region(fdc.sra, 6);
1252 release_region(fdc.sra + 7, 1);
1253 } else {
1254 release_region(fdc.sra, 8);
1255 }
1256 }
1257 TRACE_EXIT;
1258 return result;
1259 }
1260
1261 int fdc_init(void)
1262 {
1263 TRACE_FUN(8, "fdc_init");
1264 int result = 0;
1265
1266 fdc_config();
1267 if (fdc_grab_irq_and_dma() < 0) {
1268 result = -EBUSY;
1269 } else {
1270 ftape_motor = 0;
1271 fdc_catch_stray_interrupts(1);
1272 TRACE(5, "resetting fdc");
1273 fdc_reset();
1274 if (fdc.type == no_fdc) {
1275 fdc.type = fdc_probe();
1276 }
1277 if (fdc.type != no_fdc) {
1278 if (fdc.type >= i82077) {
1279 if (fdc_fifo_enable() < 0) {
1280 TRACE(2, "couldn't enable fdc fifo !");
1281 } else {
1282 TRACE(5, "fdc fifo enabled and locked");
1283 }
1284 }
1285 } else {
1286 fdc_release_irq_and_dma();
1287 result = -EIO;
1288 }
1289 }
1290 if (result >= 0) {
1291 if (fdc.dor2 == 0) {
1292 request_region(fdc.sra, 6, "fdc (ftape)");
1293 request_region(fdc.sra + 7, 1, "fdc (ftape)");
1294 } else {
1295 request_region(fdc.sra, 8, "fdc (ftape)");
1296 }
1297 }
1298 TRACE_EXIT;
1299 return result;
1300 }