The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/fd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993,1991 Carnegie Mellon University
    4  * Copyright (c) 1991 IBM Corporation 
    5  * All Rights Reserved.
    6  * 
    7  * Permission to use, copy, modify and distribute this software and its
    8  * documentation is hereby granted, provided that both the copyright
    9  * notice and this permission notice appear in all copies of the
   10  * software, derivative works or modified versions, and any portions
   11  * thereof, and that both notices appear in supporting documentation,
   12  * and that the name IBM not be used in advertising or publicity 
   13  * pertaining to distribution of the software without specific, written
   14  * prior permission.
   15  * 
   16  * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   17  * CONDITION.  CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
   18  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   19  * 
   20  * Carnegie Mellon requests users of this software to return to
   21  * 
   22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   23  *  School of Computer Science
   24  *  Carnegie Mellon University
   25  *  Pittsburgh PA 15213-3890
   26  * 
   27  * any improvements or extensions that they make and grant Carnegie Mellon
   28  * the rights to redistribute these changes.
   29  */
   30 
   31 /*
   32  * HISTORY
   33  * $Log:        fd.c,v $
   34  * Revision 2.5  93/12/07  13:53:45  dbg
   35  *      Removed UNTIMEOUT and wait calls from fdabios_init, since it is
   36  *      called at probe time (when neither thread services nor timeouts
   37  *      are available).  They're not necessary, since the called ABIOS
   38  *      functions always return.  I should really arrange to attach the
   39  *      clock before calling the floppy probe, but that will have to
   40  *      wait.
   41  *      [93/12/07            dbg]
   42  * 
   43  * Revision 2.4  93/11/17  16:52:44  dbg
   44  *      A tiny bit of delinting.  It needs a lot more.
   45  *      [93/10/29            dbg]
   46  * 
   47  * Revision 2.3  93/03/11  14:08:53  danner
   48  *      u_long -> u_int
   49  *      [93/03/09            danner]
   50  * 
   51  * Revision 2.2  93/02/04  07:59:23  danner
   52  *      Disable media-change detection for the floppy to allow booting
   53  *      from them in the microkernel world.
   54  *      [93/01/18            zon]
   55  * 
   56  *      Integrate PS2 code from IBM.
   57  *      [93/01/18            prithvi]
   58  * 
   59  */
   60 
   61 /*
   62  * COMPONENT_NAME: (FLOPPY) Mach 3.0 PS/2 Floppy Driver  
   63  *
   64  * FUNCTIONS: 
   65  *
   66  * ORIGINS: 27
   67  */                                                                   
   68 
   69 /*  OSF/1 PS/2 ABIOS diskette driver.  Driver lineage: AIX v3 R2 -> AIX v3 PS/2
   70  * -> OSF/1 PS/2.
   71  */
   72 
   73 
   74 /* Changed for the 3.0 port */
   75 
   76 #include <fd.h>
   77 
   78 #ifdef  MACH_KERNEL 
   79 #include <sys/types.h>
   80 #include <device/io_req.h>
   81 #include <device/buf.h>
   82 #include <device/errno.h>
   83 #include <i386/pmap.h>
   84 #include <sys/ioctl.h>
   85 #include <sys/syslog.h>
   86 #include <i386ps2/abios.h>
   87 #include <i386/ipl.h>
   88 #include <i386ps2/bus.h>
   89 #include <i386ps2/debugf.h>
   90 #include <i386ps2/fd_abios.h>
   91 #include <i386ps2/fdreg.h>
   92 #define PRIBIO          20  /* taken from i386at/m765.h */
   93 #else   /* MACH_KERNEL */
   94 #include <sys/types.h>
   95 #include <sys/buf.h>
   96 #include <sys/errno.h>
   97 #ifdef OSF
   98 #include <sys/fcntl.h>
   99 #else
  100 #include <sys/file.h>
  101 #endif /* OSF */
  102 #include <i386/pmap.h>
  103 #include <sys/ioctl.h>
  104 #include <sys/param.h>
  105 #include <sys/proc.h>
  106 #include <sys/syslog.h>
  107 #include <sys/uio.h>
  108 #include <sys/user.h>
  109 #include <i386ps2/abios.h>
  110 #include <i386/ipl.h>
  111 #include <kern/assert.h>
  112 #include <kern/task.h>
  113 #ifdef OSF
  114 #include <i386/handler.h>
  115 #endif /* OSF */
  116 #include <i386ps2/bus.h>
  117 #include "debugf.h"
  118 #include "fd_abios.h"
  119 #include "fdreg.h"
  120 #include "fd.h"
  121 #endif  /* MACH_KERNEL */
  122 
  123 extern int hz;
  124 
  125 extern hd_delay(int);
  126 
  127 #define HZ      hz
  128 
  129 #if defined(FDDEBUG) && !defined(DEBUG)
  130 #define DEBUG   1
  131 #endif
  132 
  133 #ifdef DEBUG
  134 int fddebug = 0;
  135 #define FDDEBUG(cond,args) if (cond) (args)
  136 #define FDINIT          (fddebug & DEBUG_CONFIG)
  137 #define FDOPEN          (fddebug & DEBUG_OPEN)
  138 #define FDCLOSE         (fddebug & DEBUG_CLOSE)
  139 #define FDREAD          (fddebug & DEBUG_READ)
  140 #define FDWRITE         (fddebug & DEBUG_WRITE)
  141 #define FDSTRAT         (fddebug & DEBUG_STRATEGY)
  142 #define FDINTR          (fddebug & DEBUG_INTR)
  143 #define FDIOCTL         (fddebug & DEBUG_IOCTL)
  144 #define FDCMD           (fddebug & BIT16)
  145 #define FDSTAT          (fddebug & BIT9)
  146 #define FDABIOS         (fddebug & DEBUG_ABIOS)
  147 #define FDSTUB          (fddebug & BIT17)
  148 #define FDDETAIL        (fddebug & DEBUG_ERR_COND)
  149 #else
  150 #define FDDEBUG(cond,args)
  151 #endif
  152 
  153 struct buf *geteblk();          /* Added for Mach 3.0  */
  154 
  155 /* Changed for the 3.0 port */
  156 
  157 #ifdef  MACH_KERNEL
  158 int fdopen(), fdclose(), fdread(), fdwrite(), fdstrategy(), fdintr();
  159 #else   /* MACH_KERNEL */
  160 int fdopen(), fdclose(), fdread(), fdwrite(), fdstrategy(), fdioctl();
  161 int fdintr();
  162 #endif  /* MACH_KERNEL */
  163 
  164 /* Additional internal device driver routines. 
  165 */
  166 int  fd_iocformat(dev_t, long, struct floppy *);
  167 int  fd_iocsinfo(struct floppy *, long);
  168 static void fd_sched(struct floppy *);
  169 void fd_stot();
  170 static int fdcall_abios(int, struct Fd_request *);
  171 static int fdcall_abios_poll(int, struct Fd_request *, int);
  172 int  fdcheck_sequence(struct floppy *);
  173 static void fdcleanup(struct floppy *);
  174 static int fdcommon_intr(struct Fd_request *);
  175 int  fddisk_changed(struct floppy *);
  176 int  fddoor_check(struct floppy *,int);
  177 int  fderror(struct floppy *);
  178 static int  fdexecute_command(struct floppy *, int);
  179 static void fdget_adapter();
  180 static void fdio(struct buf *);
  181 static void fdiodone(struct buf *, struct Fd_request *, struct floppy *, int);
  182 static int  fdissue_command(struct floppy *, int);
  183 static int  fdload_floppy(struct floppy *, int);
  184 int  fdmincnt(struct buf *);
  185 int  fdsettle_test(struct floppy *, int);
  186 static int  fdsetup_transfer(struct floppy *);
  187 int  fdspeed_test(struct floppy *);
  188 int  fdstage1_config(dev_t);
  189 void fdtimer(struct fdwatchdog *);
  190 static void fdlog_error();
  191 static int d_max_page();
  192 void fd_error_decode(
  193         int     code,
  194         char    *msg);
  195 
  196 /* Macros:
  197 */
  198 #define fdtype(fdp)             fdload_floppy(fdp,FDRMEDIA_PARMS)
  199 #define fdstartio(fdp)          fdexecute_command(fdp,\
  200                 (fdp->headptr->b_flags&B_READ) ? FDREAD_DATA : FDWRITE_DATA);
  201 
  202 #define fd_no_retry(fdp)        (fdp)->retry_count = FDMAXRETRIES;
  203 #define fd_clear_retry(fdp)     (fdp)->retry_count = \
  204                                 ((fdp)->retry_flag == TRUE) ? 0 : FDMAXRETRIES;
  205 
  206 /* Changed for the 3.0 Port */
  207 
  208 #ifdef  MACH_KERNEL             
  209 #define get_pmap(bp)            (kernel_pmap)
  210 #else   /* MACH_KERNEL */
  211 #define get_pmap(bp)            ( ((bp)->b_proc) ?\
  212                                         (bp)->b_proc->task->map->pmap :\
  213                                         kernel_pmap )
  214 #endif  /* MACH_KERNEL */
  215 
  216 
  217 #define NS_PER_TICK     (1000000000/HZ)
  218 #define NS_TO_TICKS(x)  ((x + (NS_PER_TICK - 1)) / NS_PER_TICK)
  219 #define us2tics(us)     NS_TO_TICKS( ((us) * 1000) )    /* us -> ticks */
  220 
  221 /* Global vars:
  222 */
  223 static struct adapter_structure fdadapter;
  224 static struct floppy floppies[FDMAXDRIVES];
  225 static struct buf fdbp[FDMAXDRIVES];
  226 
  227 #ifdef OSF
  228 static  ihandler_t      fd_handler;
  229 static  ihandler_id_t   *fd_handler_id;
  230 #endif /* OSF */
  231 
  232 static struct fd_data fd_data[] = {
  233         { 18, 80, 2, 27, 108, 255 },            /* FDLOAD_144 */
  234         { 9, 80, 2, 42, 80, 255 },              /* FDLOAD_720 */
  235         { 9, 40, 2, 42, 80, 255 }               /* FDLOAD_360 */
  236 };
  237 
  238 static int fddrive_val[FDMAXDRIVES] = {
  239         FDDRIVE0,
  240         FDDRIVE1
  241 };
  242 
  243 static char *fd_tmp_errors[] = {
  244         "unsupported drive type",       /* FD_UNSUP_DRIVE       */
  245         "unknown bytes/sector",         /* FD_UNSUP_SECT        */
  246         "unsupported minor",            /* FD_UNSUP_MINOR       */
  247         "lost interrupt",               /* FD_ERR_LOSTINT       */
  248         "media not present",            /* FD_ERR_NOMEDIA       */
  249         "media bad",                    /* FD_ERR_RETRY         */
  250         "media changed"                 /* FD_ERR_CHMEDIA       */
  251 };
  252 
  253 int fdprobe(), fdslave(), fdattach();
  254 
  255 int (*fdcintrs[])() = { fdintr, 0};
  256 
  257 struct i386_dev *fdinfo[NFD];
  258 struct i386_ctlr *fdcinfo[NFDC];
  259 
  260 struct  i386_driver      fdcdriver = {
  261         /* probe slave    attach   dname  dinfo   mname  minfo */
  262         fdprobe, fdslave, fdattach, "fd", fdinfo, "fdc", fdcinfo };
  263 
  264 #ifdef DEBUG
  265 #define MAX_ABIOS_FUNCTION_NAMES        (sizeof abios_function_names/ sizeof abios_function_names[0])
  266 static char *abios_function_names[] =  {
  267         "def_int", "ret_log_id_param",                          /* 0 - 1 */
  268         "reserved", "read_dev_param",                           /* 2 - 3 */
  269         "set_dev_param", "reset",                               /* 4 - 5 */
  270         "enable", "disable",                                    /* 6 - 7 */
  271         "read", "write",                                        /* 8 - 9 */
  272         "write-verify", "verify",                               /* a - b */
  273         "read-media-type", "set-media-type",                    /* c - d */
  274         "change-signal-status", "motor-off"                     /* e - f */
  275         "int-status"                                            /* 10    */
  276 };
  277 
  278 #define ABIOS_FUNCTION_NAME(fn) ((unsigned) (fn) < MAX_ABIOS_FUNCTION_NAMES ? abios_function_names[fn] : "unknown")
  279 #endif /* DEBUG */
  280 
  281 /*
  282  * TODO: 
  283  * call fdinit here so that we can set up interrupts properly before
  284  * open is called. Can't do it now because fdexecute_command currently
  285  * will sleep which appears to be a no-no at this stage.
  286  */
  287 
  288 fdprobe(addr,ctlr)
  289 struct i386_ctlr *ctlr;
  290 {
  291         return(fdinit(ctlr) == FDSUCCESS);
  292 }
  293 
  294 /*
  295  * determine if the given slave (unit) is present
  296  */
  297 fdslave(iod)
  298 struct i386_dev *iod;
  299 {
  300     if (iod->dev_slave >= fdadapter.fd_numd)
  301         return(0);              /* no such drive */
  302     return(1);
  303 }
  304 
  305 fdattach(iod)
  306 struct i386_dev *iod;
  307 {
  308 }
  309 
  310 
  311 int 
  312 fdinit(ctlr)
  313 struct i386_ctlr *ctlr;
  314 {
  315   struct floppy *fdp = &floppies[0];
  316   int i, rc;
  317 
  318   FDDEBUG(FDINIT,printf("fdinit: start\n"));
  319 
  320   printf("IBM ABIOS Floppy Disk Driver Ver : 1.1\n");
  321 
  322 
  323   /* Initialize the adapter struture
  324   */
  325   fdadapter.fdintr_status = FDFREE;
  326   fdadapter.need_controller = FALSE;
  327   fdadapter.int_wd.func = NULL;
  328   fdadapter.mot_wd.func = NULL;
  329   fdadapter.need_sleep = 0;             /* NEEDS WORK -- needed ? */
  330 
  331 
  332   /* Initialize each floppy structure
  333    */
  334   for (i = 0; i < FDMAXDRIVES; i++) {
  335     floppies[i].drive_state = FDSTAT_CLOS;
  336     floppies[i].headptr = NULL;
  337     floppies[i].tailptr = NULL;
  338     floppies[i].close_sleep = 0;        /* NEEDS WORK -- sleep on? */
  339     floppies[i].timeout_flag = FALSE;
  340     floppies[i].retry_flag = TRUE;
  341     floppies[i].read_count_bytes = 0;
  342     floppies[i].read_count_megabytes = 0;
  343     floppies[i].write_count_bytes = 0;
  344     floppies[i].write_count_megabytes = 0;
  345     floppies[i].open_check = FALSE;
  346     floppies[i].motor_off_time = 10;
  347 
  348     /* NEEDS WORK: THE FOLLOWING CAN PROBABLY GO AWAY! */
  349     floppies[i].drive_type = D_135H;
  350     floppies[i].head_settle_time = 0;
  351     floppies[i].motor_start = 0;
  352   }
  353 
  354   fdadapter.int_wd.time = 5 * HZ;       /* 5 second interrupt watchdog */
  355   fdadapter.int_wd.func = fdtimer;
  356   fdadapter.int_wd.type = FDINT_WD;
  357 
  358   /* 10 second motor off watchdog
  359    */
  360   fdadapter.mot_wd.time = fdp->motor_off_time * HZ;
  361   fdadapter.mot_wd.func = fdtimer;
  362   fdadapter.mot_wd.type = FDMOT_WD;
  363 
  364   /*  Do initialization of ABIOS structures.  This must
  365    * be done before int_enable() and ABIOS_RESET.
  366    *
  367    * Note: we can set FDBUSY because we are resetting
  368    *     the adapter and there can't be any other 
  369    *     activity on the floppy.
  370    */
  371   fdadapter.fdintr_status = FDBUSY;
  372 
  373 
  374 #ifdef  MACH_KERNEL
  375   rc = fdabios_init(fdp);
  376 #else   /* MACH_KERNEL */
  377   rc = fdexecute_command(fdp,FDABIOS_INIT);
  378 #endif  /* MACH_KERNEL */
  379 
  380 
  381   if (rc != FDSUCCESS) {
  382     FDDEBUG(FDOPEN,printf("FDOPEN: FDABIOS_INIT failed\n"));
  383 #ifdef  MACH_KERNEL
  384 #else   /* MACH_KERNEL */
  385     fdcleanup(NULL);
  386 #endif  /* MACH_KERNEL */
  387     return(EIO);
  388   }
  389 
  390   if (fdadapter.fd_numd == 0)           /* ABIOS sanity check */
  391   {
  392 #ifdef  MACH_KERNEL
  393     return D_NO_SUCH_DEVICE;
  394 #else   /* MACH_KERNEL */
  395     return(ENODEV);
  396 #endif  /* MACH_KERNEL */
  397   }
  398 
  399   if (fdadapter.fd_numd > FDMAXDRIVES) {
  400     log(LOG_WARNING,"fd: %d drives present.  Only %d are supported\n",
  401         fdadapter.fd_numd, FDMAXDRIVES);
  402     fdadapter.fd_numd = FDMAXDRIVES;
  403   }
  404 
  405 #ifdef OSF
  406   /* init interrupts */
  407   fd_handler.ih_level = fdadapter.fd_intl;
  408   fd_handler.ih_handler =  fdintr;
  409   fd_handler.ih_resolver = (int (*)()) NULL;
  410   fd_handler.ih_stats.intr_type = INTR_DEVICE;
  411   fd_handler.ih_stats.intr_cnt = 0;
  412   fd_handler.ih_priority = SPLFD;
  413   fd_handler.ih_flags = IH_FLAG_NOSHARE;
  414   if ((fd_handler_id = handler_add( &fd_handler )) != NULL)
  415     handler_enable( fd_handler_id );
  416   else
  417     return(ENXIO);
  418 #else
  419   ctlr->ctlr_pic = fdadapter.fd_intl;
  420   ctlr->ctlr_spl = SPLFD;
  421   take_ctlr_irq(ctlr);
  422 #endif /* OSF */
  423   return(FDSUCCESS);
  424 }
  425 
  426 /*
  427  * reset the adapter, since this causes an interrupt and hence
  428  * a sleep we are called from open not from probe/slave/attach
  429  */
  430 fdreset()
  431 {
  432   struct floppy *fdp = &floppies[0];
  433   int rc;
  434 
  435   /*  Reset the ABIOS "diskette system".  This does
  436    * stuff for the adapter, not a particular diskette
  437    * drive.
  438    */
  439   fdadapter.fdintr_status = FDBUSY;
  440   rc = fdexecute_command(fdp,FDABIOS_RESET);
  441   if (rc != FDSUCCESS) {
  442     FDDEBUG(FDOPEN, printf( "FDOPEN: FDABIOS_RESET failed\n"));
  443     fdcleanup(fdp);
  444     return(EIO);
  445   }
  446   
  447   return(FDSUCCESS);
  448 }
  449 
  450 /* NOTES: The 'devno' parameter always indicates which drive to open, and may
  451  * indicate the diskette characteristics to use.  The 'minor' macro is used
  452  * to extract the minor number from 'devno'.  If the minor number portion of
  453  * 'devno' is a 0 or a 1, then the fdopen() routine will attempt to
  454  * determine the drive type and diskette type by reading from the drive with
  455  * different drive characteristics.  This is done by calling the fdtype()
  456  * routine.  If the minor number is 4 or greater, then the diskette
  457  * characteristics implied by that format specific special file are used. 
  458  * The determination of the drive type can be suppressed by ORing the O_NDELAY
  459  * flag into the 'devflag' parameter.  This is mainly used by the format
  460  * command since the open will otherwise fail for an unformatted diskette. 
  461  */
  462 int
  463 fdopen(dev, flags)
  464      dev_t dev;
  465      int flags;
  466 {
  467   register struct floppy *fdp;
  468   int drive;
  469   int rc;
  470   int firstopen = 1;            /* For MULTIPLE_OPENS */
  471   static int fdinited = 0;
  472 
  473   FDDEBUG(FDOPEN,printf("fdopen(%x,%x)\n",dev,flags));
  474 
  475   /*  This needs to be done early so we can use the values it
  476    * initializes.
  477    */
  478   if (!fdinited) {
  479     fdinited = 1;
  480     if ( (rc = fdreset()) != FDSUCCESS )
  481       return(rc);
  482   }
  483 
  484   drive = fd_drive(dev);                /* get the drive # */
  485   if (drive < 0 || drive >= fdadapter.fd_numd) {
  486     FDDEBUG(FDOPEN, printf("FDOPEN: bad drive number %d\n",drive));
  487     return (EINVAL);
  488   }
  489 
  490   fdp = &floppies[drive];
  491 
  492 /* This was commented out for MACH 3.0 because flags is not passed down */
  493 
  494 #ifdef  MACH_KERNEL
  495 #else   /* MACH_KERNEL */
  496 
  497   if (fdp->drive_state != FDSTAT_CLOS) {
  498     /*  Check to see if 2nd open has the same characteristics as the
  499      * previous opens, as well as exclusive opens.
  500      */
  501     FDDEBUG(FDOPEN, printf("fdopen: drive already open\n"));
  502 
  503     if ( (minor(fdp->device_number) != minor(dev)) ||
  504          (flags & O_EXCL) || (fdp->drive_state & FDSTAT_EXOP) ) {
  505       return(EBUSY);
  506     }
  507     
  508     goto fd_multopen;   /* skip some 1st time stuff */
  509   }
  510 #endif  /* MACH_KERNEL */
  511 
  512 
  513   /* Load the structure 'floppy' with the default values and the minor
  514    * device number. 
  515    */
  516   fdp->device_number = dev;
  517   rc = fdload_floppy(fdp, FDREAD_PARMS);        /* drive info */
  518   if (rc != FDSUCCESS) {
  519     fdcleanup(fdp);
  520     FDDEBUG(FDOPEN,printf("FDOPEN: default load failed\n"));
  521     return (rc);
  522   }
  523 
  524   /* This has to happen before fddoor_check() so that we get past
  525    * the media changed signal successfully.
  526    */
  527   fdp->fd_change = FDCHANGE_NEW;
  528 
  529 fd_multopen:
  530 
  531 #ifdef  MACH_KERNEL
  532 if (!(flags & D_NODELAY)) {
  533 
  534 /*
  535    Commented out to allow working of floppy for Mach 3.0 
  536 
  537    rc = fddoor_check(fdp, (flags&D_WRITE));
  538 */
  539    if (rc != FDSUCCESS) {
  540         fdcleanup(fdp);
  541         return(rc);
  542    }
  543 }
  544 #else   /* MACH_KERNEL */
  545 
  546   if (flags & O_EXCL)
  547     fdp->drive_state |= FDSTAT_EXOP;
  548 
  549   /* Don't read the diskette if open with O_NDELAY
  550   */
  551   if (!(flags & O_NDELAY)) {
  552     /* Check for diskette presence and write protection (if opening for
  553      * write).
  554      */
  555     rc = fddoor_check(fdp, (flags&FWRITE));
  556     if (rc != FDSUCCESS) {
  557       fdcleanup(fdp);
  558       return (rc);
  559     }
  560   }
  561 
  562 #endif  /* MACH_KERNEL */
  563 
  564   else {
  565     /* If the O_NDELAY flag is set, the open is done.  Set
  566      * drive state to FDOPEN and return. 
  567      */
  568     fdp->drive_state = FDSTAT_OPEN;
  569     FDDEBUG(FDOPEN,printf("fdopen: opened O_NDELAY\n"));
  570     return(0);
  571   }
  572 
  573   /*  Some more stuff that needs to only be done on the first open.
  574   */
  575   if (firstopen) {
  576 #ifdef NEEDS_WORK               /* NEEDS WORK */
  577 /* NEEDS WORK --  Need to do media sence and r/w the diskette before we
  578 ** NEEDS WORK -- can determine it's soft type...someday.
  579 */
  580     /*  Call fdtype() to load the floppy structure with the
  581      * correct characteristics.
  582      */
  583     rc = fdtype(fdp);
  584     if (rc != FDSUCCESS) {
  585       FDDEBUG(FDOPEN, ("FDOPEN: fdtype failed\n"));
  586       fdcleanup(fdp);
  587       fdp->drive_state = FDSTAT_CLOS;
  588       return (rc);
  589     }
  590 #endif
  591 
  592     /*  We're finally ready to set the open flag.  Note that
  593      * we don't want to set the open flag until the very end
  594      * so that we can tell if the drive was on a multiple
  595      * open or not.
  596      */
  597     fdp->drive_state = FDSTAT_OPEN;
  598     fdp->close_waiting = FALSE;
  599   }
  600 
  601   FDDEBUG(FDOPEN,printf("fdopen: successful\n"));
  602   return(0);
  603 }
  604 
  605 /*  Close the diskette drive.  Turn off the light if there is no other
  606  * activity on the adapter.  Make sure timers and stuff are off.
  607  */
  608 int 
  609 fdclose(devno)
  610      dev_t devno;
  611 {
  612   register struct floppy *fdp;
  613   int pri;                              /* for spl* calls */
  614   int drive;
  615 
  616   FDDEBUG(FDCLOSE, printf("fdclose: entering...\n"));
  617 
  618   drive = fd_drive(devno);
  619 
  620   FDDEBUG(FDCLOSE,printf("fdclose: drive %d\n", drive));
  621 
  622   /* Is the drive given valid?
  623    */
  624   if (drive < 0 || drive >= fdadapter.fd_numd)
  625     return (EINVAL);
  626 
  627   fdp = &floppies[drive];
  628 
  629   /* Check if see if finished with all i/o for this drive.  If
  630    * not, sleep until i/o is finished. 
  631    */
  632   pri = splfd();
  633   while (fdp->headptr != NULL) {
  634     FDDEBUG(FDCLOSE, printf("fdclose: wait for i/o to finish\n"));
  635 
  636     fdp->close_waiting = TRUE;
  637     sleep(&fdp->close_sleep, PRIBIO);   /* NEEDS WORK */
  638   }
  639   splx(pri);
  640 
  641   /* Mark this drive as FDCLOSED, call fdcleanup() to do any
  642    * cleanup that is possible (including turning off the
  643    * light if need be).
  644    */
  645   fdp->drive_state = FDSTAT_CLOS;
  646   fdcleanup(fdp);
  647 
  648   FDDEBUG(FDCLOSE, printf("fdclose: done\n"));
  649   return(0);
  650 }
  651 
  652 /*  The block i/o entry point.  Check parameters for validity and enqueue
  653  * the request, starting i/o if the adapter is free.
  654  */
  655 int 
  656 fdstrategy(bp)
  657      register struct buf *bp;
  658 {
  659   register struct floppy *fdp;
  660   int pri;
  661 
  662   FDDEBUG(FDSTRAT, printf("fdstrategy: entering...\n"));
  663 
  664   fdp = &floppies[fd_drive(bp->b_dev)];
  665   bp->b_resid = 0;
  666   bp->b_error = 0;
  667   bp->av_forw = NULL;
  668 
  669   /* If the byte transfer length is not a multiple of 512
  670    * bytes, return EINVAL and return. 
  671    */
  672   if (bp->b_bcount % fdp->bytes_per_sector) {
  673     FDDEBUG(FDSTRAT, printf("fdstrategy: n != x*512\n"));
  674     bp->b_flags |= B_ERROR;
  675     bp->b_error = EINVAL;
  676 
  677     /* no data transferred */
  678     bp->b_resid += bp->b_bcount;
  679 
  680     iodone(bp);
  681     goto fd_done;
  682   }
  683 
  684   /*  Verify that i/o does not start past the end of the
  685    * diskette. Also, verify that the starting block number is
  686    * non-negative.
  687    *
  688    *  Error codes:
  689    *    EINVAL - the blkno is negative, or is a read past
  690    *    the last block on the media
  691    *    ENOSPC - A write past the end of the media.
  692    *
  693    *  Note that a read on the last block (actually 1st non-
  694    * valid block) is not an error, but not data is transferred.
  695    */
  696   if ( (bp->b_blkno < 0) || (bp->b_blkno >= fdp->number_of_blocks) ) {
  697     FDDEBUG(FDSTRAT, printf("fdstrategy: invalid blkno\n"));
  698 
  699     if (!(bp->b_flags & B_READ)) {      /* B_WRITE */
  700       bp->b_flags |= B_ERROR;
  701       if (bp->b_blkno < 0)
  702         bp->b_error = EINVAL;
  703       else
  704 #ifdef  MACH_KERNEL
  705         bp->b_error = EIO;              /* EIO is mapped D_IO_ERROR */
  706 #else   /* MACH_KERNEL */
  707         bp->b_error = ENOSPC;
  708 #endif  /* MACH_KERNEL */
  709     }
  710     else if (bp->b_blkno == fdp->number_of_blocks) {
  711       bp->b_error = 0;
  712     }
  713     else {
  714       bp->b_flags |= B_ERROR;
  715       bp->b_error = EINVAL;
  716     }
  717 
  718     /* all cases use the same b_resid */
  719     bp->b_resid = bp->b_bcount;
  720 
  721     iodone(bp);
  722     goto fd_done;
  723   }
  724 
  725   /*  See if there are any buffer headers in the queue.
  726    * If there are, put the buffer header at the end of
  727    * the queue.  If the queue is empty, put the buffer
  728    * header in the queue and call fdio(). 
  729    */
  730   pri = splfd();
  731 
  732   if (fdp->headptr != NULL) {   /* queue not empty */
  733     FDDEBUG(FDSTRAT, printf("fdstrategy: buf appended to q\n"));
  734 
  735     /* link it in the list:
  736      *  - old tail points at new element
  737      *  - new element becomes the new tail
  738      */
  739     fdp->tailptr->av_forw = bp;
  740     fdp->tailptr = bp;
  741 
  742     splx(pri);
  743   }
  744   else {                        /* q empty -> start i/o */
  745     /* set up the queue of 1 buf struct
  746      *  - head and tail are the same.
  747      */
  748     fdp->headptr = fdp->tailptr = bp;
  749 
  750     /*  If the adapter is free (other diskettes also
  751      * not busy) then start the io.  If the adapter
  752      * is busy, then the interrupt handler will find
  753      * the request and start it up.
  754      *
  755      *  To start the i/o, re-enable interrupts, make
  756      * sure we can get the adapter (it will not sleep
  757      * if we are at interrupt level), and then start
  758      * the i/o.
  759      */
  760     if (fdadapter.fdintr_status == FDFREE) {
  761       FDDEBUG(FDSTRAT, printf("fdstrategy: startio\n"));
  762 
  763       splx(pri);
  764       fdget_adapter();
  765       fdio(bp);
  766     }
  767     else
  768       splx(pri);
  769   }
  770 
  771 fd_done:
  772   FDDEBUG(FDSTRAT, printf("fdstrategy: done\n"));
  773   return (FDSUCCESS);
  774 }
  775 
  776 /*  Raw read.  Use physio() to do the transfer.
  777  *
  778  * NEEDS WORK - We should handle unaligned transfers for both read and
  779  * NEEDS WORK - in a common routine around here somewhere.
  780  */
  781 int 
  782 fdread(devno, uiop)
  783      dev_t devno;
  784      struct uio *uiop;
  785 {
  786   register struct buf *bp = &fdbp[fd_drive(devno)];
  787 
  788 #ifdef  MACH_KERNEL
  789 #else   /* MACH_KERNEL */
  790   register struct iovec *iov;
  791   register int cnt;
  792 #endif  /* MACH_KERNEL */
  793 
  794   FDDEBUG(FDREAD, printf("fdread: start\n"));
  795 
  796 
  797 #ifdef  MACH_KERNEL
  798 #else   /* MACH_KERNEL */
  799 
  800   /*  Check for atleast 512 byte alignment on all io_vec's.
  801    */
  802   iov = uiop->uio_iov;
  803   for(cnt = 0 ; cnt < uiop->uio_iovcnt; cnt++) {
  804     if ( ((u_int)(iov++)->iov_base) & 0x1ff)
  805       return(EIO);
  806   }
  807 
  808 #endif  /* MACH_KERNEL */
  809 
  810   return(physio(fdstrategy,bp,devno,B_READ,fdmincnt,uiop));
  811 }
  812 
  813 /* Raw write.  Use physio() to do the transfer.
  814  */
  815 int 
  816 fdwrite(devno, uiop)
  817      dev_t devno;
  818      struct uio *uiop;
  819 {
  820   register struct buf *bp = &fdbp[fd_drive(devno)];
  821 
  822 #ifdef  MACH_KERNEL
  823 #else   /* MACH_KERNEL */
  824   register struct iovec *iov;
  825   register int cnt;
  826 #endif  /* MACH_KERNEL */
  827 
  828   FDDEBUG(FDWRITE, printf("fdwrite: start\n"));
  829 
  830 
  831 #ifdef  MACH_KERNEL
  832 #else   /* MACH_KERNEL */
  833   /*  Check for atleast 512 byte alignment on all io_vec's.
  834    */
  835   iov = uiop->uio_iov;
  836   for(cnt = 0 ; cnt < uiop->uio_iovcnt; cnt++) {
  837     if ( ((u_int)(iov++)->iov_base) & 0x1ff)
  838       return(EIO);
  839   }
  840 #endif  /* MACH_KERNEL */
  841 
  842   return(physio(fdstrategy,bp,devno,B_WRITE,fdmincnt,uiop));
  843 }
  844 
  845 /* Changed for the 3.0 port */
  846 
  847 #ifdef  MACH_KERNEL
  848 #else   /* MACH_KERNEL */
  849 
  850 /* ioctl entry point.  Lots of status, plus things like format.
  851  *
  852  * NEEDS WORK -- no ioctl's are currently implemented.
  853  */
  854 int 
  855 fdioctl(devno, op, arg, devflag)
  856      dev_t devno;
  857      int op;
  858      register long arg;
  859      u_int devflag;
  860 {
  861 #ifdef NEEDS_WORK                       /* NEEDS WORK: LOOK AT IOCTLs LATER */
  862   register struct floppy *fdp;
  863   register struct devinfo *devinfop;
  864   register struct fdinfo *fdinfop;
  865   register struct fdparms *fdparmsp;
  866   int tmp;
  867   int rc = FDSUCCESS;
  868 
  869   FDDEBUG(FDIOCTL, printf("fdioctl: start\n"));
  870 
  871   fdp = &floppies[fd_drive(devno)];
  872 
  873   switch (op) {
  874 
  875   case IOCINFO:
  876     /* The following ioctl operation is defined for every device
  877      * that uses the ioctl interface. 
  878      *
  879      * IOCINFO - returns some information about the diskette.
  880      * This is a standard ioctl option that can be issued to find
  881      * out information about any device that uses ioctls.  A
  882      * poiner to a structure of type devinfo should be passed in
  883      * the 'arg' parameter.  The information about the diskette
  884      * will be loaded into the devinfo structure. 
  885      */
  886     FDDEBUG(FDIOCTL, printf("fdioctl: IOCINFO\n"));
  887 
  888     /* Allocate a devinfo structure. */
  889     devinfop = (struct devinfo *) malloc(sizeof(struct devinfo));
  890 
  891     if (devinfop == NULL)
  892       rc = ENOMEM;
  893     else {
  894       devinfop->devtype = DD_DISK;
  895       devinfop->flags = DF_RAND;
  896       devinfop->un.dk.bytpsec = (short) fdp->bytes_per_sector;
  897       devinfop->un.dk.secptrk = (short) fdp->sectors_per_track;
  898       devinfop->un.dk.trkpcyl = (short) fdp->tracks_per_cylinder;
  899       devinfop->un.dk.numblks = (long) fdp->number_of_blocks;
  900 
  901       /* Copy the structure to the user's address space.
  902        */
  903       tmp = copyout( (char *)devinfop, (char *)arg,
  904                     sizeof(struct devinfo) );
  905       if (tmp == -1)
  906         rc = EINVAL;
  907 
  908       free((caddr_t) devinfop);
  909     }
  910     break;
  911 
  912   case FDIOCFORMAT:
  913     /* See the header comment for fdiocformat()
  914      */
  915     FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCFORMAT\n"));
  916 
  917     rc = fd_iocformat(devno,arg,fdp);
  918 
  919     FDDEBUG(FDIOCTL, printf("fdioctl: done\n"));
  920     break;
  921 
  922   case FDIOCGINFO:
  923     /* FDIOCGINFO - gets the current diskette characteristics.  A
  924      * pointer to a structure of type fdinfo must be passed in
  925      * the 'arg' parameter.  This operation will load the fdinfo
  926      * structure with the current diskette parameters. 
  927      */
  928     FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCGINFO\n"));
  929 
  930     /* Allocate an fdinfo structure. */
  931     fdinfop = (struct fdinfo *) malloc(sizeof(struct fdinfo));
  932 
  933     if (fdinfop == NULL)
  934       rc = ENOMEM;
  935     else {
  936       fdinfop->type = (short) (fdp->drive_type);
  937       fdinfop->nsects = (int) (fdp->sectors_per_track);
  938       fdinfop->sides = (int) (fdp->tracks_per_cylinder);
  939       fdinfop->ncyls = (int) (fdp->cylinders_per_disk);
  940 
  941       /* Call copyout to copy the fdinfo structure to the
  942        * user. 
  943        */
  944       tmp = copyout((char *) (fdinfop), (char *) (arg),
  945                     sizeof(struct fdinfo));
  946       if (tmp == -1)
  947         rc = EINVAL;
  948 
  949       free((caddr_t) fdinfop);
  950     }
  951     break;
  952 
  953   case FDIOCSINFO:
  954     /* See the header comment for fd_iocsinfo()
  955      */
  956     FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCSINFO\n"));
  957     rc = fd_iocsinfo(fdp,arg);
  958     break;
  959 
  960   case FDIOCRETRY:
  961   case FDIOCNORETRY:
  962     /* FDIOCRETRY - enables retries on errors.
  963      * FDIOCNORETRY - disables retries on errors.
  964      *
  965      * These operations require RAS_CONFIG authority.
  966      */
  967     FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCNORETRY\n"));
  968 
  969     if (priv_chk(RAS_CONFIG))
  970       fdp->retry_flag = (op == FDIOCRETRY) ? TRUE : FALSE;
  971     else
  972       rc = EACCES;
  973     break;
  974 
  975   case FDIOCSTATUS:
  976     /* See header comment for fd_iocstatus()
  977      */
  978     rc = fd_iocstatus(fdp,arg);
  979     break;
  980 
  981   case FDIOCGETPARMS:
  982     /* FDIOCGETPARMS - gets various drive and diskette parameters
  983      * and returns them to the caller. 
  984      *
  985      * The following two ioctls are designed for use by the PC
  986      * simulator. 
  987      */
  988     FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCGETPARMS\n"));
  989 
  990     /* Allocate an fdparms structure.
  991      */
  992     fdparmsp = (struct fdparms *) malloc(sizeof(struct fdparms));
  993     if (fdparmsp == NULL) {
  994       rc = ENOMEM;
  995       break;
  996     }
  997 
  998     fdparmsp->diskette_type = fdp->diskette_type;
  999     fdparmsp->sector_size = fdp->e_bytesps;
 1000     fdparmsp->sectors_per_track = fdp->sectors_per_track;
 1001     fdparmsp->sectors_per_cylinder = fdp->sectors_per_cylinder;
 1002     fdparmsp->tracks_per_cylinder = fdp->tracks_per_cylinder;
 1003     fdparmsp->cylinders_per_disk = fdp->cylinders_per_disk;
 1004     fdparmsp->data_rate = fdp->data_rate;
 1005     fdparmsp->head_settle_time = fdp->head_settle_time;
 1006     fdparmsp->head_load = 0;
 1007     fdparmsp->fill_byte = fdp->fill_byte;
 1008     fdparmsp->step_rate = 0;
 1009     fdparmsp->step_rate_time = 0;
 1010     fdparmsp->gap = fdp->gap;
 1011     fdparmsp->format_gap = fdp->format_gap;
 1012     fdparmsp->data_length = fdp->data_length;
 1013     fdparmsp->motor_off_time = fdp->motor_off_time;
 1014     fdparmsp->bytes_per_sector = fdp->bytes_per_sector;
 1015     fdparmsp->number_of_blocks = fdp->number_of_blocks;
 1016 
 1017     /* Call copyout to copy the fdinfo structure to the user. */
 1018 
 1019     tmp = copyout((char *) (fdparmsp), (char *) (arg), sizeof(struct fdparms));
 1020     if (tmp == -1)
 1021       rc = EINVAL;
 1022     free((caddr_t) fdparmsp);
 1023     break;
 1024 
 1025   case FDIOCSETPARMS:
 1026 #define check(cnd,errno)        if (!(cnd)) {                   
 1027                                         free((caddr_t) fdparmsp);
 1028                                         rc = (errno);           
 1029                                         break;  
 1030                                 }
 1031 #define cond(member)            (fdp->member == fdparmsp->member)
 1032 
 1033     /* FDIOCGETPARMS - sets various drive and diskette parameters
 1034      * from values passed in from the caller. 
 1035      */
 1036     FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCSETPARMS\n"));
 1037 
 1038     /* Allocate an fdparms structure. */
 1039 
 1040     fdparmsp = (struct fdparms *) malloc(sizeof(struct fdparms));
 1041     if (fdparmsp == NULL) {
 1042       rc = ENOMEM;
 1043       break;
 1044     }
 1045 
 1046     /* get the fdparms structure from the user
 1047      */
 1048     tmp = copyin((char *) (arg), (char *) (fdparmsp),
 1049                  sizeof(struct fdparms));
 1050     check(tmp == 0,EINVAL);
 1051 
 1052     /*  There are certin fields we just can't let the user
 1053      * change, because it will reek havoc on the driver, and
 1054      * potentially the kernel.  Here we check them, and return
 1055      * EINVAL if they are bad.  Note they are also not set, but
 1056      * we want to return EINVAL, just to make sure someone
 1057      * doesn't get the delusion that something has changed.
 1058      */
 1059     check(fdp->diskette_type == fdparmsp->diskette_type,EINVAL);
 1060     check(fdparmsp->head_load == 0,EINVAL);
 1061     check(fdparmsp->step_rate == 0,EINVAL);
 1062     check(fdparmsp->step_rate_time == 0,EINVAL);
 1063     check(cond(sectors_per_track),EINVAL);
 1064     check(cond(sectors_per_cylinder),EINVAL);
 1065     check(cond(tracks_per_cylinder),EINVAL);
 1066     check(cond(cylinders_per_disk),EINVAL);
 1067     check(cond(data_rate),EINVAL);
 1068     check(cond(head_settle_time),EINVAL);
 1069     check(cond(number_of_blocks),EINVAL);
 1070     check(cond(bytes_per_sector),EINVAL);
 1071 
 1072     /*  Now the fields we can really change with a "Set Device
 1073      * Parameters" ABIOS call.  If the attribute has changed
 1074      * then we save the original value, and call FD_SETDP_POLL
 1075      * or FD_SETMT_POLL to attempt to change the value.  If the
 1076      * call fails, we back out the change, and fail the ioctl
 1077      * with EINVAL.
 1078      */
 1079     if (fdp->e_bytesps != fdparmsp->sector_size) {
 1080       check((fdparmsp->sector_size==FD_256_BYTE_PER_SECTOR)||
 1081             (fdparmsp->sector_size==FD_512_BYTE_PER_SECTOR),
 1082             EINVAL);
 1083       tmp = fdp->e_bytesps;
 1084       fdp->e_bytesps = fdparmsp->sector_size;
 1085       fdget_adapter();
 1086       if (fdexecute_command(fdp,FD_SETDP_POLL)!=FDSUCCESS) {
 1087         fdp->e_bytesps = tmp;
 1088         free(fdparmsp);
 1089         rc = EINVAL;
 1090         break;
 1091       }
 1092 
 1093       /*  When changing the sector_size, bytes_per_sector
 1094        * is implicitly changed, and we need to reflect
 1095        * this back to the user so he can continue to make
 1096        * fdiocsetparms ioctl's with the current fdparm
 1097        * structure.
 1098        */
 1099       fdparmsp->bytes_per_sector = fdp->bytes_per_sector;
 1100       tmp = copyout((char *) (fdparmsp), (char *) (arg),
 1101                     sizeof(struct fdparms));
 1102       check(tmp == 0,EINVAL);
 1103     }
 1104 
 1105     if (fdp->gap != fdparmsp->gap) {
 1106       tmp = fdp->gap;
 1107       fdp->gap = fdparmsp->gap;
 1108       fdget_adapter();
 1109       if (fdexecute_command(fdp,FD_SETDP_POLL)!=FDSUCCESS) {
 1110         fdp->gap = tmp;
 1111         free(fdparmsp);
 1112         rc = EINVAL;
 1113         break;
 1114       }
 1115     }
 1116 
 1117     if (fdp->data_length != fdparmsp->data_length) {
 1118       tmp = fdp->data_length;
 1119       fdp->data_length = fdparmsp->data_length;
 1120       fdget_adapter();
 1121       if (fdexecute_command(fdp,FD_SETDP_POLL)!=FDSUCCESS) {
 1122         fdp->data_length = tmp;
 1123         free(fdparmsp);
 1124         rc = EINVAL;
 1125         break;
 1126       }
 1127     }
 1128 
 1129     if (fdp->fill_byte != fdparmsp->fill_byte) {
 1130       tmp = fdp->fill_byte;
 1131       fdp->fill_byte = fdparmsp->fill_byte;
 1132       fdget_adapter();
 1133       if (fdexecute_command(fdp,FD_SETMT_POLL)!=FDSUCCESS) {
 1134         fdp->fill_byte = tmp;
 1135         free(fdparmsp);
 1136         rc = EINVAL;
 1137         break;
 1138       }
 1139     }
 1140 
 1141     if (fdp->format_gap != fdparmsp->format_gap) {
 1142       tmp = fdp->format_gap;
 1143       fdp->format_gap = fdparmsp->format_gap;
 1144       fdget_adapter();
 1145       if (fdexecute_command(fdp,FD_SETMT_POLL)!=FDSUCCESS) {
 1146         fdp->format_gap = tmp;
 1147         free(fdparmsp);
 1148         rc = EINVAL;
 1149         break;
 1150       }
 1151     }
 1152 
 1153     /*  Update the motor off time:  If it is really changed, then
 1154      * calculate the delta between the 2 times, making sure the
 1155      * value is atleast 1 second so it won't possibly get missed.
 1156      */
 1157     /* NEEDS WORK -- this code changed a touch from version 3
 1158      * NEEDS WORK -- since we use 1/HZ timers instead of watch-
 1159      * NEEDS WORK -- dogish timers, and we have to untimeout()
 1160      * NEEDS WORK -- them, and can't update on the fly...Don't
 1161      * NEEDS WORK -- if we can get it to change the time, until
 1162      * NEEDS WORK -- with the next time out...
 1163      */
 1164     if (fdp->motor_off_time != fdparmsp->motor_off_time) {
 1165 #ifdef NEEDS_WORK       /* NEEDS WORK */
 1166       tmp =     fdadapter.mot_wd.time - 
 1167         (fdp->motor_off_time -
 1168          fdparmsp->motor_off_time);
 1169       tmp = (tmp < 1) ? 1 : tmp;
 1170       fdadapter.mot_wd.timer.count = tmp;
 1171 #endif
 1172       fdadapter.mot_wd.time = fdparmsp->motor_off_time;
 1173       fdp->motor_off_time = fdparmsp->motor_off_time;
 1174     }
 1175 
 1176     free((caddr_t) fdparmsp);
 1177     break;
 1178 
 1179   default:
 1180     FDDEBUG(FDIOCTL, printf("fdioctl: no such ioctl\n"));
 1181     rc = EINVAL;
 1182     break;
 1183   }
 1184 
 1185   FDDEBUG(FDIOCTL, printf("fdioctl: done\n"));
 1186   return (rc);
 1187 #else
 1188   return(EINVAL);
 1189 #endif
 1190 }
 1191 #endif  /* MACH_KERNEL */
 1192 
 1193 
 1194 /*  This routine calls fdcall_abios() and uses sleep() to wait until
 1195  * the call is completed.  The FD_RB_SYNC flag is set in the request
 1196  * block so the interrupt handler knows to handle the request specially.
 1197  *
 1198  * The interrupt handler uses wakeup() to wake this process up, and does
 1199  * not do an iodone() since a polled request will never come from the 
 1200  * buffer cache.
 1201  *
 1202  * The 3rd parameter to this function (sched) is a boolean that indicates
 1203  * if we should call fd_sched() to look for more ABIOS requests to process.
 1204  * This is useful when a particular function requires multiple ABIOS
 1205  * requests or the caller needs to use values out of the request block,
 1206  * and does not want to have these values trashed by subsequent ABIOS calls.
 1207  *
 1208  * NOTES: fdcall_abios_poll() should not be used for ABIOS calls that do
 1209  * not stage on time, or stage on interrupt.  Use fdcall_abios() for this
 1210  * directly.  If the poll functionality is used in this case, then the
 1211  * error code cannot be returned properly.
 1212  *
 1213  *  open_check gets set to FALSE when the polled request is done.  See
 1214  * fdtimer() for more info.
 1215  */
 1216 static int
 1217 fdcall_abios_poll(abios_function, rb, sched)
 1218      int abios_function;
 1219      register struct Fd_request *rb;
 1220      int sched;
 1221 {
 1222   register struct floppy *fdp;
 1223   int rc;
 1224   int pri;                      /* for i_ calls */
 1225 
 1226   FDDEBUG(FDABIOS, printf("fdcall_abios_poll: function 0x%x (%s) rb=0x%x sched=%d\n",
 1227         abios_function, ABIOS_FUNCTION_NAME(abios_function),rb,sched));
 1228 
 1229   fdp = &floppies[rb->r_unit];  /* get floppy structure */
 1230   fdp->timeout_flag = FALSE;    /* clear timeout flag */
 1231   rb->state |= FD_RB_SYNC;      /* this is a synchronous request */
 1232   rb->req_errno = 0;            /* clear for non-intr calls */
 1233 
 1234 
 1235   fdcall_abios(abios_function,rb);
 1236 
 1237 
 1238 
 1239   /*  Sleep until our request is finished.
 1240    */
 1241   
 1242   pri = splfd();
 1243 
 1244   while (rb->r_return_code != ABIOS_DONE) {
 1245     FDDEBUG(FDABIOS,printf("fdcall_abios_poll: calling sleep\n"));
 1246     sleep(&rb->sleep_on_intr, PRIBIO);  /* NEEDS WORK */        
 1247     FDDEBUG(FDABIOS, printf("fdcall_abios_poll: sleep done\n"));
 1248   }
 1249 
 1250 
 1251   splx(pri);
 1252 
 1253 
 1254   /*  Any errors will be found on interrupt level and passed 
 1255    * back to use through req_errno.
 1256    */
 1257 
 1258   rc = rb->req_errno;
 1259 
 1260   pri = splfd();
 1261   rb->state &= ~FD_RB_SYNC;     /* done with sync reqest */
 1262   fdp->open_check = FALSE;      /* make sure this gets set off */
 1263 
 1264   /*  If the caller wants is to schedule more jobs, and the request
 1265    * passed then try schedule a job.  If the request failed then
 1266    * fdexecute_command() will end up calling fd_sched() for us.
 1267    */
 1268 
 1269   if ( (sched == TRUE) && (rc == FDSUCCESS) )
 1270     fd_sched(fdp);              /* look for additional requests */
 1271 
 1272   splx(pri);
 1273 
 1274   FDDEBUG(FDABIOS, printf("fdcall_abios_poll: done\n"));
 1275 
 1276   return (rc);
 1277 }
 1278 
 1279 /*  Calls ABIOS (abios_common_start() is used).  Sets up a watchdog
 1280  * timer to watch for losing interrupts.  Also sets up for the first
 1281  * first stage on time by scheduling a stage on time "interrupt".
 1282  */
 1283 static int
 1284 fdcall_abios(abios_function, rb)
 1285      int abios_function;
 1286      register struct Fd_request *rb;
 1287 {
 1288   FDDEBUG(FDABIOS, printf("fdcall_abios: function 0x%x (%s)\n", abios_function,       ABIOS_FUNCTION_NAME(abios_function)));
 1289 
 1290   rb->r_function = abios_function;
 1291   rb->r_return_code = ABIOS_UNDEFINED;
 1292   rb->state |= FD_RB_STARTED;
 1293 
 1294   abios_common_start(rb, fdadapter.fd_flag);
 1295 
 1296   FDDEBUG(FDABIOS, {
 1297       printf("[start_rw] RET abios_common_start... status=%x [", rb->r_return_code);
 1298         fd_error_decode(rb->r_return_code, "]\n");});
 1299 
 1300   /*  Schedule a pseudeo interrupt if ABIOS tells us to wait.
 1301    */
 1302 
 1303 
 1304   if (rb->r_return_code == ABIOS_STAGE_ON_TIME) {
 1305     FDDEBUG(FDABIOS,printf("fdcall_abios: ABIOS_STAGE_ON_TIME(%d)\n",
 1306                            fd_wait_time(rb)));
 1307 
 1308     timeout(fd_stot,(caddr_t)NULL,us2tics(fd_wait_time(rb)));
 1309   }
 1310 
 1311   /*  If this operation does not return immediatly, it will set
 1312    * r_time_out.  Set a watchdog for the proper # of seconds
 1313    * incase this operation does not complete.
 1314    */
 1315 
 1316   if (rb->r_time_out != 0) {
 1317     fdadapter.int_wd.time = (rb->r_time_out >> 3) * HZ;
 1318     fdadapter.int_wd.fdp = &floppies[fdadapter.fd_req.r_unit];
 1319     TIMEOUT(fdadapter.int_wd);
 1320   }
 1321 
 1322   FDDEBUG(FDABIOS, printf("fdcall_abios: done\n"));
 1323   return(FDSUCCESS);
 1324 }
 1325 
 1326 /*  Does some front/back end processing for fdissue_command().
 1327  *
 1328  *  Calls fdissue_command() and arranges for proper scheduling of further
 1329  * jobs after that request is done.
 1330  */
 1331 static int 
 1332 fdexecute_command(fdp, arg)
 1333      register struct floppy *fdp;
 1334      int arg;
 1335 {
 1336   int sched_needed;             /* schedule flag */
 1337   int pri;                      /* for i_* */
 1338   int rc;
 1339 
 1340   /*  This is a safty catch.  It is assumed that the job calling
 1341    * fdexecute_command() has gotten access to the controller.
 1342    */
 1343   assert(fdadapter.fdintr_status == FDBUSY);
 1344 
 1345   rc = fdissue_command(fdp, arg);
 1346 
 1347   if (rc == FDSUCCESS) {
 1348     switch (arg) {
 1349     case FDABIOS_INIT:
 1350     case FDREAD_PARMS:
 1351     case FDRMEDIA_PARMS:
 1352     case FDLOAD_144:
 1353     case FDLOAD_720:
 1354     case FDLOAD_360:
 1355     case FD_SETDP_POLL:
 1356       /*  For commands that poll and need to read data
 1357        * out of the request block, we must schedule
 1358        * the pending requests.
 1359        */
 1360       sched_needed = TRUE;
 1361       break;
 1362 
 1363     default:
 1364       sched_needed = FALSE;
 1365       break;
 1366     }
 1367   }
 1368   else {
 1369     /*  A schedule is not on polled requests that fail.  All
 1370      * non-polled requests return FDSUCCESS always.
 1371      */
 1372     sched_needed = TRUE;
 1373   }
 1374 
 1375   /*  If we have a status of free, check to see if there are any
 1376    * requests to do, and if so, do start them up.
 1377    */
 1378   pri = splfd();
 1379   if (sched_needed == TRUE)
 1380     fd_sched(fdp);
 1381   splx(pri);
 1382 
 1383   return (rc);
 1384 }
 1385 
 1386 /*  Sets up the floppy structure for i/o and calls fdstartio. This routine
 1387  * translates the starting block of a read or write into the cylinder,
 1388  * head, sector address required by the controller.  It then computes
 1389  * the total number of reads or writes needed and initializes the fields
 1390  * in the floppy structure that are used to execute a read or write. 
 1391  *
 1392  * NOTES: This routine is called once for each buf struct processed.  It is
 1393  * called by both fdstrategy() and fdintr() to initiate a new i/o sequence
 1394  * for a given buf struct. 
 1395  */
 1396 static void 
 1397 fdio(bp)
 1398      register struct buf *bp;
 1399 {
 1400   register struct floppy *fdp;
 1401   u_char drive;
 1402   daddr_t last_block;
 1403 
 1404   drive = fd_drive(bp->b_dev);
 1405   fdp = &floppies[drive];
 1406   FDDEBUG(FDCMD, printf("fdio: start io drive %d\n", drive));
 1407 
 1408   /* See if a request goes past the end of the diskette.
 1409    */
 1410   last_block = bp->b_blkno + (bp->b_bcount / fdp->bytes_per_sector);
 1411 
 1412   fdp->modified_bcount = bp->b_bcount;  /* cnt for this transfer */
 1413 
 1414   if (last_block > fdp->number_of_blocks) {
 1415     /* Request starts before the end of the diskette but
 1416      * runs over the end. Set up to do a partial data transfer
 1417      * and return the number of bytes not transferred in the
 1418      * b_resid field. 
 1419      */
 1420     FDDEBUG(FDCMD, printf("fdio: truncated request\n"));
 1421 
 1422     bp->b_resid =       (last_block - fdp->number_of_blocks) *
 1423       fdp->bytes_per_sector;
 1424     fdp->modified_bcount -= bp->b_resid;
 1425   }
 1426 
 1427   /* initialize io counters */
 1428   fdp->buf_offset = 0;
 1429   fdp->sectors_done = 0;
 1430   fd_clear_retry(fdp);
 1431 
 1432   /*  Set up the transfer with fdsetup_transfer, and if this
 1433    * succeeds, then actually start the transfer.
 1434    */
 1435   if (fdsetup_transfer(fdp))
 1436     fdstartio(fdp);
 1437 
 1438   return;
 1439 }
 1440 
 1441 /*  Takes an fdp, and sets the transfer in terms of what AIBOS understands.
 1442  * Mainly this is converting an offset into a physical address on the
 1443  * diskette.
 1444  *
 1445  *  We also have to check for splitting transfers that would encompass
 1446  * multiple heads.  Another thing we do is set up the request block which
 1447  * includes using pmap_extract() to get the physical address.
 1448  */
 1449 static int
 1450 fdsetup_transfer(fdp)
 1451      register struct floppy *fdp;
 1452 {
 1453   daddr_t blkno;
 1454   u_char cyl;
 1455   u_char head;
 1456   u_char sect;
 1457   u_short sectors_left;
 1458   u_short temp;
 1459   int msize;                    /* maximum size of transfer */
 1460   u_int paddr;
 1461   u_int vaddr;
 1462 
 1463   /*  Calculate blkno of transfer as where we were suppost to 
 1464    * start plus where we currently are.
 1465    */
 1466   blkno = (daddr_t) fdp->headptr->b_blkno + fdp->sectors_done;
 1467 
 1468   /* Translate block number into physical address. 
 1469    */
 1470   FDDEBUG(FDCMD, printf("fdio: start block is #%d\n", blkno));
 1471   cyl = fdp->start.cylinder = blkno / fdp->sectors_per_cylinder;
 1472   temp = blkno % fdp->sectors_per_cylinder;
 1473   head = fdp->start.head = temp / fdp->sectors_per_track;
 1474   sect = fdp->start.sector = (temp % fdp->sectors_per_track) + 1;
 1475 
 1476   /* Set up the other fields in 'floppy' that are used for keeping
 1477    * track of reads and writes. 
 1478    */
 1479   fdp->start_block = blkno;
 1480   fdp->sector_count = fdp->modified_bcount / fdp->bytes_per_sector;
 1481 
 1482   /* compute number of sectors to r/w from starting cylinder
 1483    */
 1484   sectors_left = fdp->sectors_per_cylinder - head *
 1485     fdp->sectors_per_track - sect + 1;
 1486 
 1487   /*  If a read requires of multiple sectors goes onto another cylinder
 1488    * then we have to split it into multiple requests.
 1489    */
 1490   if (sectors_left < fdp->sector_count) {
 1491     FDDEBUG(FDCMD, printf("fdsetup_transfer: multiple requests!!\n"));
 1492 
 1493     fdp->transfer_split = TRUE;
 1494     fdp->start.transfer_length = sectors_left * fdp->bytes_per_sector;
 1495   }
 1496   else {
 1497     fdp->start.transfer_length = fdp->modified_bcount;
 1498     fdp->transfer_split = FALSE;
 1499   }
 1500 
 1501   /* Check to see if transfer crosses a page boundry.  If so we
 1502    * need to split it into multiple transfers.  Also set up both
 1503    * the virtual and physical pointers for the ABIOS call.
 1504    */
 1505   vaddr = (u_int) fdp->headptr->b_un.b_addr + fdp->buf_offset;
 1506   msize = d_max_page(fdp->headptr, vaddr, &paddr, fdp->start.transfer_length);
 1507   fd_data_ptr_1(&fdadapter.fd_req) = vaddr;
 1508   fd_data_ptr_2(&fdadapter.fd_req) = paddr;
 1509 
 1510   if (msize < fdp->start.transfer_length) {
 1511     FDDEBUG(FDCMD,printf("fdsetup_transfer: split for page!\n"));
 1512 
 1513     if (!msize) {
 1514       fdiodone(fdp->headptr,&fdadapter.fd_req,fdp,EIO);
 1515       return(0);
 1516     }
 1517 
 1518     fdp->transfer_split = TRUE;
 1519     fdp->start.transfer_length = msize;
 1520   }
 1521 
 1522   return(1);
 1523 }
 1524 
 1525 /*  Builds a command for ABIOS, and then calls the ABIOS interface routines.
 1526  *
 1527  *  This should only be called when you have the FDBUSY flag set for you
 1528  * job.  Currently only fdexecute_command() and fdcommon_intr() call this.
 1529  */
 1530 static int 
 1531 fdissue_command(fdp, arg)
 1532      register struct floppy *fdp;
 1533      int arg;
 1534 {
 1535   int rc = FDSUCCESS;
 1536   register struct Fd_request *fdreq;
 1537   u_char drive_number;
 1538   int poll = arg & FDABIOS_POLL;        /* save poll status */
 1539 
 1540   arg &= ~FDABIOS_POLL;         /* make it transparent to switch */
 1541 
 1542   /* Set up:
 1543    *    - reset timeout flag.
 1544    *    - stop previous motor watchdog timer.
 1545    *    - get local copies of the adapter pointer and the driveno
 1546    */
 1547   fdp->timeout_flag = FALSE;
 1548   UNTIMEOUT(fdadapter.mot_wd);
 1549   fdreq = &fdadapter.fd_req;
 1550   drive_number = fd_drive(fdp->device_number);
 1551 
 1552   switch (arg) {
 1553   case FDABIOS_INIT:
 1554     /*  Does the first few ABIOS calls to initialize the 
 1555      * request block, and find a little bit of info about
 1556      * the adapter.  This is the first thing that should
 1557      * be called for ABIOS, and before i_init() is done.
 1558      *
 1559      *  ie fdintr() must not be called till after this
 1560      * done.  Nothing here will cause an interrupt.
 1561      */
 1562     FDDEBUG(FDCMD, printf("FDABIOS_INIT: entering...\n"));
 1563 
 1564     fdadapter.fd_flag = 0;
 1565     fdreq->state = FD_RB_IDLE;
 1566     fdreq->sleep_on_intr = 0;   /* NEEDS WORK -- sleep on? */
 1567 
 1568     /* First we have to set up the initial request block,
 1569      * and call "Return Logical ID parameters" in order
 1570      * to get info for future ABIOS calls.
 1571      */
 1572 
 1573     FD_SET_RESERVED_ABIOS_LOGICAL_PARAMETER(fdreq);
 1574 
 1575     fdreq->r_current_req_blck_len = sizeof(struct Fd_request);
 1576     fdreq->r_logical_id = abios_next_LID(FD_ID,2);
 1577     fdreq->r_unit = 0;
 1578     fdreq->request_header.Request_Block_Flags = 0; /* ABIOS32 */
 1579     fdreq->request_header.ELA_Offset = 0;
 1580     fd_no_retry(fdp);
 1581 
 1582     rc = fdcall_abios_poll(ABIOS_LOGICAL_PARAMETER, fdreq, FALSE);
 1583 
 1584     if (rc != FDSUCCESS)
 1585       break;
 1586 
 1587     /*  Note:  We don't have to do an fdget_adapter() here
 1588      * because the above call will not reschedule the floppy
 1589      * adapter, and the FDBUSY flag will not get turned off.
 1590      */
 1591 
 1592     /* update certain fields based on what abios just told us
 1593      *  1) use the real block length
 1594      *  2) logical .vs. physical ptr 
 1595      *  3) hardware interrupt level
 1596      *  4) # of drives on the adapter
 1597      */
 1598     fdreq->r_current_req_blck_len = fdreq->r_request_block_length;
 1599     fdadapter.fd_flag = fdreq->r_logical_id_flags;
 1600     fdadapter.fd_intl = fdreq->r_hardware_intr;
 1601     fdadapter.fd_numd = fdreq->r_number_units;
 1602 
 1603     /* We need to make this call before ABIOS_RESET inorder
 1604      * to get the motor_off_delay
 1605      */
 1606     
 1607     FD_SET_RESERVED_ABIOS_READ_PARAMETER(fdreq);
 1608     fdreq->r_unit = 0;
 1609     fd_no_retry(fdp);
 1610 
 1611     rc = fdcall_abios_poll(ABIOS_READ_PARAMETER, fdreq, FALSE);
 1612 
 1613     fdadapter.motor_off_delay = fd_motor_off_delay_time(fdreq);
 1614     /* rc falls through */
 1615     break;
 1616 
 1617   case FDABIOS_RESET:
 1618     /*  This does an ABIOS_RESET on the diskette system which
 1619      * basically gets the adapter set up.  This should
 1620      * be the 2nd thing called when initializing the adapter.
 1621      * First FDABIOS_INIT should be called.
 1622      */
 1623     FDDEBUG(FDCMD, printf("FDABIOS_RESET: entering...\n"));
 1624 
 1625     FD_SET_RESERVED_ABIOS_RESET(fdreq);
 1626     fdreq->r_unit = fd_drive(fdp->device_number);
 1627     fd_no_retry(fdp);
 1628 
 1629     rc = fdcall_abios_poll(ABIOS_RESET, fdreq, TRUE);
 1630     /* rc falls through */
 1631     break;
 1632 
 1633   case FDREAD_PARMS:
 1634     /*  This does a "Read Device Parameters" ABIOS call
 1635      * inorder to populate the floppy structure with what
 1636      * ABIOS thinks the values should be.
 1637      */
 1638     FDDEBUG(FDCMD, printf("FDREAD_PARMS: entering...\n"));
 1639 
 1640     FD_SET_RESERVED_ABIOS_READ_PARAMETER(fdreq);
 1641     fdreq->r_unit = fd_drive(fdp->device_number);
 1642     fd_no_retry(fdp);
 1643 
 1644     rc = fdcall_abios_poll(ABIOS_READ_PARAMETER, fdreq, FALSE);
 1645     if (rc != FDSUCCESS)
 1646       break;
 1647 
 1648     switch(fd_drive_type(fdreq)) {
 1649     case FD_NO_DRIVE:
 1650       rc = EIO;
 1651       break;
 1652     case FD_360_KB_DRIVE:
 1653       fdp->drive_type = D_48;
 1654       break;
 1655     case FD_1440_KB_DRIVE:
 1656       fdp->drive_type = D_135H;
 1657       break;
 1658     default:
 1659       fdlog_error(fdp,FD_UNSUP_DRIVE);
 1660       rc = EIO;
 1661       break;
 1662     }
 1663 
 1664     switch (fdp->e_bytesps = fd_bytes_per_sector(fdreq)) {
 1665     case FD_256_BYTE_PER_SECTOR:
 1666       fdp->bytes_per_sector = 256;
 1667       break;
 1668     case FD_512_BYTE_PER_SECTOR:
 1669       fdp->bytes_per_sector = 512;
 1670       break;
 1671     default:
 1672       fdlog_error(fdp,FD_UNSUP_SECT);
 1673       rc = EIO;
 1674     }
 1675 
 1676     /* Move info from request block to the fdp
 1677      */
 1678     fdp->sectors_per_track = fd_sectors_per_track(fdreq);
 1679     fdp->abios_flags = fd_dev_ctrl_flag(fdreq);
 1680     fdp->motor_start = fd_motor_start_delay_time(fdreq);
 1681     fdp->cylinders_per_disk = fd_num_of_cylinders(fdreq);
 1682     fdp->tracks_per_cylinder = fd_num_of_heads(fdreq);
 1683     fdp->fill_byte = fd_format_fill_byte(fdreq);
 1684     fdp->head_settle_time = fd_head_settle_time(fdreq);
 1685     fdp->gap = fd_rwv_gap_len(fdreq);
 1686     fdp->format_gap = fd_format_gap_len(fdreq);
 1687     fdp->data_length = fd_data_len(fdreq);
 1688 
 1689 
 1690     /* Calculate the rest of the fdp values:
 1691      */
 1692     fdp->number_of_blocks = fdp->sectors_per_track *
 1693       fdp->cylinders_per_disk * fdp->tracks_per_cylinder;
 1694     fdp->sectors_per_cylinder = fdp->sectors_per_track *
 1695       fdp->tracks_per_cylinder;
 1696     break;
 1697 
 1698   case FDRMEDIA_PARMS:
 1699     /*  This will report the media parameters used for the
 1700      * the last r/w/format. 
 1701      */
 1702     FDDEBUG(FDCMD, printf("FDRMEDIA_PARMS: entering...\n"));
 1703 
 1704     FD_SET_RESERVED_ABIOS_FD_READ_MEDIA_TYPE(fdreq);
 1705     fdreq->r_unit = fd_drive(fdp->device_number);
 1706     fd_no_retry(fdp);
 1707 
 1708     rc = fdcall_abios_poll(ABIOS_FD_READ_MEDIA_TYPE, fdreq, FALSE);
 1709     if (rc != FDSUCCESS)
 1710       break;
 1711 
 1712     /* Convert ABIOS return to a real value
 1713      */
 1714     switch (fdp->e_bytesps = fd_bytes_per_sector(fdreq)) {
 1715     case FD_256_BYTE_PER_SECTOR:
 1716       fdp->bytes_per_sector = 256;
 1717       break;
 1718     case FD_512_BYTE_PER_SECTOR:
 1719       fdp->bytes_per_sector = 512;
 1720       break;
 1721     default:
 1722       fdlog_error(fdp,FD_UNSUP_SECT);
 1723       rc = EIO;
 1724     }
 1725 
 1726     /* On the PS/2 the 5 1/4" adapter is 250 KBPS.  all the
 1727      * other adapters are 500 KBPS.
 1728      */
 1729     fdp->data_rate = (minor(fdp->device_number) & FD_5)
 1730       ? FD250KBPS : FD500KBPS;
 1731 
 1732     /* Move data from request block into fdp
 1733      */
 1734     fdp->sectors_per_track = fd_sectors_per_track(fdreq);
 1735     fdp->cylinders_per_disk = fd_num_of_cylinders(fdreq);
 1736     fdp->tracks_per_cylinder = fd_num_of_heads(fdreq);
 1737     fdp->gap = fd_rwv_gap_len(fdreq);
 1738     fdp->format_gap = fd_format_gap_len(fdreq);
 1739     fdp->data_length = fd_data_len(fdreq);
 1740 
 1741     fdp->number_of_blocks = fdp->sectors_per_track *
 1742       fdp->cylinders_per_disk * fdp->tracks_per_cylinder;
 1743     fdp->sectors_per_cylinder = fdp->sectors_per_track *
 1744       fdp->tracks_per_cylinder;
 1745 
 1746     /*  Now see if the values returned by the read media type
 1747      * agree with the minor we're opened under.  If they do,
 1748      * then everything is fine, otherwise return an appropriate
 1749      * errno.
 1750      */
 1751     switch (minor(fdp->device_number) & ~FDDRIVEMASK) {
 1752     case FD_GENERIC | FD_3:
 1753     case FD_GENERIC | FD_5:
 1754       /*  We don't have to check because by giving the
 1755        * generic minor, we agree to use what the drive
 1756        * tells us.
 1757        */
 1758       break;
 1759     case FD_3H:
 1760       if (fdp->number_of_blocks != 2880)
 1761         rc = EIO;
 1762       break;
 1763     case FD_3L:
 1764       if (fdp->number_of_blocks != 1440)
 1765         rc = EIO;
 1766       break;
 1767     case FD_5L:
 1768       if (fdp->number_of_blocks != 720)
 1769         rc = EIO;
 1770       break;
 1771     case FD_5H:
 1772     default:
 1773       fdlog_error(fdp,FD_UNSUP_MINOR);
 1774       rc = EINVAL;
 1775       break;
 1776     }
 1777 
 1778     /*  Lastly we want to set the diskette_type field.  We
 1779      * already know the disk_type.  This will tell us how
 1780      * the media in the diskette is formatted.
 1781      */
 1782     switch (fdp->number_of_blocks) {
 1783     case 720:           /* 360K 5 1/4" */
 1784       fdp->diskette_type = FD360_5;
 1785       break;
 1786     case 1440:          /* 720K 3 1/2" */
 1787       fdp->diskette_type = FD720_3;
 1788       break;
 1789     case 2880:          /* 144M 3 1/2" */
 1790       fdp->diskette_type = FD1440_3;
 1791       break;
 1792     default:
 1793       fdlog_error(fdp,FD_UNSUP_DRIVE);
 1794       rc = EINVAL;
 1795     }
 1796 
 1797     break;
 1798 
 1799   case FDLOAD_144:
 1800   case FDLOAD_720:
 1801   case FDLOAD_360:
 1802     /* These are dummy commands that do not use ABIOS, but
 1803      * make the setting of drive parameters easier because
 1804      * we can use a consistant interface.
 1805      */
 1806     {
 1807       int off = arg & ~0x100;
 1808 
 1809       /* Copy the data from the array to the fdp
 1810        */
 1811       fdp->sectors_per_track = fd_data[off].sectors;
 1812       fdp->cylinders_per_disk = fd_data[off].cylinders;
 1813       fdp->tracks_per_cylinder = fd_data[off].heads;
 1814       fdp->gap = fd_data[off].gap;
 1815       fdp->format_gap = fd_data[off].format_gap;
 1816       fdp->data_length = fd_data[off].data_len;
 1817 
 1818       fdp->number_of_blocks = fdp->sectors_per_track *
 1819         fdp->cylinders_per_disk * fdp->tracks_per_cylinder;
 1820       fdp->sectors_per_cylinder = fdp->sectors_per_track *
 1821         fdp->tracks_per_cylinder;
 1822     }
 1823     break;
 1824 
 1825   case FDREAD_DATA:
 1826     /*  This reads data off the diskette.  It finishes setting
 1827      * up the the request block and then calls the ABIOS 
 1828      * proper ABIOS interface (polled, or non-polled).
 1829      *
 1830      *  The data pointers should be set up before this is
 1831      * called.
 1832      *
 1833      * NOTE: the retry count is controlled by fdio().
 1834      */
 1835     FDDEBUG(FDCMD, printf("fdissue_command: READ_DATA\n"));
 1836 
 1837     FD_SET_RESERVED_ABIOS_READ(fdreq);
 1838     fdreq->r_unit = fd_drive(fdp->device_number);
 1839 
 1840     fd_num_sector_rw(fdreq) = fdp->start.transfer_length /
 1841       fdp->bytes_per_sector;
 1842     fd_cylinder_num(fdreq) = fdp->start.cylinder;
 1843     fd_head_num(fdreq) = fdp->start.head;
 1844     fd_sector_num(fdreq) = fdp->start.sector;
 1845 
 1846     FDDEBUG(FDCMD, printf("vaddr: %x\n",fd_data_ptr_1(fdreq)));
 1847     FDDEBUG(FDCMD, printf("paddr: %x\n",fd_data_ptr_2(fdreq)));
 1848     FDDEBUG(FDCMD, printf("# sectors: %d\n",
 1849                           fdp->start.transfer_length / fdp->bytes_per_sector));
 1850     FDDEBUG(FDCMD, printf("cylinder: %d\n",fdp->start.cylinder));
 1851     FDDEBUG(FDCMD, printf("head: %d\n",fdp->start.head));
 1852     FDDEBUG(FDCMD, printf("sector: %d\n",fdp->start.sector));
 1853 
 1854     rc = (poll)         ? fdcall_abios_poll(ABIOS_READ,fdreq, TRUE)
 1855                         : fdcall_abios(ABIOS_READ, fdreq);
 1856     break;
 1857 
 1858   case FDWRITE_DATA:
 1859     /*  This writes data to the diskette.  It finishes setting
 1860      * up the the request block and then calls the ABIOS 
 1861      * proper ABIOS interface (polled, or non-polled).
 1862      *
 1863      *  The data pointers should be set up before this is
 1864      * called.
 1865      *
 1866      * NOTE: the retry count is controlled by fdio().
 1867      */
 1868     FDDEBUG(FDCMD, printf("fdissue_command: WRITE_DATA\n"));
 1869 
 1870     FD_SET_RESERVED_ABIOS_READ(fdreq);
 1871     fdreq->r_unit = fd_drive(fdp->device_number);
 1872     fd_num_sector_rw(fdreq) = fdp->start.transfer_length /
 1873       fdp->bytes_per_sector;
 1874     fd_cylinder_num(fdreq) = fdp->start.cylinder;
 1875     fd_head_num(fdreq) = fdp->start.head;
 1876     fd_sector_num(fdreq) = fdp->start.sector;
 1877 
 1878     FDDEBUG(FDCMD, printf("vaddr: %x\n",fd_data_ptr_1(fdreq)));
 1879     FDDEBUG(FDCMD, printf("paddr: %x\n",fd_data_ptr_2(fdreq)));
 1880     FDDEBUG(FDCMD, printf("# sectors: %d\n",
 1881                           fdp->start.transfer_length / fdp->bytes_per_sector));
 1882     FDDEBUG(FDCMD, printf("cylinder: %d\n",fdp->start.cylinder));
 1883     FDDEBUG(FDCMD, printf("head: %d\n",fdp->start.head));
 1884     FDDEBUG(FDCMD, printf("sector: %d\n",fdp->start.sector));
 1885     
 1886     rc = (poll) ? fdcall_abios_poll(ABIOS_WRITE, fdreq, TRUE)
 1887                 : fdcall_abios(ABIOS_WRITE, fdreq);
 1888     break;
 1889 
 1890   case FDMOTOR_OFF:
 1891     /*  This does an ABIOS request to turn the motor (and
 1892      * the light) for the drive off.
 1893      */
 1894     FD_SET_RESERVED_ABIOS_FD_TURN_OFF_MOTOR(fdreq);
 1895     fdreq->r_unit = fd_drive(fdp->device_number);
 1896     fd_no_retry(fdp);
 1897 
 1898     rc = fdcall_abios_poll(ABIOS_FD_TURN_OFF_MOTOR, fdreq, TRUE);
 1899     /* RC Falls through to break */
 1900 
 1901     /*  fdcall_abios_poll() will call fdsched() {like it shoud}
 1902      * and restart the motor watchdog.
 1903      */
 1904     UNTIMEOUT(fdadapter.mot_wd);
 1905     break;
 1906 
 1907   case FDFORMAT_TRACK:
 1908     /*  This does and ABIOS request to format a track.  It
 1909      * has to create an xmem descriptor and get the physical
 1910      * address of the format information.
 1911      *
 1912      *  It fills in the request block and does the format
 1913      * to how the drive was set up (high or low, etc).
 1914      */
 1915     FDDEBUG(FDCMD,"fdissue_command: FDFORMAT_TRACK\n");
 1916 
 1917     FD_SET_RESERVED_ABIOS_FD_SET_MEDIA_TYPE(fdreq);
 1918     fdreq->r_unit = fd_drive(fdp->device_number);
 1919 
 1920     fd_sectors_per_track(fdreq) = fdp->sectors_per_track;
 1921     fd_bytes_per_sector(fdreq) = fdp->e_bytesps;
 1922     fd_num_of_cylinders(fdreq) = fdp->cylinders_per_disk;
 1923     fd_format_fill_byte(fdreq) = fdp->fill_byte;
 1924     fd_format_gap_len(fdreq) = fdp->format_gap;
 1925 
 1926     fd_no_retry(fdp);           /* don't try again */
 1927 
 1928     rc = fdcall_abios_poll(ABIOS_FD_SET_MEDIA_TYPE, fdreq, FALSE);
 1929     if (rc != FDSUCCESS) {
 1930       break;
 1931     }
 1932 
 1933     fd_xfer_sub_function(fdreq) = FD_XFER_SUB_FORMAT;
 1934     fd_cylinder_num(fdreq) = fdp->cylinder_id;
 1935     fd_head_num(fdreq) = fdp->head_id;
 1936 
 1937     fd_clear_retry(fdp);                /* retry this request */
 1938 
 1939     rc = (poll) ? fdcall_abios_poll(ABIOS_ADDITIONAL_XFER, fdreq, TRUE)
 1940                 : fdcall_abios(ABIOS_ADDITIONAL_XFER, fdreq);
 1941 
 1942     break;
 1943 
 1944   case FDDISK_SAME:
 1945     /*  Check to see if the Change signal is high.  In order
 1946      * to return a value w/o using the fdp structure, we use
 1947      * two return codes that are > 0, and will look like
 1948      * errors.  fdexecute_command() will see the error and
 1949      * try to schedule more work for the diskette adapter
 1950      * to do.
 1951      *
 1952      *  Note that we first check to see if the change signal
 1953      * is supported.  If it is not supported with the current
 1954      * drive, then we just say the diskette is the same.
 1955      */
 1956     if (!(fdp->abios_flags & FD_CHANGE_SIGNAL_AVAIL)) {
 1957       rc = DISK_SAME;
 1958       break;
 1959     }
 1960 
 1961     FD_SET_RESERVED_ABIOS_FD_CHANGE_SIGNAL_STATUS(fdreq);
 1962     fdreq->r_unit = fd_drive(fdp->device_number);
 1963                 
 1964     fdcall_abios_poll(ABIOS_FD_CHANGE_SIGNAL_STATUS,fdreq,FALSE);
 1965 
 1966     /*  If the diskette changed signal is high report it.  If
 1967      * no say the diskette is the same, even though this drive
 1968      * may not support it.
 1969      */
 1970     if (fd_change_signal_status(fdreq) == FD_CHANGE_SIGNAL_ACTIVE)
 1971       rc = DISK_CHANGED;
 1972     else
 1973       rc = DISK_SAME;
 1974     break;
 1975 
 1976   case FD_SETDP:
 1977     /*  This call does a "Set Device Parameters" ABIOS call
 1978      * and is used by the one of the ioctl()'s.
 1979      */
 1980     FD_SET_RESERVED_ABIOS_WRITE_PARAMETER(fdreq);
 1981     fd_bytes_per_sector(fdreq) = fdp->e_bytesps;
 1982     fd_rwv_gap_len(fdreq) = fdp->gap;
 1983     fd_data_len(fdreq) = fdp->data_length;
 1984 
 1985     fdreq->r_unit = fd_drive(fdp->device_number);
 1986 
 1987     rc = fdcall_abios_poll(ABIOS_WRITE_PARAMETER, fdreq, FALSE);
 1988 
 1989     if (rc == FDSUCCESS) {
 1990       switch(fdp->e_bytesps) {
 1991       case FD_256_BYTE_PER_SECTOR:
 1992         fdp->bytes_per_sector = 256;
 1993         break;
 1994       case FD_512_BYTE_PER_SECTOR:
 1995         fdp->bytes_per_sector = 512;
 1996         break;
 1997       default:
 1998         fdlog_error(fdp,FD_UNSUP_SECT);
 1999         rc = EIO;
 2000       }
 2001     }
 2002     break;
 2003 
 2004   case FD_SETMT:
 2005     /*  This call does a "Set Media Type for Format" ABIOS call
 2006      * and is used by one of the ioctl's.  It is done at this
 2007      * time instead of waiting till a format occurs to make
 2008      * sure the data given is valid.
 2009      */
 2010     FD_SET_RESERVED_ABIOS_FD_SET_MEDIA_TYPE(fdreq);
 2011     fd_sectors_per_track(fdreq) = fdp->sectors_per_track;
 2012     fd_bytes_per_sector(fdreq) = fdp->e_bytesps;
 2013     fd_num_of_cylinders(fdreq) = fdp->cylinders_per_disk;
 2014     fd_format_fill_byte(fdreq) = fdp->fill_byte;
 2015     fd_format_gap_len(fdreq) = fdp->format_gap;
 2016     
 2017     fdreq->r_unit = fd_drive(fdp->device_number);
 2018 
 2019     rc = (poll) ? fdcall_abios_poll(ABIOS_FD_SET_MEDIA_TYPE,fdreq,TRUE)
 2020                 : fdcall_abios(ABIOS_FD_SET_MEDIA_TYPE, fdreq);
 2021     break;
 2022 
 2023   default:
 2024     FDDEBUG(FDCMD, printf("fdissue_command: unknown command\n"));
 2025     rc = EINVAL;
 2026     break;
 2027   }
 2028   return (rc);
 2029 }
 2030 
 2031 /*  Handles the diskette timer exceptions. This routine is called when
 2032  * when a watchdog timer pops.  It then determines the proper actions to
 2033  * take and does them. 
 2034  *
 2035  *  There are 2 types of watchdogs.  There is one to turn the motor off,
 2036  * and one for lost interrupts.  The motor timer is easy, but the interrupt
 2037  * timer is harder because it can mean different things depending on the
 2038  * state of the drive, and the type of drive.
 2039  *
 2040  * NEEDS WORK: IS THE FOLLOWING STILL NEEDED, AND/OR TRUE WITH OSF?
 2041  * NOTES: It is assumed that the interrupt level when the timer pops will
 2042  * splfd().
 2043  */
 2044 void 
 2045 fdtimer(timer)
 2046      register struct fdwatchdog *timer;
 2047 {
 2048   register struct floppy *fdp;
 2049   int rc;
 2050 
 2051   switch (timer->type) {
 2052   case FDINT_WD:
 2053     /*  In this case an ABIOS request that should have finished
 2054      * did not within the recommended timeout.  We log the
 2055      * error, and then try to keep going...
 2056      */
 2057     FDDEBUG(FDCMD,printf("interrupt watchdog!\n"));
 2058     fdp = fdadapter.int_wd.fdp;
 2059 
 2060     /*  We need to finish up with the request block early
 2061      * incase we have to do any ABIOS calls later.
 2062      */
 2063     rc = fdadapter.fd_req.r_return_code;
 2064     abios_common_timeout(&fdadapter.fd_req, fdadapter.fd_flag);
 2065     fdadapter.fd_req.r_return_code = rc;
 2066 
 2067     /*  If the watchdog timeout came on the 5 1/4" drive
 2068      * then it could be that the media is not present,
 2069      * because this drive cannot sense the diskette is not
 2070      * there.  Unfortunatly there is no good way to test
 2071      * this.
 2072      *
 2073      *  The best we can do is in fddoor_check() is to set
 2074      * a flag in the fdp structure, and if we get a watchdog
 2075      * on a 5 1/4" drive and the flag is set, then we return
 2076      * EIO.
 2077      *
 2078      *  The other problem encountered on the 5 1/4 is when
 2079      * doing a format, without the diskette in the drive.
 2080      * It looks like ABIOS doesn't do the reset so we do
 2081      * it ourselves.  This only happens when opening NDELAY
 2082      * since the drive isn't checked with a read.
 2083      */
 2084     if ((minor(fdp->device_number) & FD_5) && ((fdp->open_check == TRUE) ||
 2085         (fdadapter.fd_req.r_function == ABIOS_ADDITIONAL_XFER) ) ) {
 2086       fdlog_error(fdp,FD_ERR_NOMEDIA);
 2087       rc = EIO;
 2088     }
 2089     else {
 2090       /* Log timeout error. 
 2091        */
 2092       fdlog_error(fdp, FD_ERR_LOSTINT);
 2093       fdp->timeout_flag = TRUE;
 2094       rc = EIO;
 2095     }
 2096 
 2097     /*  If we need to recalibrate (5 1/4" disk) then set up and
 2098      * do the reset (note that this will do the fdiodone() for
 2099      * us.  Otherwise call fdiodone().
 2100      */
 2101     if (fdp->abios_flags & FD_RECALIBRATE_REQUIRED) {
 2102       register struct Fd_request *rb;
 2103 
 2104       rb = &fdadapter.fd_req;
 2105       rb->state |= FD_RB_RESET;
 2106       rb->req_errno = rc;
 2107       fdcall_abios(ABIOS_RESET, rb);
 2108     }
 2109     else
 2110       fdiodone(fdp->headptr, &fdadapter.fd_req, fdp, rc);
 2111 
 2112     break;
 2113 
 2114   case FDMOT_WD:
 2115     /*  Note:  In this case the light is on.  All care has
 2116      * been taken not to let the watchdog continue if this
 2117      * drive is busy.  Hence we don't (and can't sleep())
 2118      * call fdget_adapter(), and can just turn off the light.
 2119      */
 2120     FDDEBUG(FDCMD,printf("fdtimer: motor watchdog!\n"));
 2121     fdadapter.fdintr_status = FDBUSY;
 2122     fdexecute_command(fdadapter.mot_wd.fdp,FDMOTOR_OFF);
 2123     break;
 2124   }
 2125 }
 2126 
 2127 #ifdef DEBUG
 2128 #undef DEBUG_RB
 2129 #ifdef DEBUG_RB
 2130 
 2131 /*  This can be compiled in for printing out AIBOS request blocks for driver
 2132  * debugging.
 2133  */
 2134 static void
 2135 fd_dump_rb(rb)
 2136      struct Fd_request *rb;
 2137 {
 2138   register int i,j;
 2139 
 2140   printf("RB: len %d, lid %d, unit %d, func %\n",
 2141          rb->r_current_req_blck_len,
 2142          rb->r_logical_id,
 2143          rb->r_unit,
 2144          rb->r_function);
 2145   printf("flags %d, ELA %d, rc %d, timeout %d\n",
 2146          rb->request_header.Request_Block_Flags,
 2147          rb->request_header.ELA_Offset,
 2148          rb->r_return_code,
 2149          rb->r_time_out);
 2150         
 2151   for (i=0 ; i < 128 ; i += 24) {
 2152     for (j = 0 ; j < 24 ; j += 4)
 2153       printf("%02x%02x%02x%02x  ",
 2154              rb->un.uc[i+j],
 2155              rb->un.uc[i+j+1],
 2156              rb->un.uc[i+j+2],
 2157              rb->un.uc[i+j+3]);
 2158     printf("\n");
 2159   }
 2160                 
 2161   printf("state %x, sleep %x, req_errno %d\n",
 2162          rb->state, rb->sleep_on_intr, rb->req_errno);
 2163 }
 2164 #endif
 2165 #endif
 2166 
 2167 
 2168 /*  If DEBUG is on we also want to leave some hooks in to test the
 2169  * watchdog timers for losing interrupts.  To test losing an interrupt,
 2170  * have fd_inttest set to a non-zero value.
 2171  *
 2172  *  The best way to do this is to set a breakpoint in fdintr() and then
 2173  * set the flag to 1 on the interrupt you want to simulate the loss of.
 2174  *
 2175  * WARNING -- Don't forget to set this flag back to 0, or nothing works!
 2176  */
 2177 #ifdef DEBUG
 2178 #define WATCHTEST
 2179 #endif
 2180 #ifdef WATCHTEST
 2181 int fd_inttest = 0;
 2182 #endif
 2183 
 2184 /*  This is the front end to the common interrupt handler for ABIOS
 2185  * stage on time (stot) events.  When ABIOS tells us to stage on 
 2186  * time we call timeout() which will set a timer to call fd_stot()
 2187  * after the period has expired.
 2188  *
 2189  *  We call fdcommon_intr() which will query ABIOS with what to do next.
 2190  * The one parameter to this routine is a pointer to the ABIOS request
 2191  * block.
 2192  */
 2193 void
 2194 fd_stot()
 2195 {
 2196   int pri;
 2197 
 2198   FDDEBUG(FDINTR, printf("fd_stot: entering...\n"));
 2199   pri = splfd();
 2200   fdcommon_intr(&fdadapter.fd_req);
 2201   splx(pri);
 2202 }
 2203 
 2204 /*  This is the interrupt handler for the diskette controller.  It calls
 2205  * fdcommon_intr with the current ABIOS request block to do most of the
 2206  * work.  If this call corresponds to our interrupt, then we i_reset()
 2207  * it, and in either case we return the return value from fdcommon_intr().
 2208  *
 2209  * NOTES: Turn off the interrupt watchdog.
 2210  */
 2211 fdintr(fdtmp)
 2212      register struct intr *fdtmp;
 2213 {
 2214   /*  We have gotten our interrupt so turn off the timer ASAP.
 2215    */
 2216   UNTIMEOUT(fdadapter.int_wd);
 2217 
 2218   FDDEBUG(FDINTR, printf("\nfdintr: entering...\n"));
 2219 
 2220   fdcommon_intr(&fdadapter.fd_req);
 2221 
 2222   return(1);            /* return to FLIH */
 2223 }
 2224 
 2225 /*  Handles an interrupt for the floppy driver.  First we check
 2226  * to make sure we are expecting an interrupt.  If so we call
 2227  * abios_common_interrupt() to process the interrupt.  Next we
 2228  * do what abios_common_interrupt() told us to do.
 2229  *
 2230  *  When we have an ABIOS_DONE condition we call fdiodone() to terminate
 2231  * the i/o for us.
 2232  */
 2233 static int
 2234 fdcommon_intr(fdreq)
 2235      register struct Fd_request *fdreq;
 2236 {
 2237   register struct buf *bp;
 2238   register struct floppy *fdp;
 2239 
 2240   FDDEBUG(FDINTR, printf("\nfdcommon_intr: entering...\n"));
 2241 
 2242   /*  Get data structures pointing at the right place.  Note that
 2243    * the bp may be NULL if FD_RB_SYNC bit is set in the request
 2244    * block.  In anycase if FD_RB_SYNC is set the bp should not
 2245    * be used.
 2246    */
 2247   fdp = &floppies[fdreq->r_unit];
 2248   bp = fdp->headptr;
 2249 
 2250   /* Make sure we are expecting an interuupt
 2251    */
 2252   if ( (fdreq->state==FD_RB_IDLE) || (fdreq->r_return_code==ABIOS_UNDEFINED))
 2253     return(0);                  /* not me! */
 2254 
 2255   abios_common_interrupt(fdreq, fdadapter.fd_flag);
 2256   FDDEBUG(FDINTR, {
 2257           printf("fdcommon_intr: after abios_common_interrupt rc=0x%x [",
 2258                  fdreq->r_return_code);
 2259           fd_error_decode(fdreq->r_return_code, "]\n"); });
 2260 
 2261 #ifdef WATCHTEST
 2262   /* For more info about watchdog testing, see above comment.
 2263    */
 2264   if (fd_inttest) {             /* if true loose interrupt */
 2265     return(0);
 2266   }
 2267 #endif
 2268 
 2269   /*  If ABIOS_NOT_MY_INT and ABIOS_STAGE_ON_INT are both set in the
 2270    * return code from abios_common_start(), then the interrupt
 2271    * is not ours.  Return and let the slih go through the list
 2272    * of devices on this interrupt level.
 2273    */
 2274   if ( fdreq->r_return_code & (ABIOS_NOT_MY_INT & ABIOS_STAGE_ON_INT) ) {
 2275     FDDEBUG(FDINTR, printf("fdcommon_intr: ABIOS_NOT_MY_INTR\n"));
 2276     return(0);                          /* not me either! */
 2277   }
 2278 
 2279   /*  Now check the various cases of the return code and do the
 2280    * appropriate action.
 2281    */
 2282   switch (fdreq->r_return_code) {
 2283   case ABIOS_DONE:
 2284     /*  The request has completed successfully.  For read
 2285      * and write we have to update some counters, but for
 2286      * all other cases we're done.
 2287      */
 2288     FDDEBUG(FDINTR,printf("fdcommon_intr: ABIOS_DONE\n"));
 2289 
 2290     if ((fdreq->r_function == ABIOS_READ) ||
 2291         (fdreq->r_function == ABIOS_WRITE)) {
 2292 
 2293       /*  Keep track of the number of sectors moved,
 2294        * as well as updating the modified_bcount (used
 2295        * for counting the i/o on strategy requests).
 2296        */
 2297       fdp->sectors_done += fd_sectors_moved(fdreq);
 2298       fdp->modified_bcount -= fd_sectors_moved(fdreq) * fdp->bytes_per_sector;
 2299 
 2300       /* check if all sectors were moved
 2301        */
 2302       if ( fd_sectors_moved(fdreq) <
 2303           fd_num_sector_rw(fdreq) ) {
 2304         fdiodone(bp,fdreq,fdp,EIO);
 2305       }
 2306       /* Check for a split request.
 2307        *
 2308        *  A request is split if it goes from sector that
 2309        * is one head and is continued on the next head.
 2310        *
 2311        *  The other case is when the place to dma to/from
 2312        * crosses a page boundry that is not contiguous
 2313        * in physical memory.
 2314        *
 2315        * See fdsetup_transfer()
 2316        *
 2317        *  Note that the convention for polled r/w calls
 2318        * is that they will not set up split transfers,
 2319        * hence it is legal for us to call fdstartio and
 2320        * then indirect through the buf struct pointer.
 2321        */
 2322       else if (fdp->transfer_split != 0) {
 2323         FDDEBUG(FDINTR,printf("split request\n"));
 2324 
 2325         /* Update the offset so the address to
 2326          * move to can be determined correctly
 2327          */
 2328         fdp->buf_offset += fd_sectors_moved(fdreq) * fdp->bytes_per_sector;
 2329 
 2330         /*  If we have more of this transfer to do,
 2331          * then start the i/o for it.
 2332          */
 2333         if (fdsetup_transfer(fdp))
 2334           fdstartio(fdp);
 2335         break;          /* don't do fdiodone()! */
 2336       }
 2337     }
 2338 
 2339     /*  If the RESET flag is set, that means we have just
 2340      * completed a special RESET for an error condition
 2341      * (probably on the 5 1/4" drive).  Flip the RESET bit
 2342      * off and call fdiodone with the set errno.
 2343      */
 2344     if (fdreq->state & FD_RB_RESET) {
 2345       fdreq->state &= ~FD_RB_RESET;
 2346       fdiodone(bp,fdreq,fdp,fdreq->req_errno);
 2347     }
 2348     else
 2349       fdiodone(bp,fdreq,fdp,FDSUCCESS);
 2350     break;
 2351 
 2352   case ABIOS_STAGE_ON_INT:
 2353     /*  Discrete multi stages, just continue.  Eventualy
 2354      * we will get a done or some sort of errors.
 2355      */
 2356     FDDEBUG(FDINTR, printf("fdcommon_intr: ABIOS_STAGE_ON_INT\n"));
 2357     fdreq->state |= FD_RB_STAGING;
 2358     break;
 2359 
 2360   case ABIOS_STAGE_ON_TIME:
 2361     /*  In this case we want to call fd_stot in fd_wait_time()
 2362      * micro seconds.
 2363      */
 2364     FDDEBUG(FDINTR, printf("fdcommon_intr: ABIOS_STAGE_ON_TIME\n"));
 2365     timeout(fd_stot,(caddr_t)NULL,us2tics(fd_wait_time(fdreq)));
 2366     break;
 2367 
 2368   case FDABIOS_MEDIACHANGED:
 2369     /*  If this is our first request to the drive, this
 2370      * this is a retryable error (and the only way to
 2371      * clear the signal).
 2372      *
 2373      *  However, if this is not the first request for this open
 2374      * it is an error to have changed media.
 2375      */
 2376     FDDEBUG(FDINTR, printf("fdcommon_intr: FDABIOS_MEDIACHANGED\n"));
 2377 
 2378     /* to boot from floppy, have to allow media to change... */
 2379     fdissue_command(fdp,fdreq->r_function);
 2380     break;
 2381     if (fdp->fd_change == FDCHANGE_NEW) {
 2382       fdp->fd_change = FDCHANGE_INIT;
 2383       fdissue_command(fdp,fdreq->r_function);
 2384     }
 2385     else {
 2386       /* return media changed error
 2387        */
 2388       fdlog_error(fdp,FD_ERR_CHMEDIA);
 2389       fdiodone(bp,fdreq,fdp,EIO);
 2390     }
 2391     break;
 2392 
 2393   case FDABIOS_MEDIANOTPRESENT:
 2394     /*  This is an obvious error condition.
 2395      */
 2396     fdlog_error(fdp,FD_ERR_NOMEDIA);
 2397     fdiodone(bp,fdreq,fdp,EIO);
 2398     break;
 2399 
 2400   case FDABIOS_WRITEPROTECTED:
 2401     /*  The diskette was write protected and we attempted to
 2402      * do a write to it.  Return EIO (no write protected errno).
 2403      */
 2404     FDDEBUG(FDINTR,printf("fdcommon_intr: WRITE PROTECTED\n"));
 2405     fdiodone(bp,fdreq,fdp,EIO);
 2406     break;
 2407 
 2408   default:
 2409     /*  All the errors get handled here.  Retry the error.
 2410      * up to FDMAXRETRIES, and if all is still lost, return
 2411      * EIO.
 2412      */
 2413     FDDEBUG(FDINTR, printf("fdcommon_intr: error (rc=%x)\n",
 2414                            fdreq->r_return_code));
 2415 
 2416     if (fdp->retry_count < FDMAXRETRIES) {
 2417       fdp->retry_count++;
 2418       fdissue_command(fdp,fdreq->r_function);
 2419     }
 2420     else {
 2421       /*  We're out of retries, so log the error.  If
 2422        * the error is on the 5 1/4" drive reset the     
 2423        * drive.  Note that resetting the drive will
 2424        * call fdiodone for us.
 2425        */
 2426       fdlog_error(fdp,FD_ERR_RETRY);
 2427 
 2428       if (fdp->abios_flags & FD_RECALIBRATE_REQUIRED) {
 2429         fdreq->state |= FD_RB_RESET;
 2430         fdreq->req_errno = EIO;
 2431         fdcall_abios(ABIOS_RESET,fdreq);
 2432       }
 2433       else
 2434         fdiodone(bp,fdreq,fdp,EIO);
 2435     }
 2436     break;
 2437 
 2438   }
 2439 
 2440   FDDEBUG(FDINTR, printf("fdcommon_intr: done\n"));
 2441   return(1);
 2442 }
 2443 
 2444 /* NEEDS WORK - are polled interrupt abios requests still done now
 2445  * NEEDS WORK - that we call strategy to sense the media?
 2446  */
 2447 /*  Completes the i/o for the specified request.  Handles two different
 2448  * cases.  One for polled requests, and one for non-polled (from strategy)
 2449  * requests.
 2450  *
 2451  * NOTES: This should only be used after i/o has been attemped on the
 2452  * buf struct in question.  Before that time just call iodone() directly.
 2453  */
 2454 static void
 2455 fdiodone(buf,fdreq,fdp,errno)
 2456      register struct buf *buf;
 2457      register struct Fd_request *fdreq;
 2458      register struct floppy *fdp;
 2459      int errno;
 2460 {
 2461   if ( (fdreq->state & FD_RB_SYNC) || (buf == NULL) ) {
 2462     /* Polled request:
 2463      *
 2464      *  The error code is returned to the caller in req_errno.
 2465      *
 2466      *  We need to set ABIOS_DONE, so that polled requests
 2467      * will wake up even if we have an error.  req_errno is
 2468      * used to handle the error conditions.
 2469      *
 2470      *  Also note that any outstanding requests will be started
 2471      * up after the request is woken up.  It would be better to
 2472      * be able to check the queues here, and then start the
 2473      * requests, but we have to wait for the data to get back
 2474      * to the caller of the polled request.
 2475      */
 2476     FDDEBUG(FDINTR, printf("fdiodone: entering...polled\n"));
 2477     fdreq->req_errno = errno;
 2478     fdreq->r_return_code = ABIOS_DONE;
 2479     wakeup(&fdreq->sleep_on_intr);
 2480   }
 2481   else {
 2482     /* Strategy request:
 2483      *
 2484      *  This is a little more complicated than the polled
 2485      * request.  We check for errors, and for people to 
 2486      * wake up, play with the queue's and then look for
 2487      * more work to do.
 2488      *
 2489      *  Note that we can use the buf struct in this case.
 2490      */
 2491     FDDEBUG(FDINTR, printf("fdiodone: entering...intr\n"));
 2492 
 2493     /*  If this request resulted in an error, then set
 2494      * the flags in the buf struct to indicate the error.
 2495      */
 2496     if (errno) {
 2497       buf->b_resid += fdp->modified_bcount;
 2498       buf->b_flags |= B_ERROR;
 2499       buf->b_error = errno;
 2500     }
 2501     else {
 2502       /*  we have had a succesful non-polled call, so 
 2503        * note that the diskette is in ok.
 2504        */
 2505       fdp->fd_change = FDCHANGE_INIT;
 2506     }
 2507 
 2508     /*  Tally i/o counts:
 2509      *  - read_count_bytes is the number of bytes less
 2510      *  than a megabyte read.  read_count_megabytes is
 2511      *  the number of megabytes read.  By using both of
 2512      *  them together, you get an accurate #.
 2513      *
 2514      *  - write_count* is the same, but for write operations.
 2515      */
 2516     if (buf->b_flags & B_READ) {
 2517       fdp->read_count_bytes += buf->b_bcount - buf->b_resid;
 2518       if (fdp->read_count_bytes >= 0x100000) {
 2519         fdp->read_count_megabytes += fdp->read_count_bytes / 0x100000;
 2520         fdp->read_count_bytes %= 0x100000;
 2521       }
 2522     }
 2523     else {              /* B_WRITE */
 2524       fdp->write_count_bytes += buf->b_bcount - buf->b_resid;
 2525       if (fdp->write_count_bytes >= 1000000) {
 2526         fdp->write_count_megabytes += fdp->write_count_bytes / 1000000;
 2527         fdp->write_count_bytes %= 1000000;
 2528       }
 2529     }
 2530 
 2531     /* if this is the last buffer, dq everything, else
 2532      * get the next one...
 2533      */
 2534     if (fdp->headptr == fdp->tailptr) {
 2535       fdp->headptr = fdp->tailptr = NULL;
 2536 
 2537       /*  If fd_close() has been called with outstanding
 2538        * i/o on this drive the the close_waiting flag
 2539        * will be set.  We have to wake up the process
 2540        * that is waiting on the close and indicate that
 2541        * it's i/o is done.
 2542        *
 2543        *  Note that we only do this when the request
 2544        * queue is empty, and there is no more
 2545        * outstanding i/o for this drive.
 2546        */
 2547       if (fdp->close_waiting == TRUE) {
 2548         fdp->close_waiting = FALSE;
 2549         wakeup(&fdp->close_sleep);
 2550       }
 2551     }
 2552     else
 2553       fdp->headptr = fdp->headptr->av_forw;
 2554 
 2555     FDDEBUG(FDINTR,printf("fdiodone: fdp->headptr is %x\n", fdp->headptr));
 2556 
 2557     fd_sched(fdp);              /* look for more requests */
 2558     iodone(buf);                /* done with this buffer */
 2559   }
 2560 }
 2561 
 2562 /* Looks for more work for the diskette adapter to work on.
 2563  */
 2564 static void
 2565 fd_sched(fdp)
 2566      register struct floppy *fdp;
 2567 {
 2568   register struct floppy *tfdp, *lfdp;
 2569   int unit, pri;
 2570 
 2571   /*  Handle watchdog timers:
 2572    *    - Make sure the interrupt loss watchdog is off.  If we
 2573    *      are finishing a request via an interrupt it will be
 2574    *      off, but if we are doing a non interrupting ABIOS call
 2575    *      it may not.  It is low enough overhead, so we just
 2576    *      do it again.
 2577    *
 2578    *    - Start the motor off timer.  If we start another request this
 2579    *      timer will be turned off.
 2580    */
 2581   UNTIMEOUT(fdadapter.int_wd);
 2582   fdadapter.mot_wd.fdp = fdp;
 2583   TIMEOUT(fdadapter.mot_wd);
 2584 
 2585   /*  If we need the controller to process an open, give
 2586    * that presedence over other q'ed requests.  Otherwise
 2587    * go and look for other requests to do.
 2588    */
 2589   pri = splfd();
 2590   if (fdadapter.need_controller == TRUE) {
 2591     fdadapter.fdintr_status = FDFREE;
 2592     wakeup(&fdadapter.need_sleep);
 2593   }
 2594   else {
 2595     /*  Look for another request to start.  To be fair try
 2596      * the other drives first.
 2597      */
 2598     tfdp = &floppies[unit=next_unit(fdadapter.fd_req.r_unit)];
 2599     lfdp = (struct floppy *)NULL;
 2600     while (lfdp != fdp) {
 2601       if (tfdp->headptr != NULL) {
 2602         /*  Do the request, and then
 2603          * don't loop looking for more
 2604          */
 2605         fdio(tfdp->headptr);
 2606         break;
 2607       }
 2608       lfdp = tfdp;
 2609       tfdp = &floppies[next_unit(unit)];
 2610     }
 2611 
 2612     /*  If we didn't run anything new, then set the intr
 2613      * status to free and wake up any polled requests that
 2614      * want to access the adapter.
 2615      */
 2616     if (lfdp == fdp)
 2617       fdadapter.fdintr_status = FDFREE;
 2618   }
 2619   splx(pri);
 2620 }
 2621 
 2622 /*
 2623  * This does the work of an FDIOCFORMAT ioctl call. 
 2624  *
 2625  * The following ioctl operations are provided for the format
 2626  * command. 
 2627  *
 2628  * FDIOCFORMAT - formats a diskette track.  A track is
 2629  * formatted using values passed in an array of bytes
 2630  * pointed to by the 'arg' parameter.  The buffer should be
 2631  * 4 times the number of sectors per track long.  Four bytes
 2632  * of data are needed for each sector on the track.  The
 2633  * following shows the structure of the data buffer:
 2634  *                       _________________
 2635  *                      |                 |
 2636  *                      | cylinder number | - byte 0
 2637  *              S       |_________________|
 2638  *              E       |                 |
 2639  *              C       |   side number   | - byte 1
 2640  *              T       |_________________|
 2641  *              O       |                 |
 2642  *              R       |  sector number  | - byte 2
 2643  *                      |_________________|
 2644  *              0       |                 |
 2645  *                      | # bytes/sector  | - byte 3
 2646  *                      |_________________| 
 2647  *
 2648  *                              .
 2649  *                              .
 2650  *                              .
 2651  *                       _________________
 2652  *                      |                 |
 2653  *                      | cylinder number | - byte (n * 4) - 4
 2654  *              S       |_________________|
 2655  *              E       |                 |
 2656  *              C       |   side number   | - byte (n * 4) - 3
 2657  *              T       |_________________|
 2658  *              O       |                 |
 2659  *              R       | sector number   | - byte (n * 4) - 2
 2660  *                      |_________________|
 2661  *              n       |                 |
 2662  *                      | # bytes/sector  | - byte (n * 4) - 1
 2663  *                      |_________________| 
 2664  *
 2665  *    where n is the number of sectors per track.  In general,
 2666  * the cylinder number, side number, and number of bytes per
 2667  * sector should not change from sector to sector. The sector
 2668  * number should be different for each sector. Usually the
 2669  * sector numbers will correspond to the physical sector
 2670  * numbers, but they can be different if some special copy
 2671  * protection scheme is being used. 
 2672  */
 2673 #ifdef NEEDS_WORK               /* NEEDS WORK -- more ioctls..later */
 2674 static int
 2675 fd_iocformat(devno,arg,fdp)
 2676      dev_t devno;
 2677      register long arg;
 2678      register struct floppy *fdp;
 2679 {
 2680   int rc = FDSUCCESS;
 2681   caddr_t paddr;
 2682   struct Fd_request *fdreq = &fdadpter.fd_req;
 2683 
 2684   fdp->format_size = fdp->sectors_per_track * 4;
 2685 
 2686   /* allocate a page for the format info.
 2687    */
 2688   fdp->format_buffer = (char *)
 2689     xmalloc(fdp->format_size, PGSHIFT, pinned_heap);
 2690   if (fdp->format_buffer == NULL)
 2691     return(ENOMEM);
 2692 
 2693   /* pin the buffer.
 2694    */
 2695   rc = pin((caddr_t) fdp->format_buffer, (int) fdp->format_size);
 2696   if (rc != 0) {
 2697     xmfree((caddr_t) fdp->format_buffer, (caddr_t) pinned_heap);
 2698     return(rc);         /* return pin's errno */
 2699   }
 2700 
 2701   /* copy the buffer in our address space.
 2702    */
 2703   rc = copyin((char *) (arg), (char *) (fdp->format_buffer),
 2704               fdp->format_size);
 2705   if (rc == -1) {
 2706     unpin((caddr_t) fdp->format_buffer, (int) fdp->format_size);
 2707     xmfree((caddr_t) fdp->format_buffer, (caddr_t) pinned_heap);
 2708     return(EINVAL);
 2709   }
 2710 
 2711   fdp->cylinder_id = *(fdp->format_buffer);             /* byte 0 */
 2712   fdp->head_id = *((char *)(fdp->format_buffer)+1);     /* byte 1 */
 2713 
 2714   fdget_adapter();
 2715         
 2716   if ((paddr = pmap_extract(kernel_pmap,fdp->format_buffer)) == 0) {
 2717     free(fdp->format_buffer);
 2718     return(EIO);
 2719   }
 2720   fd_data_ptr_1(fdreq) = (u_int) fdp->format_buffer;
 2721   fd_data_ptr_2(fdreq) = (u_int) paddr;
 2722 
 2723   rc = fdexecute_command(fdp,FDFORMAT_TRACK_POLL);
 2724 
 2725   unpin((caddr_t) fdp->format_buffer, (int) fdp->format_size);
 2726   xmfree((caddr_t) fdp->format_buffer, (caddr_t) pinned_heap);
 2727 
 2728   return(rc);
 2729 }
 2730 #endif
 2731 
 2732 /* Does the work for a FDIOCSINFO ioctl.
 2733  *
 2734  *      FDIOCSINFO - sets the current diskette characteristics.
 2735  *      A structure of type fdinfo is loaded with the desired   
 2736  *      values and a pointer to this structure must be passed
 2737  *      to the device driver in the 'arg' parameter. 
 2738  *
 2739  * NOTES: This routine is fairly hardcoded with values for the various
 2740  * formats of the 2 drives and will have to be updated when new drives
 2741  * or formats are added.
 2742  */
 2743 #ifdef NEEDS_WORK               /* NEEDS WORK -- ioctl stuff...later */
 2744 static int
 2745 fd_iocsinfo(fdp,arg)
 2746      register struct floppy *fdp;
 2747      register long arg;
 2748 {
 2749   register struct fdinfo *fdinfop;
 2750   int tmp;
 2751   int rc = FDSUCCESS;
 2752 
 2753   /* Allocate an fdinfo structure. */
 2754   fdinfop = (struct fdinfo *) malloc(sizeof(struct fdinfo));
 2755 
 2756   if (fdinfop == NULL)
 2757     return(ENOMEM);
 2758 
 2759   /* Call copyin to get the fdinfo structure from the user. 
 2760    */
 2761   tmp = copyin((char *) (arg), (char *) (fdinfop), sizeof(struct fdinfo));
 2762   if (tmp == -1) {
 2763     free(fdinfop);
 2764     return(EINVAL);
 2765   }
 2766 
 2767   /*  Make sure the request has the correct drive type.  If not there
 2768    * must be a user error.
 2769    */
 2770   if (fdp->drive_type != fdinfop->type) {
 2771     free(fdinfop);
 2772     return(EINVAL);
 2773   }
 2774 
 2775   switch (fdinfop->type) {
 2776   case D_48:            /* 360K, 5.25" drive */
 2777     switch (fdinfop->ncyls) {
 2778     case 40:    /* 360K diskette */
 2779       if ( (fdinfop->sides == 2) && (fdinfop->nsects == 9) )
 2780         rc = fdload_floppy(fdp,FDLOAD_360);
 2781       else
 2782         rc = EINVAL;
 2783       break;
 2784       /*  The 1.2M diskette is not currently supported, but this
 2785        * will be handy if one does come up.
 2786        */
 2787     case 80:    /* 1.2M diskette -- not supported */
 2788       if ( (fdinfop->nsects != 15) || (fdinfop->sides != 2) )
 2789         rc = EINVAL;
 2790       else
 2791         rc = EINVAL;
 2792       break;
 2793     default:
 2794       rc = EINVAL;
 2795       break;
 2796     }
 2797     break;
 2798 
 2799   case D_135H:  /* 1.44M, 3.5" drive */
 2800     if ((fdinfop->sides != 2) || (fdinfop->ncyls != 80))
 2801       rc = EINVAL;
 2802     else {
 2803       switch (fdinfop->nsects) {
 2804       case 9:           /* 720K diskette */
 2805         rc = fdload_floppy(fdp, FDLOAD_720);
 2806         break;
 2807       case 18:  /* 1.44M diskette */
 2808         rc = fdload_floppy(fdp,FDLOAD_144);
 2809         break;
 2810       default:
 2811         rc = EINVAL;
 2812         break;
 2813       }
 2814     }
 2815     break;
 2816   default:
 2817     rc = EINVAL;
 2818     break;
 2819   }
 2820 
 2821   if (rc == FDSUCCESS)
 2822     fdp->drive_type = (u_char) fdinfop->type;
 2823 
 2824   free((caddr_t) fdinfop);
 2825 
 2826   return(rc);
 2827 }
 2828 #endif
 2829 
 2830 /* Does a FDIOCSTATUS ioctl.
 2831  *
 2832  *      FDIOCSTATUS - returns the status of the diskette drive and
 2833  *      device driver.  A pointer to a structure of type fd_status
 2834  *      should be be passed in the 'arg' parameter.  The driver
 2835  *      status will be loaded into the fd_status structure
 2836  *      The result phase portion of the status is only
 2837  *      valid if the device driver was opened in raw mode. 
 2838  *      otherwise, there is no way of knowing to which i/o
 2839  *      operation the result phase corresponds. 
 2840  *
 2841  * NEEDS WORK - In our ABIOS implementation there are fields in the fd_status
 2842  * struct that are not used.  Let's see about cleaning them up.
 2843  */
 2844 #ifdef NEEDS_WORK               /* NEEDS WORK -- ioctl's */
 2845 static int
 2846 fd_iocstatus(fdp,arg)
 2847      register struct floppy *fdp;
 2848      long arg;
 2849 {
 2850   register struct fd_status *fdstatusp;
 2851   int rc = FDSUCCESS;
 2852   int tmp;
 2853 
 2854   FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCSTATUS\n"));
 2855 
 2856   /* Allocate an fd_status structure. */
 2857 
 2858   fdstatusp = (struct fd_status *) malloc(sizeof(struct fd_status));
 2859 
 2860   if (fdstatusp == NULL)
 2861     return(ENOMEM);
 2862 
 2863   /* Start building the status1 bitmask with the drive number.
 2864    */
 2865   tmp = fddrive_val[fd_drive(fdp->device_number)];
 2866 
 2867   fdstatusp->status1 = (u_char) fdp->data_rate;
 2868 
 2869   /* Start building the status2 bitmask with the retry flag.
 2870    */
 2871   if (fdp->retry_flag)
 2872     tmp = FDRETRY;
 2873   else
 2874     tmp = 0;
 2875 
 2876   if (fdp->timeout_flag == TRUE)
 2877     tmp |= FDTIMEOUT;
 2878 
 2879   switch (fdp->drive_type) {
 2880   case D_48:
 2881     tmp |= FD5INCHLOW;
 2882     break;
 2883   case D_135H:
 2884     tmp |= FD3INCHHIGH;
 2885     break;
 2886   default:
 2887     break;
 2888   }
 2889 
 2890   fdstatusp->status2 = (u_char) tmp;
 2891   fdstatusp->status3 = fdp->diskette_type;
 2892 
 2893   fdstatusp->head_settle_time = fdp->head_settle_time;
 2894   fdstatusp->motor_speed = 300;         /* On R2 1.44 its 300 */
 2895   fdstatusp->Mbytes_read = fdp->read_count_megabytes;
 2896   fdstatusp->Mbytes_written = fdp->write_count_megabytes;
 2897 
 2898   fdstatusp->cylinder_num = fdp->start.cylinder;
 2899   fdstatusp->head_num = fdp->start.head;
 2900   fdstatusp->sector_num = fdp->start.sector;
 2901                 
 2902   fdstatusp->bytes_num = fdp->sector_count * fdp->bytes_per_sector;
 2903   fdstatusp->bytes_num = fdp->e_bytesps;
 2904 
 2905   fdget_adapter();
 2906   tmp = fdexecute_command(fdp,FDDISK_SAME);
 2907 
 2908   switch(tmp) {
 2909   case DISK_CHANGED:
 2910     fdstatusp->dsktchng = TRUE;
 2911     break;
 2912   case DISK_SAME:
 2913     fdstatusp->dsktchng = FALSE;
 2914     break;
 2915   default:
 2916     /*  Unknown rc from command, so return an error.
 2917      */
 2918     free((caddr_t) fdstatusp);
 2919     return(EIO);
 2920   }
 2921 
 2922   /* Call copyout to copy the fd_status structure to the user
 2923    */
 2924   tmp = copyout((char *) (fdstatusp), (char *) (arg),
 2925                 sizeof(struct fd_status));
 2926   if (tmp == -1) {
 2927     rc = EINVAL;
 2928   }
 2929 
 2930   free((caddr_t) fdstatusp);
 2931   return(rc);
 2932 }
 2933 #endif
 2934 
 2935 
 2936 /*  Cleans up initialization stuff prior to exiting. This routine is
 2937  * called just before exiting in fd_open and fd_close. 
 2938  */
 2939 static void 
 2940 fdcleanup(fdp)
 2941      struct floppy *fdp;
 2942 {
 2943   register int unit;
 2944   int pri;
 2945 
 2946   /*  If our drive is still open, we're done otherwise turn off
 2947    * the light.  If the other drives are also closed then reclaim
 2948    * some system resources.
 2949    */
 2950   if (fdp != NULL) {
 2951     if (fdp->drive_state & FDSTAT_OPEN)
 2952       return;
 2953 
 2954     /*  If the adapter is free, get it, and turn off the
 2955      * motor.  If the adapter is not free, something else
 2956      * is going on, and hence we won't have to turn off
 2957      * the light.
 2958      */
 2959     pri = splfd();
 2960     if (fdadapter.fdintr_status == FDFREE) {
 2961       fdget_adapter();
 2962       splx(pri);
 2963       fdexecute_command(fdp,FDMOTOR_OFF);
 2964     }
 2965     else
 2966       splx(pri);
 2967 
 2968     for (unit=0 ; unit < FDMAXDRIVES ; unit++)
 2969       if (floppies[unit].drive_state & FDSTAT_OPEN)
 2970         return;
 2971   }
 2972 
 2973   /* Reclaim some of the resources we were using.  If there is
 2974    * activity on the diskette adapter we will not get this far.
 2975    */
 2976   /* NEEDS WORK -- do we really want to untimeout() on the
 2977    * NEEDS WORK -- watchdog timers here??  This might cause
 2978    * NEEDS WORK -- problems with they system if they arn't
 2979    * NEEDS WORK -- on, but probably not....
 2980    */
 2981   UNTIMEOUT(fdadapter.mot_wd);
 2982   UNTIMEOUT(fdadapter.int_wd);
 2983 
 2984   return;
 2985 }
 2986 
 2987 /*
 2988  *  Checks to see if the drive door is open.  To do this with
 2989  * an ABIOS interface we read the first sector into memory.  This sector
 2990  * is written back if we need to check for write protect.
 2991  *
 2992  * NOTES: We set fdp->open_check to TRUE to know when the 5 1/4" drive
 2993  * does not have a diskette in it.  fdcall_abios_poll() will turn this
 2994  * flag off.  See fdtimer() for further explination.
 2995  */
 2996 #if NEEDS_WORK
 2997 static
 2998 #endif
 2999 int 
 3000 fddoor_check(fdp, wrck)
 3001      register struct floppy *fdp;
 3002      int wrck;
 3003 {
 3004   struct buf *bp;
 3005   int rc;
 3006 
 3007   FDDEBUG(FDCMD, printf("fddoor_check: entering...\n"));
 3008 
 3009   bp = geteblk(512);
 3010 #ifdef OSF
 3011   event_clear(&bp->b_iocomplete);
 3012 #endif /* OSF */
 3013   if (!bp) return(ENOMEM);
 3014   bp->b_dev = fdp->device_number;
 3015   bp->b_bcount = 512;
 3016   bp->b_flags = B_READ;
 3017   bp->b_blkno = 0;
 3018   fdstrategy(bp);
 3019 #if     MACH_KERNEL
 3020   biowait(bp);
 3021   rc = bp->b_error;
 3022 #else
 3023   rc = biowait(bp);
 3024 #endif
 3025   if (rc) goto dcdone;
 3026 
 3027   if (wrck) {
 3028     bp->b_bcount = 512;
 3029     bp->b_error = 0;
 3030     bp->b_resid = 0;
 3031                                 /* Added to fix B_INVAL for Mach 3.0 */
 3032 
 3033 #ifdef  MACH_KERNEL
 3034     bp->b_flags = B_WRITE;
 3035 #else   /* MACH_KERNEL */
 3036     bp->b_flags = B_WRITE|B_INVAL;
 3037 #endif  /* MACH_KERNEL */
 3038     bp->b_blkno = 0;
 3039 #ifdef OSF
 3040     event_clear(&bp->b_iocomplete);
 3041 #endif /* OSF */
 3042     fdstrategy(bp);
 3043 #if     MACH_KERNEL
 3044     biowait(bp);
 3045     rc = bp->b_error;
 3046 #else
 3047     rc = biowait(bp);
 3048 #endif
 3049   }
 3050 
 3051 dcdone:
 3052   brelse(bp);
 3053   return(rc);
 3054 }
 3055 
 3056 /*  Loads the proper diskette characteristics.  The 2nd parameter is a
 3057  * function for fdexecute_command(), which will do the actual loading.
 3058  *
 3059  *  There are actually 2 different ways that the fdp structure can be
 3060  * populated.  After fdexecute_command() is done we do some sanity
 3061  * checks.
 3062  */
 3063 static int 
 3064 fdload_floppy(fdp,cmd)
 3065      register struct floppy *fdp;
 3066      int cmd;
 3067 {
 3068   int rc = FDSUCCESS;
 3069   u_char drive_type;
 3070 
 3071   drive_type = fdp->drive_type;
 3072 
 3073   fdget_adapter();
 3074 
 3075   if ( (rc = fdexecute_command(fdp,cmd)) != FDSUCCESS )
 3076     return(rc);
 3077 
 3078 #ifdef NEEDS_WORK               /* NEEDS WORK */
 3079   /* NEEDS WORK -- ok.  We probably won't check drive_type anymore to
 3080    * NEEDS WORK -- compare what it was configured for.  This routine
 3081    * NEEDS WORK -- can probably drop to a macro like fdtype(), and we
 3082    * NEEDS WORK -- should also make sure both fdtype and load_floppy
 3083    * NEEDS WORK -- are really infact needed.
 3084    */
 3085   /* Is the drive type what it was configured for?
 3086    */
 3087   if (drive_type != fdp->drive_type)
 3088     return(EINVAL);
 3089 
 3090   /* NEEDS WORK -- since drive_type is no longer configed,
 3091    * NEEDS WORK -- this will have to change eventually.
 3092    */
 3093   switch(fdp->drive_type) {
 3094   case D_135H:
 3095     /*  If they wanted a 5 1/4 inch drive explicitly, then
 3096      * we have an error because this is a 3 1/2 inch drive.
 3097      */
 3098     if (minor(fdp->device_number) & FD_5)
 3099       rc = EINVAL;
 3100     break;
 3101   case D_48:
 3102     /*  If they wanted a 3 1/2 inch drive explicitly, then
 3103      * we have an error because this is a 5 1/4 inch drive.
 3104      */
 3105     if ((minor(fdp->device_number) & FD_5) == 0)
 3106       rc = EINVAL;
 3107     break;
 3108   }
 3109 #endif
 3110 
 3111   return (rc);
 3112 }
 3113 
 3114 /*  Currently this is a no-op.
 3115  */
 3116 int 
 3117 fdmincnt(bp)
 3118      struct buf *bp;
 3119 {
 3120   return (0);
 3121 }
 3122 
 3123 /*
 3124  *  Logs a hard diskette error.  It is called when we get an error that
 3125  * should be reported to the user by more than an errno.
 3126  *
 3127  *  Usually it will occur after all the retries are done, and the error
 3128  * still exists.
 3129  *
 3130  */
 3131 static void 
 3132 fdlog_error(fdp, value)
 3133      register struct floppy *fdp;
 3134      u_char value;
 3135 {
 3136   char *msg;
 3137 
 3138   FDDEBUG(FDSTAT, printf("fdlog_error: entering...\n"));
 3139 
 3140   /* NEEDS WORK -- this should be syslog or whatever the heck
 3141    * NEEDS WORK -- OSF/1 uses.  Took out the errsave() stuff.
 3142    */
 3143 
 3144   /* Differentiate between some hardware and internal errors.
 3145    */
 3146   switch(fdadapter.fd_req.r_return_code) {
 3147   case 0x8000:          /* Device Busy, Operation Fefused */
 3148   case 0x800f:          /* Invalid Value in NVRAM */
 3149   case 0x9009:          /* Controller Failure on Reset */
 3150   case 0x9108:          /* DMA Overrun on Operation */
 3151   case 0x9120:          /* Controller Failure */
 3152   case 0x9140:          /* Seek Operation Failed */
 3153   case 0x9180:          /* General Error */
 3154   case 0xa120:          /* Controller Failure */
 3155   case 0xb020:          /* Controller Failure */
 3156     msg = "hardware error";
 3157     break;
 3158   case 0xc000:          /* Invalid Logical ID */
 3159   case 0xc001:          /* Invalid Function */
 3160   case 0xc003:          /* Invalid Unit Number */
 3161   case 0xc004:          /* Invalid Request Block Length */
 3162   case 0xc005:          /* Invalid Diskette Parameter */
 3163     msg = "internal driver error";
 3164     break;
 3165   default:
 3166     msg = fd_tmp_errors[value];
 3167     break;
 3168   }
 3169   printf("***fd%d: %s (%x)!***\n",fdadapter.fd_req.r_unit, msg,
 3170          fdadapter.fd_req.r_return_code);
 3171 }
 3172 
 3173 /*  Gains access of the diskette adapter for the caller, sleeping if
 3174  * necessary.  This can be called from interrupt level, because FDBUSY
 3175  * is set in this case.
 3176  */
 3177 static void
 3178 fdget_adapter()
 3179 {
 3180   register int pri;
 3181 
 3182   pri = splfd();
 3183 
 3184   while (fdadapter.fdintr_status != FDFREE) {
 3185     FDDEBUG(FDCMD,printf("fdget_adapter: adapter not free!\n"));
 3186 
 3187     fdadapter.need_controller = TRUE;
 3188     sleep(&fdadapter.need_sleep,PRIBIO);        /* NEEDS WORK */
 3189   }
 3190 
 3191   fdadapter.fdintr_status = FDBUSY;
 3192   fdadapter.need_controller = FALSE;
 3193 
 3194   splx(pri);
 3195 }
 3196 
 3197 /* Checks for non-contiguous physical pages.  We can't dma across a virtual
 3198  * page boundry that are not physically contiguous.
 3199  */
 3200 static int
 3201 d_max_page(bp,baddr,paddr,max)
 3202      struct buf *bp;
 3203      u_int baddr;
 3204      u_int *paddr;
 3205      unsigned long max;
 3206 {
 3207   unsigned long count = ((unsigned long) baddr) & (I386_PGBYTES-1);
 3208   unsigned long old_addr;
 3209   unsigned long new_addr;
 3210 
 3211   /* if count is aligned, we can transfer a whole page */
 3212   if (count==0) count = I386_PGBYTES;
 3213 
 3214   if ( (*paddr = pmap_extract(get_pmap(bp),baddr)) == 0)
 3215     return(0);
 3216 
 3217   /*  Now loop through and get the real address of each of the
 3218    ** following pages.  Break on the first non-contiguous page,
 3219    ** or when we exceed count.
 3220    */
 3221   baddr += I386_PGBYTES;
 3222   old_addr = *paddr + I386_PGBYTES;
 3223   while ( (count < max) &&
 3224          ((new_addr = pmap_extract(get_pmap(bp),baddr)) != 0) &&
 3225          (new_addr == old_addr) ) {
 3226     count += I386_PGBYTES;
 3227     baddr += I386_PGBYTES;
 3228     old_addr += I386_PGBYTES;
 3229   }
 3230   return(count > max ? max : count);
 3231 }
 3232 
 3233 struct fd_errors { 
 3234 int     code;
 3235 char    *msg;
 3236 } fd_err_codes [] = {
 3237         {0x00,  "timeout"},
 3238         {0x01,  "bad-command"},
 3239         {0x02,  "address-mark-not-found"},
 3240         {0x04,  "record-not-found"},
 3241         {0x05,  "reset-failed"},
 3242         {0x07,  "activity-failed"},
 3243         {0x0a,  "defective-sector"},
 3244         {0x0b,  "bad-track"},
 3245         {0x0d,  "invalid-sector"},
 3246         {0x0e,  "CAM-detected"},
 3247         {0x0f,  "DMA-arb-level-bad"},
 3248         {0x10,  "bad-ecc-error"},
 3249         {0x11,  "ecc-corrected"},
 3250         {0x20,  "bad-controller"},
 3251         {0x21,  "equipment-check"},
 3252         {0x40,  "bad-seek"},
 3253         {0x80,  "device-didn't-respond"},
 3254         {0xaa,  "drive-not-ready"},
 3255         {0xbb,  "undefined-error"},
 3256         {0xcc,  "write-fault"},
 3257         {0xff,  "incomplete-sense"},
 3258         {0xc000,"invalid LID"},
 3259         {0xc001,"invalid function"},
 3260         {0xc003,"invalid unit number"},
 3261         {0xc004,"invalid request block length"},
 3262         {0xc005,"invalid parameter"}
 3263 
 3264 };
 3265 
 3266 void fd_error_decode(
 3267         int     code,
 3268         char    *msg)
 3269 {
 3270         int i;
 3271         int n = code&0x00ff;
 3272 
 3273         if ((code&0x8000) == 0) {
 3274                 char *p;
 3275                 switch(code)
 3276                 {
 3277                 case 0:
 3278                         p = "completed ok";
 3279                         break;
 3280                 case 1:
 3281                         p = "stage on int";
 3282                         break;
 3283                 case 2:
 3284                         p = "stage on time";
 3285                         break;
 3286                 case 5:
 3287                         p = "not my int";
 3288                         break;
 3289                 default:
 3290                         printf("unknown[0x%x]%s", code, msg);
 3291                         return;
 3292                 }
 3293                 printf("%s%s", p, msg);
 3294                 return;
 3295         }
 3296         if (code&0x4000) {
 3297                 printf("PARAMETER ");
 3298                 n = code;
 3299         }
 3300         if (code&0x2000)
 3301                 printf("TIME-OUT ");
 3302         if (code&0x1000)
 3303                 printf("DEVICE ");
 3304         if (code&0x100)
 3305                 printf("RETRYABLE ");
 3306         printf("ERROR ");
 3307         for (i=0; i<(sizeof fd_err_codes)/(sizeof fd_err_codes[0]); ++i)
 3308                 if (fd_err_codes[i].code == n)
 3309                         {
 3310                         printf("%s%s", fd_err_codes[i].msg, msg);
 3311                         return;
 3312                         }
 3313         printf("unknown[0x%x]%s", code, msg);
 3314 }
 3315 
 3316 
 3317 #ifdef  MACH_KERNEL
 3318 
 3319 
 3320 
 3321 /*
 3322  * NAME: fdgetstat(dev, flavour, data, count) 
 3323  *                                                                    
 3324  * FUNCTION: This function implements one half of the functions implemented
 3325  *           by the IOCTL routine in the MACH 2.5 version of this floppy
 3326  *           driver. 
 3327  *                                                                    
 3328  * EXECUTION ENVIRONMENT:
 3329  *                                                                   
 3330  * RETURNS: 
 3331  */  
 3332 
 3333 
 3334 
 3335 io_return_t fdgetstat(dev, flavor, data, count)
 3336         dev_t           dev;            /* device */
 3337         int             flavor;         /* command */
 3338         int *           data;           /* pointer to OUT array */
 3339         unsigned int    *count;         /* OUT */
 3340 {
 3341 
 3342         register struct floppy *fdp;
 3343         register struct fdparms *fdparmsp;
 3344         io_return_t     errcode = D_SUCCESS;
 3345 
 3346         fdp = &floppies[fd_drive(dev)];
 3347 
 3348         switch(flavor){
 3349 
 3350         case    FDIOCGETPARMS:
 3351 
 3352                         /* Check to see if out buffer is large enough */
 3353         
 3354                 if (*count < sizeof(struct fdparms)/sizeof(int))
 3355                         return(D_INVALID_OPERATION);    
 3356 
 3357                 /* In mach 2.5 space for fdparmsp was allocated here */
 3358                 /* initialized, then a copyout would be done to the */
 3359                 /* user supplied buffer space. and then a copyout   */
 3360                 /* would be done to user space. But here the pointer */
 3361                 /* to data is in kernel space and so it need not be */
 3362                 /* done. */
 3363 
 3364 
 3365                 fdparmsp = (struct fdparms *)data;
 3366 
 3367                 fdparmsp->diskette_type         = fdp->diskette_type;
 3368                 fdparmsp->sector_size           = fdp->e_bytesps;
 3369                 fdparmsp->sectors_per_track     = fdp->sectors_per_track; 
 3370                 fdparmsp->sectors_per_cylinder  = fdp->sectors_per_cylinder;
 3371                 fdparmsp->tracks_per_cylinder   = fdp->tracks_per_cylinder;
 3372                 fdparmsp->cylinders_per_disk    = fdp->cylinders_per_disk;
 3373                 fdparmsp->data_rate             = fdp->data_rate;
 3374                 fdparmsp->head_settle_time      = fdp->head_settle_time;
 3375                 fdparmsp->head_load             = 0;
 3376                 fdparmsp->fill_byte             = fdp->fill_byte;
 3377                 fdparmsp->step_rate             = 0;
 3378                 fdparmsp->step_rate_time        = 0;
 3379                 fdparmsp->gap                   = fdp->gap;
 3380                 fdparmsp->format_gap            = fdp->format_gap;
 3381                 fdparmsp->data_length           = fdp->data_length;
 3382                 fdparmsp->motor_off_time        = fdp->motor_off_time;  
 3383                 fdparmsp->bytes_per_sector      = fdp->bytes_per_sector;
 3384                 fdparmsp->number_of_blocks      = fdp->number_of_blocks;
 3385 
 3386                 /* force the out buffer to be word alligned */
 3387 
 3388                 *count = sizeof(struct fdparms)/sizeof(int);
 3389 
 3390                 errcode = D_SUCCESS;
 3391                 break;
 3392 
 3393         default:
 3394 
 3395                 errcode = D_INVALID_OPERATION;
 3396         
 3397         }  /* End of case flavor statement */
 3398 
 3399         return(errcode);
 3400 
 3401 }
 3402 
 3403 
 3404 
 3405 /*
 3406  * NAME: fdsetstat(dev, flavour, data, count) 
 3407  *                                                                    
 3408  * FUNCTION: This function implements a set of the functions that were
 3409  *           being performed in the IOCT routine of the MACH 2.5 version 
 3410  *           of this floppy driver 
 3411  *                                                                    
 3412  * EXECUTION ENVIRONMENT:
 3413  *                                                                   
 3414  * RETURNS: 
 3415  */  
 3416 
 3417 
 3418 io_return_t fdsetstat(dev, flavor, data, count)
 3419         dev_t           dev;
 3420         int             flavor;
 3421         int *           data;
 3422         unsigned int    count;
 3423 {
 3424 
 3425         register struct floppy *fdp;
 3426         register struct devinfo *devinfop;
 3427         register struct fdinfo *fdinfop;
 3428         register struct fdparms *fdparmsp;
 3429         int     temp;
 3430         io_return_t     errcode = D_SUCCESS;
 3431 
 3432 
 3433         fdp = &floppies[fd_drive(dev)];
 3434 
 3435 #define check(cnd, err)         if (!(cnd)) {           \
 3436                                         errcode = (err);\
 3437                                         break;          \
 3438                                 }
 3439 
 3440 #define cond(member)            (fdp->member == fdparmsp->member)       
 3441 
 3442 
 3443 
 3444         switch(flavor){
 3445         
 3446         case    FDIOCSETPARMS:
 3447 
 3448                 /* define two macros that will be used to screen */
 3449                 /* requests to set protected parameters of the */
 3450                 /* floppy drive that ABIOS doesnt support changes */
 3451                 /* to by the user */
 3452 
 3453 /*
 3454 
 3455 #define check(cnd, err)         if (!(cnd)) {                   \
 3456                                         errcode = (err);        \ 
 3457                                         break;                  \
 3458                                 }
 3459 
 3460 #define cond(member)            (fdp->member == fdparmsp->member)
 3461 
 3462 */
 3463 
 3464                 /* base the the fdparmsp on the user supplied data */
 3465 
 3466                 fdparmsp = (struct fdparms *)data;
 3467                 
 3468                 if (fdparmsp == NULL)
 3469                 {
 3470                         errcode = ENOMEM;
 3471                         break;
 3472                 }
 3473 
 3474                 /* Check to see if ABIOS protected fields are being */
 3475                 /* requested to be changed, if so retuen Error */
 3476 
 3477 
 3478                 check(fdp->diskette_type == fdparmsp->diskette_type,
 3479                         D_INVALID_OPERATION);
 3480                 check(fdparmsp->head_load == 0, D_INVALID_OPERATION);
 3481                 check(fdparmsp->step_rate == 0, D_INVALID_OPERATION);
 3482                 check(fdparmsp->step_rate_time == 0, D_INVALID_OPERATION);
 3483                 check(cond(sectors_per_track), D_INVALID_OPERATION);
 3484                 check(cond(sectors_per_cylinder), D_INVALID_OPERATION);
 3485                 check(cond(tracks_per_cylinder), D_INVALID_OPERATION);
 3486                 check(cond(cylinders_per_disk), D_INVALID_OPERATION);
 3487                 check(cond(data_rate), D_INVALID_OPERATION);
 3488                 check(cond(head_settle_time), D_INVALID_OPERATION);
 3489                 check(cond(number_of_blocks), D_INVALID_OPERATION);
 3490                 check(cond(bytes_per_sector), D_INVALID_OPERATION);
 3491 
 3492                 /* If we are here it means that the request is a legal */
 3493                 /* ABIOS supported request. So we check to see which of */
 3494                 /* the legal parameters are being requested to be changed */
 3495                 /* save the original value, attempt a change, if the ABIOS */
 3496                 /* request fails then we reset the value to the original */
 3497                 /* legal value and return a FAILURE */
 3498 
 3499 
 3500         /* Check to see if bytes_per_sector changed */
 3501 
 3502 
 3503                 if (fdp->e_bytesps != fdparmsp->sector_size)
 3504                 {
 3505 
 3506                         /* 256 and 512 Bytes per sector are legal values */
 3507 
 3508                         check((fdparmsp->sector_size==FD_256_BYTE_PER_SECTOR) ||
 3509                                (fdparmsp->sector_size==FD_512_BYTE_PER_SECTOR),
 3510                                 D_INVALID_OPERATION);
 3511 
 3512                         temp = fdp->e_bytesps;  /* save original */
 3513 
 3514                         fdp->e_bytesps = fdparmsp->sector_size;
 3515         
 3516                         fdget_adapter();
 3517 
 3518                         if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
 3519                         {
 3520 
 3521                                 fdp->e_bytesps = temp;
 3522                                 errcode = D_INVALID_OPERATION;
 3523                                 break;
 3524 
 3525                         }
 3526 
 3527                 /* When changing sector_size, bytes_per_sector will be */
 3528                 /* implicitly changed, so update the users view of */
 3529                 /* bytes_per_sector accordingly */
 3530 
 3531                         fdparmsp->bytes_per_sector = fdp->bytes_per_sector;
 3532 
 3533 
 3534                         check(temp == 0, D_INVALID_OPERATION);  /* Magic */
 3535 
 3536                 } 
 3537 
 3538         /* Check to see if gap has changed */
 3539 
 3540                 if (fdp->gap != fdparmsp->gap)
 3541                 {
 3542                         temp = fdp->gap;        /* save original value */
 3543                         fdp->gap = fdparmsp->gap;
 3544                         fdget_adapter();
 3545                         if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
 3546                         {
 3547                                 fdp->gap = temp;
 3548                                 errcode = D_INVALID_OPERATION;
 3549                                 break;
 3550 
 3551                         }
 3552                 }
 3553 
 3554 
 3555         /* Check to see if data_length has changed */
 3556 
 3557                 
 3558                 if (fdp->data_length != fdparmsp->data_length)
 3559                 {
 3560                         temp = fdp->data_length;        /* save original */
 3561                         fdp->data_length = fdparmsp->data_length;
 3562                         fdget_adapter();
 3563                         if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
 3564                         {
 3565                                 fdp->data_length = temp;
 3566                                 errcode = D_INVALID_OPERATION;
 3567                                 break;
 3568                         }
 3569                 }
 3570 
 3571         /* Check to see fill_byte has changed */
 3572 
 3573                 
 3574                 if (fdp->fill_byte != fdparmsp->fill_byte)
 3575                 {
 3576                         temp = fdp->fill_byte;          /* save original */
 3577                         fdp->fill_byte = fdparmsp->fill_byte;
 3578                         fdget_adapter();
 3579                         if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
 3580                         {
 3581                                 fdp->fill_byte = temp;
 3582                                 errcode = D_INVALID_OPERATION;
 3583                                 break;
 3584                         }
 3585                 }
 3586 
 3587 
 3588         /* Check to see if format_gap has changed */
 3589 
 3590                 if (fdp->format_gap != fdparmsp->format_gap)
 3591                 {
 3592                         temp = fdp->format_gap;         /* save original */
 3593                         fdp->format_gap = fdparmsp->format_gap;
 3594                         fdget_adapter();
 3595                         if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
 3596                         {
 3597                                 fdp->format_gap = temp;
 3598                                 errcode = D_INVALID_OPERATION;
 3599                                 break;
 3600                         }
 3601                 }
 3602 
 3603         /* Check if motor_off_time has changed */
 3604 
 3605                 if (fdp->motor_off_time != fdparmsp->motor_off_time)
 3606                 {
 3607                         fdadapter.mot_wd.time = fdparmsp->motor_off_time;
 3608                         fdp->motor_off_time = fdparmsp->motor_off_time;
 3609                         break;
 3610                 }
 3611 
 3612 
 3613         case FDIOCFORMAT:
 3614 
 3615         default:
 3616 
 3617                 errcode = D_INVALID_OPERATION;
 3618                 break;
 3619                         
 3620 
 3621         } /* End of switch statement for flavor */
 3622 
 3623 
 3624         return(errcode);
 3625 }
 3626 
 3627 /*
 3628  * NAME: fdabios_init 
 3629  *                                                                    
 3630  * FUNCTION: This function initializes the floppy driver data structures
 3631  *           by calling ABIOS to querry for the parameters of the floppy
 3632  *           drive and controller in the system. 
 3633  *                                                                    
 3634  * EXECUTION ENVIRONMENT:
 3635  *                                                                   
 3636  * This is called by fdinit() at system initialization time.                     *                                             
 3637  * RETURNS: NONE
 3638  */  
 3639 
 3640 fdabios_init(fdp)
 3641 register struct floppy *fdp;
 3642 {
 3643 
 3644         register struct Fd_request *fdreq;              
 3645         u_char  drive_number;
 3646         int rc = FDSUCCESS;
 3647 
 3648         fdadapter.fdintr_status = FDBUSY; 
 3649 
 3650         fdp->timeout_flag = FALSE;
 3651 #ifdef  MACH_KERNEL
 3652         /* called at probe; timeouts not set (or available) */
 3653 #else
 3654         UNTIMEOUT(fdadapter.mot_wd);
 3655 #endif  /* MACH_KERNEL */
 3656 
 3657         fdreq = &fdadapter.fd_req;
 3658         drive_number = fd_drive(fdp->device_number);
 3659         fdadapter.fd_flag = 0;
 3660         fdreq->state = FD_RB_IDLE;      /* may not be needed */
 3661         fdreq->sleep_on_intr = 0;      /* may not be needed */
 3662 
 3663         FD_SET_RESERVED_ABIOS_LOGICAL_PARAMETER(fdreq);
 3664 
 3665         fdreq->r_current_req_blck_len = sizeof(struct Fd_request);
 3666         fdreq->r_logical_id = abios_next_LID(FD_ID, 2);
 3667         fdreq->r_unit = 0;
 3668         fdreq->request_header.Request_Block_Flags = 0;
 3669         fdreq->request_header.ELA_Offset = 0;
 3670         fd_no_retry(fdp);
 3671 
 3672 
 3673         fdp->timeout_flag = FALSE;
 3674         fdreq->state |= FD_RB_SYNC;
 3675         fdreq->req_errno = 0;
 3676 
 3677 
 3678         fdreq->r_function = FDABIOS_INIT;
 3679         fdreq->r_return_code = ABIOS_UNDEFINED;
 3680         fdreq->state |= FD_RB_STARTED;
 3681 
 3682         abios_common_start(fdreq, fdadapter.fd_flag);
 3683 
 3684         /* wait for ABIOS to get done */
 3685 
 3686         while (fdreq->r_return_code == ABIOS_UNDEFINED)
 3687         {
 3688                 assert_wait(0, FALSE);
 3689                 thread_set_timeout(10);
 3690                 thread_block((continuation_t) 0);
 3691         }
 3692 
 3693         /* Look for synchronous errors from ABIOS */
 3694 
 3695         if (fdreq->r_return_code & 0x8000)
 3696         {
 3697                 if (fdreq->r_return_code == 0xc000)
 3698                    printf("Req 1: Invalid Logical ID\n\n");
 3699                 if (fdreq->r_return_code == 0xc001)
 3700                    printf("Req 1: Invalid Function\n\n");
 3701                 if (fdreq->r_return_code == 0xc003)
 3702                    printf("Req 1: Invalid Unit Number\n\n");
 3703                 if (fdreq->r_return_code == 0xc004)
 3704                    printf("Req 1: Invalid Request Block Length\n\n");
 3705                 else
 3706                    printf("Req 1: Unkown Error\n\n");
 3707 
 3708                 return(EIO);
 3709         }
 3710 
 3711         while (fdreq->r_return_code != ABIOS_DONE)
 3712         {
 3713                 assert_wait(0, FALSE);
 3714                 thread_set_timeout(10);
 3715                 thread_block((continuation_t) 0);
 3716         }
 3717 
 3718         rc = fdreq->req_errno;
 3719 
 3720         if (rc != FDSUCCESS)
 3721                 return(rc);
 3722 
 3723         fdreq->r_current_req_blck_len = fdreq->r_request_block_length;
 3724         fdadapter.fd_flag = fdreq->r_logical_id_flags;
 3725         fdadapter.fd_intl = fdreq->r_hardware_intr;
 3726         fdadapter.fd_numd = fdreq->r_number_units;
 3727 
 3728 
 3729         if (fdadapter.fd_numd == 0)
 3730 #ifdef  MACH_KERNEL
 3731                 return D_NO_SUCH_DEVICE;
 3732 #else   /* MACH_KERNEL */
 3733                 return(ENODEV);
 3734 #endif  /* MACH_KERNEL */
 3735 
 3736         if (fdadapter.fd_numd > FDMAXDRIVES)
 3737                 fdadapter.fd_numd = FDMAXDRIVES;
 3738 
 3739 
 3740         FD_SET_RESERVED_ABIOS_READ_PARAMETER(fdreq);
 3741 
 3742         fd_no_retry(fdp);
 3743         
 3744         fdp->timeout_flag = FALSE;
 3745         fdreq->state |= FD_RB_SYNC;
 3746         fdreq->req_errno = 0;
 3747 
 3748         fdreq->r_function = ABIOS_READ_PARAMETER;
 3749         fdreq->r_return_code = ABIOS_UNDEFINED;
 3750         fdreq->state |= FD_RB_STARTED;
 3751 
 3752 
 3753         abios_common_start(fdreq, fdadapter.fd_flag);
 3754 
 3755         /* wait for ABIOS to get done */
 3756 
 3757         while(fdreq->r_return_code == ABIOS_UNDEFINED)
 3758         {
 3759                 assert_wait(0, FALSE);
 3760                 thread_set_timeout(10);
 3761                 thread_block((continuation_t) 0);
 3762         }
 3763 
 3764 
 3765         /* Look for synchronous errors from ABIOS */
 3766 
 3767         if (fdreq->r_return_code & 0x8000)
 3768         {
 3769 
 3770                 if (fdreq->r_return_code == 0x8000)
 3771                    printf("Req 2: Device Busy Error\n\n");
 3772                 if (fdreq->r_return_code == 0x8001)
 3773                    printf("Req 2: Diskette Not Started\n\n");
 3774                 if (fdreq->r_return_code == 0xc000)
 3775                    printf("Req 2: Invalid Logical ID\n\n");
 3776                 if (fdreq->r_return_code == 0xc001)
 3777                    printf("Req 2: Invalid Function\n\n");
 3778                 if (fdreq->r_return_code == 0xc003)
 3779                    printf("Req 2: Invalid Unit Number\n\n");
 3780                 if (fdreq->r_return_code == 0xc004)
 3781                    printf("Req 2: Invalid Request Block Length\n\n");
 3782                 else
 3783                    printf("Req 2: Sync Error reported by ABIOS \n\n");
 3784 
 3785                 return(EIO);
 3786         }
 3787 
 3788         while (fdreq->r_return_code != ABIOS_DONE)
 3789         {
 3790                 assert_wait(0, FALSE);
 3791                 thread_set_timeout(10);
 3792                 thread_block((continuation_t)0);
 3793         }
 3794 
 3795 
 3796         rc = fdreq->req_errno;
 3797 
 3798         if (rc != FDSUCCESS)
 3799                 return(rc);
 3800 
 3801         fdadapter.motor_off_delay = fd_motor_off_delay_time(fdreq);
 3802 
 3803         fdadapter.fdintr_status = FDFREE;
 3804 
 3805         return(rc);
 3806 
 3807 }
 3808 
 3809 #endif  /* MACH_KERNEL */
 3810 
 3811 
 3812         

Cache object: 6617fa9053d9e297158f63bbccd2821d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.