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