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