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