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