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