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