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/dev/isa/fdc.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 /*      $OpenBSD: fdc.c,v 1.24 2022/04/06 18:59:28 naddy 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/ioctl.h>
   49 #include <sys/device.h>
   50 #include <sys/disklabel.h>
   51 #include <sys/disk.h>
   52 #include <sys/buf.h>
   53 #include <sys/malloc.h>
   54 #include <sys/uio.h>
   55 #include <sys/mtio.h>
   56 #include <sys/syslog.h>
   57 #include <sys/queue.h>
   58 #include <sys/timeout.h>
   59 #include <sys/kthread.h>
   60 
   61 #include <machine/cpu.h>
   62 #include <machine/bus.h>
   63 #include <machine/conf.h>
   64 #include <machine/intr.h>
   65 #include <machine/ioctl_fd.h>
   66 
   67 #include <dev/isa/isavar.h>
   68 #include <dev/isa/fdreg.h>
   69 
   70 #if defined(__i386__) || defined(__amd64__)     /* XXX */
   71 #include <dev/ic/mc146818reg.h>                 /* for NVRAM access */
   72 #include <i386/isa/nvram.h>
   73 #endif
   74 
   75 #include <dev/isa/fdlink.h>
   76 
   77 #include "fd.h"
   78 
   79 /* controller driver configuration */
   80 int fdcprobe(struct device *, void *, void *);
   81 void fdcattach(struct device *, struct device *, void *);
   82 void fdcattach_deferred(void *);
   83 void fdc_create_kthread(void *);
   84 
   85 const 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(struct device *parent, void *match, void *aux)
   98 {
   99         register struct isa_attach_args *ia = aux;
  100         bus_space_tag_t iot;
  101         bus_space_handle_t ioh;
  102         bus_space_handle_t ioh_ctl;
  103         int rv;
  104 
  105         iot = ia->ia_iot;
  106         rv = 0;
  107 
  108         /* Map the i/o space. */
  109         if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh))
  110                 return 0;
  111         if (bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
  112                           FDCTL_NPORT, 0, &ioh_ctl))
  113                 return 0;
  114 
  115         /* reset */
  116         bus_space_write_1(iot, ioh, fdout, 0);
  117         delay(100);
  118         bus_space_write_1(iot, ioh, fdout, FDO_FRST);
  119 
  120         /* see if it can handle a command */
  121         if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
  122                 goto out;
  123         out_fdc(iot, ioh, 0xdf);
  124         out_fdc(iot, ioh, 2);
  125 
  126         rv = 1;
  127         ia->ia_iosize = FDC_NPORT;
  128         ia->ia_msize = 0;
  129 
  130  out:
  131         bus_space_unmap(iot, ioh, FDC_NPORT);
  132         bus_space_unmap(iot, ioh_ctl, FDCTL_NPORT);
  133         return rv;
  134 }
  135 
  136 void
  137 fdcattach(struct device *parent, struct device *self, void *aux)
  138 {
  139         struct fdc_softc *fdc = (void *)self;
  140         bus_space_tag_t iot;
  141         bus_space_handle_t ioh;
  142         bus_space_handle_t ioh_ctl;
  143         struct isa_attach_args *ia = aux;
  144 
  145         iot = ia->ia_iot;
  146 
  147         /* Re-map the I/O space. */
  148         if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh) ||
  149             bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
  150                           FDCTL_NPORT, 0, &ioh_ctl))
  151                 panic("fdcattach: couldn't map I/O ports");
  152 
  153         fdc->sc_iot = iot;
  154         fdc->sc_ioh = ioh;
  155         fdc->sc_ioh_ctl = ioh_ctl;
  156 
  157         fdc->sc_drq = ia->ia_drq;
  158         fdc->sc_state = DEVIDLE;
  159         TAILQ_INIT(&fdc->sc_link.fdlink.sc_drives);     /* XXX */
  160 
  161         printf("\n");
  162 
  163         fdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  164             IPL_BIO, fdcintr, fdc, fdc->sc_dev.dv_xname);
  165 
  166         kthread_create_deferred(fdc_create_kthread, fdc);
  167 }
  168 
  169 void
  170 fdc_create_kthread(void *arg)
  171 {
  172         struct fdc_softc *sc = arg;
  173         if (kthread_create(fdcattach_deferred, arg, NULL, "fdcattach") != 0) {
  174                 printf("%s: failed to create kernel thread, disabled\n",
  175                     sc->sc_dev.dv_xname);
  176         }
  177 }
  178 
  179 void
  180 fdcattach_deferred(void *arg)
  181 {
  182         struct fdc_softc *fdc = arg;
  183         struct fdc_attach_args fa;
  184         int type;
  185 
  186 #if defined(__i386__) || defined(__amd64__)
  187         /*
  188          * The NVRAM info only tells us about the first two disks on the
  189          * `primary' floppy controller.
  190          */
  191         if (fdc->sc_dev.dv_unit == 0)
  192                 type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
  193         else
  194 #endif
  195                 type = -1;
  196 
  197         timeout_set(&fdc->fdcpseudointr_to, fdcpseudointr, fdc);
  198 
  199         /* physical limit: four drives per controller. */
  200         for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
  201                 fa.fa_flags = 0;
  202                 fa.fa_type = 0;
  203 #if NFD > 0
  204                 if (type >= 0 && fa.fa_drive < 2)
  205                         fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
  206                             type, fa.fa_drive);
  207                 else
  208 #endif
  209                         fa.fa_deftype = NULL;           /* unknown */
  210                 (void)config_found(&fdc->sc_dev, (void *)&fa, fddprint);
  211         }
  212         kthread_exit(0);
  213 }
  214 
  215 /*
  216  * Print the location of a disk/tape drive (called just before attaching the
  217  * the drive).  If `fdc' is not NULL, the drive was found but was not
  218  * in the system config file; print the drive name as well.
  219  * Return QUIET (config_find ignores this if the device was configured) to
  220  * avoid printing `fdN not configured' messages.
  221  */
  222 int
  223 fddprint(void *aux, const char *fdc)
  224 {
  225         register struct fdc_attach_args *fa = aux;
  226 
  227         if (!fdc)
  228                 printf(" drive %d", fa->fa_drive);
  229         return QUIET;
  230 }
  231 
  232 int
  233 fdcresult(struct fdc_softc *fdc)
  234 {
  235         bus_space_tag_t iot = fdc->sc_iot;
  236         bus_space_handle_t ioh = fdc->sc_ioh;
  237         u_char i;
  238         int j = 100000, n = 0;
  239 
  240         for (; j; j--) {
  241                 i = bus_space_read_1(iot, ioh, fdsts) &
  242                     (NE7_DIO | NE7_RQM | NE7_CB);
  243                 if (i == NE7_RQM)
  244                         return n;
  245                 if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
  246                         if (n >= sizeof(fdc->sc_status)) {
  247                                 log(LOG_ERR, "fdcresult: overrun\n");
  248                                 return -1;
  249                         }
  250                         fdc->sc_status[n++] =
  251                             bus_space_read_1(iot, ioh, fddata);
  252                 }
  253                 delay(10);
  254         }
  255         return -1;
  256 }
  257 
  258 int
  259 out_fdc(bus_space_tag_t iot, bus_space_handle_t ioh, u_char x)
  260 {
  261         int i = 100000;
  262 
  263         while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
  264         if (i <= 0)
  265                 return -1;
  266         while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
  267         if (i <= 0)
  268                 return -1;
  269         bus_space_write_1(iot, ioh, fddata, x);
  270         return 0;
  271 }
  272 
  273 void
  274 fdcstart(struct fdc_softc *fdc)
  275 {
  276 
  277 #ifdef DIAGNOSTIC
  278         /* only got here if controller's drive queue was inactive; should
  279            be in idle state */
  280         if (fdc->sc_state != DEVIDLE) {
  281                 printf("fdcstart: not idle\n");
  282                 return;
  283         }
  284 #endif
  285         (void) fdcintr(fdc);
  286 }
  287 
  288 void
  289 fdcstatus(struct device *dv, int n, char *s)
  290 {
  291         struct fdc_softc *fdc = (void *)dv->dv_parent;
  292 
  293         if (n == 0) {
  294                 out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
  295                 (void) fdcresult(fdc);
  296                 n = 2;
  297         }
  298 
  299         printf("%s: %s", dv->dv_xname, s);
  300 
  301         switch (n) {
  302         case 0:
  303                 printf("\n");
  304                 break;
  305         case 2:
  306                 printf(" (st0 %b cyl %d)\n",
  307                     fdc->sc_status[0], NE7_ST0BITS,
  308                     fdc->sc_status[1]);
  309                 break;
  310         case 7:
  311                 printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
  312                     fdc->sc_status[0], NE7_ST0BITS,
  313                     fdc->sc_status[1], NE7_ST1BITS,
  314                     fdc->sc_status[2], NE7_ST2BITS,
  315                     fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
  316                 break;
  317 #ifdef DIAGNOSTIC
  318         default:
  319                 printf("\nfdcstatus: weird size");
  320                 break;
  321 #endif
  322         }
  323 }
  324 
  325 void
  326 fdcpseudointr(void *arg)
  327 {
  328         int s;
  329 
  330         /* Just ensure it has the right spl. */
  331         s = splbio();
  332         (void) fdcintr(arg);
  333         splx(s);
  334 }
  335 
  336 int
  337 fdcintr(void *arg)
  338 {
  339 #if NFD > 0
  340         struct fdc_softc *fdc = arg;
  341         extern int fdintr(struct fdc_softc *);
  342 
  343         /* Will switch on device type, shortly. */
  344         return (fdintr(fdc));
  345 #else
  346         printf("fdcintr: got interrupt, but no devices!\n");
  347         return (1);
  348 #endif
  349 }

Cache object: e8643e9d073fd5d8cd259173782f5451


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