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