LCOV - code coverage report
Current view: top level - dev/isa - fdc.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 131 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: fdc.c,v 1.23 2017/12/30 20:46:59 guenther 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             : 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           0 : fdcprobe(struct device *parent, void *match, void *aux)
      98             : {
      99           0 :         register struct isa_attach_args *ia = aux;
     100             :         bus_space_tag_t iot;
     101           0 :         bus_space_handle_t ioh;
     102           0 :         bus_space_handle_t ioh_ctl;
     103             :         int rv;
     104             : 
     105           0 :         iot = ia->ia_iot;
     106             :         rv = 0;
     107             : 
     108             :         /* Map the i/o space. */
     109           0 :         if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh))
     110           0 :                 return 0;
     111           0 :         if (bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
     112             :                           FDCTL_NPORT, 0, &ioh_ctl))
     113           0 :                 return 0;
     114             : 
     115             :         /* reset */
     116           0 :         bus_space_write_1(iot, ioh, fdout, 0);
     117           0 :         delay(100);
     118           0 :         bus_space_write_1(iot, ioh, fdout, FDO_FRST);
     119             : 
     120             :         /* see if it can handle a command */
     121           0 :         if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
     122             :                 goto out;
     123           0 :         out_fdc(iot, ioh, 0xdf);
     124           0 :         out_fdc(iot, ioh, 2);
     125             : 
     126             :         rv = 1;
     127           0 :         ia->ia_iosize = FDC_NPORT;
     128           0 :         ia->ia_msize = 0;
     129             : 
     130             :  out:
     131           0 :         bus_space_unmap(iot, ioh, FDC_NPORT);
     132           0 :         bus_space_unmap(iot, ioh_ctl, FDCTL_NPORT);
     133           0 :         return rv;
     134           0 : }
     135             : 
     136             : void
     137           0 : fdcattach(struct device *parent, struct device *self, void *aux)
     138             : {
     139           0 :         struct fdc_softc *fdc = (void *)self;
     140             :         bus_space_tag_t iot;
     141           0 :         bus_space_handle_t ioh;
     142           0 :         bus_space_handle_t ioh_ctl;
     143           0 :         struct isa_attach_args *ia = aux;
     144             : 
     145           0 :         iot = ia->ia_iot;
     146             : 
     147             :         /* Re-map the I/O space. */
     148           0 :         if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh) ||
     149           0 :             bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
     150             :                           FDCTL_NPORT, 0, &ioh_ctl))
     151           0 :                 panic("fdcattach: couldn't map I/O ports");
     152             : 
     153           0 :         fdc->sc_iot = iot;
     154           0 :         fdc->sc_ioh = ioh;
     155           0 :         fdc->sc_ioh_ctl = ioh_ctl;
     156             : 
     157           0 :         fdc->sc_drq = ia->ia_drq;
     158           0 :         fdc->sc_state = DEVIDLE;
     159           0 :         TAILQ_INIT(&fdc->sc_link.fdlink.sc_drives);      /* XXX */
     160             : 
     161           0 :         printf("\n");
     162             : 
     163           0 :         fdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
     164           0 :             IPL_BIO, fdcintr, fdc, fdc->sc_dev.dv_xname);
     165             : 
     166           0 :         kthread_create_deferred(fdc_create_kthread, fdc);
     167           0 : }
     168             : 
     169             : void
     170           0 : fdc_create_kthread(void *arg)
     171             : {
     172           0 :         struct fdc_softc *sc = arg;
     173           0 :         if (kthread_create(fdcattach_deferred, arg, NULL, "fdcattach") != 0) {
     174           0 :                 printf("%s: failed to create kernel thread, disabled\n",
     175           0 :                     sc->sc_dev.dv_xname);
     176           0 :         }
     177           0 : }
     178             : 
     179             : void
     180           0 : fdcattach_deferred(void *arg)
     181             : {
     182           0 :         struct fdc_softc *fdc = arg;
     183           0 :         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           0 :         if (fdc->sc_dev.dv_unit == 0)
     192           0 :                 type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
     193             :         else
     194             : #endif
     195             :                 type = -1;
     196             : 
     197           0 :         timeout_set(&fdc->fdcpseudointr_to, fdcpseudointr, fdc);
     198             : 
     199             :         /* physical limit: four drives per controller. */
     200           0 :         for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
     201           0 :                 fa.fa_flags = 0;
     202           0 :                 fa.fa_type = 0;
     203             : #if NFD > 0
     204           0 :                 if (type >= 0 && fa.fa_drive < 2)
     205           0 :                         fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
     206             :                             type, fa.fa_drive);
     207             :                 else
     208             : #endif
     209           0 :                         fa.fa_deftype = NULL;           /* unknown */
     210           0 :                 (void)config_found(&fdc->sc_dev, (void *)&fa, fddprint);
     211             :         }
     212           0 :         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           0 : fddprint(void *aux, const char *fdc)
     224             : {
     225           0 :         register struct fdc_attach_args *fa = aux;
     226             : 
     227           0 :         if (!fdc)
     228           0 :                 printf(" drive %d", fa->fa_drive);
     229           0 :         return QUIET;
     230             : }
     231             : 
     232             : int
     233           0 : fdcresult(struct fdc_softc *fdc)
     234             : {
     235           0 :         bus_space_tag_t iot = fdc->sc_iot;
     236           0 :         bus_space_handle_t ioh = fdc->sc_ioh;
     237             :         u_char i;
     238             :         int j = 100000, n = 0;
     239             : 
     240           0 :         for (; j; j--) {
     241           0 :                 i = bus_space_read_1(iot, ioh, fdsts) &
     242             :                     (NE7_DIO | NE7_RQM | NE7_CB);
     243           0 :                 if (i == NE7_RQM)
     244           0 :                         return n;
     245           0 :                 if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
     246           0 :                         if (n >= sizeof(fdc->sc_status)) {
     247           0 :                                 log(LOG_ERR, "fdcresult: overrun\n");
     248           0 :                                 return -1;
     249             :                         }
     250           0 :                         fdc->sc_status[n++] =
     251           0 :                             bus_space_read_1(iot, ioh, fddata);
     252           0 :                 }
     253           0 :                 delay(10);
     254             :         }
     255           0 :         return -1;
     256           0 : }
     257             : 
     258             : int
     259           0 : out_fdc(bus_space_tag_t iot, bus_space_handle_t ioh, u_char x)
     260             : {
     261             :         int i = 100000;
     262             : 
     263           0 :         while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
     264           0 :         if (i <= 0)
     265           0 :                 return -1;
     266           0 :         while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
     267           0 :         if (i <= 0)
     268           0 :                 return -1;
     269           0 :         bus_space_write_1(iot, ioh, fddata, x);
     270           0 :         return 0;
     271           0 : }
     272             : 
     273             : void
     274           0 : 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           0 :         if (fdc->sc_state != DEVIDLE) {
     281           0 :                 printf("fdcstart: not idle\n");
     282           0 :                 return;
     283             :         }
     284             : #endif
     285           0 :         (void) fdcintr(fdc);
     286           0 : }
     287             : 
     288             : void
     289           0 : fdcstatus(struct device *dv, int n, char *s)
     290             : {
     291           0 :         struct fdc_softc *fdc = (void *)dv->dv_parent;
     292             : 
     293           0 :         if (n == 0) {
     294           0 :                 out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
     295           0 :                 (void) fdcresult(fdc);
     296             :                 n = 2;
     297           0 :         }
     298             : 
     299           0 :         printf("%s: %s", dv->dv_xname, s);
     300             : 
     301           0 :         switch (n) {
     302             :         case 0:
     303           0 :                 printf("\n");
     304           0 :                 break;
     305             :         case 2:
     306           0 :                 printf(" (st0 %b cyl %d)\n",
     307           0 :                     fdc->sc_status[0], NE7_ST0BITS,
     308           0 :                     fdc->sc_status[1]);
     309           0 :                 break;
     310             :         case 7:
     311           0 :                 printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
     312           0 :                     fdc->sc_status[0], NE7_ST0BITS,
     313           0 :                     fdc->sc_status[1], NE7_ST1BITS,
     314           0 :                     fdc->sc_status[2], NE7_ST2BITS,
     315           0 :                     fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
     316           0 :                 break;
     317             : #ifdef DIAGNOSTIC
     318             :         default:
     319           0 :                 printf("\nfdcstatus: weird size");
     320           0 :                 break;
     321             : #endif
     322             :         }
     323           0 : }
     324             : 
     325             : void
     326           0 : fdcpseudointr(void *arg)
     327             : {
     328             :         int s;
     329             : 
     330             :         /* Just ensure it has the right spl. */
     331           0 :         s = splbio();
     332           0 :         (void) fdcintr(arg);
     333           0 :         splx(s);
     334           0 : }
     335             : 
     336             : int
     337           0 : fdcintr(void *arg)
     338             : {
     339             : #if NFD > 0
     340           0 :         struct fdc_softc *fdc = arg;
     341             :         extern int fdintr(struct fdc_softc *);
     342             : 
     343             :         /* Will switch on device type, shortly. */
     344           0 :         return (fdintr(fdc));
     345             : #else
     346             :         printf("fdcintr: got interrupt, but no devices!\n");
     347             :         return (1);
     348             : #endif
     349             : }

Generated by: LCOV version 1.13