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#include <linux/module.h>
57#include <linux/slab.h>
58
59#include <linux/fd.h>
60#include <linux/hdreg.h>
61#include <linux/delay.h>
62#include <linux/init.h>
63#include <linux/mutex.h>
64#include <linux/fs.h>
65#include <linux/blk-mq.h>
66#include <linux/elevator.h>
67#include <linux/interrupt.h>
68#include <linux/platform_device.h>
69
70#include <asm/setup.h>
71#include <linux/uaccess.h>
72#include <asm/amigahw.h>
73#include <asm/amigaints.h>
74#include <asm/irq.h>
75
76#undef DEBUG
77
78#define RAW_IOCTL
79#ifdef RAW_IOCTL
80#define IOCTL_RAW_TRACK 0x5254524B
81#endif
82
83
84
85
86
87
88
89
90
91#define DSKRDY (0x1<<5)
92#define DSKTRACK0 (0x1<<4)
93#define DSKPROT (0x1<<3)
94#define DSKCHANGE (0x1<<2)
95
96
97
98
99
100#define DSKMOTOR (0x1<<7)
101#define DSKSEL3 (0x1<<6)
102#define DSKSEL2 (0x1<<5)
103#define DSKSEL1 (0x1<<4)
104#define DSKSEL0 (0x1<<3)
105#define DSKSIDE (0x1<<2)
106#define DSKDIREC (0x1<<1)
107#define DSKSTEP (0x1)
108
109
110
111
112
113#define DSKBYT (1<<15)
114#define DMAON (1<<14)
115#define DISKWRITE (1<<13)
116#define WORDEQUAL (1<<12)
117
118
119
120
121
122
123#ifndef SETCLR
124#define ADK_SETCLR (1<<15)
125#endif
126#define ADK_PRECOMP1 (1<<14)
127#define ADK_PRECOMP0 (1<<13)
128#define ADK_MFMPREC (1<<12)
129#define ADK_WORDSYNC (1<<10)
130#define ADK_MSBSYNC (1<<9)
131#define ADK_FAST (1<<8)
132
133
134
135
136
137#define DSKLEN_DMAEN (1<<15)
138#define DSKLEN_WRITE (1<<14)
139
140
141
142
143
144#define DSKINDEX (0x1<<4)
145
146
147
148
149
150#define MFM_SYNC 0x4489
151
152
153#define FD_RECALIBRATE 0x07
154#define FD_SEEK 0x0F
155#define FD_READ 0xE6
156#define FD_WRITE 0xC5
157#define FD_SENSEI 0x08
158#define FD_SPECIFY 0x03
159#define FD_FORMAT 0x4D
160#define FD_VERSION 0x10
161#define FD_CONFIGURE 0x13
162#define FD_PERPENDICULAR 0x12
163
164#define FD_MAX_UNITS 4
165#define FLOPPY_MAX_SECTORS 22
166
167struct fd_data_type {
168 char *name;
169 int sects;
170 int (*read_fkt)(int);
171 void (*write_fkt)(int);
172};
173
174struct fd_drive_type {
175 unsigned long code;
176 char *name;
177 unsigned int tracks;
178 unsigned int heads;
179 unsigned int read_size;
180 unsigned int write_size;
181 unsigned int sect_mult;
182 unsigned int precomp1;
183 unsigned int precomp2;
184 unsigned int step_delay;
185 unsigned int settle_time;
186 unsigned int side_time;
187};
188
189struct amiga_floppy_struct {
190 struct fd_drive_type *type;
191 struct fd_data_type *dtype;
192 int track;
193 unsigned char *trackbuf;
194
195 int blocks;
196
197 int changed;
198 int disk;
199 int motor;
200 int busy;
201 int dirty;
202 int status;
203 struct gendisk *gendisk;
204 struct blk_mq_tag_set tag_set;
205};
206
207
208
209
210#define FD_OK 0
211#define FD_ERROR -1
212#define FD_NOUNIT 1
213#define FD_UNITBUSY 2
214#define FD_NOTACTIVE 3
215#define FD_NOTREADY 4
216
217#define MFM_NOSYNC 1
218#define MFM_HEADER 2
219#define MFM_DATA 3
220#define MFM_TRACK 4
221
222
223
224
225#define FD_NODRIVE 0x00000000
226#define FD_DD_3 0xffffffff
227#define FD_HD_3 0x55555555
228#define FD_DD_5 0xaaaaaaaa
229
230static DEFINE_MUTEX(amiflop_mutex);
231static unsigned long int fd_def_df0 = FD_DD_3;
232
233module_param(fd_def_df0, ulong, 0);
234MODULE_LICENSE("GPL");
235
236
237
238
239#define MOTOR_ON (ciab.prb &= ~DSKMOTOR)
240#define MOTOR_OFF (ciab.prb |= DSKMOTOR)
241#define SELECT(mask) (ciab.prb &= ~mask)
242#define DESELECT(mask) (ciab.prb |= mask)
243#define SELMASK(drive) (1 << (3 + (drive & 3)))
244
245static struct fd_drive_type drive_types[] = {
246
247
248{ FD_DD_3, "DD 3.5", 80, 2, 14716, 13630, 1, 80,161, 3, 18, 1},
249{ FD_HD_3, "HD 3.5", 80, 2, 28344, 27258, 2, 80,161, 3, 18, 1},
250{ FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2},
251{ FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
252};
253static int num_dr_types = ARRAY_SIZE(drive_types);
254
255static int amiga_read(int), dos_read(int);
256static void amiga_write(int), dos_write(int);
257static struct fd_data_type data_types[] = {
258 { "Amiga", 11 , amiga_read, amiga_write},
259 { "MS-Dos", 9, dos_read, dos_write}
260};
261
262
263static struct amiga_floppy_struct unit[FD_MAX_UNITS];
264
265static struct timer_list flush_track_timer[FD_MAX_UNITS];
266static struct timer_list post_write_timer;
267static unsigned long post_write_timer_drive;
268static struct timer_list motor_on_timer;
269static struct timer_list motor_off_timer[FD_MAX_UNITS];
270static int on_attempts;
271
272
273
274static volatile int fdc_busy = -1;
275static volatile int fdc_nested;
276static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
277
278static DECLARE_COMPLETION(motor_on_completion);
279
280static volatile int selected = -1;
281
282static int writepending;
283static int writefromint;
284static char *raw_buf;
285
286static DEFINE_SPINLOCK(amiflop_lock);
287
288#define RAW_BUF_SIZE 30000
289
290
291
292
293
294
295static volatile char block_flag;
296static DECLARE_WAIT_QUEUE_HEAD(wait_fd_block);
297
298
299static unsigned char mfmencode[16]={
300 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
301 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
302};
303static unsigned char mfmdecode[128];
304
305
306static DECLARE_COMPLETION(ms_wait_completion);
307#define MS_TICKS ((amiga_eclock+50)/1000)
308
309
310
311
312
313
314#define MAX_ERRORS 12
315
316#define custom amiga_custom
317
318
319static int fd_ref[4] = { 0,0,0,0 };
320static int fd_device[4] = { 0, 0, 0, 0 };
321
322
323
324
325
326
327
328
329
330static irqreturn_t ms_isr(int irq, void *dummy)
331{
332 complete(&ms_wait_completion);
333 return IRQ_HANDLED;
334}
335
336
337
338static void ms_delay(int ms)
339{
340 int ticks;
341 static DEFINE_MUTEX(mutex);
342
343 if (ms > 0) {
344 mutex_lock(&mutex);
345 ticks = MS_TICKS*ms-1;
346 ciaa.tblo=ticks%256;
347 ciaa.tbhi=ticks/256;
348 ciaa.crb=0x19;
349 wait_for_completion(&ms_wait_completion);
350 mutex_unlock(&mutex);
351 }
352}
353
354
355
356
357static inline int try_fdc(int drive)
358{
359 drive &= 3;
360 return ((fdc_busy < 0) || (fdc_busy == drive));
361}
362
363static void get_fdc(int drive)
364{
365 unsigned long flags;
366
367 drive &= 3;
368#ifdef DEBUG
369 printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
370#endif
371 local_irq_save(flags);
372 wait_event(fdc_wait, try_fdc(drive));
373 fdc_busy = drive;
374 fdc_nested++;
375 local_irq_restore(flags);
376}
377
378static inline void rel_fdc(void)
379{
380#ifdef DEBUG
381 if (fdc_nested == 0)
382 printk("fd: unmatched rel_fdc\n");
383 printk("rel_fdc: fdc_busy %d fdc_nested %d\n",fdc_busy,fdc_nested);
384#endif
385 fdc_nested--;
386 if (fdc_nested == 0) {
387 fdc_busy = -1;
388 wake_up(&fdc_wait);
389 }
390}
391
392static void fd_select (int drive)
393{
394 unsigned char prb = ~0;
395
396 drive&=3;
397#ifdef DEBUG
398 printk("selecting %d\n",drive);
399#endif
400 if (drive == selected)
401 return;
402 get_fdc(drive);
403 selected = drive;
404
405 if (unit[drive].track % 2 != 0)
406 prb &= ~DSKSIDE;
407 if (unit[drive].motor == 1)
408 prb &= ~DSKMOTOR;
409 ciab.prb |= (SELMASK(0)|SELMASK(1)|SELMASK(2)|SELMASK(3));
410 ciab.prb = prb;
411 prb &= ~SELMASK(drive);
412 ciab.prb = prb;
413 rel_fdc();
414}
415
416static void fd_deselect (int drive)
417{
418 unsigned char prb;
419 unsigned long flags;
420
421 drive&=3;
422#ifdef DEBUG
423 printk("deselecting %d\n",drive);
424#endif
425 if (drive != selected) {
426 printk(KERN_WARNING "Deselecting drive %d while %d was selected!\n",drive,selected);
427 return;
428 }
429
430 get_fdc(drive);
431 local_irq_save(flags);
432
433 selected = -1;
434
435 prb = ciab.prb;
436 prb |= (SELMASK(0)|SELMASK(1)|SELMASK(2)|SELMASK(3));
437 ciab.prb = prb;
438
439 local_irq_restore (flags);
440 rel_fdc();
441
442}
443
444static void motor_on_callback(struct timer_list *unused)
445{
446 if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
447 complete_all(&motor_on_completion);
448 } else {
449 motor_on_timer.expires = jiffies + HZ/10;
450 add_timer(&motor_on_timer);
451 }
452}
453
454static int fd_motor_on(int nr)
455{
456 nr &= 3;
457
458 del_timer(motor_off_timer + nr);
459
460 if (!unit[nr].motor) {
461 unit[nr].motor = 1;
462 fd_select(nr);
463
464 reinit_completion(&motor_on_completion);
465 mod_timer(&motor_on_timer, jiffies + HZ/2);
466
467 on_attempts = 10;
468 wait_for_completion(&motor_on_completion);
469 fd_deselect(nr);
470 }
471
472 if (on_attempts == 0) {
473 on_attempts = -1;
474#if 0
475 printk (KERN_ERR "motor_on failed, turning motor off\n");
476 fd_motor_off (motor_off_timer + nr);
477 return 0;
478#else
479 printk (KERN_WARNING "DSKRDY not set after 1.5 seconds - assuming drive is spinning notwithstanding\n");
480#endif
481 }
482
483 return 1;
484}
485
486static void fd_motor_off(struct timer_list *timer)
487{
488 unsigned long drive = ((unsigned long)timer -
489 (unsigned long)&motor_off_timer[0]) /
490 sizeof(motor_off_timer[0]);
491
492 drive&=3;
493 if (!try_fdc(drive)) {
494
495 timer->expires = jiffies + 1;
496 add_timer(timer);
497 return;
498 }
499 unit[drive].motor = 0;
500 fd_select(drive);
501 udelay (1);
502 fd_deselect(drive);
503}
504
505static void floppy_off (unsigned int nr)
506{
507 int drive;
508
509 drive = nr & 3;
510 mod_timer(motor_off_timer + drive, jiffies + 3*HZ);
511}
512
513static int fd_calibrate(int drive)
514{
515 unsigned char prb;
516 int n;
517
518 drive &= 3;
519 get_fdc(drive);
520 if (!fd_motor_on (drive))
521 return 0;
522 fd_select (drive);
523 prb = ciab.prb;
524 prb |= DSKSIDE;
525 prb &= ~DSKDIREC;
526 ciab.prb = prb;
527 for (n = unit[drive].type->tracks/2; n != 0; --n) {
528 if (ciaa.pra & DSKTRACK0)
529 break;
530 prb &= ~DSKSTEP;
531 ciab.prb = prb;
532 prb |= DSKSTEP;
533 udelay (2);
534 ciab.prb = prb;
535 ms_delay(unit[drive].type->step_delay);
536 }
537 ms_delay (unit[drive].type->settle_time);
538 prb |= DSKDIREC;
539 n = unit[drive].type->tracks + 20;
540 for (;;) {
541 prb &= ~DSKSTEP;
542 ciab.prb = prb;
543 prb |= DSKSTEP;
544 udelay (2);
545 ciab.prb = prb;
546 ms_delay(unit[drive].type->step_delay + 1);
547 if ((ciaa.pra & DSKTRACK0) == 0)
548 break;
549 if (--n == 0) {
550 printk (KERN_ERR "fd%d: calibrate failed, turning motor off\n", drive);
551 fd_motor_off (motor_off_timer + drive);
552 unit[drive].track = -1;
553 rel_fdc();
554 return 0;
555 }
556 }
557 unit[drive].track = 0;
558 ms_delay(unit[drive].type->settle_time);
559
560 rel_fdc();
561 fd_deselect(drive);
562 return 1;
563}
564
565static int fd_seek(int drive, int track)
566{
567 unsigned char prb;
568 int cnt;
569
570#ifdef DEBUG
571 printk("seeking drive %d to track %d\n",drive,track);
572#endif
573 drive &= 3;
574 get_fdc(drive);
575 if (unit[drive].track == track) {
576 rel_fdc();
577 return 1;
578 }
579 if (!fd_motor_on(drive)) {
580 rel_fdc();
581 return 0;
582 }
583 if (unit[drive].track < 0 && !fd_calibrate(drive)) {
584 rel_fdc();
585 return 0;
586 }
587
588 fd_select (drive);
589 cnt = unit[drive].track/2 - track/2;
590 prb = ciab.prb;
591 prb |= DSKSIDE | DSKDIREC;
592 if (track % 2 != 0)
593 prb &= ~DSKSIDE;
594 if (cnt < 0) {
595 cnt = - cnt;
596 prb &= ~DSKDIREC;
597 }
598 ciab.prb = prb;
599 if (track % 2 != unit[drive].track % 2)
600 ms_delay (unit[drive].type->side_time);
601 unit[drive].track = track;
602 if (cnt == 0) {
603 rel_fdc();
604 fd_deselect(drive);
605 return 1;
606 }
607 do {
608 prb &= ~DSKSTEP;
609 ciab.prb = prb;
610 prb |= DSKSTEP;
611 udelay (1);
612 ciab.prb = prb;
613 ms_delay (unit[drive].type->step_delay);
614 } while (--cnt != 0);
615 ms_delay (unit[drive].type->settle_time);
616
617 rel_fdc();
618 fd_deselect(drive);
619 return 1;
620}
621
622static unsigned long fd_get_drive_id(int drive)
623{
624 int i;
625 ulong id = 0;
626
627 drive&=3;
628 get_fdc(drive);
629
630 MOTOR_ON;
631 udelay(2);
632 SELECT(SELMASK(drive));
633 udelay(2);
634 DESELECT(SELMASK(drive));
635 udelay(2);
636 MOTOR_OFF;
637 udelay(2);
638 SELECT(SELMASK(drive));
639 udelay(2);
640 DESELECT(SELMASK(drive));
641 udelay(2);
642
643
644 for (i=0; i<32; i++) {
645 SELECT(SELMASK(drive));
646 udelay(2);
647
648
649 id <<= 1;
650 id |= (ciaa.pra & DSKRDY) ? 0 : 1;
651
652 DESELECT(SELMASK(drive));
653 }
654
655 rel_fdc();
656
657
658
659
660
661
662
663 if(drive == 0 && id == FD_NODRIVE)
664 {
665 id = fd_def_df0;
666 printk(KERN_NOTICE "fd: drive 0 didn't identify, setting default %08lx\n", (ulong)fd_def_df0);
667 }
668
669 return (id);
670}
671
672static irqreturn_t fd_block_done(int irq, void *dummy)
673{
674 if (block_flag)
675 custom.dsklen = 0x4000;
676
677 if (block_flag == 2) {
678 writepending = 2;
679 post_write_timer.expires = jiffies + 1;
680 post_write_timer_drive = selected;
681 add_timer(&post_write_timer);
682 }
683 else {
684 block_flag = 0;
685 wake_up (&wait_fd_block);
686 }
687 return IRQ_HANDLED;
688}
689
690static void raw_read(int drive)
691{
692 drive&=3;
693 get_fdc(drive);
694 wait_event(wait_fd_block, !block_flag);
695 fd_select(drive);
696
697 custom.adkcon = ADK_MSBSYNC;
698 custom.adkcon = ADK_SETCLR|ADK_WORDSYNC|ADK_FAST;
699
700 custom.dsksync = MFM_SYNC;
701
702 custom.dsklen = 0;
703 custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf);
704 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN;
705 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN;
706
707 block_flag = 1;
708
709 wait_event(wait_fd_block, !block_flag);
710
711 custom.dsklen = 0;
712 fd_deselect(drive);
713 rel_fdc();
714}
715
716static int raw_write(int drive)
717{
718 ushort adk;
719
720 drive&=3;
721 get_fdc(drive);
722 if ((ciaa.pra & DSKPROT) == 0) {
723 rel_fdc();
724 return 0;
725 }
726 wait_event(wait_fd_block, !block_flag);
727 fd_select(drive);
728
729 custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
730
731 adk = ADK_SETCLR|ADK_FAST;
732 if ((ulong)unit[drive].track >= unit[drive].type->precomp2)
733 adk |= ADK_PRECOMP1;
734 else if ((ulong)unit[drive].track >= unit[drive].type->precomp1)
735 adk |= ADK_PRECOMP0;
736 custom.adkcon = adk;
737
738 custom.dsklen = DSKLEN_WRITE;
739 custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf);
740 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE;
741 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE;
742
743 block_flag = 2;
744 return 1;
745}
746
747
748
749
750
751static void post_write (unsigned long drive)
752{
753#ifdef DEBUG
754 printk("post_write for drive %ld\n",drive);
755#endif
756 drive &= 3;
757 custom.dsklen = 0;
758 block_flag = 0;
759 writepending = 0;
760 writefromint = 0;
761 unit[drive].dirty = 0;
762 wake_up(&wait_fd_block);
763 fd_deselect(drive);
764 rel_fdc();
765}
766
767static void post_write_callback(struct timer_list *timer)
768{
769 post_write(post_write_timer_drive);
770}
771
772
773
774
775
776
777
778static unsigned long scan_sync(unsigned long raw, unsigned long end)
779{
780 ushort *ptr = (ushort *)raw, *endp = (ushort *)end;
781
782 while (ptr < endp && *ptr++ != 0x4489)
783 ;
784 if (ptr < endp) {
785 while (*ptr == 0x4489 && ptr < endp)
786 ptr++;
787 return (ulong)ptr;
788 }
789 return 0;
790}
791
792static inline unsigned long checksum(unsigned long *addr, int len)
793{
794 unsigned long csum = 0;
795
796 len /= sizeof(*addr);
797 while (len-- > 0)
798 csum ^= *addr++;
799 csum = ((csum>>1) & 0x55555555) ^ (csum & 0x55555555);
800
801 return csum;
802}
803
804static unsigned long decode (unsigned long *data, unsigned long *raw,
805 int len)
806{
807 ulong *odd, *even;
808
809
810 len >>= 2;
811 odd = raw;
812 even = odd + len;
813
814
815 raw += len * 2;
816
817 do {
818 *data++ = ((*odd++ & 0x55555555) << 1) | (*even++ & 0x55555555);
819 } while (--len != 0);
820
821 return (ulong)raw;
822}
823
824struct header {
825 unsigned char magic;
826 unsigned char track;
827 unsigned char sect;
828 unsigned char ord;
829 unsigned char labels[16];
830 unsigned long hdrchk;
831 unsigned long datachk;
832};
833
834static int amiga_read(int drive)
835{
836 unsigned long raw;
837 unsigned long end;
838 int scnt;
839 unsigned long csum;
840 struct header hdr;
841
842 drive&=3;
843 raw = (long) raw_buf;
844 end = raw + unit[drive].type->read_size;
845
846 for (scnt = 0;scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) {
847 if (!(raw = scan_sync(raw, end))) {
848 printk (KERN_INFO "can't find sync for sector %d\n", scnt);
849 return MFM_NOSYNC;
850 }
851
852 raw = decode ((ulong *)&hdr.magic, (ulong *)raw, 4);
853 raw = decode ((ulong *)&hdr.labels, (ulong *)raw, 16);
854 raw = decode ((ulong *)&hdr.hdrchk, (ulong *)raw, 4);
855 raw = decode ((ulong *)&hdr.datachk, (ulong *)raw, 4);
856 csum = checksum((ulong *)&hdr,
857 (char *)&hdr.hdrchk-(char *)&hdr);
858
859#ifdef DEBUG
860 printk ("(%x,%d,%d,%d) (%lx,%lx,%lx,%lx) %lx %lx\n",
861 hdr.magic, hdr.track, hdr.sect, hdr.ord,
862 *(ulong *)&hdr.labels[0], *(ulong *)&hdr.labels[4],
863 *(ulong *)&hdr.labels[8], *(ulong *)&hdr.labels[12],
864 hdr.hdrchk, hdr.datachk);
865#endif
866
867 if (hdr.hdrchk != csum) {
868 printk(KERN_INFO "MFM_HEADER: %08lx,%08lx\n", hdr.hdrchk, csum);
869 return MFM_HEADER;
870 }
871
872
873 if (hdr.track != unit[drive].track) {
874 printk(KERN_INFO "MFM_TRACK: %d, %d\n", hdr.track, unit[drive].track);
875 return MFM_TRACK;
876 }
877
878 raw = decode ((ulong *)(unit[drive].trackbuf + hdr.sect*512),
879 (ulong *)raw, 512);
880 csum = checksum((ulong *)(unit[drive].trackbuf + hdr.sect*512), 512);
881
882 if (hdr.datachk != csum) {
883 printk(KERN_INFO "MFM_DATA: (%x:%d:%d:%d) sc=%d %lx, %lx\n",
884 hdr.magic, hdr.track, hdr.sect, hdr.ord, scnt,
885 hdr.datachk, csum);
886 printk (KERN_INFO "data=(%lx,%lx,%lx,%lx)\n",
887 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[0],
888 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[1],
889 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[2],
890 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[3]);
891 return MFM_DATA;
892 }
893 }
894
895 return 0;
896}
897
898static void encode(unsigned long data, unsigned long *dest)
899{
900 unsigned long data2;
901
902 data &= 0x55555555;
903 data2 = data ^ 0x55555555;
904 data |= ((data2 >> 1) | 0x80000000) & (data2 << 1);
905
906 if (*(dest - 1) & 0x00000001)
907 data &= 0x7FFFFFFF;
908
909 *dest = data;
910}
911
912static void encode_block(unsigned long *dest, unsigned long *src, int len)
913{
914 int cnt, to_cnt = 0;
915 unsigned long data;
916
917
918 for (cnt = 0; cnt < len / 4; cnt++) {
919 data = src[cnt] >> 1;
920 encode(data, dest + to_cnt++);
921 }
922
923
924 for (cnt = 0; cnt < len / 4; cnt++) {
925 data = src[cnt];
926 encode(data, dest + to_cnt++);
927 }
928}
929
930static unsigned long *putsec(int disk, unsigned long *raw, int cnt)
931{
932 struct header hdr;
933 int i;
934
935 disk&=3;
936 *raw = (raw[-1]&1) ? 0x2AAAAAAA : 0xAAAAAAAA;
937 raw++;
938 *raw++ = 0x44894489;
939
940 hdr.magic = 0xFF;
941 hdr.track = unit[disk].track;
942 hdr.sect = cnt;
943 hdr.ord = unit[disk].dtype->sects * unit[disk].type->sect_mult - cnt;
944 for (i = 0; i < 16; i++)
945 hdr.labels[i] = 0;
946 hdr.hdrchk = checksum((ulong *)&hdr,
947 (char *)&hdr.hdrchk-(char *)&hdr);
948 hdr.datachk = checksum((ulong *)(unit[disk].trackbuf+cnt*512), 512);
949
950 encode_block(raw, (ulong *)&hdr.magic, 4);
951 raw += 2;
952 encode_block(raw, (ulong *)&hdr.labels, 16);
953 raw += 8;
954 encode_block(raw, (ulong *)&hdr.hdrchk, 4);
955 raw += 2;
956 encode_block(raw, (ulong *)&hdr.datachk, 4);
957 raw += 2;
958 encode_block(raw, (ulong *)(unit[disk].trackbuf+cnt*512), 512);
959 raw += 256;
960
961 return raw;
962}
963
964static void amiga_write(int disk)
965{
966 unsigned int cnt;
967 unsigned long *ptr = (unsigned long *)raw_buf;
968
969 disk&=3;
970
971 for (cnt = 0; cnt < 415 * unit[disk].type->sect_mult; cnt++)
972 *ptr++ = 0xaaaaaaaa;
973
974
975 for (cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++)
976 ptr = putsec (disk, ptr, cnt);
977 *(ushort *)ptr = (ptr[-1]&1) ? 0x2AA8 : 0xAAA8;
978}
979
980
981struct dos_header {
982 unsigned char track,
983 side,
984 sec,
985 len_desc;
986 unsigned short crc;
987
988
989
990 unsigned char gap1[22];
991};
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048static ushort dos_crc(void * data_a3, int data_d0, int data_d1, int data_d3)
1049{
1050 static unsigned char CRCTable1[] = {
1051 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1,
1052 0x12,0x02,0x32,0x22,0x52,0x42,0x72,0x62,0x93,0x83,0xb3,0xa3,0xd3,0xc3,0xf3,0xe3,
1053 0x24,0x34,0x04,0x14,0x64,0x74,0x44,0x54,0xa5,0xb5,0x85,0x95,0xe5,0xf5,0xc5,0xd5,
1054 0x36,0x26,0x16,0x06,0x76,0x66,0x56,0x46,0xb7,0xa7,0x97,0x87,0xf7,0xe7,0xd7,0xc7,
1055 0x48,0x58,0x68,0x78,0x08,0x18,0x28,0x38,0xc9,0xd9,0xe9,0xf9,0x89,0x99,0xa9,0xb9,
1056 0x5a,0x4a,0x7a,0x6a,0x1a,0x0a,0x3a,0x2a,0xdb,0xcb,0xfb,0xeb,0x9b,0x8b,0xbb,0xab,
1057 0x6c,0x7c,0x4c,0x5c,0x2c,0x3c,0x0c,0x1c,0xed,0xfd,0xcd,0xdd,0xad,0xbd,0x8d,0x9d,
1058 0x7e,0x6e,0x5e,0x4e,0x3e,0x2e,0x1e,0x0e,0xff,0xef,0xdf,0xcf,0xbf,0xaf,0x9f,0x8f,
1059 0x91,0x81,0xb1,0xa1,0xd1,0xc1,0xf1,0xe1,0x10,0x00,0x30,0x20,0x50,0x40,0x70,0x60,
1060 0x83,0x93,0xa3,0xb3,0xc3,0xd3,0xe3,0xf3,0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72,
1061 0xb5,0xa5,0x95,0x85,0xf5,0xe5,0xd5,0xc5,0x34,0x24,0x14,0x04,0x74,0x64,0x54,0x44,
1062 0xa7,0xb7,0x87,0x97,0xe7,0xf7,0xc7,0xd7,0x26,0x36,0x06,0x16,0x66,0x76,0x46,0x56,
1063 0xd9,0xc9,0xf9,0xe9,0x99,0x89,0xb9,0xa9,0x58,0x48,0x78,0x68,0x18,0x08,0x38,0x28,
1064 0xcb,0xdb,0xeb,0xfb,0x8b,0x9b,0xab,0xbb,0x4a,0x5a,0x6a,0x7a,0x0a,0x1a,0x2a,0x3a,
1065 0xfd,0xed,0xdd,0xcd,0xbd,0xad,0x9d,0x8d,0x7c,0x6c,0x5c,0x4c,0x3c,0x2c,0x1c,0x0c,
1066 0xef,0xff,0xcf,0xdf,0xaf,0xbf,0x8f,0x9f,0x6e,0x7e,0x4e,0x5e,0x2e,0x3e,0x0e,0x1e
1067 };
1068
1069 static unsigned char CRCTable2[] = {
1070 0x00,0x21,0x42,0x63,0x84,0xa5,0xc6,0xe7,0x08,0x29,0x4a,0x6b,0x8c,0xad,0xce,0xef,
1071 0x31,0x10,0x73,0x52,0xb5,0x94,0xf7,0xd6,0x39,0x18,0x7b,0x5a,0xbd,0x9c,0xff,0xde,
1072 0x62,0x43,0x20,0x01,0xe6,0xc7,0xa4,0x85,0x6a,0x4b,0x28,0x09,0xee,0xcf,0xac,0x8d,
1073 0x53,0x72,0x11,0x30,0xd7,0xf6,0x95,0xb4,0x5b,0x7a,0x19,0x38,0xdf,0xfe,0x9d,0xbc,
1074 0xc4,0xe5,0x86,0xa7,0x40,0x61,0x02,0x23,0xcc,0xed,0x8e,0xaf,0x48,0x69,0x0a,0x2b,
1075 0xf5,0xd4,0xb7,0x96,0x71,0x50,0x33,0x12,0xfd,0xdc,0xbf,0x9e,0x79,0x58,0x3b,0x1a,
1076 0xa6,0x87,0xe4,0xc5,0x22,0x03,0x60,0x41,0xae,0x8f,0xec,0xcd,0x2a,0x0b,0x68,0x49,
1077 0x97,0xb6,0xd5,0xf4,0x13,0x32,0x51,0x70,0x9f,0xbe,0xdd,0xfc,0x1b,0x3a,0x59,0x78,
1078 0x88,0xa9,0xca,0xeb,0x0c,0x2d,0x4e,0x6f,0x80,0xa1,0xc2,0xe3,0x04,0x25,0x46,0x67,
1079 0xb9,0x98,0xfb,0xda,0x3d,0x1c,0x7f,0x5e,0xb1,0x90,0xf3,0xd2,0x35,0x14,0x77,0x56,
1080 0xea,0xcb,0xa8,0x89,0x6e,0x4f,0x2c,0x0d,0xe2,0xc3,0xa0,0x81,0x66,0x47,0x24,0x05,
1081 0xdb,0xfa,0x99,0xb8,0x5f,0x7e,0x1d,0x3c,0xd3,0xf2,0x91,0xb0,0x57,0x76,0x15,0x34,
1082 0x4c,0x6d,0x0e,0x2f,0xc8,0xe9,0x8a,0xab,0x44,0x65,0x06,0x27,0xc0,0xe1,0x82,0xa3,
1083 0x7d,0x5c,0x3f,0x1e,0xf9,0xd8,0xbb,0x9a,0x75,0x54,0x37,0x16,0xf1,0xd0,0xb3,0x92,
1084 0x2e,0x0f,0x6c,0x4d,0xaa,0x8b,0xe8,0xc9,0x26,0x07,0x64,0x45,0xa2,0x83,0xe0,0xc1,
1085 0x1f,0x3e,0x5d,0x7c,0x9b,0xba,0xd9,0xf8,0x17,0x36,0x55,0x74,0x93,0xb2,0xd1,0xf0
1086 };
1087
1088
1089 register int i;
1090 register unsigned char *CRCT1, *CRCT2, *data, c, crch, crcl;
1091
1092 CRCT1=CRCTable1;
1093 CRCT2=CRCTable2;
1094 data=data_a3;
1095 crcl=data_d1;
1096 crch=data_d0;
1097 for (i=data_d3; i>=0; i--) {
1098 c = (*data++) ^ crch;
1099 crch = CRCT1[c] ^ crcl;
1100 crcl = CRCT2[c];
1101 }
1102 return (crch<<8)|crcl;
1103}
1104
1105static inline ushort dos_hdr_crc (struct dos_header *hdr)
1106{
1107 return dos_crc(&(hdr->track), 0xb2, 0x30, 3);
1108}
1109
1110static inline ushort dos_data_crc(unsigned char *data)
1111{
1112 return dos_crc(data, 0xe2, 0x95 ,511);
1113}
1114
1115static inline unsigned char dos_decode_byte(ushort word)
1116{
1117 register ushort w2;
1118 register unsigned char byte;
1119 register unsigned char *dec = mfmdecode;
1120
1121 w2=word;
1122 w2>>=8;
1123 w2&=127;
1124 byte = dec[w2];
1125 byte <<= 4;
1126 w2 = word & 127;
1127 byte |= dec[w2];
1128 return byte;
1129}
1130
1131static unsigned long dos_decode(unsigned char *data, unsigned short *raw, int len)
1132{
1133 int i;
1134
1135 for (i = 0; i < len; i++)
1136 *data++=dos_decode_byte(*raw++);
1137 return ((ulong)raw);
1138}
1139
1140#ifdef DEBUG
1141static void dbg(unsigned long ptr)
1142{
1143 printk("raw data @%08lx: %08lx, %08lx ,%08lx, %08lx\n", ptr,
1144 ((ulong *)ptr)[0], ((ulong *)ptr)[1],
1145 ((ulong *)ptr)[2], ((ulong *)ptr)[3]);
1146}
1147#endif
1148
1149static int dos_read(int drive)
1150{
1151 unsigned long end;
1152 unsigned long raw;
1153 int scnt;
1154 unsigned short crc,data_crc[2];
1155 struct dos_header hdr;
1156
1157 drive&=3;
1158 raw = (long) raw_buf;
1159 end = raw + unit[drive].type->read_size;
1160
1161 for (scnt=0; scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) {
1162 do {
1163 if (!(raw = scan_sync (raw, end))) {
1164 printk(KERN_INFO "dos_read: no hdr sync on "
1165 "track %d, unit %d for sector %d\n",
1166 unit[drive].track,drive,scnt);
1167 return MFM_NOSYNC;
1168 }
1169#ifdef DEBUG
1170 dbg(raw);
1171#endif
1172 } while (*((ushort *)raw)!=0x5554);
1173 raw+=2;
1174 raw = dos_decode((unsigned char *)&hdr,(ushort *) raw,8);
1175 crc = dos_hdr_crc(&hdr);
1176
1177#ifdef DEBUG
1178 printk("(%3d,%d,%2d,%d) %x\n", hdr.track, hdr.side,
1179 hdr.sec, hdr.len_desc, hdr.crc);
1180#endif
1181
1182 if (crc != hdr.crc) {
1183 printk(KERN_INFO "dos_read: MFM_HEADER %04x,%04x\n",
1184 hdr.crc, crc);
1185 return MFM_HEADER;
1186 }
1187 if (hdr.track != unit[drive].track/unit[drive].type->heads) {
1188 printk(KERN_INFO "dos_read: MFM_TRACK %d, %d\n",
1189 hdr.track,
1190 unit[drive].track/unit[drive].type->heads);
1191 return MFM_TRACK;
1192 }
1193
1194 if (hdr.side != unit[drive].track%unit[drive].type->heads) {
1195 printk(KERN_INFO "dos_read: MFM_SIDE %d, %d\n",
1196 hdr.side,
1197 unit[drive].track%unit[drive].type->heads);
1198 return MFM_TRACK;
1199 }
1200
1201 if (hdr.len_desc != 2) {
1202 printk(KERN_INFO "dos_read: unknown sector len "
1203 "descriptor %d\n", hdr.len_desc);
1204 return MFM_DATA;
1205 }
1206#ifdef DEBUG
1207 printk("hdr accepted\n");
1208#endif
1209 if (!(raw = scan_sync (raw, end))) {
1210 printk(KERN_INFO "dos_read: no data sync on track "
1211 "%d, unit %d for sector%d, disk sector %d\n",
1212 unit[drive].track, drive, scnt, hdr.sec);
1213 return MFM_NOSYNC;
1214 }
1215#ifdef DEBUG
1216 dbg(raw);
1217#endif
1218
1219 if (*((ushort *)raw)!=0x5545) {
1220 printk(KERN_INFO "dos_read: no data mark after "
1221 "sync (%d,%d,%d,%d) sc=%d\n",
1222 hdr.track,hdr.side,hdr.sec,hdr.len_desc,scnt);
1223 return MFM_NOSYNC;
1224 }
1225
1226 raw+=2;
1227 raw = dos_decode((unsigned char *)(unit[drive].trackbuf + (hdr.sec - 1) * 512), (ushort *) raw, 512);
1228 raw = dos_decode((unsigned char *)data_crc,(ushort *) raw,4);
1229 crc = dos_data_crc(unit[drive].trackbuf + (hdr.sec - 1) * 512);
1230
1231 if (crc != data_crc[0]) {
1232 printk(KERN_INFO "dos_read: MFM_DATA (%d,%d,%d,%d) "
1233 "sc=%d, %x %x\n", hdr.track, hdr.side,
1234 hdr.sec, hdr.len_desc, scnt,data_crc[0], crc);
1235 printk(KERN_INFO "data=(%lx,%lx,%lx,%lx,...)\n",
1236 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[0],
1237 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[1],
1238 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[2],
1239 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[3]);
1240 return MFM_DATA;
1241 }
1242 }
1243 return 0;
1244}
1245
1246static inline ushort dos_encode_byte(unsigned char byte)
1247{
1248 register unsigned char *enc, b2, b1;
1249 register ushort word;
1250
1251 enc=mfmencode;
1252 b1=byte;
1253 b2=b1>>4;
1254 b1&=15;
1255 word=enc[b2] <<8 | enc [b1];
1256 return (word|((word&(256|64)) ? 0: 128));
1257}
1258
1259static void dos_encode_block(ushort *dest, unsigned char *src, int len)
1260{
1261 int i;
1262
1263 for (i = 0; i < len; i++) {
1264 *dest=dos_encode_byte(*src++);
1265 *dest|=((dest[-1]&1)||(*dest&0x4000))? 0: 0x8000;
1266 dest++;
1267 }
1268}
1269
1270static unsigned long *ms_putsec(int drive, unsigned long *raw, int cnt)
1271{
1272 static struct dos_header hdr={0,0,0,2,0,
1273 {78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78}};
1274 int i;
1275 static ushort crc[2]={0,0x4e4e};
1276
1277 drive&=3;
1278
1279
1280 for(i=0;i<6;i++)
1281 *raw++=0xaaaaaaaa;
1282
1283 *raw++=0x44894489;
1284 *raw++=0x44895554;
1285
1286
1287 hdr.track=unit[drive].track/unit[drive].type->heads;
1288 hdr.side=unit[drive].track%unit[drive].type->heads;
1289 hdr.sec=cnt+1;
1290 hdr.crc=dos_hdr_crc(&hdr);
1291
1292
1293 dos_encode_block((ushort *)raw,(unsigned char *) &hdr.track,28);
1294 raw+=14;
1295
1296
1297 for(i=0;i<6;i++)
1298 *raw++=0xaaaaaaaa;
1299
1300
1301 *raw++=0x44894489;
1302 *raw++=0x44895545;
1303
1304
1305 dos_encode_block((ushort *)raw,
1306 (unsigned char *)unit[drive].trackbuf+cnt*512,512);
1307 raw+=256;
1308
1309
1310 crc[0]=dos_data_crc(unit[drive].trackbuf+cnt*512);
1311 dos_encode_block((ushort *) raw,(unsigned char *)crc,4);
1312 raw+=2;
1313
1314
1315 for(i=0;i<38;i++)
1316 *raw++=0x92549254;
1317
1318 return raw;
1319}
1320
1321static void dos_write(int disk)
1322{
1323 int cnt;
1324 unsigned long raw = (unsigned long) raw_buf;
1325 unsigned long *ptr=(unsigned long *)raw;
1326
1327 disk&=3;
1328
1329 for (cnt=0;cnt<425;cnt++)
1330 *ptr++=0x92549254;
1331
1332
1333 if (unit[disk].type->sect_mult==2)
1334 for(cnt=0;cnt<473;cnt++)
1335 *ptr++=0x92549254;
1336
1337
1338 for (cnt=0;cnt<20;cnt++)
1339 *ptr++=0x92549254;
1340 for (cnt=0;cnt<6;cnt++)
1341 *ptr++=0xaaaaaaaa;
1342 *ptr++=0x52245224;
1343 *ptr++=0x52245552;
1344 for (cnt=0;cnt<20;cnt++)
1345 *ptr++=0x92549254;
1346
1347
1348 for(cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++)
1349 ptr=ms_putsec(disk,ptr,cnt);
1350
1351 *(ushort *)ptr = 0xaaa8;
1352}
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364static void flush_track_callback(struct timer_list *timer)
1365{
1366 unsigned long nr = ((unsigned long)timer -
1367 (unsigned long)&flush_track_timer[0]) /
1368 sizeof(flush_track_timer[0]);
1369
1370 nr&=3;
1371 writefromint = 1;
1372 if (!try_fdc(nr)) {
1373
1374 flush_track_timer[nr].expires = jiffies + 1;
1375 add_timer(flush_track_timer + nr);
1376 return;
1377 }
1378 get_fdc(nr);
1379 (*unit[nr].dtype->write_fkt)(nr);
1380 if (!raw_write(nr)) {
1381 printk (KERN_NOTICE "floppy disk write protected\n");
1382 writefromint = 0;
1383 writepending = 0;
1384 }
1385 rel_fdc();
1386}
1387
1388static int non_int_flush_track (unsigned long nr)
1389{
1390 unsigned long flags;
1391
1392 nr&=3;
1393 writefromint = 0;
1394 del_timer(&post_write_timer);
1395 get_fdc(nr);
1396 if (!fd_motor_on(nr)) {
1397 writepending = 0;
1398 rel_fdc();
1399 return 0;
1400 }
1401 local_irq_save(flags);
1402 if (writepending != 2) {
1403 local_irq_restore(flags);
1404 (*unit[nr].dtype->write_fkt)(nr);
1405 if (!raw_write(nr)) {
1406 printk (KERN_NOTICE "floppy disk write protected "
1407 "in write!\n");
1408 writepending = 0;
1409 return 0;
1410 }
1411 wait_event(wait_fd_block, block_flag != 2);
1412 }
1413 else {
1414 local_irq_restore(flags);
1415 ms_delay(2);
1416 post_write(nr);
1417 }
1418 rel_fdc();
1419 return 1;
1420}
1421
1422static int get_track(int drive, int track)
1423{
1424 int error, errcnt;
1425
1426 drive&=3;
1427 if (unit[drive].track == track)
1428 return 0;
1429 get_fdc(drive);
1430 if (!fd_motor_on(drive)) {
1431 rel_fdc();
1432 return -1;
1433 }
1434
1435 if (unit[drive].dirty == 1) {
1436 del_timer (flush_track_timer + drive);
1437 non_int_flush_track (drive);
1438 }
1439 errcnt = 0;
1440 while (errcnt < MAX_ERRORS) {
1441 if (!fd_seek(drive, track))
1442 return -1;
1443 raw_read(drive);
1444 error = (*unit[drive].dtype->read_fkt)(drive);
1445 if (error == 0) {
1446 rel_fdc();
1447 return 0;
1448 }
1449
1450 unit[drive].track = -1;
1451 errcnt++;
1452 }
1453 rel_fdc();
1454 return -1;
1455}
1456
1457static blk_status_t amiflop_rw_cur_segment(struct amiga_floppy_struct *floppy,
1458 struct request *rq)
1459{
1460 int drive = floppy - unit;
1461 unsigned int cnt, block, track, sector;
1462 char *data;
1463
1464 for (cnt = 0; cnt < blk_rq_cur_sectors(rq); cnt++) {
1465#ifdef DEBUG
1466 printk("fd: sector %ld + %d requested for %s\n",
1467 blk_rq_pos(rq), cnt,
1468 (rq_data_dir(rq) == READ) ? "read" : "write");
1469#endif
1470 block = blk_rq_pos(rq) + cnt;
1471 track = block / (floppy->dtype->sects * floppy->type->sect_mult);
1472 sector = block % (floppy->dtype->sects * floppy->type->sect_mult);
1473 data = bio_data(rq->bio) + 512 * cnt;
1474#ifdef DEBUG
1475 printk("access to track %d, sector %d, with buffer at "
1476 "0x%08lx\n", track, sector, data);
1477#endif
1478
1479 if (get_track(drive, track) == -1)
1480 return BLK_STS_IOERR;
1481
1482 if (rq_data_dir(rq) == READ) {
1483 memcpy(data, floppy->trackbuf + sector * 512, 512);
1484 } else {
1485 memcpy(floppy->trackbuf + sector * 512, data, 512);
1486
1487
1488 if (!fd_motor_on(drive))
1489 return BLK_STS_IOERR;
1490
1491
1492
1493
1494 floppy->dirty = 1;
1495
1496 mod_timer (flush_track_timer + drive, jiffies + 1);
1497 }
1498 }
1499
1500 return BLK_STS_OK;
1501}
1502
1503static blk_status_t amiflop_queue_rq(struct blk_mq_hw_ctx *hctx,
1504 const struct blk_mq_queue_data *bd)
1505{
1506 struct request *rq = bd->rq;
1507 struct amiga_floppy_struct *floppy = rq->rq_disk->private_data;
1508 blk_status_t err;
1509
1510 if (!spin_trylock_irq(&amiflop_lock))
1511 return BLK_STS_DEV_RESOURCE;
1512
1513 blk_mq_start_request(rq);
1514
1515 do {
1516 err = amiflop_rw_cur_segment(floppy, rq);
1517 } while (blk_update_request(rq, err, blk_rq_cur_bytes(rq)));
1518 blk_mq_end_request(rq, err);
1519
1520 spin_unlock_irq(&amiflop_lock);
1521 return BLK_STS_OK;
1522}
1523
1524static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1525{
1526 int drive = MINOR(bdev->bd_dev) & 3;
1527
1528 geo->heads = unit[drive].type->heads;
1529 geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
1530 geo->cylinders = unit[drive].type->tracks;
1531 return 0;
1532}
1533
1534static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
1535 unsigned int cmd, unsigned long param)
1536{
1537 struct amiga_floppy_struct *p = bdev->bd_disk->private_data;
1538 int drive = p - unit;
1539 static struct floppy_struct getprm;
1540 void __user *argp = (void __user *)param;
1541
1542 switch(cmd){
1543 case FDFMTBEG:
1544 get_fdc(drive);
1545 if (fd_ref[drive] > 1) {
1546 rel_fdc();
1547 return -EBUSY;
1548 }
1549 fsync_bdev(bdev);
1550 if (fd_motor_on(drive) == 0) {
1551 rel_fdc();
1552 return -ENODEV;
1553 }
1554 if (fd_calibrate(drive) == 0) {
1555 rel_fdc();
1556 return -ENXIO;
1557 }
1558 floppy_off(drive);
1559 rel_fdc();
1560 break;
1561 case FDFMTTRK:
1562 if (param < p->type->tracks * p->type->heads)
1563 {
1564 get_fdc(drive);
1565 if (fd_seek(drive,param) != 0){
1566 memset(p->trackbuf, FD_FILL_BYTE,
1567 p->dtype->sects * p->type->sect_mult * 512);
1568 non_int_flush_track(drive);
1569 }
1570 floppy_off(drive);
1571 rel_fdc();
1572 }
1573 else
1574 return -EINVAL;
1575 break;
1576 case FDFMTEND:
1577 floppy_off(drive);
1578 invalidate_bdev(bdev);
1579 break;
1580 case FDGETPRM:
1581 memset((void *)&getprm, 0, sizeof (getprm));
1582 getprm.track=p->type->tracks;
1583 getprm.head=p->type->heads;
1584 getprm.sect=p->dtype->sects * p->type->sect_mult;
1585 getprm.size=p->blocks;
1586 if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct)))
1587 return -EFAULT;
1588 break;
1589 case FDSETPRM:
1590 case FDDEFPRM:
1591 return -EINVAL;
1592 case FDFLUSH:
1593 del_timer (flush_track_timer + drive);
1594 non_int_flush_track(drive);
1595 break;
1596#ifdef RAW_IOCTL
1597 case IOCTL_RAW_TRACK:
1598 if (copy_to_user(argp, raw_buf, p->type->read_size))
1599 return -EFAULT;
1600 else
1601 return p->type->read_size;
1602#endif
1603 default:
1604 printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",
1605 cmd, drive);
1606 return -ENOSYS;
1607 }
1608 return 0;
1609}
1610
1611static int fd_ioctl(struct block_device *bdev, fmode_t mode,
1612 unsigned int cmd, unsigned long param)
1613{
1614 int ret;
1615
1616 mutex_lock(&amiflop_mutex);
1617 ret = fd_locked_ioctl(bdev, mode, cmd, param);
1618 mutex_unlock(&amiflop_mutex);
1619
1620 return ret;
1621}
1622
1623static void fd_probe(int dev)
1624{
1625 unsigned long code;
1626 int type;
1627 int drive;
1628
1629 drive = dev & 3;
1630 code = fd_get_drive_id(drive);
1631
1632
1633 for (type = 0; type < num_dr_types; type++)
1634 if (drive_types[type].code == code)
1635 break;
1636
1637 if (type >= num_dr_types) {
1638 printk(KERN_WARNING "fd_probe: unsupported drive type "
1639 "%08lx found\n", code);
1640 unit[drive].type = &drive_types[num_dr_types-1];
1641 return;
1642 }
1643
1644 unit[drive].type = drive_types + type;
1645 unit[drive].track = -1;
1646
1647 unit[drive].disk = -1;
1648 unit[drive].motor = 0;
1649 unit[drive].busy = 0;
1650 unit[drive].status = -1;
1651}
1652
1653
1654
1655
1656
1657
1658static int floppy_open(struct block_device *bdev, fmode_t mode)
1659{
1660 int drive = MINOR(bdev->bd_dev) & 3;
1661 int system = (MINOR(bdev->bd_dev) & 4) >> 2;
1662 int old_dev;
1663 unsigned long flags;
1664
1665 mutex_lock(&amiflop_mutex);
1666 old_dev = fd_device[drive];
1667
1668 if (fd_ref[drive] && old_dev != system) {
1669 mutex_unlock(&amiflop_mutex);
1670 return -EBUSY;
1671 }
1672
1673 if (mode & (FMODE_READ|FMODE_WRITE)) {
1674 check_disk_change(bdev);
1675 if (mode & FMODE_WRITE) {
1676 int wrprot;
1677
1678 get_fdc(drive);
1679 fd_select (drive);
1680 wrprot = !(ciaa.pra & DSKPROT);
1681 fd_deselect (drive);
1682 rel_fdc();
1683
1684 if (wrprot) {
1685 mutex_unlock(&amiflop_mutex);
1686 return -EROFS;
1687 }
1688 }
1689 }
1690
1691 local_irq_save(flags);
1692 fd_ref[drive]++;
1693 fd_device[drive] = system;
1694 local_irq_restore(flags);
1695
1696 unit[drive].dtype=&data_types[system];
1697 unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
1698 data_types[system].sects*unit[drive].type->sect_mult;
1699 set_capacity(unit[drive].gendisk, unit[drive].blocks);
1700
1701 printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
1702 unit[drive].type->name, data_types[system].name);
1703
1704 mutex_unlock(&amiflop_mutex);
1705 return 0;
1706}
1707
1708static void floppy_release(struct gendisk *disk, fmode_t mode)
1709{
1710 struct amiga_floppy_struct *p = disk->private_data;
1711 int drive = p - unit;
1712
1713 mutex_lock(&amiflop_mutex);
1714 if (unit[drive].dirty == 1) {
1715 del_timer (flush_track_timer + drive);
1716 non_int_flush_track (drive);
1717 }
1718
1719 if (!fd_ref[drive]--) {
1720 printk(KERN_CRIT "floppy_release with fd_ref == 0");
1721 fd_ref[drive] = 0;
1722 }
1723#ifdef MODULE
1724 floppy_off (drive);
1725#endif
1726 mutex_unlock(&amiflop_mutex);
1727}
1728
1729
1730
1731
1732
1733
1734
1735static unsigned amiga_check_events(struct gendisk *disk, unsigned int clearing)
1736{
1737 struct amiga_floppy_struct *p = disk->private_data;
1738 int drive = p - unit;
1739 int changed;
1740 static int first_time = 1;
1741
1742 if (first_time)
1743 changed = first_time--;
1744 else {
1745 get_fdc(drive);
1746 fd_select (drive);
1747 changed = !(ciaa.pra & DSKCHANGE);
1748 fd_deselect (drive);
1749 rel_fdc();
1750 }
1751
1752 if (changed) {
1753 fd_probe(drive);
1754 p->track = -1;
1755 p->dirty = 0;
1756 writepending = 0;
1757 writefromint = 0;
1758 return DISK_EVENT_MEDIA_CHANGE;
1759 }
1760 return 0;
1761}
1762
1763static const struct block_device_operations floppy_fops = {
1764 .owner = THIS_MODULE,
1765 .open = floppy_open,
1766 .release = floppy_release,
1767 .ioctl = fd_ioctl,
1768 .getgeo = fd_getgeo,
1769 .check_events = amiga_check_events,
1770};
1771
1772static const struct blk_mq_ops amiflop_mq_ops = {
1773 .queue_rq = amiflop_queue_rq,
1774};
1775
1776static struct gendisk *fd_alloc_disk(int drive)
1777{
1778 struct gendisk *disk;
1779
1780 disk = alloc_disk(1);
1781 if (!disk)
1782 goto out;
1783
1784 disk->queue = blk_mq_init_sq_queue(&unit[drive].tag_set, &amiflop_mq_ops,
1785 2, BLK_MQ_F_SHOULD_MERGE);
1786 if (IS_ERR(disk->queue)) {
1787 disk->queue = NULL;
1788 goto out_put_disk;
1789 }
1790
1791 unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL);
1792 if (!unit[drive].trackbuf)
1793 goto out_cleanup_queue;
1794
1795 return disk;
1796
1797out_cleanup_queue:
1798 blk_cleanup_queue(disk->queue);
1799 disk->queue = NULL;
1800 blk_mq_free_tag_set(&unit[drive].tag_set);
1801out_put_disk:
1802 put_disk(disk);
1803out:
1804 unit[drive].type->code = FD_NODRIVE;
1805 return NULL;
1806}
1807
1808static int __init fd_probe_drives(void)
1809{
1810 int drive,drives,nomem;
1811
1812 pr_info("FD: probing units\nfound");
1813 drives=0;
1814 nomem=0;
1815 for(drive=0;drive<FD_MAX_UNITS;drive++) {
1816 struct gendisk *disk;
1817 fd_probe(drive);
1818 if (unit[drive].type->code == FD_NODRIVE)
1819 continue;
1820
1821 disk = fd_alloc_disk(drive);
1822 if (!disk) {
1823 pr_cont(" no mem for fd%d", drive);
1824 nomem = 1;
1825 continue;
1826 }
1827 unit[drive].gendisk = disk;
1828 drives++;
1829
1830 pr_cont(" fd%d",drive);
1831 disk->major = FLOPPY_MAJOR;
1832 disk->first_minor = drive;
1833 disk->fops = &floppy_fops;
1834 sprintf(disk->disk_name, "fd%d", drive);
1835 disk->private_data = &unit[drive];
1836 set_capacity(disk, 880*2);
1837 add_disk(disk);
1838 }
1839 if ((drives > 0) || (nomem == 0)) {
1840 if (drives == 0)
1841 pr_cont(" no drives");
1842 pr_cont("\n");
1843 return drives;
1844 }
1845 pr_cont("\n");
1846 return -ENOMEM;
1847}
1848
1849static struct kobject *floppy_find(dev_t dev, int *part, void *data)
1850{
1851 int drive = *part & 3;
1852 if (unit[drive].type->code == FD_NODRIVE)
1853 return NULL;
1854 *part = 0;
1855 return get_disk_and_module(unit[drive].gendisk);
1856}
1857
1858static int __init amiga_floppy_probe(struct platform_device *pdev)
1859{
1860 int i, ret;
1861
1862 if (register_blkdev(FLOPPY_MAJOR,"fd"))
1863 return -EBUSY;
1864
1865 ret = -ENOMEM;
1866 raw_buf = amiga_chip_alloc(RAW_BUF_SIZE, "Floppy");
1867 if (!raw_buf) {
1868 printk("fd: cannot get chip mem buffer\n");
1869 goto out_blkdev;
1870 }
1871
1872 ret = -EBUSY;
1873 if (request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) {
1874 printk("fd: cannot get irq for dma\n");
1875 goto out_irq;
1876 }
1877
1878 if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) {
1879 printk("fd: cannot get irq for timer\n");
1880 goto out_irq2;
1881 }
1882
1883 ret = -ENODEV;
1884 if (fd_probe_drives() < 1)
1885 goto out_probe;
1886
1887 blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
1888 floppy_find, NULL, NULL);
1889
1890
1891 timer_setup(&motor_on_timer, motor_on_callback, 0);
1892 motor_on_timer.expires = 0;
1893 for (i = 0; i < FD_MAX_UNITS; i++) {
1894 timer_setup(&motor_off_timer[i], fd_motor_off, 0);
1895 motor_off_timer[i].expires = 0;
1896 timer_setup(&flush_track_timer[i], flush_track_callback, 0);
1897 flush_track_timer[i].expires = 0;
1898
1899 unit[i].track = -1;
1900 }
1901
1902 timer_setup(&post_write_timer, post_write_callback, 0);
1903 post_write_timer.expires = 0;
1904
1905 for (i = 0; i < 128; i++)
1906 mfmdecode[i]=255;
1907 for (i = 0; i < 16; i++)
1908 mfmdecode[mfmencode[i]]=i;
1909
1910
1911 custom.dmacon = DMAF_SETCLR | DMAF_DISK;
1912
1913
1914 ciaa.crb = 8;
1915 return 0;
1916
1917out_probe:
1918 free_irq(IRQ_AMIGA_CIAA_TB, NULL);
1919out_irq2:
1920 free_irq(IRQ_AMIGA_DSKBLK, NULL);
1921out_irq:
1922 amiga_chip_free(raw_buf);
1923out_blkdev:
1924 unregister_blkdev(FLOPPY_MAJOR,"fd");
1925 return ret;
1926}
1927
1928static struct platform_driver amiga_floppy_driver = {
1929 .driver = {
1930 .name = "amiga-floppy",
1931 },
1932};
1933
1934static int __init amiga_floppy_init(void)
1935{
1936 return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe);
1937}
1938
1939module_init(amiga_floppy_init);
1940
1941#ifndef MODULE
1942static int __init amiga_floppy_setup (char *str)
1943{
1944 int n;
1945 if (!MACH_IS_AMIGA)
1946 return 0;
1947 if (!get_option(&str, &n))
1948 return 0;
1949 printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n);
1950 fd_def_df0 = n;
1951 return 1;
1952}
1953
1954__setup("floppy=", amiga_floppy_setup);
1955#endif
1956
1957MODULE_ALIAS("platform:amiga-floppy");
1958