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/i386at/fd.c

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

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /* 
   27  * HISTORY
   28  * $Log:        fd.c,v $
   29  * Revision 2.15  93/08/02  21:43:43  mrt
   30  *      Put the free copyright on this file, again.
   31  *      [93/07/22            mrt]
   32  * 
   33  * Revision 2.14  93/05/15  19:32:35  mrt
   34  *      machparam.h -> machspl.h
   35  * 
   36  * Revision 2.13  93/05/10  21:19:02  rvb
   37  *      Lint.
   38  *      [93/05/08  11:19:03  af]
   39  * 
   40  * Revision 2.12  93/01/24  13:15:28  danner
   41  *      [93/01/19  11:03:43  rvb]
   42  * 
   43  *      Test lower bound of media type; convert fd_addr to vm_offset_t.
   44  * 
   45  * Revision 2.11  93/01/14  17:30:11  danner
   46  *      Proper spl typing.
   47  *      [92/11/30            af]
   48  * 
   49  * Revision 2.10  92/07/09  22:53:34  rvb
   50  *      There is a problem with ADAPTEC boards, where scsi disk dma will
   51  *      lock out the floppy dma.  An expedient fix seems to be to drop
   52  *      the DMA size for the floppy, in the retry code when/if this happens.
   53  *      [92/07/08            rvb]
   54  * 
   55  * Revision 2.9  92/04/08  08:58:30  rpd
   56  *      Fixed fdprobe to loop longer.  From rvb.
   57  *      [92/04/08            rpd]
   58  * 
   59  * Revision 2.8  92/02/23  22:42:57  elf
   60  *      Added (mandatory) DEV_GET_SIZE flavor of get_status.
   61  *      [92/02/22            af]
   62  * 
   63  * Revision 2.7  92/01/27  16:42:54  rpd
   64  *      Fixed fdgetstat and fdsetstat to return D_INVALID_OPERATION
   65  *      for unsupported flavors.
   66  *      [92/01/26            rpd]
   67  * 
   68  * Revision 2.6  91/11/12  11:09:18  rvb
   69  *      Amazing how hard getting the probe to work for all machines is.
   70  *      [91/10/16            rvb]
   71  * 
   72  * Revision 2.5  91/10/07  17:25:22  af
   73  *      Still better
   74  *      [91/10/07  16:29:57  rvb]
   75  * 
   76  *      From mg32: Better probe for multiple controllers now possible.
   77  *      [91/09/23            rvb]
   78  *      New chips/busses.[ch] nomenclature.
   79  *      [91/09/09  17:12:23  rvb]
   80  * 
   81  *      Added a reset in open to prevent "no such device" errors
   82  *      Added dlb's fddevinfo.
   83  *      Reworked to make 2.5/3.0 compatible
   84  *      [91/09/04  15:46:49  rvb]
   85  * 
   86  *      Major rewrite by mg32.
   87  *      [91/08/07            mg32]
   88  * 
   89  * Revision 2.4  91/08/24  11:57:32  af
   90  *      New MI autoconf.
   91  *      [91/08/02  02:53:26  af]
   92  * 
   93  * Revision 2.3  91/05/14  16:22:47  mrt
   94  *      Correcting copyright
   95  * 
   96  * Revision 2.2  91/02/14  14:42:23  mrt
   97  *      This file is the logical contatenation of the previous c765.c,
   98  *      m765knl.c and m765drv.c, in that order.  
   99  *      [91/01/15            rvb]
  100  * 
  101  * Revision 2.5  91/01/08  17:33:32  rpd
  102  *      Add some 3.0 get/set stat stuff.
  103  *      [91/01/04  12:21:06  rvb]
  104  * 
  105  * Revision 2.4  90/11/26  14:50:54  rvb
  106  *      jsb bet me to XMK34, sigh ...
  107  *      [90/11/26            rvb]
  108  *      Synched 2.5 & 3.0 at I386q (r1.6.1.6) & XMK35 (r2.4)
  109  *      [90/11/15            rvb]
  110  * 
  111  * Revision 1.6.1.6  90/11/27  13:44:55  rvb
  112  *      Synched 2.5 & 3.0 at I386q (r1.6.1.6) & XMK35 (r2.4)
  113  *      [90/11/15            rvb]
  114  * 
  115  * Revision 2.3  90/08/27  22:01:22  dbg
  116  *      Remove include of device/param.h (unnecessary).  Flush ushort.
  117  *      [90/07/17            dbg]
  118  * 
  119  * Revision 1.6.1.5  90/08/25  15:44:31  rvb
  120  *      Use take_<>_irq() vs direct manipulations of ivect and friends.
  121  *      [90/08/20            rvb]
  122  * 
  123  * Revision 1.6.1.4  90/07/27  11:26:53  rvb
  124  *      Fix Intel Copyright as per B. Davies authorization.
  125  *      [90/07/27            rvb]
  126  * 
  127  * Revision 1.6.1.3  90/07/10  11:45:11  rvb
  128  *      New style probe/attach.
  129  *      NOTE: the whole probe/slave/attach is a crock.  Someone
  130  *      who spends the time to understand the driver should do
  131  *      it right.
  132  *      [90/06/15            rvb]
  133  * 
  134  * Revision 2.2  90/05/03  15:45:37  dbg
  135  *      Convert for pure kernel.
  136  *      Optimized fd_disksort iff dp empty.
  137  *      [90/04/19            dbg]
  138  * 
  139  * Revision 1.6.1.2  90/01/08  13:30:14  rvb
  140  *      Add Intel copyright.
  141  *      [90/01/08            rvb]
  142  * 
  143  * Revision 1.6.1.1  89/10/22  11:34:51  rvb
  144  *      Received from Intel October 5, 1989.
  145  *      [89/10/13            rvb]
  146  * 
  147  * Revision 1.6  89/09/25  12:27:05  rvb
  148  *      vtoc.h -> disk.h
  149  *      [89/09/23            rvb]
  150  * 
  151  * Revision 1.5  89/09/09  15:23:15  rvb
  152  *      Have fd{read,write} use stragegy now that physio maps correctly.
  153  *      [89/09/06            rvb]
  154  * 
  155  * Revision 1.4  89/03/09  20:07:26  rpd
  156  *      More cleanup.
  157  * 
  158  * Revision 1.3  89/02/26  12:40:28  gm0w
  159  *      Changes for cleanup.
  160  *
  161  */
  162  
  163 /*
  164   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
  165 
  166                 All Rights Reserved
  167 
  168 Permission to use, copy, modify, and distribute this software and
  169 its documentation for any purpose and without fee is hereby
  170 granted, provided that the above copyright notice appears in all
  171 copies and that both the copyright notice and this permission notice
  172 appear in supporting documentation, and that the name of Intel
  173 not be used in advertising or publicity pertaining to distribution
  174 of the software without specific, written prior permission.
  175 
  176 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
  177 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  178 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
  179 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  180 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
  181 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  182 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  183 */
  184 
  185 /*      Copyright (c) 1987, 1988 TOSHIBA Corp.          */
  186 /*              All Rights Reserved                     */
  187 
  188 #include <fd.h>
  189 
  190 #ifdef  MACH_KERNEL
  191 #include <sys/types.h>
  192 #include <device/buf.h>
  193 #include <device/errno.h>
  194 #else   MACH_KERNEL
  195 #include <sys/buf.h>
  196 #include <sys/errno.h>
  197 #include <sys/user.h>
  198 #endif  MACH_KERNEL
  199 #include <sys/ioctl.h>
  200 #include <i386/pio.h>
  201 #include <i386/machspl.h>
  202 #include <chips/busses.h>
  203 #include <i386at/fdreg.h>
  204 #include <i386at/disk.h>
  205 
  206 #ifdef  DEBUG
  207 #define D(x) x
  208 #else   /* DEBUG */
  209 #define D(x)
  210 #endif  /* DEBUG */
  211 
  212 /*
  213  * Floppy Device-Table Definitions (drtabs)
  214  *
  215  *      Cyls,Sec,spc,part,Mtype,RWFpl,FGpl
  216  */
  217 struct  fddrtab m765f[] = {                     /* format table */
  218         80, 18, 1440,  9, 0x88, 0x2a, 0x50,     /* [0] 3.50" 720  Kb  */
  219         80, 36, 2880, 18, 0x08, 0x1b, 0x6c,     /* [1] 3.50" 1.44 Meg */
  220         40, 18,  720,  9, 0xa8, 0x2a, 0x50,     /* [2] 5.25" 360  Kb  */
  221         80, 30, 2400, 15, 0x08, 0x1b, 0x54      /* [3] 5.25" 1.20 Meg */
  222 };
  223 
  224 /*
  225  * The following are static initialization variables
  226  * which are based on the configuration.
  227  */
  228 struct ctrl_info ctrl_info[MAXUNIT>>1] = {              /* device data table */
  229         {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ,
  230         {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
  231 };
  232 
  233 struct unit_info unit_info[MAXUNIT];            /* unit buffer headers  */
  234 
  235 char *fderr = "FD Error on unit";
  236 char *fdmsg[] = {
  237         "?",
  238         "Missing data address mark",
  239         "Write protected",
  240         "Sector not found",
  241         "Data Overrun",                         /* Over run error */
  242         "Uncorrectable data read error",        /* CRC Error */
  243         "FDC Error",
  244         "Illegal format type",
  245         "Drive not ready",
  246         "diskette not present - please insert",
  247         "Illegal interrupt type"
  248 };
  249 
  250 struct buf      fdrbuf[MAXUNIT];        /* data transfer buffer structures */
  251 
  252 int     fdminphys();
  253 int     fdintr(), fdprobe(), fdslave();
  254 void    fdattach();
  255 vm_offset_t     fd_std[NFD] = { 0 };
  256 struct  bus_device *fd_dinfo[NFD*2];
  257 struct  bus_ctlr *fd_minfo[NFD];
  258 struct  bus_driver      fddriver = 
  259         {fdprobe, fdslave, fdattach, 0, fd_std, "fd", fd_dinfo, "fdc", fd_minfo, 0};
  260 
  261 int     m765verify[MAXUNIT] = {1,1,1,1};        /* write after read flag */
  262                                                 /* 0 != verify mode     */ 
  263                                                 /* 0 == not verify mode */
  264 #ifdef  MACH_KERNEL
  265 extern struct buf *geteblk();
  266 #endif  MACH_KERNEL
  267 
  268 #define trfrate(uip, type)   outb(VFOREG(uip->addr),(((type)&RATEMASK)>>6))
  269 #define rbskrate(uip, type)  trfrate(uip,(type)&RAPID?RPSEEK:NMSEEK)
  270 #define getparm(type)   ((type<0||type>3)?(struct fddrtab *)ERROR:&m765f[type])
  271 #define relative(s1,s2) ((s1)>(s2)?(s1)-(s2):(s2)-(s1))
  272 
  273 fdprobe(port, ctlr)
  274 struct bus_ctlr *ctlr;
  275 {
  276         int                     spot = STSREG((int) ctlr->address);
  277         struct ctrl_info        *cip = &ctrl_info[ctlr->unit];
  278         int                     i, in;
  279 
  280         outb(spot, DATAOK);
  281         for (i = 1000; i--;) {
  282                 in = inb(spot);
  283                 if ((in&DATAOK) == DATAOK && !(in&0x0f)) {
  284                         take_ctlr_irq(ctlr);
  285                         cip->b_cmd.c_rbmtr = 0;         /* recalibrate/moter flag */
  286                         cip->b_cmd.c_intr = CMDRST;     /* interrupt flag */
  287                         cip->b_unitf = 0;
  288                         cip->b_uip = 0;
  289                         cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
  290                         printf("%s%d: port = %x, spl = %d, pic = %d.\n", ctlr->name,
  291                                 ctlr->unit, ctlr->address, ctlr->sysdep, ctlr->sysdep1);
  292                         return(1);
  293                 }
  294         }
  295         return(0);
  296 }
  297 
  298 fdslave(dev, xxxx)
  299 struct bus_device               *dev;
  300 {
  301         return(1);      /* gross hack */
  302 }
  303 
  304 void fdattach(dev)
  305 struct bus_device *dev;
  306 {
  307         struct unit_info        *uip = &unit_info[dev->unit];
  308         struct ctrl_info        *cip = &ctrl_info[dev->ctlr];
  309 
  310         uip->dev = dev;
  311         dev->address = dev->mi->address;
  312         uip->addr = dev->address;
  313         uip->b_cmd = &cip->b_cmd;
  314         uip->b_seekaddr = 0;
  315         uip->av_forw = 0;
  316         uip->wakeme = 0;
  317         if (cip->b_unitf) {
  318                 uip->b_unitf=cip->b_unitf->b_unitf;
  319                 cip->b_unitf->b_unitf=uip;
  320         } else {
  321                 uip->b_unitf=uip;
  322                 cip->b_unitf=uip;
  323         }
  324         uip->d_drtab.dr_type &= ~OKTYPE; 
  325 
  326         printf(", port = %x, spl = %d, pic = %d.",
  327                 dev->address, dev->sysdep, dev->sysdep1);
  328 
  329         rstout(uip);
  330         specify(uip);
  331 }
  332 /*****************************************************************************
  333  *
  334  * TITLE:       fdopen
  335  *
  336  * ABSTRACT:    Open a unit. 
  337  *
  338  ****************************************************************************/
  339 fdopen(dev, flag, otyp)
  340 dev_t   dev;
  341 int     flag;                   /* not used */
  342 int     otyp;                   /* not used */
  343 {
  344         struct fddrtab          *driv;
  345         struct buf              *wbp;
  346         spl_t                   x = SPL();
  347         int                     error = 0;
  348         int                     unit = UNIT(dev);
  349         struct unit_info        *uip = &unit_info[unit];
  350         int                     slave = uip->dev->slave;
  351         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
  352         struct  fdcmd           *cmdp = uip->b_cmd;
  353         if (unit < MAXUNIT){
  354           /* Since all functions that use this are called from open, we only
  355              set this once, right here. */
  356                 rstout(uip);
  357                 cip->b_wup = uip;
  358                 openchk(cmdp);
  359                 cmdp->c_devflag |= FDMCHK;
  360                 chkbusy(cmdp);
  361                 cmdp->c_stsflag |= MTRFLAG;
  362                 mtr_on(uip);
  363                 if(inb(VFOREG(uip->addr))&OPENBIT || 
  364                    !(uip->d_drtab.dr_type&OKTYPE)){
  365                         uip->d_drtab.dr_type &= ~OKTYPE;
  366                         if(!rbrate(RAPID, uip))
  367                                 fdseek(RAPID, uip, 2);
  368                         if(inb(VFOREG(uip->addr))&OPENBIT)
  369                                 error = ENXIO;
  370                 }
  371                 cmdp->c_stsflag &= ~MTRFLAG;
  372                 mtr_on(uip);
  373                 openfre(cmdp);
  374                 if(!error && !(uip->d_drtab.dr_type & OKTYPE)) {
  375                         if (MEDIATYPE(dev)>3)
  376                                 goto endopen;
  377                         driv = &m765f[MEDIATYPE(dev)];
  378                         wbp = geteblk(BLKSIZE);
  379                         m765sweep(uip, driv);
  380                         cmdp->c_rbmtr &= ~(1<<(RBSHIFT+(slave)));
  381                         ++cip->b_rwerr;
  382                         wbp->b_dev = dev; wbp->b_error = 0; wbp->b_resid = 0;
  383                         wbp->b_flags = (B_READ|B_VERIFY); wbp->b_bcount = 512;
  384                         wbp->b_pfcent = 2*driv->dr_spc + driv->dr_nsec - 1;
  385                         setqueue(wbp, uip);
  386                         biowait(wbp);
  387                         brelse(wbp);
  388                         error = 0;
  389                         uip->d_drtab.dr_type |= OKTYPE;
  390                 }
  391         } else
  392                 error = ENXIO;
  393       endopen:
  394         splx(x);
  395         return(error);
  396 }
  397 /*****************************************************************************
  398  *
  399  * TITLE:       fdclose
  400  *
  401  * ABSTRACT:    Close a unit.
  402  *
  403  *      Called on last close. mark the unit closed and not-ready.
  404  *
  405  *      Unix doesn't actually "open" an inode for rootdev, swapdev or pipedev.
  406  *      If UNIT(swapdev) != UNIT(rootdev), then must add code in init() to 
  407  *      "open" swapdev.  These  devices should never be closed.
  408  *
  409  *****************************************************************************/
  410 fdclose(dev, flag, otyp, offset)
  411 dev_t   dev;            /* major, minor numbers */
  412 int     flag;           /* not used */
  413 int     otyp;           /* not used */
  414 off_t   offset;         /* not used */
  415 {
  416         extern                  dev_t   rootdev, swapdev;
  417         struct unit_info        *uip = &unit_info[UNIT(dev)];
  418         spl_t s;
  419 
  420 #ifdef  MACH_KERNEL
  421 #else   MACH_KERNEL
  422         if ((dev == rootdev) || (dev == swapdev))  /* never close these */
  423                 return(0);
  424 #endif  MACH_KERNEL
  425 
  426         /* Clear the bit.
  427          * If last close of drive insure drtab queue is empty before returning.
  428          */
  429         s = SPL();
  430         while(uip->av_forw != 0) {
  431                 uip->wakeme = 1;
  432                 sleep(uip, PRIBIO);
  433         }
  434         splx(s);
  435 #ifdef  MACH_KERNEL
  436         return(0);
  437 #else   MACH_KERNEL
  438         close(0);
  439 #endif  MACH_KERNEL
  440 }
  441 /*****************************************************************************
  442  *
  443  * TITLE:       fdstrategy
  444  *
  445  * ABSTRACT:    Queue an I/O Request, and start it if not busy already.
  446  *
  447  *      Reject request if unit is not-ready.
  448  *
  449  *      Note:   check for not-ready done here ==> could get requests
  450  *              queued prior to unit going not-ready.
  451  *              not-ready status to those requests that are attempted
  452  *              before a new volume is inserted.  Once a new volume is
  453  *              inserted, would get good I/O's to wrong volume.
  454  *
  455  * CALLS:       iodone(),setqueue()
  456  *
  457  * CALLING ROUTINES:    fdread (indirectly, thru physio)
  458  *                      fdwrite (indirectly, thru physio)
  459  *
  460  ****************************************************************************/
  461 fdstrategy(bp)
  462 struct buf *bp; /* buffer header */
  463 {
  464         unsigned                bytes_left;
  465         daddr_t                 secno;
  466         struct unit_info        *uip = &unit_info[UNIT(bp->b_dev)];
  467         struct fddrtab          *dr = &uip->d_drtab;
  468         struct fddrtab          *sdr;
  469 
  470         bp->b_error = 0;
  471         /* set b_resid to b_bcount because we haven't done anything yet */
  472         bp->b_resid = bp->b_bcount;
  473         if (!(dr->dr_type & OKTYPE) || 
  474             ((sdr = getparm(MEDIATYPE(bp->b_dev)))==(struct fddrtab *)ERROR) ||
  475             /* wrong parameters */
  476             (sdr->dr_ncyl != dr->dr_ncyl) || (sdr->dr_nsec != dr->dr_nsec) ||
  477             ((sdr->dr_type|OKTYPE) != dr->dr_type) ||
  478             (sdr->dr_rwgpl != dr->dr_rwgpl) ||
  479             (sdr->dr_fgpl != dr->dr_fgpl)) {
  480                 bp->b_flags |= B_ERROR;
  481                 bp->b_error = EIO;
  482                 biodone(bp);
  483                 return(0);
  484         }
  485         /*
  486          * Figure "secno" from b_blkno. Adjust sector # for partition.
  487          *
  488          * If reading just past the end of the device, it's
  489          * End of File.  If not reading, or if read starts further in
  490          * than the first sector after the partition, it's an error.
  491          *
  492          * secno is logical blockno / # of logical blocks per sector */
  493         secno = (bp->b_blkno * NBPSCTR) >> 9;
  494         if (secno >= dr->p_nsec) {
  495                 if (!((bp->b_flags & B_READ) && (secno == dr->p_nsec))){
  496                         /* off the deep end */
  497                         bp->b_flags |= B_ERROR;
  498                         bp->b_error = ENXIO;
  499                 }
  500                 biodone(bp);
  501                 return(0);
  502         }
  503 /* At this point, it is no longer possible to directly return from strategy.
  504    We now set b_resid to the number of bytes we cannot transfer because
  505    they lie beyond the end of the request's partition.  This value is 0
  506    if the entire request is within the partition. */
  507         bytes_left = (dr->p_nsec - secno) << 9;
  508         bp->b_resid = ((bp->b_bcount<=bytes_left)?0:(bp->b_bcount-bytes_left));
  509         bp->b_pfcent = secno;
  510         setqueue(bp, uip);
  511         return(0);
  512 }
  513 
  514 /***************************************************************************
  515  *
  516  *      set queue to buffer
  517  *
  518  ***************************************************************************/
  519 setqueue(bp, uip)
  520 struct buf *bp;
  521 struct unit_info *uip;
  522 {
  523         spl_t                   x = SPL();
  524         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
  525         struct  fdcmd           *cmdp = uip->b_cmd;
  526 
  527         openchk(cmdp);          /* openning check */
  528         cmdp->c_devflag |= STRCHK;
  529         fd_disksort(uip, bp);   /* queue the request */
  530         /*
  531          * If no requests are in progress, start this one up.  Else
  532          * leave it on the queue, and fdintr will call m765io later.
  533          */
  534         if(!cip->b_uip)
  535                 m765io(uip);
  536         splx(x);
  537 }
  538 /***************************************************************************
  539  *
  540  *      check io_busy routine
  541  *
  542  ***************************************************************************/
  543 chkbusy(cmdp)
  544 struct  fdcmd   *cmdp;
  545 {
  546         while(cmdp->c_devflag & STRCHK){
  547                 cmdp->c_devflag |= STRWAIT;
  548                 sleep(&cmdp->c_devflag,PZERO);
  549         } 
  550 }
  551 /***************************************************************************
  552  *
  553  *      check fdopen() routine
  554  *
  555  ***************************************************************************/
  556 openchk(cmdp)
  557 struct  fdcmd   *cmdp;
  558 {
  559         while(cmdp->c_devflag & FDMCHK ){
  560                 cmdp->c_devflag |= FDWAIT;
  561                 sleep(&cmdp->c_devflag,PZERO);
  562         } 
  563 }
  564 /***************************************************************************
  565  *
  566  *      free fdopen() routine
  567  *
  568  ***************************************************************************/
  569 openfre(cmdp)
  570 struct  fdcmd   *cmdp;
  571 {
  572         cmdp->c_devflag &= ~FDMCHK;
  573         if(cmdp->c_devflag & FDWAIT){
  574                 cmdp->c_devflag &= ~FDWAIT;
  575                 wakeup(&cmdp->c_devflag);
  576         }
  577 }
  578 /*****************************************************************************
  579  *
  580  * TITLE:       m765io
  581  *
  582  * ABSTRACT:    Start handling an I/O request.
  583  *
  584  ****************************************************************************/
  585 m765io(uip)
  586 struct unit_info *uip;
  587 {
  588         extern int(m765iosub)();
  589         register struct buf *bp;
  590         struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
  591 
  592         bp = uip->av_forw; /*move bp to ctrl_info[ctrl].b_buf*/
  593         cip->b_buf = bp;
  594         cip->b_uip = uip;
  595         cip->b_xferaddr  = bp->b_un.b_addr;
  596         cip->b_xfercount = bp->b_bcount - bp->b_resid;
  597         cip->b_sector    = bp->b_pfcent;
  598         uip->b_cmd->c_stsflag |= MTRFLAG;
  599         if(!mtr_start(uip))
  600                 timeout(m765iosub, uip, HZ);
  601         else
  602                 m765iosub(uip);
  603 }
  604 /****************************************************************************
  605  *
  606  *      m765io subroutine
  607  *
  608  ****************************************************************************/
  609 m765iosub(uip)
  610 struct unit_info *uip;
  611 {
  612         struct fddrtab          *dr = &uip->d_drtab;
  613         int                     startsec;
  614         int                     slave = uip->dev->slave;
  615         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
  616         struct  fdcmd           *cmdp = uip->b_cmd;
  617 
  618         rwcmdset(uip);
  619         if(cip->b_buf->b_flags&B_FORMAT)
  620                 goto skipchk;
  621         startsec = (cmdp->c_rwdata[3] * dr->dr_nsec) + cmdp->c_rwdata[4];
  622         if(startsec+(cip->b_xfercount>>9)-1 > dr->dr_spc)
  623                 cip->b_xferdma = (dr->dr_spc-startsec+1) << 9;
  624         else
  625 skipchk:        cip->b_xferdma = cip->b_xfercount;
  626         if(!(cmdp->c_rbmtr & (1<<(RBSHIFT+slave))))
  627                 cip->b_status = rbirate(uip);
  628         else if(uip->b_seekaddr != cmdp->c_saddr)
  629                 cip->b_status = fdiseek(uip,cmdp->c_saddr);
  630         else
  631                 cip->b_status = outicmd(uip);
  632         if(cip->b_status)
  633                 intrerr0(uip);
  634         return;
  635 }
  636 /***************************************************************************
  637  *
  638  *      read / write / format / verify command set to command table
  639  *
  640  ***************************************************************************/
  641 rwcmdset(uip)
  642 struct unit_info *uip;
  643 {
  644         short                   resid;
  645         int                     slave = uip->dev->slave;
  646         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
  647         struct fdcmd            *cmdp = uip->b_cmd;
  648 
  649         switch(cip->b_buf->b_flags&(B_FORMAT|B_VERIFY|B_READ|B_WRITE)){
  650         case B_VERIFY|B_WRITE:  /* VERIFY after WRITE */
  651                 cmdp->c_rwdata[0] = RDMV;
  652                 break;
  653         case B_FORMAT:
  654                 cmdp->c_dcount = FMTCNT; 
  655                 cmdp->c_rwdata[0] = FMTM;
  656                 cmdp->c_saddr = cip->b_sector / uip->d_drtab.dr_spc;
  657                 resid = cip->b_sector % uip->d_drtab.dr_spc;
  658                 cmdp->c_rwdata[1] = slave|((resid/uip->d_drtab.dr_nsec)<<2);
  659                 cmdp->c_rwdata[2] = 
  660                         ((struct fmttbl *)cip->b_buf->b_un.b_addr)->s_type;
  661                 cmdp->c_rwdata[3] = uip->d_drtab.dr_nsec;
  662                 cmdp->c_rwdata[4] = uip->d_drtab.dr_fgpl;
  663                 cmdp->c_rwdata[5] = FMTDATA;
  664                 break;
  665         case B_WRITE:
  666         case B_READ:
  667         case B_READ|B_VERIFY:
  668                 cmdp->c_dcount = RWCNT;
  669                 if(cip->b_buf->b_flags&B_READ)
  670                         if(cip->b_buf->b_flags&B_VERIFY)
  671                                 cmdp->c_rwdata[0] = RDMV;
  672                         else
  673                                 cmdp->c_rwdata[0] = RDM;
  674                 else
  675                         cmdp->c_rwdata[0] = WTM;        /* format or write */
  676                 resid = cip->b_sector % uip->d_drtab.dr_spc;
  677                 cmdp->c_rwdata[3] = resid / uip->d_drtab.dr_nsec;
  678                 cmdp->c_rwdata[1] = slave|(cmdp->c_rwdata[3]<<2);
  679                 cmdp->c_rwdata[2] = cmdp->c_saddr = 
  680                         cip->b_sector / uip->d_drtab.dr_spc;
  681                 cmdp->c_rwdata[4] = (resid % uip->d_drtab.dr_nsec) + 1;
  682                 cmdp->c_rwdata[5] = 2;
  683                 cmdp->c_rwdata[6] = uip->d_drtab.dr_nsec;
  684                 cmdp->c_rwdata[7] = uip->d_drtab.dr_rwgpl;
  685                 cmdp->c_rwdata[8] = DTL;
  686                 D(printf("SET %x %x C%x H%x S%x %x %x %x %x ",
  687                         cmdp->c_rwdata[0], cmdp->c_rwdata[1],
  688                         cmdp->c_rwdata[2], cmdp->c_rwdata[3],
  689                         cmdp->c_rwdata[4], cmdp->c_rwdata[5],
  690                         cmdp->c_rwdata[6], cmdp->c_rwdata[7],
  691                         cmdp->c_rwdata[8]));
  692                 break;
  693         }
  694 }
  695 /*****************************************************************************
  696  *
  697  * TITLE:       fdread
  698  *
  699  * ABSTRACT:    "Raw" read.  Use physio().
  700  *
  701  * CALLS:       m765breakup (indirectly, thru physio)
  702  *
  703  ****************************************************************************/
  704 fdread(dev, uio)
  705 register dev_t  dev;
  706 struct uio *uio;
  707 { 
  708 #ifdef  MACH_KERNEL
  709         /* no need for page-size restriction */
  710         return (block_io(fdstrategy, minphys, uio));
  711 #else   MACH_KERNEL
  712         return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_READ,fdminphys,uio));
  713 #endif  MACH_KERNEL
  714 }
  715 /*****************************************************************************
  716  *
  717  * TITLE:       fdwrite
  718  *
  719  * ABSTRACT:    "Raw" write.  Use physio().
  720  *
  721  * CALLS:       m765breakup (indirectly, thru physio)
  722  *
  723  ****************************************************************************/
  724 fdwrite(dev, uio)
  725 register dev_t  dev;
  726 struct uio *uio;
  727 {
  728 #ifdef  MACH_KERNEL
  729         /* no need for page-size restriction */
  730         return (block_io(fdstrategy, minphys, uio));
  731 #else   MACH_KERNEL
  732         return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_WRITE,fdminphys,uio));
  733 #endif  MACH_KERNEL
  734 }
  735 /*****************************************************************************
  736  *
  737  * TITLE:       fdminphys
  738  *
  739  * ABSTRACT:    Trim buffer length if buffer-size is bigger than page size
  740  *
  741  * CALLS:       physio
  742  *
  743  ****************************************************************************/
  744 fdminphys(bp)
  745 struct buf      *bp;
  746 {
  747         if (bp->b_bcount > PAGESIZ)
  748                 bp->b_bcount = PAGESIZ;
  749 }
  750 #ifdef  MACH_KERNEL
  751 /* IOC_OUT only and not IOC_INOUT */
  752 io_return_t fdgetstat(dev, flavor, data, count)
  753         dev_t           dev;
  754         int             flavor;
  755         int *           data;           /* pointer to OUT array */
  756         unsigned int    *count;         /* OUT */
  757 {
  758         switch (flavor) {
  759 
  760         /* Mandatory flavors */
  761 
  762         case DEV_GET_SIZE: {
  763                 int ret;
  764                 struct disk_parms       p;
  765 
  766                 ret = fd_getparms(dev, &p);
  767                 if (ret) return ret;
  768                 data[DEV_GET_SIZE_DEVICE_SIZE] = p.dp_pnumsec * NBPSCTR;
  769                 data[DEV_GET_SIZE_RECORD_SIZE] = NBPSCTR;
  770                 *count = DEV_GET_SIZE_COUNT;
  771                 break;
  772         }
  773 
  774         /* Extra flavors */
  775 
  776         case V_GETPARMS:
  777                 if (*count < sizeof (struct disk_parms)/sizeof (int))
  778                         return (D_INVALID_OPERATION);
  779                 *count = sizeof (struct disk_parms)/sizeof(int);
  780                 return (fd_getparms(dev, data));
  781         default:
  782                 return (D_INVALID_OPERATION);
  783         }
  784 }
  785 /* IOC_VOID or IOC_IN or IOC_INOUT */
  786 /*ARGSUSED*/
  787 io_return_t fdsetstat(dev, flavor, data, count)
  788         dev_t           dev;
  789         int             flavor;
  790         int *           data;
  791         unsigned int    count;
  792 {
  793         int                     unit = UNIT(dev);
  794         switch (flavor) {
  795         case V_SETPARMS:    /* Caller wants reset_parameters */
  796                 return(fd_setparms(unit,*(int *)data));
  797         case V_FORMAT:
  798                 return(fd_format(dev,data));
  799         case V_VERIFY:  /* cmdarg : 0 == no verify, 0 != verify */
  800                 m765verify[unit] = *(int *)data;
  801                 return(D_SUCCESS);
  802         default:
  803                 return(D_INVALID_OPERATION);
  804         }
  805 }
  806 
  807 /*
  808  *      Get block size
  809  */
  810 int
  811 fddevinfo(dev, flavor, info)
  812 dev_t   dev;
  813 int     flavor;
  814 char    *info;
  815 {
  816         register struct fddrtab *dr;
  817         register struct fdpart *p;
  818         register int result = D_SUCCESS;
  819 
  820         switch (flavor) {
  821         case D_INFO_BLOCK_SIZE:
  822                 dr = &unit_info[UNIT(dev)].d_drtab;
  823 
  824                 if(dr->dr_type & OKTYPE)
  825                         *((int *) info) =  512;
  826                 else
  827                         result = D_INVALID_OPERATION;
  828 
  829                 break;
  830         default:
  831                 result = D_INVALID_OPERATION;
  832         }
  833 
  834         return(result);
  835 }
  836 #else   MACH_KERNEL
  837 /*****************************************************************************
  838  *
  839  * TITLE:       fdioctl
  840  *
  841  * ABSTRACT:    m765 driver special functions.
  842  *
  843  * CALLING ROUTINES:    kernel
  844  *
  845  ****************************************************************************/
  846 int 
  847 fdioctl(dev, cmd, cmdarg, flag)
  848 dev_t   dev;            /* major, minor numbers */
  849 int     cmd;            /* command code */
  850 int     *cmdarg;        /* user structure with parameters */
  851 int     flag;           /* not used */
  852 {
  853         register unsigned       unit = UNIT(dev);
  854         switch (cmd) {
  855         case V_SETPARMS:    /* Caller wants reset_parameters */
  856                 return(fd_setparms(unit,*cmdarg));
  857         case V_GETPARMS:    /* Caller wants device parameters */
  858                 return(fd_getparms(dev,cmdarg));
  859         case V_FORMAT:
  860                 return(fd_format(dev,cmdarg));
  861         case V_VERIFY:  /* cmdarg : 0 == no verify, 0 != verify */
  862                 m765verify[unit] = *cmdarg;
  863                 return(0);
  864         }
  865         return(EINVAL);
  866 }
  867 #endif  MACH_KERNEL
  868 /****************************************************************************
  869  *
  870  *      set fd parameters 
  871  *
  872  ****************************************************************************/
  873 int
  874 fd_setparms(unit, cmdarg)
  875 register unsigned int unit;
  876 long cmdarg;
  877 {
  878         struct fddrtab   *fdparm;
  879         spl_t            x;
  880         struct unit_info *uip = &unit_info[unit];
  881         struct  fdcmd    *cmdp = uip->b_cmd;
  882 
  883         cmdp->c_rbmtr &= ~(1<<(RBSHIFT+uip->dev->slave));
  884         if ((fdparm = getparm(MEDIATYPE(cmdarg))) == (struct fddrtab *)ERROR)
  885                 return(EINVAL);
  886         x = SPL();
  887         openchk(cmdp);
  888         cmdp->c_devflag |= FDMCHK;
  889         chkbusy(cmdp);
  890         m765sweep(uip, fdparm);
  891         uip->d_drtab.dr_type |= OKTYPE;
  892         openfre(cmdp);
  893         splx(x);
  894         return(0);
  895 }
  896 /****************************************************************************
  897  *
  898  *      get fd parameters 
  899  *
  900  ****************************************************************************/
  901 int
  902 fd_getparms(dev,cmdarg)
  903 dev_t   dev;            /* major, minor numbers */
  904 int     *cmdarg;
  905 {
  906         struct disk_parms       *diskp = (struct disk_parms *)cmdarg;
  907         register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab;
  908 
  909         if(dr->dr_type & OKTYPE){
  910                 diskp->dp_type = DPT_FLOPPY;
  911                 diskp->dp_heads = 2;
  912                 diskp->dp_sectors = dr->dr_nsec;
  913                 diskp->dp_pstartsec = 0;
  914                 diskp->dp_cyls = dr->dr_ncyl;
  915                 diskp->dp_pnumsec = dr->p_nsec;
  916                 return(0);
  917         }
  918         return(ENXIO);
  919 }
  920 /****************************************************************************
  921  *
  922  *      format command
  923  *
  924  ****************************************************************************/
  925 fd_format(dev,cmdarg)
  926 dev_t   dev;            /* major, minor numbers */
  927 int     *cmdarg;
  928 
  929 {
  930         register struct buf     *bp;
  931         register daddr_t        track;
  932         union  io_arg           *varg;
  933         u_short                 num_trks;
  934         register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab;
  935 
  936         if(!(dr->dr_type & OKTYPE))
  937                 return(EINVAL); 
  938         varg = (union io_arg *)cmdarg;
  939         num_trks = varg->ia_fmt.num_trks;
  940         track = (daddr_t)(varg->ia_fmt.start_trk*dr->dr_nsec);
  941         if((track + (num_trks*dr->dr_nsec))>dr->p_nsec)
  942                 return(EINVAL);
  943         bp = geteblk(BLKSIZE);          /* get struct buf area */
  944         while (num_trks>0) {
  945                 bp->b_flags &= ~B_DONE;
  946                 bp->b_dev = dev;
  947                 bp->b_error = 0; bp->b_resid = 0;
  948                 bp->b_flags = B_FORMAT; 
  949                 bp->b_bcount = dr->dr_nsec * FMTID;
  950                 bp->b_blkno = (daddr_t)((track << 9) / NBPSCTR);
  951                 if(makeidtbl(bp->b_un.b_addr,dr,
  952                              varg->ia_fmt.start_trk++,varg->ia_fmt.intlv))
  953                         return(EINVAL);
  954                 fdstrategy(bp);
  955                 biowait(bp);
  956                 if(bp->b_error)
  957                         if((bp->b_error == (char)EBBHARD) || 
  958                            (bp->b_error == (char)EBBSOFT))
  959                                 return(EIO);
  960                         else
  961                                 return(bp->b_error);
  962                 num_trks--;
  963                 track += dr->dr_nsec;
  964         }
  965         brelse(bp);
  966         return(0);
  967 }
  968 /****************************************************************************
  969  *
  970  *      make id table for format
  971  *
  972  ****************************************************************************/
  973 makeidtbl(tblpt,dr,track,intlv)
  974 struct fmttbl *tblpt;
  975 struct fddrtab *dr;
  976 unsigned short track;
  977 unsigned short intlv;
  978 {
  979         register int    i,j,secno;
  980 
  981         if(intlv >= dr->dr_nsec)
  982                 return(1);
  983         for(i=0; i<dr->dr_nsec; i++)
  984                 tblpt[i].sector = 0;
  985         for(i=0,j=0,secno=1; i<dr->dr_nsec; i++){
  986                 tblpt[j].cyl = track >> 1;
  987                 tblpt[j].head = track & 1;
  988                 tblpt[j].sector = secno++;
  989                 tblpt[j].s_type = 2;
  990                 if((j+=intlv) < dr->dr_nsec)
  991                         continue;
  992                 for(j-=dr->dr_nsec; j < dr->dr_nsec ; j++)
  993                         if(!tblpt[j].sector)
  994                                 break;
  995         }
  996         return(0);
  997 }
  998 /*****************************************************************************
  999  *
 1000  * TITLE:       fdintr
 1001  *
 1002  * ABSTRACT:    Handle interrupt.
 1003  *
 1004  *      Interrupt procedure for m765 driver.  Gets status of last
 1005  *      operation and performs service function according to the
 1006  *      type of interrupt.  If it was an operation complete interrupt,
 1007  *      switches on the current driver state and either declares the
 1008  *      operation done, or starts the next operation
 1009  *
 1010  ****************************************************************************/
 1011 fdintr(ctrl)
 1012 int     ctrl;
 1013 {
 1014         extern                  int(m765intrsub)();
 1015         struct unit_info        *uip = ctrl_info[ctrl].b_uip;
 1016         struct unit_info        *wup = ctrl_info[ctrl].b_wup;
 1017         struct fdcmd            *cmdp = &ctrl_info[ctrl].b_cmd;
 1018         if(cmdp->c_stsflag & INTROUT)
 1019                 untimeout(fdintr, ctrl);
 1020         cmdp->c_stsflag &= ~INTROUT;    
 1021         switch(cmdp->c_intr){
 1022         case RWFLAG:
 1023                 rwintr(uip);
 1024                 break;  
 1025         case SKFLAG:
 1026         case SKEFLAG|SKFLAG:
 1027         case RBFLAG:
 1028                 timeout(m765intrsub, uip, SEEKWAIT);
 1029                 break;
 1030         case WUPFLAG:
 1031                 cmdp->c_intr &= ~WUPFLAG;
 1032                 wakeup(wup);
 1033         }
 1034         return(0);
 1035 }
 1036 /*****************************************************************************
 1037  *
 1038  *      interrup subroutine (seek recalibrate)
 1039  *
 1040  *****************************************************************************/
 1041 m765intrsub(uip)
 1042 struct unit_info *uip;
 1043 {
 1044         struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
 1045 
 1046         if((cip->b_status = sis(uip))!=  ST0OK)
 1047                 switch(uip->b_cmd->c_intr){
 1048                 case SKFLAG:
 1049                         seekintr(uip);
 1050                         break;
 1051                 case SKEFLAG|SKFLAG:
 1052                         seekintre(uip);
 1053                         break;
 1054                 case RBFLAG:
 1055                         rbintr(uip);
 1056                 }
 1057 }
 1058 /*****************************************************************************
 1059  *
 1060  *      read / write / format / verify interrupt routine
 1061  *
 1062  *****************************************************************************/
 1063 rwintr(uip)
 1064 struct unit_info *uip;
 1065 {
 1066         int                     rsult[7];
 1067         register int            rtn, count;
 1068         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1069         struct fdcmd            *cmdp = uip->b_cmd;
 1070 
 1071         cmdp->c_intr &= ~RWFLAG;
 1072         if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY))
 1073                 if(inb(VFOREG(uip->addr))&OPENBIT){
 1074                         if(cip->b_buf->b_flags&B_FORMAT){
 1075                                 cip->b_status = TIMEOUT;
 1076                                 intrerr0(uip);
 1077                         } else {
 1078                                 if((inb(STSREG(uip->addr))&ST0OK)!=ST0OK)
 1079                                         printf("%s %d : %s\n",
 1080                                                 fderr,
 1081                                                 uip-unit_info,
 1082                                                 fdmsg[DOORERR]);
 1083                                 rstout(uip);
 1084                                 specify(uip);
 1085                                 cmdp->c_rbmtr &= RBRST;
 1086                                 cmdp->c_intr |= SKEFLAG;
 1087                                 if(cmdp->c_saddr > 2)
 1088                                         fdiseek(uip, cmdp->c_saddr-2);
 1089                                 else
 1090                                         fdiseek(uip, cmdp->c_saddr+2);
 1091                         }
 1092                         return;
 1093                 }
 1094         for( count = 0 ; count < 7 ; count++ ){
 1095                 if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
 1096                         goto rwend;
 1097                 rsult[count] = inb(DATAREG(uip->addr));
 1098         }
 1099         rtn = 0;
 1100         if(rsult[0]&0xc0){
 1101                 rtn = cmdp->c_rwdata[0]<<8;
 1102                 if(rsult[0]&0x80){ rtn |= FDCERR;   goto rwend; }
 1103                 if(rsult[1]&0x80){ rtn |= NOREC;    goto rwend; }
 1104                 if(rsult[1]&0x20){ rtn |= CRCERR;   goto rwend; }
 1105                 if(rsult[1]&0x10){ rtn |= OVERRUN;  goto rwend; }
 1106                 if(rsult[1]&0x04){ rtn |= NOREC;    goto rwend; }
 1107                 if(rsult[1]&0x02){ rtn |= WTPRT;    goto rwend; }
 1108                 if(rsult[1]&0x01){ rtn |= ADDRERR;  goto rwend; }
 1109                 rtn |= FDCERR;
 1110 rwend:          outb(0x0a, 0x06);
 1111         }
 1112         if(cip->b_status = rtn) {
 1113                 D(printf("\n->rwierr %x ", rtn));
 1114                 rwierr(uip);
 1115         } else { /* write command */
 1116                 if(((cip->b_buf->b_flags&(B_FORMAT|B_READ|B_WRITE))==B_WRITE) 
 1117                    && !(cip->b_buf->b_flags & B_VERIFY)) {
 1118                         D(printf("->w/v "));
 1119                         cip->b_buf->b_flags |= B_VERIFY;
 1120                         rwcmdset(uip);
 1121                         if(cip->b_status = outicmd(uip))
 1122                                 intrerr0(uip);
 1123                         return;
 1124                 }
 1125                 /* clear retry count */
 1126                 cip->b_buf->b_flags &= ~B_VERIFY;
 1127                 cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
 1128                 cip->b_xfercount -= cip->b_xferdma;
 1129                 cip->b_xferaddr += cip->b_xferdma;
 1130                 cip->b_sector = cip->b_sector+(cip->b_xferdma>>9);
 1131                 D(printf("->done%s\n", cip->b_xfercount?"":"." ));
 1132                 /* next address (cyl,head,sec) */
 1133                 if((int)cip->b_xfercount>0)
 1134                         m765iosub(uip);
 1135                 else
 1136                         quechk(uip);
 1137         }
 1138 }
 1139 /*****************************************************************************
 1140  *
 1141  *      read / write / format / verify error routine
 1142  *
 1143  *****************************************************************************/
 1144 rwierr(uip)
 1145 struct unit_info *uip;
 1146 {
 1147         short                   status;
 1148         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1149         struct  fdcmd           *cmdp = uip->b_cmd;
 1150 
 1151         D(printf("%x-%x-%x ", cip->b_rwerr&SRMASK, cip->b_rwerr&MRMASK, cip->b_rwerr&LRMASK));
 1152         if((cip->b_buf->b_flags&(B_READ|B_VERIFY))==(B_READ|B_VERIFY)){
 1153                 if((cip->b_rwerr&SRMASK)<MEDIARD)
 1154                         goto rwrtry;
 1155                 if((cip->b_rwerr&MRMASK)<MEDIASEEK)
 1156                         goto rwseek;
 1157                 goto rwexit;
 1158         } else
 1159                 if(cip->b_buf->b_flags&B_VERIFY){
 1160                         cip->b_buf->b_flags &= ~B_VERIFY;
 1161                         rwcmdset(uip);
 1162                 }
 1163 rwrtry: status = cip->b_status;
 1164         if((++cip->b_rwerr&SRMASK)<SRETRY)
 1165                 cip->b_status = outicmd(uip);
 1166         else {
 1167 rwseek:         cip->b_rwerr = (cip->b_rwerr&RMRMASK)+MINC;
 1168                 if((cip->b_rwerr&MRMASK)<MRETRY){
 1169                         cmdp->c_intr |= SKEFLAG;
 1170                         if(cmdp->c_saddr > 2)
 1171                                 cip->b_status=fdiseek(uip,cmdp->c_saddr-2);
 1172                         else
 1173                                 cip->b_status=fdiseek(uip,cmdp->c_saddr+2);
 1174                 } else {
 1175                         cip->b_rwerr = (cip->b_rwerr&LRMASK)+LINC;
 1176                         if((cip->b_rwerr&LRMASK)<LRETRY)
 1177                                 cip->b_status=rbirate(uip);
 1178                 }
 1179         }
 1180         if(cip->b_status){
 1181                 D(printf("ERR->intrerr0 "));
 1182                 cip->b_status = status;
 1183 rwexit:         intrerr0(uip);
 1184         }
 1185 }
 1186 /*****************************************************************************
 1187  *
 1188  *      recalibrate interrupt routine
 1189  *
 1190  *****************************************************************************/
 1191 rbintr(uip)
 1192 struct unit_info *uip;
 1193 {
 1194         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1195         struct fdcmd            *cmdp = uip->b_cmd;
 1196 
 1197         cmdp->c_intr &= ~RBFLAG;
 1198         if(cip->b_status) {
 1199                 if(++cip->b_rberr<SRETRY)
 1200                         cip->b_status = rbirate(uip);
 1201         } else {
 1202                 cmdp->c_rbmtr |= 1<<(RBSHIFT+uip->dev->slave);
 1203                 uip->b_seekaddr = 0;
 1204                 cip->b_rberr = 0;
 1205                 cip->b_status=fdiseek(uip, cmdp->c_saddr);
 1206         }
 1207         if(cip->b_status)
 1208                 intrerr0(uip);
 1209 }
 1210 /******************************************************************************
 1211  *
 1212  *      seek interrupt routine
 1213  *
 1214  *****************************************************************************/
 1215 seekintr(uip)
 1216 struct unit_info *uip;
 1217 {
 1218         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1219         struct fdcmd            *cmdp = uip->b_cmd;
 1220 
 1221         cmdp->c_intr &= ~SKFLAG;
 1222         if(cip->b_status)
 1223                 seekierr(uip, cmdp->c_saddr);
 1224         else {
 1225                 uip->b_seekaddr = cmdp->c_saddr;
 1226                 cip->b_status = outicmd(uip);
 1227         }
 1228         if(cip->b_status)
 1229                 intrerr0(uip);
 1230         else
 1231                 cip->b_seekerr = 0;
 1232 }
 1233 /*****************************************************************************
 1234  *
 1235  *      seek error retry interrupt routine
 1236  *
 1237  *****************************************************************************/
 1238 seekintre(uip)
 1239 struct unit_info *uip;
 1240 {
 1241         register char           seekpoint;
 1242         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1243         struct fdcmd            *cmdp = uip->b_cmd;
 1244 
 1245         cmdp->c_intr &= ~(SKEFLAG|SKFLAG);
 1246         if(cmdp->c_saddr > 2)
 1247                 seekpoint = cmdp->c_saddr-2;
 1248         else
 1249                 seekpoint = cmdp->c_saddr+2;
 1250         if(cip->b_status)
 1251                 seekierr(uip, seekpoint);
 1252         else {
 1253                 uip->b_seekaddr = seekpoint;
 1254                 cip->b_status = fdiseek(uip, cmdp->c_saddr);
 1255         }
 1256         if(cip->b_status)
 1257                 intrerr0(uip);
 1258         else
 1259                 cip->b_seekerr = 0;
 1260 }
 1261 /*****************************************************************************
 1262  *
 1263  *      seek error routine
 1264  *
 1265  *****************************************************************************/
 1266 seekierr(uip, seekpoint)
 1267 struct unit_info *uip;
 1268 register char           seekpoint;
 1269 {
 1270         struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
 1271 
 1272         if((++cip->b_seekerr&SRMASK)<SRETRY)
 1273                 cip->b_status=fdiseek(uip, seekpoint);
 1274         else {
 1275                 cip->b_seekerr = (cip->b_seekerr&MRMASK) + MINC;
 1276                 if((cip->b_seekerr&MRMASK)<MRETRY)
 1277                         cip->b_status=rbirate(uip);
 1278         }
 1279         if(cip->b_status)
 1280                 intrerr0(uip);
 1281 }
 1282 /*****************************************************************************
 1283  *
 1284  * TITLE:       m765sweep
 1285  *
 1286  * ABSTRACT:    Perform an initialization sweep.  
 1287  *
 1288  **************************************************************************/
 1289 m765sweep(uip, cdr)
 1290 struct unit_info *uip;
 1291 register struct fddrtab  *cdr;  /* device initialization data */
 1292 {
 1293         register struct fddrtab *dr = &uip->d_drtab;
 1294 
 1295         dr->dr_ncyl = cdr->dr_ncyl;
 1296         dr->dr_nsec = cdr->dr_nsec;
 1297         dr->dr_spc  = cdr->dr_spc;
 1298         dr->p_nsec  = cdr->p_nsec;
 1299         dr->dr_type = cdr->dr_type;
 1300         dr->dr_rwgpl= cdr->dr_rwgpl;
 1301         dr->dr_fgpl = cdr->dr_fgpl;
 1302 }
 1303 /*****************************************************************************
 1304  *
 1305  *  TITLE:  m765disksort
 1306  *
 1307  *****************************************************************************/
 1308 fd_disksort(uip, bp)
 1309 struct unit_info *uip;          /*  Pointer to head of active queue     */
 1310 register struct buf *bp;        /*  Pointer to buffer to be inserted    */
 1311 {
 1312         register struct buf *bp2; /*  Pointer to next buffer in queue   */
 1313         register struct buf *bp1; /*  Pointer where to insert buffer    */
 1314 
 1315         if (!(bp1 = uip->av_forw)) {
 1316                 /* No other buffers to compare against */
 1317                 uip->av_forw = bp;
 1318                 bp->av_forw = 0;
 1319                 return;
 1320         }
 1321         bp2 = bp1->av_forw;
 1322         while(bp2 && (relative(bp1->b_pfcent,bp->b_pfcent) >=
 1323                       relative(bp1->b_pfcent,bp2->b_pfcent))) {
 1324                 bp1 = bp2;
 1325                 bp2 = bp1->av_forw;
 1326         }
 1327         bp1->av_forw = bp;
 1328         bp->av_forw = bp2;
 1329 }
 1330 /*****************************************************************************
 1331  *
 1332  *      Set Interrupt error and FDC reset
 1333  *
 1334  *****************************************************************************/
 1335 intrerr0(uip)
 1336 struct unit_info *uip;
 1337 {
 1338         struct buf              *bp; /* Pointer to next buffer in queue */
 1339         int                     resid;
 1340         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1341         struct  fdcmd           *cmdp = uip->b_cmd;
 1342         register struct fddrtab *dr = &uip->d_drtab;
 1343 
 1344         if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)){
 1345                 resid = cip->b_xfercount = cip->b_xferdma-1-inb(DMACNT)*0x101;
 1346                 resid = (cip->b_sector + (resid>>9)) % dr->dr_spc;
 1347                 printf("%s %d : %s\n",
 1348                         fderr,
 1349                         uip->dev->slave,
 1350                         fdmsg[cip->b_status&BYTEMASK]);
 1351                 printf("cylinder = %d  ",cmdp->c_saddr);
 1352                 printf("head = %d  sector = %d  byte/sec = %d\n",
 1353                 resid / dr->dr_nsec , (resid % dr->dr_nsec)+1 , 512);
 1354         }
 1355         cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
 1356         cmdp->c_intr = CMDRST;
 1357         if(((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)) &&
 1358            uip->dev->slave)
 1359                 dr->dr_type &= ~OKTYPE; 
 1360         bp = cip->b_buf;
 1361         bp->b_flags |= B_ERROR;
 1362         switch(cip->b_status&BYTEMASK){
 1363         case ADDRERR:
 1364         case OVERRUN:
 1365         case FDCERR:
 1366         case TIMEOUT:
 1367                 bp->b_error = EIO;
 1368                 break;
 1369         case WTPRT:
 1370 #ifdef MACH_KERNEL
 1371                 bp->b_error = ENXIO;
 1372 #else
 1373                 bp->b_error = ENODEV;
 1374 #endif
 1375                 break;
 1376         case NOREC:
 1377                 bp->b_error = EBBHARD;
 1378                 break;
 1379         case CRCERR:
 1380                 bp->b_error = EBBSOFT;
 1381         }
 1382         rstout(uip);
 1383         specify(uip);
 1384         cmdp->c_rbmtr &= RBRST;
 1385         quechk(uip);
 1386 }
 1387 /*****************************************************************************
 1388  *
 1389  *      Next queue check routine
 1390  *
 1391  *****************************************************************************/
 1392 quechk(uip)
 1393 struct unit_info *uip;
 1394 {
 1395         register struct buf     *bp = uip->av_forw;
 1396         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1397         struct unit_info        *loop;
 1398         struct fdcmd            *cmdp = uip->b_cmd;
 1399         /* clear retry count */
 1400         cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
 1401         bp->b_resid = bp->b_resid + cip->b_xfercount;
 1402         uip->av_forw=bp->av_forw;
 1403         if (!uip->av_forw && uip->wakeme) {
 1404                 uip->wakeme = 0;
 1405                 wakeup(uip);
 1406         }
 1407         biodone(bp);
 1408         loop = uip;
 1409         do {
 1410                 loop=loop->b_unitf;
 1411                 if (loop->av_forw) {
 1412                         m765io(loop);
 1413                         return;
 1414                 }
 1415         } while (loop!=uip);
 1416         cip->b_uip = 0;
 1417         cmdp->c_stsflag &= ~MTRFLAG;
 1418         mtr_on(uip);
 1419         cmdp->c_devflag &= ~STRCHK;
 1420         if(cmdp->c_devflag & STRWAIT){
 1421                 cmdp->c_devflag &= ~STRWAIT;
 1422                 wakeup(&cmdp->c_devflag);
 1423         }
 1424 }
 1425 fdprint(dev,str)
 1426 dev_t   dev;
 1427 char    *str;
 1428 {
 1429         printf("floppy disk driver: %s on bad dev %d, partition %d\n",
 1430                         str, UNIT(dev), 0);
 1431 }
 1432 fdsize()
 1433 {
 1434         printf("fdsize()        -- not implemented\n");
 1435 }
 1436 fddump()
 1437 {
 1438         printf("fddump()        -- not implemented\n");
 1439 }
 1440 /*****************************************************************************
 1441  *
 1442  *      fdc reset routine
 1443  *
 1444  *****************************************************************************/
 1445 rstout(uip)
 1446 struct unit_info *uip;
 1447 {
 1448         register int    outd;
 1449 
 1450         outd = ((uip->b_cmd->c_rbmtr&MTRMASK)<<MTR_ON)|uip->dev->slave;
 1451         outb(CTRLREG(uip->addr), outd);
 1452         outd |= FDC_RST;
 1453         outb(CTRLREG(uip->addr), outd);
 1454         outd |= DMAREQ;
 1455         outb(CTRLREG(uip->addr), outd);
 1456 }
 1457 /*****************************************************************************
 1458  *
 1459  *      specify command routine
 1460  *
 1461  *****************************************************************************/
 1462 specify(uip)
 1463 struct unit_info *uip;
 1464 {
 1465         /* status check */
 1466         if(fdc_sts(FD_OSTS, uip))
 1467                 return;
 1468         /* Specify command */
 1469         outb(DATAREG(uip->addr), SPCCMD);
 1470         /* status check */
 1471         if(fdc_sts(FD_OSTS, uip))
 1472                 return;
 1473         /* Step rate,Head unload time */
 1474         outb(DATAREG(uip->addr), SRTHUT);
 1475         /* status check */
 1476         if(fdc_sts(FD_OSTS, uip))
 1477                 return;
 1478         /* Head load time,Non DMA Mode*/
 1479         outb(DATAREG(uip->addr), HLTND);
 1480         return;
 1481 }
 1482 /****************************************************************************
 1483  *
 1484  *      recalibrate command routine
 1485  *
 1486  ****************************************************************************/
 1487 rbrate(mtype,uip)
 1488 char     mtype;
 1489 struct unit_info *uip;
 1490 {
 1491         register int    rtn = 1, rty_flg=2;
 1492         spl_t           x;
 1493         struct  fdcmd   *cmdp = uip->b_cmd;
 1494 
 1495         rbskrate(uip, mtype);                   /* set transfer rate */
 1496         while((rty_flg--)&&rtn){
 1497                 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
 1498                         break;
 1499                 /*recalibrate command*/
 1500                 outb(DATAREG(uip->addr), RBCMD);
 1501                 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
 1502                         break;
 1503                 /* Device to wake up specified in open */
 1504                 cmdp->c_intr |= WUPFLAG;
 1505                 x = SPL();
 1506                 outb(DATAREG(uip->addr), uip->dev->slave);
 1507                 rtn = ERROR;
 1508                 while(rtn) {
 1509                         uip->wakeme = 1;
 1510                         sleep(uip, PZERO);
 1511                         if((rtn = sis(uip)) == ST0OK)
 1512                           /* Device to wake up specified in open */
 1513                                 cmdp->c_intr |= WUPFLAG;
 1514                         else
 1515                                 break;
 1516                 }
 1517                 splx(x);
 1518         }
 1519         return(rtn);
 1520 }
 1521 /*****************************************************************************
 1522  *
 1523  *      seek command routine
 1524  *
 1525  ****************************************************************************/
 1526 fdseek(mtype, uip, cylno)
 1527 register char   mtype;
 1528 struct unit_info *uip;
 1529 register int    cylno;
 1530 {
 1531         spl_t           x;
 1532         int             rtn;
 1533         struct  fdcmd   *cmdp = uip->b_cmd;
 1534 
 1535         rbskrate(uip, mtype);
 1536         if(rtn = fdc_sts(FD_OSTS, uip))                 /* status check */
 1537                 return(rtn);
 1538         outb(DATAREG(uip->addr), SEEKCMD);              /* seek command */
 1539         if(rtn = fdc_sts(FD_OSTS, uip))                 /* status check */
 1540                 return(rtn);
 1541         outb(DATAREG(uip->addr), uip->dev->slave);      /* drive number */
 1542         if(rtn = fdc_sts(FD_OSTS, uip))                 /* status check */
 1543                 return(rtn);
 1544         x = SPL();
 1545         /* Device to wake up specified in open */
 1546         cmdp->c_intr |= WUPFLAG;
 1547         outb(DATAREG(uip->addr), cylno);                /* seek count */
 1548         rtn = ERROR;
 1549         while(rtn){     
 1550                 uip->wakeme = 1;
 1551                 sleep(uip, PZERO);
 1552                 if((rtn = sis(uip)) == ST0OK)
 1553                   /* Device to wake up specified in open */
 1554                         cmdp->c_intr |= WUPFLAG;
 1555                 else
 1556                         break;
 1557         }
 1558         splx(x);
 1559         return(rtn);
 1560 }
 1561 /*****************************************************************************
 1562  *
 1563  *      seek commnd routine(use interrupt)
 1564  *
 1565  *****************************************************************************/
 1566 fdiseek(uip, cylno) 
 1567 struct unit_info *uip;
 1568 int     cylno;
 1569 {
 1570         register int    rtn;
 1571 
 1572         D(printf("SK %x ", cylno));
 1573         rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */
 1574         if(rtn = fdc_sts(FD_OSTS, uip))         /* status check */
 1575                 goto fdiend;
 1576         outb(DATAREG(uip->addr), SEEKCMD);      /* seek command */
 1577         if(rtn = fdc_sts(FD_OSTS, uip))         /* status check */
 1578                 goto fdiend;
 1579         outb(DATAREG(uip->addr), uip->dev->slave);      /* drive number */
 1580         if(rtn = fdc_sts(FD_OSTS, uip))         /* status check */
 1581                 goto fdiend;
 1582         uip->b_seekaddr = cylno;
 1583         if(uip->d_drtab.dr_type&DOUBLE)
 1584                 cylno = cylno * 2;
 1585         uip->b_cmd->c_intr |= SKFLAG;
 1586         outb(DATAREG(uip->addr), cylno);        /* seek count */
 1587 fdiend: 
 1588         if(rtn)
 1589                 rtn |= SEEKCMD<<8;
 1590         return(rtn);
 1591 }
 1592 /*****************************************************************************
 1593  *
 1594  *      recalibrate command routine(use interrupt)
 1595  *
 1596  *****************************************************************************/
 1597 rbirate(uip)
 1598 struct unit_info *uip;
 1599 {
 1600         register int    rtn;
 1601 
 1602         rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */
 1603         if(!(rtn = fdc_sts(FD_OSTS, uip))) {            /* status check */
 1604                 /* recalibrate command */
 1605                 outb(DATAREG(uip->addr), RBCMD);
 1606                 if(!(rtn = fdc_sts(FD_OSTS, uip))) {    /* status check */
 1607                         uip->b_cmd->c_intr |= RBFLAG;
 1608                         outb(DATAREG(uip->addr), uip->dev->slave);
 1609                 }
 1610         }
 1611         return(rtn ? rtn|RBCMD<<8 : 0);
 1612 }
 1613 /*****************************************************************************
 1614  *
 1615  *      read / write / format / verify command out routine(use interrupt)
 1616  *
 1617  *****************************************************************************/
 1618 outicmd(uip)
 1619 struct unit_info *uip;
 1620 {
 1621         int                     rtn;
 1622         register int            *data,cnt0,dmalen;
 1623         register long           address;
 1624         struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
 1625         struct fdcmd            *cmdp = uip->b_cmd;
 1626         spl_t                    x = splhi();
 1627 
 1628         outb(DMACMD1,DMADATA0); /* DMA #1 command register      */
 1629         outb(DMAMSK1,DMADATA1); /* DMA #1 all mask register     */
 1630         /* Perhaps outb(0x0a,0x02); might work better on line above? */
 1631         switch(cmdp->c_rwdata[0]){
 1632         case RDM:
 1633                 D(printf("RDM"));
 1634                 outb(DMABPFF,DMARD);
 1635                 outb(DMAMODE,DMARD);
 1636                 break;
 1637         case WTM:
 1638         case FMTM:
 1639                 D(printf("W"));
 1640                 outb(DMABPFF,DMAWT);
 1641                 outb(DMAMODE,DMAWT);
 1642                 break;
 1643         case RDMV:
 1644                 D(printf("RDMV"));
 1645                 outb(DMABPFF,DMAVRF);
 1646                 outb(DMAMODE,DMAVRF);
 1647         }
 1648         /* get work buffer physical address */
 1649         address = kvtophys(cip->b_xferaddr);
 1650         dmalen = i386_trunc_page(address) + I386_PGBYTES - address;
 1651         if ( (cip->b_rwerr&MRMASK) >= 0x10)
 1652                 dmalen = 0x200;
 1653         if (dmalen<=cip->b_xferdma) 
 1654                 cip->b_xferdma = dmalen;
 1655         else
 1656                 dmalen = cip->b_xferdma;
 1657         D(printf(" %x L%x ", address, dmalen));
 1658         /* set buffer address */
 1659         outb(DMAADDR,(int)address&BYTEMASK);
 1660         outb(DMAADDR,(((int)address>>8)&BYTEMASK));
 1661         outb(DMAPAGE,(((int)address>>16)&BYTEMASK));
 1662         /* set transfer count */
 1663         outb(DMACNT,(--dmalen)&BYTEMASK);
 1664         outb(DMACNT,((dmalen>>8)&BYTEMASK));
 1665         outb(DMAMSK,CHANNEL2);
 1666         splx(x);
 1667         trfrate(uip, uip->d_drtab.dr_type);     /* set transfer rate */
 1668         data = &cmdp->c_rwdata[0];
 1669         for(cnt0 = 0; cnt0<cmdp->c_dcount; cnt0++,data++){
 1670                 if(rtn = fdc_sts(FD_OSTS, uip)) /*status check*/
 1671                         break;
 1672                 outb(DATAREG(uip->addr), *data);
 1673         }
 1674         if(!rtn){
 1675                 cmdp->c_intr |= RWFLAG;
 1676                 cmdp->c_stsflag |= INTROUT;
 1677                 cnt0 = ((cip->b_buf->b_flags&(B_READ|B_VERIFY)) ==
 1678                         (B_READ|B_VERIFY))?TOUT:ITOUT;
 1679 #ifdef  MACH_KERNEL
 1680                 timeout(fdintr,uip->dev->ctlr,cnt0);
 1681 #else   MACH_KERNEL
 1682                 cmdp->c_timeid = timeout(fdintr,uip->dev->ctlr,cnt0);
 1683 #endif  MACH_KERNEL
 1684         }
 1685         return(rtn);
 1686 }
 1687 /*****************************************************************************
 1688  *
 1689  *      sense interrupt status routine
 1690  *
 1691  *****************************************************************************/
 1692 sis(uip)
 1693 struct unit_info *uip;
 1694 {
 1695         register int    rtn, st0;
 1696 
 1697         if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
 1698                 return(rtn);
 1699         outb(DATAREG(uip->addr), SISCMD);
 1700         if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
 1701                 return(rtn);
 1702         st0 = inb(DATAREG(uip->addr)) & ST0OK;  /* get st0 */
 1703         if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
 1704                 return(rtn);
 1705         inb(DATAREG(uip->addr));        /* get pcn */
 1706         if (st0&(ST0AT|ST0IC))
 1707                 st0 = FDCERR;
 1708         return(st0);
 1709 }
 1710 
 1711 /*****************************************************************************
 1712  *
 1713  *      fdc status get routine
 1714  *
 1715  *****************************************************************************/
 1716 fdc_sts(mode, uip)
 1717 register int    mode;
 1718 struct unit_info *uip;
 1719 {
 1720         register int    ind;
 1721         int             cnt0 = STSCHKCNT;
 1722 
 1723         while(cnt0--)
 1724                 if(((ind=inb(STSREG(uip->addr))) & DATAOK) && 
 1725                    ((ind & DTOCPU) == mode))
 1726                         return(0);
 1727         return(TIMEOUT);
 1728 }
 1729 /*****************************************************************************
 1730  *
 1731  *      motor on routine
 1732  *
 1733  *****************************************************************************/
 1734 mtr_on(uip)
 1735 struct unit_info *uip;
 1736 {
 1737         extern          int(mtr_off)();
 1738         extern          int(wakeup)();
 1739         struct  fdcmd   *cmdp = uip->b_cmd;
 1740 
 1741         if(!(mtr_start(uip))){
 1742                 timeout(wakeup,&cmdp->c_stsflag,HZ);
 1743                 sleep(&cmdp->c_stsflag,PZERO);
 1744         }
 1745         cmdp->c_stsflag |= MTROFF;
 1746 #ifdef  MACH_KERNEL
 1747         timeout(mtr_off,uip,MTRSTOP);
 1748 #else   MACH_KERNEL
 1749         cmdp->c_mtrid = timeout(mtr_off,uip,MTRSTOP);
 1750 #endif  MACH_KERNEL
 1751 }
 1752 /*****************************************************************************
 1753  *
 1754  *      motor start routine
 1755  *
 1756  *****************************************************************************/
 1757 mtr_start(uip)
 1758 struct unit_info *uip;
 1759 {
 1760         int             status;
 1761         int             (mtr_off)();
 1762         struct  fdcmd   *cmdp = uip->b_cmd;
 1763         int             slave = uip->dev->slave;
 1764         if(cmdp->c_stsflag & MTROFF){
 1765                 untimeout(mtr_off, uip);
 1766                 cmdp->c_stsflag &= ~MTROFF;
 1767         }
 1768         status = cmdp->c_rbmtr&(1<<slave);
 1769         cmdp->c_rbmtr |= (1<<slave);
 1770         outb(CTRLREG(uip->addr), ((cmdp->c_rbmtr&MTRMASK)<<MTR_ON)|
 1771                                      FDC_RST|slave|DMAREQ);
 1772         return(status);
 1773 }
 1774 /*****************************************************************************
 1775  *
 1776  *      motor off routine
 1777  *
 1778  *****************************************************************************/
 1779 mtr_off(uip)
 1780 struct unit_info *uip;
 1781 {
 1782         struct  fdcmd   *cmdp = uip->b_cmd;
 1783 
 1784         cmdp->c_stsflag &= ~MTROFF;
 1785         if(!(cmdp->c_stsflag&MTRFLAG)){
 1786                 cmdp->c_rbmtr &= MTRRST;
 1787                 outb(CTRLREG(uip->addr), FDC_RST | DMAREQ);
 1788         }
 1789 }

Cache object: 214082c134c1d366246d1d8f9007c746


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