Home | History | Annotate | Line # | Download | only in dev
fd.c revision 1.70
      1  1.70        pk /*	$NetBSD: fd.c,v 1.70 2000/01/17 16:57:15 pk Exp $	*/
      2   1.1        pk 
      3   1.1        pk /*-
      4  1.64   mycroft  * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.
      5   1.1        pk  * Copyright (c) 1995 Paul Kranenburg.
      6   1.1        pk  * Copyright (c) 1990 The Regents of the University of California.
      7   1.1        pk  * All rights reserved.
      8   1.1        pk  *
      9   1.1        pk  * This code is derived from software contributed to Berkeley by
     10   1.1        pk  * Don Ahn.
     11   1.1        pk  *
     12   1.1        pk  * Redistribution and use in source and binary forms, with or without
     13   1.1        pk  * modification, are permitted provided that the following conditions
     14   1.1        pk  * are met:
     15   1.1        pk  * 1. Redistributions of source code must retain the above copyright
     16   1.1        pk  *    notice, this list of conditions and the following disclaimer.
     17   1.1        pk  * 2. Redistributions in binary form must reproduce the above copyright
     18   1.1        pk  *    notice, this list of conditions and the following disclaimer in the
     19   1.1        pk  *    documentation and/or other materials provided with the distribution.
     20   1.1        pk  * 3. All advertising materials mentioning features or use of this software
     21   1.1        pk  *    must display the following acknowledgement:
     22   1.1        pk  *	This product includes software developed by the University of
     23   1.1        pk  *	California, Berkeley and its contributors.
     24   1.1        pk  * 4. Neither the name of the University nor the names of its contributors
     25   1.1        pk  *    may be used to endorse or promote products derived from this software
     26   1.1        pk  *    without specific prior written permission.
     27   1.1        pk  *
     28   1.1        pk  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     29   1.1        pk  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     30   1.1        pk  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     31   1.1        pk  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     32   1.1        pk  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     33   1.1        pk  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     34   1.1        pk  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     35   1.1        pk  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     36   1.1        pk  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     37   1.1        pk  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     38   1.1        pk  * SUCH DAMAGE.
     39   1.1        pk  *
     40   1.1        pk  *	@(#)fd.c	7.4 (Berkeley) 5/25/91
     41   1.1        pk  */
     42  1.57       mrg 
     43  1.62  jonathan #include "opt_ddb.h"
     44  1.65  jonathan #include "opt_md.h"
     45   1.1        pk 
     46   1.1        pk #include <sys/param.h>
     47   1.1        pk #include <sys/systm.h>
     48   1.1        pk #include <sys/kernel.h>
     49   1.1        pk #include <sys/file.h>
     50   1.1        pk #include <sys/ioctl.h>
     51   1.1        pk #include <sys/device.h>
     52   1.1        pk #include <sys/disklabel.h>
     53   1.1        pk #include <sys/dkstat.h>
     54   1.1        pk #include <sys/disk.h>
     55  1.42        pk #include <sys/fdio.h>
     56   1.1        pk #include <sys/buf.h>
     57  1.42        pk #include <sys/malloc.h>
     58  1.42        pk #include <sys/proc.h>
     59   1.1        pk #include <sys/uio.h>
     60  1.19   thorpej #include <sys/stat.h>
     61   1.1        pk #include <sys/syslog.h>
     62   1.1        pk #include <sys/queue.h>
     63  1.30  christos #include <sys/conf.h>
     64  1.24  christos 
     65  1.24  christos #include <dev/cons.h>
     66  1.56       mrg 
     67  1.56       mrg #include <vm/vm.h>
     68  1.67       mrg 
     69  1.56       mrg #include <uvm/uvm_extern.h>
     70   1.1        pk 
     71   1.1        pk #include <machine/cpu.h>
     72   1.1        pk #include <machine/autoconf.h>
     73  1.30  christos #include <machine/conf.h>
     74  1.30  christos 
     75   1.2        pk #include <sparc/sparc/auxreg.h>
     76   1.1        pk #include <sparc/dev/fdreg.h>
     77   1.2        pk #include <sparc/dev/fdvar.h>
     78   1.1        pk 
     79   1.1        pk #define FDUNIT(dev)	(minor(dev) / 8)
     80   1.1        pk #define FDTYPE(dev)	(minor(dev) % 8)
     81   1.1        pk 
     82  1.42        pk /* XXX misuse a flag to identify format operation */
     83  1.42        pk #define B_FORMAT B_XXX
     84   1.1        pk #define b_cylin b_resid
     85   1.1        pk 
     86   1.2        pk #define FD_DEBUG
     87   1.2        pk #ifdef FD_DEBUG
     88   1.2        pk int	fdc_debug = 0;
     89   1.2        pk #endif
     90   1.2        pk 
     91   1.1        pk enum fdc_state {
     92   1.1        pk 	DEVIDLE = 0,
     93   1.1        pk 	MOTORWAIT,
     94   1.1        pk 	DOSEEK,
     95   1.1        pk 	SEEKWAIT,
     96   1.1        pk 	SEEKTIMEDOUT,
     97   1.1        pk 	SEEKCOMPLETE,
     98   1.1        pk 	DOIO,
     99   1.2        pk 	IOCOMPLETE,
    100   1.1        pk 	IOTIMEDOUT,
    101   1.1        pk 	DORESET,
    102   1.1        pk 	RESETCOMPLETE,
    103   1.1        pk 	RESETTIMEDOUT,
    104   1.1        pk 	DORECAL,
    105   1.1        pk 	RECALWAIT,
    106   1.1        pk 	RECALTIMEDOUT,
    107   1.1        pk 	RECALCOMPLETE,
    108   1.1        pk };
    109   1.1        pk 
    110   1.1        pk /* software state, per controller */
    111   1.1        pk struct fdc_softc {
    112  1.14        pk 	struct device	sc_dev;		/* boilerplate */
    113  1.58        pk 	bus_space_tag_t	sc_bustag;
    114  1.70        pk 
    115   1.1        pk 	struct fd_softc *sc_fd[4];	/* pointers to children */
    116   1.1        pk 	TAILQ_HEAD(drivehead, fd_softc) sc_drives;
    117   1.1        pk 	enum fdc_state	sc_state;
    118   1.2        pk 	int		sc_flags;
    119   1.2        pk #define FDC_82077		0x01
    120   1.2        pk #define FDC_NEEDHEADSETTLE	0x02
    121   1.2        pk #define FDC_EIS			0x04
    122   1.2        pk 	int		sc_errors;		/* number of retries so far */
    123   1.6        pk 	int		sc_overruns;		/* number of DMA overruns */
    124   1.2        pk 	int		sc_cfg;			/* current configuration */
    125   1.2        pk 	struct fdcio	sc_io;
    126  1.70        pk #define sc_handle	sc_io.fdcio_handle
    127   1.2        pk #define sc_reg_msr	sc_io.fdcio_reg_msr
    128   1.2        pk #define sc_reg_fifo	sc_io.fdcio_reg_fifo
    129   1.2        pk #define sc_reg_dor	sc_io.fdcio_reg_dor
    130   1.2        pk #define sc_reg_drs	sc_io.fdcio_reg_msr
    131   1.2        pk #define sc_istate	sc_io.fdcio_istate
    132   1.2        pk #define sc_data		sc_io.fdcio_data
    133   1.2        pk #define sc_tc		sc_io.fdcio_tc
    134   1.2        pk #define sc_nstat	sc_io.fdcio_nstat
    135   1.2        pk #define sc_status	sc_io.fdcio_status
    136   1.3        pk #define sc_intrcnt	sc_io.fdcio_intrcnt
    137   1.1        pk };
    138   1.1        pk 
    139   1.2        pk #ifndef FDC_C_HANDLER
    140   1.2        pk extern	struct fdcio	*fdciop;
    141   1.2        pk #endif
    142   1.2        pk 
    143   1.1        pk /* controller driver configuration */
    144  1.58        pk int	fdcmatch_mainbus __P((struct device *, struct cfdata *, void *));
    145  1.58        pk int	fdcmatch_obio __P((struct device *, struct cfdata *, void *));
    146  1.58        pk void	fdcattach_mainbus __P((struct device *, struct device *, void *));
    147  1.58        pk void	fdcattach_obio __P((struct device *, struct device *, void *));
    148   1.1        pk 
    149  1.69        pk void	fdcattach __P((struct fdc_softc *, int));
    150  1.58        pk 
    151  1.58        pk struct cfattach fdc_mainbus_ca = {
    152  1.58        pk 	sizeof(struct fdc_softc), fdcmatch_mainbus, fdcattach_mainbus
    153  1.58        pk };
    154  1.58        pk struct cfattach fdc_obio_ca = {
    155  1.58        pk 	sizeof(struct fdc_softc), fdcmatch_obio, fdcattach_obio
    156  1.26   thorpej };
    157  1.24  christos 
    158  1.24  christos __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t));
    159  1.24  christos 
    160   1.1        pk /*
    161   1.1        pk  * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
    162   1.1        pk  * we tell them apart.
    163   1.1        pk  */
    164   1.1        pk struct fd_type {
    165   1.1        pk 	int	sectrac;	/* sectors per track */
    166   1.1        pk 	int	heads;		/* number of heads */
    167   1.1        pk 	int	seccyl;		/* sectors per cylinder */
    168   1.1        pk 	int	secsize;	/* size code for sectors */
    169   1.1        pk 	int	datalen;	/* data len when secsize = 0 */
    170   1.1        pk 	int	steprate;	/* step rate and head unload time */
    171   1.1        pk 	int	gap1;		/* gap len between sectors */
    172   1.1        pk 	int	gap2;		/* formatting gap */
    173  1.49        pk 	int	cylinders;	/* total num of cylinders */
    174   1.1        pk 	int	size;		/* size of disk in sectors */
    175   1.1        pk 	int	step;		/* steps per cylinder */
    176   1.1        pk 	int	rate;		/* transfer speed code */
    177  1.42        pk 	int	fillbyte;	/* format fill byte */
    178  1.42        pk 	int	interleave;	/* interleave factor (formatting) */
    179   1.1        pk 	char	*name;
    180   1.1        pk };
    181   1.1        pk 
    182   1.1        pk /* The order of entries in the following table is important -- BEWARE! */
    183   1.1        pk struct fd_type fd_types[] = {
    184  1.42        pk 	{ 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB"    }, /* 1.44MB diskette */
    185  1.42        pk 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB"    }, /* 3.5" 720kB diskette */
    186  1.42        pk 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x"  }, /* 360kB in 720kB drive */
    187  1.53        pk 	{  8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS,0xf6,1, "1.2MB/NEC" } /* 1.2 MB japanese format */
    188   1.1        pk };
    189   1.1        pk 
    190   1.1        pk /* software state, per disk (with up to 4 disks per ctlr) */
    191   1.1        pk struct fd_softc {
    192  1.16   thorpej 	struct device	sc_dv;		/* generic device info */
    193  1.16   thorpej 	struct disk	sc_dk;		/* generic disk info */
    194   1.1        pk 
    195   1.1        pk 	struct fd_type *sc_deftype;	/* default type descriptor */
    196   1.1        pk 	struct fd_type *sc_type;	/* current type descriptor */
    197   1.1        pk 
    198   1.1        pk 	daddr_t	sc_blkno;	/* starting block number */
    199   1.1        pk 	int sc_bcount;		/* byte count left */
    200   1.1        pk 	int sc_skip;		/* bytes already transferred */
    201   1.1        pk 	int sc_nblks;		/* number of blocks currently tranferring */
    202   1.1        pk 	int sc_nbytes;		/* number of bytes currently tranferring */
    203   1.1        pk 
    204   1.1        pk 	int sc_drive;		/* physical unit number */
    205   1.1        pk 	int sc_flags;
    206   1.1        pk #define	FD_OPEN		0x01		/* it's open */
    207   1.1        pk #define	FD_MOTOR	0x02		/* motor should be on */
    208   1.1        pk #define	FD_MOTOR_WAIT	0x04		/* motor coming up */
    209   1.1        pk 	int sc_cylin;		/* where we think the head is */
    210  1.42        pk 	int sc_opts;		/* user-set options */
    211   1.1        pk 
    212  1.20   thorpej 	void	*sc_sdhook;	/* shutdownhook cookie */
    213  1.20   thorpej 
    214   1.1        pk 	TAILQ_ENTRY(fd_softc) sc_drivechain;
    215   1.1        pk 	int sc_ops;		/* I/O ops since last switch */
    216   1.1        pk 	struct buf sc_q;	/* head of buf chain */
    217   1.1        pk };
    218   1.1        pk 
    219   1.1        pk /* floppy driver configuration */
    220  1.44        pk int	fdmatch __P((struct device *, struct cfdata *, void *));
    221   1.1        pk void	fdattach __P((struct device *, struct device *, void *));
    222   1.1        pk 
    223  1.26   thorpej struct cfattach fd_ca = {
    224  1.26   thorpej 	sizeof(struct fd_softc), fdmatch, fdattach
    225  1.26   thorpej };
    226  1.26   thorpej 
    227  1.55   thorpej extern struct cfdriver fd_cd;
    228   1.1        pk 
    229  1.19   thorpej void fdgetdisklabel __P((dev_t));
    230   1.1        pk int fd_get_parms __P((struct fd_softc *));
    231   1.1        pk void fdstrategy __P((struct buf *));
    232   1.1        pk void fdstart __P((struct fd_softc *));
    233  1.37       cgd int fdprint __P((void *, const char *));
    234   1.1        pk 
    235   1.1        pk struct dkdriver fddkdriver = { fdstrategy };
    236   1.1        pk 
    237   1.1        pk struct	fd_type *fd_nvtotype __P((char *, int, int));
    238  1.12        pk void	fd_set_motor __P((struct fdc_softc *fdc));
    239   1.1        pk void	fd_motor_off __P((void *arg));
    240   1.1        pk void	fd_motor_on __P((void *arg));
    241   1.1        pk int	fdcresult __P((struct fdc_softc *fdc));
    242   1.1        pk int	out_fdc __P((struct fdc_softc *fdc, u_char x));
    243   1.1        pk void	fdcstart __P((struct fdc_softc *fdc));
    244   1.1        pk void	fdcstatus __P((struct device *dv, int n, char *s));
    245  1.12        pk void	fdc_reset __P((struct fdc_softc *fdc));
    246   1.1        pk void	fdctimeout __P((void *arg));
    247   1.1        pk void	fdcpseudointr __P((void *arg));
    248   1.2        pk #ifdef FDC_C_HANDLER
    249  1.58        pk int	fdchwintr __P((void *));
    250   1.2        pk #else
    251   1.2        pk void	fdchwintr __P((void));
    252   1.2        pk #endif
    253  1.58        pk int	fdcswintr __P((void *));
    254  1.42        pk int	fdcstate __P((struct fdc_softc *));
    255   1.1        pk void	fdcretry __P((struct fdc_softc *fdc));
    256   1.1        pk void	fdfinish __P((struct fd_softc *fd, struct buf *bp));
    257  1.42        pk int	fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *));
    258  1.50        pk void	fd_do_eject __P((struct fd_softc *));
    259  1.19   thorpej void	fd_mountroot_hook __P((struct device *));
    260  1.70        pk static int fdconf __P((struct fdc_softc *));
    261  1.70        pk static void establish_chip_type __P((
    262  1.70        pk 		struct fdc_softc *,
    263  1.70        pk 		bus_space_tag_t,
    264  1.70        pk 		bus_type_t,
    265  1.70        pk 		bus_addr_t,
    266  1.70        pk 		bus_size_t,
    267  1.70        pk 		bus_space_handle_t));
    268  1.70        pk 
    269   1.1        pk 
    270   1.2        pk #if PIL_FDSOFT == 4
    271   1.1        pk #define IE_FDSOFT	IE_L4
    272   1.2        pk #else
    273   1.2        pk #error 4
    274   1.2        pk #endif
    275   1.1        pk 
    276  1.42        pk #ifdef FDC_C_HANDLER
    277  1.42        pk #if defined(SUN4M)
    278  1.42        pk #define FD_SET_SWINTR do {		\
    279  1.42        pk 	if (CPU_ISSUN4M)		\
    280  1.42        pk 		raise(0, PIL_FDSOFT);	\
    281  1.42        pk 	else				\
    282  1.42        pk 		ienab_bis(IE_L4);	\
    283  1.42        pk } while(0)
    284  1.42        pk #else
    285  1.42        pk #define AUDIO_SET_SWINTR ienab_bis(IE_FDSOFT)
    286  1.42        pk #endif /* defined(SUN4M) */
    287  1.42        pk #endif /* FDC_C_HANDLER */
    288  1.42        pk 
    289  1.23        pk #define OBP_FDNAME	(CPU_ISSUN4M ? "SUNW,fdtwo" : "fd")
    290  1.10        pk 
    291   1.1        pk int
    292  1.58        pk fdcmatch_mainbus(parent, match, aux)
    293   1.1        pk 	struct device *parent;
    294  1.44        pk 	struct cfdata *match;
    295  1.44        pk 	void *aux;
    296   1.1        pk {
    297  1.58        pk 	struct mainbus_attach_args *ma = aux;
    298   1.1        pk 
    299  1.23        pk 	/*
    300  1.58        pk 	 * Floppy controller is on mainbus on sun4c.
    301  1.23        pk 	 */
    302  1.58        pk 	if (!CPU_ISSUN4C)
    303  1.58        pk 		return (0);
    304  1.58        pk 
    305  1.58        pk 	/* sun4c PROMs call the controller "fd" */
    306  1.58        pk 	if (strcmp("fd", ma->ma_name) != 0)
    307  1.23        pk 		return (0);
    308  1.23        pk 
    309  1.60        pk 	return (bus_space_probe(ma->ma_bustag,
    310  1.60        pk 				ma->ma_iospace,
    311  1.60        pk 				ma->ma_paddr,
    312  1.60        pk 				1,	/* probe size */
    313  1.60        pk 				0,	/* offset */
    314  1.60        pk 				0,	/* flags */
    315  1.60        pk 				NULL, NULL));
    316  1.58        pk }
    317  1.58        pk 
    318  1.58        pk int
    319  1.58        pk fdcmatch_obio(parent, match, aux)
    320  1.58        pk 	struct device *parent;
    321  1.58        pk 	struct cfdata *match;
    322  1.58        pk 	void *aux;
    323  1.58        pk {
    324  1.58        pk 	union obio_attach_args *uoba = aux;
    325  1.58        pk 	struct sbus_attach_args *sa;
    326  1.23        pk 
    327  1.23        pk 	/*
    328  1.23        pk 	 * Floppy controller is on obio on sun4m.
    329  1.23        pk 	 */
    330  1.58        pk 	if (uoba->uoba_isobio4 != 0)
    331  1.23        pk 		return (0);
    332  1.23        pk 
    333  1.58        pk 	sa = &uoba->uoba_sbus;
    334  1.58        pk 
    335  1.58        pk 	/* sun4m PROMs call the controller "SUNW,fdtwo" */
    336  1.58        pk 	if (strcmp("SUNW,fdtwo", sa->sa_name) != 0)
    337   1.1        pk 		return (0);
    338  1.23        pk 
    339  1.60        pk 	return (bus_space_probe(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
    340  1.60        pk 				1,	/* probe size */
    341  1.60        pk 				0,	/* offset */
    342  1.60        pk 				0,	/* flags */
    343  1.60        pk 				NULL, NULL));
    344   1.1        pk }
    345   1.1        pk 
    346  1.70        pk static void
    347  1.70        pk establish_chip_type(fdc, tag, type, addr, size, handle)
    348  1.70        pk 	struct fdc_softc	*fdc;
    349  1.70        pk 	bus_space_tag_t		tag;
    350  1.70        pk 	bus_type_t		type;
    351  1.70        pk 	bus_addr_t		addr;
    352  1.70        pk 	bus_size_t		size;
    353  1.70        pk 	bus_space_handle_t	handle;
    354  1.70        pk {
    355  1.70        pk 	u_int8_t v;
    356  1.70        pk 
    357  1.70        pk 	/*
    358  1.70        pk 	 * This hack from Chris Torek: apparently DOR really
    359  1.70        pk 	 * addresses MSR/DRS on a 82072.
    360  1.70        pk 	 * We used to rely on the VERSION command to tell the
    361  1.70        pk 	 * difference (which did not work).
    362  1.70        pk 	 */
    363  1.70        pk 
    364  1.70        pk 	/* First, check the size of the register bank */
    365  1.70        pk 	if (size < 8)
    366  1.70        pk 		/* It isn't a 82077 */
    367  1.70        pk 		return;
    368  1.70        pk 
    369  1.70        pk 	/* Then probe the DOR register offset */
    370  1.70        pk 	if (bus_space_probe(tag, type, addr,
    371  1.70        pk 			    1,			/* probe size */
    372  1.70        pk 			    FDREG77_DOR,	/* offset */
    373  1.70        pk 			    0,			/* flags */
    374  1.70        pk 			    NULL, NULL) == 0) {
    375  1.70        pk 
    376  1.70        pk 		/* It isn't a 82077 */
    377  1.70        pk 		return;
    378  1.70        pk 	}
    379  1.70        pk 
    380  1.70        pk 	v = bus_space_read_1(tag, handle, FDREG77_DOR);
    381  1.70        pk 	if (v == NE7_RQM) {
    382  1.70        pk 		/*
    383  1.70        pk 		 * Value in DOR looks like it's really MSR
    384  1.70        pk 		 */
    385  1.70        pk 		bus_space_write_1(tag, handle, FDREG77_DOR, FDC_250KBPS);
    386  1.70        pk 		v = bus_space_read_1(tag, handle, FDREG77_DOR);
    387  1.70        pk 		if (v == NE7_RQM) {
    388  1.70        pk 			/*
    389  1.70        pk 			 * The value in the DOR didn't stick;
    390  1.70        pk 			 * it isn't a 82077
    391  1.70        pk 			 */
    392  1.70        pk 			return;
    393  1.70        pk 		}
    394  1.70        pk 	}
    395  1.70        pk 
    396  1.70        pk 	fdc->sc_flags |= FDC_82077;
    397  1.70        pk }
    398  1.70        pk 
    399   1.1        pk /*
    400   1.1        pk  * Arguments passed between fdcattach and fdprobe.
    401   1.1        pk  */
    402   1.1        pk struct fdc_attach_args {
    403   1.1        pk 	int fa_drive;
    404   1.1        pk 	struct fd_type *fa_deftype;
    405   1.1        pk };
    406   1.1        pk 
    407   1.1        pk /*
    408   1.1        pk  * Print the location of a disk drive (called just before attaching the
    409   1.1        pk  * the drive).  If `fdc' is not NULL, the drive was found but was not
    410   1.1        pk  * in the system config file; print the drive name as well.
    411   1.1        pk  * Return QUIET (config_find ignores this if the device was configured) to
    412   1.1        pk  * avoid printing `fdN not configured' messages.
    413   1.1        pk  */
    414   1.1        pk int
    415   1.1        pk fdprint(aux, fdc)
    416   1.1        pk 	void *aux;
    417  1.37       cgd 	const char *fdc;
    418   1.1        pk {
    419   1.1        pk 	register struct fdc_attach_args *fa = aux;
    420   1.1        pk 
    421   1.1        pk 	if (!fdc)
    422  1.39  christos 		printf(" drive %d", fa->fa_drive);
    423  1.42        pk 	return (QUIET);
    424   1.1        pk }
    425   1.1        pk 
    426  1.70        pk static int
    427   1.1        pk fdconf(fdc)
    428   1.1        pk 	struct fdc_softc *fdc;
    429   1.1        pk {
    430   1.1        pk 	int	vroom;
    431   1.1        pk 
    432   1.1        pk 	if (out_fdc(fdc, NE7CMD_DUMPREG) || fdcresult(fdc) != 10)
    433  1.70        pk 		return (-1);
    434   1.1        pk 
    435   1.1        pk 	/*
    436   1.1        pk 	 * dumpreg[7] seems to be a motor-off timeout; set it to whatever
    437   1.1        pk 	 * the PROM thinks is appropriate.
    438   1.1        pk 	 */
    439   1.1        pk 	if ((vroom = fdc->sc_status[7]) == 0)
    440   1.1        pk 		vroom = 0x64;
    441   1.1        pk 
    442   1.1        pk 	/* Configure controller to use FIFO and Implied Seek */
    443   1.1        pk 	out_fdc(fdc, NE7CMD_CFG);
    444   1.1        pk 	out_fdc(fdc, vroom);
    445   1.2        pk 	out_fdc(fdc, fdc->sc_cfg);
    446   1.1        pk 	out_fdc(fdc, 0); /* PRETRK */
    447  1.70        pk 	/* No result phase for the NE7CMD_CFG command */
    448  1.70        pk 
    449  1.70        pk 	if ((fdc->sc_flags & FDC_82077) != 0) {
    450  1.70        pk 		/* Lock configuration across soft resets. */
    451  1.70        pk 		out_fdc(fdc, NE7CMD_LOCK | CFG_LOCK);
    452  1.70        pk 		if (fdcresult(fdc) != 1) {
    453  1.70        pk #ifdef DEBUG
    454  1.70        pk 			printf("fdconf: CFGLOCK failed");
    455  1.70        pk #endif
    456  1.70        pk 			return (-1);
    457  1.70        pk 		}
    458  1.70        pk 	}
    459  1.70        pk 
    460  1.70        pk 	return (0);
    461  1.70        pk #if 0
    462  1.70        pk 	if (out_fdc(fdc, NE7CMD_VERSION) == 0 &&
    463  1.70        pk 	    fdcresult(fdc) == 1 && fdc->sc_status[0] == 0x90) {
    464  1.70        pk 		if (fdc_debug)
    465  1.70        pk 			printf("[version cmd]");
    466  1.70        pk 	}
    467  1.70        pk #endif
    468   1.1        pk }
    469   1.1        pk 
    470  1.58        pk 	/*
    471  1.58        pk 	 * Controller and drives are represented by one and the same
    472  1.58        pk 	 * Openprom node, so we can as well check for the floppy boots here.
    473  1.58        pk 	 */
    474  1.58        pk 
    475  1.58        pk void
    476  1.58        pk fdcattach_mainbus(parent, self, aux)
    477  1.58        pk 	struct device *parent, *self;
    478  1.58        pk 	void *aux;
    479  1.58        pk {
    480  1.58        pk 	struct fdc_softc *fdc = (void *)self;
    481  1.58        pk 	struct mainbus_attach_args *ma = aux;
    482  1.58        pk 
    483  1.58        pk 	fdc->sc_bustag = ma->ma_bustag;
    484  1.58        pk 
    485  1.59        pk 	if (ma->ma_promvaddr != 0)
    486  1.70        pk 		fdc->sc_handle = (bus_space_handle_t)ma->ma_promvaddr;
    487  1.59        pk 	else {
    488  1.60        pk 		if (bus_space_map2(
    489  1.59        pk 				ma->ma_bustag,
    490  1.59        pk 				ma->ma_iospace,
    491  1.60        pk 				ma->ma_paddr,
    492  1.59        pk 				ma->ma_size,
    493  1.59        pk 				BUS_SPACE_MAP_LINEAR,
    494  1.59        pk 				0,
    495  1.70        pk 				&fdc->sc_handle) != 0) {
    496  1.59        pk 			printf("%s: cannot map registers\n", self->dv_xname);
    497  1.59        pk 			return;
    498  1.59        pk 		}
    499  1.59        pk 	}
    500  1.58        pk 
    501  1.70        pk 	establish_chip_type(fdc,
    502  1.70        pk 			    ma->ma_bustag,
    503  1.70        pk 			    ma->ma_iospace,
    504  1.70        pk 			    ma->ma_paddr,
    505  1.70        pk 			    ma->ma_size,
    506  1.70        pk 			    fdc->sc_handle);
    507  1.70        pk 
    508  1.69        pk 	fdcattach(fdc, ma->ma_pri);
    509  1.58        pk }
    510  1.58        pk 
    511   1.1        pk void
    512  1.58        pk fdcattach_obio(parent, self, aux)
    513   1.1        pk 	struct device *parent, *self;
    514   1.1        pk 	void *aux;
    515   1.1        pk {
    516   1.1        pk 	struct fdc_softc *fdc = (void *)self;
    517  1.58        pk 	union obio_attach_args *uoba = aux;
    518  1.58        pk 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
    519  1.58        pk 
    520  1.58        pk 	fdc->sc_bustag = sa->sa_bustag;
    521  1.58        pk 
    522  1.63        pk 	if (sa->sa_npromvaddrs != 0)
    523  1.70        pk 		fdc->sc_handle = (bus_space_handle_t)sa->sa_promvaddrs[0];
    524  1.58        pk 	else {
    525  1.58        pk 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
    526  1.58        pk 				 sa->sa_offset,
    527  1.58        pk 				 sa->sa_size,
    528  1.58        pk 				 BUS_SPACE_MAP_LINEAR,
    529  1.58        pk 				 0,
    530  1.70        pk 				 &fdc->sc_handle) != 0) {
    531  1.58        pk 			printf("%s: cannot map control registers\n",
    532  1.58        pk 				self->dv_xname);
    533  1.58        pk 			return;
    534  1.58        pk 		}
    535  1.58        pk 	}
    536  1.58        pk 
    537  1.70        pk 	establish_chip_type(fdc,
    538  1.70        pk 			    sa->sa_bustag,
    539  1.70        pk 			    sa->sa_slot,
    540  1.70        pk 			    sa->sa_offset,
    541  1.70        pk 			    sa->sa_size,
    542  1.70        pk 			    fdc->sc_handle);
    543  1.70        pk 
    544  1.68        pk 	if (sa->sa_nintr != 0)
    545  1.69        pk 		fdcattach(fdc, sa->sa_pri);
    546  1.58        pk }
    547  1.58        pk 
    548  1.58        pk void
    549  1.69        pk fdcattach(fdc, pri)
    550  1.58        pk 	struct fdc_softc *fdc;
    551  1.24  christos 	int pri;
    552  1.58        pk {
    553  1.58        pk 	struct fdc_attach_args fa;
    554   1.8        pk 	char code;
    555   1.1        pk 
    556   1.2        pk 	fdc->sc_state = DEVIDLE;
    557   1.2        pk 	fdc->sc_istate = ISTATE_IDLE;
    558   1.2        pk 	fdc->sc_flags |= FDC_EIS;
    559   1.2        pk 	TAILQ_INIT(&fdc->sc_drives);
    560   1.2        pk 
    561  1.70        pk 	if ((fdc->sc_flags & FDC_82077) != 0) {
    562  1.70        pk 		fdc->sc_reg_msr = FDREG77_MSR;
    563  1.70        pk 		fdc->sc_reg_fifo = FDREG77_FIFO;
    564  1.70        pk 		fdc->sc_reg_dor = FDREG77_DOR;
    565  1.70        pk 		code = '7';
    566  1.70        pk 	} else {
    567  1.70        pk 		fdc->sc_reg_msr = FDREG72_MSR;
    568  1.70        pk 		fdc->sc_reg_fifo = FDREG72_FIFO;
    569  1.70        pk 		fdc->sc_reg_dor = 0;
    570  1.70        pk 		code = '2';
    571  1.70        pk 	}
    572  1.70        pk 
    573  1.70        pk 	printf(" softpri %d: chip 8207%c\n", PIL_FDSOFT, code);
    574  1.70        pk 
    575  1.70        pk 	/*
    576  1.70        pk 	 * Configure controller; enable FIFO, Implied seek, no POLL mode?.
    577  1.70        pk 	 * Note: CFG_EFIFO is active-low, initial threshold value: 8
    578  1.70        pk 	 */
    579  1.70        pk 	fdc->sc_cfg = CFG_EIS|/*CFG_EFIFO|*/CFG_POLL|(8 & CFG_THRHLD_MASK);
    580  1.70        pk 	if (fdconf(fdc) != 0) {
    581  1.70        pk 		printf("%s: no drives attached\n", fdc->sc_dev.dv_xname);
    582  1.70        pk 		return;
    583  1.70        pk 	}
    584  1.70        pk 
    585   1.2        pk #ifdef FDC_C_HANDLER
    586  1.58        pk 	(void)bus_intr_establish(fdc->sc_bustag, pri, 0,
    587  1.58        pk 				 fdchwintr, fdc);
    588   1.2        pk #else
    589   1.2        pk 	fdciop = &fdc->sc_io;
    590  1.58        pk 	(void)bus_intr_establish(fdc->sc_bustag, pri,
    591  1.58        pk 				 BUS_INTR_ESTABLISH_FASTTRAP,
    592  1.58        pk 				 (int (*) __P((void *)))fdchwintr, NULL);
    593   1.2        pk #endif
    594  1.58        pk 	(void)bus_intr_establish(fdc->sc_bustag, PIL_FDSOFT,
    595  1.58        pk 				 BUS_INTR_ESTABLISH_SOFTINTR,
    596  1.58        pk 				 fdcswintr, fdc);
    597   1.1        pk 
    598  1.14        pk 	evcnt_attach(&fdc->sc_dev, "intr", &fdc->sc_intrcnt);
    599   1.1        pk 
    600   1.1        pk 	/* physical limit: four drives per controller. */
    601   1.1        pk 	for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
    602   1.1        pk 		fa.fa_deftype = NULL;		/* unknown */
    603   1.1        pk 	fa.fa_deftype = &fd_types[0];		/* XXX */
    604  1.58        pk 		(void)config_found(&fdc->sc_dev, (void *)&fa, fdprint);
    605   1.1        pk 	}
    606   1.1        pk }
    607   1.1        pk 
    608   1.1        pk int
    609   1.1        pk fdmatch(parent, match, aux)
    610   1.1        pk 	struct device *parent;
    611  1.44        pk 	struct cfdata *match;
    612  1.44        pk 	void *aux;
    613   1.1        pk {
    614   1.1        pk 	struct fdc_softc *fdc = (void *)parent;
    615  1.70        pk 	bus_space_tag_t t = fdc->sc_bustag;
    616  1.70        pk 	bus_space_handle_t h = fdc->sc_handle;
    617   1.1        pk 	struct fdc_attach_args *fa = aux;
    618   1.1        pk 	int drive = fa->fa_drive;
    619  1.33        pk 	int n, ok;
    620   1.1        pk 
    621   1.8        pk 	if (drive > 0)
    622  1.50        pk 		/* XXX - for now, punt on more than one drive */
    623  1.42        pk 		return (0);
    624   1.8        pk 
    625   1.1        pk 	if (fdc->sc_flags & FDC_82077) {
    626   1.1        pk 		/* select drive and turn on motor */
    627  1.70        pk 		bus_space_write_1(t, h, fdc->sc_reg_dor,
    628  1.70        pk 				  drive | FDO_FRST | FDO_MOEN(drive));
    629   1.1        pk 		/* wait for motor to spin up */
    630   1.1        pk 		delay(250000);
    631   1.1        pk 	} else {
    632  1.49        pk 		auxregbisc(AUXIO4C_FDS, 0);
    633   1.1        pk 	}
    634   1.1        pk 	fdc->sc_nstat = 0;
    635   1.1        pk 	out_fdc(fdc, NE7CMD_RECAL);
    636   1.1        pk 	out_fdc(fdc, drive);
    637  1.70        pk 
    638  1.70        pk 	/* Wait for recalibration to complete */
    639  1.33        pk 	for (n = 0; n < 10000; n++) {
    640  1.70        pk 		u_int8_t v;
    641  1.70        pk 
    642  1.33        pk 		delay(1000);
    643  1.70        pk 		v = bus_space_read_1(t, h, fdc->sc_reg_msr);
    644  1.70        pk 		if ((v & (NE7_RQM|NE7_DIO|NE7_CB)) == NE7_RQM) {
    645   1.2        pk 			/* wait a bit longer till device *really* is ready */
    646   1.2        pk 			delay(100000);
    647   1.2        pk 			if (out_fdc(fdc, NE7CMD_SENSEI))
    648   1.2        pk 				break;
    649   1.7        pk 			if (fdcresult(fdc) == 1 && fdc->sc_status[0] == 0x80)
    650   1.2        pk 				/*
    651   1.2        pk 				 * Got `invalid command'; we interpret it
    652   1.2        pk 				 * to mean that the re-calibrate hasn't in
    653   1.2        pk 				 * fact finished yet
    654   1.2        pk 				 */
    655   1.2        pk 				continue;
    656   1.1        pk 			break;
    657   1.1        pk 		}
    658   1.1        pk 	}
    659   1.1        pk 	n = fdc->sc_nstat;
    660   1.1        pk #ifdef FD_DEBUG
    661   1.2        pk 	if (fdc_debug) {
    662   1.1        pk 		int i;
    663  1.39  christos 		printf("fdprobe: %d stati:", n);
    664   1.1        pk 		for (i = 0; i < n; i++)
    665  1.52      fair 			printf(" 0x%x", fdc->sc_status[i]);
    666  1.39  christos 		printf("\n");
    667   1.1        pk 	}
    668   1.1        pk #endif
    669  1.33        pk 	ok = (n == 2 && (fdc->sc_status[0] & 0xf8) == 0x20) ? 1 : 0;
    670  1.33        pk 
    671   1.1        pk 	/* turn off motor */
    672   1.1        pk 	if (fdc->sc_flags & FDC_82077) {
    673  1.50        pk 		/* deselect drive and turn motor off */
    674  1.70        pk 		bus_space_write_1(t, h, fdc->sc_reg_dor, FDO_FRST | FDO_DS);
    675   1.1        pk 	} else {
    676  1.49        pk 		auxregbisc(0, AUXIO4C_FDS);
    677   1.1        pk 	}
    678   1.1        pk 
    679  1.42        pk 	return (ok);
    680   1.1        pk }
    681   1.1        pk 
    682   1.1        pk /*
    683   1.1        pk  * Controller is working, and drive responded.  Attach it.
    684   1.1        pk  */
    685   1.1        pk void
    686   1.1        pk fdattach(parent, self, aux)
    687   1.1        pk 	struct device *parent, *self;
    688   1.1        pk 	void *aux;
    689   1.1        pk {
    690   1.1        pk 	struct fdc_softc *fdc = (void *)parent;
    691   1.1        pk 	struct fd_softc *fd = (void *)self;
    692   1.1        pk 	struct fdc_attach_args *fa = aux;
    693   1.1        pk 	struct fd_type *type = fa->fa_deftype;
    694   1.1        pk 	int drive = fa->fa_drive;
    695   1.1        pk 
    696   1.1        pk 	/* XXX Allow `flags' to override device type? */
    697   1.1        pk 
    698   1.1        pk 	if (type)
    699  1.39  christos 		printf(": %s %d cyl, %d head, %d sec\n", type->name,
    700  1.49        pk 		    type->cylinders, type->heads, type->sectrac);
    701   1.1        pk 	else
    702  1.39  christos 		printf(": density unknown\n");
    703   1.1        pk 
    704   1.1        pk 	fd->sc_cylin = -1;
    705   1.1        pk 	fd->sc_drive = drive;
    706   1.1        pk 	fd->sc_deftype = type;
    707   1.1        pk 	fdc->sc_fd[drive] = fd;
    708  1.16   thorpej 
    709  1.50        pk 	out_fdc(fdc, NE7CMD_SPECIFY);
    710  1.50        pk 	out_fdc(fdc, type->steprate);
    711  1.50        pk 	out_fdc(fdc, 6 | NE7_SPECIFY_NODMA);
    712  1.50        pk 
    713  1.16   thorpej 	/*
    714  1.16   thorpej 	 * Initialize and attach the disk structure.
    715  1.16   thorpej 	 */
    716  1.16   thorpej 	fd->sc_dk.dk_name = fd->sc_dv.dv_xname;
    717   1.1        pk 	fd->sc_dk.dk_driver = &fddkdriver;
    718  1.16   thorpej 	disk_attach(&fd->sc_dk);
    719  1.13        pk 
    720  1.19   thorpej 	/*
    721  1.19   thorpej 	 * Establish a mountroot_hook anyway in case we booted
    722  1.19   thorpej 	 * with RB_ASKNAME and get selected as the boot device.
    723  1.19   thorpej 	 */
    724  1.47   thorpej 	mountroothook_establish(fd_mountroot_hook, &fd->sc_dv);
    725  1.20   thorpej 
    726  1.20   thorpej 	/* Make sure the drive motor gets turned off at shutdown time. */
    727  1.20   thorpej 	fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd);
    728  1.19   thorpej 
    729   1.1        pk 	/* XXX Need to do some more fiddling with sc_dk. */
    730  1.16   thorpej 	dk_establish(&fd->sc_dk, &fd->sc_dv);
    731   1.1        pk }
    732   1.1        pk 
    733  1.24  christos __inline struct fd_type *
    734   1.1        pk fd_dev_to_type(fd, dev)
    735   1.1        pk 	struct fd_softc *fd;
    736   1.1        pk 	dev_t dev;
    737   1.1        pk {
    738   1.1        pk 	int type = FDTYPE(dev);
    739   1.1        pk 
    740   1.1        pk 	if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
    741  1.42        pk 		return (NULL);
    742  1.42        pk 	return (type ? &fd_types[type - 1] : fd->sc_deftype);
    743   1.1        pk }
    744   1.1        pk 
    745   1.1        pk void
    746   1.1        pk fdstrategy(bp)
    747   1.1        pk 	register struct buf *bp;	/* IO operation to perform */
    748   1.1        pk {
    749   1.1        pk 	struct fd_softc *fd;
    750   1.1        pk 	int unit = FDUNIT(bp->b_dev);
    751   1.1        pk 	int sz;
    752   1.1        pk  	int s;
    753   1.1        pk 
    754   1.1        pk 	/* Valid unit, controller, and request? */
    755  1.26   thorpej 	if (unit >= fd_cd.cd_ndevs ||
    756  1.26   thorpej 	    (fd = fd_cd.cd_devs[unit]) == 0 ||
    757   1.1        pk 	    bp->b_blkno < 0 ||
    758  1.53        pk 	    (((bp->b_bcount % FD_BSIZE(fd)) != 0 ||
    759  1.53        pk 	      (bp->b_blkno * DEV_BSIZE) % FD_BSIZE(fd) != 0) &&
    760  1.43        pk 	     (bp->b_flags & B_FORMAT) == 0)) {
    761   1.1        pk 		bp->b_error = EINVAL;
    762   1.1        pk 		goto bad;
    763   1.1        pk 	}
    764   1.1        pk 
    765   1.1        pk 	/* If it's a null transfer, return immediately. */
    766   1.1        pk 	if (bp->b_bcount == 0)
    767   1.1        pk 		goto done;
    768   1.1        pk 
    769  1.53        pk 	sz = howmany(bp->b_bcount, DEV_BSIZE);
    770   1.1        pk 
    771  1.53        pk 	if (bp->b_blkno + sz > (fd->sc_type->size * DEV_BSIZE) / FD_BSIZE(fd)) {
    772  1.53        pk 		sz = (fd->sc_type->size * DEV_BSIZE) / FD_BSIZE(fd)
    773  1.53        pk 		     - bp->b_blkno;
    774   1.1        pk 		if (sz == 0) {
    775   1.1        pk 			/* If exactly at end of disk, return EOF. */
    776   1.1        pk 			bp->b_resid = bp->b_bcount;
    777   1.1        pk 			goto done;
    778   1.1        pk 		}
    779   1.1        pk 		if (sz < 0) {
    780   1.1        pk 			/* If past end of disk, return EINVAL. */
    781   1.1        pk 			bp->b_error = EINVAL;
    782   1.1        pk 			goto bad;
    783   1.1        pk 		}
    784   1.1        pk 		/* Otherwise, truncate request. */
    785   1.1        pk 		bp->b_bcount = sz << DEV_BSHIFT;
    786   1.1        pk 	}
    787   1.1        pk 
    788  1.53        pk  	bp->b_cylin = (bp->b_blkno * DEV_BSIZE) /
    789  1.53        pk 		      (FD_BSIZE(fd) * fd->sc_type->seccyl);
    790   1.1        pk 
    791   1.1        pk #ifdef FD_DEBUG
    792   1.2        pk 	if (fdc_debug > 1)
    793  1.39  christos 	    printf("fdstrategy: b_blkno %d b_bcount %ld blkno %d cylin %ld\n",
    794   1.2        pk 		    bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylin);
    795   1.1        pk #endif
    796   1.1        pk 
    797   1.1        pk 	/* Queue transfer on drive, activate drive and controller if idle. */
    798   1.1        pk 	s = splbio();
    799   1.1        pk 	disksort(&fd->sc_q, bp);
    800   1.1        pk 	untimeout(fd_motor_off, fd); /* a good idea */
    801   1.1        pk 	if (!fd->sc_q.b_active)
    802   1.1        pk 		fdstart(fd);
    803   1.1        pk #ifdef DIAGNOSTIC
    804   1.1        pk 	else {
    805  1.16   thorpej 		struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent;
    806   1.1        pk 		if (fdc->sc_state == DEVIDLE) {
    807  1.39  christos 			printf("fdstrategy: controller inactive\n");
    808   1.1        pk 			fdcstart(fdc);
    809   1.1        pk 		}
    810   1.1        pk 	}
    811   1.1        pk #endif
    812   1.1        pk 	splx(s);
    813   1.1        pk 	return;
    814   1.1        pk 
    815   1.1        pk bad:
    816   1.1        pk 	bp->b_flags |= B_ERROR;
    817   1.1        pk done:
    818   1.1        pk 	/* Toss transfer; we're done early. */
    819   1.1        pk 	biodone(bp);
    820   1.1        pk }
    821   1.1        pk 
    822   1.1        pk void
    823   1.1        pk fdstart(fd)
    824   1.1        pk 	struct fd_softc *fd;
    825   1.1        pk {
    826  1.16   thorpej 	struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent;
    827   1.1        pk 	int active = fdc->sc_drives.tqh_first != 0;
    828   1.1        pk 
    829   1.1        pk 	/* Link into controller queue. */
    830   1.1        pk 	fd->sc_q.b_active = 1;
    831   1.1        pk 	TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
    832   1.1        pk 
    833   1.1        pk 	/* If controller not already active, start it. */
    834   1.1        pk 	if (!active)
    835   1.1        pk 		fdcstart(fdc);
    836   1.1        pk }
    837   1.1        pk 
    838   1.1        pk void
    839   1.1        pk fdfinish(fd, bp)
    840   1.1        pk 	struct fd_softc *fd;
    841   1.1        pk 	struct buf *bp;
    842   1.1        pk {
    843  1.16   thorpej 	struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent;
    844   1.1        pk 
    845   1.1        pk 	/*
    846   1.1        pk 	 * Move this drive to the end of the queue to give others a `fair'
    847   1.1        pk 	 * chance.  We only force a switch if N operations are completed while
    848   1.1        pk 	 * another drive is waiting to be serviced, since there is a long motor
    849   1.1        pk 	 * startup delay whenever we switch.
    850   1.1        pk 	 */
    851   1.1        pk 	if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
    852   1.1        pk 		fd->sc_ops = 0;
    853   1.1        pk 		TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
    854   1.1        pk 		if (bp->b_actf) {
    855   1.1        pk 			TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
    856   1.1        pk 		} else
    857   1.1        pk 			fd->sc_q.b_active = 0;
    858   1.1        pk 	}
    859   1.1        pk 	bp->b_resid = fd->sc_bcount;
    860   1.1        pk 	fd->sc_skip = 0;
    861   1.1        pk 	fd->sc_q.b_actf = bp->b_actf;
    862  1.16   thorpej 
    863   1.1        pk 	biodone(bp);
    864   1.1        pk 	/* turn off motor 5s from now */
    865   1.1        pk 	timeout(fd_motor_off, fd, 5 * hz);
    866   1.1        pk 	fdc->sc_state = DEVIDLE;
    867   1.1        pk }
    868   1.1        pk 
    869   1.1        pk void
    870  1.12        pk fdc_reset(fdc)
    871  1.12        pk 	struct fdc_softc *fdc;
    872  1.12        pk {
    873  1.70        pk 	bus_space_tag_t t = fdc->sc_bustag;
    874  1.70        pk 	bus_space_handle_t h = fdc->sc_handle;
    875  1.70        pk 
    876  1.12        pk 	if (fdc->sc_flags & FDC_82077) {
    877  1.70        pk 		bus_space_write_1(t, h, fdc->sc_reg_dor,
    878  1.70        pk 				  FDO_FDMAEN | FDO_MOEN(0));
    879  1.12        pk 	}
    880  1.12        pk 
    881  1.70        pk 	bus_space_write_1(t, h, fdc->sc_reg_drs, DRS_RESET);
    882  1.12        pk 	delay(10);
    883  1.70        pk 	bus_space_write_1(t, h, fdc->sc_reg_drs, 0);
    884  1.50        pk 
    885  1.50        pk 	if (fdc->sc_flags & FDC_82077) {
    886  1.70        pk 		bus_space_write_1(t, h, fdc->sc_reg_dor,
    887  1.70        pk 				  FDO_FRST | FDO_FDMAEN | FDO_DS);
    888  1.50        pk 	}
    889  1.12        pk #ifdef FD_DEBUG
    890  1.12        pk 	if (fdc_debug)
    891  1.39  christos 		printf("fdc reset\n");
    892  1.12        pk #endif
    893  1.12        pk }
    894  1.12        pk 
    895  1.12        pk void
    896  1.12        pk fd_set_motor(fdc)
    897   1.1        pk 	struct fdc_softc *fdc;
    898   1.1        pk {
    899   1.1        pk 	struct fd_softc *fd;
    900   1.1        pk 	u_char status;
    901   1.1        pk 	int n;
    902   1.1        pk 
    903   1.1        pk 	if (fdc->sc_flags & FDC_82077) {
    904  1.12        pk 		status = FDO_FRST | FDO_FDMAEN;
    905  1.24  christos 		if ((fd = fdc->sc_drives.tqh_first) != NULL)
    906  1.12        pk 			status |= fd->sc_drive;
    907  1.12        pk 
    908   1.1        pk 		for (n = 0; n < 4; n++)
    909   1.1        pk 			if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
    910   1.1        pk 				status |= FDO_MOEN(n);
    911  1.70        pk 		bus_space_write_1(fdc->sc_bustag, fdc->sc_handle,
    912  1.70        pk 				  fdc->sc_reg_dor, status);
    913   1.1        pk 	} else {
    914   1.1        pk 		int on = 0;
    915   1.1        pk 
    916   1.1        pk 		for (n = 0; n < 4; n++)
    917   1.1        pk 			if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
    918   1.1        pk 				on = 1;
    919   1.1        pk 		if (on) {
    920  1.49        pk 			auxregbisc(AUXIO4C_FDS, 0);
    921   1.1        pk 		} else {
    922  1.49        pk 			auxregbisc(0, AUXIO4C_FDS);
    923   1.1        pk 		}
    924   1.1        pk 	}
    925   1.1        pk }
    926   1.1        pk 
    927   1.1        pk void
    928   1.1        pk fd_motor_off(arg)
    929   1.1        pk 	void *arg;
    930   1.1        pk {
    931   1.1        pk 	struct fd_softc *fd = arg;
    932   1.1        pk 	int s;
    933   1.1        pk 
    934   1.1        pk 	s = splbio();
    935   1.1        pk 	fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
    936  1.16   thorpej 	fd_set_motor((struct fdc_softc *)fd->sc_dv.dv_parent);
    937   1.1        pk 	splx(s);
    938   1.1        pk }
    939   1.1        pk 
    940   1.1        pk void
    941   1.1        pk fd_motor_on(arg)
    942   1.1        pk 	void *arg;
    943   1.1        pk {
    944   1.1        pk 	struct fd_softc *fd = arg;
    945  1.16   thorpej 	struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent;
    946   1.1        pk 	int s;
    947   1.1        pk 
    948   1.1        pk 	s = splbio();
    949   1.1        pk 	fd->sc_flags &= ~FD_MOTOR_WAIT;
    950   1.1        pk 	if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
    951  1.42        pk 		(void) fdcstate(fdc);
    952   1.1        pk 	splx(s);
    953   1.1        pk }
    954   1.1        pk 
    955   1.1        pk int
    956   1.1        pk fdcresult(fdc)
    957   1.1        pk 	struct fdc_softc *fdc;
    958   1.1        pk {
    959  1.70        pk 	bus_space_tag_t t = fdc->sc_bustag;
    960  1.70        pk 	bus_space_handle_t h = fdc->sc_handle;
    961   1.1        pk 	int j = 100000,
    962   1.1        pk 	    n = 0;
    963   1.1        pk 
    964   1.1        pk 	for (; j; j--) {
    965  1.70        pk 		u_int8_t v = bus_space_read_1(t, h, fdc->sc_reg_msr);
    966  1.70        pk 		v &= (NE7_DIO | NE7_RQM | NE7_CB);
    967  1.70        pk 		if (v == NE7_RQM)
    968   1.1        pk 			return (fdc->sc_nstat = n);
    969  1.70        pk 		if (v == (NE7_DIO | NE7_RQM | NE7_CB)) {
    970   1.1        pk 			if (n >= sizeof(fdc->sc_status)) {
    971   1.1        pk 				log(LOG_ERR, "fdcresult: overrun\n");
    972  1.42        pk 				return (-1);
    973   1.1        pk 			}
    974  1.70        pk 			fdc->sc_status[n++] =
    975  1.70        pk 				bus_space_read_1(t, h, fdc->sc_reg_fifo);
    976  1.41        pk 		} else
    977  1.41        pk 			delay(10);
    978   1.1        pk 	}
    979   1.1        pk 	log(LOG_ERR, "fdcresult: timeout\n");
    980   1.1        pk 	return (fdc->sc_nstat = -1);
    981   1.1        pk }
    982   1.1        pk 
    983   1.1        pk int
    984   1.1        pk out_fdc(fdc, x)
    985   1.1        pk 	struct fdc_softc *fdc;
    986  1.70        pk 	u_int8_t x;
    987   1.1        pk {
    988  1.70        pk 	bus_space_tag_t t = fdc->sc_bustag;
    989  1.70        pk 	bus_space_handle_t h = fdc->sc_handle;
    990  1.70        pk 	int i;
    991  1.70        pk 
    992  1.70        pk 	for (i = 100000; i-- > 0;) {
    993  1.70        pk 		u_int8_t v = bus_space_read_1(t, h, fdc->sc_reg_msr);
    994  1.70        pk 		if ((v & (NE7_DIO|NE7_RQM)) == NE7_RQM)
    995  1.70        pk 			break;
    996  1.41        pk 		delay(1);
    997  1.70        pk 	}
    998   1.1        pk 	if (i <= 0)
    999  1.42        pk 		return (-1);
   1000   1.1        pk 
   1001  1.70        pk 	bus_space_write_1(t, h, fdc->sc_reg_fifo, x);
   1002  1.42        pk 	return (0);
   1003   1.1        pk }
   1004   1.1        pk 
   1005   1.1        pk int
   1006  1.24  christos fdopen(dev, flags, fmt, p)
   1007   1.1        pk 	dev_t dev;
   1008  1.19   thorpej 	int flags, fmt;
   1009  1.19   thorpej 	struct proc *p;
   1010   1.1        pk {
   1011  1.19   thorpej  	int unit, pmask;
   1012   1.1        pk 	struct fd_softc *fd;
   1013   1.1        pk 	struct fd_type *type;
   1014   1.1        pk 
   1015   1.1        pk 	unit = FDUNIT(dev);
   1016  1.26   thorpej 	if (unit >= fd_cd.cd_ndevs)
   1017  1.42        pk 		return (ENXIO);
   1018  1.26   thorpej 	fd = fd_cd.cd_devs[unit];
   1019   1.1        pk 	if (fd == 0)
   1020  1.42        pk 		return (ENXIO);
   1021   1.1        pk 	type = fd_dev_to_type(fd, dev);
   1022   1.1        pk 	if (type == NULL)
   1023  1.42        pk 		return (ENXIO);
   1024   1.1        pk 
   1025   1.1        pk 	if ((fd->sc_flags & FD_OPEN) != 0 &&
   1026   1.1        pk 	    fd->sc_type != type)
   1027  1.42        pk 		return (EBUSY);
   1028   1.1        pk 
   1029   1.1        pk 	fd->sc_type = type;
   1030   1.1        pk 	fd->sc_cylin = -1;
   1031   1.1        pk 	fd->sc_flags |= FD_OPEN;
   1032   1.1        pk 
   1033  1.19   thorpej 	/*
   1034  1.19   thorpej 	 * Only update the disklabel if we're not open anywhere else.
   1035  1.19   thorpej 	 */
   1036  1.19   thorpej 	if (fd->sc_dk.dk_openmask == 0)
   1037  1.19   thorpej 		fdgetdisklabel(dev);
   1038  1.19   thorpej 
   1039  1.19   thorpej 	pmask = (1 << DISKPART(dev));
   1040  1.19   thorpej 
   1041  1.19   thorpej 	switch (fmt) {
   1042  1.19   thorpej 	case S_IFCHR:
   1043  1.19   thorpej 		fd->sc_dk.dk_copenmask |= pmask;
   1044  1.19   thorpej 		break;
   1045  1.19   thorpej 
   1046  1.19   thorpej 	case S_IFBLK:
   1047  1.19   thorpej 		fd->sc_dk.dk_bopenmask |= pmask;
   1048  1.19   thorpej 		break;
   1049  1.19   thorpej 	}
   1050  1.19   thorpej 	fd->sc_dk.dk_openmask =
   1051  1.19   thorpej 	    fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask;
   1052  1.19   thorpej 
   1053  1.42        pk 	return (0);
   1054   1.1        pk }
   1055   1.1        pk 
   1056   1.1        pk int
   1057  1.19   thorpej fdclose(dev, flags, fmt, p)
   1058   1.1        pk 	dev_t dev;
   1059  1.19   thorpej 	int flags, fmt;
   1060  1.19   thorpej 	struct proc *p;
   1061   1.1        pk {
   1062  1.26   thorpej 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1063  1.19   thorpej 	int pmask = (1 << DISKPART(dev));
   1064   1.1        pk 
   1065   1.1        pk 	fd->sc_flags &= ~FD_OPEN;
   1066  1.42        pk 	fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT);
   1067  1.19   thorpej 
   1068  1.19   thorpej 	switch (fmt) {
   1069  1.19   thorpej 	case S_IFCHR:
   1070  1.19   thorpej 		fd->sc_dk.dk_copenmask &= ~pmask;
   1071  1.19   thorpej 		break;
   1072  1.19   thorpej 
   1073  1.19   thorpej 	case S_IFBLK:
   1074  1.19   thorpej 		fd->sc_dk.dk_bopenmask &= ~pmask;
   1075  1.19   thorpej 		break;
   1076  1.19   thorpej 	}
   1077  1.29        pk 	fd->sc_dk.dk_openmask =
   1078  1.19   thorpej 	    fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask;
   1079  1.19   thorpej 
   1080  1.42        pk 	return (0);
   1081   1.9        pk }
   1082   1.9        pk 
   1083   1.9        pk int
   1084  1.24  christos fdread(dev, uio, flag)
   1085   1.9        pk         dev_t dev;
   1086   1.9        pk         struct uio *uio;
   1087  1.24  christos 	int flag;
   1088   1.9        pk {
   1089   1.9        pk 
   1090   1.9        pk         return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
   1091   1.9        pk }
   1092   1.9        pk 
   1093   1.9        pk int
   1094  1.24  christos fdwrite(dev, uio, flag)
   1095   1.9        pk         dev_t dev;
   1096   1.9        pk         struct uio *uio;
   1097  1.24  christos 	int flag;
   1098   1.9        pk {
   1099   1.9        pk 
   1100   1.9        pk         return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
   1101   1.1        pk }
   1102   1.1        pk 
   1103   1.1        pk void
   1104   1.1        pk fdcstart(fdc)
   1105   1.1        pk 	struct fdc_softc *fdc;
   1106   1.1        pk {
   1107   1.1        pk 
   1108   1.1        pk #ifdef DIAGNOSTIC
   1109   1.1        pk 	/* only got here if controller's drive queue was inactive; should
   1110   1.1        pk 	   be in idle state */
   1111   1.1        pk 	if (fdc->sc_state != DEVIDLE) {
   1112  1.39  christos 		printf("fdcstart: not idle\n");
   1113   1.1        pk 		return;
   1114   1.1        pk 	}
   1115   1.1        pk #endif
   1116  1.42        pk 	(void) fdcstate(fdc);
   1117   1.1        pk }
   1118   1.1        pk 
   1119   1.1        pk void
   1120   1.1        pk fdcstatus(dv, n, s)
   1121   1.1        pk 	struct device *dv;
   1122   1.1        pk 	int n;
   1123   1.1        pk 	char *s;
   1124   1.1        pk {
   1125   1.1        pk 	struct fdc_softc *fdc = (void *)dv->dv_parent;
   1126  1.40   thorpej 	char bits[64];
   1127   1.1        pk #if 0
   1128   1.1        pk 	/*
   1129   1.1        pk 	 * A 82072 seems to return <invalid command> on
   1130   1.1        pk 	 * gratuitous Sense Interrupt commands.
   1131   1.1        pk 	 */
   1132   1.1        pk 	if (n == 0 && (fdc->sc_flags & FDC_82077)) {
   1133   1.1        pk 		out_fdc(fdc, NE7CMD_SENSEI);
   1134   1.1        pk 		(void) fdcresult(fdc);
   1135   1.1        pk 		n = 2;
   1136   1.1        pk 	}
   1137   1.1        pk #endif
   1138   1.1        pk 
   1139   1.1        pk 	/* Just print last status */
   1140   1.1        pk 	n = fdc->sc_nstat;
   1141   1.1        pk 
   1142  1.39  christos 	printf("%s: %s: state %d", dv->dv_xname, s, fdc->sc_state);
   1143   1.1        pk 
   1144   1.1        pk 	switch (n) {
   1145   1.1        pk 	case 0:
   1146  1.39  christos 		printf("\n");
   1147   1.1        pk 		break;
   1148   1.1        pk 	case 2:
   1149  1.40   thorpej 		printf(" (st0 %s cyl %d)\n",
   1150  1.40   thorpej 		    bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS,
   1151  1.40   thorpej 		    bits, sizeof(bits)), fdc->sc_status[1]);
   1152   1.1        pk 		break;
   1153   1.1        pk 	case 7:
   1154  1.40   thorpej 		printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
   1155  1.40   thorpej 		    NE7_ST0BITS, bits, sizeof(bits)));
   1156  1.40   thorpej 		printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
   1157  1.40   thorpej 		    NE7_ST1BITS, bits, sizeof(bits)));
   1158  1.40   thorpej 		printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
   1159  1.40   thorpej 		    NE7_ST2BITS, bits, sizeof(bits)));
   1160  1.40   thorpej 		printf(" cyl %d head %d sec %d)\n",
   1161   1.1        pk 		    fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
   1162   1.1        pk 		break;
   1163   1.1        pk #ifdef DIAGNOSTIC
   1164   1.1        pk 	default:
   1165  1.39  christos 		printf(" fdcstatus: weird size: %d\n", n);
   1166   1.1        pk 		break;
   1167   1.1        pk #endif
   1168   1.1        pk 	}
   1169   1.1        pk }
   1170   1.1        pk 
   1171   1.1        pk void
   1172   1.1        pk fdctimeout(arg)
   1173   1.1        pk 	void *arg;
   1174   1.1        pk {
   1175   1.1        pk 	struct fdc_softc *fdc = arg;
   1176   1.1        pk 	struct fd_softc *fd = fdc->sc_drives.tqh_first;
   1177   1.1        pk 	int s;
   1178   1.1        pk 
   1179   1.1        pk 	s = splbio();
   1180  1.16   thorpej 	fdcstatus(&fd->sc_dv, 0, "timeout");
   1181   1.1        pk 
   1182   1.1        pk 	if (fd->sc_q.b_actf)
   1183   1.1        pk 		fdc->sc_state++;
   1184   1.1        pk 	else
   1185   1.1        pk 		fdc->sc_state = DEVIDLE;
   1186   1.1        pk 
   1187  1.42        pk 	(void) fdcstate(fdc);
   1188   1.1        pk 	splx(s);
   1189   1.1        pk }
   1190   1.1        pk 
   1191   1.2        pk void
   1192   1.2        pk fdcpseudointr(arg)
   1193   1.2        pk 	void *arg;
   1194   1.2        pk {
   1195   1.2        pk 	struct fdc_softc *fdc = arg;
   1196   1.2        pk 	int s;
   1197   1.2        pk 
   1198   1.2        pk 	/* Just ensure it has the right spl. */
   1199   1.2        pk 	s = splbio();
   1200  1.42        pk 	(void) fdcstate(fdc);
   1201   1.2        pk 	splx(s);
   1202   1.2        pk }
   1203   1.2        pk 
   1204   1.2        pk 
   1205   1.2        pk #ifdef FDC_C_HANDLER
   1206   1.1        pk /*
   1207   1.1        pk  * hardware interrupt entry point: must be converted to `fast'
   1208   1.1        pk  * (in-window) handler.
   1209   1.1        pk  */
   1210   1.1        pk int
   1211  1.58        pk fdchwintr(arg)
   1212  1.58        pk 	void *arg;
   1213   1.1        pk {
   1214  1.58        pk 	struct fdc_softc *fdc = arg;
   1215  1.70        pk 	bus_space_tag_t t = fdc->sc_bustag;
   1216  1.70        pk 	bus_space_handle_t h = fdc->sc_handle;
   1217   1.1        pk 
   1218   1.2        pk 	switch (fdc->sc_istate) {
   1219  1.42        pk 	case ISTATE_IDLE:
   1220  1.42        pk 		return (0);
   1221   1.2        pk 	case ISTATE_SENSEI:
   1222   1.1        pk 		out_fdc(fdc, NE7CMD_SENSEI);
   1223   1.1        pk 		fdcresult(fdc);
   1224   1.2        pk 		fdc->sc_istate = ISTATE_IDLE;
   1225  1.42        pk 		FD_SET_SWINTR;
   1226  1.42        pk 		return (1);
   1227   1.2        pk 	case ISTATE_SPURIOUS:
   1228   1.1        pk 		fdcresult(fdc);
   1229   1.2        pk 		fdc->sc_istate = ISTATE_SPURIOUS;
   1230  1.39  christos 		printf("fdc: stray hard interrupt... ");
   1231  1.42        pk 		FD_SET_SWINTR;
   1232  1.42        pk 		return (1);
   1233   1.2        pk 	case ISTATE_DMA:
   1234   1.2        pk 		break;
   1235   1.2        pk 	default:
   1236  1.39  christos 		printf("fdc: goofed ...\n");
   1237  1.42        pk 		return (1);
   1238   1.1        pk 	}
   1239   1.1        pk 
   1240   1.1        pk 	for (;;) {
   1241  1.70        pk 		u_int8_t msr;
   1242   1.1        pk 
   1243  1.70        pk 		msr = bus_space_read_1(t, h, fdc->sc_reg_msr);
   1244   1.1        pk 
   1245   1.1        pk 		if ((msr & NE7_RQM) == 0)
   1246   1.1        pk 			break;
   1247   1.1        pk 
   1248   1.1        pk 		if ((msr & NE7_NDM) == 0) {
   1249   1.1        pk 			fdcresult(fdc);
   1250   1.2        pk 			fdc->sc_istate = ISTATE_IDLE;
   1251   1.1        pk 			ienab_bis(IE_FDSOFT);
   1252  1.39  christos 			printf("fdc: overrun: tc = %d\n", fdc->sc_tc);
   1253   1.1        pk 			break;
   1254   1.1        pk 		}
   1255   1.1        pk 
   1256   1.1        pk 		if (msr & NE7_DIO) {
   1257  1.70        pk 			*fdc->sc_data++ =
   1258  1.70        pk 				bus_space_read_1(t, h, fdc->sc_reg_fifo);
   1259   1.1        pk 		} else {
   1260  1.70        pk 			bus_space_write_1(t, h, fdc->sc_reg_fifo,
   1261  1.70        pk 					  *fdc->sc_data);
   1262  1.70        pk 			fdc->sc_data++;
   1263   1.1        pk 		}
   1264   1.1        pk 		if (--fdc->sc_tc == 0) {
   1265  1.50        pk 			fdc->sc_istate = ISTATE_DONE;
   1266  1.49        pk 			FTC_FLIP;
   1267   1.1        pk 			fdcresult(fdc);
   1268  1.42        pk 			FD_SET_SWINTR;
   1269   1.1        pk 			break;
   1270   1.1        pk 		}
   1271   1.1        pk 	}
   1272  1.42        pk 	return (1);
   1273   1.1        pk }
   1274   1.2        pk #endif
   1275   1.1        pk 
   1276   1.1        pk int
   1277  1.58        pk fdcswintr(arg)
   1278  1.58        pk 	void *arg;
   1279   1.1        pk {
   1280  1.58        pk 	struct fdc_softc *fdc = arg;
   1281  1.42        pk 	int s;
   1282  1.42        pk 
   1283  1.42        pk 	if (fdc->sc_istate != ISTATE_DONE)
   1284  1.42        pk 		return (0);
   1285  1.42        pk 
   1286  1.42        pk 	fdc->sc_istate = ISTATE_IDLE;
   1287  1.42        pk 	s = splbio();
   1288  1.42        pk 	fdcstate(fdc);
   1289  1.42        pk 	splx(s);
   1290  1.42        pk 	return (1);
   1291  1.42        pk }
   1292  1.42        pk 
   1293  1.42        pk int
   1294  1.42        pk fdcstate(fdc)
   1295  1.42        pk 	struct fdc_softc *fdc;
   1296  1.42        pk {
   1297   1.1        pk #define	st0	fdc->sc_status[0]
   1298   1.1        pk #define	st1	fdc->sc_status[1]
   1299   1.1        pk #define	cyl	fdc->sc_status[1]
   1300   1.2        pk #define OUT_FDC(fdc, c, s) \
   1301   1.2        pk     do { if (out_fdc(fdc, (c))) { (fdc)->sc_state = (s); goto loop; } } while(0)
   1302   1.2        pk 
   1303   1.1        pk 	struct fd_softc *fd;
   1304   1.1        pk 	struct buf *bp;
   1305  1.24  christos 	int read, head, sec, nblks;
   1306   1.1        pk 	struct fd_type *type;
   1307  1.43        pk 	struct ne7_fd_formb *finfo = NULL;
   1308   1.1        pk 
   1309  1.12        pk 
   1310   1.2        pk 	if (fdc->sc_istate != ISTATE_IDLE) {
   1311   1.2        pk 		/* Trouble... */
   1312  1.39  christos 		printf("fdc: spurious interrupt: state %d, istate=%d\n",
   1313  1.12        pk 			fdc->sc_state, fdc->sc_istate);
   1314   1.2        pk 		fdc->sc_istate = ISTATE_IDLE;
   1315  1.12        pk 		if (fdc->sc_state == RESETCOMPLETE ||
   1316  1.12        pk 		    fdc->sc_state == RESETTIMEDOUT) {
   1317  1.12        pk 			panic("fdcintr: spurious interrupt can't be cleared");
   1318  1.12        pk 		}
   1319   1.2        pk 		goto doreset;
   1320   1.2        pk 	}
   1321   1.2        pk 
   1322  1.12        pk loop:
   1323   1.1        pk 	/* Is there a drive for the controller to do a transfer with? */
   1324   1.1        pk 	fd = fdc->sc_drives.tqh_first;
   1325   1.1        pk 	if (fd == NULL) {
   1326   1.1        pk 		fdc->sc_state = DEVIDLE;
   1327  1.42        pk  		return (0);
   1328   1.1        pk 	}
   1329   1.1        pk 
   1330   1.1        pk 	/* Is there a transfer to this drive?  If not, deactivate drive. */
   1331   1.1        pk 	bp = fd->sc_q.b_actf;
   1332   1.1        pk 	if (bp == NULL) {
   1333   1.1        pk 		fd->sc_ops = 0;
   1334   1.1        pk 		TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
   1335   1.1        pk 		fd->sc_q.b_active = 0;
   1336   1.1        pk 		goto loop;
   1337   1.1        pk 	}
   1338   1.1        pk 
   1339  1.43        pk 	if (bp->b_flags & B_FORMAT)
   1340  1.43        pk 		finfo = (struct ne7_fd_formb *)bp->b_data;
   1341  1.43        pk 
   1342   1.1        pk 	switch (fdc->sc_state) {
   1343   1.1        pk 	case DEVIDLE:
   1344   1.1        pk 		fdc->sc_errors = 0;
   1345   1.1        pk 		fd->sc_skip = 0;
   1346   1.1        pk 		fd->sc_bcount = bp->b_bcount;
   1347  1.53        pk 		fd->sc_blkno = (bp->b_blkno * DEV_BSIZE) / FD_BSIZE(fd);
   1348   1.1        pk 		untimeout(fd_motor_off, fd);
   1349   1.1        pk 		if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
   1350   1.1        pk 			fdc->sc_state = MOTORWAIT;
   1351  1.42        pk 			return (1);
   1352   1.1        pk 		}
   1353   1.1        pk 		if ((fd->sc_flags & FD_MOTOR) == 0) {
   1354   1.1        pk 			/* Turn on the motor, being careful about pairing. */
   1355   1.1        pk 			struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
   1356   1.1        pk 			if (ofd && ofd->sc_flags & FD_MOTOR) {
   1357   1.1        pk 				untimeout(fd_motor_off, ofd);
   1358   1.1        pk 				ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
   1359   1.1        pk 			}
   1360   1.1        pk 			fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
   1361  1.12        pk 			fd_set_motor(fdc);
   1362   1.1        pk 			fdc->sc_state = MOTORWAIT;
   1363   1.2        pk 			if (fdc->sc_flags & FDC_82077) { /* XXX */
   1364   1.2        pk 				/* Allow .25s for motor to stabilize. */
   1365   1.2        pk 				timeout(fd_motor_on, fd, hz / 4);
   1366   1.2        pk 			} else {
   1367   1.2        pk 				fd->sc_flags &= ~FD_MOTOR_WAIT;
   1368   1.2        pk 				goto loop;
   1369   1.2        pk 			}
   1370  1.42        pk 			return (1);
   1371   1.1        pk 		}
   1372   1.1        pk 		/* Make sure the right drive is selected. */
   1373  1.12        pk 		fd_set_motor(fdc);
   1374   1.1        pk 
   1375  1.49        pk 		/*FALLTHROUGH*/
   1376   1.1        pk 	case DOSEEK:
   1377   1.1        pk 	doseek:
   1378  1.43        pk 		if ((fdc->sc_flags & FDC_EIS) &&
   1379  1.43        pk 		    (bp->b_flags & B_FORMAT) == 0) {
   1380   1.2        pk 			fd->sc_cylin = bp->b_cylin;
   1381   1.2        pk 			/* We use implied seek */
   1382   1.2        pk 			goto doio;
   1383   1.2        pk 		}
   1384   1.2        pk 
   1385   1.1        pk 		if (fd->sc_cylin == bp->b_cylin)
   1386   1.1        pk 			goto doio;
   1387   1.1        pk 
   1388   1.2        pk 		/* specify command */
   1389   1.2        pk 		OUT_FDC(fdc, NE7CMD_SPECIFY, SEEKTIMEDOUT);
   1390   1.2        pk 		OUT_FDC(fdc, fd->sc_type->steprate, SEEKTIMEDOUT);
   1391  1.50        pk 		/* XXX head load time == 6ms */
   1392  1.50        pk 		OUT_FDC(fdc, 6 | NE7_SPECIFY_NODMA, SEEKTIMEDOUT);
   1393   1.2        pk 
   1394   1.2        pk 		fdc->sc_istate = ISTATE_SENSEI;
   1395   1.2        pk 		/* seek function */
   1396   1.2        pk 		OUT_FDC(fdc, NE7CMD_SEEK, SEEKTIMEDOUT);
   1397   1.2        pk 		OUT_FDC(fdc, fd->sc_drive, SEEKTIMEDOUT); /* drive number */
   1398   1.2        pk 		OUT_FDC(fdc, bp->b_cylin * fd->sc_type->step, SEEKTIMEDOUT);
   1399   1.1        pk 
   1400   1.1        pk 		fd->sc_cylin = -1;
   1401   1.1        pk 		fdc->sc_state = SEEKWAIT;
   1402   1.1        pk 		fdc->sc_nstat = 0;
   1403  1.18   thorpej 
   1404  1.18   thorpej 		fd->sc_dk.dk_seek++;
   1405  1.18   thorpej 		disk_busy(&fd->sc_dk);
   1406  1.18   thorpej 
   1407   1.1        pk 		timeout(fdctimeout, fdc, 4 * hz);
   1408  1.42        pk 		return (1);
   1409   1.1        pk 
   1410   1.1        pk 	case DOIO:
   1411   1.1        pk 	doio:
   1412  1.50        pk 		if (finfo != NULL)
   1413  1.43        pk 			fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
   1414  1.43        pk 				      (char *)finfo;
   1415   1.1        pk 		type = fd->sc_type;
   1416   1.1        pk 		sec = fd->sc_blkno % type->seccyl;
   1417   1.1        pk 		nblks = type->seccyl - sec;
   1418  1.53        pk 		nblks = min(nblks, fd->sc_bcount / FD_BSIZE(fd));
   1419  1.53        pk 		nblks = min(nblks, FDC_MAXIOSIZE / FD_BSIZE(fd));
   1420   1.1        pk 		fd->sc_nblks = nblks;
   1421  1.53        pk 		fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FD_BSIZE(fd);
   1422   1.1        pk 		head = sec / type->sectrac;
   1423   1.1        pk 		sec -= head * type->sectrac;
   1424   1.1        pk #ifdef DIAGNOSTIC
   1425   1.1        pk 		{int block;
   1426   1.1        pk 		 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
   1427   1.1        pk 		 if (block != fd->sc_blkno) {
   1428  1.39  christos 			 printf("fdcintr: block %d != blkno %d\n", block, fd->sc_blkno);
   1429   1.1        pk #ifdef DDB
   1430   1.1        pk 			 Debugger();
   1431   1.1        pk #endif
   1432   1.1        pk 		 }}
   1433   1.1        pk #endif
   1434   1.1        pk 		read = bp->b_flags & B_READ;
   1435   1.1        pk 
   1436   1.1        pk 		/* Setup for pseudo DMA */
   1437   1.2        pk 		fdc->sc_data = bp->b_data + fd->sc_skip;
   1438   1.1        pk 		fdc->sc_tc = fd->sc_nbytes;
   1439   1.1        pk 
   1440  1.70        pk 		bus_space_write_1(fdc->sc_bustag, fdc->sc_handle,
   1441  1.70        pk 				  fdc->sc_reg_drs, type->rate);
   1442   1.1        pk #ifdef FD_DEBUG
   1443   1.2        pk 		if (fdc_debug > 1)
   1444  1.39  christos 			printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
   1445   1.2        pk 				read ? "read" : "write", fd->sc_drive,
   1446   1.2        pk 				fd->sc_cylin, head, sec, nblks);
   1447   1.1        pk #endif
   1448   1.2        pk 		fdc->sc_state = IOCOMPLETE;
   1449   1.2        pk 		fdc->sc_istate = ISTATE_DMA;
   1450   1.1        pk 		fdc->sc_nstat = 0;
   1451  1.50        pk 		if (finfo != NULL) {
   1452  1.43        pk 			/* formatting */
   1453  1.43        pk 			OUT_FDC(fdc, NE7CMD_FORMAT, IOTIMEDOUT);
   1454  1.43        pk 			OUT_FDC(fdc, (head << 2) | fd->sc_drive, IOTIMEDOUT);
   1455  1.43        pk 			OUT_FDC(fdc, finfo->fd_formb_secshift, IOTIMEDOUT);
   1456  1.43        pk 			OUT_FDC(fdc, finfo->fd_formb_nsecs, IOTIMEDOUT);
   1457  1.43        pk 			OUT_FDC(fdc, finfo->fd_formb_gaplen, IOTIMEDOUT);
   1458  1.43        pk 			OUT_FDC(fdc, finfo->fd_formb_fillbyte, IOTIMEDOUT);
   1459  1.43        pk 		} else {
   1460  1.43        pk 			if (read)
   1461  1.43        pk 				OUT_FDC(fdc, NE7CMD_READ, IOTIMEDOUT);
   1462  1.43        pk 			else
   1463  1.43        pk 				OUT_FDC(fdc, NE7CMD_WRITE, IOTIMEDOUT);
   1464  1.43        pk 			OUT_FDC(fdc, (head << 2) | fd->sc_drive, IOTIMEDOUT);
   1465  1.43        pk 			OUT_FDC(fdc, fd->sc_cylin, IOTIMEDOUT);	/*track*/
   1466  1.43        pk 			OUT_FDC(fdc, head, IOTIMEDOUT);
   1467  1.43        pk 			OUT_FDC(fdc, sec + 1, IOTIMEDOUT);	/*sector+1*/
   1468  1.43        pk 			OUT_FDC(fdc, type->secsize, IOTIMEDOUT);/*sector size*/
   1469  1.43        pk 			OUT_FDC(fdc, type->sectrac, IOTIMEDOUT);/*secs/track*/
   1470  1.43        pk 			OUT_FDC(fdc, type->gap1, IOTIMEDOUT);	/*gap1 size*/
   1471  1.43        pk 			OUT_FDC(fdc, type->datalen, IOTIMEDOUT);/*data length*/
   1472  1.43        pk 		}
   1473  1.18   thorpej 
   1474  1.18   thorpej 		disk_busy(&fd->sc_dk);
   1475  1.18   thorpej 
   1476   1.1        pk 		/* allow 2 seconds for operation */
   1477   1.1        pk 		timeout(fdctimeout, fdc, 2 * hz);
   1478  1.42        pk 		return (1);				/* will return later */
   1479   1.1        pk 
   1480   1.1        pk 	case SEEKWAIT:
   1481   1.1        pk 		untimeout(fdctimeout, fdc);
   1482   1.1        pk 		fdc->sc_state = SEEKCOMPLETE;
   1483   1.2        pk 		if (fdc->sc_flags & FDC_NEEDHEADSETTLE) {
   1484   1.2        pk 			/* allow 1/50 second for heads to settle */
   1485   1.2        pk 			timeout(fdcpseudointr, fdc, hz / 50);
   1486  1.42        pk 			return (1);		/* will return later */
   1487   1.2        pk 		}
   1488  1.49        pk 		/*FALLTHROUGH*/
   1489   1.1        pk 	case SEEKCOMPLETE:
   1490  1.18   thorpej 		disk_unbusy(&fd->sc_dk, 0);	/* no data on seek */
   1491  1.18   thorpej 
   1492   1.1        pk 		/* Make sure seek really happened. */
   1493   1.1        pk 		if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 ||
   1494   1.1        pk 		    cyl != bp->b_cylin * fd->sc_type->step) {
   1495   1.1        pk #ifdef FD_DEBUG
   1496   1.2        pk 			if (fdc_debug)
   1497  1.16   thorpej 				fdcstatus(&fd->sc_dv, 2, "seek failed");
   1498   1.1        pk #endif
   1499   1.1        pk 			fdcretry(fdc);
   1500   1.1        pk 			goto loop;
   1501   1.1        pk 		}
   1502   1.1        pk 		fd->sc_cylin = bp->b_cylin;
   1503   1.1        pk 		goto doio;
   1504   1.1        pk 
   1505   1.1        pk 	case IOTIMEDOUT:
   1506  1.49        pk 		FTC_FLIP;
   1507   1.1        pk 		(void)fdcresult(fdc);
   1508  1.49        pk 		/*FALLTHROUGH*/
   1509   1.1        pk 	case SEEKTIMEDOUT:
   1510   1.1        pk 	case RECALTIMEDOUT:
   1511   1.1        pk 	case RESETTIMEDOUT:
   1512   1.1        pk 		fdcretry(fdc);
   1513   1.1        pk 		goto loop;
   1514   1.1        pk 
   1515   1.1        pk 	case IOCOMPLETE: /* IO DONE, post-analyze */
   1516   1.1        pk 		untimeout(fdctimeout, fdc);
   1517  1.18   thorpej 
   1518  1.18   thorpej 		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid));
   1519  1.18   thorpej 
   1520  1.50        pk 		if (fdc->sc_nstat != 7 || st1 != 0 ||
   1521  1.50        pk 		    ((st0 & 0xf8) != 0 &&
   1522  1.50        pk 		     ((st0 & 0xf8) != 0x20 || (fdc->sc_cfg & CFG_EIS) == 0))) {
   1523   1.1        pk #ifdef FD_DEBUG
   1524   1.2        pk 			if (fdc_debug) {
   1525  1.16   thorpej 				fdcstatus(&fd->sc_dv, 7,
   1526   1.2        pk 					bp->b_flags & B_READ
   1527   1.2        pk 					? "read failed" : "write failed");
   1528  1.50        pk 				printf("blkno %d nblks %d nstat %d tc %d\n",
   1529  1.50        pk 				       fd->sc_blkno, fd->sc_nblks,
   1530  1.50        pk 				       fdc->sc_nstat, fdc->sc_tc);
   1531   1.2        pk 			}
   1532   1.1        pk #endif
   1533   1.6        pk 			if (fdc->sc_nstat == 7 &&
   1534   1.6        pk 			    (st1 & ST1_OVERRUN) == ST1_OVERRUN) {
   1535   1.6        pk 
   1536   1.6        pk 				/*
   1537   1.6        pk 				 * Silently retry overruns if no other
   1538   1.6        pk 				 * error bit is set. Adjust threshold.
   1539   1.6        pk 				 */
   1540   1.2        pk 				int thr = fdc->sc_cfg & CFG_THRHLD_MASK;
   1541   1.6        pk 				if (thr < 15) {
   1542   1.6        pk 					thr++;
   1543   1.6        pk 					fdc->sc_cfg &= ~CFG_THRHLD_MASK;
   1544   1.6        pk 					fdc->sc_cfg |= (thr & CFG_THRHLD_MASK);
   1545   1.2        pk #ifdef FD_DEBUG
   1546   1.6        pk 					if (fdc_debug)
   1547  1.39  christos 						printf("fdc: %d -> threshold\n", thr);
   1548   1.2        pk #endif
   1549   1.6        pk 					fdconf(fdc);
   1550   1.6        pk 					fdc->sc_overruns = 0;
   1551   1.6        pk 				}
   1552  1.34        pk 				if (++fdc->sc_overruns < 3) {
   1553  1.34        pk 					fdc->sc_state = DOIO;
   1554   1.6        pk 					goto loop;
   1555  1.34        pk 				}
   1556   1.2        pk 			}
   1557   1.1        pk 			fdcretry(fdc);
   1558   1.1        pk 			goto loop;
   1559   1.1        pk 		}
   1560   1.1        pk 		if (fdc->sc_errors) {
   1561   1.1        pk 			diskerr(bp, "fd", "soft error", LOG_PRINTF,
   1562  1.53        pk 			    fd->sc_skip / FD_BSIZE(fd),
   1563  1.53        pk 			    (struct disklabel *)NULL);
   1564  1.39  christos 			printf("\n");
   1565   1.1        pk 			fdc->sc_errors = 0;
   1566   1.6        pk 		} else {
   1567  1.12        pk 			if (--fdc->sc_overruns < -20) {
   1568   1.6        pk 				int thr = fdc->sc_cfg & CFG_THRHLD_MASK;
   1569   1.6        pk 				if (thr > 0) {
   1570   1.6        pk 					thr--;
   1571   1.6        pk 					fdc->sc_cfg &= ~CFG_THRHLD_MASK;
   1572   1.6        pk 					fdc->sc_cfg |= (thr & CFG_THRHLD_MASK);
   1573   1.6        pk #ifdef FD_DEBUG
   1574   1.6        pk 					if (fdc_debug)
   1575  1.39  christos 						printf("fdc: %d -> threshold\n", thr);
   1576   1.6        pk #endif
   1577   1.6        pk 					fdconf(fdc);
   1578   1.6        pk 				}
   1579   1.6        pk 				fdc->sc_overruns = 0;
   1580   1.6        pk 			}
   1581   1.1        pk 		}
   1582   1.1        pk 		fd->sc_blkno += fd->sc_nblks;
   1583   1.1        pk 		fd->sc_skip += fd->sc_nbytes;
   1584   1.1        pk 		fd->sc_bcount -= fd->sc_nbytes;
   1585  1.50        pk 		if (finfo == NULL && fd->sc_bcount > 0) {
   1586   1.1        pk 			bp->b_cylin = fd->sc_blkno / fd->sc_type->seccyl;
   1587   1.1        pk 			goto doseek;
   1588   1.1        pk 		}
   1589   1.1        pk 		fdfinish(fd, bp);
   1590   1.1        pk 		goto loop;
   1591   1.1        pk 
   1592   1.1        pk 	case DORESET:
   1593   1.2        pk 	doreset:
   1594   1.1        pk 		/* try a reset, keep motor on */
   1595  1.12        pk 		fd_set_motor(fdc);
   1596   1.1        pk 		delay(100);
   1597  1.12        pk 		fdc_reset(fdc);
   1598  1.12        pk 		fdc->sc_nstat = 0;
   1599  1.12        pk 		fdc->sc_istate = ISTATE_SENSEI;
   1600   1.1        pk 		fdc->sc_state = RESETCOMPLETE;
   1601   1.1        pk 		timeout(fdctimeout, fdc, hz / 2);
   1602  1.42        pk 		return (1);			/* will return later */
   1603   1.1        pk 
   1604   1.1        pk 	case RESETCOMPLETE:
   1605   1.1        pk 		untimeout(fdctimeout, fdc);
   1606  1.12        pk 		fdconf(fdc);
   1607   1.1        pk 
   1608   1.1        pk 		/* fall through */
   1609   1.1        pk 	case DORECAL:
   1610   1.1        pk 		fdc->sc_state = RECALWAIT;
   1611   1.2        pk 		fdc->sc_istate = ISTATE_SENSEI;
   1612   1.1        pk 		fdc->sc_nstat = 0;
   1613   1.2        pk 		/* recalibrate function */
   1614   1.2        pk 		OUT_FDC(fdc, NE7CMD_RECAL, RECALTIMEDOUT);
   1615   1.2        pk 		OUT_FDC(fdc, fd->sc_drive, RECALTIMEDOUT);
   1616   1.1        pk 		timeout(fdctimeout, fdc, 5 * hz);
   1617  1.42        pk 		return (1);			/* will return later */
   1618   1.1        pk 
   1619   1.1        pk 	case RECALWAIT:
   1620   1.1        pk 		untimeout(fdctimeout, fdc);
   1621   1.1        pk 		fdc->sc_state = RECALCOMPLETE;
   1622   1.2        pk 		if (fdc->sc_flags & FDC_NEEDHEADSETTLE) {
   1623   1.2        pk 			/* allow 1/30 second for heads to settle */
   1624   1.2        pk 			timeout(fdcpseudointr, fdc, hz / 30);
   1625  1.42        pk 			return (1);		/* will return later */
   1626   1.2        pk 		}
   1627   1.1        pk 
   1628   1.1        pk 	case RECALCOMPLETE:
   1629   1.1        pk 		if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
   1630   1.1        pk #ifdef FD_DEBUG
   1631   1.2        pk 			if (fdc_debug)
   1632  1.16   thorpej 				fdcstatus(&fd->sc_dv, 2, "recalibrate failed");
   1633   1.1        pk #endif
   1634   1.1        pk 			fdcretry(fdc);
   1635   1.1        pk 			goto loop;
   1636   1.1        pk 		}
   1637   1.1        pk 		fd->sc_cylin = 0;
   1638   1.1        pk 		goto doseek;
   1639   1.1        pk 
   1640   1.1        pk 	case MOTORWAIT:
   1641   1.1        pk 		if (fd->sc_flags & FD_MOTOR_WAIT)
   1642  1.42        pk 			return (1);		/* time's not up yet */
   1643   1.1        pk 		goto doseek;
   1644   1.1        pk 
   1645   1.1        pk 	default:
   1646  1.16   thorpej 		fdcstatus(&fd->sc_dv, 0, "stray interrupt");
   1647  1.42        pk 		return (1);
   1648   1.1        pk 	}
   1649   1.1        pk #ifdef DIAGNOSTIC
   1650   1.1        pk 	panic("fdcintr: impossible");
   1651   1.1        pk #endif
   1652   1.1        pk #undef	st0
   1653   1.1        pk #undef	st1
   1654   1.1        pk #undef	cyl
   1655   1.1        pk }
   1656   1.1        pk 
   1657   1.1        pk void
   1658   1.1        pk fdcretry(fdc)
   1659   1.1        pk 	struct fdc_softc *fdc;
   1660   1.1        pk {
   1661  1.40   thorpej 	char bits[64];
   1662   1.1        pk 	struct fd_softc *fd;
   1663   1.1        pk 	struct buf *bp;
   1664   1.1        pk 
   1665   1.1        pk 	fd = fdc->sc_drives.tqh_first;
   1666   1.1        pk 	bp = fd->sc_q.b_actf;
   1667   1.6        pk 
   1668   1.6        pk 	fdc->sc_overruns = 0;
   1669  1.42        pk 	if (fd->sc_opts & FDOPT_NORETRY)
   1670  1.42        pk 		goto fail;
   1671   1.1        pk 
   1672   1.1        pk 	switch (fdc->sc_errors) {
   1673   1.1        pk 	case 0:
   1674   1.1        pk 		/* try again */
   1675   1.2        pk 		fdc->sc_state =
   1676  1.22   thorpej 			(fdc->sc_flags & FDC_EIS) ? DOIO : DOSEEK;
   1677   1.1        pk 		break;
   1678   1.1        pk 
   1679   1.1        pk 	case 1: case 2: case 3:
   1680   1.1        pk 		/* didn't work; try recalibrating */
   1681   1.1        pk 		fdc->sc_state = DORECAL;
   1682   1.1        pk 		break;
   1683   1.1        pk 
   1684   1.1        pk 	case 4:
   1685   1.1        pk 		/* still no go; reset the bastard */
   1686   1.1        pk 		fdc->sc_state = DORESET;
   1687   1.1        pk 		break;
   1688   1.1        pk 
   1689   1.1        pk 	default:
   1690  1.42        pk 	fail:
   1691  1.42        pk 		if ((fd->sc_opts & FDOPT_SILENT) == 0) {
   1692  1.42        pk 			diskerr(bp, "fd", "hard error", LOG_PRINTF,
   1693  1.53        pk 				fd->sc_skip / FD_BSIZE(fd),
   1694  1.42        pk 				(struct disklabel *)NULL);
   1695  1.42        pk 
   1696  1.42        pk 			printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
   1697  1.42        pk 				NE7_ST0BITS, bits, sizeof(bits)));
   1698  1.42        pk 			printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
   1699  1.42        pk 				NE7_ST1BITS, bits, sizeof(bits)));
   1700  1.42        pk 			printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
   1701  1.42        pk 				NE7_ST2BITS, bits, sizeof(bits)));
   1702  1.42        pk 			printf(" cyl %d head %d sec %d)\n",
   1703  1.42        pk 				fdc->sc_status[3], fdc->sc_status[4],
   1704  1.42        pk 				fdc->sc_status[5]);
   1705  1.42        pk 		}
   1706   1.1        pk 
   1707   1.1        pk 		bp->b_flags |= B_ERROR;
   1708   1.1        pk 		bp->b_error = EIO;
   1709   1.1        pk 		fdfinish(fd, bp);
   1710   1.1        pk 	}
   1711   1.1        pk 	fdc->sc_errors++;
   1712   1.1        pk }
   1713   1.1        pk 
   1714   1.1        pk int
   1715   1.1        pk fdsize(dev)
   1716   1.1        pk 	dev_t dev;
   1717   1.1        pk {
   1718   1.1        pk 
   1719   1.1        pk 	/* Swapping to floppies would not make sense. */
   1720  1.42        pk 	return (-1);
   1721   1.1        pk }
   1722   1.1        pk 
   1723   1.1        pk int
   1724  1.24  christos fddump(dev, blkno, va, size)
   1725  1.24  christos 	dev_t dev;
   1726  1.24  christos 	daddr_t blkno;
   1727  1.24  christos 	caddr_t va;
   1728  1.24  christos 	size_t size;
   1729   1.1        pk {
   1730   1.1        pk 
   1731   1.1        pk 	/* Not implemented. */
   1732  1.42        pk 	return (EINVAL);
   1733   1.1        pk }
   1734   1.1        pk 
   1735   1.1        pk int
   1736  1.24  christos fdioctl(dev, cmd, addr, flag, p)
   1737   1.1        pk 	dev_t dev;
   1738   1.1        pk 	u_long cmd;
   1739   1.1        pk 	caddr_t addr;
   1740   1.1        pk 	int flag;
   1741  1.24  christos 	struct proc *p;
   1742   1.1        pk {
   1743  1.70        pk 	struct fd_softc *fd;
   1744  1.70        pk 	struct fdc_softc *fdc;
   1745  1.42        pk 	struct fdformat_parms *form_parms;
   1746  1.42        pk 	struct fdformat_cmd *form_cmd;
   1747  1.42        pk 	struct ne7_fd_formb fd_formb;
   1748  1.42        pk 	int il[FD_MAX_NSEC + 1];
   1749  1.70        pk 	int unit;
   1750  1.42        pk 	int i, j;
   1751   1.1        pk 	int error;
   1752   1.1        pk 
   1753  1.70        pk 	unit = FDUNIT(dev);
   1754  1.70        pk 	if (unit >= fd_cd.cd_ndevs)
   1755  1.70        pk 		return (ENXIO);
   1756  1.70        pk 
   1757  1.70        pk 	fd = fd_cd.cd_devs[FDUNIT(dev)];
   1758  1.70        pk 	fdc = (struct fdc_softc *)fd->sc_dv.dv_parent;
   1759  1.70        pk 
   1760   1.1        pk 	switch (cmd) {
   1761   1.1        pk 	case DIOCGDINFO:
   1762  1.16   thorpej 		*(struct disklabel *)addr = *(fd->sc_dk.dk_label);
   1763   1.1        pk 		return 0;
   1764   1.1        pk 
   1765   1.1        pk 	case DIOCWLABEL:
   1766   1.1        pk 		if ((flag & FWRITE) == 0)
   1767   1.1        pk 			return EBADF;
   1768   1.1        pk 		/* XXX do something */
   1769  1.42        pk 		return (0);
   1770   1.1        pk 
   1771   1.1        pk 	case DIOCWDINFO:
   1772   1.1        pk 		if ((flag & FWRITE) == 0)
   1773  1.42        pk 			return (EBADF);
   1774   1.1        pk 
   1775  1.16   thorpej 		error = setdisklabel(fd->sc_dk.dk_label,
   1776  1.11        pk 				    (struct disklabel *)addr, 0,
   1777  1.16   thorpej 				    fd->sc_dk.dk_cpulabel);
   1778   1.1        pk 		if (error)
   1779  1.42        pk 			return (error);
   1780   1.1        pk 
   1781  1.11        pk 		error = writedisklabel(dev, fdstrategy,
   1782  1.16   thorpej 				       fd->sc_dk.dk_label,
   1783  1.16   thorpej 				       fd->sc_dk.dk_cpulabel);
   1784  1.42        pk 		return (error);
   1785  1.21   thorpej 
   1786  1.21   thorpej 	case DIOCLOCK:
   1787  1.21   thorpej 		/*
   1788  1.21   thorpej 		 * Nothing to do here, really.
   1789  1.21   thorpej 		 */
   1790  1.42        pk 		return (0);
   1791   1.1        pk 
   1792  1.13        pk 	case DIOCEJECT:
   1793  1.66    bouyer 		if (*(int *)addr == 0) {
   1794  1.66    bouyer 			int part = DISKPART(dev);
   1795  1.66    bouyer 			/*
   1796  1.66    bouyer 			 * Don't force eject: check that we are the only
   1797  1.66    bouyer 			 * partition open. If so, unlock it.
   1798  1.66    bouyer 			 */
   1799  1.66    bouyer 			if ((fd->sc_dk.dk_openmask & ~(1 << part)) != 0 ||
   1800  1.66    bouyer 			    fd->sc_dk.dk_bopenmask + fd->sc_dk.dk_copenmask !=
   1801  1.66    bouyer 			    fd->sc_dk.dk_openmask) {
   1802  1.66    bouyer 				return (EBUSY);
   1803  1.66    bouyer 			}
   1804  1.66    bouyer 		}
   1805  1.66    bouyer 		/* FALLTHROUGH */
   1806  1.66    bouyer 	case ODIOCEJECT:
   1807  1.50        pk 		fd_do_eject(fd);
   1808  1.42        pk 		return (0);
   1809  1.42        pk 
   1810  1.42        pk 	case FDIOCGETFORMAT:
   1811  1.42        pk 		form_parms = (struct fdformat_parms *)addr;
   1812  1.42        pk 		form_parms->fdformat_version = FDFORMAT_VERSION;
   1813  1.42        pk 		form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
   1814  1.49        pk 		form_parms->ncyl = fd->sc_type->cylinders;
   1815  1.42        pk 		form_parms->nspt = fd->sc_type->sectrac;
   1816  1.42        pk 		form_parms->ntrk = fd->sc_type->heads;
   1817  1.42        pk 		form_parms->stepspercyl = fd->sc_type->step;
   1818  1.42        pk 		form_parms->gaplen = fd->sc_type->gap2;
   1819  1.42        pk 		form_parms->fillbyte = fd->sc_type->fillbyte;
   1820  1.42        pk 		form_parms->interleave = fd->sc_type->interleave;
   1821  1.42        pk 		switch (fd->sc_type->rate) {
   1822  1.42        pk 		case FDC_500KBPS:
   1823  1.42        pk 			form_parms->xfer_rate = 500 * 1024;
   1824  1.42        pk 			break;
   1825  1.42        pk 		case FDC_300KBPS:
   1826  1.42        pk 			form_parms->xfer_rate = 300 * 1024;
   1827  1.42        pk 			break;
   1828  1.42        pk 		case FDC_250KBPS:
   1829  1.42        pk 			form_parms->xfer_rate = 250 * 1024;
   1830  1.42        pk 			break;
   1831  1.42        pk 		default:
   1832  1.42        pk 			return (EINVAL);
   1833  1.42        pk 		}
   1834  1.43        pk 		return (0);
   1835  1.42        pk 
   1836  1.42        pk 	case FDIOCSETFORMAT:
   1837  1.42        pk 		if ((flag & FWRITE) == 0)
   1838  1.42        pk 			return (EBADF);	/* must be opened for writing */
   1839  1.42        pk 
   1840  1.42        pk 		form_parms = (struct fdformat_parms *)addr;
   1841  1.42        pk 		if (form_parms->fdformat_version != FDFORMAT_VERSION)
   1842  1.42        pk 			return (EINVAL);/* wrong version of formatting prog */
   1843  1.42        pk 
   1844  1.42        pk 		i = form_parms->nbps >> 7;
   1845  1.42        pk 		if ((form_parms->nbps & 0x7f) || ffs(i) == 0 ||
   1846  1.42        pk 		    i & ~(1 << (ffs(i)-1)))
   1847  1.42        pk 			/* not a power-of-two multiple of 128 */
   1848  1.42        pk 			return (EINVAL);
   1849  1.42        pk 
   1850  1.42        pk 		switch (form_parms->xfer_rate) {
   1851  1.42        pk 		case 500 * 1024:
   1852  1.42        pk 			fd->sc_type->rate = FDC_500KBPS;
   1853  1.42        pk 			break;
   1854  1.42        pk 		case 300 * 1024:
   1855  1.42        pk 			fd->sc_type->rate = FDC_300KBPS;
   1856  1.42        pk 			break;
   1857  1.42        pk 		case 250 * 1024:
   1858  1.42        pk 			fd->sc_type->rate = FDC_250KBPS;
   1859  1.42        pk 			break;
   1860  1.42        pk 		default:
   1861  1.42        pk 			return (EINVAL);
   1862  1.42        pk 		}
   1863  1.42        pk 
   1864  1.42        pk 		if (form_parms->nspt > FD_MAX_NSEC ||
   1865  1.42        pk 		    form_parms->fillbyte > 0xff ||
   1866  1.42        pk 		    form_parms->interleave > 0xff)
   1867  1.42        pk 			return EINVAL;
   1868  1.42        pk 		fd->sc_type->sectrac = form_parms->nspt;
   1869  1.42        pk 		if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
   1870  1.42        pk 			return EINVAL;
   1871  1.42        pk 		fd->sc_type->heads = form_parms->ntrk;
   1872  1.42        pk 		fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
   1873  1.42        pk 		fd->sc_type->secsize = ffs(i)-1;
   1874  1.42        pk 		fd->sc_type->gap2 = form_parms->gaplen;
   1875  1.49        pk 		fd->sc_type->cylinders = form_parms->ncyl;
   1876  1.42        pk 		fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
   1877  1.42        pk 			form_parms->nbps / DEV_BSIZE;
   1878  1.42        pk 		fd->sc_type->step = form_parms->stepspercyl;
   1879  1.42        pk 		fd->sc_type->fillbyte = form_parms->fillbyte;
   1880  1.42        pk 		fd->sc_type->interleave = form_parms->interleave;
   1881  1.49        pk 		return (0);
   1882  1.16   thorpej 
   1883  1.42        pk 	case FDIOCFORMAT_TRACK:
   1884  1.42        pk 		if((flag & FWRITE) == 0)
   1885  1.42        pk 			/* must be opened for writing */
   1886  1.42        pk 			return (EBADF);
   1887  1.42        pk 		form_cmd = (struct fdformat_cmd *)addr;
   1888  1.42        pk 		if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
   1889  1.42        pk 			/* wrong version of formatting prog */
   1890  1.42        pk 			return (EINVAL);
   1891  1.42        pk 
   1892  1.42        pk 		if (form_cmd->head >= fd->sc_type->heads ||
   1893  1.49        pk 		    form_cmd->cylinder >= fd->sc_type->cylinders) {
   1894  1.42        pk 			return (EINVAL);
   1895  1.42        pk 		}
   1896  1.42        pk 
   1897  1.42        pk 		fd_formb.head = form_cmd->head;
   1898  1.42        pk 		fd_formb.cyl = form_cmd->cylinder;
   1899  1.42        pk 		fd_formb.transfer_rate = fd->sc_type->rate;
   1900  1.42        pk 		fd_formb.fd_formb_secshift = fd->sc_type->secsize;
   1901  1.42        pk 		fd_formb.fd_formb_nsecs = fd->sc_type->sectrac;
   1902  1.42        pk 		fd_formb.fd_formb_gaplen = fd->sc_type->gap2;
   1903  1.42        pk 		fd_formb.fd_formb_fillbyte = fd->sc_type->fillbyte;
   1904  1.42        pk 
   1905  1.49        pk 		bzero(il, sizeof il);
   1906  1.42        pk 		for (j = 0, i = 1; i <= fd_formb.fd_formb_nsecs; i++) {
   1907  1.49        pk 			while (il[(j%fd_formb.fd_formb_nsecs) + 1])
   1908  1.42        pk 				j++;
   1909  1.49        pk 			il[(j%fd_formb.fd_formb_nsecs) + 1] = i;
   1910  1.42        pk 			j += fd->sc_type->interleave;
   1911  1.42        pk 		}
   1912  1.42        pk 		for (i = 0; i < fd_formb.fd_formb_nsecs; i++) {
   1913  1.42        pk 			fd_formb.fd_formb_cylno(i) = form_cmd->cylinder;
   1914  1.42        pk 			fd_formb.fd_formb_headno(i) = form_cmd->head;
   1915  1.42        pk 			fd_formb.fd_formb_secno(i) = il[i+1];
   1916  1.42        pk 			fd_formb.fd_formb_secsize(i) = fd->sc_type->secsize;
   1917  1.42        pk 		}
   1918  1.42        pk 
   1919  1.42        pk 		return fdformat(dev, &fd_formb, p);
   1920  1.42        pk 
   1921  1.42        pk 	case FDIOCGETOPTS:		/* get drive options */
   1922  1.42        pk 		*(int *)addr = fd->sc_opts;
   1923  1.42        pk 		return (0);
   1924  1.42        pk 
   1925  1.42        pk 	case FDIOCSETOPTS:		/* set drive options */
   1926  1.42        pk 		fd->sc_opts = *(int *)addr;
   1927  1.42        pk 		return (0);
   1928  1.42        pk 
   1929   1.1        pk #ifdef DEBUG
   1930   1.1        pk 	case _IO('f', 100):
   1931   1.1        pk 		out_fdc(fdc, NE7CMD_DUMPREG);
   1932   1.1        pk 		fdcresult(fdc);
   1933  1.70        pk 		printf("fdc: dumpreg(%d regs): <", fdc->sc_nstat);
   1934   1.1        pk 		for (i = 0; i < fdc->sc_nstat; i++)
   1935  1.52      fair 			printf(" 0x%x", fdc->sc_status[i]);
   1936  1.39  christos 		printf(">\n");
   1937  1.70        pk 		return (0);
   1938   1.1        pk 
   1939   1.1        pk 	case _IOW('f', 101, int):
   1940  1.70        pk 		fdc->sc_cfg &= ~CFG_THRHLD_MASK;
   1941  1.70        pk 		fdc->sc_cfg |= (*(int *)addr & CFG_THRHLD_MASK);
   1942  1.70        pk 		fdconf(fdc);
   1943  1.42        pk 		return (0);
   1944  1.70        pk 
   1945   1.1        pk 	case _IO('f', 102):
   1946   1.1        pk 		out_fdc(fdc, NE7CMD_SENSEI);
   1947   1.1        pk 		fdcresult(fdc);
   1948  1.70        pk 		printf("fdc: sensei(%d regs): <", fdc->sc_nstat);
   1949   1.1        pk 		for (i=0; i< fdc->sc_nstat; i++)
   1950  1.39  christos 			printf(" 0x%x", fdc->sc_status[i]);
   1951  1.39  christos 		printf(">\n");
   1952  1.42        pk 		return (0);
   1953   1.1        pk #endif
   1954   1.1        pk 	default:
   1955  1.42        pk 		return (ENOTTY);
   1956   1.1        pk 	}
   1957   1.1        pk 
   1958   1.1        pk #ifdef DIAGNOSTIC
   1959   1.1        pk 	panic("fdioctl: impossible");
   1960   1.1        pk #endif
   1961  1.19   thorpej }
   1962  1.19   thorpej 
   1963  1.42        pk int
   1964  1.42        pk fdformat(dev, finfo, p)
   1965  1.42        pk 	dev_t dev;
   1966  1.42        pk 	struct ne7_fd_formb *finfo;
   1967  1.42        pk 	struct proc *p;
   1968  1.42        pk {
   1969  1.42        pk 	int rv = 0, s;
   1970  1.42        pk 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1971  1.42        pk 	struct fd_type *type = fd->sc_type;
   1972  1.42        pk 	struct buf *bp;
   1973  1.42        pk 
   1974  1.42        pk 	/* set up a buffer header for fdstrategy() */
   1975  1.42        pk 	bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
   1976  1.42        pk 	if (bp == 0)
   1977  1.42        pk 		return (ENOBUFS);
   1978  1.42        pk 
   1979  1.42        pk 	PHOLD(p);
   1980  1.42        pk 	bzero((void *)bp, sizeof(struct buf));
   1981  1.42        pk 	bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
   1982  1.42        pk 	bp->b_proc = p;
   1983  1.42        pk 	bp->b_dev = dev;
   1984  1.42        pk 
   1985  1.42        pk 	/*
   1986  1.49        pk 	 * Calculate a fake blkno, so fdstrategy() would initiate a
   1987  1.49        pk 	 * seek to the requested cylinder.
   1988  1.42        pk 	 */
   1989  1.53        pk 	bp->b_blkno = ((finfo->cyl * (type->sectrac * type->heads)
   1990  1.53        pk 		       + finfo->head * type->sectrac) * FD_BSIZE(fd))
   1991  1.53        pk 		      / DEV_BSIZE;
   1992  1.42        pk 
   1993  1.42        pk 	bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
   1994  1.42        pk 	bp->b_data = (caddr_t)finfo;
   1995  1.42        pk 
   1996  1.42        pk #ifdef FD_DEBUG
   1997  1.42        pk 	if (fdc_debug)
   1998  1.52      fair 		printf("fdformat: blkno 0x%x count %ld\n",
   1999  1.42        pk 			bp->b_blkno, bp->b_bcount);
   2000  1.42        pk #endif
   2001  1.42        pk 
   2002  1.42        pk 	/* now do the format */
   2003  1.42        pk 	fdstrategy(bp);
   2004  1.42        pk 
   2005  1.42        pk 	/* ...and wait for it to complete */
   2006  1.42        pk 	s = splbio();
   2007  1.42        pk 	while (!(bp->b_flags & B_DONE)) {
   2008  1.42        pk 		rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
   2009  1.42        pk 		if (rv == EWOULDBLOCK)
   2010  1.42        pk 			break;
   2011  1.42        pk 	}
   2012  1.42        pk 	splx(s);
   2013  1.42        pk 
   2014  1.42        pk 	if (rv == EWOULDBLOCK) {
   2015  1.42        pk 		/* timed out */
   2016  1.42        pk 		rv = EIO;
   2017  1.42        pk 		biodone(bp);
   2018  1.42        pk 	}
   2019  1.42        pk 	if (bp->b_flags & B_ERROR) {
   2020  1.42        pk 		rv = bp->b_error;
   2021  1.42        pk 	}
   2022  1.42        pk 	PRELE(p);
   2023  1.42        pk 	free(bp, M_TEMP);
   2024  1.42        pk 	return (rv);
   2025  1.42        pk }
   2026  1.42        pk 
   2027  1.19   thorpej void
   2028  1.19   thorpej fdgetdisklabel(dev)
   2029  1.19   thorpej 	dev_t dev;
   2030  1.19   thorpej {
   2031  1.19   thorpej 	int unit = FDUNIT(dev), i;
   2032  1.26   thorpej 	struct fd_softc *fd = fd_cd.cd_devs[unit];
   2033  1.19   thorpej 	struct disklabel *lp = fd->sc_dk.dk_label;
   2034  1.19   thorpej 	struct cpu_disklabel *clp = fd->sc_dk.dk_cpulabel;
   2035  1.19   thorpej 
   2036  1.19   thorpej 	bzero(lp, sizeof(struct disklabel));
   2037  1.19   thorpej 	bzero(lp, sizeof(struct cpu_disklabel));
   2038  1.19   thorpej 
   2039  1.19   thorpej 	lp->d_type = DTYPE_FLOPPY;
   2040  1.53        pk 	lp->d_secsize = FD_BSIZE(fd);
   2041  1.19   thorpej 	lp->d_secpercyl = fd->sc_type->seccyl;
   2042  1.19   thorpej 	lp->d_nsectors = fd->sc_type->sectrac;
   2043  1.49        pk 	lp->d_ncylinders = fd->sc_type->cylinders;
   2044  1.19   thorpej 	lp->d_ntracks = fd->sc_type->heads;	/* Go figure... */
   2045  1.19   thorpej 	lp->d_rpm = 3600;	/* XXX like it matters... */
   2046  1.19   thorpej 
   2047  1.19   thorpej 	strncpy(lp->d_typename, "floppy", sizeof(lp->d_typename));
   2048  1.19   thorpej 	strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
   2049  1.19   thorpej 	lp->d_interleave = 1;
   2050  1.19   thorpej 
   2051  1.19   thorpej 	lp->d_partitions[RAW_PART].p_offset = 0;
   2052  1.19   thorpej 	lp->d_partitions[RAW_PART].p_size = lp->d_secpercyl * lp->d_ncylinders;
   2053  1.19   thorpej 	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
   2054  1.19   thorpej 	lp->d_npartitions = RAW_PART + 1;
   2055  1.19   thorpej 
   2056  1.19   thorpej 	lp->d_magic = DISKMAGIC;
   2057  1.19   thorpej 	lp->d_magic2 = DISKMAGIC;
   2058  1.19   thorpej 	lp->d_checksum = dkcksum(lp);
   2059  1.19   thorpej 
   2060  1.19   thorpej 	/*
   2061  1.19   thorpej 	 * Call the generic disklabel extraction routine.  If there's
   2062  1.19   thorpej 	 * not a label there, fake it.
   2063  1.19   thorpej 	 */
   2064  1.19   thorpej 	if (readdisklabel(dev, fdstrategy, lp, clp) != NULL) {
   2065  1.19   thorpej 		strncpy(lp->d_packname, "default label",
   2066  1.19   thorpej 		    sizeof(lp->d_packname));
   2067  1.19   thorpej 		/*
   2068  1.19   thorpej 		 * Reset the partition info; it might have gotten
   2069  1.19   thorpej 		 * trashed in readdisklabel().
   2070  1.19   thorpej 		 *
   2071  1.19   thorpej 		 * XXX Why do we have to do this?  readdisklabel()
   2072  1.19   thorpej 		 * should be safe...
   2073  1.19   thorpej 		 */
   2074  1.19   thorpej 		for (i = 0; i < MAXPARTITIONS; ++i) {
   2075  1.19   thorpej 			lp->d_partitions[i].p_offset = 0;
   2076  1.19   thorpej 			if (i == RAW_PART) {
   2077  1.19   thorpej 				lp->d_partitions[i].p_size =
   2078  1.19   thorpej 				    lp->d_secpercyl * lp->d_ncylinders;
   2079  1.19   thorpej 				lp->d_partitions[i].p_fstype = FS_BSDFFS;
   2080  1.19   thorpej 			} else {
   2081  1.19   thorpej 				lp->d_partitions[i].p_size = 0;
   2082  1.19   thorpej 				lp->d_partitions[i].p_fstype = FS_UNUSED;
   2083  1.19   thorpej 			}
   2084  1.19   thorpej 		}
   2085  1.19   thorpej 		lp->d_npartitions = RAW_PART + 1;
   2086  1.19   thorpej 	}
   2087  1.19   thorpej }
   2088  1.19   thorpej 
   2089  1.19   thorpej void
   2090  1.50        pk fd_do_eject(fd)
   2091  1.50        pk 	struct fd_softc *fd;
   2092  1.19   thorpej {
   2093  1.50        pk 	struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent;
   2094  1.50        pk 
   2095  1.49        pk 	if (CPU_ISSUN4C) {
   2096  1.49        pk 		auxregbisc(AUXIO4C_FDS, AUXIO4C_FEJ);
   2097  1.49        pk 		delay(10);
   2098  1.49        pk 		auxregbisc(AUXIO4C_FEJ, AUXIO4C_FDS);
   2099  1.50        pk 		return;
   2100  1.49        pk 	}
   2101  1.50        pk 	if (CPU_ISSUN4M && (fdc->sc_flags & FDC_82077)) {
   2102  1.70        pk 		bus_space_tag_t t = fdc->sc_bustag;
   2103  1.70        pk 		bus_space_handle_t h = fdc->sc_handle;
   2104  1.70        pk 		u_int8_t dor = FDO_FRST | FDO_FDMAEN | FDO_MOEN(0);
   2105  1.70        pk 
   2106  1.70        pk 		bus_space_write_1(t, h, fdc->sc_reg_dor, dor | FDO_EJ);
   2107  1.50        pk 		delay(10);
   2108  1.70        pk 		bus_space_write_1(t, h, fdc->sc_reg_dor, FDO_FRST | FDO_DS);
   2109  1.50        pk 		return;
   2110  1.49        pk 	}
   2111  1.19   thorpej }
   2112  1.19   thorpej 
   2113  1.45        pk #ifdef MEMORY_DISK_HOOKS
   2114  1.45        pk int	fd_read_md_image __P((size_t *, caddr_t *));
   2115  1.36        pk #endif
   2116  1.36        pk 
   2117  1.19   thorpej /* ARGSUSED */
   2118  1.19   thorpej void
   2119  1.19   thorpej fd_mountroot_hook(dev)
   2120  1.19   thorpej 	struct device *dev;
   2121  1.19   thorpej {
   2122  1.19   thorpej 	int c;
   2123  1.19   thorpej 
   2124  1.50        pk 	fd_do_eject((struct fd_softc *)dev);
   2125  1.39  christos 	printf("Insert filesystem floppy and press return.");
   2126  1.19   thorpej 	for (;;) {
   2127  1.19   thorpej 		c = cngetc();
   2128  1.19   thorpej 		if ((c == '\r') || (c == '\n')) {
   2129  1.39  christos 			printf("\n");
   2130  1.36        pk 			break;
   2131  1.36        pk 		}
   2132  1.36        pk 	}
   2133  1.36        pk }
   2134  1.36        pk 
   2135  1.45        pk #ifdef MEMORY_DISK_HOOKS
   2136  1.36        pk 
   2137  1.36        pk #define FDMICROROOTSIZE ((2*18*80) << DEV_BSHIFT)
   2138  1.36        pk 
   2139  1.36        pk int
   2140  1.45        pk fd_read_md_image(sizep, addrp)
   2141  1.36        pk 	size_t	*sizep;
   2142  1.36        pk 	caddr_t	*addrp;
   2143  1.36        pk {
   2144  1.36        pk 	struct buf buf, *bp = &buf;
   2145  1.36        pk 	dev_t dev;
   2146  1.36        pk 	off_t offset;
   2147  1.36        pk 	caddr_t addr;
   2148  1.36        pk 
   2149  1.36        pk 	dev = makedev(54,0);	/* XXX */
   2150  1.36        pk 
   2151  1.36        pk 	MALLOC(addr, caddr_t, FDMICROROOTSIZE, M_DEVBUF, M_WAITOK);
   2152  1.36        pk 	*addrp = addr;
   2153  1.36        pk 
   2154  1.36        pk 	if (fdopen(dev, 0, S_IFCHR, NULL))
   2155  1.36        pk 		panic("fd: mountroot: fdopen");
   2156  1.36        pk 
   2157  1.36        pk 	offset = 0;
   2158  1.36        pk 
   2159  1.36        pk 	for (;;) {
   2160  1.36        pk 		bp->b_dev = dev;
   2161  1.36        pk 		bp->b_error = 0;
   2162  1.36        pk 		bp->b_resid = 0;
   2163  1.36        pk 		bp->b_proc = NULL;
   2164  1.36        pk 		bp->b_flags = B_BUSY | B_PHYS | B_RAW | B_READ;
   2165  1.36        pk 		bp->b_blkno = btodb(offset);
   2166  1.36        pk 		bp->b_bcount = DEV_BSIZE;
   2167  1.36        pk 		bp->b_data = addr;
   2168  1.36        pk 		fdstrategy(bp);
   2169  1.36        pk 		while ((bp->b_flags & B_DONE) == 0) {
   2170  1.36        pk 			tsleep((caddr_t)bp, PRIBIO + 1, "physio", 0);
   2171  1.19   thorpej 		}
   2172  1.36        pk 		if (bp->b_error)
   2173  1.36        pk 			panic("fd: mountroot: fdread error %d", bp->b_error);
   2174  1.36        pk 
   2175  1.36        pk 		if (bp->b_resid != 0)
   2176  1.36        pk 			break;
   2177  1.36        pk 
   2178  1.36        pk 		addr += DEV_BSIZE;
   2179  1.36        pk 		offset += DEV_BSIZE;
   2180  1.36        pk 		if (offset + DEV_BSIZE > FDMICROROOTSIZE)
   2181  1.36        pk 			break;
   2182  1.19   thorpej 	}
   2183  1.36        pk 	(void)fdclose(dev, 0, S_IFCHR, NULL);
   2184  1.36        pk 	*sizep = offset;
   2185  1.50        pk 	fd_do_eject(fd_cd.cd_devs[FDUNIT(dev)]);
   2186  1.42        pk 	return (0);
   2187   1.1        pk }
   2188  1.36        pk #endif
   2189