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