1: /* This file contains the device dependent part of the driver for the Floppy
   2:  * Disk Controller (FDC) using the NEC PD765 chip.
   3:  *
   4:  * The file contains two entry points:
   5:  *
   6:  *   floppy_task:       main entry when system is brought up
   7:  *   floppy_stop:       stop all activity
   8:  *
   9:  *  Changes:
  10:  *      27 Oct. 1986 by Jakob Schripsema: fdc_results fixed for 8 MHz
  11:  *      28 Nov. 1986 by Peter Kay: better resetting for 386
  12:  *      06 Jan. 1988 by Al Crew: allow 1.44 MB diskettes
  13:  *              1989 by Bruce Evans: I/O vector to keep up with 1-1 interleave
  14:  *      13 May  1991 by Don Chapman: renovated the errors loop.
  15:  *              1991 by Bruce Evans: len[] / motors / reset / step rate / ...
  16:  *      14 Feb  1992 by Andy Tanenbaum: check drive density on opens only
  17:  *      27 Mar  1992 by Kees J. Bot: last details on density checking
  18:  *      04 Apr  1992 by Kees J. Bot: device dependent/independent split
  19:  *      14 May  2000 by Kees J. Bot: d-d/i rewrite.
  20:  *      12 Aug  2003 by Mike Haertel: Null seek no interrupt fix
  21:  */
  22: 
  23: #include "kernel.h"
  24: #include "driver.h"
  25: #include "drvlib.h"
  26: #include <ibm/diskparm.h>
  27: 
  28: /* I/O Ports used by floppy disk task. */
  29: #define DOR            0x3F2    /* motor drive control bits */
  30: #define FDC_STATUS     0x3F4    /* floppy disk controller status register */
  31: #define FDC_DATA       0x3F5    /* floppy disk controller data register */
  32: #define FDC_RATE       0x3F7    /* transfer rate register */
  33: #define DMA_ADDR       0x004    /* port for low 16 bits of DMA address */
  34: #define DMA_TOP        0x081    /* port for top 4 bits of 20-bit DMA addr */
  35: #define DMA_COUNT      0x005    /* port for DMA count (count =  bytes - 1) */
  36: #define DMA_FLIPFLOP   0x00C    /* DMA byte pointer flip-flop */
  37: #define DMA_MODE       0x00B    /* DMA mode port */
  38: #define DMA_INIT       0x00A    /* DMA init port */
  39: #define DMA_RESET_VAL   0x06
  40: 
  41: /* Status registers returned as result of operation. */
  42: #define ST0             0x00    /* status register 0 */
  43: #define ST1             0x01    /* status register 1 */
  44: #define ST2             0x02    /* status register 2 */
  45: #define ST3             0x00    /* status register 3 (return by DRIVE_SENSE) */
  46: #define ST_CYL          0x03    /* slot where controller reports cylinder */
  47: #define ST_HEAD         0x04    /* slot where controller reports head */
  48: #define ST_SEC          0x05    /* slot where controller reports sector */
  49: #define ST_PCN          0x01    /* slot where controller reports present cyl */
  50: 
  51: /* Fields within the I/O ports. */
  52: /* Main status register. */
  53: #define CTL_BUSY        0x10    /* bit is set when read or write in progress */
  54: #define DIRECTION       0x40    /* bit is set when reading data reg is valid */
  55: #define MASTER          0x80    /* bit is set when data reg can be accessed */
  56: 
  57: /* Digital output port (DOR). */
  58: #define MOTOR_SHIFT        4    /* high 4 bits control the motors in DOR */
  59: #define ENABLE_INT      0x0C    /* used for setting DOR port */
  60: 
  61: /* ST0. */
  62: #define ST0_BITS        0xF8    /* check top 5 bits of seek status */
  63: #define TRANS_ST0       0x00    /* top 5 bits of ST0 for READ/WRITE */
  64: #define SEEK_ST0        0x20    /* top 5 bits of ST0 for SEEK */
  65: 
  66: /* ST1. */
  67: #define BAD_SECTOR      0x05    /* if these bits are set in ST1, recalibrate */
  68: #define WRITE_PROTECT   0x02    /* bit is set if diskette is write protected */
  69: 
  70: /* ST2. */
  71: #define BAD_CYL         0x1F    /* if any of these bits are set, recalibrate */
  72: 
  73: /* ST3 (not used). */
  74: #define ST3_FAULT       0x80    /* if this bit is set, drive is sick */
  75: #define ST3_WR_PROTECT  0x40    /* set when diskette is write protected */
  76: #define ST3_READY       0x20    /* set when drive is ready */
  77: 
  78: /* Floppy disk controller command bytes. */
  79: #define FDC_SEEK        0x0F    /* command the drive to seek */
  80: #define FDC_READ        0xE6    /* command the drive to read */
  81: #define FDC_WRITE       0xC5    /* command the drive to write */
  82: #define FDC_SENSE       0x08    /* command the controller to tell its status */
  83: #define FDC_RECALIBRATE 0x07    /* command the drive to go to cyl 0 */
  84: #define FDC_SPECIFY     0x03    /* command the drive to accept params */
  85: #define FDC_READ_ID     0x4A    /* command the drive to read sector identity */
  86: #define FDC_FORMAT      0x4D    /* command the drive to format a track */
  87: 
  88: /* DMA channel commands. */
  89: #define DMA_READ        0x46    /* DMA read opcode */
  90: #define DMA_WRITE       0x4A    /* DMA write opcode */
  91: 
  92: /* Parameters for the disk drive. */
  93: #define HC_SIZE         2880    /* # sectors on largest legal disk (1.44MB) */
  94: #define NR_HEADS        0x02    /* two heads (i.e., two tracks/cylinder) */
  95: #define MAX_SECTORS       18    /* largest # sectors per track */
  96: #define DTL             0xFF    /* determines data length (sector size) */
  97: #define SPEC2           0x02    /* second parameter to SPECIFY */
  98: #define MOTOR_OFF      (3*HZ)   /* how long to wait before stopping motor */
  99: #define WAKEUP         (2*HZ)   /* timeout on I/O, FDC won't quit. */
 100: 
 101: /* Error codes */
 102: #define ERR_SEEK         (-1)   /* bad seek */
 103: #define ERR_TRANSFER     (-2)   /* bad transfer */
 104: #define ERR_STATUS       (-3)   /* something wrong when getting status */
 105: #define ERR_READ_ID      (-4)   /* bad read id */
 106: #define ERR_RECALIBRATE  (-5)   /* recalibrate didn't work properly */
 107: #define ERR_DRIVE        (-6)   /* something wrong with a drive */
 108: #define ERR_WR_PROTECT   (-7)   /* diskette is write protected */
 109: #define ERR_TIMEOUT      (-8)   /* interrupt timeout */
 110: 
 111: /* No retries on some errors. */
 112: #define err_no_retry(err)       ((err) <= ERR_WR_PROTECT)
 113: 
 114: /* Encoding of drive type in minor device number. */
 115: #define DEV_TYPE_BITS   0x7C    /* drive type + 1, if nonzero */
 116: #define DEV_TYPE_SHIFT     2    /* right shift to normalize type bits */
 117: #define FORMAT_DEV_BIT  0x80    /* bit in minor to turn write into format */
 118: 
 119: /* Miscellaneous. */
 120: #define MAX_ERRORS         6    /* how often to try rd/wt before quitting */
 121: #define MAX_RESULTS        7    /* max number of bytes controller returns */
 122: #define NR_DRIVES          2    /* maximum number of drives */
 123: #define DIVISOR          128    /* used for sector size encoding */
 124: #define SECTOR_SIZE_CODE   2    /* code to say "512" to the controller */
 125: #define TIMEOUT       500000L   /* microseconds waiting for FDC */
 126: #define NT                 7    /* number of diskette/drive combinations */
 127: #define UNCALIBRATED       0    /* drive needs to be calibrated at next use */
 128: #define CALIBRATED         1    /* no calibration needed */
 129: #define BASE_SECTOR        1    /* sectors are numbered starting at 1 */
 130: #define NO_SECTOR        (-1)   /* current sector unknown */
 131: #define NO_CYL           (-1)   /* current cylinder unknown, must seek */
 132: #define NO_DENS          100    /* current media unknown */
 133: #define BSY_IDLE           0    /* busy doing nothing */
 134: #define BSY_IO             1    /* busy doing I/O */
 135: #define BSY_WAKEN          2    /* got a wakeup call */
 136: 
 137: /* Seven combinations of diskette/drive are supported.
 138:  *
 139:  * # Diskette Drive  Sectors  Tracks   Rotation Data-rate  Comment
 140:  * 0   360K    360K     9       40     300 RPM  250 kbps   Standard PC DSDD
 141:  * 1   1.2M    1.2M    15       80     360 RPM  500 kbps   AT disk in AT drive
 142:  * 2   360K    720K     9       40     300 RPM  250 kbps   Quad density PC
 143:  * 3   720K    720K     9       80     300 RPM  250 kbps   Toshiba, et al.
 144:  * 4   360K    1.2M     9       40     360 RPM  300 kbps   PC disk in AT drive
 145:  * 5   720K    1.2M     9       80     360 RPM  300 kbps   Toshiba in AT drive
 146:  * 6   1.44M   1.44M   18       80     300 RPM  500 kbps   PS/2, et al.
 147:  *
 148:  * In addition, 720K diskettes can be read in 1.44MB drives, but that does
 149:  * not need a different set of parameters.  This combination uses
 150:  *
 151:  * 3   720K    1.44M    9       80     300 RPM  250 kbps   PS/2, et al.
 152:  */
 153: PRIVATE struct density {
 154:         u8_t    secpt;          /* sectors per track */
 155:         u8_t    cyls;           /* tracks per side */
 156:         u8_t    steps;          /* steps per cylinder (2 = double step) */
 157:         u8_t    test;           /* sector to try for density test */
 158:         u8_t    rate;           /* data rate (2=250, 1=300, 0=500 kbps) */
 159:         u8_t    start;          /* motor start (clock ticks) */
 160:         u8_t    gap;            /* gap size */
 161:         u8_t    spec1;          /* first specify byte (SRT/HUT) */
 162: } fdensity[NT] = {
 163:         {  9, 40, 1, 4*9, 2, 4*HZ/8, 0x2A, 0xDF },      /*  360K / 360K  */
 164:         { 15, 80, 1,  14, 0, 4*HZ/8, 0x1B, 0xDF },      /*  1.2M / 1.2M  */
 165:         {  9, 40, 2, 2*9, 2, 4*HZ/8, 0x2A, 0xDF },      /*  360K / 720K  */
 166:         {  9, 80, 1, 4*9, 2, 6*HZ/8, 0x2A, 0xDF },      /*  720K / 720K  */
 167:         {  9, 40, 2, 2*9, 1, 4*HZ/8, 0x23, 0xDF },      /*  360K / 1.2M  */
 168:         {  9, 80, 1, 4*9, 1, 4*HZ/8, 0x23, 0xDF },      /*  720K / 1.2M  */
 169:         { 18, 80, 1,  17, 0, 6*HZ/8, 0x1B, 0xCF },      /* 1.44M / 1.44M */
 170: };
 171: 
 172: /* The following table is used with the test_sector array to recognize a
 173:  * drive/floppy combination.  The sector to test has been determined by
 174:  * looking at the differences in gap size, sectors/track, and double stepping.
 175:  * This means that types 0 and 3 can't be told apart, only the motor start
 176:  * time differs.  If a read test succeeds then the drive is limited to the
 177:  * set of densities it can support to avoid unnecessary tests in the future.
 178:  */
 179: 
 180: #define b(d)    (1 << (d))        /* bit for density d. */
 181: 
 182: PRIVATE struct test_order {
 183:         u8_t    t_density;      /* floppy/drive type */
 184:         u8_t    t_class;        /* limit drive to this class of densities */
 185: } test_order[NT-1] = {
 186:         { 6,  b(3) | b(6) },            /* 1.44M  {720K, 1.44M} */
 187:         { 1,  b(1) | b(4) | b(5) },     /* 1.2M   {1.2M, 360K, 720K} */
 188:         { 3,  b(2) | b(3) | b(6) },     /* 720K   {360K, 720K, 1.44M} */
 189:         { 4,  b(1) | b(4) | b(5) },     /* 360K   {1.2M, 360K, 720K} */
 190:         { 5,  b(1) | b(4) | b(5) },     /* 720K   {1.2M, 360K, 720K} */
 191:         { 2,  b(2) | b(3) },            /* 360K   {360K, 720K} */
 192:         /* Note that type 0 is missing, type 3 can read/write it too, which is
 193:          * why the type 3 parameters have been pessimized to be like type 0.
 194:          */
 195: };
 196: 
 197: /* Variables. */
 198: PRIVATE struct floppy {         /* main drive struct, one entry per drive */
 199:   unsigned fl_curcyl;           /* current cylinder */
 200:   unsigned fl_hardcyl;          /* hardware cylinder, as opposed to: */
 201:   unsigned fl_cylinder;         /* cylinder number addressed */
 202:   unsigned fl_sector;           /* sector addressed */
 203:   unsigned fl_head;             /* head number addressed */
 204:   char fl_calibration;          /* CALIBRATED or UNCALIBRATED */
 205:   u8_t fl_density;              /* NO_DENS = ?, 0 = 360K; 1 = 360K/1.2M; etc.*/
 206:   u8_t fl_class;                /* bitmap for possible densities */
 207:   timer_t fl_tmr_stop;          /* timer to stop motor */
 208:   struct device fl_geom;        /* Geometry of the drive */
 209:   struct device fl_part[NR_PARTITIONS];  /* partition's base & size */
 210: } floppy[NR_DRIVES];
 211: 
 212: PRIVATE int motor_status;       /* bitmap of current motor status */
 213: PRIVATE int need_reset;         /* set to 1 when controller must be reset */
 214: PRIVATE unsigned f_drive;       /* selected drive */
 215: PRIVATE unsigned f_device;      /* selected minor device */
 216: PRIVATE struct floppy *f_fp;    /* current drive */
 217: PRIVATE struct density *f_dp;   /* current density parameters */
 218: PRIVATE struct density *prev_dp;/* previous density parameters */
 219: PRIVATE unsigned f_sectors;     /* equal to f_dp->secpt (needed a lot) */
 220: PRIVATE int f_busy;             /* BSY_IDLE, BSY_IO, BSY_WAKEN */
 221: PRIVATE irq_hook_t f_hook;      /* interrupt hook */
 222: PRIVATE timer_t f_tmr_timeout;  /* timer for various timeouts */
 223: PRIVATE struct device *f_dv;    /* device's base and size */
 224: PRIVATE struct disk_parameter_s fmt_param; /* parameters for format */
 225: PRIVATE u8_t f_results[MAX_RESULTS];/* the controller can give lots of output */
 226: 
 227: 
 228: FORWARD _PROTOTYPE( struct device *f_prepare, (int device) );
 229: FORWARD _PROTOTYPE( char *f_name, (void) );
 230: FORWARD _PROTOTYPE( void f_cleanup, (void) );
 231: FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, off_t position,
 232:                                         iovec_t *iov, unsigned nr_req) );
 233: FORWARD _PROTOTYPE( void dma_setup, (int opcode) );
 234: FORWARD _PROTOTYPE( void start_motor, (void) );
 235: FORWARD _PROTOTYPE( void stop_motor, (timer_t *tp) );
 236: FORWARD _PROTOTYPE( int seek, (void) );
 237: FORWARD _PROTOTYPE( int fdc_transfer, (int opcode) );
 238: FORWARD _PROTOTYPE( int fdc_results, (void) );
 239: FORWARD _PROTOTYPE( int f_handler, (irq_hook_t *hook) );
 240: FORWARD _PROTOTYPE( int fdc_command, (u8_t *cmd, int len) );
 241: FORWARD _PROTOTYPE( void fdc_out, (int val) );
 242: FORWARD _PROTOTYPE( int recalibrate, (void) );
 243: FORWARD _PROTOTYPE( void f_reset, (void) );
 244: FORWARD _PROTOTYPE( int f_intr_wait, (void) );
 245: FORWARD _PROTOTYPE( void f_timeout, (timer_t *tp) );
 246: FORWARD _PROTOTYPE( int read_id, (void) );
 247: FORWARD _PROTOTYPE( int f_do_open, (struct driver *dp, message *m_ptr) );
 248: FORWARD _PROTOTYPE( int test_read, (int density) );
 249: FORWARD _PROTOTYPE( void f_geometry, (struct partition *entry));
 250: 
 251: 
 252: /* Entry points to this driver. */
 253: PRIVATE struct driver f_dtab = {
 254:   f_name,       /* current device's name */
 255:   f_do_open,    /* open or mount request, sense type of diskette */
 256:   do_nop,       /* nothing on a close */
 257:   do_diocntl,   /* get or set a partitions geometry */
 258:   f_prepare,    /* prepare for I/O on a given minor device */
 259:   f_transfer,   /* do the I/O */
 260:   f_cleanup,    /* cleanup before sending reply to user process */
 261:   f_geometry    /* tell the geometry of the diskette */
 262: };
 263: 
 264: 
 265: /*===========================================================================*
 266:  *                              floppy_task                                  *
 267:  *===========================================================================*/
 268: PUBLIC void floppy_task()
 269: {
 270: /* Initialize the floppy structure. */
 271: 
 272:   struct floppy *fp;
 273: 
 274:   for (fp = &floppy[0]; fp < &floppy[NR_DRIVES]; fp++) {
 275:         fp->fl_curcyl = NO_CYL;
 276:         fp->fl_density = NO_DENS;
 277:         fp->fl_class = ~0;
 278:   }
 279: 
 280:   put_irq_handler(&f_hook, FLOPPY_IRQ, f_handler);
 281:   enable_irq(&f_hook);           /* ready for floppy interrupts */
 282: 
 283:   driver_task(&f_dtab);
 284: }
 285: 
 286: 
 287: /*===========================================================================*
 288:  *                              f_prepare                                    *
 289:  *===========================================================================*/
 290: PRIVATE struct device *f_prepare(device)
 291: int device;
 292: {
 293: /* Prepare for I/O on a device. */
 294: 
 295:   f_device = device;
 296:   f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
 297:   if (f_drive < 0 || f_drive >= NR_DRIVES) return(NIL_DEV);
 298: 
 299:   f_fp = &floppy[f_drive];
 300:   f_dv = &f_fp->fl_geom;
 301:   if (f_fp->fl_density < NT) {
 302:         f_dp = &fdensity[f_fp->fl_density];
 303:         f_sectors = f_dp->secpt;
 304:         f_fp->fl_geom.dv_size = mul64u((long) (NR_HEADS * f_sectors
 305:                                         * f_dp->cyls), SECTOR_SIZE);
 306:   }
 307: 
 308:   /* A partition? */
 309:   if ((device &= DEV_TYPE_BITS) >= MINOR_fd0p0)
 310:         f_dv = &f_fp->fl_part[(device - MINOR_fd0p0) >> DEV_TYPE_SHIFT];
 311: 
 312:   return f_dv;
 313: }
 314: 
 315: 
 316: /*===========================================================================*
 317:  *                              f_name                                       *
 318:  *===========================================================================*/
 319: PRIVATE char *f_name()
 320: {
 321: /* Return a name for the current device. */
 322:   static char name[] = "fd0";
 323: 
 324:   name[2] = '0' + f_drive;
 325:   return name;
 326: }
 327: 
 328: 
 329: /*===========================================================================*
 330:  *                              f_cleanup                                    *
 331:  *===========================================================================*/
 332: PRIVATE void f_cleanup()
 333: {
 334:   /* Start a timer to turn the motor off in a few seconds. */
 335:   tmr_arg(&f_fp->fl_tmr_stop)->ta_int = f_drive;
 336:   tmr_settimer(&f_fp->fl_tmr_stop, FLOPPY, get_uptime()+MOTOR_OFF, stop_motor);
 337: 
 338:   /* Exiting the floppy driver, so forget where we are. */
 339:   f_fp->fl_sector = NO_SECTOR;
 340: }
 341: 
 342: 
 343: /*===========================================================================*
 344:  *                              f_transfer                                   *
 345:  *===========================================================================*/
 346: PRIVATE int f_transfer(proc_nr, opcode, position, iov, nr_req)
 347: int proc_nr;                    /* process doing the request */
 348: int opcode;                     /* DEV_GATHER or DEV_SCATTER */
 349: off_t position;                 /* offset on device to read or write */
 350: iovec_t *iov;                   /* pointer to read or write request vector */
 351: unsigned nr_req;                /* length of request vector */
 352: {
 353:   struct floppy *fp = f_fp;
 354:   iovec_t *iop, *iov_end = iov + nr_req;
 355:   int r, errors;
 356:   unsigned block;       /* Seen any 32M floppies lately? */
 357:   unsigned nbytes, count, chunk, sector;
 358:   unsigned long dv_size = cv64ul(f_dv->dv_size);
 359:   vir_bytes user_addr;
 360:   vir_bytes uaddrs[MAX_SECTORS], *up;
 361:   u8_t cmd[3];
 362:   phys_bytes user_base = proc_vir2phys(proc_addr(proc_nr), 0);
 363: 
 364:   /* Check disk address. */
 365:   if ((position & SECTOR_MASK) != 0) return(EINVAL);
 366: 
 367:   errors = 0;
 368:   while (nr_req > 0) {
 369:         /* How many bytes to transfer? */
 370:         nbytes = 0;
 371:         for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
 372: 
 373:         /* Which block on disk and how close to EOF? */
 374:         if (position >= dv_size) return(OK);             /* At EOF */
 375:         if (position + nbytes > dv_size) nbytes = dv_size - position;
 376:         block = div64u(add64ul(f_dv->dv_base, position), SECTOR_SIZE);
 377: 
 378:         if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
 379: 
 380:         /* Using a formatting device? */
 381:         if (f_device & FORMAT_DEV_BIT) {
 382:                 if (opcode != DEV_SCATTER) return(EIO);
 383:                 if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param))
 384:                         return(EINVAL);
 385: 
 386:                 phys_copy(user_base + iov->iov_addr + SECTOR_SIZE,
 387:                         vir2phys(&fmt_param), (phys_bytes) sizeof(fmt_param));
 388: 
 389:                 /* Check that the number of sectors in the data is reasonable,
 390:                  * to avoid division by 0.  Leave checking of other data to
 391:                  * the FDC.
 392:                  */
 393:                 if (fmt_param.sectors_per_cylinder == 0) return(EIO);
 394: 
 395:                 /* Only the first sector of the parameters now needed. */
 396:                 iov->iov_size = nbytes = SECTOR_SIZE;
 397:         }
 398: 
 399:         /* Only try one sector if there were errors. */
 400:         if (errors > 0) nbytes = SECTOR_SIZE;
 401: 
 402:         /* Compute cylinder and head of the track to access. */
 403:         fp->fl_cylinder = block / (NR_HEADS * f_sectors);
 404:         fp->fl_hardcyl = fp->fl_cylinder * f_dp->steps;
 405:         fp->fl_head = (block % (NR_HEADS * f_sectors)) / f_sectors;
 406: 
 407:         /* For each sector on this track compute the user address it is to
 408:          * go or to come from.
 409:          */
 410:         for (up = uaddrs; up < uaddrs + MAX_SECTORS; up++) *up = 0;
 411:         count = 0;
 412:         iop = iov;
 413:         sector = block % f_sectors;
 414:         for (;;) {
 415:                 user_addr = iop->iov_addr;
 416:                 chunk = iop->iov_size;
 417:                 if ((chunk & SECTOR_MASK) != 0) return(EINVAL);
 418: 
 419:                 while (chunk > 0) {
 420:                         uaddrs[sector++] = user_addr;
 421:                         chunk -= SECTOR_SIZE;
 422:                         user_addr += SECTOR_SIZE;
 423:                         count += SECTOR_SIZE;
 424:                         if (sector == f_sectors || count == nbytes)
 425:                                 goto track_set_up;
 426:                 }
 427:                 iop++;
 428:         }
 429:   track_set_up:
 430: 
 431:         /* First check to see if a reset is needed. */
 432:         if (need_reset) f_reset();
 433: 
 434:         /* See if motor is running; if not, turn it on and wait. */
 435:         start_motor();
 436: 
 437:         /* Set the stepping rate and data rate */
 438:         if (f_dp != prev_dp) {
 439:                 cmd[0] = FDC_SPECIFY;
 440:                 cmd[1] = f_dp->spec1;
 441:                 cmd[2] = SPEC2;
 442:                 (void) fdc_command(cmd, 3);
 443:                 outb(FDC_RATE, f_dp->rate);
 444:                 prev_dp = f_dp;
 445:         }
 446: 
 447:         /* If we are going to a new cylinder, perform a seek. */
 448:         r = seek();
 449: 
 450:         /* Avoid read_id() if we don't plan to read much. */
 451:         if (fp->fl_sector == NO_SECTOR && count < (6 * SECTOR_SIZE))
 452:                 fp->fl_sector = 0;
 453: 
 454:         for (nbytes = 0; nbytes < count; nbytes += SECTOR_SIZE) {
 455:                 if (fp->fl_sector == NO_SECTOR) {
 456:                         /* Find out what the current sector is.  This often
 457:                          * fails right after a seek, so try it twice.
 458:                          */
 459:                         if (r == OK && read_id() != OK) r = read_id();
 460:                 }
 461: 
 462:                 /* Look for the next job in uaddrs[] */
 463:                 if (r == OK) {
 464:                         for (;;) {
 465:                                 if (fp->fl_sector >= f_sectors)
 466:                                         fp->fl_sector = 0;
 467: 
 468:                                 up = &uaddrs[fp->fl_sector];
 469:                                 if (*up != 0) break;
 470:                                 fp->fl_sector++;
 471:                         }
 472:                 }
 473: 
 474:                 if (r == OK && opcode == DEV_SCATTER) {
 475:                         /* Copy the user bytes to the DMA buffer. */
 476:                         phys_copy(user_base + *up, tmp_phys,
 477:                                                 (phys_bytes) SECTOR_SIZE);
 478:                 }
 479: 
 480:                 /* Set up the DMA chip and perform the transfer. */
 481:                 if (r == OK) {
 482:                         dma_setup(opcode);
 483:                         r = fdc_transfer(opcode);
 484:                 }
 485: 
 486:                 if (r == OK && opcode == DEV_GATHER) {
 487:                         /* Copy the DMA buffer to user space. */
 488:                         phys_copy(tmp_phys, user_base + *up,
 489:                                                 (phys_bytes) SECTOR_SIZE);
 490:                 }
 491: 
 492:                 if (r != OK) {
 493:                         /* Don't retry if write protected or too many errors. */
 494:                         if (err_no_retry(r) || ++errors == MAX_ERRORS)
 495:                                 return(EIO);
 496: 
 497:                         /* Recalibrate if halfway. */
 498:                         if (errors == MAX_ERRORS / 2)
 499:                                 fp->fl_calibration = UNCALIBRATED;
 500: 
 501:                         nbytes = 0;
 502:                         break;          /* retry */
 503:                 }
 504:         }
 505: 
 506:         /* Book the bytes successfully transferred. */
 507:         position += nbytes;
 508:         for (;;) {
 509:                 if (nbytes < iov->iov_size) {
 510:                         /* Not done with this one yet. */
 511:                         iov->iov_addr += nbytes;
 512:                         iov->iov_size -= nbytes;
 513:                         break;
 514:                 }
 515:                 nbytes -= iov->iov_size;
 516:                 iov->iov_addr += iov->iov_size;
 517:                 iov->iov_size = 0;
 518:                 if (nbytes == 0) {
 519:                         /* The rest is optional, so we return to give FS a
 520:                          * chance to think it over.
 521:                          */
 522:                         return(OK);
 523:                 }
 524:                 iov++;
 525:                 nr_req--;
 526:         }
 527:   }
 528:   return(OK);
 529: }
 530: 
 531: 
 532: /*===========================================================================*
 533:  *                              dma_setup                                    *
 534:  *===========================================================================*/
 535: PRIVATE void dma_setup(opcode)
 536: int opcode;                     /* DEV_GATHER or DEV_SCATTER */
 537: {
 538: /* The IBM PC can perform DMA operations by using the DMA chip.  To use it,
 539:  * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
 540:  * to be read from or written to, the byte count minus 1, and a read or write
 541:  * opcode.  This routine sets up the DMA chip.  Note that the chip is not
 542:  * capable of doing a DMA across a 64K boundary (e.g., you can't read a
 543:  * 512-byte block starting at physical address 65520).
 544:  */
 545: 
 546:   /* Set up the DMA registers.  (The comment on the reset is a bit strong,
 547:    * it probably only resets the floppy channel.)
 548:    */
 549:   outb(DMA_INIT, DMA_RESET_VAL);        /* reset the dma controller */
 550:   outb(DMA_FLIPFLOP, 0);                /* write anything to reset it */
 551:   outb(DMA_MODE, opcode == DEV_SCATTER ? DMA_WRITE : DMA_READ);
 552:   outb(DMA_ADDR, (unsigned) tmp_phys >>  0);
 553:   outb(DMA_ADDR, (unsigned) tmp_phys >>  8);
 554:   outb(DMA_TOP, (unsigned) (tmp_phys >> 16));
 555:   outb(DMA_COUNT, (SECTOR_SIZE - 1) >> 0);
 556:   outb(DMA_COUNT, (SECTOR_SIZE - 1) >> 8);
 557:   outb(DMA_INIT, 2);                    /* some sort of enable */
 558: }
 559: 
 560: 
 561: /*===========================================================================*
 562:  *                              start_motor                                  *
 563:  *===========================================================================*/
 564: PRIVATE void start_motor()
 565: {
 566: /* Control of the floppy disk motors is a big pain.  If a motor is off, you
 567:  * have to turn it on first, which takes 1/2 second.  You can't leave it on
 568:  * all the time, since that would wear out the diskette.  However, if you turn
 569:  * the motor off after each operation, the system performance will be awful.
 570:  * The compromise used here is to leave it on for a few seconds after each
 571:  * operation.  If a new operation is started in that interval, it need not be
 572:  * turned on again.  If no new operation is started, a timer goes off and the
 573:  * motor is turned off.  I/O port DOR has bits to control each of 4 drives.
 574:  */
 575: 
 576:   int motor_bit, running;
 577:   message mess;
 578: 
 579:   motor_bit = 1 << f_drive;               /* bit mask for this drive */
 580:   running = motor_status & motor_bit;    /* nonzero if this motor is running */
 581:   motor_status |= motor_bit;            /* want this drive running too */
 582: 
 583:   outb(DOR, (motor_status << MOTOR_SHIFT) | ENABLE_INT | f_drive);
 584: 
 585:   /* If the motor was already running, we don't have to wait for it. */
 586:   if (running) return;                  /* motor was already running */
 587: 
 588:   tmr_settimer(&f_tmr_timeout, CLOCK, get_uptime() + f_dp->start, f_timeout);
 589:   f_busy = BSY_IO;
 590:   do receive(HARDWARE, &mess); while (f_busy == BSY_IO);
 591:   f_fp->fl_sector = NO_SECTOR;
 592: }
 593: 
 594: 
 595: /*===========================================================================*
 596:  *                              stop_motor                                   *
 597:  *===========================================================================*/
 598: PRIVATE void stop_motor(tp)
 599: timer_t *tp;
 600: {
 601: /* This routine is called by the clock interrupt after several seconds have
 602:  * elapsed with no floppy disk activity.  It turns the drive motor off.
 603:  */
 604: 
 605:   motor_status &= ~(1 << tmr_arg(tp)->ta_int);
 606:   outb(DOR, (motor_status << MOTOR_SHIFT) | ENABLE_INT);
 607: }
 608: 
 609: 
 610: /*===========================================================================*
 611:  *                              floppy_stop                                  *
 612:  *===========================================================================*/
 613: PUBLIC void floppy_stop()
 614: {
 615: /* Stop all activity. */
 616: 
 617:   outb(DOR, ENABLE_INT);
 618: }
 619: 
 620: 
 621: /*===========================================================================*
 622:  *                              seek                                         *
 623:  *===========================================================================*/
 624: PRIVATE int seek()
 625: {
 626: /* Issue a SEEK command on the indicated drive unless the arm is already
 627:  * positioned on the correct cylinder.
 628:  */
 629: 
 630:   struct floppy *fp = f_fp;
 631:   int r;
 632:   message mess;
 633:   u8_t cmd[3];
 634: 
 635:   /* Are we already on the correct cylinder? */
 636:   if (fp->fl_calibration == UNCALIBRATED)
 637:         if (recalibrate() != OK) return(ERR_SEEK);
 638:   if (fp->fl_curcyl == fp->fl_hardcyl) return(OK);
 639: 
 640:   /* No.  Wrong cylinder.  Issue a SEEK and wait for interrupt. */
 641:   cmd[0] = FDC_SEEK;
 642:   cmd[1] = (fp->fl_head << 2) | f_drive;
 643:   cmd[2] = fp->fl_hardcyl;
 644:   if (fdc_command(cmd, 3) != OK) return(ERR_SEEK);
 645:   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
 646: 
 647:   /* Interrupt has been received.  Check drive status. */
 648:   fdc_out(FDC_SENSE);           /* probe FDC to make it return status */
 649:   r = fdc_results();            /* get controller status bytes */
 650:   if (r != OK || (f_results[ST0] & ST0_BITS) != SEEK_ST0
 651:                                 || f_results[ST1] != fp->fl_hardcyl) {
 652:         /* seek failed, may need a recalibrate */
 653:         return(ERR_SEEK);
 654:   }
 655:   /* Give head time to settle on a format, no retrying here! */
 656:   if (f_device & FORMAT_DEV_BIT) {
 657:         tmr_settimer(&f_tmr_timeout, CLOCK, get_uptime() + HZ/30, f_timeout);
 658:         f_busy = BSY_IO;
 659:         do receive(HARDWARE, &mess); while (f_busy == BSY_IO);
 660:   }
 661:   fp->fl_curcyl = fp->fl_hardcyl;
 662:   fp->fl_sector = NO_SECTOR;
 663:   return(OK);
 664: }
 665: 
 666: 
 667: /*===========================================================================*
 668:  *                              fdc_transfer                                 *
 669:  *===========================================================================*/
 670: PRIVATE int fdc_transfer(opcode)
 671: int opcode;                     /* DEV_GATHER or DEV_SCATTER */
 672: {
 673: /* The drive is now on the proper cylinder.  Read, write or format 1 block. */
 674: 
 675:   struct floppy *fp = f_fp;
 676:   int r, s;
 677:   u8_t cmd[9];
 678: 
 679:   /* Never attempt a transfer if the drive is uncalibrated or motor is off. */
 680:   if (fp->fl_calibration == UNCALIBRATED) return(ERR_TRANSFER);
 681:   if ((motor_status & (1 << f_drive)) == 0) return(ERR_TRANSFER);
 682: 
 683:   /* The command is issued by outputting several bytes to the controller chip.
 684:    */
 685:   if (f_device & FORMAT_DEV_BIT) {
 686:         cmd[0] = FDC_FORMAT;
 687:         cmd[1] = (fp->fl_head << 2) | f_drive;
 688:         cmd[2] = fmt_param.sector_size_code;
 689:         cmd[3] = fmt_param.sectors_per_cylinder;
 690:         cmd[4] = fmt_param.gap_length_for_format;
 691:         cmd[5] = fmt_param.fill_byte_for_format;
 692:         if (fdc_command(cmd, 6) != OK) return(ERR_TRANSFER);
 693:   } else {
 694:         cmd[0] = opcode == DEV_SCATTER ? FDC_WRITE : FDC_READ;
 695:         cmd[1] = (fp->fl_head << 2) | f_drive;
 696:         cmd[2] = fp->fl_cylinder;
 697:         cmd[3] = fp->fl_head;
 698:         cmd[4] = BASE_SECTOR + fp->fl_sector;
 699:         cmd[5] = SECTOR_SIZE_CODE;
 700:         cmd[6] = f_sectors;
 701:         cmd[7] = f_dp->gap;      /* sector gap */
 702:         cmd[8] = DTL;           /* data length */
 703:         if (fdc_command(cmd, 9) != OK) return(ERR_TRANSFER);
 704:   }
 705: 
 706:   /* Block, waiting for disk interrupt. */
 707:   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
 708: 
 709:   /* Get controller status and check for errors. */
 710:   r = fdc_results();
 711:   if (r != OK) return(r);
 712: 
 713:   if (f_results[ST1] & WRITE_PROTECT) {
 714:         printf("%s: diskette is write protected.\n", f_name());
 715:         return(ERR_WR_PROTECT);
 716:   }
 717: 
 718:   if ((f_results[ST0] & ST0_BITS) != TRANS_ST0) return(ERR_TRANSFER);
 719:   if (f_results[ST1] | f_results[ST2]) return(ERR_TRANSFER);
 720: 
 721:   if (f_device & FORMAT_DEV_BIT) return(OK);
 722: 
 723:   /* Compare actual numbers of sectors transferred with expected number. */
 724:   s =  (f_results[ST_CYL] - fp->fl_cylinder) * NR_HEADS * f_sectors;
 725:   s += (f_results[ST_HEAD] - fp->fl_head) * f_sectors;
 726:   s += (f_results[ST_SEC] - BASE_SECTOR - fp->fl_sector);
 727:   if (s != 1) return(ERR_TRANSFER);
 728: 
 729:   /* This sector is next for I/O: */
 730:   fp->fl_sector = f_results[ST_SEC] - BASE_SECTOR;
 731: #if 0
 732:   if (processor < 386) fp->fl_sector++;           /* Old CPU can't keep up. */
 733: #endif
 734:   return(OK);
 735: }
 736: 
 737: 
 738: /*==========================================================================*
 739:  *                              fdc_results                                 *
 740:  *==========================================================================*/
 741: PRIVATE int fdc_results()
 742: {
 743: /* Extract results from the controller after an operation, then allow floppy
 744:  * interrupts again.
 745:  */
 746: 
 747:   int result_nr, status;
 748:   struct micro_state ms;
 749: 
 750:   /* Extract bytes from FDC until it says it has no more.  The loop is
 751:    * really an outer loop on result_nr and an inner loop on status.
 752:    */
 753:   result_nr = 0;
 754:   micro_start(&ms);
 755:   do {
 756:         /* Reading one byte is almost a mirror of fdc_out() - the DIRECTION
 757:          * bit must be set instead of clear, but the CTL_BUSY bit destroys
 758:          * the perfection of the mirror.
 759:          */
 760:         status = inb(FDC_STATUS) & (MASTER | DIRECTION | CTL_BUSY);
 761:         if (status == (MASTER | DIRECTION | CTL_BUSY)) {
 762:                 if (result_nr >= MAX_RESULTS) break;     /* too many results */
 763:                 f_results[result_nr++] = inb(FDC_DATA);
 764:                 continue;
 765:         }
 766:         if (status == MASTER) { /* all read */
 767:                 enable_irq(&f_hook);
 768:                 return(OK);     /* only good exit */
 769:         }
 770:   } while (micro_elapsed(&ms) < TIMEOUT);
 771:   need_reset = TRUE;            /* controller chip must be reset */
 772:   enable_irq(&f_hook);
 773:   return(ERR_STATUS);
 774: }
 775: 
 776: 
 777: /*==========================================================================*
 778:  *                              f_handler                                   *
 779:  *==========================================================================*/
 780: PRIVATE int f_handler(hook)
 781: irq_hook_t *hook;
 782: {
 783: /* FDC interrupt, send message to floppy task. */
 784: 
 785:   f_busy = BSY_IDLE;
 786:   interrupt(FLOPPY);
 787:   return 0;
 788: }
 789: 
 790: 
 791: /*===========================================================================*
 792:  *                              fdc_command                                  *
 793:  *===========================================================================*/
 794: PRIVATE int fdc_command(cmd, len)
 795: u8_t *cmd;              /* command bytes */
 796: int len;                /* command length */
 797: {
 798: /* Output a command to the controller. */
 799: 
 800:   /* Schedule a wakeup call. */
 801:   tmr_settimer(&f_tmr_timeout, CLOCK, get_uptime() + WAKEUP, f_timeout);
 802: 
 803:   f_busy = BSY_IO;
 804:   while (len > 0) {
 805:         fdc_out(*cmd++);
 806:         len--;
 807:   }
 808:   return(need_reset ? ERR_DRIVE : OK);
 809: }
 810: 
 811: 
 812: /*===========================================================================*
 813:  *                              fdc_out                                      *
 814:  *===========================================================================*/
 815: PRIVATE void fdc_out(val)
 816: int val;                /* write this byte to floppy disk controller */
 817: {
 818: /* Output a byte to the controller.  This is not entirely trivial, since you
 819:  * can only write to it when it is listening, and it decides when to listen.
 820:  * If the controller refuses to listen, the FDC chip is given a hard reset.
 821:  */
 822: 
 823:   struct micro_state ms;
 824: 
 825:   if (need_reset) return;       /* if controller is not listening, return */
 826: 
 827:   /* It may take several tries to get the FDC to accept a command. */
 828:   micro_start(&ms);
 829:   while ((inb(FDC_STATUS) & (MASTER | DIRECTION)) != (MASTER | 0)) {
 830:         if (micro_elapsed(&ms) >= TIMEOUT) {
 831:                 /* Controller is not listening.  Hit it over the head. */
 832:                 need_reset = TRUE;
 833:                 return;
 834:         }
 835:   }
 836:   outb(FDC_DATA, val);
 837: }
 838: 
 839: 
 840: /*===========================================================================*
 841:  *                              recalibrate                                  *
 842:  *===========================================================================*/
 843: PRIVATE int recalibrate()
 844: {
 845: /* The floppy disk controller has no way of determining its absolute arm
 846:  * position (cylinder).  Instead, it steps the arm a cylinder at a time and
 847:  * keeps track of where it thinks it is (in software).  However, after a
 848:  * SEEK, the hardware reads information from the diskette telling where the
 849:  * arm actually is.  If the arm is in the wrong place, a recalibration is done,
 850:  * which forces the arm to cylinder 0.  This way the controller can get back
 851:  * into sync with reality.
 852:  */
 853: 
 854:   struct floppy *fp = f_fp;
 855:   int r;
 856:   u8_t cmd[2];
 857: 
 858:   /* Issue the RECALIBRATE command and wait for the interrupt. */
 859:   cmd[0] = FDC_RECALIBRATE;     /* tell drive to recalibrate itself */
 860:   cmd[1] = f_drive;             /* specify drive */
 861:   if (fdc_command(cmd, 2) != OK) return(ERR_SEEK);
 862:   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
 863: 
 864:   /* Determine if the recalibration succeeded. */
 865:   fdc_out(FDC_SENSE);           /* issue SENSE command to request results */
 866:   r = fdc_results();            /* get results of the FDC_RECALIBRATE command*/
 867:   fp->fl_curcyl = NO_CYL;        /* force a SEEK next time */
 868:   fp->fl_sector = NO_SECTOR;
 869:   if (r != OK ||                /* controller would not respond */
 870:      (f_results[ST0] & ST0_BITS) != SEEK_ST0 || f_results[ST_PCN] != 0) {
 871:         /* Recalibration failed.  FDC must be reset. */
 872:         need_reset = TRUE;
 873:         return(ERR_RECALIBRATE);
 874:   } else {
 875:         /* Recalibration succeeded. */
 876:         fp->fl_calibration = CALIBRATED;
 877:         fp->fl_curcyl = f_results[ST_PCN];
 878:         return(OK);
 879:   }
 880: }
 881: 
 882: 
 883: /*===========================================================================*
 884:  *                              f_reset                                      *
 885:  *===========================================================================*/
 886: PRIVATE void f_reset()
 887: {
 888: /* Issue a reset to the controller.  This is done after any catastrophe,
 889:  * like the controller refusing to respond.
 890:  */
 891: 
 892:   int i;
 893:   message mess;
 894: 
 895:   /* Disable interrupts and strobe reset bit low. */
 896:   need_reset = FALSE;
 897: 
 898:   /* It is not clear why the next lock is needed.  Writing 0 to DOR causes
 899:    * interrupt, while the PC documentation says turning bit 8 off disables
 900:    * interrupts.  Without the lock:
 901:    *   1) the interrupt handler sets the floppy mask bit in the 8259.
 902:    *   2) writing ENABLE_INT to DOR causes the FDC to assert the interrupt
 903:    *      line again, but the mask stops the cpu being interrupted.
 904:    *   3) the sense interrupt clears the interrupt (not clear which one).
 905:    * and for some reason the reset does not work.
 906:    */
 907:   (void) fdc_command((u8_t *) 0, 0);   /* need only the timer */
 908:   lock();
 909:   motor_status = 0;
 910:   outb(DOR, 0);                 /* strobe reset bit low */
 911:   outb(DOR, ENABLE_INT);        /* strobe it high again */
 912:   unlock();
 913:                                 /* collect the RESET interrupt */
 914:   do receive(HARDWARE, &mess); while (f_busy == BSY_IO);
 915: 
 916:   /* The controller supports 4 drives and returns a result for each of them.
 917:    * Collect all the results now.  The old version only collected the first
 918:    * result.  This happens to work for 2 drives, but it doesn't work for 3
 919:    * or more drives, at least with only drives 0 and 2 actually connected
 920:    * (the controller generates an extra interrupt for the middle drive when
 921:    * drive 2 is accessed and the driver panics).
 922:    *
 923:    * It would be better to keep collecting results until there are no more.
 924:    * For this, fdc_results needs to return the number of results (instead
 925:    * of OK) when it succeeds.
 926:    */
 927:   for (i = 0; i < 4; i++) {
 928:         fdc_out(FDC_SENSE);     /* probe FDC to make it return status */
 929:         (void) fdc_results();   /* flush controller */
 930:   }
 931:   for (i = 0; i < NR_DRIVES; i++)        /* clear each drive */
 932:         floppy[i].fl_calibration = UNCALIBRATED;
 933: 
 934:   /* The current timing parameters must be specified again. */
 935:   prev_dp = NULL;
 936: }
 937: 
 938: 
 939: /*===========================================================================*
 940:  *                              f_intr_wait                                  *
 941:  *===========================================================================*/
 942: PRIVATE int f_intr_wait()
 943: {
 944: /* Wait for an interrupt, but not forever.  The FDC may have all the time of
 945:  * the world, but we humans do not.
 946:  */
 947:   message mess;
 948: 
 949:   do receive(HARDWARE, &mess); while (f_busy == BSY_IO);
 950: 
 951:   if (f_busy == BSY_WAKEN) {
 952:         /* No interrupt from the FDC, this means that there is probably no
 953:          * floppy in the drive.  Get the FDC down to earth and return error.
 954:          */
 955:         need_reset = TRUE;
 956:         return(ERR_TIMEOUT);
 957:   }
 958:   return(OK);
 959: }
 960: 
 961: 
 962: /*===========================================================================*
 963:  *                              f_timeout                                    *
 964:  *===========================================================================*/
 965: PRIVATE void f_timeout(tp)
 966: timer_t *tp;
 967: {
 968: /* This routine is called when a timer expires.  Usually to tell that a
 969:  * motor has spun up, but also to forge an interrupt when it takes too long
 970:  * for the FDC to interrupt (no floppy in the drive).  It sets a flag to tell
 971:  * what has happened.
 972:  */
 973:   if (f_busy == BSY_IO) {
 974:         f_busy = BSY_WAKEN;
 975:         interrupt(FLOPPY);
 976:   }
 977: }
 978: 
 979: 
 980: /*==========================================================================*
 981:  *                              read_id                                     *
 982:  *==========================================================================*/
 983: PRIVATE int read_id()
 984: {
 985: /* Determine current cylinder and sector. */
 986: 
 987:   struct floppy *fp = f_fp;
 988:   int result;
 989:   u8_t cmd[2];
 990: 
 991:   /* Never attempt a read id if the drive is uncalibrated or motor is off. */
 992:   if (fp->fl_calibration == UNCALIBRATED) return(ERR_READ_ID);
 993:   if ((motor_status & (1 << f_drive)) == 0) return(ERR_READ_ID);
 994: 
 995:   /* The command is issued by outputting 2 bytes to the controller chip. */
 996:   cmd[0] = FDC_READ_ID;         /* issue the read id command */
 997:   cmd[1] = (fp->fl_head << 2) | f_drive;
 998:   if (fdc_command(cmd, 2) != OK) return(ERR_READ_ID);
 999:   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
1000: 
1001:   /* Get controller status and check for errors. */
1002:   result = fdc_results();
1003:   if (result != OK) return(result);
1004: 
1005:   if ((f_results[ST0] & ST0_BITS) != TRANS_ST0) return(ERR_READ_ID);
1006:   if (f_results[ST1] | f_results[ST2]) return(ERR_READ_ID);
1007: 
1008:   /* The next sector is next for I/O: */
1009:   fp->fl_sector = f_results[ST_SEC] - BASE_SECTOR + 1;
1010:   return(OK);
1011: }
1012: 
1013: 
1014: /*==========================================================================*
1015:  *                              f_do_open                                   *
1016:  *==========================================================================*/
1017: PRIVATE int f_do_open(dp, m_ptr)
1018: struct driver *dp;
1019: message *m_ptr;                 /* pointer to open message */
1020: {
1021: /* Handle an open on a floppy.  Determine diskette type if need be. */
1022: 
1023:   int dtype;
1024:   struct test_order *top;
1025: 
1026:   /* Decode the message parameters. */
1027:   if (f_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
1028: 
1029:   dtype = f_device & DEV_TYPE_BITS;      /* get density from minor dev */
1030:   if (dtype >= MINOR_fd0p0) dtype = 0;
1031: 
1032:   if (dtype != 0) {
1033:         /* All types except 0 indicate a specific drive/medium combination.*/
1034:         dtype = (dtype >> DEV_TYPE_SHIFT) - 1;
1035:         if (dtype >= NT) return(ENXIO);
1036:         f_fp->fl_density = dtype;
1037:         (void) f_prepare(f_device);     /* Recompute parameters. */
1038:         return(OK);
1039:   }
1040:   if (f_device & FORMAT_DEV_BIT) return(EIO);    /* Can't format /dev/fdN */
1041: 
1042:   /* The device opened is /dev/fdN.  Experimentally determine drive/medium.
1043:    * First check fl_density.  If it is not NO_DENS, the drive has been used
1044:    * before and the value of fl_density tells what was found last time. Try
1045:    * that first.  If the motor is still running then assume nothing changed.
1046:    */
1047:   if (f_fp->fl_density != NO_DENS) {
1048:         if (motor_status & (1 << f_drive)) return(OK);
1049:         if (test_read(f_fp->fl_density) == OK) return(OK);
1050:   }
1051: 
1052:   /* Either drive type is unknown or a different diskette is now present.
1053:    * Use test_order to try them one by one.
1054:    */
1055:   for (top = &test_order[0]; top < &test_order[NT-1]; top++) {
1056:         dtype = top->t_density;
1057: 
1058:         /* Skip densities that have been proven to be impossible */
1059:         if (!(f_fp->fl_class & (1 << dtype))) continue;
1060: 
1061:         if (test_read(dtype) == OK) {
1062:                 /* The test succeeded, use this knowledge to limit the
1063:                  * drive class to match the density just read.
1064:                  */
1065:                 f_fp->fl_class &= top->t_class;
1066:                 return(OK);
1067:         }
1068:         /* Test failed, wrong density or did it time out? */
1069:         if (f_busy == BSY_WAKEN) break;
1070:   }
1071:   f_fp->fl_density = NO_DENS;
1072:   return(EIO);                  /* nothing worked */
1073: }
1074: 
1075: 
1076: /*==========================================================================*
1077:  *                              test_read                                   *
1078:  *==========================================================================*/
1079: PRIVATE int test_read(density)
1080: int density;
1081: {
1082: /* Try to read the highest numbered sector on cylinder 2.  Not all floppy
1083:  * types have as many sectors per track, and trying cylinder 2 finds the
1084:  * ones that need double stepping.
1085:  */
1086:   int device;
1087:   off_t position;
1088:   iovec_t iovec1;
1089: 
1090:   f_fp->fl_density = density;
1091:   device = ((density + 1) << DEV_TYPE_SHIFT) + f_drive;
1092: 
1093:   (void) f_prepare(device);
1094:   position = (off_t) f_dp->test << SECTOR_SHIFT;
1095:   iovec1.iov_addr = (vir_bytes) tmp_buf;
1096:   iovec1.iov_size = SECTOR_SIZE;
1097:   (void) f_transfer(FLOPPY, DEV_GATHER, position, &iovec1, 1);
1098: 
1099:   if (iovec1.iov_size != 0) return(EIO);
1100: 
1101:   partition(&f_dtab, f_drive, P_FLOPPY);
1102:   return(OK);
1103: }
1104: 
1105: 
1106: /*============================================================================*
1107:  *                              f_geometry                                    *
1108:  *============================================================================*/
1109: PRIVATE void f_geometry(entry)
1110: struct partition *entry;
1111: {
1112:   entry->cylinders = f_dp->cyls;
1113:   entry->heads = NR_HEADS;
1114:   entry->sectors = f_sectors;
1115: }