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

Cache object: 642651b0a0c6681e13845a67712e9f2b


[ 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.