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