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