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