root/kernel/blk_drv/floppy.c

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

DEFINITIONS

This source file includes following definitions.
  1. floppy_deselect
  2. request_done
  3. floppy_change
  4. setup_DMA
  5. output_byte
  6. result
  7. bad_flp_intr
  8. perpendicular_mode
  9. configure_fdc_mode
  10. tell_sector
  11. rw_interrupt
  12. setup_rw_floppy
  13. seek_interrupt
  14. transfer
  15. recal_interrupt
  16. unexpected_floppy_interrupt
  17. recalibrate_floppy
  18. reset_interrupt
  19. reset_floppy
  20. floppy_shutdown
  21. shake_done
  22. retry_recal
  23. shake_zero
  24. shake_one
  25. floppy_on_interrupt
  26. setup_format_params
  27. redo_fd_request
  28. do_fd_request
  29. fd_ioctl
  30. find_base
  31. config_types
  32. floppy_open
  33. floppy_release
  34. ignore_interrupt
  35. floppy_interrupt
  36. floppy_init

   1 /*
   2  *  linux/kernel/floppy.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * 02.12.91 - Changed to static variables to indicate need for reset
   9  * and recalibrate. This makes some things easier (output_byte reset
  10  * checking etc), and means less interrupt jumping in case of errors,
  11  * so the code is hopefully easier to understand.
  12  */
  13 
  14 /*
  15  * This file is certainly a mess. I've tried my best to get it working,
  16  * but I don't like programming floppies, and I have only one anyway.
  17  * Urgel. I should check for more errors, and do more graceful error
  18  * recovery. Seems there are problems with several drives. I've tried to
  19  * correct them. No promises. 
  20  */
  21 
  22 /*
  23  * As with hd.c, all routines within this file can (and will) be called
  24  * by interrupts, so extreme caution is needed. A hardware interrupt
  25  * handler may not sleep, or a kernel panic will happen. Thus I cannot
  26  * call "floppy-on" directly, but have to set a special timer interrupt
  27  * etc.
  28  */
  29 
  30 /*
  31  * 28.02.92 - made track-buffering routines, based on the routines written
  32  * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus.
  33  */
  34 
  35 /*
  36  * Automatic floppy-detection and formatting written by Werner Almesberger
  37  * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
  38  * the floppy-change signal detection.
  39  */
  40 
  41 /*
  42  * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed 
  43  * FDC data overrun bug, added some preliminary stuff for vertical
  44  * recording support.
  45  *
  46  * 1992/9/17: Added DMA allocation & DMA functions. -- hhb.
  47  *
  48  * TODO: Errors are still not counted properly.
  49  */
  50 
  51 /* 1992/9/20
  52  * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl)
  53  * modelled after the freeware MS/DOS program fdformat/88 V1.8 by 
  54  * Christoph H. Hochst\"atter.
  55  * I have fixed the shift values to the ones I always use. Maybe a new
  56  * ioctl() should be created to be able to modify them.
  57  * There is a bug in the driver that makes it impossible to format a
  58  * floppy as the first thing after bootup.
  59  */
  60 
  61 #define REALLY_SLOW_IO
  62 #define FLOPPY_IRQ 6
  63 #define FLOPPY_DMA 2
  64 
  65 #include <linux/sched.h>
  66 #include <linux/fs.h>
  67 #include <linux/kernel.h>
  68 #include <linux/timer.h>
  69 #include <linux/fdreg.h>
  70 #include <linux/fd.h>
  71 #include <linux/errno.h>
  72 
  73 #include <asm/dma.h>
  74 #include <asm/system.h>
  75 #include <asm/io.h>
  76 #include <asm/segment.h>
  77 
  78 #define MAJOR_NR 2
  79 #include "blk.h"
  80 
  81 static unsigned int changed_floppies = 0, fake_change = 0;
  82 
  83 static int initial_reset_flag = 0;
  84 static int need_configure = 1;          /* for 82077 */
  85 static int recalibrate = 0;
  86 static int reset = 0;
  87 static int recover = 0; /* recalibrate immediately after resetting */
  88 static int seek = 0;
  89 
  90 extern unsigned char current_DOR;
  91 
  92 #define TYPE(x) ((x)>>2)
  93 #define DRIVE(x) ((x)&0x03)
  94 
  95 /*
  96  * Note that MAX_ERRORS=X doesn't imply that we retry every bad read
  97  * max X times - some types of errors increase the errorcount by 2 or
  98  * even 3, so we might actually retry only X/2 times before giving up.
  99  */
 100 #define MAX_ERRORS 12
 101 
 102 /*
 103  * Maximum disk size (in kilobytes). This default is used whenever the
 104  * current disk size is unknown.
 105  */
 106 #define MAX_DISK_SIZE 1440
 107 
 108 /*
 109  * Maximum number of sectors in a track buffer. Track buffering is disabled
 110  * if tracks are bigger.
 111  */
 112 #define MAX_BUFFER_SECTORS 18
 113 
 114 /*
 115  * The DMA channel used by the floppy controller cannot access data at
 116  * addresses >= 1MB
 117  */
 118 #define LAST_DMA_ADDR   (0x100000 - BLOCK_SIZE)
 119 
 120 /*
 121  * globals used by 'result()'
 122  */
 123 #define MAX_REPLIES 7
 124 static unsigned char reply_buffer[MAX_REPLIES];
 125 #define ST0 (reply_buffer[0])
 126 #define ST1 (reply_buffer[1])
 127 #define ST2 (reply_buffer[2])
 128 #define ST3 (reply_buffer[3])
 129 
 130 /*
 131  * This struct defines the different floppy types.
 132  *
 133  * The 'stretch' tells if the tracks need to be doubled for some
 134  * types (ie 360kB diskette in 1.2MB drive etc). Others should
 135  * be self-explanatory.
 136  */
 137 static struct floppy_struct floppy_type[] = {
 138         {    0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL },    /* no testing */
 139         {  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,NULL },    /* 360kB PC diskettes */
 140         { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,NULL },    /* 1.2 MB AT-diskettes */
 141         {  720, 9,2,40,1,0x2A,0x02,0xDF,0x50,NULL },    /* 360kB in 720kB drive */
 142         { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,NULL },    /* 3.5" 720kB diskette */
 143         {  720, 9,2,40,1,0x23,0x01,0xDF,0x50,NULL },    /* 360kB in 1.2MB drive */
 144         { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,NULL },    /* 720kB in 1.2MB drive */
 145         { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL },    /* 1.44MB diskette */
 146 };
 147 
 148 /*
 149  * Auto-detection. Each drive type has a pair of formats which are
 150  * used in succession to try to read the disk. If the FDC cannot lock onto
 151  * the disk, the next format is tried. This uses the variable 'probing'.
 152  */
 153 static struct floppy_struct floppy_types[] = {
 154         {  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
 155         {  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
 156         { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"1.2M" },    /* 1.2 MB AT-diskettes */
 157         {  720, 9,2,40,1,0x23,0x01,0xDF,0x50,"360k/AT" }, /* 360kB in 1.2MB drive */
 158         { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" },    /* 3.5" 720kB diskette */
 159         { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" },    /* 3.5" 720kB diskette */
 160         { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"1.44M" },   /* 1.44MB diskette */
 161         { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k/AT" }, /* 3.5" 720kB diskette */
 162 };
 163 
 164 /* Auto-detection: Disk type used until the next media change occurs. */
 165 struct floppy_struct *current_type[4] = { NULL, NULL, NULL, NULL };
 166 
 167 /* This type is tried first. */
 168 struct floppy_struct *base_type[4];
 169 
 170 /*
 171  * User-provided type information. current_type points to
 172  * the respective entry of this array.
 173  */
 174 struct floppy_struct user_params[4];
 175 
 176 static int floppy_sizes[] ={
 177         MAX_DISK_SIZE, MAX_DISK_SIZE, MAX_DISK_SIZE, MAX_DISK_SIZE,
 178          360, 360 ,360, 360,
 179         1200,1200,1200,1200,
 180          360, 360, 360, 360,
 181          720, 720, 720, 720,
 182          360, 360, 360, 360,
 183          720, 720, 720, 720,
 184         1440,1440,1440,1440
 185 };
 186 
 187 /*
 188  * The driver is trying to determine the correct media format
 189  * while probing is set. rw_interrupt() clears it after a
 190  * successful access.
 191  */
 192 static int probing = 0;
 193 
 194 /*
 195  * (User-provided) media information is _not_ discarded after a media change
 196  * if the corresponding keep_data flag is non-zero. Positive values are
 197  * decremented after each probe.
 198  */
 199 static int keep_data[4] = { 0,0,0,0 };
 200 
 201 /*
 202  * Announce successful media type detection and media information loss after
 203  * disk changes.
 204  * Also used to enable/disable printing of overrun warnings.
 205  */
 206 static ftd_msg[4] = { 0,0,0,0 };
 207 
 208 /* Prevent "aliased" accesses. */
 209 
 210 static fd_ref[4] = { 0,0,0,0 };
 211 static fd_device[4] = { 0,0,0,0 };
 212 
 213 /* Synchronization of FDC access. */
 214 static volatile int format_status = FORMAT_NONE, fdc_busy = 0;
 215 static struct wait_queue *fdc_wait = NULL, *format_done = NULL;
 216 
 217 /* Errors during formatting are counted here. */
 218 static int format_errors;
 219 
 220 /* Format request descriptor. */
 221 static struct format_descr format_req;
 222 
 223 /*
 224  * Current device number. Taken either from the block header or from the
 225  * format request descriptor.
 226  */
 227 #define CURRENT_DEVICE (format_status == FORMAT_BUSY ? format_req.device : \
 228    (CURRENT->dev))
 229 
 230 /* Current error count. */
 231 #define CURRENT_ERRORS (format_status == FORMAT_BUSY ? format_errors : \
 232     (CURRENT->errors))
 233 
 234 /*
 235  * Threshold for reporting FDC errors to the console.
 236  * Setting this to zero may flood your screen when using
 237  * ultra cheap floppies ;-)
 238  */
 239 static unsigned short min_report_error_cnt[4] = {2, 2, 2, 2};
 240 
 241 /*
 242  * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
 243  * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
 244  * H is head unload time (1=16ms, 2=32ms, etc)
 245  *
 246  * Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc)
 247  * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
 248  */
 249 
 250 /*
 251  * Track buffer and block buffer (in case track buffering doesn't work).
 252  * Because these are written to by the DMA controller, they must
 253  * not contain a 64k byte boundary crossing, or data will be
 254  * corrupted/lost. Alignment of these is enforced in boot/head.s.
 255  * Note that you must not change the sizes below without updating head.s.
 256  */
 257 extern char tmp_floppy_area[BLOCK_SIZE];
 258 extern char floppy_track_buffer[512*2*MAX_BUFFER_SECTORS];
 259 
 260 static void redo_fd_request(void);
 261 
 262 /*
 263  * These are global variables, as that's the easiest way to give
 264  * information to interrupts. They are the data used for the current
 265  * request.
 266  */
 267 #define NO_TRACK 255
 268 
 269 static int read_track = 0;      /* flag to indicate if we want to read entire track */
 270 static int buffer_track = -1;
 271 static int buffer_drive = -1;
 272 static int cur_spec1 = -1;
 273 static int cur_rate = -1;
 274 static struct floppy_struct * floppy = floppy_type;
 275 static unsigned char current_drive = 255;
 276 static unsigned char sector = 0;
 277 static unsigned char head = 0;
 278 static unsigned char track = 0;
 279 static unsigned char seek_track = 0;
 280 static unsigned char current_track = NO_TRACK;
 281 static unsigned char command = 0;
 282 static unsigned char fdc_version = FDC_TYPE_STD;        /* FDC version code */
 283 unsigned char selected = 0;
 284 struct wait_queue * wait_on_floppy_select = NULL;
 285 
 286 void floppy_deselect(unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 287 {
 288         if (nr != (current_DOR & 3))
 289                 printk("floppy_deselect: drive not selected\n");
 290         selected = 0;
 291         wake_up(&wait_on_floppy_select);
 292 }
 293 
 294 void request_done(int uptodate)
     /* [previous][next][first][last][top][bottom][index][help] */
 295 {
 296         timer_active &= ~(1 << FLOPPY_TIMER);
 297         if (format_status != FORMAT_BUSY)
 298                 end_request(uptodate);
 299         else {
 300                 format_status = uptodate ? FORMAT_OKAY : FORMAT_ERROR;
 301                 wake_up(&format_done);
 302         }
 303 }
 304 
 305 /*
 306  * floppy-change is never called from an interrupt, so we can relax a bit
 307  * here, sleep etc. Note that floppy-on tries to set current_DOR to point
 308  * to the desired drive, but it will probably not survive the sleep if
 309  * several floppies are used at the same time: thus the loop.
 310  */
 311 int floppy_change(struct buffer_head * bh)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313         unsigned int mask = 1 << (bh->b_dev & 0x03);
 314 
 315         if (MAJOR(bh->b_dev) != 2) {
 316                 printk("floppy_changed: not a floppy\n");
 317                 return 0;
 318         }
 319         if (fake_change & mask) {
 320                 fake_change &= ~mask;
 321 /* omitting the next line breaks formatting in a horrible way ... */
 322                 changed_floppies &= ~mask;
 323                 return 1;
 324         }
 325         if (changed_floppies & mask) {
 326                 changed_floppies &= ~mask;
 327                 recalibrate = 1;
 328                 return 1;
 329         }
 330         if (!bh)
 331                 return 0;
 332         if (bh->b_dirt)
 333                 ll_rw_block(WRITE, 1, &bh);
 334         else {
 335                 buffer_track = -1;
 336                 bh->b_uptodate = 0;
 337                 ll_rw_block(READ, 1, &bh);
 338         }
 339         cli();
 340         while (bh->b_lock)
 341                 sleep_on(&bh->b_wait);
 342         sti();
 343         if (changed_floppies & mask) {
 344                 changed_floppies &= ~mask;
 345                 recalibrate = 1;
 346                 return 1;
 347         }
 348         return 0;
 349 }
 350 
 351 #define copy_buffer(from,to) \
 352 __asm__("cld ; rep ; movsl" \
 353         ::"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \
 354         :"cx","di","si")
 355 
 356 static void setup_DMA(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 357 {
 358         unsigned long addr,count;
 359         unsigned char dma_code;
 360 
 361         dma_code = DMA_WRITE;
 362         if (command == FD_READ)
 363                 dma_code = DMA_READ;
 364         if (command == FD_FORMAT) {
 365                 addr = (long) tmp_floppy_area;
 366                 count = floppy->sect*4;
 367         } else {
 368                 addr = (long) CURRENT->buffer;
 369                 count = 1024;
 370         }
 371         if (read_track) {
 372 /* mark buffer-track bad, in case all this fails.. */
 373                 buffer_drive = buffer_track = -1;
 374                 count = floppy->sect*2*512;
 375                 addr = (long) floppy_track_buffer;
 376         } else if (addr >= LAST_DMA_ADDR) {
 377                 addr = (long) tmp_floppy_area;
 378                 if (command == FD_WRITE)
 379                         copy_buffer(CURRENT->buffer,tmp_floppy_area);
 380         }
 381         cli();
 382         disable_dma(FLOPPY_DMA);
 383         clear_dma_ff(FLOPPY_DMA);
 384         set_dma_mode(FLOPPY_DMA, (command == FD_READ)? DMA_MODE_READ : DMA_MODE_WRITE);
 385         set_dma_addr(FLOPPY_DMA, addr);
 386         set_dma_count(FLOPPY_DMA, count);
 387         enable_dma(FLOPPY_DMA);
 388         sti();
 389 }
 390 
 391 static void output_byte(char byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 392 {
 393         int counter;
 394         unsigned char status;
 395 
 396         if (reset)
 397                 return;
 398         for(counter = 0 ; counter < 10000 ; counter++) {
 399                 status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR);
 400                 if (status == STATUS_READY) {
 401                         outb(byte,FD_DATA);
 402                         return;
 403                 }
 404         }
 405         current_track = NO_TRACK;
 406         reset = 1;
 407         printk("Unable to send byte to FDC\n");
 408 }
 409 
 410 static int result(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 411 {
 412         int i = 0, counter, status;
 413 
 414         if (reset)
 415                 return -1;
 416         for (counter = 0 ; counter < 10000 ; counter++) {
 417                 status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
 418                 if (status == STATUS_READY) {
 419                         return i;
 420                 }
 421                 if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
 422                         if (i >= MAX_REPLIES) {
 423                                 printk("floppy_stat reply overrun\n");
 424                                 break;
 425                         }
 426                         reply_buffer[i++] = inb_p(FD_DATA);
 427                 }
 428         }
 429         reset = 1;
 430         current_track = NO_TRACK;
 431         printk("Getstatus times out\n");
 432         return -1;
 433 }
 434 
 435 static void bad_flp_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 436 {
 437         int errors;
 438 
 439         current_track = NO_TRACK;
 440         if (format_status == FORMAT_BUSY)
 441                 errors = ++format_errors;
 442         else if (!CURRENT) {
 443                 printk(DEVICE_NAME ": no current request\n");
 444                 reset = recalibrate = 1;
 445                 return;
 446         } else
 447                 errors = ++CURRENT->errors;
 448         if (errors > MAX_ERRORS) {
 449                 floppy_deselect(current_drive);
 450                 request_done(0);
 451         }
 452         if (errors > MAX_ERRORS/2)
 453                 reset = 1;
 454         else
 455                 recalibrate = 1;
 456 }       
 457 
 458 
 459 /* Set perpendicular mode as required, based on data rate, if supported.
 460  * 82077 Untested! 1Mbps data rate only possible with 82077-1.
 461  * TODO: increase MAX_BUFFER_SECTORS, add floppy_type entries.
 462  */
 463 static inline void perpendicular_mode(unsigned char rate)
     /* [previous][next][first][last][top][bottom][index][help] */
 464 {
 465         if (fdc_version == FDC_TYPE_82077) {
 466                 output_byte(FD_PERPENDICULAR);
 467                 if (rate & 0x40) {
 468                         unsigned char r = rate & 0x03;
 469                         if (r == 0)
 470                                 output_byte(2); /* perpendicular, 500 kbps */
 471                         else if (r == 3)
 472                                 output_byte(3); /* perpendicular, 1Mbps */
 473                         else {
 474                                 printk(DEVICE_NAME ": Invalid data rate for perpendicular mode!\n");
 475                                 reset = 1;
 476                         }
 477                 } else
 478                         output_byte(0);         /* conventional mode */
 479         } else {
 480                 if (rate & 0x40) {
 481                         printk(DEVICE_NAME ": perpendicular mode not supported by this FDC.\n");
 482                         reset = 1;
 483                 }
 484         }
 485 } /* perpendicular_mode */
 486 
 487 
 488 /*
 489  * This has only been tested for the case fdc_version == FDC_TYPE_STD.
 490  * In case you have a 82077 and want to test it, you'll have to compile
 491  * with `FDC_FIFO_UNTESTED' defined. You may also want to add support for
 492  * recognizing drives with vertical recording support.
 493  */
 494 static void configure_fdc_mode(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 495 {
 496         if (need_configure && (fdc_version == FDC_TYPE_82077)) {
 497                 /* Enhanced version with FIFO & vertical recording. */
 498                 output_byte(FD_CONFIGURE);
 499                 output_byte(0);
 500                 output_byte(0x1A);      /* FIFO on, polling off, 10 byte threshold */
 501                 output_byte(0);         /* precompensation from track 0 upwards */
 502                 need_configure = 0;
 503                 printk(DEVICE_NAME ": FIFO enabled\n");
 504         }
 505         if (cur_spec1 != floppy->spec1) {
 506                 cur_spec1 = floppy->spec1;
 507                 output_byte(FD_SPECIFY);
 508                 output_byte(cur_spec1);         /* hut etc */
 509                 output_byte(6);                 /* Head load time =6ms, DMA */
 510         }
 511         if (cur_rate != floppy->rate) {
 512                 /* use bit 6 of floppy->rate to indicate perpendicular mode */
 513                 perpendicular_mode(floppy->rate);
 514                 outb_p((cur_rate = (floppy->rate)) & ~0x40, FD_DCR);
 515         }
 516 } /* configure_fdc_mode */
 517 
 518 
 519 static void tell_sector(int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 520 {
 521         if (nr!=7) {
 522                 printk(" -- FDC reply errror");
 523                 reset = 1;
 524         } else
 525                 printk(": track %d, head %d, sector %d", reply_buffer[3],
 526                         reply_buffer[4], reply_buffer[5]);
 527 } /* tell_sector */
 528 
 529 
 530 /*
 531  * Ok, this interrupt is called after a DMA read/write has succeeded
 532  * or failed, so we check the results, and copy any buffers.
 533  * hhb: Added better error reporting.
 534  */
 535 static void rw_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537         char * buffer_area;
 538         int nr;
 539         char bad;
 540 
 541         nr = result();
 542         /* check IC to find cause of interrupt */
 543         switch ((ST0 & ST0_INTR)>>6) {
 544                 case 1: /* error occured during command execution */
 545                         bad = 1;
 546                         if (ST1 & ST1_WP) {
 547                                 printk(DEVICE_NAME ": Drive %d is write protected\n", current_drive);
 548                                 floppy_deselect(current_drive);
 549                                 request_done(0);
 550                                 bad = 0;
 551                         } else if (ST1 & ST1_OR) {
 552                                 if (ftd_msg[ST0 & ST0_DS])
 553                                         printk(DEVICE_NAME ": Over/Underrun - retrying\n");
 554                                 /* could continue from where we stopped, but ... */
 555                                 bad = 0;
 556                         } else if (CURRENT_ERRORS > min_report_error_cnt[ST0 & ST0_DS]) {
 557                                 printk(DEVICE_NAME " %d: ", ST0 & ST0_DS);
 558                                 if (ST0 & ST0_ECE) {
 559                                         printk("Recalibrate failed!");
 560                                 } else if (ST2 & ST2_CRC) {
 561                                         printk("data CRC error");
 562                                         tell_sector(nr);
 563                                 } else if (ST1 & ST1_CRC) {
 564                                         printk("CRC error");
 565                                         tell_sector(nr);
 566                                 } else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) {
 567                                         if (!probing) {
 568                                                 printk("sector not found");
 569                                                 tell_sector(nr);
 570                                         } else
 571                                                 printk("probe failed...");
 572                                 } else if (ST2 & ST2_WC) {      /* seek error */
 573                                         printk("wrong cylinder");
 574                                 } else if (ST2 & ST2_BC) {      /* cylinder marked as bad */
 575                                         printk("bad cylinder");
 576                                 } else {
 577                                         printk("unknown error. ST[0..3] are: 0x%x 0x%x 0x%x 0x%x\n", ST0, ST1, ST2, ST3);
 578                                 }
 579                                 printk("\n");
 580 
 581                         }
 582                         if (bad)
 583                                 bad_flp_intr();
 584                         redo_fd_request();
 585                         return;
 586                 case 2: /* invalid command given */
 587                         printk(DEVICE_NAME ": Invalid FDC command given!\n");
 588                         request_done(0);
 589                         return;
 590                 case 3:
 591                         printk(DEVICE_NAME ": Abnormal termination caused by polling\n");
 592                         bad_flp_intr();
 593                         redo_fd_request();
 594                         return;
 595                 default: /* (0) Normal command termination */
 596                         break;
 597         }
 598 
 599         if (probing) {
 600                 int drive = MINOR(CURRENT->dev);
 601 
 602                 if (ftd_msg[drive])
 603                         printk("Auto-detected floppy type %s in fd%d\n",
 604                             floppy->name,drive);
 605                 current_type[drive] = floppy;
 606                 floppy_sizes[drive] = floppy->size >> 1;
 607                 probing = 0;
 608         }
 609         if (read_track) {
 610                 buffer_track = seek_track;
 611                 buffer_drive = current_drive;
 612                 buffer_area = floppy_track_buffer +
 613                         ((sector-1 + head*floppy->sect)<<9);
 614                 copy_buffer(buffer_area,CURRENT->buffer);
 615         } else if (command == FD_READ &&
 616                 (unsigned long)(CURRENT->buffer) >= LAST_DMA_ADDR)
 617                 copy_buffer(tmp_floppy_area,CURRENT->buffer);
 618         floppy_deselect(current_drive);
 619         request_done(1);
 620         redo_fd_request();
 621 }
 622 
 623 /*
 624  * We try to read tracks, but if we get too many errors, we
 625  * go back to reading just one sector at a time.
 626  *
 627  * This means we should be able to read a sector even if there
 628  * are other bad sectors on this track.
 629  */
 630 inline void setup_rw_floppy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 631 {
 632         setup_DMA();
 633         do_floppy = rw_interrupt;
 634         output_byte(command);
 635         if (command != FD_FORMAT) {
 636                 if (read_track) {
 637                         output_byte(current_drive);
 638                         output_byte(track);
 639                         output_byte(0);
 640                         output_byte(1);
 641                 } else {
 642                         output_byte(head<<2 | current_drive);
 643                         output_byte(track);
 644                         output_byte(head);
 645                         output_byte(sector);
 646                 }
 647                 output_byte(2);         /* sector size = 512 */
 648                 output_byte(floppy->sect);
 649                 output_byte(floppy->gap);
 650                 output_byte(0xFF);      /* sector size (0xff when n!=0 ?) */
 651         } else {
 652                 output_byte(head<<2 | current_drive);
 653                 output_byte(2);
 654                 output_byte(floppy->sect);
 655                 output_byte(floppy->fmt_gap);
 656                 output_byte(FD_FILL_BYTE);
 657         }
 658         if (reset)
 659                 redo_fd_request();
 660 }
 661 
 662 /*
 663  * This is the routine called after every seek (or recalibrate) interrupt
 664  * from the floppy controller. Note that the "unexpected interrupt" routine
 665  * also does a recalibrate, but doesn't come here.
 666  */
 667 static void seek_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 668 {
 669 /* sense drive status */
 670         output_byte(FD_SENSEI);
 671         if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
 672                 printk(DEVICE_NAME ": seek failed\n");
 673                 recalibrate = 1;
 674                 bad_flp_intr();
 675                 redo_fd_request();
 676                 return;
 677         }
 678         current_track = ST1;
 679         setup_rw_floppy();
 680 }
 681 
 682 
 683 /*
 684  * This routine is called when everything should be correctly set up
 685  * for the transfer (ie floppy motor is on and the correct floppy is
 686  * selected).
 687  */
 688 static void transfer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 689 {
 690         read_track = (command == FD_READ) && (CURRENT_ERRORS < 4) &&
 691             (floppy->sect <= MAX_BUFFER_SECTORS);
 692 
 693         configure_fdc_mode();
 694 
 695         if (reset) {
 696                 redo_fd_request();
 697                 return;
 698         }
 699         if (!seek) {
 700                 setup_rw_floppy();
 701                 return;
 702         }
 703 
 704         do_floppy = seek_interrupt;
 705         output_byte(FD_SEEK);
 706         if (read_track)
 707                 output_byte(current_drive);
 708         else
 709                 output_byte((head<<2) | current_drive);
 710         output_byte(seek_track);
 711         if (reset)
 712                 redo_fd_request();
 713 }
 714 
 715 /*
 716  * Special case - used after a unexpected interrupt (or reset)
 717  */
 718 
 719 static void recalibrate_floppy(void);
 720 
 721 static void recal_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 722 {
 723         output_byte(FD_SENSEI);
 724         current_track = NO_TRACK;
 725         if (result()!=2 || (ST0 & 0xE0) == 0x60)
 726                 reset = 1;
 727 /* Recalibrate until track 0 is reached. Might help on some errors. */
 728         if ((ST0 & 0x10) == 0x10)
 729                 recalibrate_floppy();   /* FIXME: should limit nr of recalibrates */
 730         else
 731                 redo_fd_request();
 732 }
 733 
 734 static void unexpected_floppy_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 735 {
 736         current_track = NO_TRACK;
 737         output_byte(FD_SENSEI);
 738         printk(DEVICE_NAME ": unexpected interrupt\n");
 739         if (result()!=2 || (ST0 & 0xE0) == 0x60)
 740                 reset = 1;
 741         else
 742                 recalibrate = 1;
 743 }
 744 
 745 static void recalibrate_floppy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 746 {
 747         recalibrate = 0;
 748         current_track = 0;
 749         do_floppy = recal_interrupt;
 750         output_byte(FD_RECALIBRATE);
 751         output_byte(head<<2 | current_drive);
 752         if (reset)
 753                 redo_fd_request();
 754 }
 755 
 756 /*
 757  * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
 758  */
 759 static void reset_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 760 {
 761         short i;
 762 
 763         for (i=0; i<4; i++) {
 764                 output_byte(FD_SENSEI);
 765                 (void) result();
 766         }
 767         output_byte(FD_SPECIFY);
 768         output_byte(cur_spec1);         /* hut etc */
 769         output_byte(6);                 /* Head load time =6ms, DMA */
 770         configure_fdc_mode();           /* reprogram fdc */
 771         if (initial_reset_flag) {
 772                 initial_reset_flag = 0;
 773                 recalibrate = 1;
 774                 reset = 0;
 775                 return;
 776         }
 777         if (!recover)
 778                 redo_fd_request();
 779         else {
 780                 recalibrate_floppy();
 781                 recover = 0;
 782         }
 783 }
 784 
 785 /*
 786  * reset is done by pulling bit 2 of DOR low for a while.
 787  */
 788 static void reset_floppy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 789 {
 790         int i;
 791 
 792         do_floppy = reset_interrupt;
 793         reset = 0;
 794         current_track = NO_TRACK;
 795         cur_spec1 = -1;
 796         cur_rate = -1;
 797         recalibrate = 1;
 798         need_configure = 1;
 799         if (!initial_reset_flag)
 800                 printk("Reset-floppy called\n");
 801         cli();
 802         outb_p(current_DOR & ~0x04, FD_DOR);
 803         for (i=0 ; i<1000 ; i++)
 804                 __asm__("nop");
 805         outb(current_DOR, FD_DOR);
 806         sti();
 807 }
 808 
 809 static void floppy_shutdown(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 810 {
 811         cli();
 812         do_floppy = NULL;
 813         request_done(0);
 814         recover = 1;
 815         reset_floppy();
 816         sti();
 817         redo_fd_request();
 818 }
 819 
 820 static void shake_done(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 821 {
 822         current_track = NO_TRACK;
 823         if (inb(FD_DIR) & 0x80)
 824                 request_done(0);
 825         redo_fd_request();
 826 }
 827 
 828 static int retry_recal(void (*proc)(void))
     /* [previous][next][first][last][top][bottom][index][help] */
 829 {
 830         output_byte(FD_SENSEI);
 831         if (result() == 2 && (ST0 & 0x10) != 0x10) return 0;
 832         do_floppy = proc;
 833         output_byte(FD_RECALIBRATE);
 834         output_byte(head<<2 | current_drive);
 835         return 1;
 836 }
 837 
 838 static void shake_zero(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 839 {
 840         if (!retry_recal(shake_zero)) shake_done();
 841 }
 842 
 843 static void shake_one(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 844 {
 845         if (retry_recal(shake_one)) return;
 846         do_floppy = shake_done;
 847         output_byte(FD_SEEK);
 848         output_byte(head << 2 | current_drive);
 849         output_byte(1);
 850 }
 851 
 852 static void floppy_on_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 853 {
 854         if (inb(FD_DIR) & 0x80) {
 855                 changed_floppies |= 1<<current_drive;
 856                 buffer_track = -1;
 857                 if (keep_data[current_drive]) {
 858                         if (keep_data[current_drive] > 0)
 859                                 keep_data[current_drive]--;
 860                 }
 861                 else {
 862                         if (ftd_msg[current_drive] && current_type[current_drive] != NULL)
 863                                 printk("Disk type is undefined after disk "
 864                                     "change in fd%d\n",current_drive);
 865                         current_type[current_drive] = NULL;
 866                         floppy_sizes[current_drive] = MAX_DISK_SIZE;
 867                 }
 868 /* Forcing the drive to seek makes the "media changed" condition go away.
 869  * There should be a cleaner solution for that ...
 870  */
 871                 if (!reset && !recalibrate) {
 872                         do_floppy = (current_track && current_track != NO_TRACK)
 873                             ?  shake_zero : shake_one;
 874                         output_byte(FD_RECALIBRATE);
 875                         output_byte(head<<2 | current_drive);
 876                         return;
 877                 }
 878         }
 879         if (reset) {
 880                 reset_floppy();
 881                 return;
 882         }
 883         if (recalibrate) {
 884                 recalibrate_floppy();
 885                 return;
 886         }
 887 /* We cannot do a floppy-select, as that might sleep. We just force it */
 888         selected = 1;
 889         if (current_drive != (current_DOR & 3)) {
 890                 seek = 1;
 891                 current_track = NO_TRACK;
 892                 current_DOR &= 0xFC;
 893                 current_DOR |= current_drive;
 894                 outb(current_DOR,FD_DOR);
 895                 add_timer(2,&transfer);
 896         } else
 897                 transfer();
 898 }
 899 
 900 static void setup_format_params(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 901 {
 902     unsigned char *here = (unsigned char *) tmp_floppy_area;
 903     int count,head_shift,track_shift,total_shift;
 904 
 905     /* allow for about 30ms for data transport per track */
 906     head_shift  = floppy->sect / 6;
 907     /* a ``cylinder'' is two tracks plus a little stepping time */
 908     track_shift = 2 * head_shift + 1; 
 909     /* count backwards */
 910     total_shift = floppy->sect - 
 911         ((track_shift * track + head_shift * head) % floppy->sect);
 912 
 913     /* XXX: should do a check to see this fits in tmp_floppy_area!! */
 914     for (count = 0; count < floppy->sect; count++) {
 915         *here++ = track;
 916         *here++ = head;
 917         *here++ = 1 + (( count + total_shift ) % floppy->sect);
 918         *here++ = 2; /* 512 bytes */
 919     }
 920 }
 921 
 922 static void redo_fd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 923 {
 924         unsigned int block;
 925         char * buffer_area;
 926         int device;
 927 
 928         if (CURRENT && CURRENT->dev < 0) return;
 929 
 930 repeat:
 931         if (format_status == FORMAT_WAIT)
 932                 format_status = FORMAT_BUSY;
 933         if (format_status != FORMAT_BUSY) {
 934                 if (!CURRENT) {
 935                         if (!fdc_busy)
 936                                 printk("FDC access conflict!");
 937                         fdc_busy = 0;
 938                         wake_up(&fdc_wait);
 939                         CLEAR_INTR;
 940                         return;
 941                 }
 942                 if (MAJOR(CURRENT->dev) != MAJOR_NR)
 943                         panic(DEVICE_NAME ": request list destroyed"); \
 944                 if (CURRENT->bh) {
 945                         if (!CURRENT->bh->b_lock)
 946                                 panic(DEVICE_NAME ": block not locked");
 947                 }
 948         }
 949         seek = 0;
 950         probing = 0;
 951         device = MINOR(CURRENT_DEVICE);
 952         if (device > 3)
 953                 floppy = (device >> 2) + floppy_type;
 954         else { /* Auto-detection */
 955                 if ((floppy = current_type[device & 3]) == NULL) {
 956                         probing = 1;
 957                         if ((floppy = base_type[device & 3]) ==
 958                             NULL) {
 959                                 request_done(0);
 960                                 goto repeat;
 961                         }
 962                         floppy += CURRENT_ERRORS & 1;
 963                 }
 964         }
 965         if (format_status != FORMAT_BUSY) {
 966                 if (current_drive != CURRENT_DEV) {
 967                         current_track = NO_TRACK;
 968                         current_drive = CURRENT_DEV;
 969                 }
 970                 block = CURRENT->sector;
 971                 if (block+2 > floppy->size) {
 972                         request_done(0);
 973                         goto repeat;
 974                 }
 975                 sector = block % floppy->sect;
 976                 block /= floppy->sect;
 977                 head = block % floppy->head;
 978                 track = block / floppy->head;
 979                 seek_track = track << floppy->stretch;
 980                 if (CURRENT->cmd == READ)
 981                         command = FD_READ;
 982                 else if (CURRENT->cmd == WRITE)
 983                         command = FD_WRITE;
 984                 else {
 985                         printk("do_fd_request: unknown command\n");
 986                         request_done(0);
 987                         goto repeat;
 988                 }
 989         } else {
 990                 if (current_drive != (format_req.device & 3))
 991                         current_track = NO_TRACK;
 992                 current_drive = format_req.device & 3;
 993                 if (((unsigned) format_req.track) >= floppy->track ||
 994                     (format_req.head & 0xfffe) || probing) {
 995                         request_done(0);
 996                         goto repeat;
 997                 }
 998                 head = format_req.head;
 999                 track = format_req.track;
1000                 seek_track = track << floppy->stretch;
1001                 if (seek_track == buffer_track) buffer_track = -1;
1002                 command = FD_FORMAT;
1003                 setup_format_params();
1004         }
1005         timer_table[FLOPPY_TIMER].expires = jiffies+10*HZ;
1006         timer_active |= 1 << FLOPPY_TIMER;
1007         if ((seek_track == buffer_track) &&
1008          (current_drive == buffer_drive)) {
1009                 buffer_area = floppy_track_buffer +
1010                         ((sector + head*floppy->sect)<<9);
1011                 if (command == FD_READ) {
1012                         copy_buffer(buffer_area,CURRENT->buffer);
1013                         request_done(1);
1014                         goto repeat;
1015                 } else if (command == FD_WRITE)
1016                         copy_buffer(CURRENT->buffer,buffer_area);
1017         }
1018         if (seek_track != current_track)
1019                 seek = 1;
1020         sector++;
1021         add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);
1022 }
1023 
1024 void do_fd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1025 {
1026         cli();
1027         while (fdc_busy) sleep_on(&fdc_wait);
1028         fdc_busy = 1;
1029         sti();
1030         redo_fd_request();
1031 }
1032 
1033 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
1034     unsigned int param)
1035 {
1036         int drive,cnt,okay;
1037         struct floppy_struct *this;
1038 
1039         switch (cmd) {
1040                 RO_IOCTLS(inode->i_rdev,param);
1041         }
1042         drive = MINOR(inode->i_rdev);
1043         switch (cmd) {
1044                 case FDFMTBEG:
1045                         if (!suser())
1046                                 return -EPERM;
1047                         return 0;
1048                 case FDFMTEND:
1049                         if (!suser())
1050                                 return -EPERM;
1051                         cli();
1052                         fake_change |= 1 << (drive & 3);
1053                         sti();
1054                         drive &= 3;
1055                         cmd = FDCLRPRM;
1056                         break;
1057                 case FDGETPRM:
1058                         if (drive > 3) this = &floppy_type[drive >> 2];
1059                         else if ((this = current_type[drive & 3]) == NULL)
1060                                     return -ENODEV;
1061                         verify_area((void *) param,sizeof(struct floppy_struct));
1062                         for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
1063                                 put_fs_byte(((char *) this)[cnt],
1064                                     (char *) param+cnt);
1065                         return 0;
1066                 case FDFMTTRK:
1067                         if (!suser())
1068                                 return -EPERM;
1069                         cli();
1070                         while (format_status != FORMAT_NONE)
1071                                 sleep_on(&format_done);
1072                         for (cnt = 0; cnt < sizeof(struct format_descr); cnt++)
1073                                 ((char *) &format_req)[cnt] = get_fs_byte(
1074                                     (char *) param+cnt);
1075                         format_req.device = drive;
1076                         format_status = FORMAT_WAIT;
1077                         format_errors = 0;
1078                         while (format_status != FORMAT_OKAY && format_status !=
1079                             FORMAT_ERROR) {
1080                                 if (fdc_busy) sleep_on(&fdc_wait);
1081                                 else {
1082                                         fdc_busy = 1;
1083                                         redo_fd_request();
1084                                 }
1085                         }
1086                         while (format_status != FORMAT_OKAY && format_status !=
1087                             FORMAT_ERROR)
1088                                 sleep_on(&format_done);
1089                         sti();
1090                         okay = format_status == FORMAT_OKAY;
1091                         format_status = FORMAT_NONE;
1092                         wake_up(&format_done);
1093                         return okay ? 0 : -EIO;
1094         }
1095         if (!suser())
1096                 return -EPERM;
1097         if (drive < 0 || drive > 3)
1098                 return -EINVAL;
1099         switch (cmd) {
1100                 case FDCLRPRM:
1101                         current_type[drive] = NULL;
1102                         floppy_sizes[drive] = MAX_DISK_SIZE;
1103                         keep_data[drive] = 0;
1104                         break;
1105                 case FDSETPRM:
1106                 case FDDEFPRM:
1107                         for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
1108                                 ((char *) &user_params[drive])[cnt] =
1109                                     get_fs_byte((char *) param+cnt);
1110                         current_type[drive] = &user_params[drive];
1111                         floppy_sizes[drive] = user_params[drive].size >> 1;
1112                         if (cmd == FDDEFPRM) keep_data[drive] = -1;
1113                         else {
1114                                 cli();
1115                                 while (fdc_busy) sleep_on(&fdc_wait);
1116                                 fdc_busy = 1;
1117                                 sti();
1118                                 outb_p((current_DOR & 0xfc) | drive |
1119                                     (0x10 << drive),FD_DOR);
1120                                 for (cnt = 0; cnt < 1000; cnt++) __asm__("nop");
1121                                 keep_data[drive] = (inb(FD_DIR) & 0x80) ? 1 : 0;
1122                                 outb_p(current_DOR,FD_DOR);
1123                                 fdc_busy = 0;
1124                                 wake_up(&fdc_wait);
1125                         }
1126                         break;
1127                 case FDMSGON:
1128                         ftd_msg[drive] = 1;
1129                         break;
1130                 case FDMSGOFF:
1131                         ftd_msg[drive] = 0;
1132                         break;
1133                 case FDSETEMSGTRESH:
1134                         min_report_error_cnt[drive] = (unsigned short) (param & 0x0f);
1135                         break;
1136                 default:
1137                         return -EINVAL;
1138         }
1139         return 0;
1140 }
1141 
1142 #define CMOS_READ(addr) ({ \
1143 outb_p(0x80|addr,0x70); \
1144 inb_p(0x71); \
1145 })
1146 
1147 static struct floppy_struct *find_base(int drive,int code)
     /* [previous][next][first][last][top][bottom][index][help] */
1148 {
1149         struct floppy_struct *base;
1150 
1151         if (code > 0 && code < 5) {
1152                 base = &floppy_types[(code-1)*2];
1153                 printk("fd%d is %s",drive,base->name);
1154                 return base;
1155         }
1156         printk("fd%d is unknown type %d",drive,code);
1157         return NULL;
1158 }
1159 
1160 static void config_types(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1161 {
1162         printk("Floppy drive(s): ");
1163         base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
1164         if (((CMOS_READ(0x14) >> 6) & 1) == 0)
1165                 base_type[1] = NULL;
1166         else {
1167                 printk(", ");
1168                 base_type[1] = find_base(1,CMOS_READ(0x10) & 15);
1169         }
1170         base_type[2] = base_type[3] = NULL;
1171         printk("\n");
1172 }
1173 
1174 /*
1175  * floppy_open check for aliasing (/dev/fd0 can be the same as
1176  * /dev/PS0 etc), and disallows simultaneous access to the same
1177  * drive with different device numbers.
1178  */
1179 static int floppy_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1180 {
1181         int drive;
1182         int old_dev;
1183 
1184         drive = inode->i_rdev & 3;
1185         old_dev = fd_device[drive];
1186         if (fd_ref[drive])
1187                 if (old_dev != inode->i_rdev)
1188                         return -EBUSY;
1189         fd_ref[drive]++;
1190         fd_device[drive] = inode->i_rdev;
1191         buffer_drive = buffer_track = -1;
1192         if (old_dev && old_dev != inode->i_rdev)
1193                 invalidate_buffers(old_dev);
1194         if (filp && filp->f_mode)
1195                 check_disk_change(inode->i_rdev);
1196         return 0;
1197 }
1198 
1199 static void floppy_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1200 {
1201         sync_dev(inode->i_rdev);
1202         if (!fd_ref[inode->i_rdev & 3]--) {
1203                 printk("floppy_release with fd_ref == 0");
1204                 fd_ref[inode->i_rdev & 3] = 0;
1205         }
1206 }
1207 
1208 static struct file_operations floppy_fops = {
1209         NULL,                   /* lseek - default */
1210         block_read,             /* read - general block-dev read */
1211         block_write,            /* write - general block-dev write */
1212         NULL,                   /* readdir - bad */
1213         NULL,                   /* select */
1214         fd_ioctl,               /* ioctl */
1215         NULL,                   /* mmap */
1216         floppy_open,            /* open */
1217         floppy_release          /* release */
1218 };
1219 
1220 
1221 /*
1222  * The version command is not supposed to generate an interrupt, but
1223  * my FDC does, except when booting in SVGA screen mode.
1224  * When it does generate an interrupt, it doesn't return any status bytes.
1225  * It appears to have something to do with the version command...
1226  *
1227  * This should never be called, because of the reset after the version check.
1228  */
1229 static void ignore_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1230 {
1231         printk(DEVICE_NAME ": weird interrupt ignored (%d)\n", result());
1232         reset = 1;
1233         CLEAR_INTR;     /* ignore only once */
1234 }
1235 
1236 
1237 static void floppy_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
1238 {
1239         void (*handler)(void) = DEVICE_INTR;
1240 
1241         DEVICE_INTR = NULL;
1242         if (!handler)
1243                 handler = unexpected_floppy_interrupt;
1244         handler();
1245 }
1246 
1247 /*
1248  * This is the floppy IRQ description. The SA_INTERRUPT in sa_flags
1249  * means we run the IRQ-handler with interrupts disabled.
1250  */
1251 static struct sigaction floppy_sigaction = {
1252         floppy_interrupt,
1253         0,
1254         SA_INTERRUPT,
1255         NULL
1256 };
1257 
1258 void floppy_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1259 {
1260         outb(current_DOR,FD_DOR);
1261         blk_size[MAJOR_NR] = floppy_sizes;
1262         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1263         blkdev_fops[MAJOR_NR] = &floppy_fops;
1264         timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
1265         timer_active &= ~(1 << FLOPPY_TIMER);
1266         config_types();
1267         if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
1268                 printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ);
1269         if (request_dma(FLOPPY_DMA))
1270                 printk("Unable to grab DMA%d for the floppy driver\n", FLOPPY_DMA);
1271         /* Try to determine the floppy controller type */
1272         DEVICE_INTR = ignore_interrupt; /* don't ask ... */
1273         output_byte(FD_VERSION);        /* get FDC version code */
1274         if (result() != 1) {
1275                 printk(DEVICE_NAME ": FDC failed to return version byte\n");
1276                 fdc_version = FDC_TYPE_STD;
1277         } else
1278                 fdc_version = reply_buffer[0];
1279         if (fdc_version != FDC_TYPE_STD) 
1280                 printk(DEVICE_NAME ": FDC version 0x%x\n", fdc_version);
1281 #ifndef FDC_FIFO_UNTESTED
1282         fdc_version = FDC_TYPE_STD;     /* force std fdc type; can't test other. */
1283 #endif
1284 
1285         /* Not all FDCs seem to be able to handle the version command
1286          * properly, so force a reset for the standard FDC clones,
1287          * to avoid interrupt garbage.
1288          */
1289 
1290         if (fdc_version == FDC_TYPE_STD) {
1291                 initial_reset_flag = 1;
1292                 reset_floppy();
1293         }
1294 }

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