[BACK]Return to fdc.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/fdc.c, Revision 1.1

1.1     ! nbrk        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: }

CVSweb