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