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