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