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