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#include <linux/module.h>
65
66#include <linux/sched.h>
67#include <linux/string.h>
68#include <linux/fs.h>
69#include <linux/fcntl.h>
70#include <linux/kernel.h>
71#include <linux/timer.h>
72#include <linux/fd.h>
73#include <linux/errno.h>
74#include <linux/types.h>
75#include <linux/delay.h>
76#include <linux/mm.h>
77#include <linux/slab.h>
78#include <linux/init.h>
79
80#include <asm/setup.h>
81#include <asm/system.h>
82#include <asm/bitops.h>
83#include <asm/irq.h>
84#include <asm/pgtable.h>
85#include <asm/uaccess.h>
86
87#include <asm/atafd.h>
88#include <asm/atafdreg.h>
89#include <asm/atarihw.h>
90#include <asm/atariints.h>
91#include <asm/atari_stdma.h>
92#include <asm/atari_stram.h>
93
94#define MAJOR_NR FLOPPY_MAJOR
95#include <linux/blk.h>
96#include <linux/blkpg.h>
97
98#define FD_MAX_UNITS 2
99
100#undef DEBUG
101
102
103static struct atari_disk_type {
104 const char *name;
105 unsigned spt;
106 unsigned blocks;
107 unsigned fdc_speed;
108 unsigned stretch;
109} disk_type[] = {
110 { "d360", 9, 720, 0, 0},
111 { "D360", 9, 720, 0, 1},
112 { "D720", 9,1440, 0, 0},
113 { "D820", 10,1640, 0, 0},
114
115#define MAX_TYPE_DD 3
116 { "h1200",15,2400, 3, 0},
117 { "H1440",18,2880, 3, 0},
118 { "H1640",20,3280, 3, 0},
119
120#define MAX_TYPE_HD 6
121 { "E2880",36,5760, 3, 0},
122 { "E3280",40,6560, 3, 0},
123
124#define MAX_TYPE_ED 8
125
126 { "H1680",21,3360, 3, 0},
127 { "h410",10,820, 0, 1},
128 { "h1476",18,2952, 3, 0},
129 { "H1722",21,3444, 3, 0},
130 { "h420",10,840, 0, 1},
131 { "H830",10,1660, 0, 0},
132 { "h1494",18,2952, 3, 0},
133 { "H1743",21,3486, 3, 0},
134 { "h880",11,1760, 0, 0},
135 { "D1040",13,2080, 0, 0},
136 { "D1120",14,2240, 0, 0},
137 { "h1600",20,3200, 3, 0},
138 { "H1760",22,3520, 3, 0},
139 { "H1920",24,3840, 3, 0},
140 { "E3200",40,6400, 3, 0},
141 { "E3520",44,7040, 3, 0},
142 { "E3840",48,7680, 3, 0},
143 { "H1840",23,3680, 3, 0},
144 { "D800",10,1600, 0, 0},
145};
146
147static int StartDiskType[] = {
148 MAX_TYPE_DD,
149 MAX_TYPE_HD,
150 MAX_TYPE_ED
151};
152
153#define TYPE_DD 0
154#define TYPE_HD 1
155#define TYPE_ED 2
156
157static int DriveType = TYPE_HD;
158
159
160static struct {
161 int index;
162 unsigned drive_types;
163} minor2disktype[] = {
164 { 0, TYPE_DD },
165 { 4, TYPE_HD },
166 { 1, TYPE_DD },
167 { 2, TYPE_DD },
168 { 1, TYPE_DD },
169 { 2, TYPE_DD },
170 { 5, TYPE_HD },
171 { 7, TYPE_ED },
172
173 { 8, TYPE_ED },
174 { 5, TYPE_HD },
175 { 9, TYPE_HD },
176 { 10, TYPE_DD },
177 { 3, TYPE_DD },
178 { 11, TYPE_HD },
179 { 12, TYPE_HD },
180 { 13, TYPE_DD },
181 { 14, TYPE_DD },
182 { 15, TYPE_HD },
183 { 16, TYPE_HD },
184 { 17, TYPE_DD },
185 { 18, TYPE_DD },
186 { 19, TYPE_DD },
187 { 20, TYPE_HD },
188 { 21, TYPE_HD },
189 { 22, TYPE_HD },
190 { 23, TYPE_ED },
191 { 24, TYPE_ED },
192 { 25, TYPE_ED },
193 { 26, TYPE_HD },
194 { 27, TYPE_DD },
195 { 6, TYPE_HD },
196};
197
198#define NUM_DISK_MINORS (sizeof(minor2disktype)/sizeof(*minor2disktype))
199
200
201
202
203
204#define MAX_DISK_SIZE 3280
205
206
207
208
209
210static struct atari_disk_type user_params[FD_MAX_UNITS];
211
212
213
214
215
216
217
218static struct atari_disk_type default_params[FD_MAX_UNITS];
219
220static int floppy_sizes[256];
221static int floppy_blocksizes[256];
222
223
224static struct atari_floppy_struct {
225 int connected;
226 int autoprobe;
227
228 struct atari_disk_type *disktype;
229
230 int track;
231
232 unsigned int steprate;
233 unsigned int wpstat;
234
235 int flags;
236} unit[FD_MAX_UNITS];
237
238#define UD unit[drive]
239#define UDT unit[drive].disktype
240#define SUD unit[SelectedDrive]
241#define SUDT unit[SelectedDrive].disktype
242
243
244#define FDC_READ(reg) ({ \
245 \
246 unsigned short __val; \
247 \
248 dma_wd.dma_mode_status = 0x80 | (reg); \
249 udelay(25); \
250 __val = dma_wd.fdc_acces_seccount; \
251 MFPDELAY(); \
252 \
253 __val & 0xff; \
254})
255
256#define FDC_WRITE(reg,val) \
257 do { \
258 \
259 \
260 dma_wd.dma_mode_status = 0x80 | (reg); \
261 udelay(25); \
262 dma_wd.fdc_acces_seccount = (val); \
263 MFPDELAY(); \
264 \
265 } while(0)
266
267
268
269
270
271
272
273
274
275static int MaxSectors[] = {
276 11, 22, 44
277};
278static int BufferSize[] = {
279 15*512, 30*512, 60*512
280};
281
282#define BUFFER_SIZE (BufferSize[DriveType])
283
284unsigned char *DMABuffer;
285static unsigned long PhysDMABuffer;
286
287static int UseTrackbuffer = -1;
288MODULE_PARM(UseTrackbuffer, "i");
289
290unsigned char *TrackBuffer;
291static unsigned long PhysTrackBuffer;
292static int BufferDrive, BufferSide, BufferTrack;
293static int read_track;
294
295#define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512)
296#define IS_BUFFERED(drive,side,track) \
297 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
298
299
300
301
302
303
304static int SelectedDrive = 0;
305static int ReqCmd, ReqBlock;
306static int ReqSide, ReqTrack, ReqSector, ReqCnt;
307static int HeadSettleFlag = 0;
308static unsigned char *ReqData, *ReqBuffer;
309static int MotorOn = 0, MotorOffTrys;
310static int IsFormatting = 0, FormatError;
311
312static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
313MODULE_PARM(UserSteprate, "1-" __MODULE_STRING(FD_MAX_UNITS) "i");
314
315
316static volatile int fdc_busy = 0;
317static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
318static DECLARE_WAIT_QUEUE_HEAD(format_wait);
319
320static unsigned long changed_floppies = 0xff, fake_change = 0;
321#define CHECK_CHANGE_DELAY HZ/2
322
323#define FD_MOTOR_OFF_DELAY (3*HZ)
324#define FD_MOTOR_OFF_MAXTRY (10*20)
325
326#define FLOPPY_TIMEOUT (6*HZ)
327#define RECALIBRATE_ERRORS 4
328
329#define MAX_ERRORS 8
330
331
332
333
334
335
336
337
338static int Probing = 0;
339
340
341
342
343static int NeedSeek = 0;
344
345
346#ifdef DEBUG
347#define DPRINT(a) printk a
348#else
349#define DPRINT(a)
350#endif
351
352
353
354static void fd_select_side( int side );
355static void fd_select_drive( int drive );
356static void fd_deselect( void );
357static void fd_motor_off_timer( unsigned long dummy );
358static void check_change( unsigned long dummy );
359static __inline__ void set_head_settle_flag( void );
360static __inline__ int get_head_settle_flag( void );
361static void floppy_irq (int irq, void *dummy, struct pt_regs *fp);
362static void fd_error( void );
363static int do_format(kdev_t drive, struct atari_format_descr *desc);
364static void do_fd_action( int drive );
365static void fd_calibrate( void );
366static void fd_calibrate_done( int status );
367static void fd_seek( void );
368static void fd_seek_done( int status );
369static void fd_rwsec( void );
370static void fd_readtrack_check( unsigned long dummy );
371static void fd_rwsec_done( int status );
372static void fd_rwsec_done1(int status);
373static void fd_writetrack( void );
374static void fd_writetrack_done( int status );
375static void fd_times_out( unsigned long dummy );
376static void finish_fdc( void );
377static void finish_fdc_done( int dummy );
378static void floppy_off( unsigned int nr);
379static __inline__ void copy_buffer( void *from, void *to);
380static void setup_req_params( int drive );
381static void redo_fd_request( void);
382static int invalidate_drive(kdev_t rdev);
383static int fd_ioctl( struct inode *inode, struct file *filp, unsigned int
384 cmd, unsigned long param);
385static void fd_probe( int drive );
386static int fd_test_drive_present( int drive );
387static void config_types( void );
388static int floppy_open( struct inode *inode, struct file *filp );
389static int floppy_release( struct inode * inode, struct file * filp );
390
391
392
393static struct timer_list motor_off_timer =
394 { function: fd_motor_off_timer };
395static struct timer_list readtrack_timer =
396 { function: fd_readtrack_check };
397
398static struct timer_list timeout_timer =
399 { function: fd_times_out };
400
401static struct timer_list fd_timer =
402 { function: check_change };
403
404static inline void
405start_motor_off_timer(void)
406{
407 mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY);
408 MotorOffTrys = 0;
409}
410
411static inline void
412start_check_change_timer( void )
413{
414 mod_timer(&fd_timer, jiffies + CHECK_CHANGE_DELAY);
415}
416
417static inline void
418start_timeout(void)
419{
420 mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT);
421}
422
423static inline void
424stop_timeout(void)
425{
426 del_timer(&timeout_timer);
427}
428
429
430
431static void fd_select_side( int side )
432{
433 unsigned long flags;
434
435 save_flags(flags);
436 cli();
437
438 sound_ym.rd_data_reg_sel = 14;
439 sound_ym.wd_data = (side == 0) ? sound_ym.rd_data_reg_sel | 0x01 :
440 sound_ym.rd_data_reg_sel & 0xfe;
441
442 restore_flags(flags);
443}
444
445
446
447
448
449
450static void fd_select_drive( int drive )
451{
452 unsigned long flags;
453 unsigned char tmp;
454
455 if (drive == SelectedDrive)
456 return;
457
458 save_flags(flags);
459 cli();
460 sound_ym.rd_data_reg_sel = 14;
461 tmp = sound_ym.rd_data_reg_sel;
462 sound_ym.wd_data = (tmp | DSKDRVNONE) & ~(drive == 0 ? DSKDRV0 : DSKDRV1);
463 atari_dont_touch_floppy_select = 1;
464 restore_flags(flags);
465
466
467 FDC_WRITE( FDCREG_TRACK, UD.track );
468 udelay(25);
469
470
471 if (UDT)
472 if (ATARIHW_PRESENT(FDCSPEED))
473 dma_wd.fdc_speed = UDT->fdc_speed;
474
475 SelectedDrive = drive;
476}
477
478
479
480
481static void fd_deselect( void )
482{
483 unsigned long flags;
484
485 save_flags(flags);
486 cli();
487 atari_dont_touch_floppy_select = 0;
488 sound_ym.rd_data_reg_sel=14;
489 sound_ym.wd_data = (sound_ym.rd_data_reg_sel |
490 (MACH_IS_FALCON ? 3 : 7));
491
492
493 SelectedDrive = -1;
494 restore_flags(flags);
495}
496
497
498
499
500
501
502
503static void fd_motor_off_timer( unsigned long dummy )
504{
505 unsigned char status;
506
507 if (SelectedDrive < 0)
508
509 return;
510
511 if (stdma_islocked())
512 goto retry;
513
514 status = FDC_READ( FDCREG_STATUS );
515
516 if (!(status & 0x80)) {
517
518 MotorOn = 0;
519 fd_deselect();
520 return;
521 }
522
523
524 retry:
525
526
527
528
529
530 mod_timer(&motor_off_timer,
531 jiffies + (MotorOffTrys++ < FD_MOTOR_OFF_MAXTRY ? HZ/20 : HZ/2));
532}
533
534
535
536
537
538
539static void check_change( unsigned long dummy )
540{
541 static int drive = 0;
542
543 unsigned long flags;
544 unsigned char old_porta;
545 int stat;
546
547 if (++drive > 1 || !UD.connected)
548 drive = 0;
549
550 save_flags(flags);
551 cli();
552
553 if (!stdma_islocked()) {
554 sound_ym.rd_data_reg_sel = 14;
555 old_porta = sound_ym.rd_data_reg_sel;
556 sound_ym.wd_data = (old_porta | DSKDRVNONE) &
557 ~(drive == 0 ? DSKDRV0 : DSKDRV1);
558 stat = !!(FDC_READ( FDCREG_STATUS ) & FDCSTAT_WPROT);
559 sound_ym.wd_data = old_porta;
560
561 if (stat != UD.wpstat) {
562 DPRINT(( "wpstat[%d] = %d\n", drive, stat ));
563 UD.wpstat = stat;
564 set_bit (drive, &changed_floppies);
565 }
566 }
567 restore_flags(flags);
568
569 start_check_change_timer();
570}
571
572
573
574
575
576
577static __inline__ void set_head_settle_flag( void )
578{
579 HeadSettleFlag = FDCCMDADD_E;
580}
581
582static __inline__ int get_head_settle_flag( void )
583{
584 int tmp = HeadSettleFlag;
585 HeadSettleFlag = 0;
586 return( tmp );
587}
588
589
590
591
592
593
594static void (*FloppyIRQHandler)( int status ) = NULL;
595
596static void floppy_irq (int irq, void *dummy, struct pt_regs *fp)
597{
598 unsigned char status;
599 void (*handler)( int );
600
601 handler = xchg(&FloppyIRQHandler, NULL);
602
603 if (handler) {
604 nop();
605 status = FDC_READ( FDCREG_STATUS );
606 DPRINT(("FDC irq, status = %02x handler = %08lx\n",status,(unsigned long)handler));
607 handler( status );
608 }
609 else {
610 DPRINT(("FDC irq, no handler\n"));
611 }
612}
613
614
615
616
617
618
619static void fd_error( void )
620{
621 if (IsFormatting) {
622 IsFormatting = 0;
623 FormatError = 1;
624 wake_up( &format_wait );
625 return;
626 }
627
628 if (QUEUE_EMPTY) return;
629 CURRENT->errors++;
630 if (CURRENT->errors >= MAX_ERRORS) {
631 printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
632 end_request( 0 );
633 }
634 else if (CURRENT->errors == RECALIBRATE_ERRORS) {
635 printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
636 if (SelectedDrive != -1)
637 SUD.track = -1;
638 }
639 redo_fd_request();
640}
641
642
643
644#define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
645
646
647
648
649#define FILL(n,val) \
650 do { \
651 memset( p, val, n ); \
652 p += n; \
653 } while(0)
654
655static int do_format(kdev_t device, struct atari_format_descr *desc)
656{
657 unsigned char *p;
658 int sect, nsect;
659 unsigned long flags;
660 int type, drive = MINOR(device) & 3;
661
662 DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
663 drive, desc->track, desc->head, desc->sect_offset ));
664
665 save_flags(flags);
666 cli();
667 while( fdc_busy ) sleep_on( &fdc_wait );
668 fdc_busy = 1;
669 stdma_lock(floppy_irq, NULL);
670 atari_turnon_irq( IRQ_MFP_FDC );
671 restore_flags(flags);
672
673 type = MINOR(device) >> 2;
674 if (type) {
675 if (--type >= NUM_DISK_MINORS ||
676 minor2disktype[type].drive_types > DriveType) {
677 redo_fd_request();
678 return -EINVAL;
679 }
680 type = minor2disktype[type].index;
681 UDT = &disk_type[type];
682 }
683
684 if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
685 redo_fd_request();
686 return -EINVAL;
687 }
688
689 nsect = UDT->spt;
690 p = TrackBuffer;
691
692
693 BufferDrive = -1;
694
695 del_timer( &motor_off_timer );
696
697 FILL( 60 * (nsect / 9), 0x4e );
698 for( sect = 0; sect < nsect; ++sect ) {
699 FILL( 12, 0 );
700 FILL( 3, 0xf5 );
701 *p++ = 0xfe;
702 *p++ = desc->track;
703 *p++ = desc->head;
704 *p++ = (nsect + sect - desc->sect_offset) % nsect + 1;
705 *p++ = 2;
706 *p++ = 0xf7;
707 FILL( 22, 0x4e );
708 FILL( 12, 0 );
709 FILL( 3, 0xf5 );
710 *p++ = 0xfb;
711 FILL( 512, 0xe5 );
712 *p++ = 0xf7;
713 FILL( 40, 0x4e );
714 }
715 FILL( TrackBuffer+BUFFER_SIZE-p, 0x4e );
716
717 IsFormatting = 1;
718 FormatError = 0;
719 ReqTrack = desc->track;
720 ReqSide = desc->head;
721 do_fd_action( drive );
722
723 sleep_on( &format_wait );
724
725 redo_fd_request();
726 return( FormatError ? -EIO : 0 );
727}
728
729
730
731
732
733
734
735
736
737
738
739static void do_fd_action( int drive )
740{
741 DPRINT(("do_fd_action\n"));
742
743 if (UseTrackbuffer && !IsFormatting) {
744 repeat:
745 if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
746 if (ReqCmd == READ) {
747 copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
748 if (++ReqCnt < CURRENT->current_nr_sectors) {
749
750 setup_req_params( drive );
751 goto repeat;
752 }
753 else {
754
755 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
756 CURRENT->sector += CURRENT->current_nr_sectors;
757 end_request( 1 );
758 redo_fd_request();
759 return;
760 }
761 }
762 else {
763
764
765 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
766 }
767 }
768 }
769
770 if (SelectedDrive != drive)
771 fd_select_drive( drive );
772
773 if (UD.track == -1)
774 fd_calibrate();
775 else if (UD.track != ReqTrack << UDT->stretch)
776 fd_seek();
777 else if (IsFormatting)
778 fd_writetrack();
779 else
780 fd_rwsec();
781}
782
783
784
785
786static void fd_calibrate( void )
787{
788 if (SUD.track >= 0) {
789 fd_calibrate_done( 0 );
790 return;
791 }
792
793 if (ATARIHW_PRESENT(FDCSPEED))
794 dma_wd.fdc_speed = 0; ;
795 DPRINT(("fd_calibrate\n"));
796 SET_IRQ_HANDLER( fd_calibrate_done );
797
798 FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | SUD.steprate );
799
800 NeedSeek = 1;
801 MotorOn = 1;
802 start_timeout();
803
804}
805
806
807static void fd_calibrate_done( int status )
808{
809 DPRINT(("fd_calibrate_done()\n"));
810 stop_timeout();
811
812
813 if (ATARIHW_PRESENT(FDCSPEED))
814 dma_wd.fdc_speed = SUDT->fdc_speed;
815 if (status & FDCSTAT_RECNF) {
816 printk(KERN_ERR "fd%d: restore failed\n", SelectedDrive );
817 fd_error();
818 }
819 else {
820 SUD.track = 0;
821 fd_seek();
822 }
823}
824
825
826
827
828
829
830static void fd_seek( void )
831{
832 if (SUD.track == ReqTrack << SUDT->stretch) {
833 fd_seek_done( 0 );
834 return;
835 }
836
837 if (ATARIHW_PRESENT(FDCSPEED)) {
838 dma_wd.fdc_speed = 0;
839 MFPDELAY();
840 }
841
842 DPRINT(("fd_seek() to track %d\n",ReqTrack));
843 FDC_WRITE( FDCREG_DATA, ReqTrack << SUDT->stretch);
844 udelay(25);
845 SET_IRQ_HANDLER( fd_seek_done );
846 FDC_WRITE( FDCREG_CMD, FDCCMD_SEEK | SUD.steprate );
847
848 MotorOn = 1;
849 set_head_settle_flag();
850 start_timeout();
851
852}
853
854
855static void fd_seek_done( int status )
856{
857 DPRINT(("fd_seek_done()\n"));
858 stop_timeout();
859
860
861 if (ATARIHW_PRESENT(FDCSPEED))
862 dma_wd.fdc_speed = SUDT->fdc_speed;
863 if (status & FDCSTAT_RECNF) {
864 printk(KERN_ERR "fd%d: seek error (to track %d)\n",
865 SelectedDrive, ReqTrack );
866
867 SUD.track = -1;
868 fd_error();
869 }
870 else {
871 SUD.track = ReqTrack << SUDT->stretch;
872 NeedSeek = 0;
873 if (IsFormatting)
874 fd_writetrack();
875 else
876 fd_rwsec();
877 }
878}
879
880
881
882
883
884
885static int MultReadInProgress = 0;
886
887
888static void fd_rwsec( void )
889{
890 unsigned long paddr, flags;
891 unsigned int rwflag, old_motoron;
892 unsigned int track;
893
894 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n",ReqSector, ReqCmd == WRITE ? 'w' : 'r' ));
895 if (ReqCmd == WRITE) {
896 if (ATARIHW_PRESENT(EXTD_DMA)) {
897 paddr = virt_to_phys(ReqData);
898 }
899 else {
900 copy_buffer( ReqData, DMABuffer );
901 paddr = PhysDMABuffer;
902 }
903 dma_cache_maintenance( paddr, 512, 1 );
904 rwflag = 0x100;
905 }
906 else {
907 if (read_track)
908 paddr = PhysTrackBuffer;
909 else
910 paddr = ATARIHW_PRESENT(EXTD_DMA) ?
911 virt_to_phys(ReqData) : PhysDMABuffer;
912 rwflag = 0;
913 }
914
915 fd_select_side( ReqSide );
916
917
918 FDC_WRITE( FDCREG_SECTOR, read_track ? 1 : ReqSector );
919 MFPDELAY();
920
921 if (SUDT->stretch) {
922 track = FDC_READ( FDCREG_TRACK);
923 MFPDELAY();
924 FDC_WRITE( FDCREG_TRACK, track >> SUDT->stretch);
925 }
926 udelay(25);
927
928
929 save_flags(flags);
930 cli();
931 dma_wd.dma_lo = (unsigned char)paddr;
932 MFPDELAY();
933 paddr >>= 8;
934 dma_wd.dma_md = (unsigned char)paddr;
935 MFPDELAY();
936 paddr >>= 8;
937 if (ATARIHW_PRESENT(EXTD_DMA))
938 st_dma_ext_dmahi = (unsigned short)paddr;
939 else
940 dma_wd.dma_hi = (unsigned char)paddr;
941 MFPDELAY();
942 restore_flags(flags);
943
944
945 dma_wd.dma_mode_status = 0x90 | rwflag;
946 MFPDELAY();
947 dma_wd.dma_mode_status = 0x90 | (rwflag ^ 0x100);
948 MFPDELAY();
949 dma_wd.dma_mode_status = 0x90 | rwflag;
950 MFPDELAY();
951
952
953 dma_wd.fdc_acces_seccount = read_track ? SUDT->spt : 1;
954
955 udelay(25);
956
957
958 dma_wd.dma_mode_status = FDCSELREG_STP | rwflag;
959 udelay(25);
960 SET_IRQ_HANDLER( fd_rwsec_done );
961 dma_wd.fdc_acces_seccount =
962 (get_head_settle_flag() |
963 (rwflag ? FDCCMD_WRSEC : (FDCCMD_RDSEC | (read_track ? FDCCMDADD_M : 0))));
964
965 old_motoron = MotorOn;
966 MotorOn = 1;
967 NeedSeek = 1;
968
969
970 if (read_track) {
971
972
973
974
975
976 MultReadInProgress = 1;
977 mod_timer(&readtrack_timer,
978
979 jiffies + HZ/5 + (old_motoron ? 0 : HZ));
980 }
981 start_timeout();
982}
983
984
985static void fd_readtrack_check( unsigned long dummy )
986{
987 unsigned long flags, addr, addr2;
988
989 save_flags(flags);
990 cli();
991
992 if (!MultReadInProgress) {
993
994
995
996
997
998
999 restore_flags(flags);
1000 return;
1001 }
1002
1003
1004
1005 addr = 0;
1006 do {
1007 addr2 = addr;
1008 addr = dma_wd.dma_lo & 0xff;
1009 MFPDELAY();
1010 addr |= (dma_wd.dma_md & 0xff) << 8;
1011 MFPDELAY();
1012 if (ATARIHW_PRESENT( EXTD_DMA ))
1013 addr |= (st_dma_ext_dmahi & 0xffff) << 16;
1014 else
1015 addr |= (dma_wd.dma_hi & 0xff) << 16;
1016 MFPDELAY();
1017 } while(addr != addr2);
1018
1019 if (addr >= PhysTrackBuffer + SUDT->spt*512) {
1020
1021
1022
1023 SET_IRQ_HANDLER( NULL );
1024 MultReadInProgress = 0;
1025 restore_flags(flags);
1026 DPRINT(("fd_readtrack_check(): done\n"));
1027 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1028 udelay(25);
1029
1030
1031
1032
1033 fd_rwsec_done1(0);
1034 }
1035 else {
1036
1037 restore_flags(flags);
1038 DPRINT(("fd_readtrack_check(): not yet finished\n"));
1039 mod_timer(&readtrack_timer, jiffies + HZ/5/10);
1040 }
1041}
1042
1043
1044static void fd_rwsec_done( int status )
1045{
1046 DPRINT(("fd_rwsec_done()\n"));
1047
1048 if (read_track) {
1049 del_timer(&readtrack_timer);
1050 if (!MultReadInProgress)
1051 return;
1052 MultReadInProgress = 0;
1053 }
1054 fd_rwsec_done1(status);
1055}
1056
1057static void fd_rwsec_done1(int status)
1058{
1059 unsigned int track;
1060
1061 stop_timeout();
1062
1063
1064 if (SUDT->stretch) {
1065 track = FDC_READ( FDCREG_TRACK);
1066 MFPDELAY();
1067 FDC_WRITE( FDCREG_TRACK, track << SUDT->stretch);
1068 }
1069
1070 if (!UseTrackbuffer) {
1071 dma_wd.dma_mode_status = 0x90;
1072 MFPDELAY();
1073 if (!(dma_wd.dma_mode_status & 0x01)) {
1074 printk(KERN_ERR "fd%d: DMA error\n", SelectedDrive );
1075 goto err_end;
1076 }
1077 }
1078 MFPDELAY();
1079
1080 if (ReqCmd == WRITE && (status & FDCSTAT_WPROT)) {
1081 printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
1082 goto err_end;
1083 }
1084 if ((status & FDCSTAT_RECNF) &&
1085
1086
1087 !(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) {
1088 if (Probing) {
1089 if (SUDT > disk_type) {
1090 if (SUDT[-1].blocks > ReqBlock) {
1091
1092 SUDT--;
1093 floppy_sizes[SelectedDrive] = SUDT->blocks >> 1;
1094 } else
1095 Probing = 0;
1096 }
1097 else {
1098 if (SUD.flags & FTD_MSG)
1099 printk(KERN_INFO "fd%d: Auto-detected floppy type %s\n",
1100 SelectedDrive, SUDT->name );
1101 Probing=0;
1102 }
1103 } else {
1104
1105 if (SUD.autoprobe) {
1106 SUDT = disk_type + StartDiskType[DriveType];
1107 floppy_sizes[SelectedDrive] = SUDT->blocks >> 1;
1108 Probing = 1;
1109 }
1110 }
1111 if (Probing) {
1112 if (ATARIHW_PRESENT(FDCSPEED)) {
1113 dma_wd.fdc_speed = SUDT->fdc_speed;
1114 MFPDELAY();
1115 }
1116 setup_req_params( SelectedDrive );
1117 BufferDrive = -1;
1118 do_fd_action( SelectedDrive );
1119 return;
1120 }
1121
1122 printk(KERN_ERR "fd%d: sector %d not found (side %d, track %d)\n",
1123 SelectedDrive, FDC_READ (FDCREG_SECTOR), ReqSide, ReqTrack );
1124 goto err_end;
1125 }
1126 if (status & FDCSTAT_CRC) {
1127 printk(KERN_ERR "fd%d: CRC error (side %d, track %d, sector %d)\n",
1128 SelectedDrive, ReqSide, ReqTrack, FDC_READ (FDCREG_SECTOR) );
1129 goto err_end;
1130 }
1131 if (status & FDCSTAT_LOST) {
1132 printk(KERN_ERR "fd%d: lost data (side %d, track %d, sector %d)\n",
1133 SelectedDrive, ReqSide, ReqTrack, FDC_READ (FDCREG_SECTOR) );
1134 goto err_end;
1135 }
1136
1137 Probing = 0;
1138
1139 if (ReqCmd == READ) {
1140 if (!read_track) {
1141 void *addr;
1142 addr = ATARIHW_PRESENT( EXTD_DMA ) ? ReqData : DMABuffer;
1143 dma_cache_maintenance( virt_to_phys(addr), 512, 0 );
1144 if (!ATARIHW_PRESENT( EXTD_DMA ))
1145 copy_buffer (addr, ReqData);
1146 } else {
1147 dma_cache_maintenance( PhysTrackBuffer, MaxSectors[DriveType] * 512, 0 );
1148 BufferDrive = SelectedDrive;
1149 BufferSide = ReqSide;
1150 BufferTrack = ReqTrack;
1151 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1152 }
1153 }
1154
1155 if (++ReqCnt < CURRENT->current_nr_sectors) {
1156
1157 setup_req_params( SelectedDrive );
1158 do_fd_action( SelectedDrive );
1159 }
1160 else {
1161
1162 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1163 CURRENT->sector += CURRENT->current_nr_sectors;
1164 end_request( 1 );
1165 redo_fd_request();
1166 }
1167 return;
1168
1169 err_end:
1170 BufferDrive = -1;
1171 fd_error();
1172}
1173
1174
1175static void fd_writetrack( void )
1176{
1177 unsigned long paddr, flags;
1178 unsigned int track;
1179
1180 DPRINT(("fd_writetrack() Tr=%d Si=%d\n", ReqTrack, ReqSide ));
1181
1182 paddr = PhysTrackBuffer;
1183 dma_cache_maintenance( paddr, BUFFER_SIZE, 1 );
1184
1185 fd_select_side( ReqSide );
1186
1187
1188 if (SUDT->stretch) {
1189 track = FDC_READ( FDCREG_TRACK);
1190 MFPDELAY();
1191 FDC_WRITE(FDCREG_TRACK,track >> SUDT->stretch);
1192 }
1193 udelay(40);
1194
1195
1196 save_flags(flags);
1197 cli();
1198 dma_wd.dma_lo = (unsigned char)paddr;
1199 MFPDELAY();
1200 paddr >>= 8;
1201 dma_wd.dma_md = (unsigned char)paddr;
1202 MFPDELAY();
1203 paddr >>= 8;
1204 if (ATARIHW_PRESENT( EXTD_DMA ))
1205 st_dma_ext_dmahi = (unsigned short)paddr;
1206 else
1207 dma_wd.dma_hi = (unsigned char)paddr;
1208 MFPDELAY();
1209 restore_flags(flags);
1210
1211
1212 dma_wd.dma_mode_status = 0x190;
1213 MFPDELAY();
1214 dma_wd.dma_mode_status = 0x90;
1215 MFPDELAY();
1216 dma_wd.dma_mode_status = 0x190;
1217 MFPDELAY();
1218
1219
1220 dma_wd.fdc_acces_seccount = BUFFER_SIZE/512;
1221 udelay(40);
1222
1223
1224 dma_wd.dma_mode_status = FDCSELREG_STP | 0x100;
1225 udelay(40);
1226 SET_IRQ_HANDLER( fd_writetrack_done );
1227 dma_wd.fdc_acces_seccount = FDCCMD_WRTRA | get_head_settle_flag();
1228
1229 MotorOn = 1;
1230 start_timeout();
1231
1232}
1233
1234
1235static void fd_writetrack_done( int status )
1236{
1237 DPRINT(("fd_writetrack_done()\n"));
1238
1239 stop_timeout();
1240
1241 if (status & FDCSTAT_WPROT) {
1242 printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
1243 goto err_end;
1244 }
1245 if (status & FDCSTAT_LOST) {
1246 printk(KERN_ERR "fd%d: lost data (side %d, track %d)\n",
1247 SelectedDrive, ReqSide, ReqTrack );
1248 goto err_end;
1249 }
1250
1251 wake_up( &format_wait );
1252 return;
1253
1254 err_end:
1255 fd_error();
1256}
1257
1258static void fd_times_out( unsigned long dummy )
1259{
1260 atari_disable_irq( IRQ_MFP_FDC );
1261 if (!FloppyIRQHandler) goto end;
1262
1263
1264 SET_IRQ_HANDLER( NULL );
1265
1266
1267 if (UseTrackbuffer)
1268 del_timer( &readtrack_timer );
1269 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1270 udelay( 25 );
1271
1272 printk(KERN_ERR "floppy timeout\n" );
1273 fd_error();
1274 end:
1275 atari_enable_irq( IRQ_MFP_FDC );
1276}
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286static void finish_fdc( void )
1287{
1288 if (!NeedSeek) {
1289 finish_fdc_done( 0 );
1290 }
1291 else {
1292 DPRINT(("finish_fdc: dummy seek started\n"));
1293 FDC_WRITE (FDCREG_DATA, SUD.track);
1294 SET_IRQ_HANDLER( finish_fdc_done );
1295 FDC_WRITE (FDCREG_CMD, FDCCMD_SEEK);
1296 MotorOn = 1;
1297 start_timeout();
1298
1299
1300
1301 }
1302}
1303
1304
1305static void finish_fdc_done( int dummy )
1306{
1307 unsigned long flags;
1308
1309 DPRINT(("finish_fdc_done entered\n"));
1310 stop_timeout();
1311 NeedSeek = 0;
1312
1313 if (timer_pending(&fd_timer) && time_before(fd_timer.expires, jiffies + 5))
1314
1315
1316
1317 mod_timer(&fd_timer, jiffies + 5);
1318 else
1319 start_check_change_timer();
1320 start_motor_off_timer();
1321
1322 save_flags(flags);
1323 cli();
1324 stdma_release();
1325 fdc_busy = 0;
1326 wake_up( &fdc_wait );
1327 restore_flags(flags);
1328
1329 DPRINT(("finish_fdc() finished\n"));
1330}
1331
1332
1333
1334static int fd_ref[4] = { 0,0,0,0 };
1335static int fd_device[4] = { 0,0,0,0 };
1336
1337
1338
1339
1340
1341#define CURRENT_DEVICE (CURRENT->rq_dev)
1342
1343
1344#define CURRENT_ERRORS (CURRENT->errors)
1345
1346
1347
1348static void floppy_off( unsigned int nr) {}
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366static int check_floppy_change (kdev_t dev)
1367{
1368 unsigned int drive = MINOR(dev) & 0x03;
1369
1370 if (MAJOR(dev) != MAJOR_NR) {
1371 printk(KERN_ERR "floppy_changed: not a floppy\n");
1372 return 0;
1373 }
1374
1375 if (test_bit (drive, &fake_change)) {
1376
1377 return 1;
1378 }
1379 if (test_bit (drive, &changed_floppies)) {
1380
1381 return 1;
1382 }
1383 if (UD.wpstat) {
1384
1385
1386
1387 return 1;
1388 }
1389
1390 return 0;
1391}
1392
1393static int floppy_revalidate (kdev_t dev)
1394{
1395 int drive = MINOR(dev) & 3;
1396
1397 if (test_bit(drive, &changed_floppies) ||
1398 test_bit(drive, &fake_change) ||
1399 unit[drive].disktype == 0) {
1400 if (UD.flags & FTD_MSG)
1401 printk(KERN_ERR "floppy: clear format %p!\n", UDT);
1402 BufferDrive = -1;
1403 clear_bit(drive, &fake_change);
1404 clear_bit(drive, &changed_floppies);
1405
1406
1407
1408 if (default_params[drive].blocks == 0)
1409 UDT = 0;
1410 else
1411 UDT = &default_params[drive];
1412 }
1413 return 0;
1414}
1415
1416static __inline__ void copy_buffer(void *from, void *to)
1417{
1418 ulong *p1 = (ulong *)from, *p2 = (ulong *)to;
1419 int cnt;
1420
1421 for( cnt = 512/4; cnt; cnt-- )
1422 *p2++ = *p1++;
1423}
1424
1425
1426
1427
1428static void setup_req_params( int drive )
1429{
1430 int block = ReqBlock + ReqCnt;
1431
1432 ReqTrack = block / UDT->spt;
1433 ReqSector = block - ReqTrack * UDT->spt + 1;
1434 ReqSide = ReqTrack & 1;
1435 ReqTrack >>= 1;
1436 ReqData = ReqBuffer + 512 * ReqCnt;
1437
1438 if (UseTrackbuffer)
1439 read_track = (ReqCmd == READ && CURRENT_ERRORS == 0);
1440 else
1441 read_track = 0;
1442
1443 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n",ReqSide,
1444 ReqTrack, ReqSector, (unsigned long)ReqData ));
1445}
1446
1447
1448static void redo_fd_request(void)
1449{
1450 int device, drive, type;
1451
1452 DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->dev=%04x CURRENT->sector=%ld\n",
1453 (unsigned long)CURRENT, !QUEUE_EMPTY ? CURRENT->rq_dev : 0,
1454 !QUEUE_EMPTY ? CURRENT->sector : 0 ));
1455
1456 IsFormatting = 0;
1457
1458 if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE){
1459 return;
1460 }
1461
1462repeat:
1463
1464 if (QUEUE_EMPTY)
1465 goto the_end;
1466
1467 if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
1468 panic(DEVICE_NAME ": request list destroyed");
1469
1470 if (CURRENT->bh && !buffer_locked(CURRENT->bh))
1471 panic(DEVICE_NAME ": block not locked");
1472
1473 device = MINOR(CURRENT_DEVICE);
1474 drive = device & 3;
1475 type = device >> 2;
1476
1477 if (!UD.connected) {
1478
1479 printk(KERN_ERR "Unknown Device: fd%d\n", drive );
1480 end_request(0);
1481 goto repeat;
1482 }
1483
1484 if (type == 0) {
1485 if (!UDT) {
1486 Probing = 1;
1487 UDT = disk_type + StartDiskType[DriveType];
1488 floppy_sizes[drive] = UDT->blocks >> 1;
1489 UD.autoprobe = 1;
1490 }
1491 }
1492 else {
1493
1494 if (--type >= NUM_DISK_MINORS) {
1495 printk(KERN_WARNING "fd%d: invalid disk format", drive );
1496 end_request( 0 );
1497 goto repeat;
1498 }
1499 if (minor2disktype[type].drive_types > DriveType) {
1500 printk(KERN_WARNING "fd%d: unsupported disk format", drive );
1501 end_request( 0 );
1502 goto repeat;
1503 }
1504 type = minor2disktype[type].index;
1505 UDT = &disk_type[type];
1506 floppy_sizes[drive] = UDT->blocks >> 1;
1507 UD.autoprobe = 0;
1508 }
1509
1510 if (CURRENT->sector + 1 > UDT->blocks) {
1511 end_request(0);
1512 goto repeat;
1513 }
1514
1515
1516 del_timer( &motor_off_timer );
1517
1518 ReqCnt = 0;
1519 ReqCmd = CURRENT->cmd;
1520 ReqBlock = CURRENT->sector;
1521 ReqBuffer = CURRENT->buffer;
1522 setup_req_params( drive );
1523 do_fd_action( drive );
1524
1525 return;
1526
1527 the_end:
1528 finish_fdc();
1529}
1530
1531
1532void do_fd_request(request_queue_t * q)
1533{
1534 unsigned long flags;
1535
1536 DPRINT(("do_fd_request for pid %d\n",current->pid));
1537 while( fdc_busy ) sleep_on( &fdc_wait );
1538 fdc_busy = 1;
1539 stdma_lock(floppy_irq, NULL);
1540
1541 atari_disable_irq( IRQ_MFP_FDC );
1542 save_flags(flags);
1543
1544 redo_fd_request();
1545 restore_flags(flags);
1546 atari_enable_irq( IRQ_MFP_FDC );
1547}
1548
1549
1550static int invalidate_drive(kdev_t rdev)
1551{
1552
1553 BufferDrive = -1;
1554 set_bit(MINOR(rdev) & 3, &fake_change);
1555 check_disk_change(rdev);
1556 return 0;
1557}
1558
1559static int fd_ioctl(struct inode *inode, struct file *filp,
1560 unsigned int cmd, unsigned long param)
1561{
1562 int drive, type;
1563 kdev_t device;
1564 struct atari_format_descr fmt_desc;
1565 struct atari_disk_type *dtp;
1566 struct floppy_struct getprm;
1567 int settype;
1568 struct floppy_struct setprm;
1569
1570 device = inode->i_rdev;
1571 switch (cmd) {
1572 case BLKROSET:
1573 case BLKROGET:
1574 case BLKRASET:
1575 case BLKRAGET:
1576 case BLKFLSBUF:
1577 return blk_ioctl(device, cmd, param);
1578 }
1579 drive = MINOR (device);
1580 type = drive >> 2;
1581 drive &= 3;
1582 switch (cmd) {
1583 case FDGETPRM:
1584 case BLKGETSIZE:
1585 if (type) {
1586 if (--type >= NUM_DISK_MINORS)
1587 return -ENODEV;
1588 if (minor2disktype[type].drive_types > DriveType)
1589 return -ENODEV;
1590 type = minor2disktype[type].index;
1591 dtp = &disk_type[type];
1592 if (UD.flags & FTD_MSG)
1593 printk (KERN_ERR "floppy%d: found dtp %p name %s!\n",
1594 drive, dtp, dtp->name);
1595 }
1596 else {
1597 if (!UDT)
1598 return -ENXIO;
1599 else
1600 dtp = UDT;
1601 }
1602 if (cmd == BLKGETSIZE)
1603 return put_user(dtp->blocks, (unsigned long *)param);
1604
1605 memset((void *)&getprm, 0, sizeof(getprm));
1606 getprm.size = dtp->blocks;
1607 getprm.sect = dtp->spt;
1608 getprm.head = 2;
1609 getprm.track = dtp->blocks/dtp->spt/2;
1610 getprm.stretch = dtp->stretch;
1611 if (copy_to_user((void *)param, &getprm, sizeof(getprm)))
1612 return -EFAULT;
1613 return 0;
1614 }
1615 switch (cmd) {
1616 case FDSETPRM:
1617 case FDDEFPRM:
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628 if (fd_ref[drive] != 1 && fd_ref[drive] != -1)
1629 return -EBUSY;
1630 if (copy_from_user(&setprm, (void *) param, sizeof(setprm)))
1631 return -EFAULT;
1632
1633
1634
1635
1636
1637 if (check_floppy_change(device))
1638 floppy_revalidate(device);
1639
1640 if (UD.flags & FTD_MSG)
1641 printk (KERN_INFO "floppy%d: setting size %d spt %d str %d!\n",
1642 drive, setprm.size, setprm.sect, setprm.stretch);
1643
1644
1645 if (type) {
1646
1647 redo_fd_request();
1648 return -EINVAL;
1649 }
1650
1651
1652
1653
1654
1655
1656
1657
1658 for (settype = 0; settype < NUM_DISK_MINORS; settype++) {
1659 int setidx = 0;
1660 if (minor2disktype[settype].drive_types > DriveType) {
1661
1662 continue;
1663 }
1664 setidx = minor2disktype[settype].index;
1665 dtp = &disk_type[setidx];
1666
1667
1668 if ( dtp->blocks == setprm.size
1669 && dtp->spt == setprm.sect
1670 && dtp->stretch == setprm.stretch ) {
1671 if (UD.flags & FTD_MSG)
1672 printk (KERN_INFO "floppy%d: setting %s %p!\n",
1673 drive, dtp->name, dtp);
1674 UDT = dtp;
1675 floppy_sizes[drive] = UDT->blocks >> 1;
1676
1677 if (cmd == FDDEFPRM) {
1678
1679 default_params[drive].name = dtp->name;
1680 default_params[drive].spt = dtp->spt;
1681 default_params[drive].blocks = dtp->blocks;
1682 default_params[drive].fdc_speed = dtp->fdc_speed;
1683 default_params[drive].stretch = dtp->stretch;
1684 }
1685
1686 return 0;
1687 }
1688
1689 }
1690
1691
1692
1693 if (cmd == FDDEFPRM) {
1694
1695 dtp = &default_params[drive];
1696 } else
1697
1698 dtp = &user_params[drive];
1699
1700 dtp->name = "user format";
1701 dtp->blocks = setprm.size;
1702 dtp->spt = setprm.sect;
1703 if (setprm.sect > 14)
1704 dtp->fdc_speed = 3;
1705 else
1706 dtp->fdc_speed = 0;
1707 dtp->stretch = setprm.stretch;
1708
1709 if (UD.flags & FTD_MSG)
1710 printk (KERN_INFO "floppy%d: blk %d spt %d str %d!\n",
1711 drive, dtp->blocks, dtp->spt, dtp->stretch);
1712
1713
1714 if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 ||
1715 setprm.head != 2) {
1716 redo_fd_request();
1717 return -EINVAL;
1718 }
1719
1720 UDT = dtp;
1721 floppy_sizes[drive] = UDT->blocks >> 1;
1722
1723 return 0;
1724 case FDMSGON:
1725 UD.flags |= FTD_MSG;
1726 return 0;
1727 case FDMSGOFF:
1728 UD.flags &= ~FTD_MSG;
1729 return 0;
1730 case FDSETEMSGTRESH:
1731 return -EINVAL;
1732 case FDFMTBEG:
1733 return 0;
1734 case FDFMTTRK:
1735 if (fd_ref[drive] != 1 && fd_ref[drive] != -1)
1736 return -EBUSY;
1737 if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
1738 return -EFAULT;
1739 return do_format(device, &fmt_desc);
1740 case FDCLRPRM:
1741 UDT = NULL;
1742
1743 default_params[drive].blocks = 0;
1744 floppy_sizes[drive] = MAX_DISK_SIZE;
1745 return invalidate_drive (device);
1746 case FDFMTEND:
1747 case FDFLUSH:
1748 return invalidate_drive(device);
1749 }
1750 return -EINVAL;
1751}
1752
1753
1754
1755
1756static void __init fd_probe( int drive )
1757{
1758 UD.connected = 0;
1759 UDT = NULL;
1760
1761 if (!fd_test_drive_present( drive ))
1762 return;
1763
1764 UD.connected = 1;
1765 UD.track = 0;
1766 switch( UserSteprate[drive] ) {
1767 case 2:
1768 UD.steprate = FDCSTEP_2;
1769 break;
1770 case 3:
1771 UD.steprate = FDCSTEP_3;
1772 break;
1773 case 6:
1774 UD.steprate = FDCSTEP_6;
1775 break;
1776 case 12:
1777 UD.steprate = FDCSTEP_12;
1778 break;
1779 default:
1780 if (ATARIHW_PRESENT( FDCSPEED ) || MACH_IS_MEDUSA)
1781 UD.steprate = FDCSTEP_3;
1782 else
1783 UD.steprate = FDCSTEP_6;
1784 break;
1785 }
1786 MotorOn = 1;
1787}
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799static int __init fd_test_drive_present( int drive )
1800{
1801 unsigned long timeout;
1802 unsigned char status;
1803 int ok;
1804
1805 if (drive >= (MACH_IS_FALCON ? 1 : 2)) return( 0 );
1806 fd_select_drive( drive );
1807
1808
1809 atari_turnoff_irq( IRQ_MFP_FDC );
1810 FDC_WRITE (FDCREG_TRACK, 0xff00);
1811 FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | FDCCMDADD_H | FDCSTEP_6 );
1812
1813 timeout = jiffies + 2*HZ+HZ/2;
1814 while (time_before(jiffies, timeout))
1815 if (!(mfp.par_dt_reg & 0x20))
1816 break;
1817
1818 status = FDC_READ( FDCREG_STATUS );
1819 ok = (status & FDCSTAT_TR00) != 0;
1820
1821
1822
1823 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1824 udelay(500);
1825 status = FDC_READ( FDCREG_STATUS );
1826 udelay(20);
1827
1828 if (ok) {
1829
1830 FDC_WRITE( FDCREG_DATA, 0 );
1831 FDC_WRITE( FDCREG_CMD, FDCCMD_SEEK );
1832 while( mfp.par_dt_reg & 0x20 )
1833 ;
1834 status = FDC_READ( FDCREG_STATUS );
1835 }
1836
1837 atari_turnon_irq( IRQ_MFP_FDC );
1838 return( ok );
1839}
1840
1841
1842
1843
1844
1845
1846static void __init config_types( void )
1847{
1848 int drive, cnt = 0;
1849
1850
1851 if (ATARIHW_PRESENT(FDCSPEED))
1852 dma_wd.fdc_speed = 0;
1853
1854 printk(KERN_INFO "Probing floppy drive(s):\n");
1855 for( drive = 0; drive < FD_MAX_UNITS; drive++ ) {
1856 fd_probe( drive );
1857 if (UD.connected) {
1858 printk(KERN_INFO "fd%d\n", drive);
1859 ++cnt;
1860 }
1861 }
1862
1863 if (FDC_READ( FDCREG_STATUS ) & FDCSTAT_BUSY) {
1864
1865
1866
1867
1868
1869
1870 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1871 udelay(500);
1872 FDC_READ( FDCREG_STATUS );
1873 udelay(20);
1874 }
1875
1876 if (cnt > 0) {
1877 start_motor_off_timer();
1878 if (cnt == 1) fd_select_drive( 0 );
1879 start_check_change_timer();
1880 }
1881}
1882
1883
1884
1885
1886
1887
1888
1889static int floppy_open( struct inode *inode, struct file *filp )
1890{
1891 int drive, type;
1892 int old_dev;
1893
1894 if (!filp) {
1895 DPRINT (("Weird, open called with filp=0\n"));
1896 return -EIO;
1897 }
1898
1899 drive = MINOR(inode->i_rdev) & 3;
1900 type = MINOR(inode->i_rdev) >> 2;
1901 DPRINT(("fd_open: type=%d\n",type));
1902 if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
1903 return -ENXIO;
1904
1905 old_dev = fd_device[drive];
1906
1907 if (fd_ref[drive] && old_dev != MINOR(inode->i_rdev))
1908 return -EBUSY;
1909
1910 if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1911 return -EBUSY;
1912
1913 if (filp->f_flags & O_EXCL)
1914 fd_ref[drive] = -1;
1915 else
1916 fd_ref[drive]++;
1917
1918 fd_device[drive] = MINOR(inode->i_rdev);
1919
1920 if (old_dev && old_dev != MINOR(inode->i_rdev))
1921 invalidate_buffers(MKDEV(FLOPPY_MAJOR, old_dev));
1922
1923 if (filp->f_flags & O_NDELAY)
1924 return 0;
1925
1926 if (filp->f_mode & 3) {
1927 check_disk_change(inode->i_rdev);
1928 if (filp->f_mode & 2) {
1929 if (UD.wpstat) {
1930 floppy_release(inode, filp);
1931 return -EROFS;
1932 }
1933 }
1934 }
1935
1936 return 0;
1937}
1938
1939
1940static int floppy_release( struct inode * inode, struct file * filp )
1941{
1942 int drive = MINOR(inode->i_rdev) & 3;
1943
1944 if (fd_ref[drive] < 0)
1945 fd_ref[drive] = 0;
1946 else if (!fd_ref[drive]--) {
1947 printk(KERN_ERR "floppy_release with fd_ref == 0");
1948 fd_ref[drive] = 0;
1949 }
1950
1951 return 0;
1952}
1953
1954static struct block_device_operations floppy_fops = {
1955 owner: THIS_MODULE,
1956 open: floppy_open,
1957 release: floppy_release,
1958 ioctl: fd_ioctl,
1959 check_media_change: check_floppy_change,
1960 revalidate: floppy_revalidate,
1961};
1962
1963int __init atari_floppy_init (void)
1964{
1965 int i;
1966
1967 if (!MACH_IS_ATARI)
1968
1969 return -ENXIO;
1970
1971 if (MACH_IS_HADES)
1972
1973 return -ENXIO;
1974
1975 if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
1976 printk(KERN_ERR "Unable to get major %d for floppy\n",MAJOR_NR);
1977 return -EBUSY;
1978 }
1979
1980 if (UseTrackbuffer < 0)
1981
1982
1983
1984
1985 UseTrackbuffer = !MACH_IS_MEDUSA;
1986
1987
1988 SelectedDrive = -1;
1989 BufferDrive = -1;
1990
1991 DMABuffer = atari_stram_alloc(BUFFER_SIZE+512, "ataflop");
1992 if (!DMABuffer) {
1993 printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
1994 unregister_blkdev(MAJOR_NR, "fd");
1995 return -ENOMEM;
1996 }
1997 TrackBuffer = DMABuffer + 512;
1998 PhysDMABuffer = virt_to_phys(DMABuffer);
1999 PhysTrackBuffer = virt_to_phys(TrackBuffer);
2000 BufferDrive = BufferSide = BufferTrack = -1;
2001
2002 for (i = 0; i < FD_MAX_UNITS; i++) {
2003 unit[i].track = -1;
2004 unit[i].flags = 0;
2005 }
2006
2007 for (i = 0; i < 256; i++)
2008 if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_MINORS) {
2009 int type = minor2disktype[(i >> 2) - 1].index;
2010 floppy_sizes[i] = disk_type[type].blocks >> 1;
2011 } else
2012 floppy_sizes[i] = MAX_DISK_SIZE;
2013
2014 blk_size[MAJOR_NR] = floppy_sizes;
2015 blksize_size[MAJOR_NR] = floppy_blocksizes;
2016 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
2017
2018 printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n",
2019 DriveType == 0 ? 'D' : DriveType == 1 ? 'H' : 'E',
2020 UseTrackbuffer ? "" : "no ");
2021 config_types();
2022
2023 (void)do_floppy;
2024 return 0;
2025}
2026
2027
2028void __init atari_floppy_setup( char *str, int *ints )
2029{
2030 int i;
2031
2032 if (ints[0] < 1) {
2033 printk(KERN_ERR "ataflop_setup: no arguments!\n" );
2034 return;
2035 }
2036 else if (ints[0] > 2+FD_MAX_UNITS) {
2037 printk(KERN_ERR "ataflop_setup: too many arguments\n" );
2038 }
2039
2040 if (ints[1] < 0 || ints[1] > 2)
2041 printk(KERN_ERR "ataflop_setup: bad drive type\n" );
2042 else
2043 DriveType = ints[1];
2044
2045 if (ints[0] >= 2)
2046 UseTrackbuffer = (ints[2] > 0);
2047
2048 for( i = 3; i <= ints[0] && i-3 < FD_MAX_UNITS; ++i ) {
2049 if (ints[i] != 2 && ints[i] != 3 && ints[i] != 6 && ints[i] != 12)
2050 printk(KERN_ERR "ataflop_setup: bad steprate\n" );
2051 else
2052 UserSteprate[i-3] = ints[i];
2053 }
2054}
2055
2056#ifdef MODULE
2057
2058MODULE_LICENSE("GPL");
2059
2060int init_module (void)
2061{
2062 if (!MACH_IS_ATARI)
2063 return -ENXIO;
2064 return atari_floppy_init ();
2065}
2066
2067void cleanup_module (void)
2068{
2069 unregister_blkdev(MAJOR_NR, "fd");
2070
2071 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
2072 del_timer_sync(&fd_timer);
2073 atari_stram_free( DMABuffer );
2074}
2075#endif
2076
2077