root/drivers/block/amiflop.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ms_isr
  2. ms_delay
  3. fd_motor_off
  4. motor_on_callback
  5. motor_on
  6. floppy_off
  7. fd_select
  8. fd_deselect
  9. fd_calibrate
  10. fd_seek
  11. encode
  12. encode_block
  13. checksum
  14. putsec
  15. amiga_write
  16. decode
  17. scan_sync
  18. amiga_read
  19. dos_hdr_crc
  20. dos_data_crc
  21. dos_crc
  22. dos_decode_byte
  23. dos_decode
  24. dbg
  25. dos_read
  26. dos_encode_byte
  27. dos_encode_block
  28. ms_putsec
  29. dos_write
  30. request_done
  31. amiga_floppy_change
  32. copy_buffer
  33. raw_read
  34. raw_write
  35. post_write
  36. get_track
  37. flush_track_callback
  38. non_int_flush_track
  39. redo_fd_request
  40. do_fd_request
  41. fd_ioctl
  42. get_drive_id
  43. fd_probe
  44. probe_drives
  45. floppy_open
  46. floppy_release
  47. amiga_floppy_setup
  48. fd_block_done
  49. amiga_floppy_init

   1 /*
   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 its 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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 wont fit
 679                            and this cost about 3h to discover.... */
 680 unsigned char gap1[22];     /* for longword-aligndness (0x4e) */
 681 };
 682 
 683 /* crc routines are borrowed from the messydos-handler  */
 684 
 685 static inline ushort dos_hdr_crc (struct dos_header *hdr)
     /* [previous][next][first][last][top][bottom][index][help] */
 686 {
 687 return dos_crc(&(hdr->track), 0xb2, 0x30, 3); /* precomputed magic */
 688 }
 689 
 690 static inline ushort dos_data_crc(unsigned char *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 ; polymomials. 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
1175 {
1176   custom.dsklen = 0;
1177   writepending = 0;
1178   writefromint = 0;
1179 }
1180 
1181 static int get_track(int drive, int track)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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,
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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 }

/* [previous][next][first][last][top][bottom][index][help] */