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

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