OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [block/] [amiflop.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/amiga/amiflop.c
3
 *
4
 *  Copyright (C) 1993  Greg Harp
5
 *  Portions of this driver are based on code contributed by Brad Pepers
6
 *
7
 *  revised 28.5.95 by Joerg Dorchain
8
 *  - now no bugs(?) any more for both HD & DD
9
 *  - added support for 40 Track 5.25" drives, 80-track hopefully behaves
10
 *    like 3.5" dd (no way to test - are there any 5.25" drives out there
11
 *    that work on an A4000?)
12
 *  - wrote formatting routine (maybe dirty, but works)
13
 *
14
 *  june/july 1995 added ms-dos support by Joerg Dorchain
15
 *  (portions based on messydos.device and various contributors)
16
 *  - currently only 9 and 18 sector disks
17
 *
18
 *  - fixed a bug with the internal trackbuffer when using multiple
19
 *    disks the same time
20
 *  - made formatting a bit safer
21
 *  - added command line and machine based default for "silent" df0
22
 *
23
 *  december 1995 adapted for 1.2.13pl4 by Joerg Dorchain
24
 *  - works but I think it's inefficient. (look in redo_fd_request)
25
 *    But the changes were very efficient. (only three and a half lines)
26
 *
27
 *  january 1995 added special ioctl for tracking down read/write problems
28
 *  - usage ioctl(d, RAW_TRACK, ptr); the raw track buffer (MFM-encoded data
29
 *    is copied to area. (area should be large enough since no checking is
30
 *    done - 30K is currently sufficient). return the actual size of the
31
 *    trackbuffer
32
 *  - replaced udelays() by a timer (CIAA timer B) for the waits
33
 *    needed for the disk mechanic.
34
 *
35
 *  revised Marts 3rd, 1996 by Jes Sorensen for use in the 1.3.28 kernel.
36
 *  - Minor changes to accept the kdev_t.
37
 *  - Replaced some more udelays with ms_delays. Udelay is just a loop,
38
 *    and so the delay will be different depending on the given
39
 *    processor :-(
40
 *  - The driver could use a major cleanup because of the new
41
 *    major/minor handling that came with kdev_t. It seems to work for
42
 *    the time being, but I can't guarantee that it will stay like
43
 *    that when we start using 16 (24?) bit minors.
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 /* print _LOTS_ of infos */
70
 
71
#define RAW_IOCTL
72
#ifdef RAW_IOCTL
73
#define IOCTL_RAW_TRACK 0x5254524B  /* 'RTRK' */
74
#endif
75
 
76
/* prototypes */
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
 *  Defines
88
 */
89
#define MAX_SECTORS     22
90
 
91
/*
92
 *  Error codes
93
 */
94
#define FD_OK           0        /* operation succeeded */
95
#define FD_ERROR        -1      /* general error (seek, read, write, etc) */
96
#define FD_NOUNIT       1       /* unit does not exist */
97
#define FD_UNITBUSY     2       /* unit already active */
98
#define FD_NOTACTIVE    3       /* unit is not active */
99
#define FD_NOTREADY     4       /* unit is not ready (motor not on/no disk) */
100
 
101
/*
102
 *  Floppy ID values
103
 */
104
#define FD_NODRIVE      0x00000000  /* response when no unit is present */
105
#define FD_DD_3         0xffffffff  /* double-density 3.5" (880K) drive */
106
#define FD_HD_3         0x55555555  /* high-density 3.5" (1760K) drive */
107
#define FD_DD_5         0xaaaaaaaa  /* double-density 5.25" (440K) drive */
108
 
109
static int fd_def_df0 = 0;     /* default for df0 if it doesn't identify */
110
 
111
 
112
/*
113
 *  Macros
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
/*  code        name       tr he   rdsz   wrsz sm pc1 pc2 sd  st st*/
128
/*  warning: times are now in milliseconds (ms)                    */
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
/* defaults for 3 1/2" HD-Disks */
137
static int floppy_sizes[256]={880,880,880,880,720,720,720,};
138
static int floppy_blocksizes[256]={0,};
139
/* hardsector size assumed to be 512 */
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
/* current info on each unit */
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
/* track buffer */
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  /* size of raw disk data */
165
 
166
/*
167
 * These are global variables, as that's the easiest way to give
168
 * information to interrupts. They are the data used for the current
169
 * request.
170
 */
171
static char block_flag = 0;
172
static int selected = 0;
173
static struct wait_queue *wait_fd_block = NULL;
174
 
175
/* Synchronization of FDC access. */
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
/* MS-Dos MFM Coding tables (should go quick and easy) */
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
/* floppy internal millisecond timer stuff */
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
/* with the semaphore waits are queued up
198
   A more generic routine would do a schedule a la timer.device */
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; /* count clock, force load, one-shot, start */
208
    sleep_on(&ms_wait);
209
    up(&ms_sem);
210
  }
211
}
212
 
213
/*
214
 * Functions
215
 */
216
/*======================================================================
217
  Turn off the motor of the given drive.  Unit must already be active.
218
  Returns standard floppy error code.
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
  Seek the drive to track 0.
349
  The drive must be active and the motor must be running.
350
  Returns standard floppy error code.
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
  Seek the drive to the requested cylinder.
402
  The drive must have been calibrated at some point before this.
403
  The drive must also be active and the motor must be running.
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
  /* odd bits */
467
  for (cnt = 0; cnt < len / 4; cnt++) {
468
    data = src[cnt] >> 1;
469
    encode(data, dest + to_cnt++);
470
  }
471
 
472
  /* even bits */
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
  amiga_write converts track/labels data to raw track data
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
        /* gap space */
551
        for (cnt = 0; cnt < 415 * unit[disk].type->sect_mult; cnt++)
552
                *ptr++ = 0xaaaaaaaa;
553
 
554
        /* sectors */
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
        /* convert length from bytes to longwords */
567
        len >>= 2;
568
        odd = raw;
569
        even = odd + len;
570
 
571
        /* prepare return pointer */
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
 scan_sync - looks for the next start of sector marked by a sync. d3 is the
588
                sector number (10..0). When d3 = 10, can't be certain of a
589
                starting sync.
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
  amiga_read reads a raw track of data into a track buffer
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
                /* verify track */
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,   /* 0-80 */
673
              side,    /* 0-1 */
674
              sec,     /* 0-...*/
675
              len_desc;/* 2 */
676
unsigned short crc;     /* on 68000 we got an alignment problem,
677
                           but this compiler solves it  by adding silently
678
                           adding a pad byte so data won't fit
679
                           and this cost about 3h to discover.... */
680
unsigned char gap1[22];     /* for longword-alignedness (0x4e) */
681
};
682
 
683
/* crc routines are borrowed from the messydos-handler  */
684
 
685
static inline ushort dos_hdr_crc (struct dos_header *hdr)
686
{
687
return dos_crc(&(hdr->track), 0xb2, 0x30, 3); /* precomputed magic */
688
}
689
 
690
static inline ushort dos_data_crc(unsigned char *data)
691
{
692
return dos_crc(data, 0xe2, 0x95 ,511); /* precomputed magic */
693
}
694
 
695
/* excerpt from the messydos-device
696
; The CRC is computed not only over the actual data, but including
697
; the SYNC mark (3 * $a1) and the 'ID/DATA - Address Mark' ($fe/$fb).
698
; As we don't read or encode these fields into our buffers, we have to
699
; preload the registers containing the CRC with the values they would have
700
; after stepping over these fields.
701
;
702
; How CRCs "really" work:
703
;
704
; First, you should regard a bitstring as a series of coefficients of
705
; polynomials. We calculate with these polynomials in modulo-2
706
; arithmetic, in which both add and subtract are done the same as
707
; exclusive-or. Now, we modify our data (a very long polynomial) in
708
; such a way that it becomes divisible by the CCITT-standard 16-bit
709
;                16   12   5
710
; polynomial:   x  + x  + x + 1, represented by $11021. The easiest
711
; way to do this would be to multiply (using proper arithmetic) our
712
; datablock with $11021. So we have:
713
;   data * $11021                =
714
;   data * ($10000 + $1021)      =
715
;   data * $10000 + data * $1021
716
; The left part of this is simple: Just add two 0 bytes. But then
717
; the right part (data $1021) remains difficult and even could have
718
; a carry into the left part. The solution is to use a modified
719
; multiplication, which has a result that is not correct, but with
720
; a difference of any multiple of $11021. We then only need to keep
721
; the 16 least significant bits of the result.
722
;
723
; The following algorithm does this for us:
724
;
725
;   unsigned char *data, c, crclo, crchi;
726
;   while (not done) {
727
;       c = *data++ + crchi;
728
;       crchi = (@ c) >> 8 + crclo;
729
;       crclo = @ c;
730
;   }
731
;
732
; Remember, + is done with EOR, the @ operator is in two tables (high
733
; and low byte separately), which is calculated as
734
;
735
;      $1021 * (c & $F0)
736
;  xor $1021 * (c & $0F)
737
;  xor $1021 * (c >> 4)         (* is regular multiplication)
738
;
739
;
740
; Anyway, the end result is the same as the remainder of the division of
741
; the data by $11021. I am afraid I need to study theory a bit more...
742
 
743
 
744
my only works was to code this from manx to C....
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
/* look at the asm-code - what looks in C a bit strange is almost as good as handmade */
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
   this reads a raw track of data into trackbuffer for ms-disks
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 { /* search for the right sync of each sec-hdr */
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); /* loop usually only once done */
863
  raw+=2; /* skip over headermark */
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;  /* skip data mark (included in checksum) */
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
/* id gap 1 */
964
/* the MFM word before is always 9254 */
965
for(i=0;i<6;i++)
966
  *raw++=0xaaaaaaaa;
967
/* 3 sync + 1 headermark */
968
*raw++=0x44894489;
969
*raw++=0x44895554;
970
 
971
/* fill in the variable parts of the header */
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
/* header (without "magic") and id gap 2*/
978
dos_encode_block((ushort *)raw,(unsigned char *) &hdr.track,28);
979
raw+=14;
980
 
981
/*id gap 3 */
982
for(i=0;i<6;i++)
983
  *raw++=0xaaaaaaaa;
984
 
985
/* 3 syncs and 1 datamark */
986
*raw++=0x44894489;
987
*raw++=0x44895545;
988
 
989
/* data */
990
dos_encode_block((ushort *)raw,(unsigned char *)data,512);
991
raw+=256;
992
 
993
/*data crc + jd's special gap (long words :-/) */
994
crc[0]=dos_data_crc(data);
995
dos_encode_block((ushort *) raw,(unsigned char *)crc,4);
996
raw+=2;
997
 
998
/* data gap */
999
for(i=0;i<38;i++)
1000
  *raw++=0x92549254;
1001
 
1002
return raw; /* wrote 652 MFM words */
1003
}
1004
 
1005
 
1006
/**************************************************************
1007
  builds encoded track data from trackbuffer data
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
/* really gap4 + indexgap , but we write it first and round it up */
1017
for (cnt=0;cnt<425;cnt++)
1018
  *ptr++=0x92549254;
1019
 
1020
/* the following is just guessed */
1021
if (unit[disk].type->sect_mult==2)  /* check for HD-Disks */
1022
  for(cnt=0;cnt<473;cnt++)
1023
    *ptr++=0x92549254;
1024
 
1025
/* now the index marks...*/
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
/* sectors */
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; /* MFM word before is always 0x9254 */
1040
}
1041
 
1042
/*
1043
 * Note that MAX_ERRORS=X doesn't imply that we retry every bad read
1044
 * max X times - some types of errors increase the errorcount by 2 or
1045
 * even 3, so we might actually retry only X/2 times before giving up.
1046
 */
1047
#define MAX_ERRORS 12
1048
 
1049
/*
1050
 * The driver is trying to determine the correct media format
1051
 * while probing is set. rw_interrupt() clears it after a
1052
 * successful access.
1053
 */
1054
static int probing = 0;
1055
 
1056
/* Prevent "aliased" accesses. */
1057
static fd_ref[4] = { 0,0,0,0 };
1058
static fd_device[4] = { 0,0,0,0 };
1059
 
1060
/*
1061
 * Current device number. Taken either from the block header or from the
1062
 * format request descriptor.
1063
 */
1064
#define CURRENT_DEVICE (CURRENT->rq_dev)
1065
 
1066
/* Current error count. */
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
 * floppy-change is never called from an interrupt, so we can relax a bit
1077
 * here, sleep etc. Note that floppy-on tries to set current_DOR to point
1078
 * to the desired drive, but it will probably not survive the sleep if
1079
 * several floppies are used at the same time: thus the loop.
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; /* if this was true before, too bad! */
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
        /* setup adkcon bits correctly */
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
        /* clear adkcon bits */
1153
        custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
1154
        /* set appropriate adkcon bits */
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
                /* fall through */
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); /* 2 ms post_write delay */
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
                /* manual selection */
1276
                drive = device & 3;
1277
                floppy = unit + drive;
1278
        } else {
1279
                /* Auto-detection */
1280
                /* printk("redo_fd_request: can't handle auto detect\n");*/
1281
                /* printk("redo_fd_request: default to normal\n");*/
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
 /* Here someone could investigate to be more efficient */
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
                         * setup a callback to write the track buffer
1360
                         * after a short (1 tick) delay.
1361
                         */
1362
                        save_flags (flags);
1363
                        cli();
1364
 
1365
                        if (writepending)
1366
                            /* reset the timer */
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); /* sti(); */
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
  Return unit ID number of given disk
1486
======================================================================*/
1487
static unsigned long get_drive_id(int drive)
1488
{
1489
        int i;
1490
        ulong id = 0;
1491
 
1492
        drive&=3;
1493
        /* set up for ID */
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
        /* loop and read disk ID */
1508
        for (i=0; i<32; i++) {
1509
                SELECT(SELMASK(drive));
1510
                udelay(2);
1511
 
1512
                /* read and store value of DSKRDY */
1513
                id <<= 1;
1514
                id |= (ciaa.pra & DSKRDY) ? 0 : 1;       /* cia regs are low-active! */
1515
 
1516
                DESELECT(SELMASK(drive));
1517
        }
1518
 
1519
        selected = -1;
1520
 
1521
        /*
1522
         * RB: At least A500/A2000's df0: don't identify themselves.
1523
         * As every (real) Amiga has at least a 3.5" DD drive as df0:
1524
         * we default to that if df0: doesn't identify as a certain
1525
         * type.
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
        /* return the ID value */
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
        /* get drive type */
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
 * floppy_open check for aliasing (/dev/fd0 can be the same as
1595
 * /dev/PS0 etc), and disallows simultaneous access to the same
1596
 * drive with different device numbers.
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: accessing %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,                   /* lseek - default */
1676
        block_read,             /* read - general block-dev read */
1677
        block_write,            /* write - general block-dev write */
1678
        NULL,                   /* readdir - bad */
1679
        NULL,                   /* select */
1680
        fd_ioctl,               /* ioctl */
1681
        NULL,                   /* mmap */
1682
        floppy_open,            /* open */
1683
        floppy_release,         /* release */
1684
        block_fsync,            /* fsync */
1685
        NULL,                   /* fasync */
1686
        amiga_floppy_change,    /* check_media_change */
1687
        NULL,                   /* revalidate */
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
     * if it was a write from an interrupt,
1701
     * we will call post_write from here
1702
     */
1703
    writepending = 2;
1704
    post_write_timer.expires = 1; /* at least 2 ms */
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
  /* initialize variables */
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
  /* make sure that disk DMA is enabled */
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.