root/dev/isa/fdc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fdcprobe
  2. fdcattach
  3. fddprint
  4. fdcresult
  5. out_fdc
  6. fdcstart
  7. fdcstatus
  8. fdcpseudointr
  9. fdcintr

    1 /*      $OpenBSD: fdc.c,v 1.17 2005/09/19 01:28:04 deraadt Exp $        */
    2 /*      $NetBSD: fd.c,v 1.90 1996/05/12 23:12:03 mycroft Exp $  */
    3 
    4 /*-
    5  * Copyright (c) 1993, 1994, 1995 Charles Hannum.
    6  * Copyright (c) 1990 The Regents of the University of California.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to Berkeley by
   10  * Don Ahn.
   11  *
   12  * Portions Copyright (c) 1993, 1994 by
   13  *  jc@irbs.UUCP (John Capo)
   14  *  vak@zebub.msk.su (Serge Vakulenko)
   15  *  ache@astral.msk.su (Andrew A. Chernov)
   16  *  joerg_wunsch@uriah.sax.de (Joerg Wunsch)
   17  *
   18  * Redistribution and use in source and binary forms, with or without
   19  * modification, are permitted provided that the following conditions
   20  * are met:
   21  * 1. Redistributions of source code must retain the above copyright
   22  *    notice, this list of conditions and the following disclaimer.
   23  * 2. Redistributions in binary form must reproduce the above copyright
   24  *    notice, this list of conditions and the following disclaimer in the
   25  *    documentation and/or other materials provided with the distribution.
   26  * 3. Neither the name of the University nor the names of its contributors
   27  *    may be used to endorse or promote products derived from this software
   28  *    without specific prior written permission.
   29  *
   30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   40  * SUCH DAMAGE.
   41  *
   42  *      @(#)fd.c        7.4 (Berkeley) 5/25/91
   43  */
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/kernel.h>
   48 #include <sys/file.h>
   49 #include <sys/ioctl.h>
   50 #include <sys/device.h>
   51 #include <sys/disklabel.h>
   52 #include <sys/dkstat.h>
   53 #include <sys/disk.h>
   54 #include <sys/buf.h>
   55 #include <sys/malloc.h>
   56 #include <sys/uio.h>
   57 #include <sys/mtio.h>
   58 #include <sys/syslog.h>
   59 #include <sys/queue.h>
   60 #include <sys/timeout.h>
   61 
   62 #include <machine/cpu.h>
   63 #include <machine/bus.h>
   64 #include <machine/conf.h>
   65 #include <machine/intr.h>
   66 #include <machine/ioctl_fd.h>
   67 
   68 #include <dev/isa/isavar.h>
   69 #include <dev/isa/isadmavar.h>
   70 #include <dev/isa/fdreg.h>
   71 
   72 #if defined(__i386__) || defined(__amd64__)     /* XXX */
   73 #include <dev/ic/mc146818reg.h>                 /* for NVRAM access */
   74 #include <i386/isa/nvram.h>
   75 #endif
   76 
   77 #include <dev/isa/fdlink.h>
   78 
   79 #include "fd.h"
   80 
   81 /* controller driver configuration */
   82 int fdcprobe(struct device *, void *, void *);
   83 void fdcattach(struct device *, struct device *, void *);
   84 
   85 struct cfattach fdc_ca = {
   86         sizeof(struct fdc_softc), fdcprobe, fdcattach
   87 };
   88 
   89 struct cfdriver fdc_cd = {
   90         NULL, "fdc", DV_DULL
   91 };
   92 
   93 int fddprint(void *, const char *);
   94 int fdcintr(void *);
   95 
   96 int
   97 fdcprobe(parent, match, aux)
   98         struct device *parent;
   99         void *match, *aux;
  100 {
  101         register struct isa_attach_args *ia = aux;
  102         bus_space_tag_t iot;
  103         bus_space_handle_t ioh;
  104         bus_space_handle_t ioh_ctl;
  105         int rv;
  106 
  107         iot = ia->ia_iot;
  108         rv = 0;
  109 
  110         /* Map the i/o space. */
  111         if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh))
  112                 return 0;
  113         if (bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
  114                           FDCTL_NPORT, 0, &ioh_ctl))
  115                 return 0;
  116 
  117         /* reset */
  118         bus_space_write_1(iot, ioh, fdout, 0);
  119         delay(100);
  120         bus_space_write_1(iot, ioh, fdout, FDO_FRST);
  121 
  122         /* see if it can handle a command */
  123         if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
  124                 goto out;
  125         out_fdc(iot, ioh, 0xdf);
  126         out_fdc(iot, ioh, 2);
  127 
  128         rv = 1;
  129         ia->ia_iosize = FDC_NPORT;
  130         ia->ia_msize = 0;
  131 
  132  out:
  133         bus_space_unmap(iot, ioh, FDC_NPORT);
  134         bus_space_unmap(iot, ioh_ctl, FDCTL_NPORT);
  135         return rv;
  136 }
  137 
  138 void
  139 fdcattach(parent, self, aux)
  140         struct device *parent, *self;
  141         void *aux;
  142 {
  143         struct fdc_softc *fdc = (void *)self;
  144         bus_space_tag_t iot;
  145         bus_space_handle_t ioh;
  146         bus_space_handle_t ioh_ctl;
  147         struct isa_attach_args *ia = aux;
  148         struct fdc_attach_args fa;
  149         int type;
  150 
  151         iot = ia->ia_iot;
  152 
  153         /* Re-map the I/O space. */
  154         if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh) ||
  155             bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
  156                           FDCTL_NPORT, 0, &ioh_ctl))
  157                 panic("fdcattach: couldn't map I/O ports");
  158 
  159         fdc->sc_iot = iot;
  160         fdc->sc_ioh = ioh;
  161         fdc->sc_ioh_ctl = ioh_ctl;
  162 
  163         fdc->sc_drq = ia->ia_drq;
  164         fdc->sc_state = DEVIDLE;
  165         TAILQ_INIT(&fdc->sc_link.fdlink.sc_drives);     /* XXX */
  166 
  167         printf("\n");
  168 
  169         fdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  170             IPL_BIO, fdcintr, fdc, fdc->sc_dev.dv_xname);
  171 
  172 #if defined(__i386__) || defined(__amd64__)
  173         /*
  174          * The NVRAM info only tells us about the first two disks on the
  175          * `primary' floppy controller.
  176          */
  177         if (fdc->sc_dev.dv_unit == 0)
  178                 type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
  179         else
  180 #endif
  181                 type = -1;
  182 
  183         timeout_set(&fdc->fdcpseudointr_to, fdcpseudointr, fdc);
  184 
  185         /* physical limit: four drives per controller. */
  186         for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
  187                 fa.fa_flags = 0;
  188                 fa.fa_type = 0;
  189 #if NFD > 0
  190                 if (type >= 0 && fa.fa_drive < 2)
  191                         fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
  192                             type, fa.fa_drive);
  193                 else
  194 #endif
  195                         fa.fa_deftype = NULL;           /* unknown */
  196                 (void)config_found(self, (void *)&fa, fddprint);
  197         }
  198 }
  199 
  200 /*
  201  * Print the location of a disk/tape drive (called just before attaching the
  202  * the drive).  If `fdc' is not NULL, the drive was found but was not
  203  * in the system config file; print the drive name as well.
  204  * Return QUIET (config_find ignores this if the device was configured) to
  205  * avoid printing `fdN not configured' messages.
  206  */
  207 int
  208 fddprint(aux, fdc)
  209         void *aux;
  210         const char *fdc;
  211 {
  212         register struct fdc_attach_args *fa = aux;
  213 
  214         if (!fdc)
  215                 printf(" drive %d", fa->fa_drive);
  216         return QUIET;
  217 }
  218 
  219 int
  220 fdcresult(fdc)
  221         struct fdc_softc *fdc;
  222 {
  223         bus_space_tag_t iot = fdc->sc_iot;
  224         bus_space_handle_t ioh = fdc->sc_ioh;
  225         u_char i;
  226         int j = 100000, n = 0;
  227 
  228         for (; j; j--) {
  229                 i = bus_space_read_1(iot, ioh, fdsts) &
  230                     (NE7_DIO | NE7_RQM | NE7_CB);
  231                 if (i == NE7_RQM)
  232                         return n;
  233                 if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
  234                         if (n >= sizeof(fdc->sc_status)) {
  235                                 log(LOG_ERR, "fdcresult: overrun\n");
  236                                 return -1;
  237                         }
  238                         fdc->sc_status[n++] =
  239                             bus_space_read_1(iot, ioh, fddata);
  240                 }
  241                 delay(10);
  242         }
  243         return -1;
  244 }
  245 
  246 int
  247 out_fdc(iot, ioh, x)
  248         bus_space_tag_t iot;
  249         bus_space_handle_t ioh;
  250         u_char x;
  251 {
  252         int i = 100000;
  253 
  254         while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
  255         if (i <= 0)
  256                 return -1;
  257         while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
  258         if (i <= 0)
  259                 return -1;
  260         bus_space_write_1(iot, ioh, fddata, x);
  261         return 0;
  262 }
  263 
  264 void
  265 fdcstart(fdc)
  266         struct fdc_softc *fdc;
  267 {
  268 
  269 #ifdef DIAGNOSTIC
  270         /* only got here if controller's drive queue was inactive; should
  271            be in idle state */
  272         if (fdc->sc_state != DEVIDLE) {
  273                 printf("fdcstart: not idle\n");
  274                 return;
  275         }
  276 #endif
  277         (void) fdcintr(fdc);
  278 }
  279 
  280 void
  281 fdcstatus(dv, n, s)
  282         struct device *dv;
  283         int n;
  284         char *s;
  285 {
  286         struct fdc_softc *fdc = (void *)dv->dv_parent;
  287 
  288         if (n == 0) {
  289                 out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
  290                 (void) fdcresult(fdc);
  291                 n = 2;
  292         }
  293 
  294         printf("%s: %s", dv->dv_xname, s);
  295 
  296         switch (n) {
  297         case 0:
  298                 printf("\n");
  299                 break;
  300         case 2:
  301                 printf(" (st0 %b cyl %d)\n",
  302                     fdc->sc_status[0], NE7_ST0BITS,
  303                     fdc->sc_status[1]);
  304                 break;
  305         case 7:
  306                 printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
  307                     fdc->sc_status[0], NE7_ST0BITS,
  308                     fdc->sc_status[1], NE7_ST1BITS,
  309                     fdc->sc_status[2], NE7_ST2BITS,
  310                     fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
  311                 break;
  312 #ifdef DIAGNOSTIC
  313         default:
  314                 printf("\nfdcstatus: weird size");
  315                 break;
  316 #endif
  317         }
  318 }
  319 
  320 void
  321 fdcpseudointr(arg)
  322         void *arg;
  323 {
  324         int s;
  325 
  326         /* Just ensure it has the right spl. */
  327         s = splbio();
  328         (void) fdcintr(arg);
  329         splx(s);
  330 }
  331 
  332 int
  333 fdcintr(arg)
  334         void *arg;
  335 {
  336 #if NFD > 0
  337         struct fdc_softc *fdc = arg;
  338         extern int fdintr(struct fdc_softc *);
  339 
  340         /* Will switch on device type, shortly. */
  341         return (fdintr(fdc));
  342 #else
  343         printf("fdcintr: got interrupt, but no devices!\n");
  344         return (1);
  345 #endif
  346 }

/* [<][>][^][v][top][bottom][index][help] */