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