Home | History | Annotate | Line # | Download | only in isa
fd.c revision 1.2
      1 /*	$NetBSD: fd.c,v 1.2 2000/04/07 16:58:53 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Charles M. Hannum.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*-
     40  * Copyright (c) 1990 The Regents of the University of California.
     41  * All rights reserved.
     42  *
     43  * This code is derived from software contributed to Berkeley by
     44  * Don Ahn.
     45  *
     46  * Redistribution and use in source and binary forms, with or without
     47  * modification, are permitted provided that the following conditions
     48  * are met:
     49  * 1. Redistributions of source code must retain the above copyright
     50  *    notice, this list of conditions and the following disclaimer.
     51  * 2. Redistributions in binary form must reproduce the above copyright
     52  *    notice, this list of conditions and the following disclaimer in the
     53  *    documentation and/or other materials provided with the distribution.
     54  * 3. All advertising materials mentioning features or use of this software
     55  *    must display the following acknowledgement:
     56  *	This product includes software developed by the University of
     57  *	California, Berkeley and its contributors.
     58  * 4. Neither the name of the University nor the names of its contributors
     59  *    may be used to endorse or promote products derived from this software
     60  *    without specific prior written permission.
     61  *
     62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     72  * SUCH DAMAGE.
     73  *
     74  *	@(#)fd.c	7.4 (Berkeley) 5/25/91
     75  */
     76 
     77 /*
     78  * Floppy formatting facilities merged from FreeBSD fd.c driver:
     79  *	Id: fd.c,v 1.53 1995/03/12 22:40:56 joerg Exp
     80  * which carries the same copyright/redistribution notice as shown above with
     81  * the addition of the following statement before the "Redistribution and
     82  * use ..." clause:
     83  *
     84  * Copyright (c) 1993, 1994 by
     85  *  jc (at) irbs.UUCP (John Capo)
     86  *  vak (at) zebub.msk.su (Serge Vakulenko)
     87  *  ache (at) astral.msk.su (Andrew A. Chernov)
     88  *
     89  * Copyright (c) 1993, 1994, 1995 by
     90  *  joerg_wunsch (at) uriah.sax.de (Joerg Wunsch)
     91  *  dufault (at) hda.com (Peter Dufault)
     92  */
     93 
     94 #include "rnd.h"
     95 #include "opt_ddb.h"
     96 
     97 /*
     98  * XXX This driver should be properly MI'd some day, but this allows us
     99  * XXX to eliminate a lot of code duplication for now.
    100  */
    101 #if !defined(__alpha__) && !defined(bebox) && !defined(__i386__)
    102 #error platform not supported by this driver, yet
    103 #endif
    104 
    105 #include <sys/param.h>
    106 #include <sys/systm.h>
    107 #include <sys/callout.h>
    108 #include <sys/kernel.h>
    109 #include <sys/file.h>
    110 #include <sys/ioctl.h>
    111 #include <sys/device.h>
    112 #include <sys/disklabel.h>
    113 #include <sys/dkstat.h>
    114 #include <sys/disk.h>
    115 #include <sys/buf.h>
    116 #include <sys/malloc.h>
    117 #include <sys/uio.h>
    118 #include <sys/syslog.h>
    119 #include <sys/queue.h>
    120 #include <sys/proc.h>
    121 #include <sys/fdio.h>
    122 #if NRND > 0
    123 #include <sys/rnd.h>
    124 #endif
    125 
    126 #include <vm/vm.h>
    127 
    128 #include <uvm/uvm_extern.h>
    129 
    130 #include <dev/cons.h>
    131 
    132 #include <machine/cpu.h>
    133 #include <machine/bus.h>
    134 #include <machine/conf.h>
    135 #include <machine/intr.h>
    136 
    137 #include <dev/isa/isavar.h>
    138 #include <dev/isa/isadmavar.h>
    139 #include <dev/isa/fdreg.h>
    140 
    141 #if defined(__i386__)
    142 #include <dev/ic/mc146818reg.h>			/* for NVRAM access */
    143 #include <i386/isa/nvram.h>
    144 #endif /* __i386__ */
    145 
    146 #define FDUNIT(dev)	(minor(dev) / 8)
    147 #define FDTYPE(dev)	(minor(dev) % 8)
    148 
    149 /* XXX misuse a flag to identify format operation */
    150 #define B_FORMAT B_XXX
    151 
    152 enum fdc_state {
    153 	DEVIDLE = 0,
    154 	MOTORWAIT,
    155 	DOSEEK,
    156 	SEEKWAIT,
    157 	SEEKTIMEDOUT,
    158 	SEEKCOMPLETE,
    159 	DOIO,
    160 	IOCOMPLETE,
    161 	IOTIMEDOUT,
    162 	DORESET,
    163 	RESETCOMPLETE,
    164 	RESETTIMEDOUT,
    165 	DORECAL,
    166 	RECALWAIT,
    167 	RECALTIMEDOUT,
    168 	RECALCOMPLETE,
    169 };
    170 
    171 /* software state, per controller */
    172 struct fdc_softc {
    173 	struct device sc_dev;		/* boilerplate */
    174 	void *sc_ih;
    175 
    176 	bus_space_tag_t sc_iot;		/* ISA i/o space identifier */
    177 	bus_space_handle_t sc_ioh;	/* ISA io handle */
    178 	isa_chipset_tag_t sc_ic;	/* ISA chipset info */
    179 
    180 	struct callout sc_timo_ch;	/* timeout callout */
    181 	struct callout sc_intr_ch;	/* pseudo-intr callout */
    182 
    183 	/*
    184 	 * XXX We have port overlap with the first IDE controller.
    185 	 * Until we have a reasonable solution for handling overlap
    186 	 * like this, we kludge access to our control register at
    187 	 * offset 7.
    188 	 */
    189 	bus_space_handle_t sc_fdctlioh;
    190 #define	sc_fdinioh	sc_fdctlioh
    191 
    192 	int sc_drq;
    193 	bus_size_t sc_maxiosize;
    194 
    195 	struct fd_softc *sc_fd[4];	/* pointers to children */
    196 	TAILQ_HEAD(drivehead, fd_softc) sc_drives;
    197 	enum fdc_state sc_state;
    198 	int sc_errors;			/* number of retries so far */
    199 	u_char sc_status[7];		/* copy of registers */
    200 };
    201 
    202 /* controller driver configuration */
    203 int fdcprobe __P((struct device *, struct cfdata *, void *));
    204 int fdprint __P((void *, const char *));
    205 #ifdef NEWCONFIG
    206 void fdcforceintr __P((void *));
    207 #endif
    208 void fdcattach __P((struct device *, struct device *, void *));
    209 
    210 struct cfattach fdc_ca = {
    211 	sizeof(struct fdc_softc), fdcprobe, fdcattach
    212 };
    213 
    214 /*
    215  * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
    216  * we tell them apart.
    217  */
    218 struct fd_type {
    219 	int	sectrac;	/* sectors per track */
    220 	int	heads;		/* number of heads */
    221 	int	seccyl;		/* sectors per cylinder */
    222 	int	secsize;	/* size code for sectors */
    223 	int	datalen;	/* data len when secsize = 0 */
    224 	int	steprate;	/* step rate and head unload time */
    225 	int	gap1;		/* gap len between sectors */
    226 	int	gap2;		/* formatting gap */
    227 	int	cyls;		/* total num of cylinders */
    228 	int	size;		/* size of disk in sectors */
    229 	int	step;		/* steps per cylinder */
    230 	int	rate;		/* transfer speed code */
    231 	u_char	fillbyte;	/* format fill byte */
    232 	u_char	interleave;	/* interleave factor (formatting) */
    233 	char	*name;
    234 };
    235 
    236 /* The order of entries in the following table is important -- BEWARE! */
    237 struct fd_type fd_types[] = {
    238 	{ 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB"    }, /* 1.44MB diskette */
    239 	{ 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS,0xf6,1, "1.2MB"    }, /* 1.2 MB AT-diskettes */
    240 	{  9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS,0xf6,1, "360KB/AT" }, /* 360kB in 1.2MB drive */
    241 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS,0xf6,1, "360KB/PC" }, /* 360kB PC diskettes */
    242 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB"    }, /* 3.5 inch 720kB diskette */
    243 	{  9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS,0xf6,1, "720KB/x"  }, /* 720kB in 1.2MB drive */
    244 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x"  }, /* 360kB in 720kB drive */
    245 };
    246 
    247 /* software state, per disk (with up to 4 disks per ctlr) */
    248 struct fd_softc {
    249 	struct device sc_dev;
    250 	struct disk sc_dk;
    251 
    252 	struct fd_type *sc_deftype;	/* default type descriptor */
    253 	struct fd_type *sc_type;	/* current type descriptor */
    254 	struct fd_type sc_type_copy;	/* copy for fiddling when formatting */
    255 
    256 	struct callout sc_motoron_ch;
    257 	struct callout sc_motoroff_ch;
    258 
    259 	daddr_t	sc_blkno;	/* starting block number */
    260 	int sc_bcount;		/* byte count left */
    261  	int sc_opts;			/* user-set options */
    262 	int sc_skip;		/* bytes already transferred */
    263 	int sc_nblks;		/* number of blocks currently tranferring */
    264 	int sc_nbytes;		/* number of bytes currently tranferring */
    265 
    266 	int sc_drive;		/* physical unit number */
    267 	int sc_flags;
    268 #define	FD_OPEN		0x01		/* it's open */
    269 #define	FD_MOTOR	0x02		/* motor should be on */
    270 #define	FD_MOTOR_WAIT	0x04		/* motor coming up */
    271 	int sc_cylin;		/* where we think the head is */
    272 
    273 	void *sc_sdhook;	/* saved shutdown hook for drive. */
    274 
    275 	TAILQ_ENTRY(fd_softc) sc_drivechain;
    276 	int sc_ops;		/* I/O ops since last switch */
    277 	struct buf_queue sc_q;	/* pending I/O requests */
    278 	int sc_active;		/* number of active I/O operations */
    279 
    280 #if NRND > 0
    281 	rndsource_element_t	rnd_source;
    282 #endif
    283 };
    284 
    285 /* floppy driver configuration */
    286 int fdprobe __P((struct device *, struct cfdata *, void *));
    287 void fdattach __P((struct device *, struct device *, void *));
    288 
    289 struct cfattach fd_ca = {
    290 	sizeof(struct fd_softc), fdprobe, fdattach
    291 };
    292 
    293 extern struct cfdriver fd_cd;
    294 
    295 void fdgetdisklabel __P((struct fd_softc *));
    296 int fd_get_parms __P((struct fd_softc *));
    297 void fdstrategy __P((struct buf *));
    298 void fdstart __P((struct fd_softc *));
    299 
    300 struct dkdriver fddkdriver = { fdstrategy };
    301 
    302 #if defined(__i386__)
    303 struct fd_type *fd_nvtotype __P((char *, int, int));
    304 #endif /* __i386__ */
    305 void fd_set_motor __P((struct fdc_softc *fdc, int reset));
    306 void fd_motor_off __P((void *arg));
    307 void fd_motor_on __P((void *arg));
    308 int fdcresult __P((struct fdc_softc *fdc));
    309 int out_fdc __P((bus_space_tag_t iot, bus_space_handle_t ioh, u_char x));
    310 void fdcstart __P((struct fdc_softc *fdc));
    311 void fdcstatus __P((struct device *dv, int n, char *s));
    312 void fdctimeout __P((void *arg));
    313 void fdcpseudointr __P((void *arg));
    314 int fdcintr __P((void *));
    315 void fdcretry __P((struct fdc_softc *fdc));
    316 void fdfinish __P((struct fd_softc *fd, struct buf *bp));
    317 __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t));
    318 int fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *));
    319 
    320 void	fd_mountroot_hook __P((struct device *));
    321 
    322 int
    323 fdcprobe(parent, match, aux)
    324 	struct device *parent;
    325 	struct cfdata *match;
    326 	void *aux;
    327 {
    328 	register struct isa_attach_args *ia = aux;
    329 	bus_space_tag_t iot;
    330 	bus_space_handle_t ioh;
    331 	int rv;
    332 
    333 	iot = ia->ia_iot;
    334 	rv = 0;
    335 
    336 	/* Disallow wildcarded i/o address. */
    337 	if (ia->ia_iobase == IOBASEUNK)
    338 		return 0;
    339 
    340 	/* Map the i/o space. */
    341 	if (bus_space_map(iot, ia->ia_iobase, 6 /* XXX FDC_NPORT */, 0, &ioh))
    342 		return 0;
    343 
    344 	/* XXX XXX XXX BEGIN XXX XXX XXX */
    345 	{
    346 		bus_space_handle_t fdctlioh;
    347 		if (bus_space_map(iot, ia->ia_iobase + fdctl, 1, 0,
    348 		    &fdctlioh)) {
    349 			bus_space_unmap(iot, ioh, 6);
    350 			return 0;
    351 		}
    352 		/* not needed for the rest of the probe */
    353 		bus_space_unmap(iot, fdctlioh, 1);
    354 	}
    355 	/* XXX XXX XXX END XXX XXX XXX */
    356 
    357 	/* reset */
    358 	bus_space_write_1(iot, ioh, fdout, 0);
    359 	delay(100);
    360 	bus_space_write_1(iot, ioh, fdout, FDO_FRST);
    361 
    362 	/* see if it can handle a command */
    363 	if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
    364 		goto out;
    365 	out_fdc(iot, ioh, 0xdf);
    366 	out_fdc(iot, ioh, 2);
    367 
    368 #ifdef NEWCONFIG
    369 	if (ia->ia_iobase == IOBASEUNK || ia->ia_drq == DRQUNK)
    370 		return 0;
    371 
    372 	if (ia->ia_irq == IRQUNK) {
    373 		ia->ia_irq = isa_discoverintr(fdcforceintr, aux);
    374 		if (ia->ia_irq == IRQNONE)
    375 			goto out;
    376 
    377 		/* reset it again */
    378 		bus_space_write_1(iot, ioh, fdout, 0);
    379 		delay(100);
    380 		bus_space_write_1(iot, ioh, fdout, FDO_FRST);
    381 	}
    382 #endif
    383 
    384 	rv = 1;
    385 	ia->ia_iosize = FDC_NPORT;
    386 	ia->ia_msize = 0;
    387 
    388  out:
    389 	bus_space_unmap(iot, ioh, 6 /* XXX FDC_NPORT */);
    390 	return rv;
    391 }
    392 
    393 #ifdef NEWCONFIG
    394 /*
    395  * XXX This is broken, and needs fixing.  In general, the interface needs
    396  * XXX to change.
    397  */
    398 void
    399 fdcforceintr(aux)
    400 	void *aux;
    401 {
    402 	struct isa_attach_args *ia = aux;
    403 	int iobase = ia->ia_iobase;
    404 
    405 	/* the motor is off; this should generate an error with or
    406 	   without a disk drive present */
    407 	out_fdc(iot, ioh, NE7CMD_SEEK);
    408 	out_fdc(iot, ioh, 0);
    409 	out_fdc(iot, ioh, 0);
    410 }
    411 #endif
    412 
    413 /*
    414  * Arguments passed between fdcattach and fdprobe.
    415  */
    416 struct fdc_attach_args {
    417 	int fa_drive;
    418 	struct fd_type *fa_deftype;
    419 };
    420 
    421 /*
    422  * Print the location of a disk drive (called just before attaching the
    423  * the drive).  If `fdc' is not NULL, the drive was found but was not
    424  * in the system config file; print the drive name as well.
    425  * Return QUIET (config_find ignores this if the device was configured) to
    426  * avoid printing `fdN not configured' messages.
    427  */
    428 int
    429 fdprint(aux, fdc)
    430 	void *aux;
    431 	const char *fdc;
    432 {
    433 	register struct fdc_attach_args *fa = aux;
    434 
    435 	if (!fdc)
    436 		printf(" drive %d", fa->fa_drive);
    437 	return QUIET;
    438 }
    439 
    440 void
    441 fdcattach(parent, self, aux)
    442 	struct device *parent, *self;
    443 	void *aux;
    444 {
    445 	struct fdc_softc *fdc = (void *)self;
    446 	bus_space_tag_t iot;
    447 	bus_space_handle_t ioh;
    448 	struct isa_attach_args *ia = aux;
    449 	struct fdc_attach_args fa;
    450 #if defined(__i386__)
    451 	int type;
    452 #endif
    453 
    454 	iot = ia->ia_iot;
    455 
    456 	printf("\n");
    457 
    458 	callout_init(&fdc->sc_timo_ch);
    459 	callout_init(&fdc->sc_intr_ch);
    460 
    461 	/* Re-map the I/O space. */
    462 	if (bus_space_map(iot, ia->ia_iobase, 6 /* XXX FDC_NPORT */, 0, &ioh)) {
    463 		printf("%s: can't map i/o space\n", fdc->sc_dev.dv_xname);
    464 		return;
    465 	}
    466 
    467 	/* XXX XXX XXX BEGIN XXX XXX XXX */
    468 	if (bus_space_map(iot, ia->ia_iobase + fdctl, 1, 0,
    469 	    &fdc->sc_fdctlioh)) {
    470 		printf("%s: can't kludge i/o space\n", fdc->sc_dev.dv_xname);
    471 		return;
    472 	}
    473 	/* XXX XXX XXX END XXX XXX XXX */
    474 
    475 	fdc->sc_iot = iot;
    476 	fdc->sc_ioh = ioh;
    477 	fdc->sc_ic = ia->ia_ic;
    478 
    479 	fdc->sc_drq = ia->ia_drq;
    480 	fdc->sc_state = DEVIDLE;
    481 	TAILQ_INIT(&fdc->sc_drives);
    482 
    483 	fdc->sc_maxiosize = isa_dmamaxsize(fdc->sc_ic, fdc->sc_drq);
    484 
    485 	if (isa_dmamap_create(fdc->sc_ic, fdc->sc_drq, fdc->sc_maxiosize,
    486 	    BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
    487 		printf("%s: can't set up ISA DMA map\n",
    488 		    fdc->sc_dev.dv_xname);
    489 		return;
    490 	}
    491 
    492 	fdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
    493 	    IPL_BIO, fdcintr, fdc);
    494 
    495 #if defined(__i386__)
    496 	/*
    497 	 * The NVRAM info only tells us about the first two disks on the
    498 	 * `primary' floppy controller.
    499 	 */
    500 	if (fdc->sc_dev.dv_unit == 0)
    501 		type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
    502 	else
    503 		type = -1;
    504 #endif /* __i386__ */
    505 
    506 	/* physical limit: four drives per controller. */
    507 	for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
    508 #if defined(__i386__)
    509 		if (type >= 0 && fa.fa_drive < 2)
    510 			fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
    511 			    type, fa.fa_drive);
    512 		else
    513 			fa.fa_deftype = NULL;		/* unknown */
    514 #else
    515 		/*
    516 		 * Default to 1.44MB on Alpha and BeBox.  How do we tell
    517 		 * on these platforms?
    518 		 */
    519 		fa.fa_deftype = &fd_types[0];
    520 #endif /* __i386__ */
    521 		(void)config_found(self, (void *)&fa, fdprint);
    522 	}
    523 }
    524 
    525 int
    526 fdprobe(parent, match, aux)
    527 	struct device *parent;
    528 	struct cfdata *match;
    529 	void *aux;
    530 {
    531 	struct fdc_softc *fdc = (void *)parent;
    532 	struct cfdata *cf = match;
    533 	struct fdc_attach_args *fa = aux;
    534 	int drive = fa->fa_drive;
    535 	bus_space_tag_t iot = fdc->sc_iot;
    536 	bus_space_handle_t ioh = fdc->sc_ioh;
    537 	int n;
    538 
    539 	if (cf->cf_loc[FDCCF_DRIVE] != FDCCF_DRIVE_DEFAULT &&
    540 	    cf->cf_loc[FDCCF_DRIVE] != drive)
    541 		return 0;
    542 	/*
    543 	 * XXX
    544 	 * This is to work around some odd interactions between this driver
    545 	 * and SMC Ethernet cards.
    546 	 */
    547 	if (cf->cf_loc[FDCCF_DRIVE] == FDCCF_DRIVE_DEFAULT && drive >= 2)
    548 		return 0;
    549 
    550 	/* select drive and turn on motor */
    551 	bus_space_write_1(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive));
    552 	/* wait for motor to spin up */
    553 	delay(250000);
    554 	out_fdc(iot, ioh, NE7CMD_RECAL);
    555 	out_fdc(iot, ioh, drive);
    556 	/* wait for recalibrate */
    557 	delay(2000000);
    558 	out_fdc(iot, ioh, NE7CMD_SENSEI);
    559 	n = fdcresult(fdc);
    560 #ifdef FD_DEBUG
    561 	{
    562 		int i;
    563 		printf("fdprobe: status");
    564 		for (i = 0; i < n; i++)
    565 			printf(" %x", fdc->sc_status[i]);
    566 		printf("\n");
    567 	}
    568 #endif
    569 	/* turn off motor */
    570 	bus_space_write_1(iot, ioh, fdout, FDO_FRST);
    571 
    572 #if defined(bebox)	/* XXX What is this about? --thorpej (at) netbsd.org */
    573 	if (n != 2 || (fdc->sc_status[1] != 0))
    574 		return 0;
    575 #else
    576 	if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
    577 		return 0;
    578 #endif /* bebox */
    579 
    580 	return 1;
    581 }
    582 
    583 /*
    584  * Controller is working, and drive responded.  Attach it.
    585  */
    586 void
    587 fdattach(parent, self, aux)
    588 	struct device *parent, *self;
    589 	void *aux;
    590 {
    591 	struct fdc_softc *fdc = (void *)parent;
    592 	struct fd_softc *fd = (void *)self;
    593 	struct fdc_attach_args *fa = aux;
    594 	struct fd_type *type = fa->fa_deftype;
    595 	int drive = fa->fa_drive;
    596 
    597 	callout_init(&fd->sc_motoron_ch);
    598 	callout_init(&fd->sc_motoroff_ch);
    599 
    600 	/* XXX Allow `flags' to override device type? */
    601 
    602 	if (type)
    603 		printf(": %s, %d cyl, %d head, %d sec\n", type->name,
    604 		    type->cyls, type->heads, type->sectrac);
    605 	else
    606 		printf(": density unknown\n");
    607 
    608 	BUFQ_INIT(&fd->sc_q);
    609 	fd->sc_cylin = -1;
    610 	fd->sc_drive = drive;
    611 	fd->sc_deftype = type;
    612 	fdc->sc_fd[drive] = fd;
    613 
    614 	/*
    615 	 * Initialize and attach the disk structure.
    616 	 */
    617 	fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
    618 	fd->sc_dk.dk_driver = &fddkdriver;
    619 	disk_attach(&fd->sc_dk);
    620 
    621 	/*
    622 	 * Establish a mountroot hook.
    623 	 */
    624 	mountroothook_establish(fd_mountroot_hook, &fd->sc_dev);
    625 
    626 	/* Needed to power off if the motor is on when we halt. */
    627 	fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd);
    628 
    629 #if NRND > 0
    630 	rnd_attach_source(&fd->rnd_source, fd->sc_dev.dv_xname,
    631 			  RND_TYPE_DISK, 0);
    632 #endif
    633 }
    634 
    635 #if defined(__i386__)
    636 /*
    637  * Translate nvram type into internal data structure.  Return NULL for
    638  * none/unknown/unusable.
    639  */
    640 struct fd_type *
    641 fd_nvtotype(fdc, nvraminfo, drive)
    642 	char *fdc;
    643 	int nvraminfo, drive;
    644 {
    645 	int type;
    646 
    647 	type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
    648 	switch (type) {
    649 	case NVRAM_DISKETTE_NONE:
    650 		return NULL;
    651 	case NVRAM_DISKETTE_12M:
    652 		return &fd_types[1];
    653 	case NVRAM_DISKETTE_TYPE5:
    654 	case NVRAM_DISKETTE_TYPE6:
    655 		/* XXX We really ought to handle 2.88MB format. */
    656 	case NVRAM_DISKETTE_144M:
    657 		return &fd_types[0];
    658 	case NVRAM_DISKETTE_360K:
    659 		return &fd_types[3];
    660 	case NVRAM_DISKETTE_720K:
    661 		return &fd_types[4];
    662 	default:
    663 		printf("%s: drive %d: unknown device type 0x%x\n",
    664 		    fdc, drive, type);
    665 		return NULL;
    666 	}
    667 }
    668 #endif /* __i386__ */
    669 
    670 __inline struct fd_type *
    671 fd_dev_to_type(fd, dev)
    672 	struct fd_softc *fd;
    673 	dev_t dev;
    674 {
    675 	int type = FDTYPE(dev);
    676 
    677 	if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
    678 		return NULL;
    679 	return type ? &fd_types[type - 1] : fd->sc_deftype;
    680 }
    681 
    682 void
    683 fdstrategy(bp)
    684 	register struct buf *bp;	/* IO operation to perform */
    685 {
    686 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(bp->b_dev)];
    687 	int sz;
    688  	int s;
    689 
    690 	/* Valid unit, controller, and request? */
    691 	if (bp->b_blkno < 0 ||
    692 	    ((bp->b_bcount % FDC_BSIZE) != 0 &&
    693 	     (bp->b_flags & B_FORMAT) == 0)) {
    694 		bp->b_error = EINVAL;
    695 		goto bad;
    696 	}
    697 
    698 	/* If it's a null transfer, return immediately. */
    699 	if (bp->b_bcount == 0)
    700 		goto done;
    701 
    702 	sz = howmany(bp->b_bcount, FDC_BSIZE);
    703 
    704 	if (bp->b_blkno + sz > fd->sc_type->size) {
    705 		sz = fd->sc_type->size - bp->b_blkno;
    706 		if (sz == 0) {
    707 			/* If exactly at end of disk, return EOF. */
    708 			goto done;
    709 		}
    710 		if (sz < 0) {
    711 			/* If past end of disk, return EINVAL. */
    712 			bp->b_error = EINVAL;
    713 			goto bad;
    714 		}
    715 		/* Otherwise, truncate request. */
    716 		bp->b_bcount = sz << DEV_BSHIFT;
    717 	}
    718 
    719 	bp->b_rawblkno = bp->b_blkno;
    720  	bp->b_cylinder = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;
    721 
    722 #ifdef FD_DEBUG
    723 	printf("fdstrategy: b_blkno %d b_bcount %ld blkno %d cylin %ld sz %d\n",
    724 	    bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder, sz);
    725 #endif
    726 
    727 	/* Queue transfer on drive, activate drive and controller if idle. */
    728 	s = splbio();
    729 	disksort_cylinder(&fd->sc_q, bp);
    730 	callout_stop(&fd->sc_motoroff_ch);		/* a good idea */
    731 	if (fd->sc_active == 0)
    732 		fdstart(fd);
    733 #ifdef DIAGNOSTIC
    734 	else {
    735 		struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    736 		if (fdc->sc_state == DEVIDLE) {
    737 			printf("fdstrategy: controller inactive\n");
    738 			fdcstart(fdc);
    739 		}
    740 	}
    741 #endif
    742 	splx(s);
    743 	return;
    744 
    745 bad:
    746 	bp->b_flags |= B_ERROR;
    747 done:
    748 	/* Toss transfer; we're done early. */
    749 	bp->b_resid = bp->b_bcount;
    750 	biodone(bp);
    751 }
    752 
    753 void
    754 fdstart(fd)
    755 	struct fd_softc *fd;
    756 {
    757 	struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    758 	int active = fdc->sc_drives.tqh_first != 0;
    759 
    760 	/* Link into controller queue. */
    761 	fd->sc_active = 1;
    762 	TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
    763 
    764 	/* If controller not already active, start it. */
    765 	if (!active)
    766 		fdcstart(fdc);
    767 }
    768 
    769 void
    770 fdfinish(fd, bp)
    771 	struct fd_softc *fd;
    772 	struct buf *bp;
    773 {
    774 	struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    775 
    776 	/*
    777 	 * Move this drive to the end of the queue to give others a `fair'
    778 	 * chance.  We only force a switch if N operations are completed while
    779 	 * another drive is waiting to be serviced, since there is a long motor
    780 	 * startup delay whenever we switch.
    781 	 */
    782 	if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
    783 		fd->sc_ops = 0;
    784 		TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
    785 		if (BUFQ_NEXT(bp) != NULL)
    786 			TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
    787 		else
    788 			fd->sc_active = 0;
    789 	}
    790 	bp->b_resid = fd->sc_bcount;
    791 	fd->sc_skip = 0;
    792 	BUFQ_REMOVE(&fd->sc_q, bp);
    793 
    794 #if NRND > 0
    795 	rnd_add_uint32(&fd->rnd_source, bp->b_blkno);
    796 #endif
    797 
    798 	biodone(bp);
    799 	/* turn off motor 5s from now */
    800 	callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd);
    801 	fdc->sc_state = DEVIDLE;
    802 }
    803 
    804 int
    805 fdread(dev, uio, flags)
    806 	dev_t dev;
    807 	struct uio *uio;
    808 	int flags;
    809 {
    810 
    811 	return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
    812 }
    813 
    814 int
    815 fdwrite(dev, uio, flags)
    816 	dev_t dev;
    817 	struct uio *uio;
    818 	int flags;
    819 {
    820 
    821 	return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
    822 }
    823 
    824 void
    825 fd_set_motor(fdc, reset)
    826 	struct fdc_softc *fdc;
    827 	int reset;
    828 {
    829 	struct fd_softc *fd;
    830 	u_char status;
    831 	int n;
    832 
    833 	if ((fd = fdc->sc_drives.tqh_first) != NULL)
    834 		status = fd->sc_drive;
    835 	else
    836 		status = 0;
    837 	if (!reset)
    838 		status |= FDO_FRST | FDO_FDMAEN;
    839 	for (n = 0; n < 4; n++)
    840 		if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
    841 			status |= FDO_MOEN(n);
    842 	bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, status);
    843 }
    844 
    845 void
    846 fd_motor_off(arg)
    847 	void *arg;
    848 {
    849 	struct fd_softc *fd = arg;
    850 	int s;
    851 
    852 	s = splbio();
    853 	fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
    854 	fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0);
    855 	splx(s);
    856 }
    857 
    858 void
    859 fd_motor_on(arg)
    860 	void *arg;
    861 {
    862 	struct fd_softc *fd = arg;
    863 	struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    864 	int s;
    865 
    866 	s = splbio();
    867 	fd->sc_flags &= ~FD_MOTOR_WAIT;
    868 	if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
    869 		(void) fdcintr(fdc);
    870 	splx(s);
    871 }
    872 
    873 int
    874 fdcresult(fdc)
    875 	struct fdc_softc *fdc;
    876 {
    877 	bus_space_tag_t iot = fdc->sc_iot;
    878 	bus_space_handle_t ioh = fdc->sc_ioh;
    879 	u_char i;
    880 	int j = 100000,
    881 	    n = 0;
    882 
    883 	for (; j; j--) {
    884 		i = bus_space_read_1(iot, ioh, fdsts) &
    885 		    (NE7_DIO | NE7_RQM | NE7_CB);
    886 		if (i == NE7_RQM)
    887 			return n;
    888 		if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
    889 			if (n >= sizeof(fdc->sc_status)) {
    890 				log(LOG_ERR, "fdcresult: overrun\n");
    891 				return -1;
    892 			}
    893 			fdc->sc_status[n++] =
    894 			    bus_space_read_1(iot, ioh, fddata);
    895 		}
    896 		delay(10);
    897 	}
    898 	log(LOG_ERR, "fdcresult: timeout\n");
    899 	return -1;
    900 }
    901 
    902 int
    903 out_fdc(iot, ioh, x)
    904 	bus_space_tag_t iot;
    905 	bus_space_handle_t ioh;
    906 	u_char x;
    907 {
    908 	int i = 100000;
    909 
    910 	while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
    911 	if (i <= 0)
    912 		return -1;
    913 	while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
    914 	if (i <= 0)
    915 		return -1;
    916 	bus_space_write_1(iot, ioh, fddata, x);
    917 	return 0;
    918 }
    919 
    920 int
    921 fdopen(dev, flags, mode, p)
    922 	dev_t dev;
    923 	int flags;
    924 	int mode;
    925 	struct proc *p;
    926 {
    927  	int unit;
    928 	struct fd_softc *fd;
    929 	struct fd_type *type;
    930 
    931 	unit = FDUNIT(dev);
    932 	if (unit >= fd_cd.cd_ndevs)
    933 		return ENXIO;
    934 	fd = fd_cd.cd_devs[unit];
    935 	if (fd == 0)
    936 		return ENXIO;
    937 	type = fd_dev_to_type(fd, dev);
    938 	if (type == NULL)
    939 		return ENXIO;
    940 
    941 	if ((fd->sc_flags & FD_OPEN) != 0 &&
    942 	    memcmp(fd->sc_type, type, sizeof(*type)))
    943 		return EBUSY;
    944 
    945 	fd->sc_type_copy = *type;
    946 	fd->sc_type = &fd->sc_type_copy;
    947 	fd->sc_cylin = -1;
    948 	fd->sc_flags |= FD_OPEN;
    949 
    950 	return 0;
    951 }
    952 
    953 int
    954 fdclose(dev, flags, mode, p)
    955 	dev_t dev;
    956 	int flags;
    957 	int mode;
    958 	struct proc *p;
    959 {
    960 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
    961 
    962 	fd->sc_flags &= ~FD_OPEN;
    963 	fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT);
    964 	return 0;
    965 }
    966 
    967 void
    968 fdcstart(fdc)
    969 	struct fdc_softc *fdc;
    970 {
    971 
    972 #ifdef DIAGNOSTIC
    973 	/* only got here if controller's drive queue was inactive; should
    974 	   be in idle state */
    975 	if (fdc->sc_state != DEVIDLE) {
    976 		printf("fdcstart: not idle\n");
    977 		return;
    978 	}
    979 #endif
    980 	(void) fdcintr(fdc);
    981 }
    982 
    983 void
    984 fdcstatus(dv, n, s)
    985 	struct device *dv;
    986 	int n;
    987 	char *s;
    988 {
    989 	struct fdc_softc *fdc = (void *)dv->dv_parent;
    990 	char bits[64];
    991 
    992 	if (n == 0) {
    993 		out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
    994 		(void) fdcresult(fdc);
    995 		n = 2;
    996 	}
    997 
    998 	printf("%s: %s", dv->dv_xname, s);
    999 
   1000 	switch (n) {
   1001 	case 0:
   1002 		printf("\n");
   1003 		break;
   1004 	case 2:
   1005 		printf(" (st0 %s cyl %d)\n",
   1006 		    bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS,
   1007 		    bits, sizeof(bits)), fdc->sc_status[1]);
   1008 		break;
   1009 	case 7:
   1010 		printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
   1011 		    NE7_ST0BITS, bits, sizeof(bits)));
   1012 		printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
   1013 		    NE7_ST1BITS, bits, sizeof(bits)));
   1014 		printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
   1015 		    NE7_ST2BITS, bits, sizeof(bits)));
   1016 		printf(" cyl %d head %d sec %d)\n",
   1017 		    fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
   1018 		break;
   1019 #ifdef DIAGNOSTIC
   1020 	default:
   1021 		printf("\nfdcstatus: weird size");
   1022 		break;
   1023 #endif
   1024 	}
   1025 }
   1026 
   1027 void
   1028 fdctimeout(arg)
   1029 	void *arg;
   1030 {
   1031 	struct fdc_softc *fdc = arg;
   1032 	struct fd_softc *fd = fdc->sc_drives.tqh_first;
   1033 	int s;
   1034 
   1035 	s = splbio();
   1036 #ifdef DEBUG
   1037 	log(LOG_ERR,"fdctimeout: state %d\n", fdc->sc_state);
   1038 #endif
   1039 	fdcstatus(&fd->sc_dev, 0, "timeout");
   1040 
   1041 	if (BUFQ_FIRST(&fd->sc_q) != NULL)
   1042 		fdc->sc_state++;
   1043 	else
   1044 		fdc->sc_state = DEVIDLE;
   1045 
   1046 	(void) fdcintr(fdc);
   1047 	splx(s);
   1048 }
   1049 
   1050 void
   1051 fdcpseudointr(arg)
   1052 	void *arg;
   1053 {
   1054 	int s;
   1055 
   1056 	/* Just ensure it has the right spl. */
   1057 	s = splbio();
   1058 	(void) fdcintr(arg);
   1059 	splx(s);
   1060 }
   1061 
   1062 int
   1063 fdcintr(arg)
   1064 	void *arg;
   1065 {
   1066 	struct fdc_softc *fdc = arg;
   1067 #define	st0	fdc->sc_status[0]
   1068 #define	cyl	fdc->sc_status[1]
   1069 	struct fd_softc *fd;
   1070 	struct buf *bp;
   1071 	bus_space_tag_t iot = fdc->sc_iot;
   1072 	bus_space_handle_t ioh = fdc->sc_ioh;
   1073 	int read, head, sec, i, nblks;
   1074 	struct fd_type *type;
   1075 	struct ne7_fd_formb *finfo = NULL;
   1076 
   1077 loop:
   1078 	/* Is there a drive for the controller to do a transfer with? */
   1079 	fd = fdc->sc_drives.tqh_first;
   1080 	if (fd == NULL) {
   1081 		fdc->sc_state = DEVIDLE;
   1082  		return 1;
   1083 	}
   1084 
   1085 	/* Is there a transfer to this drive?  If not, deactivate drive. */
   1086 	bp = BUFQ_FIRST(&fd->sc_q);
   1087 	if (bp == NULL) {
   1088 		fd->sc_ops = 0;
   1089 		TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
   1090 		fd->sc_active = 0;
   1091 		goto loop;
   1092 	}
   1093 
   1094 	if (bp->b_flags & B_FORMAT)
   1095 		finfo = (struct ne7_fd_formb *)bp->b_data;
   1096 
   1097 	switch (fdc->sc_state) {
   1098 	case DEVIDLE:
   1099 		fdc->sc_errors = 0;
   1100 		fd->sc_skip = 0;
   1101 		fd->sc_bcount = bp->b_bcount;
   1102 		fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
   1103 		callout_stop(&fd->sc_motoroff_ch);
   1104 		if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
   1105 			fdc->sc_state = MOTORWAIT;
   1106 			return 1;
   1107 		}
   1108 		if ((fd->sc_flags & FD_MOTOR) == 0) {
   1109 			/* Turn on the motor, being careful about pairing. */
   1110 			struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
   1111 			if (ofd && ofd->sc_flags & FD_MOTOR) {
   1112 				callout_stop(&ofd->sc_motoroff_ch);
   1113 				ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
   1114 			}
   1115 			fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
   1116 			fd_set_motor(fdc, 0);
   1117 			fdc->sc_state = MOTORWAIT;
   1118 			/* Allow .25s for motor to stabilize. */
   1119 			callout_reset(&fd->sc_motoron_ch, hz / 4,
   1120 			    fd_motor_on, fd);
   1121 			return 1;
   1122 		}
   1123 		/* Make sure the right drive is selected. */
   1124 		fd_set_motor(fdc, 0);
   1125 
   1126 		/* fall through */
   1127 	case DOSEEK:
   1128 	doseek:
   1129 		if (fd->sc_cylin == bp->b_cylinder)
   1130 			goto doio;
   1131 
   1132 		out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */
   1133 		out_fdc(iot, ioh, fd->sc_type->steprate);
   1134 		out_fdc(iot, ioh, 6);		/* XXX head load time == 6ms */
   1135 
   1136 		out_fdc(iot, ioh, NE7CMD_SEEK);	/* seek function */
   1137 		out_fdc(iot, ioh, fd->sc_drive);	/* drive number */
   1138 		out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step);
   1139 
   1140 		fd->sc_cylin = -1;
   1141 		fdc->sc_state = SEEKWAIT;
   1142 
   1143 		fd->sc_dk.dk_seek++;
   1144 		disk_busy(&fd->sc_dk);
   1145 
   1146 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
   1147 		return 1;
   1148 
   1149 	case DOIO:
   1150 	doio:
   1151 		type = fd->sc_type;
   1152 		if (finfo)
   1153 			fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
   1154 				      (char *)finfo;
   1155 		sec = fd->sc_blkno % type->seccyl;
   1156 		nblks = type->seccyl - sec;
   1157 		nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
   1158 		nblks = min(nblks, fdc->sc_maxiosize / FDC_BSIZE);
   1159 		fd->sc_nblks = nblks;
   1160 		fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE;
   1161 		head = sec / type->sectrac;
   1162 		sec -= head * type->sectrac;
   1163 #ifdef DIAGNOSTIC
   1164 		{int block;
   1165 		 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
   1166 		 if (block != fd->sc_blkno) {
   1167 			 printf("fdcintr: block %d != blkno %d\n",
   1168 				block, fd->sc_blkno);
   1169 #ifdef DDB
   1170 			 Debugger();
   1171 #endif
   1172 		 }}
   1173 #endif
   1174 		read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE;
   1175 		isa_dmastart(fdc->sc_ic, fdc->sc_drq,
   1176 		    bp->b_data + fd->sc_skip, fd->sc_nbytes,
   1177 		    NULL, read | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
   1178 #if 0 /* XXX i/o port kludge */
   1179 		bus_space_write_1(iot, ioh, fdctl, type->rate);
   1180 #else
   1181 		bus_space_write_1(iot, fdc->sc_fdctlioh, 0, type->rate);
   1182 #endif
   1183 #ifdef FD_DEBUG
   1184 		printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
   1185 			read ? "read" : "write", fd->sc_drive, fd->sc_cylin,
   1186 			head, sec, nblks);
   1187 #endif
   1188 		if (finfo) {
   1189 			/* formatting */
   1190 			if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
   1191 				fdc->sc_errors = 4;
   1192 				fdcretry(fdc);
   1193 				goto loop;
   1194 			}
   1195 			out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
   1196 			out_fdc(iot, ioh, finfo->fd_formb_secshift);
   1197 			out_fdc(iot, ioh, finfo->fd_formb_nsecs);
   1198 			out_fdc(iot, ioh, finfo->fd_formb_gaplen);
   1199 			out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
   1200 		} else {
   1201 			if (read)
   1202 				out_fdc(iot, ioh, NE7CMD_READ);	/* READ */
   1203 			else
   1204 				out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
   1205 			out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
   1206 			out_fdc(iot, ioh, fd->sc_cylin); /* track */
   1207 			out_fdc(iot, ioh, head);
   1208 			out_fdc(iot, ioh, sec + 1);	 /* sector +1 */
   1209 			out_fdc(iot, ioh, type->secsize);/* sector size */
   1210 			out_fdc(iot, ioh, type->sectrac);/* sectors/track */
   1211 			out_fdc(iot, ioh, type->gap1);	 /* gap1 size */
   1212 			out_fdc(iot, ioh, type->datalen);/* data length */
   1213 		}
   1214 		fdc->sc_state = IOCOMPLETE;
   1215 
   1216 		disk_busy(&fd->sc_dk);
   1217 
   1218 		/* allow 2 seconds for operation */
   1219 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
   1220 		return 1;				/* will return later */
   1221 
   1222 	case SEEKWAIT:
   1223 		callout_stop(&fdc->sc_timo_ch);
   1224 		fdc->sc_state = SEEKCOMPLETE;
   1225 		/* allow 1/50 second for heads to settle */
   1226 		callout_reset(&fdc->sc_intr_ch, hz / 50, fdcpseudointr, fdc);
   1227 		return 1;
   1228 
   1229 	case SEEKCOMPLETE:
   1230 		disk_unbusy(&fd->sc_dk, 0);	/* no data on seek */
   1231 
   1232 		/* Make sure seek really happened. */
   1233 		out_fdc(iot, ioh, NE7CMD_SENSEI);
   1234 		if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
   1235 		    cyl != bp->b_cylinder * fd->sc_type->step) {
   1236 #ifdef FD_DEBUG
   1237 			fdcstatus(&fd->sc_dev, 2, "seek failed");
   1238 #endif
   1239 			fdcretry(fdc);
   1240 			goto loop;
   1241 		}
   1242 		fd->sc_cylin = bp->b_cylinder;
   1243 		goto doio;
   1244 
   1245 	case IOTIMEDOUT:
   1246 		isa_dmaabort(fdc->sc_ic, fdc->sc_drq);
   1247 	case SEEKTIMEDOUT:
   1248 	case RECALTIMEDOUT:
   1249 	case RESETTIMEDOUT:
   1250 		fdcretry(fdc);
   1251 		goto loop;
   1252 
   1253 	case IOCOMPLETE: /* IO DONE, post-analyze */
   1254 		callout_stop(&fdc->sc_timo_ch);
   1255 
   1256 		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid));
   1257 
   1258 		if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
   1259 			isa_dmaabort(fdc->sc_ic, fdc->sc_drq);
   1260 #ifdef FD_DEBUG
   1261 			fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
   1262 			    "read failed" : "write failed");
   1263 			printf("blkno %d nblks %d\n",
   1264 			    fd->sc_blkno, fd->sc_nblks);
   1265 #endif
   1266 			fdcretry(fdc);
   1267 			goto loop;
   1268 		}
   1269 		isa_dmadone(fdc->sc_ic, fdc->sc_drq);
   1270 		if (fdc->sc_errors) {
   1271 			diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF,
   1272 			    fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
   1273 			printf("\n");
   1274 			fdc->sc_errors = 0;
   1275 		}
   1276 		fd->sc_blkno += fd->sc_nblks;
   1277 		fd->sc_skip += fd->sc_nbytes;
   1278 		fd->sc_bcount -= fd->sc_nbytes;
   1279 		if (!finfo && fd->sc_bcount > 0) {
   1280 			bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl;
   1281 			goto doseek;
   1282 		}
   1283 		fdfinish(fd, bp);
   1284 		goto loop;
   1285 
   1286 	case DORESET:
   1287 		/* try a reset, keep motor on */
   1288 		fd_set_motor(fdc, 1);
   1289 		delay(100);
   1290 		fd_set_motor(fdc, 0);
   1291 		fdc->sc_state = RESETCOMPLETE;
   1292 		callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc);
   1293 		return 1;			/* will return later */
   1294 
   1295 	case RESETCOMPLETE:
   1296 		callout_stop(&fdc->sc_timo_ch);
   1297 		/* clear the controller output buffer */
   1298 		for (i = 0; i < 4; i++) {
   1299 			out_fdc(iot, ioh, NE7CMD_SENSEI);
   1300 			(void) fdcresult(fdc);
   1301 		}
   1302 
   1303 		/* fall through */
   1304 	case DORECAL:
   1305 		out_fdc(iot, ioh, NE7CMD_RECAL);	/* recalibrate function */
   1306 		out_fdc(iot, ioh, fd->sc_drive);
   1307 		fdc->sc_state = RECALWAIT;
   1308 		callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc);
   1309 		return 1;			/* will return later */
   1310 
   1311 	case RECALWAIT:
   1312 		callout_stop(&fdc->sc_timo_ch);
   1313 		fdc->sc_state = RECALCOMPLETE;
   1314 		/* allow 1/30 second for heads to settle */
   1315 		callout_reset(&fdc->sc_intr_ch, hz / 30, fdcpseudointr, fdc);
   1316 		return 1;			/* will return later */
   1317 
   1318 	case RECALCOMPLETE:
   1319 		out_fdc(iot, ioh, NE7CMD_SENSEI);
   1320 		if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
   1321 #ifdef FD_DEBUG
   1322 			fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
   1323 #endif
   1324 			fdcretry(fdc);
   1325 			goto loop;
   1326 		}
   1327 		fd->sc_cylin = 0;
   1328 		goto doseek;
   1329 
   1330 	case MOTORWAIT:
   1331 		if (fd->sc_flags & FD_MOTOR_WAIT)
   1332 			return 1;		/* time's not up yet */
   1333 		goto doseek;
   1334 
   1335 	default:
   1336 		fdcstatus(&fd->sc_dev, 0, "stray interrupt");
   1337 		return 1;
   1338 	}
   1339 #ifdef DIAGNOSTIC
   1340 	panic("fdcintr: impossible");
   1341 #endif
   1342 #undef	st0
   1343 #undef	cyl
   1344 }
   1345 
   1346 void
   1347 fdcretry(fdc)
   1348 	struct fdc_softc *fdc;
   1349 {
   1350 	char bits[64];
   1351 	struct fd_softc *fd;
   1352 	struct buf *bp;
   1353 
   1354 	fd = fdc->sc_drives.tqh_first;
   1355 	bp = BUFQ_FIRST(&fd->sc_q);
   1356 
   1357 	if (fd->sc_opts & FDOPT_NORETRY)
   1358 	    goto fail;
   1359 	switch (fdc->sc_errors) {
   1360 	case 0:
   1361 		/* try again */
   1362 		fdc->sc_state = DOSEEK;
   1363 		break;
   1364 
   1365 	case 1: case 2: case 3:
   1366 		/* didn't work; try recalibrating */
   1367 		fdc->sc_state = DORECAL;
   1368 		break;
   1369 
   1370 	case 4:
   1371 		/* still no go; reset the bastard */
   1372 		fdc->sc_state = DORESET;
   1373 		break;
   1374 
   1375 	default:
   1376 	fail:
   1377 		if ((fd->sc_opts & FDOPT_SILENT) == 0) {
   1378 			diskerr(bp, "fd", "hard error", LOG_PRINTF,
   1379 				fd->sc_skip / FDC_BSIZE,
   1380 				(struct disklabel *)NULL);
   1381 
   1382 			printf(" (st0 %s",
   1383 			       bitmask_snprintf(fdc->sc_status[0],
   1384 						NE7_ST0BITS, bits,
   1385 						sizeof(bits)));
   1386 			printf(" st1 %s",
   1387 			       bitmask_snprintf(fdc->sc_status[1],
   1388 						NE7_ST1BITS, bits,
   1389 						sizeof(bits)));
   1390 			printf(" st2 %s",
   1391 			       bitmask_snprintf(fdc->sc_status[2],
   1392 						NE7_ST2BITS, bits,
   1393 						sizeof(bits)));
   1394 			printf(" cyl %d head %d sec %d)\n",
   1395 			       fdc->sc_status[3],
   1396 			       fdc->sc_status[4],
   1397 			       fdc->sc_status[5]);
   1398 		}
   1399 
   1400 		bp->b_flags |= B_ERROR;
   1401 		bp->b_error = EIO;
   1402 		fdfinish(fd, bp);
   1403 	}
   1404 	fdc->sc_errors++;
   1405 }
   1406 
   1407 int
   1408 fdsize(dev)
   1409 	dev_t dev;
   1410 {
   1411 
   1412 	/* Swapping to floppies would not make sense. */
   1413 	return -1;
   1414 }
   1415 
   1416 int
   1417 fddump(dev, blkno, va, size)
   1418 	dev_t dev;
   1419 	daddr_t blkno;
   1420 	caddr_t va;
   1421 	size_t size;
   1422 {
   1423 
   1424 	/* Not implemented. */
   1425 	return ENXIO;
   1426 }
   1427 
   1428 int
   1429 fdioctl(dev, cmd, addr, flag, p)
   1430 	dev_t dev;
   1431 	u_long cmd;
   1432 	caddr_t addr;
   1433 	int flag;
   1434 	struct proc *p;
   1435 {
   1436 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1437 	struct fdformat_parms *form_parms;
   1438 	struct fdformat_cmd *form_cmd;
   1439 	struct ne7_fd_formb fd_formb;
   1440 	struct disklabel buffer;
   1441 	int error;
   1442 	unsigned int scratch;
   1443 	int il[FD_MAX_NSEC + 1];
   1444 	register int i, j;
   1445 
   1446 	switch (cmd) {
   1447 	case DIOCGDINFO:
   1448 		memset(&buffer, 0, sizeof(buffer));
   1449 
   1450 		buffer.d_secpercyl = fd->sc_type->seccyl;
   1451 		buffer.d_type = DTYPE_FLOPPY;
   1452 		buffer.d_secsize = FDC_BSIZE;
   1453 
   1454 		if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
   1455 			return EINVAL;
   1456 
   1457 		*(struct disklabel *)addr = buffer;
   1458 		return 0;
   1459 
   1460 	case DIOCWLABEL:
   1461 		if ((flag & FWRITE) == 0)
   1462 			return EBADF;
   1463 		/* XXX do something */
   1464 		return 0;
   1465 
   1466 	case DIOCWDINFO:
   1467 		if ((flag & FWRITE) == 0)
   1468 			return EBADF;
   1469 
   1470 		error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
   1471 		if (error)
   1472 			return error;
   1473 
   1474 		error = writedisklabel(dev, fdstrategy, &buffer, NULL);
   1475 		return error;
   1476 
   1477 	case FDIOCGETFORMAT:
   1478 		form_parms = (struct fdformat_parms *)addr;
   1479 		form_parms->fdformat_version = FDFORMAT_VERSION;
   1480 		form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
   1481 		form_parms->ncyl = fd->sc_type->cyls;
   1482 		form_parms->nspt = fd->sc_type->sectrac;
   1483 		form_parms->ntrk = fd->sc_type->heads;
   1484 		form_parms->stepspercyl = fd->sc_type->step;
   1485 		form_parms->gaplen = fd->sc_type->gap2;
   1486 		form_parms->fillbyte = fd->sc_type->fillbyte;
   1487 		form_parms->interleave = fd->sc_type->interleave;
   1488 		switch (fd->sc_type->rate) {
   1489 		case FDC_500KBPS:
   1490 			form_parms->xfer_rate = 500 * 1024;
   1491 			break;
   1492 		case FDC_300KBPS:
   1493 			form_parms->xfer_rate = 300 * 1024;
   1494 			break;
   1495 		case FDC_250KBPS:
   1496 			form_parms->xfer_rate = 250 * 1024;
   1497 			break;
   1498 		default:
   1499 			return EINVAL;
   1500 		}
   1501 		return 0;
   1502 
   1503 	case FDIOCSETFORMAT:
   1504 		if((flag & FWRITE) == 0)
   1505 			return EBADF;	/* must be opened for writing */
   1506 		form_parms = (struct fdformat_parms *)addr;
   1507 		if (form_parms->fdformat_version != FDFORMAT_VERSION)
   1508 			return EINVAL;	/* wrong version of formatting prog */
   1509 
   1510 		scratch = form_parms->nbps >> 7;
   1511 		if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
   1512 		    scratch & ~(1 << (ffs(scratch)-1)))
   1513 			/* not a power-of-two multiple of 128 */
   1514 			return EINVAL;
   1515 
   1516 		switch (form_parms->xfer_rate) {
   1517 		case 500 * 1024:
   1518 			fd->sc_type->rate = FDC_500KBPS;
   1519 			break;
   1520 		case 300 * 1024:
   1521 			fd->sc_type->rate = FDC_300KBPS;
   1522 			break;
   1523 		case 250 * 1024:
   1524 			fd->sc_type->rate = FDC_250KBPS;
   1525 			break;
   1526 		default:
   1527 			return EINVAL;
   1528 		}
   1529 
   1530 		if (form_parms->nspt > FD_MAX_NSEC ||
   1531 		    form_parms->fillbyte > 0xff ||
   1532 		    form_parms->interleave > 0xff)
   1533 			return EINVAL;
   1534 		fd->sc_type->sectrac = form_parms->nspt;
   1535 		if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
   1536 			return EINVAL;
   1537 		fd->sc_type->heads = form_parms->ntrk;
   1538 		fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
   1539 		fd->sc_type->secsize = ffs(scratch)-1;
   1540 		fd->sc_type->gap2 = form_parms->gaplen;
   1541 		fd->sc_type->cyls = form_parms->ncyl;
   1542 		fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
   1543 			form_parms->nbps / DEV_BSIZE;
   1544 		fd->sc_type->step = form_parms->stepspercyl;
   1545 		fd->sc_type->fillbyte = form_parms->fillbyte;
   1546 		fd->sc_type->interleave = form_parms->interleave;
   1547 		return 0;
   1548 
   1549 	case FDIOCFORMAT_TRACK:
   1550 		if((flag & FWRITE) == 0)
   1551 			return EBADF;	/* must be opened for writing */
   1552 		form_cmd = (struct fdformat_cmd *)addr;
   1553 		if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
   1554 			return EINVAL;	/* wrong version of formatting prog */
   1555 
   1556 		if (form_cmd->head >= fd->sc_type->heads ||
   1557 		    form_cmd->cylinder >= fd->sc_type->cyls) {
   1558 			return EINVAL;
   1559 		}
   1560 
   1561 		fd_formb.head = form_cmd->head;
   1562 		fd_formb.cyl = form_cmd->cylinder;
   1563 		fd_formb.transfer_rate = fd->sc_type->rate;
   1564 		fd_formb.fd_formb_secshift = fd->sc_type->secsize;
   1565 		fd_formb.fd_formb_nsecs = fd->sc_type->sectrac;
   1566 		fd_formb.fd_formb_gaplen = fd->sc_type->gap2;
   1567 		fd_formb.fd_formb_fillbyte = fd->sc_type->fillbyte;
   1568 
   1569 		memset(il, 0, sizeof il);
   1570 		for (j = 0, i = 1; i <= fd_formb.fd_formb_nsecs; i++) {
   1571 			while (il[(j%fd_formb.fd_formb_nsecs)+1])
   1572 				j++;
   1573 			il[(j%fd_formb.fd_formb_nsecs)+1] = i;
   1574 			j += fd->sc_type->interleave;
   1575 		}
   1576 		for (i = 0; i < fd_formb.fd_formb_nsecs; i++) {
   1577 			fd_formb.fd_formb_cylno(i) = form_cmd->cylinder;
   1578 			fd_formb.fd_formb_headno(i) = form_cmd->head;
   1579 			fd_formb.fd_formb_secno(i) = il[i+1];
   1580 			fd_formb.fd_formb_secsize(i) = fd->sc_type->secsize;
   1581 		}
   1582 
   1583 		return fdformat(dev, &fd_formb, p);
   1584 
   1585 	case FDIOCGETOPTS:		/* get drive options */
   1586 		*(int *)addr = fd->sc_opts;
   1587 		return 0;
   1588 
   1589 	case FDIOCSETOPTS:		/* set drive options */
   1590 		fd->sc_opts = *(int *)addr;
   1591 		return 0;
   1592 
   1593 	default:
   1594 		return ENOTTY;
   1595 	}
   1596 
   1597 #ifdef DIAGNOSTIC
   1598 	panic("fdioctl: impossible");
   1599 #endif
   1600 }
   1601 
   1602 int
   1603 fdformat(dev, finfo, p)
   1604 	dev_t dev;
   1605 	struct ne7_fd_formb *finfo;
   1606 	struct proc *p;
   1607 {
   1608 	int rv = 0, s;
   1609 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1610 	struct fd_type *type = fd->sc_type;
   1611 	struct buf *bp;
   1612 
   1613 	/* set up a buffer header for fdstrategy() */
   1614 	bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
   1615 	if(bp == 0)
   1616 		return ENOBUFS;
   1617 	PHOLD(p);
   1618 	memset((void *)bp, 0, sizeof(struct buf));
   1619 	bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
   1620 	bp->b_proc = p;
   1621 	bp->b_dev = dev;
   1622 
   1623 	/*
   1624 	 * calculate a fake blkno, so fdstrategy() would initiate a
   1625 	 * seek to the requested cylinder
   1626 	 */
   1627 	bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
   1628 		       + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
   1629 
   1630 	bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
   1631 	bp->b_data = (caddr_t)finfo;
   1632 
   1633 #ifdef DEBUG
   1634 	printf("fdformat: blkno %x count %lx\n", bp->b_blkno, bp->b_bcount);
   1635 #endif
   1636 
   1637 	/* now do the format */
   1638 	fdstrategy(bp);
   1639 
   1640 	/* ...and wait for it to complete */
   1641 	s = splbio();
   1642 	while(!(bp->b_flags & B_DONE)) {
   1643 		rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
   1644 		if (rv == EWOULDBLOCK)
   1645 			break;
   1646 	}
   1647 	splx(s);
   1648 
   1649 	if (rv == EWOULDBLOCK) {
   1650 		/* timed out */
   1651 		rv = EIO;
   1652 		biodone(bp);
   1653 	}
   1654 	if(bp->b_flags & B_ERROR) {
   1655 		rv = bp->b_error;
   1656 	}
   1657 	PRELE(p);
   1658 	free(bp, M_TEMP);
   1659 	return rv;
   1660 }
   1661 
   1662 /*
   1663  * Mountroot hook: prompt the user to enter the root file system
   1664  * floppy.
   1665  */
   1666 void
   1667 fd_mountroot_hook(dev)
   1668 	struct device *dev;
   1669 {
   1670 	int c;
   1671 
   1672 	printf("Insert filesystem floppy and press return.");
   1673 	cnpollc(1);
   1674 	for (;;) {
   1675 		c = cngetc();
   1676 		if ((c == '\r') || (c == '\n')) {
   1677 			printf("\n");
   1678 			break;
   1679 		}
   1680 	}
   1681 	cnpollc(0);
   1682 }
   1683