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