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