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