root/drivers/block/floppy.c

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

DEFINITIONS

This source file includes following definitions.
  1. select_callback
  2. floppy_select
  3. motor_on_callback
  4. motor_off_callback
  5. floppy_on
  6. floppy_off
  7. request_done
  8. floppy_change
  9. setup_DMA
  10. output_byte
  11. output_byte_force
  12. result
  13. bad_flp_intr
  14. perpendicular_mode
  15. configure_fdc_mode
  16. tell_sector
  17. rw_interrupt
  18. setup_rw_floppy
  19. seek_interrupt
  20. transfer
  21. recal_interrupt
  22. unexpected_floppy_interrupt
  23. recalibrate_floppy
  24. reset_interrupt
  25. reset_floppy
  26. floppy_shutdown
  27. shake_done
  28. retry_recal
  29. shake_zero
  30. shake_one
  31. floppy_ready
  32. setup_format_params
  33. redo_fd_request
  34. do_fd_request
  35. fd_ioctl
  36. find_base
  37. config_types
  38. floppy_open
  39. floppy_release
  40. check_floppy_change
  41. floppy_interrupt
  42. floppy_init
  43. floppy_grab_irq_and_dma
  44. floppy_release_irq_and_dma

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

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