1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127#include <linux/sched.h>
128#include <linux/fs.h>
129#include <linux/fcntl.h>
130#include <linux/slab.h>
131#include <linux/kernel.h>
132#include <linux/interrupt.h>
133#include <linux/timer.h>
134#include <linux/tqueue.h>
135#include <linux/fd.h>
136#include <linux/fd1772.h>
137#include <linux/errno.h>
138#include <linux/types.h>
139#include <linux/delay.h>
140#include <linux/mm.h>
141
142#include <asm/arch/oldlatches.h>
143#include <asm/bitops.h>
144#include <asm/dma.h>
145#include <asm/hardware.h>
146#include <asm/hardware/ioc.h>
147#include <asm/io.h>
148#include <asm/irq.h>
149#include <asm/mach-types.h>
150#include <asm/pgtable.h>
151#include <asm/system.h>
152#include <asm/uaccess.h>
153
154
155#define MAJOR_NR FLOPPY_MAJOR
156#define FLOPPY_DMA 0
157#include <linux/blk.h>
158
159
160
161
162
163
164#if 0
165#undef FD_MAX_UNITS
166#define FD_MAX_UNITS 2
167#endif
168
169
170#define FD_MAX_UNITS 4
171#define TRACKBUFFER 0
172
173
174#ifdef DEBUG
175#define DPRINT(a) printk a
176#else
177#define DPRINT(a)
178#endif
179
180
181static struct archy_disk_type {
182 const char *name;
183 unsigned spt;
184 unsigned blocks;
185 unsigned stretch;
186} disk_type[] = {
187
188 { "d360", 9, 720, 0 },
189 { "D360", 9, 720, 1 },
190 { "D720", 9, 1440, 0 },
191
192
193
194};
195
196#define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
197
198
199
200
201
202#define MAX_DISK_SIZE 720
203
204static int floppy_sizes[256];
205static int floppy_blocksizes[256];
206
207
208static struct archy_floppy_struct {
209 int connected;
210 int autoprobe;
211
212 struct archy_disk_type *disktype;
213
214 int track;
215
216 unsigned int steprate;
217 unsigned int wpstat;
218
219} unit[FD_MAX_UNITS];
220
221
222
223extern void fdc1772_comendhandler(void);
224extern volatile int fdc1772_comendstatus;
225extern volatile int fdc1772_fdc_int_done;
226
227#define FDC1772BASE ((0x210000>>2)|0x80000000)
228
229#define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
230
231
232
233
234
235
236
237void FDC1772_WRITE(int reg, unsigned char val)
238{
239 if (reg == FDC1772REG_CMD) {
240 DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
241 if (fdc1772_fdc_int_done) {
242 DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
243 fdc1772_fdc_int_done = 0;
244 };
245 };
246 outb(val, (reg / 2) + FDC1772BASE);
247};
248
249#define FD1772_MAX_SECTORS 22
250
251unsigned char *DMABuffer;
252
253
254#define PhysDMABuffer DMABuffer
255
256#ifdef TRACKBUFFER
257unsigned char *TrackBuffer;
258#define PhysTrackBuffer TrackBuffer
259static int BufferDrive, BufferSide, BufferTrack;
260static int read_track;
261
262#define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512)
263#define IS_BUFFERED(drive,side,track) \
264 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
265#endif
266
267
268
269
270
271
272static int SelectedDrive = 0;
273static int ReqCmd, ReqBlock;
274static int ReqSide, ReqTrack, ReqSector, ReqCnt;
275static int HeadSettleFlag = 0;
276static unsigned char *ReqData, *ReqBuffer;
277static int MotorOn = 0, MotorOffTrys;
278
279
280static volatile int fdc_busy = 0;
281static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
282
283
284
285static unsigned long changed_floppies = 0xff, fake_change = 0;
286#define CHECK_CHANGE_DELAY HZ/2
287
288
289#define FD_MOTOR_OFF_DELAY (10*HZ)
290#define FD_MOTOR_OFF_MAXTRY (10*20)
291
292#define FLOPPY_TIMEOUT (6*HZ)
293#define RECALIBRATE_ERRORS 4
294
295#define MAX_ERRORS 8
296
297
298#define START_MOTOR_OFF_TIMER(delay) \
299 do { \
300 motor_off_timer.expires = jiffies + (delay); \
301 add_timer( &motor_off_timer ); \
302 MotorOffTrys = 0; \
303 } while(0)
304
305#define START_CHECK_CHANGE_TIMER(delay) \
306 do { \
307 mod_timer(&fd_timer, jiffies + (delay)); \
308 } while(0)
309
310#define START_TIMEOUT() \
311 do { \
312 mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \
313 } while(0)
314
315#define STOP_TIMEOUT() \
316 do { \
317 del_timer( &timeout_timer ); \
318 } while(0)
319
320#define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
321
322#define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
323
324static void fd1772_checkint(void);
325
326struct tq_struct fd1772_tq =
327{ 0,0, (void *)fd1772_checkint, 0 };
328
329
330
331
332
333static int Probing = 0;
334
335
336
337
338static int NeedSeek = 0;
339
340
341
342
343static void fd_select_side(int side);
344static void fd_select_drive(int drive);
345static void fd_deselect(void);
346static void fd_motor_off_timer(unsigned long dummy);
347static void check_change(unsigned long dummy);
348static __inline__ void set_head_settle_flag(void);
349static __inline__ int get_head_settle_flag(void);
350static void floppy_irqconsequencehandler(void);
351static void fd_error(void);
352static void do_fd_action(int drive);
353static void fd_calibrate(void);
354static void fd_calibrate_done(int status);
355static void fd_seek(void);
356static void fd_seek_done(int status);
357static void fd_rwsec(void);
358#ifdef TRACKBUFFER
359static void fd_readtrack_check( unsigned long dummy );
360#endif
361static void fd_rwsec_done(int status);
362static void fd_times_out(unsigned long dummy);
363static void finish_fdc(void);
364static void finish_fdc_done(int dummy);
365static void floppy_off(unsigned int nr);
366static __inline__ void copy_buffer(void *from, void *to);
367static void setup_req_params(int drive);
368static void redo_fd_request(void);
369static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
370 cmd, unsigned long param);
371static void fd_probe(int drive);
372static int fd_test_drive_present(int drive);
373static void config_types(void);
374static int floppy_open(struct inode *inode, struct file *filp);
375static int floppy_release(struct inode *inode, struct file *filp);
376
377
378
379static struct timer_list motor_off_timer = {
380 function: fd_motor_off_timer,
381};
382
383#ifdef TRACKBUFFER
384static struct timer_list readtrack_timer = {
385 function: fd_readtrack_check,
386};
387#endif
388
389static struct timer_list timeout_timer = {
390 function: fd_times_out,
391};
392
393static struct timer_list fd_timer = {
394 function: check_change,
395};
396
397
398int stdma_islocked(void)
399{
400 return 0;
401};
402
403
404
405static void fd_select_side(int side)
406{
407 oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
408}
409
410
411
412
413
414static void fd_select_drive(int drive)
415{
416#ifdef DEBUG
417 printk("fd_select_drive:%d\n", drive);
418#endif
419
420 oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
421
422 if (drive == SelectedDrive)
423 return;
424
425 oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
426
427
428 FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
429 udelay(25);
430
431 SelectedDrive = drive;
432}
433
434
435
436
437static void fd_deselect(void)
438{
439 unsigned long flags;
440
441 DPRINT(("fd_deselect\n"));
442
443 oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
444
445 SelectedDrive = -1;
446}
447
448
449
450
451
452
453
454static void fd_motor_off_timer(unsigned long dummy)
455{
456 unsigned long flags;
457 unsigned char status;
458 int delay;
459
460 del_timer(&motor_off_timer);
461
462 if (SelectedDrive < 0)
463
464 return;
465
466 save_flags(flags);
467 cli();
468
469 if (fdc_busy)
470 goto retry;
471
472 status = FDC1772_READ(FDC1772REG_STATUS);
473
474 if (!(status & 0x80)) {
475
476
477
478
479
480
481 DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
482 fd_deselect();
483 MotorOn = 0;
484 restore_flags(flags);
485 return;
486 }
487
488
489retry:
490 restore_flags(flags);
491
492
493
494
495
496 delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
497 (++MotorOffTrys, HZ / 20) : HZ / 2;
498 START_MOTOR_OFF_TIMER(delay);
499}
500
501
502
503
504
505
506static void check_change(unsigned long dummy)
507{
508 static int drive = 0;
509
510 unsigned long flags;
511 int stat;
512
513 if (fdc_busy)
514 return;
515
516 return;
517
518 if (++drive > 1 || !unit[drive].connected)
519 drive = 0;
520
521 save_flags(flags);
522 cli();
523
524 if (!stdma_islocked()) {
525 stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
526
527
528
529 if (stat != unit[drive].wpstat) {
530 DPRINT(("wpstat[%d] = %d\n", drive, stat));
531 unit[drive].wpstat = stat;
532 set_bit(drive, &changed_floppies);
533 }
534 }
535 restore_flags(flags);
536
537 START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
538}
539
540
541
542
543
544
545static __inline__ void set_head_settle_flag(void)
546{
547 HeadSettleFlag = FDC1772CMDADD_E;
548}
549
550static __inline__ int get_head_settle_flag(void)
551{
552 int tmp = HeadSettleFlag;
553 HeadSettleFlag = 0;
554 return (tmp);
555}
556
557
558
559
560
561
562static void (*FloppyIRQHandler) (int status) = NULL;
563
564static void floppy_irqconsequencehandler(void)
565{
566 unsigned char status;
567 void (*handler) (int);
568
569 fdc1772_fdc_int_done = 0;
570
571 handler = FloppyIRQHandler;
572 FloppyIRQHandler = NULL;
573
574 if (handler) {
575 nop();
576 status = (unsigned char) fdc1772_comendstatus;
577 DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
578 handler(status);
579 } else {
580 DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
581 }
582 DPRINT(("FDC1772 irq: end of floppy_irq\n"));
583}
584
585
586
587
588
589
590static void fd_error(void)
591{
592 printk("FDC1772: fd_error\n");
593
594 if (QUEUE_EMPTY)
595 return;
596 CURRENT->errors++;
597 if (CURRENT->errors >= MAX_ERRORS) {
598 printk("fd%d: too many errors.\n", SelectedDrive);
599 end_request(0);
600 } else if (CURRENT->errors == RECALIBRATE_ERRORS) {
601 printk("fd%d: recalibrating\n", SelectedDrive);
602 if (SelectedDrive != -1)
603 unit[SelectedDrive].track = -1;
604 }
605 redo_fd_request();
606}
607
608
609
610#define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
611
612
613
614
615
616
617
618
619
620
621
622static void do_fd_action(int drive)
623{
624 DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
625
626#ifdef TRACKBUFFER
627repeat:
628
629 if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
630 if (ReqCmd == READ) {
631 copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
632 if (++ReqCnt < CURRENT->current_nr_sectors) {
633
634 setup_req_params( drive );
635 goto repeat;
636 } else {
637
638 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
639 CURRENT->sector += CURRENT->current_nr_sectors;
640 end_request( 1 );
641 redo_fd_request();
642 return;
643 }
644 } else {
645
646
647 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
648 }
649 }
650#endif
651
652 if (SelectedDrive != drive) {
653
654 fd_select_drive(drive);
655 };
656
657
658 if (unit[drive].track == -1)
659 fd_calibrate();
660 else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
661 fd_seek();
662 else
663 fd_rwsec();
664}
665
666
667
668
669static void fd_calibrate(void)
670{
671 DPRINT(("fd_calibrate\n"));
672 if (unit[SelectedDrive].track >= 0) {
673 fd_calibrate_done(0);
674 return;
675 }
676 DPRINT(("fd_calibrate (after track compare)\n"));
677 SET_IRQ_HANDLER(fd_calibrate_done);
678
679 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
680
681 NeedSeek = 1;
682 MotorOn = 1;
683 START_TIMEOUT();
684
685}
686
687
688static void fd_calibrate_done(int status)
689{
690 DPRINT(("fd_calibrate_done()\n"));
691 STOP_TIMEOUT();
692
693
694 if (status & FDC1772STAT_RECNF) {
695 printk("fd%d: restore failed\n", SelectedDrive);
696 fd_error();
697 } else {
698 unit[SelectedDrive].track = 0;
699 fd_seek();
700 }
701}
702
703
704
705
706
707
708static void fd_seek(void)
709{
710 unsigned long flags;
711 DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
712 unit[SelectedDrive].track));
713 if (unit[SelectedDrive].track == ReqTrack <<
714 unit[SelectedDrive].disktype->stretch) {
715 fd_seek_done(0);
716 return;
717 }
718 FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
719 unit[SelectedDrive].disktype->stretch);
720 udelay(25);
721 save_flags(flags);
722 clf();
723 SET_IRQ_HANDLER(fd_seek_done);
724 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
725
726 (MotorOn?FDC1772CMDADD_H:0));
727
728 restore_flags(flags);
729 MotorOn = 1;
730 set_head_settle_flag();
731 START_TIMEOUT();
732
733}
734
735
736static void fd_seek_done(int status)
737{
738 DPRINT(("fd_seek_done()\n"));
739 STOP_TIMEOUT();
740
741
742 if (status & FDC1772STAT_RECNF) {
743 printk("fd%d: seek error (to track %d)\n",
744 SelectedDrive, ReqTrack);
745
746 unit[SelectedDrive].track = -1;
747 fd_error();
748 } else {
749 unit[SelectedDrive].track = ReqTrack <<
750 unit[SelectedDrive].disktype->stretch;
751 NeedSeek = 0;
752 fd_rwsec();
753 }
754}
755
756
757
758
759
760
761#ifdef TRACKBUFFER
762static int MultReadInProgress = 0;
763#endif
764
765
766static void fd_rwsec(void)
767{
768 unsigned long paddr, flags;
769 unsigned int rwflag, old_motoron;
770 unsigned int track;
771
772 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
773 if (ReqCmd == WRITE) {
774
775 paddr = (unsigned long) ReqData;
776 rwflag = 0x100;
777 } else {
778 paddr = (unsigned long) PhysDMABuffer;
779#ifdef TRACKBUFFER
780 if (read_track)
781 paddr = (unsigned long)PhysTrackBuffer;
782#endif
783 rwflag = 0;
784 }
785
786 DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
787 ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
788 fd_select_side(ReqSide);
789
790
791
792#ifdef TRACKBUFFER
793 FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
794#else
795 FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
796#endif
797
798
799 if (unit[SelectedDrive].disktype->stretch) {
800 track = FDC1772_READ(FDC1772REG_TRACK);
801 FDC1772_WRITE(FDC1772REG_TRACK, track >>
802 unit[SelectedDrive].disktype->stretch);
803 }
804 udelay(25);
805
806 DPRINT(("fd_rwsec() before setup DMA \n"));
807
808 save_flags(flags);
809 clf();
810 disable_dma(FLOPPY_DMA);
811 set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
812 set_dma_addr(FLOPPY_DMA, (long) paddr);
813#ifdef TRACKBUFFER
814 set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
815#else
816 set_dma_count(FLOPPY_DMA, 512);
817#endif
818 SET_IRQ_HANDLER(fd_rwsec_done);
819
820 enable_dma(FLOPPY_DMA);
821
822 FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) :
823#ifdef TRACKBUFFER
824 (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
825
826
827 (MotorOn?FDC1772CMDADD_H:0))
828#else
829 FDC1772CMD_RDSEC
830#endif
831 ));
832
833 restore_flags(flags);
834 DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
835
836
837 old_motoron = MotorOn;
838 MotorOn = 1;
839 NeedSeek = 1;
840
841
842
843#ifdef TRACKBUFFER
844 if (read_track) {
845
846
847
848
849
850
851
852 mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ));
853 DPRINT(("Setting readtrack_timer to %d @ %d\n",
854 readtrack_timer.expires,jiffies));
855 MultReadInProgress = 1;
856 }
857#endif
858
859
860 START_TIMEOUT();
861
862}
863
864
865#ifdef TRACKBUFFER
866
867static void fd_readtrack_check(unsigned long dummy)
868{
869 unsigned long flags, addr;
870 extern unsigned char *fdc1772_dataaddr;
871
872 DPRINT(("fd_readtrack_check @ %d\n",jiffies));
873
874 save_flags(flags);
875 clf();
876
877 del_timer( &readtrack_timer );
878
879 if (!MultReadInProgress) {
880
881
882
883
884
885
886 restore_flags(flags);
887 return;
888 }
889
890
891 addr=(unsigned long)fdc1772_dataaddr;
892 DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
893
894 if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
895
896
897
898 SET_IRQ_HANDLER( NULL );
899 restore_flags(flags);
900 DPRINT(("fd_readtrack_check(): done\n"));
901 FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
902 udelay(25);
903
904
905
906
907 fd_rwsec_done( 0 );
908 } else {
909
910 restore_flags(flags);
911 DPRINT(("fd_readtrack_check(): not yet finished\n"));
912 readtrack_timer.expires = jiffies + HZ/5/10;
913 add_timer( &readtrack_timer );
914 }
915}
916
917#endif
918
919static void fd_rwsec_done(int status)
920{
921 unsigned int track;
922
923 DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
924
925#ifdef TRACKBUFFER
926 if (read_track && !MultReadInProgress)
927 return;
928
929 MultReadInProgress = 0;
930
931 STOP_TIMEOUT();
932
933 if (read_track)
934 del_timer( &readtrack_timer );
935#endif
936
937
938
939 if (unit[SelectedDrive].disktype->stretch) {
940 track = FDC1772_READ(FDC1772REG_TRACK);
941 FDC1772_WRITE(FDC1772REG_TRACK, track <<
942 unit[SelectedDrive].disktype->stretch);
943 }
944 if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
945 printk("fd%d: is write protected\n", SelectedDrive);
946 goto err_end;
947 }
948 if ((status & FDC1772STAT_RECNF)
949#ifdef TRACKBUFFER
950
951
952
953 && !(read_track &&
954 FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
955#endif
956 ) {
957 if (Probing) {
958 if (unit[SelectedDrive].disktype > disk_type) {
959
960 unit[SelectedDrive].disktype--;
961 floppy_sizes[SelectedDrive]
962 = unit[SelectedDrive].disktype->blocks >> 1;
963 } else
964 Probing = 0;
965 } else {
966
967 if (unit[SelectedDrive].autoprobe) {
968 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
969 floppy_sizes[SelectedDrive]
970 = unit[SelectedDrive].disktype->blocks >> 1;
971 Probing = 1;
972 }
973 }
974 if (Probing) {
975 setup_req_params(SelectedDrive);
976#ifdef TRACKBUFFER
977 BufferDrive = -1;
978#endif
979 do_fd_action(SelectedDrive);
980 return;
981 }
982 printk("fd%d: sector %d not found (side %d, track %d)\n",
983 SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
984 goto err_end;
985 }
986 if (status & FDC1772STAT_CRC) {
987 printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
988 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
989 goto err_end;
990 }
991 if (status & FDC1772STAT_LOST) {
992 printk("fd%d: lost data (side %d, track %d, sector %d)\n",
993 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
994 goto err_end;
995 }
996 Probing = 0;
997
998 if (ReqCmd == READ) {
999#ifdef TRACKBUFFER
1000 if (!read_track) {
1001
1002 copy_buffer (DMABuffer, ReqData);
1003 } else {
1004
1005 BufferDrive = SelectedDrive;
1006 BufferSide = ReqSide;
1007 BufferTrack = ReqTrack;
1008 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1009 }
1010#else
1011
1012 copy_buffer(DMABuffer, ReqData);
1013#endif
1014 }
1015 if (++ReqCnt < CURRENT->current_nr_sectors) {
1016
1017 setup_req_params(SelectedDrive);
1018 do_fd_action(SelectedDrive);
1019 } else {
1020
1021 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1022 CURRENT->sector += CURRENT->current_nr_sectors;
1023 end_request(1);
1024 redo_fd_request();
1025 }
1026 return;
1027
1028err_end:
1029#ifdef TRACKBUFFER
1030 BufferDrive = -1;
1031#endif
1032
1033 fd_error();
1034}
1035
1036
1037static void fd_times_out(unsigned long dummy)
1038{
1039 SET_IRQ_HANDLER(NULL);
1040
1041
1042 del_timer( &readtrack_timer );
1043 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1044 udelay(25);
1045
1046 printk("floppy timeout\n");
1047 STOP_TIMEOUT();
1048 fd_error();
1049}
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059static void finish_fdc(void)
1060{
1061
1062 finish_fdc_done(0);
1063 return;
1064
1065 if (!NeedSeek) {
1066 finish_fdc_done(0);
1067 } else {
1068 DPRINT(("finish_fdc: dummy seek started\n"));
1069 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1070 SET_IRQ_HANDLER(finish_fdc_done);
1071 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1072 MotorOn = 1;
1073 START_TIMEOUT();
1074
1075
1076
1077
1078 }
1079}
1080
1081
1082static void finish_fdc_done(int dummy)
1083{
1084 unsigned long flags;
1085
1086 DPRINT(("finish_fdc_done entered\n"));
1087 STOP_TIMEOUT();
1088 NeedSeek = 0;
1089
1090 if (timer_pending(&fd_timer) &&
1091 time_after(jiffies + 5, fd_timer.expires))
1092
1093
1094
1095 mod_timer(&fd_timer, jiffies + 5);
1096 else {
1097
1098 };
1099 del_timer(&motor_off_timer);
1100 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1101
1102 save_flags(flags);
1103 cli();
1104
1105 fdc_busy = 0;
1106 wake_up(&fdc_wait);
1107 restore_flags(flags);
1108
1109 DPRINT(("finish_fdc() finished\n"));
1110}
1111
1112
1113
1114static int fd_ref[4];
1115static int fd_device[4];
1116
1117
1118
1119
1120
1121#define CURRENT_DEVICE (CURRENT->rq_dev)
1122
1123
1124#define CURRENT_ERRORS (CURRENT->errors)
1125
1126
1127
1128static void floppy_off(unsigned int nr)
1129{
1130}
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144static int check_floppy_change(dev_t dev)
1145{
1146 unsigned int drive = (dev & 0x03);
1147
1148 if (MAJOR(dev) != MAJOR_NR) {
1149 printk("floppy_changed: not a floppy\n");
1150 return 0;
1151 }
1152 if (test_bit(drive, &fake_change)) {
1153
1154 return 1;
1155 }
1156 if (test_bit(drive, &changed_floppies)) {
1157
1158 return 1;
1159 }
1160 if (unit[drive].wpstat) {
1161
1162
1163
1164 return 1;
1165 }
1166 return 1;
1167}
1168
1169static int floppy_revalidate(dev_t dev)
1170{
1171 int drive = dev & 3;
1172
1173 if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1174 || unit[drive].disktype == 0) {
1175#ifdef TRACKBUFFER
1176 BufferDrive = -1;
1177#endif
1178 clear_bit(drive, &fake_change);
1179 clear_bit(drive, &changed_floppies);
1180 unit[drive].disktype = 0;
1181 }
1182 return 0;
1183}
1184
1185static __inline__ void copy_buffer(void *from, void *to)
1186{
1187 ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
1188 int cnt;
1189
1190 for (cnt = 512 / 4; cnt; cnt--)
1191 *p2++ = *p1++;
1192}
1193
1194
1195
1196
1197static void setup_req_params(int drive)
1198{
1199 int block = ReqBlock + ReqCnt;
1200
1201 ReqTrack = block / unit[drive].disktype->spt;
1202 ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1203 ReqSide = ReqTrack & 1;
1204 ReqTrack >>= 1;
1205 ReqData = ReqBuffer + 512 * ReqCnt;
1206
1207#ifdef TRACKBUFFER
1208 read_track = (ReqCmd == READ && CURRENT_ERRORS == 0);
1209#endif
1210
1211 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1212 ReqTrack, ReqSector, (unsigned long) ReqData));
1213}
1214
1215
1216static void redo_fd_request(void)
1217{
1218 int device, drive, type;
1219 struct archy_floppy_struct *floppy;
1220
1221 DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n",
1222 (unsigned long) CURRENT, CURRENT ? CURRENT->rq_dev : 0,
1223 !QUEUE_EMPTY ? CURRENT->sector : 0));
1224
1225 if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE)
1226 goto the_end;
1227
1228repeat:
1229
1230 if (QUEUE_EMPTY)
1231 goto the_end;
1232
1233 if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
1234 panic(DEVICE_NAME ": request list destroyed");
1235
1236 if (CURRENT->bh) {
1237 if (!buffer_locked(CURRENT->bh))
1238 panic(DEVICE_NAME ": block not locked");
1239 }
1240 device = MINOR(CURRENT_DEVICE);
1241 drive = device & 3;
1242 type = device >> 2;
1243 floppy = &unit[drive];
1244
1245 if (!floppy->connected) {
1246
1247 printk("Unknown Device: fd%d\n", drive);
1248 end_request(0);
1249 goto repeat;
1250 }
1251 if (type == 0) {
1252 if (!floppy->disktype) {
1253 Probing = 1;
1254 floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1255 floppy_sizes[drive] = floppy->disktype->blocks >> 1;
1256 floppy->autoprobe = 1;
1257 }
1258 } else {
1259
1260 --type;
1261 if (type >= NUM_DISK_TYPES) {
1262 printk("fd%d: invalid disk format", drive);
1263 end_request(0);
1264 goto repeat;
1265 }
1266 floppy->disktype = &disk_type[type];
1267 floppy_sizes[drive] = disk_type[type].blocks >> 1;
1268 floppy->autoprobe = 0;
1269 }
1270
1271 if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1272 end_request(0);
1273 goto repeat;
1274 }
1275
1276 del_timer(&motor_off_timer);
1277
1278 ReqCnt = 0;
1279 ReqCmd = CURRENT->cmd;
1280 ReqBlock = CURRENT->sector;
1281 ReqBuffer = CURRENT->buffer;
1282 setup_req_params(drive);
1283 do_fd_action(drive);
1284
1285 return;
1286
1287the_end:
1288 finish_fdc();
1289}
1290
1291static void fd1772_checkint(void)
1292{
1293 extern int fdc1772_bytestogo;
1294
1295
1296 if (fdc1772_fdc_int_done)
1297 floppy_irqconsequencehandler();
1298 if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1299 if (fdc_busy) {
1300 queue_task(&fd1772_tq,&tq_immediate);
1301 mark_bh(IMMEDIATE_BH);
1302 }
1303}
1304
1305void do_fd_request(request_queue_t* q)
1306{
1307 unsigned long flags;
1308
1309 DPRINT(("do_fd_request for pid %d\n", current->pid));
1310 if (fdc_busy) return;
1311 save_flags(flags);
1312 cli();
1313 while (fdc_busy)
1314 sleep_on(&fdc_wait);
1315 fdc_busy = 1;
1316 ENABLE_IRQ();
1317 restore_flags(flags);
1318
1319 fdc1772_fdc_int_done = 0;
1320
1321 redo_fd_request();
1322
1323 queue_task(&fd1772_tq,&tq_immediate);
1324 mark_bh(IMMEDIATE_BH);
1325}
1326
1327
1328static int invalidate_drive(int rdev)
1329{
1330
1331#ifdef TRACKBUFFER
1332 BufferDrive = -1;
1333#endif
1334
1335 set_bit(rdev & 3, &fake_change);
1336 check_disk_change(rdev);
1337 return 0;
1338}
1339
1340static int fd_ioctl(struct inode *inode, struct file *filp,
1341 unsigned int cmd, unsigned long param)
1342{
1343 int drive, device;
1344
1345 device = inode->i_rdev;
1346 drive = MINOR(device);
1347 switch (cmd) {
1348 case FDFMTBEG:
1349 return 0;
1350
1351
1352
1353
1354 case FDFMTEND:
1355 case FDFLUSH:
1356 return invalidate_drive(drive);
1357 }
1358 if (!capable(CAP_SYS_ADMIN))
1359 return -EPERM;
1360 if (drive < 0 || drive > 3)
1361 return -EINVAL;
1362 switch (cmd) {
1363 default:
1364 return -EINVAL;
1365 }
1366 return 0;
1367}
1368
1369
1370
1371
1372static void fd_probe(int drive)
1373{
1374 unit[drive].connected = 0;
1375 unit[drive].disktype = NULL;
1376
1377 if (!fd_test_drive_present(drive))
1378 return;
1379
1380 unit[drive].connected = 1;
1381 unit[drive].track = -1;
1382 unit[drive].steprate = FDC1772STEP_6;
1383 MotorOn = 1;
1384}
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396static int fd_test_drive_present(int drive)
1397{
1398 unsigned long timeout;
1399 unsigned char status;
1400 int ok;
1401
1402 printk("fd_test_drive_present %d\n", drive);
1403 if (drive > 1)
1404 return (0);
1405 return (1);
1406 fd_select_drive(drive);
1407
1408
1409 DISABLE_IRQ();
1410 FDC1772_WRITE(FDC1772REG_TRACK, 0x00);
1411 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
1412
1413
1414 for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
1415
1416
1417
1418
1419 if (ioc_readb(IOC_FIQSTAT) & 2)
1420 break;
1421 }
1422
1423
1424 status = FDC1772_READ(FDC1772REG_STATUS);
1425 ok = (status & FDC1772STAT_TR00) != 0;
1426
1427
1428
1429
1430 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1431 udelay(500);
1432 status = FDC1772_READ(FDC1772REG_STATUS);
1433 udelay(20);
1434
1435
1436 if (ok) {
1437
1438 FDC1772_WRITE(FDC1772REG_DATA, 0);
1439 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1440 printk("fd_test_drive_present: just before wait for int\n");
1441
1442 while (!(ioc_readb(IOC_FIQSTAT) & 2));
1443 printk("fd_test_drive_present: just after wait for int\n");
1444 status = FDC1772_READ(FDC1772REG_STATUS);
1445 }
1446 printk("fd_test_drive_present: just before ENABLE_IRQ\n");
1447 ENABLE_IRQ();
1448 printk("fd_test_drive_present: about to return\n");
1449 return (ok);
1450}
1451
1452
1453
1454
1455
1456
1457static void config_types(void)
1458{
1459 int drive, cnt = 0;
1460
1461 printk("Probing floppy drive(s):\n");
1462 for (drive = 0; drive < FD_MAX_UNITS; drive++) {
1463 fd_probe(drive);
1464 if (unit[drive].connected) {
1465 printk("fd%d\n", drive);
1466 ++cnt;
1467 }
1468 }
1469
1470 if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
1471
1472
1473
1474
1475
1476
1477 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1478 udelay(500);
1479 FDC1772_READ(FDC1772REG_STATUS);
1480 udelay(20);
1481 }
1482 if (cnt > 0) {
1483 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1484 if (cnt == 1)
1485 fd_select_drive(0);
1486
1487 }
1488}
1489
1490
1491
1492
1493
1494
1495
1496static int floppy_open(struct inode *inode, struct file *filp)
1497{
1498 int drive;
1499 int old_dev;
1500
1501 if (!filp) {
1502 DPRINT(("Weird, open called with filp=0\n"));
1503 return -EIO;
1504 }
1505 drive = MINOR(inode->i_rdev) & 3;
1506 if ((MINOR(inode->i_rdev) >> 2) > NUM_DISK_TYPES)
1507 return -ENXIO;
1508
1509 old_dev = fd_device[drive];
1510
1511 if (fd_ref[drive])
1512 if (old_dev != inode->i_rdev)
1513 return -EBUSY;
1514
1515 if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1516 return -EBUSY;
1517
1518 if (filp->f_flags & O_EXCL)
1519 fd_ref[drive] = -1;
1520 else
1521 fd_ref[drive]++;
1522
1523 fd_device[drive] = inode->i_rdev;
1524
1525 if (old_dev && old_dev != inode->i_rdev)
1526 invalidate_buffers(old_dev);
1527
1528 if (filp->f_flags & O_NDELAY)
1529 return 0;
1530
1531 if (filp->f_mode & 3) {
1532 check_disk_change(inode->i_rdev);
1533 if (filp->f_mode & 2) {
1534 if (unit[drive].wpstat) {
1535 floppy_release(inode, filp);
1536 return -EROFS;
1537 }
1538 }
1539 }
1540 return 0;
1541}
1542
1543
1544static int floppy_release(struct inode *inode, struct file *filp)
1545{
1546 int drive = MINOR(inode->i_rdev) & 3;
1547
1548 if (fd_ref[drive] < 0)
1549 fd_ref[drive] = 0;
1550 else if (!fd_ref[drive]--) {
1551 printk("floppy_release with fd_ref == 0");
1552 fd_ref[drive] = 0;
1553 }
1554
1555 return 0;
1556}
1557
1558static struct block_device_operations floppy_fops =
1559{
1560 open: floppy_open,
1561 release: floppy_release,
1562 ioctl: fd_ioctl,
1563 check_media_change: check_floppy_change,
1564 revalidate: floppy_revalidate,
1565};
1566
1567
1568int fd1772_init(void)
1569{
1570 int i, err;
1571
1572 if (!machine_is_archimedes())
1573 return 0;
1574
1575 err = register_blkdev(MAJOR_NR, "fd", &floppy_fops);
1576 if (err) {
1577 printk("Unable to get major %d for floppy\n", MAJOR_NR);
1578 goto err_out;
1579 }
1580
1581 err = -EBUSY;
1582 if (request_dma(FLOPPY_DMA, "fd1772")) {
1583 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1584 goto err_blkdev;
1585 };
1586
1587 if (request_dma(FIQ_FD1772, "fd1772 end")) {
1588 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1589 goto err_dma1;
1590 };
1591
1592
1593 err = -ENOMEM;
1594 SelectedDrive = -1;
1595#ifdef TRACKBUFFER
1596 BufferDrive = BufferSide = BufferTrack = -1;
1597
1598 DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
1599 TrackBuffer = DMABuffer + 512;
1600#else
1601
1602
1603 DMABuffer = (char *) kmalloc(2048);
1604#endif
1605 if (DMABuffer == NULL)
1606 goto err_dma2;
1607
1608 enable_dma(FIQ_FD1772);
1609 for (i = 0; i < FD_MAX_UNITS; i++) {
1610 unit[i].track = -1;
1611 }
1612
1613 for (i = 0; i < 256; i++)
1614 if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)
1615 floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;
1616 else
1617 floppy_sizes[i] = MAX_DISK_SIZE;
1618
1619 blk_size[MAJOR_NR] = floppy_sizes;
1620 blksize_size[MAJOR_NR] = floppy_blocksizes;
1621 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1622
1623 config_types();
1624
1625 return 0;
1626
1627 err_dma2:
1628 free_dma(FIQ_FD1772);
1629 err_dma1:
1630 free_dma(FLOPPY_DMA);
1631 err_blkdev:
1632 unregister_blkdev(MAJOR_NR, &floppy_fops);
1633 err_out:
1634 return err;
1635}
1636