Home | History | Annotate | Line # | Download | only in dev
hdfd.c revision 1.16
      1 /*	$NetBSD: hdfd.c,v 1.16 1999/10/21 15:03:28 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 "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 DIOCSDINFO:
   1334 	case DIOCWDINFO:
   1335 		if ((flag & FWRITE) == 0)
   1336 		    return EBADF;
   1337 
   1338 		error = setdisklabel(&buffer, (struct disklabel *)addr, 0,NULL);
   1339 		if (error)
   1340 		    return error;
   1341 
   1342 		if (cmd == DIOCWDINFO)
   1343 		    error = writedisklabel(dev, fdstrategy, &buffer, NULL);
   1344 		return error;
   1345 
   1346 	case FDIOCGETFORMAT:
   1347 		form_parms = (struct fdformat_parms *)addr;
   1348 		form_parms->fdformat_version = FDFORMAT_VERSION;
   1349 		form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
   1350 		form_parms->ncyl = fd->sc_type->tracks;
   1351 		form_parms->nspt = fd->sc_type->sectrac;
   1352 		form_parms->ntrk = fd->sc_type->heads;
   1353 		form_parms->stepspercyl = fd->sc_type->step;
   1354 		form_parms->gaplen = fd->sc_type->gap2;
   1355 		form_parms->fillbyte = fd->sc_type->fillbyte;
   1356 		form_parms->interleave = fd->sc_type->interleave;
   1357 		switch (fd->sc_type->rate) {
   1358 		case FDC_500KBPS:
   1359 			form_parms->xfer_rate = 500 * 1024;
   1360 			break;
   1361 		case FDC_300KBPS:
   1362 			form_parms->xfer_rate = 300 * 1024;
   1363 			break;
   1364 		case FDC_250KBPS:
   1365 			form_parms->xfer_rate = 250 * 1024;
   1366 			break;
   1367 		case FDC_125KBPS:
   1368 			form_parms->xfer_rate = 125 * 1024;
   1369 			break;
   1370 		default:
   1371 			return EINVAL;
   1372 		}
   1373 		return 0;
   1374 
   1375 	case FDIOCSETFORMAT:
   1376 		if((flag & FWRITE) == 0)
   1377 			return EBADF;	/* must be opened for writing */
   1378 		form_parms = (struct fdformat_parms *)addr;
   1379 		if (form_parms->fdformat_version != FDFORMAT_VERSION)
   1380 			return EINVAL;	/* wrong version of formatting prog */
   1381 
   1382 		scratch = form_parms->nbps >> 7;
   1383 		if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
   1384 		    scratch & ~(1 << (ffs(scratch)-1)))
   1385 			/* not a power-of-two multiple of 128 */
   1386 			return EINVAL;
   1387 
   1388 		switch (form_parms->xfer_rate) {
   1389 		case 500 * 1024:
   1390 			fd->sc_type->rate = FDC_500KBPS;
   1391 			break;
   1392 		case 300 * 1024:
   1393 			fd->sc_type->rate = FDC_300KBPS;
   1394 			break;
   1395 		case 250 * 1024:
   1396 			fd->sc_type->rate = FDC_250KBPS;
   1397 			break;
   1398 		case 125 * 1024:
   1399 			fd->sc_type->rate = FDC_125KBPS;
   1400 			break;
   1401 		default:
   1402 			return EINVAL;
   1403 		}
   1404 
   1405 		if (form_parms->nspt > FD_MAX_NSEC ||
   1406 		    form_parms->fillbyte > 0xff ||
   1407 		    form_parms->interleave > 0xff)
   1408 			return EINVAL;
   1409 		fd->sc_type->sectrac = form_parms->nspt;
   1410 		if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
   1411 			return EINVAL;
   1412 		fd->sc_type->heads = form_parms->ntrk;
   1413 		fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
   1414 		fd->sc_type->secsize = ffs(scratch)-1;
   1415 		fd->sc_type->gap2 = form_parms->gaplen;
   1416 		fd->sc_type->tracks = form_parms->ncyl;
   1417 		fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
   1418 			form_parms->nbps / DEV_BSIZE;
   1419 		fd->sc_type->step = form_parms->stepspercyl;
   1420 		fd->sc_type->fillbyte = form_parms->fillbyte;
   1421 		fd->sc_type->interleave = form_parms->interleave;
   1422 		return 0;
   1423 
   1424 	case FDIOCFORMAT_TRACK:
   1425 		if((flag & FWRITE) == 0)
   1426 			return EBADF;	/* must be opened for writing */
   1427 		form_cmd = (struct fdformat_cmd *)addr;
   1428 		if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
   1429 			return EINVAL;	/* wrong version of formatting prog */
   1430 
   1431 		if (form_cmd->head >= fd->sc_type->heads ||
   1432 		    form_cmd->cylinder >= fd->sc_type->tracks) {
   1433 			return EINVAL;
   1434 		}
   1435 
   1436 		fd_formb.head = form_cmd->head;
   1437 		fd_formb.cyl = form_cmd->cylinder;
   1438 		fd_formb.transfer_rate = fd->sc_type->rate;
   1439 		fd_formb.fd_formb_secshift = fd->sc_type->secsize;
   1440 		fd_formb.fd_formb_nsecs = fd->sc_type->sectrac;
   1441 		fd_formb.fd_formb_gaplen = fd->sc_type->gap2;
   1442 		fd_formb.fd_formb_fillbyte = fd->sc_type->fillbyte;
   1443 
   1444 		bzero(il,sizeof il);
   1445 		for (j = 0, i = 1; i <= fd_formb.fd_formb_nsecs; i++) {
   1446 			while (il[(j%fd_formb.fd_formb_nsecs)+1])
   1447 				j++;
   1448 			il[(j%fd_formb.fd_formb_nsecs)+1] = i;
   1449 			j += fd->sc_type->interleave;
   1450 		}
   1451 		for (i = 0; i < fd_formb.fd_formb_nsecs; i++) {
   1452 			fd_formb.fd_formb_cylno(i) = form_cmd->cylinder;
   1453 			fd_formb.fd_formb_headno(i) = form_cmd->head;
   1454 			fd_formb.fd_formb_secno(i) = il[i+1];
   1455 			fd_formb.fd_formb_secsize(i) = fd->sc_type->secsize;
   1456 		}
   1457 	case FDIOCGETOPTS:		/* get drive options */
   1458 		*(int *)addr = fd->sc_opts;
   1459 		return 0;
   1460 
   1461 	case FDIOCSETOPTS:		/* set drive options */
   1462 		fd->sc_opts = *(int *)addr;
   1463 		return 0;
   1464 
   1465 
   1466 	default:
   1467 		return ENOTTY;
   1468 	}
   1469 
   1470 #ifdef DIAGNOSTIC
   1471 	panic("fdioctl: impossible");
   1472 #endif
   1473 }
   1474 
   1475 int
   1476 fdformat(dev, finfo, p)
   1477 	dev_t dev;
   1478 	struct ne7_fd_formb *finfo;
   1479 	struct proc *p;
   1480 {
   1481 	int rv = 0, s;
   1482 	struct fd_softc *fd = hdfd_cd.cd_devs[FDUNIT(dev)];
   1483 	struct fd_type *type = fd->sc_type;
   1484 	struct buf *bp;
   1485 
   1486 	/* set up a buffer header for fdstrategy() */
   1487 	bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
   1488 	if(bp == 0)
   1489 		return ENOBUFS;
   1490 	PHOLD(p);
   1491 	bzero((void *)bp, sizeof(struct buf));
   1492 	bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
   1493 	bp->b_proc = p;
   1494 	bp->b_dev = dev;
   1495 
   1496 	/*
   1497 	 * calculate a fake blkno, so fdstrategy() would initiate a
   1498 	 * seek to the requested cylinder
   1499 	 */
   1500 	bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
   1501 		       + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
   1502 
   1503 	bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
   1504 	bp->b_data = (caddr_t)finfo;
   1505 
   1506 #ifdef DEBUG
   1507 	printf("fdformat: blkno %x count %lx\n", bp->b_blkno, bp->b_bcount);
   1508 #endif
   1509 
   1510 	/* now do the format */
   1511 	fdstrategy(bp);
   1512 
   1513 	/* ...and wait for it to complete */
   1514 	s = splbio();
   1515 	while(!(bp->b_flags & B_DONE)) {
   1516 		rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
   1517 		if (rv == EWOULDBLOCK)
   1518 			break;
   1519 	}
   1520 	splx(s);
   1521 
   1522 	if (rv == EWOULDBLOCK) {
   1523 		/* timed out */
   1524 		rv = EIO;
   1525 		biodone(bp);
   1526 	}
   1527 	if(bp->b_flags & B_ERROR) {
   1528 		rv = bp->b_error;
   1529 	}
   1530 	PRELE(p);
   1531 	free(bp, M_TEMP);
   1532 	return rv;
   1533 }
   1534 
   1535 
   1536 /*
   1537  * Obtain a disklabel. Either a real one from the disk or, if there
   1538  * is none, a fake one.
   1539  */
   1540 static void
   1541 fdgetdisklabel(fd, dev)
   1542 struct fd_softc *fd;
   1543 dev_t		dev;
   1544 {
   1545 	struct disklabel	*lp;
   1546 	struct cpu_disklabel	cpulab;
   1547 
   1548 	lp   = fd->sc_dk.dk_label;
   1549 
   1550 	bzero(lp, sizeof(*lp));
   1551 	bzero(&cpulab, sizeof(cpulab));
   1552 
   1553 	lp->d_secpercyl  = fd->sc_type->seccyl;
   1554 	lp->d_type       = DTYPE_FLOPPY;
   1555 	lp->d_secsize    = FDC_BSIZE;
   1556 	lp->d_secperunit = fd->sc_type->size;
   1557 
   1558 	/*
   1559 	 * If there is no label on the disk: fake one
   1560 	 */
   1561 	if (readdisklabel(dev, fdstrategy, lp, &cpulab) != NULL)
   1562 		fdgetdefaultlabel(fd, lp, RAW_PART);
   1563 
   1564 	if ((FDC_BSIZE * fd->sc_type->size)
   1565 		< (lp->d_secsize * lp->d_secperunit)) {
   1566 		/*
   1567 		 * XXX: Ignore these fields. If you drop a vnddisk
   1568 		 *	on more than one floppy, you'll get disturbing
   1569 		 *	sounds!
   1570 		 */
   1571 		lp->d_secpercyl  = fd->sc_type->seccyl;
   1572 		lp->d_type       = DTYPE_FLOPPY;
   1573 		lp->d_secsize    = FDC_BSIZE;
   1574 		lp->d_secperunit = fd->sc_type->size;
   1575 	}
   1576 }
   1577 
   1578 /*
   1579  * Build defaultdisk label. For now we only create a label from what we
   1580  * know from 'sc'.
   1581  */
   1582 static void
   1583 fdgetdefaultlabel(fd, lp, part)
   1584 	struct fd_softc  *fd;
   1585 	struct disklabel *lp;
   1586 	int part;
   1587 {
   1588 	bzero(lp, sizeof(struct disklabel));
   1589 
   1590 	lp->d_secsize     = 128 * (1 << fd->sc_type->secsize);
   1591 	lp->d_ntracks     = fd->sc_type->heads;
   1592 	lp->d_nsectors    = fd->sc_type->sectrac;
   1593 	lp->d_secpercyl   = lp->d_ntracks * lp->d_nsectors;
   1594 	lp->d_ncylinders  = fd->sc_type->size / lp->d_secpercyl;
   1595 	lp->d_secperunit  = fd->sc_type->size;
   1596 
   1597 	lp->d_type        = DTYPE_FLOPPY;
   1598 	lp->d_rpm         = 300; 	/* good guess I suppose.	*/
   1599 	lp->d_interleave  = 1;		/* FIXME: is this OK?		*/
   1600 	lp->d_bbsize      = 0;
   1601 	lp->d_sbsize      = 0;
   1602 	lp->d_npartitions = part + 1;
   1603 	lp->d_trkseek     = 6000; 	/* Who cares...			*/
   1604 	lp->d_magic       = DISKMAGIC;
   1605 	lp->d_magic2      = DISKMAGIC;
   1606 	lp->d_checksum    = dkcksum(lp);
   1607 	lp->d_partitions[part].p_size   = lp->d_secperunit;
   1608 	lp->d_partitions[part].p_fstype = FS_UNUSED;
   1609 	lp->d_partitions[part].p_fsize  = 1024;
   1610 	lp->d_partitions[part].p_frag   = 8;
   1611 }
   1612