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