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,bh);
 334         else {
 335                 buffer_track = -1;
 336                 bh->b_uptodate = 0;
 337                 ll_rw_block(READ,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 void inline 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         request_done(0);
 813         recover = 1;
 814         reset_floppy();
 815         sti();
 816 }
 817 
 818 static void shake_done(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 819 {
 820         current_track = NO_TRACK;
 821         if (inb(FD_DIR) & 0x80)
 822                 request_done(0);
 823         redo_fd_request();
 824 }
 825 
 826 static int retry_recal(void (*proc)(void))
     /* [previous][next][first][last][top][bottom][index][help] */
 827 {
 828         output_byte(FD_SENSEI);
 829         if (result() == 2 && (ST0 & 0x10) != 0x10) return 0;
 830         do_floppy = proc;
 831         output_byte(FD_RECALIBRATE);
 832         output_byte(head<<2 | current_drive);
 833         return 1;
 834 }
 835 
 836 static void shake_zero(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 837 {
 838         if (!retry_recal(shake_zero)) shake_done();
 839 }
 840 
 841 static void shake_one(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 842 {
 843         if (retry_recal(shake_one)) return;
 844         do_floppy = shake_done;
 845         output_byte(FD_SEEK);
 846         output_byte(head << 2 | current_drive);
 847         output_byte(1);
 848 }
 849 
 850 static void floppy_on_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 851 {
 852         if (inb(FD_DIR) & 0x80) {
 853                 changed_floppies |= 1<<current_drive;
 854                 buffer_track = -1;
 855                 if (keep_data[current_drive]) {
 856                         if (keep_data[current_drive] > 0)
 857                                 keep_data[current_drive]--;
 858                 }
 859                 else {
 860                         if (ftd_msg[current_drive] && current_type[current_drive] != NULL)
 861                                 printk("Disk type is undefined after disk "
 862                                     "change in fd%d\n",current_drive);
 863                         current_type[current_drive] = NULL;
 864                         floppy_sizes[current_drive] = MAX_DISK_SIZE;
 865                 }
 866 /* Forcing the drive to seek makes the "media changed" condition go away.
 867  * There should be a cleaner solution for that ...
 868  */
 869                 if (!reset && !recalibrate) {
 870                         do_floppy = (current_track && current_track != NO_TRACK)
 871                             ?  shake_zero : shake_one;
 872                         output_byte(FD_RECALIBRATE);
 873                         output_byte(head<<2 | current_drive);
 874                         return;
 875                 }
 876         }
 877         if (reset) {
 878                 reset_floppy();
 879                 return;
 880         }
 881         if (recalibrate) {
 882                 recalibrate_floppy();
 883                 return;
 884         }
 885 /* We cannot do a floppy-select, as that might sleep. We just force it */
 886         selected = 1;
 887         if (current_drive != (current_DOR & 3)) {
 888                 seek = 1;
 889                 current_track = NO_TRACK;
 890                 current_DOR &= 0xFC;
 891                 current_DOR |= current_drive;
 892                 outb(current_DOR,FD_DOR);
 893                 add_timer(2,&transfer);
 894         } else
 895                 transfer();
 896 }
 897 
 898 static void setup_format_params(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 899 {
 900     unsigned char *here = (unsigned char *) tmp_floppy_area;
 901     int count,head_shift,track_shift,total_shift;
 902 
 903     /* allow for about 30ms for data transport per track */
 904     head_shift  = floppy->sect / 6;
 905     /* a ``cylinder'' is two tracks plus a little stepping time */
 906     track_shift = 2 * head_shift + 1; 
 907     /* count backwards */
 908     total_shift = floppy->sect - 
 909         ((track_shift * track + head_shift * head) % floppy->sect);
 910 
 911     /* XXX: should do a check to see this fits in tmp_floppy_area!! */
 912     for (count = 0; count < floppy->sect; count++) {
 913         *here++ = track;
 914         *here++ = head;
 915         *here++ = 1 + (( count + total_shift ) % floppy->sect);
 916         *here++ = 2; /* 512 bytes */
 917     }
 918 }
 919 
 920 static void redo_fd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 921 {
 922         unsigned int block;
 923         char * buffer_area;
 924         int device;
 925 
 926 repeat:
 927         if (format_status == FORMAT_WAIT)
 928                 format_status = FORMAT_BUSY;
 929         if (format_status != FORMAT_BUSY) {
 930                 if (!CURRENT) {
 931                         if (!fdc_busy)
 932                                 printk("FDC access conflict!");
 933                         fdc_busy = 0;
 934                         wake_up(&fdc_wait);
 935                         CLEAR_INTR;
 936                         return;
 937                 }
 938                 if (MAJOR(CURRENT->dev) != MAJOR_NR)
 939                         panic(DEVICE_NAME ": request list destroyed"); \
 940                 if (CURRENT->bh) {
 941                         if (!CURRENT->bh->b_lock)
 942                                 panic(DEVICE_NAME ": block not locked");
 943                 }
 944         }
 945         seek = 0;
 946         probing = 0;
 947         device = MINOR(CURRENT_DEVICE);
 948         if (device > 3)
 949                 floppy = (device >> 2) + floppy_type;
 950         else { /* Auto-detection */
 951                 if ((floppy = current_type[device & 3]) == NULL) {
 952                         probing = 1;
 953                         if ((floppy = base_type[device & 3]) ==
 954                             NULL) {
 955                                 request_done(0);
 956                                 goto repeat;
 957                         }
 958                         floppy += CURRENT_ERRORS & 1;
 959                 }
 960         }
 961         if (format_status != FORMAT_BUSY) {
 962                 if (current_drive != CURRENT_DEV) {
 963                         current_track = NO_TRACK;
 964                         current_drive = CURRENT_DEV;
 965                 }
 966                 block = CURRENT->sector;
 967                 if (block+2 > floppy->size) {
 968                         request_done(0);
 969                         goto repeat;
 970                 }
 971                 sector = block % floppy->sect;
 972                 block /= floppy->sect;
 973                 head = block % floppy->head;
 974                 track = block / floppy->head;
 975                 seek_track = track << floppy->stretch;
 976                 if (CURRENT->cmd == READ)
 977                         command = FD_READ;
 978                 else if (CURRENT->cmd == WRITE)
 979                         command = FD_WRITE;
 980                 else {
 981                         printk("do_fd_request: unknown command\n");
 982                         request_done(0);
 983                         goto repeat;
 984                 }
 985         } else {
 986                 if (current_drive != (format_req.device & 3))
 987                         current_track = NO_TRACK;
 988                 current_drive = format_req.device & 3;
 989                 if (((unsigned) format_req.track) >= floppy->track ||
 990                     (format_req.head & 0xfffe) || probing) {
 991                         request_done(0);
 992                         goto repeat;
 993                 }
 994                 head = format_req.head;
 995                 track = format_req.track;
 996                 seek_track = track << floppy->stretch;
 997                 if (seek_track == buffer_track) buffer_track = -1;
 998                 command = FD_FORMAT;
 999                 setup_format_params();
1000         }
1001         timer_table[FLOPPY_TIMER].expires = jiffies+10*HZ;
1002         timer_active |= 1 << FLOPPY_TIMER;
1003         if ((seek_track == buffer_track) &&
1004          (current_drive == buffer_drive)) {
1005                 buffer_area = floppy_track_buffer +
1006                         ((sector + head*floppy->sect)<<9);
1007                 if (command == FD_READ) {
1008                         copy_buffer(buffer_area,CURRENT->buffer);
1009                         request_done(1);
1010                         goto repeat;
1011                 } else if (command == FD_WRITE)
1012                         copy_buffer(CURRENT->buffer,buffer_area);
1013         }
1014         if (seek_track != current_track)
1015                 seek = 1;
1016         sector++;
1017         add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);
1018 }
1019 
1020 void do_fd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1021 {
1022         cli();
1023         while (fdc_busy) sleep_on(&fdc_wait);
1024         fdc_busy = 1;
1025         sti();
1026         redo_fd_request();
1027 }
1028 
1029 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
1030     unsigned int param)
1031 {
1032         int drive,cnt,okay;
1033         struct floppy_struct *this;
1034 
1035         switch (cmd) {
1036                 RO_IOCTLS(inode->i_rdev,param);
1037         }
1038         drive = MINOR(inode->i_rdev);
1039         switch (cmd) {
1040                 case FDFMTBEG:
1041                         if (!suser())
1042                                 return -EPERM;
1043                         return 0;
1044                 case FDFMTEND:
1045                         if (!suser())
1046                                 return -EPERM;
1047                         cli();
1048                         fake_change |= 1 << (drive & 3);
1049                         sti();
1050                         drive &= 3;
1051                         cmd = FDCLRPRM;
1052                         break;
1053                 case FDGETPRM:
1054                         if (drive > 3) this = &floppy_type[drive >> 2];
1055                         else if ((this = current_type[drive & 3]) == NULL)
1056                                     return -ENODEV;
1057                         verify_area((void *) param,sizeof(struct floppy_struct));
1058                         for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
1059                                 put_fs_byte(((char *) this)[cnt],
1060                                     (char *) param+cnt);
1061                         return 0;
1062                 case FDFMTTRK:
1063                         if (!suser())
1064                                 return -EPERM;
1065                         cli();
1066                         while (format_status != FORMAT_NONE)
1067                                 sleep_on(&format_done);
1068                         for (cnt = 0; cnt < sizeof(struct format_descr); cnt++)
1069                                 ((char *) &format_req)[cnt] = get_fs_byte(
1070                                     (char *) param+cnt);
1071                         format_req.device = drive;
1072                         format_status = FORMAT_WAIT;
1073                         format_errors = 0;
1074                         while (format_status != FORMAT_OKAY && format_status !=
1075                             FORMAT_ERROR) {
1076                                 if (fdc_busy) sleep_on(&fdc_wait);
1077                                 else {
1078                                         fdc_busy = 1;
1079                                         redo_fd_request();
1080                                 }
1081                         }
1082                         while (format_status != FORMAT_OKAY && format_status !=
1083                             FORMAT_ERROR)
1084                                 sleep_on(&format_done);
1085                         sti();
1086                         okay = format_status == FORMAT_OKAY;
1087                         format_status = FORMAT_NONE;
1088                         wake_up(&format_done);
1089                         return okay ? 0 : -EIO;
1090         }
1091         if (!suser())
1092                 return -EPERM;
1093         if (drive < 0 || drive > 3)
1094                 return -EINVAL;
1095         switch (cmd) {
1096                 case FDCLRPRM:
1097                         current_type[drive] = NULL;
1098                         floppy_sizes[drive] = MAX_DISK_SIZE;
1099                         keep_data[drive] = 0;
1100                         break;
1101                 case FDSETPRM:
1102                 case FDDEFPRM:
1103                         for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
1104                                 ((char *) &user_params[drive])[cnt] =
1105                                     get_fs_byte((char *) param+cnt);
1106                         current_type[drive] = &user_params[drive];
1107                         floppy_sizes[drive] = user_params[drive].size >> 1;
1108                         if (cmd == FDDEFPRM) keep_data[drive] = -1;
1109                         else {
1110                                 cli();
1111                                 while (fdc_busy) sleep_on(&fdc_wait);
1112                                 fdc_busy = 1;
1113                                 sti();
1114                                 outb_p((current_DOR & 0xfc) | drive |
1115                                     (0x10 << drive),FD_DOR);
1116                                 for (cnt = 0; cnt < 1000; cnt++) __asm__("nop");
1117                                 keep_data[drive] = (inb(FD_DIR) & 0x80) ? 1 : 0;
1118                                 outb_p(current_DOR,FD_DOR);
1119                                 fdc_busy = 0;
1120                                 wake_up(&fdc_wait);
1121                         }
1122                         break;
1123                 case FDMSGON:
1124                         ftd_msg[drive] = 1;
1125                         break;
1126                 case FDMSGOFF:
1127                         ftd_msg[drive] = 0;
1128                         break;
1129                 case FDSETEMSGTRESH:
1130                         min_report_error_cnt[drive] = (unsigned short) (param & 0x0f);
1131                         break;
1132                 default:
1133                         return -EINVAL;
1134         }
1135         return 0;
1136 }
1137 
1138 #define CMOS_READ(addr) ({ \
1139 outb_p(0x80|addr,0x70); \
1140 inb_p(0x71); \
1141 })
1142 
1143 static struct floppy_struct *find_base(int drive,int code)
     /* [previous][next][first][last][top][bottom][index][help] */
1144 {
1145         struct floppy_struct *base;
1146 
1147         if (code > 0 && code < 5) {
1148                 base = &floppy_types[(code-1)*2];
1149                 printk("fd%d is %s",drive,base->name);
1150                 return base;
1151         }
1152         printk("fd%d is unknown type %d",drive,code);
1153         return NULL;
1154 }
1155 
1156 static void config_types(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1157 {
1158         printk("Floppy drive(s): ");
1159         base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
1160         if (((CMOS_READ(0x14) >> 6) & 1) == 0)
1161                 base_type[1] = NULL;
1162         else {
1163                 printk(", ");
1164                 base_type[1] = find_base(1,CMOS_READ(0x10) & 15);
1165         }
1166         base_type[2] = base_type[3] = NULL;
1167         printk("\n");
1168 }
1169 
1170 /*
1171  * floppy_open check for aliasing (/dev/fd0 can be the same as
1172  * /dev/PS0 etc), and disallows simultaneous access to the same
1173  * drive with different device numbers.
1174  */
1175 static int floppy_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1176 {
1177         int drive;
1178         int old_dev;
1179 
1180         drive = inode->i_rdev & 3;
1181         old_dev = fd_device[drive];
1182         if (fd_ref[drive])
1183                 if (old_dev != inode->i_rdev)
1184                         return -EBUSY;
1185         fd_ref[drive]++;
1186         fd_device[drive] = inode->i_rdev;
1187         buffer_drive = buffer_track = -1;
1188         if (old_dev && old_dev != inode->i_rdev)
1189                 invalidate_buffers(old_dev);
1190         if (filp && filp->f_mode)
1191                 check_disk_change(inode->i_rdev);
1192         return 0;
1193 }
1194 
1195 static void floppy_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1196 {
1197         sync_dev(inode->i_rdev);
1198         if (!fd_ref[inode->i_rdev & 3]--) {
1199                 printk("floppy_release with fd_ref == 0");
1200                 fd_ref[inode->i_rdev & 3] = 0;
1201         }
1202 }
1203 
1204 static struct file_operations floppy_fops = {
1205         NULL,                   /* lseek - default */
1206         block_read,             /* read - general block-dev read */
1207         block_write,            /* write - general block-dev write */
1208         NULL,                   /* readdir - bad */
1209         NULL,                   /* select */
1210         fd_ioctl,               /* ioctl */
1211         NULL,                   /* mmap */
1212         floppy_open,            /* open */
1213         floppy_release          /* release */
1214 };
1215 
1216 
1217 /*
1218  * The version command is not supposed to generate an interrupt, but
1219  * my FDC does, except when booting in SVGA screen mode.
1220  * When it does generate an interrupt, it doesn't return any status bytes.
1221  * It appears to have something to do with the version command...
1222  *
1223  * This should never be called, because of the reset after the version check.
1224  */
1225 static void ignore_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1226 {
1227         printk(DEVICE_NAME ": weird interrupt ignored (%d)\n", result());
1228         reset = 1;
1229         CLEAR_INTR;     /* ignore only once */
1230 }
1231 
1232 
1233 static void floppy_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
1234 {
1235         void (*handler)(void) = DEVICE_INTR;
1236 
1237         DEVICE_INTR = NULL;
1238         if (!handler)
1239                 handler = unexpected_floppy_interrupt;
1240         handler();
1241 }
1242 
1243 /*
1244  * This is the floppy IRQ description. The SA_INTERRUPT in sa_flags
1245  * means we run the IRQ-handler with interrupts disabled.
1246  */
1247 static struct sigaction floppy_sigaction = {
1248         floppy_interrupt,
1249         0,
1250         SA_INTERRUPT,
1251         NULL
1252 };
1253 
1254 void floppy_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1255 {
1256         outb(current_DOR,FD_DOR);
1257         blk_size[MAJOR_NR] = floppy_sizes;
1258         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1259         blkdev_fops[MAJOR_NR] = &floppy_fops;
1260         timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
1261         timer_active &= ~(1 << FLOPPY_TIMER);
1262         config_types();
1263         if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
1264                 printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ);
1265         if (request_dma(FLOPPY_DMA))
1266                 printk("Unable to grab DMA%d for the floppy driver\n", FLOPPY_DMA);
1267         /* Try to determine the floppy controller type */
1268         DEVICE_INTR = ignore_interrupt; /* don't ask ... */
1269         output_byte(FD_VERSION);        /* get FDC version code */
1270         if (result() != 1) {
1271                 printk(DEVICE_NAME ": FDC failed to return version byte\n");
1272                 fdc_version = FDC_TYPE_STD;
1273         } else
1274                 fdc_version = reply_buffer[0];
1275         if (fdc_version != FDC_TYPE_STD) 
1276                 printk(DEVICE_NAME ": FDC version 0x%x\n", fdc_version);
1277 #ifndef FDC_FIFO_UNTESTED
1278         fdc_version = FDC_TYPE_STD;     /* force std fdc type; can't test other. */
1279 #endif
1280 
1281         /* Not all FDCs seem to be able to handle the version command
1282          * properly, so force a reset for the standard FDC clones,
1283          * to avoid interrupt garbage.
1284          */
1285 
1286         if (fdc_version == FDC_TYPE_STD) {
1287                 initial_reset_flag = 1;
1288                 reset_floppy();
1289         }
1290 }

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