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