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