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