Home | History | Annotate | Line # | Download | only in mainbus
fd.c revision 1.14
      1 /*	$NetBSD: fd.c,v 1.14 2003/01/31 02:05:41 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 		{daddr_t  block;
   1056 		 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
   1057 		 if (block != fd->sc_blkno) {
   1058 			 printf("fdcintr: block %" PRId64
   1059 			     " != blkno %" PRId64 "\n",
   1060 				block, fd->sc_blkno);
   1061 #ifdef DDB
   1062 			 Debugger();
   1063 #endif
   1064 		 }}
   1065 #endif
   1066 		read = bp->b_flags & B_READ;
   1067 		if (read) {
   1068 			fdc->sc_fh.fh_func = floppy_read_fiq;
   1069 			fdc->sc_fh.fh_size = floppy_read_fiq_end -
   1070 			    floppy_read_fiq;
   1071 		} else {
   1072 			fdc->sc_fh.fh_func = floppy_write_fiq;
   1073 			fdc->sc_fh.fh_size = floppy_read_fiq_end -
   1074 			    floppy_read_fiq;
   1075 		}
   1076 		fdc->sc_fh.fh_flags = 0;
   1077 		fdc->sc_fh.fh_regs = &fdc->sc_fr;
   1078 		fdc->sc_fr.fr_r9 = IOMD_BASE + (IOMD_FIQRQ << 2);
   1079 		fdc->sc_fr.fr_r10 = fd->sc_nbytes;
   1080 		fdc->sc_fr.fr_r11 = (u_int)(bp->b_data + fd->sc_skip);
   1081 		fdc->sc_fr.fr_r12 = fdc->sc_drq;
   1082 #ifdef FD_DEBUG
   1083 		printf("fdc-doio:r9=%x r10=%x r11=%x r12=%x data=%x skip=%x\n",
   1084 		    fdc->sc_fr.fr_r9, fdc->sc_fr.fh_r10, fdc->sc_fr.fh_r11,
   1085 		    fdc->sc_fr.fh_r12, (u_int)bp->b_data, fd->sc_skip);
   1086 #endif
   1087 		if (fiq_claim(&fdc->sc_fh) == -1)
   1088 			panic("%s: Cannot claim FIQ vector", fdc->sc_dev.dv_xname);
   1089 		IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x01);
   1090 		bus_space_write_2(iot, ioh, fdctl, type->rate);
   1091 #ifdef FD_DEBUG
   1092 		printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
   1093 			read ? "read" : "write", fd->sc_drive, fd->sc_cylin,
   1094 			head, sec, nblks);
   1095 #endif
   1096 		if (finfo) {
   1097 			/* formatting */
   1098 			if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
   1099 				fdc->sc_errors = 4;
   1100 				fdcretry(fdc);
   1101 				goto loop;
   1102 			}
   1103 			out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
   1104 			out_fdc(iot, ioh, finfo->fd_formb_secshift);
   1105 			out_fdc(iot, ioh, finfo->fd_formb_nsecs);
   1106 			out_fdc(iot, ioh, finfo->fd_formb_gaplen);
   1107 			out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
   1108 		} else {
   1109 			if (read)
   1110 				out_fdc(iot, ioh, NE7CMD_READ);	/* READ */
   1111 			else
   1112 				out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
   1113 			out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
   1114 			out_fdc(iot, ioh, fd->sc_cylin); /* track */
   1115 			out_fdc(iot, ioh, head);
   1116 			out_fdc(iot, ioh, sec + 1);	 /* sector +1 */
   1117 			out_fdc(iot, ioh, type->secsize);/* sector size */
   1118 			out_fdc(iot, ioh, type->sectrac);/* sectors/track */
   1119 			out_fdc(iot, ioh, type->gap1);	 /* gap1 size */
   1120 			out_fdc(iot, ioh, type->datalen);/* data length */
   1121 		}
   1122 		fdc->sc_state = IOCOMPLETE;
   1123 
   1124 		disk_busy(&fd->sc_dk);
   1125 
   1126 		/* allow 2 seconds for operation */
   1127 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
   1128 		return 1;				/* will return later */
   1129 
   1130 	case SEEKWAIT:
   1131 		callout_stop(&fdc->sc_timo_ch);
   1132 		fdc->sc_state = SEEKCOMPLETE;
   1133 		/* allow 1/50 second for heads to settle */
   1134 #if 0
   1135 		callout_reset(&fdc->sc_intr_ch, hz / 50, fdcpseudointr, fdc);
   1136 #endif
   1137 		return 1;
   1138 
   1139 	case SEEKCOMPLETE:
   1140 		/* no data on seek */
   1141 		disk_unbusy(&fd->sc_dk, 0, 0);
   1142 
   1143 		/* Make sure seek really happened. */
   1144 		out_fdc(iot, ioh, NE7CMD_SENSEI);
   1145 		if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
   1146 		    cyl != bp->b_cylinder * fd->sc_type->step) {
   1147 #ifdef FD_DEBUG
   1148 			fdcstatus(&fd->sc_dev, 2, "seek failed");
   1149 #endif
   1150 			fdcretry(fdc);
   1151 			goto loop;
   1152 		}
   1153 		fd->sc_cylin = bp->b_cylinder;
   1154 		goto doio;
   1155 
   1156 	case IOTIMEDOUT:
   1157 		fiq_release(&fdc->sc_fh);
   1158 		IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
   1159 	case SEEKTIMEDOUT:
   1160 	case RECALTIMEDOUT:
   1161 	case RESETTIMEDOUT:
   1162 		fdcretry(fdc);
   1163 		goto loop;
   1164 
   1165 	case IOCOMPLETE: /* IO DONE, post-analyze */
   1166 		callout_stop(&fdc->sc_timo_ch);
   1167 
   1168 		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
   1169 		    (bp->b_flags & B_READ));
   1170 
   1171 		if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
   1172 			fiq_release(&fdc->sc_fh);
   1173 			IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
   1174 #ifdef FD_DEBUG
   1175 			fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
   1176 			    "read failed" : "write failed");
   1177 			printf("blkno %d nblks %d\n",
   1178 			    fd->sc_blkno, fd->sc_nblks);
   1179 #endif
   1180 			fdcretry(fdc);
   1181 			goto loop;
   1182 		}
   1183 		fiq_release(&fdc->sc_fh);
   1184 		IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
   1185 		if (fdc->sc_errors) {
   1186 #if 0
   1187 			diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF,
   1188 			    fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
   1189 			printf("\n");
   1190 #endif
   1191 			fdc->sc_errors = 0;
   1192 		}
   1193 		fd->sc_blkno += fd->sc_nblks;
   1194 		fd->sc_skip += fd->sc_nbytes;
   1195 		fd->sc_bcount -= fd->sc_nbytes;
   1196 		if (!finfo && fd->sc_bcount > 0) {
   1197 			bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl;
   1198 			goto doseek;
   1199 		}
   1200 		fdfinish(fd, bp);
   1201 		goto loop;
   1202 
   1203 	case DORESET:
   1204 		/* try a reset, keep motor on */
   1205 		fd_set_motor(fdc, 1);
   1206 		delay(100);
   1207 		fd_set_motor(fdc, 0);
   1208 		fdc->sc_state = RESETCOMPLETE;
   1209 		callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc);
   1210 		return 1;			/* will return later */
   1211 
   1212 	case RESETCOMPLETE:
   1213 		callout_stop(&fdc->sc_timo_ch);
   1214 		/* clear the controller output buffer */
   1215 		for (i = 0; i < 4; i++) {
   1216 			out_fdc(iot, ioh, NE7CMD_SENSEI);
   1217 			(void) fdcresult(fdc);
   1218 		}
   1219 
   1220 		/* fall through */
   1221 	case DORECAL:
   1222 		out_fdc(iot, ioh, NE7CMD_RECAL);	/* recalibrate function */
   1223 		out_fdc(iot, ioh, fd->sc_drive);
   1224 		fdc->sc_state = RECALWAIT;
   1225 		callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc);
   1226 		return 1;			/* will return later */
   1227 
   1228 	case RECALWAIT:
   1229 		callout_stop(&fdc->sc_timo_ch);
   1230 		fdc->sc_state = RECALCOMPLETE;
   1231 		/* allow 1/30 second for heads to settle */
   1232 #if 0
   1233 		callout_reset(&fdc->sc_intr_ch, hz / 30, fdcpseudointr, fdc);
   1234 #endif
   1235 		return 1;			/* will return later */
   1236 
   1237 	case RECALCOMPLETE:
   1238 		out_fdc(iot, ioh, NE7CMD_SENSEI);
   1239 		if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
   1240 #ifdef FD_DEBUG
   1241 			fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
   1242 #endif
   1243 			fdcretry(fdc);
   1244 			goto loop;
   1245 		}
   1246 		fd->sc_cylin = 0;
   1247 		goto doseek;
   1248 
   1249 	case MOTORWAIT:
   1250 		if (fd->sc_flags & FD_MOTOR_WAIT)
   1251 			return 1;		/* time's not up yet */
   1252 		goto doseek;
   1253 
   1254 	default:
   1255 		fdcstatus(&fd->sc_dev, 0, "stray interrupt");
   1256 		return 1;
   1257 	}
   1258 #ifdef DIAGNOSTIC
   1259 	panic("fdcintr: impossible");
   1260 #endif
   1261 #undef	st0
   1262 #undef	cyl
   1263 }
   1264 
   1265 void
   1266 fdcretry(fdc)
   1267 	struct fdc_softc *fdc;
   1268 {
   1269 	char bits[64];
   1270 	struct fd_softc *fd;
   1271 	struct buf *bp;
   1272 
   1273 	fd = fdc->sc_drives.tqh_first;
   1274 	bp = BUFQ_PEEK(&fd->sc_q);
   1275 
   1276 	if (fd->sc_opts & FDOPT_NORETRY)
   1277 	    goto fail;
   1278 	switch (fdc->sc_errors) {
   1279 	case 0:
   1280 		/* try again */
   1281 		fdc->sc_state = DOSEEK;
   1282 		break;
   1283 
   1284 	case 1: case 2: case 3:
   1285 		/* didn't work; try recalibrating */
   1286 		fdc->sc_state = DORECAL;
   1287 		break;
   1288 
   1289 	case 4:
   1290 		/* still no go; reset the bastard */
   1291 		fdc->sc_state = DORESET;
   1292 		break;
   1293 
   1294 	default:
   1295 	fail:
   1296 		if ((fd->sc_opts & FDOPT_SILENT) == 0) {
   1297 			diskerr(bp, "fd", "hard error", LOG_PRINTF,
   1298 				fd->sc_skip / FDC_BSIZE,
   1299 				(struct disklabel *)NULL);
   1300 
   1301 			printf(" (st0 %s",
   1302 			       bitmask_snprintf(fdc->sc_status[0],
   1303 						NE7_ST0BITS, bits,
   1304 						sizeof(bits)));
   1305 			printf(" st1 %s",
   1306 			       bitmask_snprintf(fdc->sc_status[1],
   1307 						NE7_ST1BITS, bits,
   1308 						sizeof(bits)));
   1309 			printf(" st2 %s",
   1310 			       bitmask_snprintf(fdc->sc_status[2],
   1311 						NE7_ST2BITS, bits,
   1312 						sizeof(bits)));
   1313 			printf(" cyl %d head %d sec %d)\n",
   1314 			       fdc->sc_status[3],
   1315 			       fdc->sc_status[4],
   1316 			       fdc->sc_status[5]);
   1317 		}
   1318 
   1319 		bp->b_flags |= B_ERROR;
   1320 		bp->b_error = EIO;
   1321 		fdfinish(fd, bp);
   1322 	}
   1323 	fdc->sc_errors++;
   1324 }
   1325 
   1326 int
   1327 fdioctl(dev, cmd, addr, flag, p)
   1328 	dev_t dev;
   1329 	u_long cmd;
   1330 	caddr_t addr;
   1331 	int flag;
   1332 	struct proc *p;
   1333 {
   1334 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1335 	struct fdformat_parms *form_parms;
   1336 	struct fdformat_cmd *form_cmd;
   1337 	struct ne7_fd_formb *fd_formb;
   1338 	struct disklabel buffer;
   1339 	int error;
   1340 	unsigned int scratch;
   1341 	int il[FD_MAX_NSEC + 1];
   1342 	register int i, j;
   1343 
   1344 	switch (cmd) {
   1345 	case DIOCGDINFO:
   1346 		memset(&buffer, 0, sizeof(buffer));
   1347 
   1348 		buffer.d_secpercyl = fd->sc_type->seccyl;
   1349 		buffer.d_type = DTYPE_FLOPPY;
   1350 		buffer.d_secsize = FDC_BSIZE;
   1351 
   1352 		if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
   1353 			return EINVAL;
   1354 
   1355 		*(struct disklabel *)addr = buffer;
   1356 		return 0;
   1357 
   1358 	case DIOCWLABEL:
   1359 		if ((flag & FWRITE) == 0)
   1360 			return EBADF;
   1361 		/* XXX do something */
   1362 		return 0;
   1363 
   1364 	case DIOCWDINFO:
   1365 		if ((flag & FWRITE) == 0)
   1366 			return EBADF;
   1367 
   1368 		error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
   1369 		if (error)
   1370 			return error;
   1371 
   1372 		error = writedisklabel(dev, fdstrategy, &buffer, NULL);
   1373 		return error;
   1374 
   1375 	case FDIOCGETFORMAT:
   1376 		form_parms = (struct fdformat_parms *)addr;
   1377 		form_parms->fdformat_version = FDFORMAT_VERSION;
   1378 		form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
   1379 		form_parms->ncyl = fd->sc_type->cyls;
   1380 		form_parms->nspt = fd->sc_type->sectrac;
   1381 		form_parms->ntrk = fd->sc_type->heads;
   1382 		form_parms->stepspercyl = fd->sc_type->step;
   1383 		form_parms->gaplen = fd->sc_type->gap2;
   1384 		form_parms->fillbyte = fd->sc_type->fillbyte;
   1385 		form_parms->interleave = fd->sc_type->interleave;
   1386 		switch (fd->sc_type->rate) {
   1387 		case FDC_500KBPS:
   1388 			form_parms->xfer_rate = 500 * 1024;
   1389 			break;
   1390 		case FDC_300KBPS:
   1391 			form_parms->xfer_rate = 300 * 1024;
   1392 			break;
   1393 		case FDC_250KBPS:
   1394 			form_parms->xfer_rate = 250 * 1024;
   1395 			break;
   1396 		default:
   1397 			return EINVAL;
   1398 		}
   1399 		return 0;
   1400 
   1401 	case FDIOCSETFORMAT:
   1402 		if((flag & FWRITE) == 0)
   1403 			return EBADF;	/* must be opened for writing */
   1404 		form_parms = (struct fdformat_parms *)addr;
   1405 		if (form_parms->fdformat_version != FDFORMAT_VERSION)
   1406 			return EINVAL;	/* wrong version of formatting prog */
   1407 
   1408 		scratch = form_parms->nbps >> 7;
   1409 		if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
   1410 		    scratch & ~(1 << (ffs(scratch)-1)))
   1411 			/* not a power-of-two multiple of 128 */
   1412 			return EINVAL;
   1413 
   1414 		switch (form_parms->xfer_rate) {
   1415 		case 500 * 1024:
   1416 			fd->sc_type->rate = FDC_500KBPS;
   1417 			break;
   1418 		case 300 * 1024:
   1419 			fd->sc_type->rate = FDC_300KBPS;
   1420 			break;
   1421 		case 250 * 1024:
   1422 			fd->sc_type->rate = FDC_250KBPS;
   1423 			break;
   1424 		default:
   1425 			return EINVAL;
   1426 		}
   1427 
   1428 		if (form_parms->nspt > FD_MAX_NSEC ||
   1429 		    form_parms->fillbyte > 0xff ||
   1430 		    form_parms->interleave > 0xff)
   1431 			return EINVAL;
   1432 		fd->sc_type->sectrac = form_parms->nspt;
   1433 		if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
   1434 			return EINVAL;
   1435 		fd->sc_type->heads = form_parms->ntrk;
   1436 		fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
   1437 		fd->sc_type->secsize = ffs(scratch)-1;
   1438 		fd->sc_type->gap2 = form_parms->gaplen;
   1439 		fd->sc_type->cyls = form_parms->ncyl;
   1440 		fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
   1441 			form_parms->nbps / DEV_BSIZE;
   1442 		fd->sc_type->step = form_parms->stepspercyl;
   1443 		fd->sc_type->fillbyte = form_parms->fillbyte;
   1444 		fd->sc_type->interleave = form_parms->interleave;
   1445 		return 0;
   1446 
   1447 	case FDIOCFORMAT_TRACK:
   1448 		if((flag & FWRITE) == 0)
   1449 			return EBADF;	/* must be opened for writing */
   1450 		form_cmd = (struct fdformat_cmd *)addr;
   1451 		if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
   1452 			return EINVAL;	/* wrong version of formatting prog */
   1453 
   1454 		if (form_cmd->head >= fd->sc_type->heads ||
   1455 		    form_cmd->cylinder >= fd->sc_type->cyls) {
   1456 			return EINVAL;
   1457 		}
   1458 
   1459 		fd_formb = malloc(sizeof(struct ne7_fd_formb),
   1460 		    M_TEMP, M_NOWAIT);
   1461 		if(fd_formb == 0)
   1462 			return ENOMEM;
   1463 
   1464 
   1465 		fd_formb->head = form_cmd->head;
   1466 		fd_formb->cyl = form_cmd->cylinder;
   1467 		fd_formb->transfer_rate = fd->sc_type->rate;
   1468 		fd_formb->fd_formb_secshift = fd->sc_type->secsize;
   1469 		fd_formb->fd_formb_nsecs = fd->sc_type->sectrac;
   1470 		fd_formb->fd_formb_gaplen = fd->sc_type->gap2;
   1471 		fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte;
   1472 
   1473 		memset(il, 0, sizeof il);
   1474 		for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) {
   1475 			while (il[(j%fd_formb->fd_formb_nsecs)+1])
   1476 				j++;
   1477 			il[(j%fd_formb->fd_formb_nsecs)+1] = i;
   1478 			j += fd->sc_type->interleave;
   1479 		}
   1480 		for (i = 0; i < fd_formb->fd_formb_nsecs; i++) {
   1481 			fd_formb->fd_formb_cylno(i) = form_cmd->cylinder;
   1482 			fd_formb->fd_formb_headno(i) = form_cmd->head;
   1483 			fd_formb->fd_formb_secno(i) = il[i+1];
   1484 			fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize;
   1485 		}
   1486 
   1487 		error = fdformat(dev, fd_formb, p);
   1488 		free(fd_formb, M_TEMP);
   1489 		return error;
   1490 
   1491 	case FDIOCGETOPTS:		/* get drive options */
   1492 		*(int *)addr = fd->sc_opts;
   1493 		return 0;
   1494 
   1495 	case FDIOCSETOPTS:		/* set drive options */
   1496 		fd->sc_opts = *(int *)addr;
   1497 		return 0;
   1498 
   1499 	default:
   1500 		return ENOTTY;
   1501 	}
   1502 
   1503 #ifdef DIAGNOSTIC
   1504 	panic("fdioctl: impossible");
   1505 #endif
   1506 }
   1507 
   1508 int
   1509 fdformat(dev, finfo, p)
   1510 	dev_t dev;
   1511 	struct ne7_fd_formb *finfo;
   1512 	struct proc *p;
   1513 {
   1514 	int rv = 0, s;
   1515 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1516 	struct fd_type *type = fd->sc_type;
   1517 	struct buf *bp;
   1518 
   1519 	/* set up a buffer header for fdstrategy() */
   1520 	bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
   1521 	if(bp == 0)
   1522 		return ENOBUFS;
   1523 	memset((void *)bp, 0, sizeof(struct buf));
   1524 	bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
   1525 	bp->b_proc = p;
   1526 	bp->b_dev = dev;
   1527 
   1528 	/*
   1529 	 * calculate a fake blkno, so fdstrategy() would initiate a
   1530 	 * seek to the requested cylinder
   1531 	 */
   1532 	bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
   1533 		       + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
   1534 
   1535 	bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
   1536 	bp->b_data = (caddr_t)finfo;
   1537 
   1538 #ifdef DEBUG
   1539 	printf("fdformat: blkno %x count %lx\n", bp->b_blkno, bp->b_bcount);
   1540 #endif
   1541 
   1542 	/* now do the format */
   1543 	fdstrategy(bp);
   1544 
   1545 	/* ...and wait for it to complete */
   1546 	s = splbio();
   1547 	while(!(bp->b_flags & B_DONE)) {
   1548 		rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
   1549 		if (rv == EWOULDBLOCK)
   1550 			break;
   1551 	}
   1552 	splx(s);
   1553 
   1554 	if (rv == EWOULDBLOCK) {
   1555 		/* timed out */
   1556 		rv = EIO;
   1557 		biodone(bp);
   1558 	}
   1559 	if(bp->b_flags & B_ERROR) {
   1560 		rv = bp->b_error;
   1561 	}
   1562 	free(bp, M_TEMP);
   1563 	return rv;
   1564 }
   1565 
   1566 #include "md.h"
   1567 #if NMD > 0
   1568 
   1569 #include <dev/md.h>
   1570 
   1571 int load_memory_disc_from_floppy __P((struct md_conf *md, dev_t dev));
   1572 
   1573 int
   1574 load_memory_disc_from_floppy(md, dev)
   1575 	struct md_conf *md;
   1576 	dev_t dev;
   1577 {
   1578 	struct buf *bp;
   1579 	int loop;
   1580 	int s;
   1581 	int type;
   1582 	int floppysize;
   1583 
   1584 	if (bdevsw_lookup(dev) != &fd_bdevsw)
   1585 		return(EINVAL);
   1586 
   1587 	if (md->md_type == MD_UNCONFIGURED || md->md_addr == 0)
   1588 		return(EBUSY);
   1589 
   1590 	type = FDTYPE(dev) - 1;
   1591 	if (type < 0) type = 0;
   1592 	floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
   1593 
   1594 	if (md->md_size < floppysize) {
   1595 		printf("Memory disc is not big enough for floppy image\n");
   1596 		return(EINVAL);
   1597 	}
   1598 
   1599 /* We have the memory disk ! */
   1600 
   1601 	printf("Loading memory disc : %4dK ", 0);
   1602 
   1603 /* obtain a buffer */
   1604 
   1605 	bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
   1606 
   1607 /* request no partition relocation by driver on I/O operations */
   1608 
   1609 	bp->b_dev = dev;
   1610 
   1611 	s = spl0();
   1612 
   1613 	if (fdopen(bp->b_dev, 0, 0, curproc) != 0) {
   1614 		brelse(bp);
   1615 		printf("Cannot open floppy device\n");
   1616 			return(EINVAL);
   1617 	}
   1618 
   1619 	for (loop = 0;
   1620 	    loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac);
   1621 	    ++loop) {
   1622 		printf("\x08\x08\x08\x08\x08\x08%4dK ",
   1623 		    loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
   1624 		bp->b_blkno = loop * fd_types[type].sectrac;
   1625 		bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE;
   1626 		bp->b_flags |= B_READ;
   1627 		bp->b_error = 0;
   1628 		bp->b_resid = 0;
   1629 		fdstrategy(bp);
   1630 
   1631 		if (biowait(bp))
   1632 			panic("Cannot load floppy image");
   1633 
   1634 		memcpy((caddr_t)md->md_addr + loop * fd_types[type].sectrac
   1635 		    * DEV_BSIZE, (caddr_t)bp->b_data,
   1636 		    fd_types[type].sectrac * DEV_BSIZE);
   1637 	}
   1638 	printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
   1639 	    loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
   1640 
   1641 	fdclose(bp->b_dev, 0, 0, curproc);
   1642 
   1643 	brelse(bp);
   1644 
   1645 	splx(s);
   1646 	return(0);
   1647 }
   1648 
   1649 #endif
   1650