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