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