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