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