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